mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-03-24 07:50:11 +01:00
alloy: Fix link click navigation in PDF files (fixes issue #3143)
This change adds a minimal implementation of the |tabs.update| extension API and modifies StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent to return a valid |streamInfo.tabId| value as required by the navigateInCurrentTab implementation in chrome/browser/resources/pdf/browser_api.js.
This commit is contained in:
parent
1d02cd2be0
commit
de66fb9406
2
BUILD.gn
2
BUILD.gn
@ -486,6 +486,8 @@ static_library("libcef_static") {
|
||||
"libcef/browser/extensions/api/storage/sync_value_store_cache.h",
|
||||
"libcef/browser/extensions/api/tabs/tabs_api.cc",
|
||||
"libcef/browser/extensions/api/tabs/tabs_api.h",
|
||||
"libcef/browser/extensions/alloy_extensions_util.cc",
|
||||
"libcef/browser/extensions/alloy_extensions_util.h",
|
||||
"libcef/browser/extensions/browser_extensions_util.cc",
|
||||
"libcef/browser/extensions/browser_extensions_util.h",
|
||||
"libcef/browser/extensions/browser_platform_delegate_background.cc",
|
||||
|
20
libcef/browser/extensions/alloy_extensions_util.cc
Normal file
20
libcef/browser/extensions/alloy_extensions_util.cc
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2021 The Chromium Embedded Framework Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
#include "libcef/browser/extensions/alloy_extensions_util.h"
|
||||
|
||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
||||
|
||||
namespace extensions {
|
||||
namespace alloy {
|
||||
|
||||
int GetTabIdForWebContents(content::WebContents* web_contents) {
|
||||
auto browser = AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
|
||||
if (!browser)
|
||||
return -1;
|
||||
return browser->GetIdentifier();
|
||||
}
|
||||
|
||||
} // namespace alloy
|
||||
} // namespace extensions
|
21
libcef/browser/extensions/alloy_extensions_util.h
Normal file
21
libcef/browser/extensions/alloy_extensions_util.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2021 The Chromium Embedded Framework Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
|
||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace extensions {
|
||||
namespace alloy {
|
||||
|
||||
// Returns the tabId for |web_contents|, or -1 if not found.
|
||||
int GetTabIdForWebContents(content::WebContents* web_contents);
|
||||
|
||||
} // namespace alloy
|
||||
} // namespace extensions
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
|
@ -6,10 +6,15 @@
|
||||
|
||||
#include "libcef/browser/extensions/extension_web_contents_observer.h"
|
||||
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
|
||||
#include "chrome/browser/extensions/extension_tab_util.h"
|
||||
#include "components/zoom/zoom_controller.h"
|
||||
#include "content/public/browser/navigation_controller.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "extensions/browser/extension_api_frame_id_map.h"
|
||||
#include "extensions/browser/extension_zoom_request_client.h"
|
||||
#include "extensions/common/error_utils.h"
|
||||
@ -99,6 +104,148 @@ ExtensionFunction::ResponseAction TabsCreateFunction::Run() {
|
||||
: NoArguments());
|
||||
}
|
||||
|
||||
BaseAPIFunction::BaseAPIFunction() : cef_details_(this) {}
|
||||
|
||||
content::WebContents* BaseAPIFunction::GetWebContents(int tab_id) {
|
||||
// Find a browser that we can access, or set |error_| and return nullptr.
|
||||
CefRefPtr<AlloyBrowserHostImpl> browser =
|
||||
cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error_);
|
||||
if (!browser)
|
||||
return nullptr;
|
||||
|
||||
return browser->web_contents();
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
std::unique_ptr<tabs::Update::Params> params(
|
||||
tabs::Update::Params::Create(*args_));
|
||||
EXTENSION_FUNCTION_VALIDATE(params.get());
|
||||
|
||||
tab_id_ = params->tab_id ? *params->tab_id : -1;
|
||||
content::WebContents* web_contents = GetWebContents(tab_id_);
|
||||
if (!web_contents)
|
||||
return RespondNow(Error(std::move(error_)));
|
||||
|
||||
web_contents_ = web_contents;
|
||||
|
||||
// TODO(rafaelw): handle setting remaining tab properties:
|
||||
// -title
|
||||
// -favIconUrl
|
||||
|
||||
// Navigate the tab to a new location if the url is different.
|
||||
if (params->update_properties.url.get()) {
|
||||
std::string updated_url = *params->update_properties.url;
|
||||
if (!UpdateURL(updated_url, tab_id_, &error_))
|
||||
return RespondNow(Error(std::move(error_)));
|
||||
}
|
||||
|
||||
bool active = false;
|
||||
// TODO(rafaelw): Setting |active| from js doesn't make much sense.
|
||||
// Move tab selection management up to window.
|
||||
if (params->update_properties.selected.get())
|
||||
active = *params->update_properties.selected;
|
||||
|
||||
// The 'active' property has replaced 'selected'.
|
||||
if (params->update_properties.active.get())
|
||||
active = *params->update_properties.active;
|
||||
|
||||
if (active) {
|
||||
// TODO: Activate the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
|
||||
}
|
||||
|
||||
if (params->update_properties.highlighted.get() &&
|
||||
*params->update_properties.highlighted) {
|
||||
// TODO: Highlight the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
|
||||
}
|
||||
|
||||
if (params->update_properties.pinned.get() &&
|
||||
*params->update_properties.pinned) {
|
||||
// TODO: Pin the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
|
||||
}
|
||||
|
||||
if (params->update_properties.muted.get()) {
|
||||
// TODO: Mute/unmute the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
return RespondNow(Error(ErrorUtils::FormatErrorMessage(
|
||||
tabs_constants::kCannotUpdateMuteCaptured,
|
||||
base::NumberToString(tab_id_))));
|
||||
}
|
||||
|
||||
if (params->update_properties.opener_tab_id.get()) {
|
||||
int opener_id = *params->update_properties.opener_tab_id;
|
||||
if (opener_id == tab_id_)
|
||||
return RespondNow(Error("Cannot set a tab's opener to itself."));
|
||||
|
||||
// TODO: Set the opener for the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
|
||||
}
|
||||
|
||||
if (params->update_properties.auto_discardable.get()) {
|
||||
// TODO: Set auto-discardable state for the tab at |tab_id_|.
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
return RespondNow(GetResult());
|
||||
}
|
||||
|
||||
bool TabsUpdateFunction::UpdateURL(const std::string& url_string,
|
||||
int tab_id,
|
||||
std::string* error) {
|
||||
GURL url;
|
||||
if (!ExtensionTabUtil::PrepareURLForNavigation(url_string, extension(), &url,
|
||||
error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_javascript_scheme = url.SchemeIs(url::kJavaScriptScheme);
|
||||
// JavaScript URLs are forbidden in chrome.tabs.update().
|
||||
if (is_javascript_scheme) {
|
||||
*error = tabs_constants::kJavaScriptUrlsNotAllowedInTabsUpdate;
|
||||
return false;
|
||||
}
|
||||
|
||||
content::NavigationController::LoadURLParams load_params(url);
|
||||
|
||||
// Treat extension-initiated navigations as renderer-initiated so that the URL
|
||||
// does not show in the omnibox until it commits. This avoids URL spoofs
|
||||
// since URLs can be opened on behalf of untrusted content.
|
||||
load_params.is_renderer_initiated = true;
|
||||
// All renderer-initiated navigations need to have an initiator origin.
|
||||
load_params.initiator_origin = extension()->origin();
|
||||
// |source_site_instance| needs to be set so that a renderer process
|
||||
// compatible with |initiator_origin| is picked by Site Isolation.
|
||||
load_params.source_site_instance = content::SiteInstance::CreateForURL(
|
||||
web_contents_->GetBrowserContext(),
|
||||
load_params.initiator_origin->GetURL());
|
||||
|
||||
// Marking the navigation as initiated via an API means that the focus
|
||||
// will stay in the omnibox - see https://crbug.com/1085779.
|
||||
load_params.transition_type = ui::PAGE_TRANSITION_FROM_API;
|
||||
|
||||
web_contents_->GetController().LoadURLWithParams(load_params);
|
||||
|
||||
DCHECK_EQ(url,
|
||||
web_contents_->GetController().GetPendingEntry()->GetVirtualURL());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseValue TabsUpdateFunction::GetResult() {
|
||||
if (!has_callback())
|
||||
return NoArguments();
|
||||
|
||||
return ArgumentList(tabs::Get::Results::Create(*cef_details_.CreateTabObject(
|
||||
AlloyBrowserHostImpl::GetBrowserForContents(web_contents_),
|
||||
/*opener_browser_id=*/-1, /*active=*/true, tab_id_)));
|
||||
}
|
||||
|
||||
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction()
|
||||
: cef_details_(this), execute_tab_id_(-1) {}
|
||||
|
||||
@ -246,18 +393,6 @@ bool TabsRemoveCSSFunction::ShouldRemoveCSS() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
ZoomAPIFunction::ZoomAPIFunction() : cef_details_(this) {}
|
||||
|
||||
content::WebContents* ZoomAPIFunction::GetWebContents(int tab_id) {
|
||||
// Find a browser that we can access, or set |error_| and return nullptr.
|
||||
CefRefPtr<AlloyBrowserHostImpl> browser =
|
||||
cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error_);
|
||||
if (!browser)
|
||||
return nullptr;
|
||||
|
||||
return browser->web_contents();
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() {
|
||||
std::unique_ptr<tabs::SetZoom::Params> params(
|
||||
tabs::SetZoom::Params::Create(*args_));
|
||||
|
@ -42,6 +42,37 @@ class TabsCreateFunction : public ExtensionFunction {
|
||||
const CefExtensionFunctionDetails cef_details_;
|
||||
};
|
||||
|
||||
class BaseAPIFunction : public ExtensionFunction {
|
||||
public:
|
||||
BaseAPIFunction();
|
||||
|
||||
protected:
|
||||
~BaseAPIFunction() override {}
|
||||
|
||||
// Gets the WebContents for |tab_id| if it is specified. Otherwise get the
|
||||
// WebContents for the active tab in the current window. Calling this function
|
||||
// may set |error_|.
|
||||
content::WebContents* GetWebContents(int tab_id);
|
||||
|
||||
std::string error_;
|
||||
const CefExtensionFunctionDetails cef_details_;
|
||||
};
|
||||
|
||||
class TabsUpdateFunction : public BaseAPIFunction {
|
||||
private:
|
||||
~TabsUpdateFunction() override {}
|
||||
|
||||
ResponseAction Run() override;
|
||||
|
||||
bool UpdateURL(const std::string& url, int tab_id, std::string* error);
|
||||
ResponseValue GetResult();
|
||||
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE)
|
||||
|
||||
int tab_id_ = -1;
|
||||
content::WebContents* web_contents_ = nullptr;
|
||||
};
|
||||
|
||||
// Implement API calls tabs.executeScript, tabs.insertCSS, and tabs.removeCSS.
|
||||
class ExecuteCodeInTabFunction : public ExecuteCodeFunction {
|
||||
public:
|
||||
@ -114,7 +145,7 @@ class ZoomAPIFunction : public ExtensionFunction {
|
||||
const CefExtensionFunctionDetails cef_details_;
|
||||
};
|
||||
|
||||
class TabsSetZoomFunction : public ZoomAPIFunction {
|
||||
class TabsSetZoomFunction : public BaseAPIFunction {
|
||||
private:
|
||||
~TabsSetZoomFunction() override {}
|
||||
|
||||
@ -123,7 +154,7 @@ class TabsSetZoomFunction : public ZoomAPIFunction {
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
|
||||
};
|
||||
|
||||
class TabsGetZoomFunction : public ZoomAPIFunction {
|
||||
class TabsGetZoomFunction : public BaseAPIFunction {
|
||||
private:
|
||||
~TabsGetZoomFunction() override {}
|
||||
|
||||
@ -132,7 +163,7 @@ class TabsGetZoomFunction : public ZoomAPIFunction {
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
|
||||
};
|
||||
|
||||
class TabsSetZoomSettingsFunction : public ZoomAPIFunction {
|
||||
class TabsSetZoomSettingsFunction : public BaseAPIFunction {
|
||||
private:
|
||||
~TabsSetZoomSettingsFunction() override {}
|
||||
|
||||
@ -141,7 +172,7 @@ class TabsSetZoomSettingsFunction : public ZoomAPIFunction {
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
|
||||
};
|
||||
|
||||
class TabsGetZoomSettingsFunction : public ZoomAPIFunction {
|
||||
class TabsGetZoomSettingsFunction : public BaseAPIFunction {
|
||||
private:
|
||||
~TabsGetZoomSettingsFunction() override {}
|
||||
|
||||
|
@ -51,6 +51,7 @@ const char* const kSupportedAPIs[] = {
|
||||
"tabs",
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsCreateFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsUpdateFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsExecuteScriptFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsInsertCSSFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsRemoveCSSFunction),
|
||||
@ -95,6 +96,7 @@ void ChromeFunctionRegistry::RegisterAll(ExtensionFunctionRegistry* registry) {
|
||||
registry->RegisterFunction<cefimpl::TabsRemoveCSSFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsGetFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsCreateFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsUpdateFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsSetZoomFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsGetZoomFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsSetZoomSettingsFunction>();
|
||||
|
@ -318,24 +318,12 @@ base::DictionaryValue* CefExtensionFunctionDetails::OpenTab(
|
||||
GURL url;
|
||||
if (params.url.get()) {
|
||||
std::string url_string = *params.url;
|
||||
url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
|
||||
function()->extension());
|
||||
if (!url.is_valid()) {
|
||||
if (error_message) {
|
||||
*error_message =
|
||||
ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string);
|
||||
}
|
||||
if (!ExtensionTabUtil::PrepareURLForNavigation(
|
||||
url_string, function()->extension(), &url, error_message)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't let extensions crash the browser or renderers.
|
||||
if (ExtensionTabUtil::IsKillURL(url)) {
|
||||
if (error_message)
|
||||
*error_message = keys::kNoCrashBrowserError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Default to foreground for the new tab. The presence of 'active' property
|
||||
// will override this default.
|
||||
bool active = true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/extensions/api/streams_private/streams_private_api.cc chrome/browser/extensions/api/streams_private/streams_private_api.cc
|
||||
index 5c903a13a14ed..d385c6c0c95c4 100644
|
||||
index 5c903a13a14ed..c85964a7bab17 100644
|
||||
--- chrome/browser/extensions/api/streams_private/streams_private_api.cc
|
||||
+++ chrome/browser/extensions/api/streams_private/streams_private_api.cc
|
||||
@@ -6,6 +6,7 @@
|
||||
@ -10,7 +10,18 @@ index 5c903a13a14ed..d385c6c0c95c4 100644
|
||||
#include "chrome/browser/extensions/extension_tab_util.h"
|
||||
#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
|
||||
#include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
|
||||
@@ -42,6 +43,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
@@ -18,6 +19,10 @@
|
||||
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
|
||||
#include "extensions/common/manifest_handlers/mime_types_handler.h"
|
||||
|
||||
+#if BUILDFLAG(ENABLE_CEF)
|
||||
+#include "cef/libcef/browser/extensions/alloy_extensions_util.h"
|
||||
+#endif
|
||||
+
|
||||
namespace extensions {
|
||||
|
||||
void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
@@ -42,6 +47,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
@ -18,7 +29,7 @@ index 5c903a13a14ed..d385c6c0c95c4 100644
|
||||
// If the request was for NoStatePrefetch, abort the prefetcher and do not
|
||||
// continue. This is because plugins cancel NoStatePrefetch, see
|
||||
// http://crbug.com/343590.
|
||||
@@ -52,6 +54,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
@@ -52,6 +58,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
no_state_prefetch_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD);
|
||||
return;
|
||||
}
|
||||
@ -26,6 +37,28 @@ index 5c903a13a14ed..d385c6c0c95c4 100644
|
||||
|
||||
auto* browser_context = web_contents->GetBrowserContext();
|
||||
|
||||
@@ -78,9 +85,18 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
|
||||
// forms of zooming won't work).
|
||||
// TODO(1042323): Present a coherent representation of a tab id for portal
|
||||
// contents.
|
||||
- int tab_id = web_contents->GetOuterWebContents()
|
||||
- ? SessionID::InvalidValue().id()
|
||||
- : ExtensionTabUtil::GetTabId(web_contents);
|
||||
+ int tab_id;
|
||||
+ if (web_contents->GetOuterWebContents()) {
|
||||
+ tab_id = SessionID::InvalidValue().id();
|
||||
+ } else
|
||||
+#if BUILDFLAG(ENABLE_CEF)
|
||||
+ if (cef::IsAlloyRuntimeEnabled()) {
|
||||
+ tab_id = alloy::GetTabIdForWebContents(web_contents);
|
||||
+ } else
|
||||
+#endif // BUILDFLAG(ENABLE_CEF)
|
||||
+ {
|
||||
+ tab_id = ExtensionTabUtil::GetTabId(web_contents);
|
||||
+ }
|
||||
|
||||
std::unique_ptr<StreamContainer> stream_container(
|
||||
new StreamContainer(tab_id, embedded, handler_url, extension_id,
|
||||
diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc
|
||||
index 7e38155c3b695..78768b28d8c99 100644
|
||||
--- extensions/browser/extension_host.cc
|
||||
|
Loading…
x
Reference in New Issue
Block a user