mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for loading extensions (issue #1947)
- Add CefRequestContext::LoadExtension, CefExtension, CefExtensionHandler and related methods/interfaces. - Add chrome://extensions-support that lists supported Chrome APIs. - Add CefBrowserHost::SetAutoResizeEnabled and CefDisplayHandler::OnAutoResize to support browser resize based on preferred web contents size. - views: Add support for custom CefMenuButton popups. - cefclient: Run with `--load-extension=set_page_color` command-line flag for an extension loading example. Add `--use-views` on Windows and Linux for an even better example.
This commit is contained in:
247
patch/patches/extensions_1947.patch
Normal file
247
patch/patches/extensions_1947.patch
Normal file
@ -0,0 +1,247 @@
|
||||
diff --git content/browser/frame_host/render_frame_host_manager.cc content/browser/frame_host/render_frame_host_manager.cc
|
||||
index c8b4275..05ca91e 100644
|
||||
--- content/browser/frame_host/render_frame_host_manager.cc
|
||||
+++ content/browser/frame_host/render_frame_host_manager.cc
|
||||
@@ -1083,10 +1083,11 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
|
||||
// TODO(alexmos): This check should've been enforced earlier in the
|
||||
// navigation, in chrome::Navigate(). Verify this, and then convert this to
|
||||
// a CHECK and remove the fallback.
|
||||
- DCHECK_EQ(browser_context,
|
||||
- render_frame_host_->GetSiteInstance()->GetBrowserContext());
|
||||
- if (browser_context !=
|
||||
- render_frame_host_->GetSiteInstance()->GetBrowserContext()) {
|
||||
+ const bool is_same = GetContentClient()->browser()->IsSameBrowserContext(
|
||||
+ browser_context,
|
||||
+ render_frame_host_->GetSiteInstance()->GetBrowserContext());
|
||||
+ DCHECK(is_same);
|
||||
+ if (!is_same) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1208,7 +1209,8 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
|
||||
|
||||
// Double-check that the new SiteInstance is associated with the right
|
||||
// BrowserContext.
|
||||
- DCHECK_EQ(new_instance->GetBrowserContext(), browser_context);
|
||||
+ DCHECK(GetContentClient()->browser()->IsSameBrowserContext(
|
||||
+ new_instance->GetBrowserContext(), browser_context));
|
||||
|
||||
// If |new_instance| is a new SiteInstance for a subframe with an isolated
|
||||
// origin, set its process reuse policy so that such subframes are
|
||||
diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h
|
||||
index e226ba1..9c9c7cf 100644
|
||||
--- content/public/browser/content_browser_client.h
|
||||
+++ content/public/browser/content_browser_client.h
|
||||
@@ -310,6 +310,13 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
const GURL& current_url,
|
||||
const GURL& new_url);
|
||||
|
||||
+ // Returns true if two browser contexts should be considered the same. CEF
|
||||
+ // uses this to treat *Impl and *Proxy contexts as the same.
|
||||
+ virtual bool IsSameBrowserContext(BrowserContext* context1,
|
||||
+ BrowserContext* context2) {
|
||||
+ return context1 == context2;
|
||||
+ }
|
||||
+
|
||||
// Returns true if the passed in URL should be assigned as the site of the
|
||||
// current SiteInstance, if it does not yet have a site.
|
||||
virtual bool ShouldAssignSiteForURL(const GURL& url);
|
||||
diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc
|
||||
index 4ec655a..b937c20 100644
|
||||
--- extensions/browser/extension_host.cc
|
||||
+++ extensions/browser/extension_host.cc
|
||||
@@ -69,11 +69,12 @@ ExtensionHost::ExtensionHost(const Extension* extension,
|
||||
DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
|
||||
host_type == VIEW_TYPE_EXTENSION_DIALOG ||
|
||||
host_type == VIEW_TYPE_EXTENSION_POPUP);
|
||||
- host_contents_.reset(WebContents::Create(
|
||||
- WebContents::CreateParams(browser_context_, site_instance))),
|
||||
- content::WebContentsObserver::Observe(host_contents_.get());
|
||||
+ host_contents_owned_.reset(WebContents::Create(
|
||||
+ WebContents::CreateParams(browser_context_, site_instance)));
|
||||
+ host_contents_ = host_contents_owned_.get();
|
||||
+ content::WebContentsObserver::Observe(host_contents_);
|
||||
host_contents_->SetDelegate(this);
|
||||
- SetViewType(host_contents_.get(), host_type);
|
||||
+ SetViewType(host_contents_, host_type);
|
||||
|
||||
render_view_host_ = host_contents_->GetRenderViewHost();
|
||||
|
||||
@@ -88,6 +89,48 @@ ExtensionHost::ExtensionHost(const Extension* extension,
|
||||
dispatcher()->set_delegate(this);
|
||||
}
|
||||
|
||||
+ExtensionHost::ExtensionHost(ExtensionHostDelegate* delegate,
|
||||
+ const Extension* extension,
|
||||
+ content::BrowserContext* browser_context,
|
||||
+ content::WebContents* host_contents,
|
||||
+ const GURL& url,
|
||||
+ ViewType host_type)
|
||||
+ : delegate_(delegate),
|
||||
+ extension_(extension),
|
||||
+ extension_id_(extension->id()),
|
||||
+ browser_context_(browser_context),
|
||||
+ host_contents_(host_contents),
|
||||
+ render_view_host_(nullptr),
|
||||
+ is_render_view_creation_pending_(false),
|
||||
+ has_loaded_once_(false),
|
||||
+ document_element_available_(false),
|
||||
+ initial_url_(url),
|
||||
+ extension_host_type_(host_type) {
|
||||
+ DCHECK(delegate);
|
||||
+ DCHECK(browser_context);
|
||||
+ DCHECK(host_contents);
|
||||
+
|
||||
+ // Not used for panels, see PanelHost.
|
||||
+ DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
|
||||
+ host_type == VIEW_TYPE_EXTENSION_DIALOG ||
|
||||
+ host_type == VIEW_TYPE_EXTENSION_POPUP);
|
||||
+
|
||||
+ content::WebContentsObserver::Observe(host_contents_);
|
||||
+ SetViewType(host_contents_, host_type);
|
||||
+
|
||||
+ render_view_host_ = host_contents_->GetRenderViewHost();
|
||||
+
|
||||
+ // Listen for when an extension is unloaded from the same profile, as it may
|
||||
+ // be the same extension that this points to.
|
||||
+ ExtensionRegistry::Get(browser_context_)->AddObserver(this);
|
||||
+
|
||||
+ // Set up web contents observers and pref observers.
|
||||
+ delegate_->OnExtensionHostCreated(host_contents_);
|
||||
+
|
||||
+ ExtensionWebContentsObserver::GetForWebContents(host_contents_)->
|
||||
+ dispatcher()->set_delegate(this);
|
||||
+}
|
||||
+
|
||||
ExtensionHost::~ExtensionHost() {
|
||||
ExtensionRegistry::Get(browser_context_)->RemoveObserver(this);
|
||||
|
||||
diff --git extensions/browser/extension_host.h extensions/browser/extension_host.h
|
||||
index fea09ed..16f81b1 100644
|
||||
--- extensions/browser/extension_host.h
|
||||
+++ extensions/browser/extension_host.h
|
||||
@@ -51,11 +51,17 @@ class ExtensionHost : public DeferredStartRenderHost,
|
||||
ExtensionHost(const Extension* extension,
|
||||
content::SiteInstance* site_instance,
|
||||
const GURL& url, ViewType host_type);
|
||||
+ ExtensionHost(ExtensionHostDelegate* delegate,
|
||||
+ const Extension* extension,
|
||||
+ content::BrowserContext* browser_context,
|
||||
+ content::WebContents* host_contents,
|
||||
+ const GURL& url,
|
||||
+ ViewType host_type);
|
||||
~ExtensionHost() override;
|
||||
|
||||
const Extension* extension() const { return extension_; }
|
||||
const std::string& extension_id() const { return extension_id_; }
|
||||
- content::WebContents* host_contents() const { return host_contents_.get(); }
|
||||
+ content::WebContents* host_contents() const { return host_contents_; }
|
||||
content::RenderViewHost* render_view_host() const;
|
||||
content::RenderProcessHost* render_process_host() const;
|
||||
bool has_loaded_once() const { return has_loaded_once_; }
|
||||
@@ -173,7 +179,8 @@ class ExtensionHost : public DeferredStartRenderHost,
|
||||
content::BrowserContext* browser_context_;
|
||||
|
||||
// The host for our HTML content.
|
||||
- std::unique_ptr<content::WebContents> host_contents_;
|
||||
+ std::unique_ptr<content::WebContents> host_contents_owned_;
|
||||
+ content::WebContents* host_contents_;
|
||||
|
||||
// A weak pointer to the current or pending RenderViewHost. We don't access
|
||||
// this through the host_contents because we want to deal with the pending
|
||||
diff --git extensions/browser/extensions_browser_client.h extensions/browser/extensions_browser_client.h
|
||||
index 64cf7b0..e801fb0 100644
|
||||
--- extensions/browser/extensions_browser_client.h
|
||||
+++ extensions/browser/extensions_browser_client.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "extensions/common/view_type.h"
|
||||
|
||||
class ExtensionFunctionRegistry;
|
||||
+class GURL;
|
||||
class PrefService;
|
||||
|
||||
namespace base {
|
||||
@@ -48,6 +49,7 @@ class ComponentExtensionResourceManager;
|
||||
class Extension;
|
||||
class ExtensionCache;
|
||||
class ExtensionError;
|
||||
+class ExtensionHost;
|
||||
class ExtensionHostDelegate;
|
||||
class ExtensionPrefsObserver;
|
||||
class ExtensionApiFrameIdMap;
|
||||
@@ -102,6 +104,11 @@ class ExtensionsBrowserClient {
|
||||
virtual content::BrowserContext* GetOriginalContext(
|
||||
content::BrowserContext* context) = 0;
|
||||
|
||||
+ // Returns the CEF *Impl context. Used in cases where we want special CEF
|
||||
+ // handling without interfering with the side-by-side Chrome build.
|
||||
+ virtual content::BrowserContext* GetCefImplContext(
|
||||
+ content::BrowserContext* context) { return nullptr; }
|
||||
+
|
||||
#if defined(OS_CHROMEOS)
|
||||
// Returns a user id hash from |context| or an empty string if no hash could
|
||||
// be extracted.
|
||||
@@ -162,6 +169,14 @@ class ExtensionsBrowserClient {
|
||||
virtual std::unique_ptr<ExtensionHostDelegate>
|
||||
CreateExtensionHostDelegate() = 0;
|
||||
|
||||
+ // CEF creates a custom ExtensionHost for background pages. If the return
|
||||
+ // value is true and |host| is NULL then fail the background host creation.
|
||||
+ virtual bool CreateBackgroundExtensionHost(
|
||||
+ const Extension* extension,
|
||||
+ content::BrowserContext* browser_context,
|
||||
+ const GURL& url,
|
||||
+ ExtensionHost** host) { return false; }
|
||||
+
|
||||
// Returns true if the client version has updated since the last run. Called
|
||||
// once each time the extensions system is loaded per browser_context. The
|
||||
// implementation may wish to use the BrowserContext to record the current
|
||||
diff --git extensions/browser/process_manager.cc extensions/browser/process_manager.cc
|
||||
index cb63e50..6e3eccd 100644
|
||||
--- extensions/browser/process_manager.cc
|
||||
+++ extensions/browser/process_manager.cc
|
||||
@@ -347,9 +347,16 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension,
|
||||
return true; // TODO(kalman): return false here? It might break things...
|
||||
|
||||
DVLOG(1) << "CreateBackgroundHost " << extension->id();
|
||||
- ExtensionHost* host =
|
||||
- new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url,
|
||||
- VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
|
||||
+ ExtensionHost* host = nullptr;
|
||||
+ if (ExtensionsBrowserClient::Get()->CreateBackgroundExtensionHost(
|
||||
+ extension, browser_context_, url, &host) && !host) {
|
||||
+ // Explicitly fail if the client can't create the host.
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!host) {
|
||||
+ host = new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url,
|
||||
+ VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
|
||||
+ }
|
||||
host->CreateRenderViewSoon();
|
||||
OnBackgroundHostCreated(host);
|
||||
return true;
|
||||
diff --git extensions/browser/process_manager_factory.cc extensions/browser/process_manager_factory.cc
|
||||
index e8929c5..5ae43b4 100644
|
||||
--- extensions/browser/process_manager_factory.cc
|
||||
+++ extensions/browser/process_manager_factory.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "extensions/browser/process_manager_factory.h"
|
||||
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
+#include "extensions/browser/extensions_browser_client.h"
|
||||
#include "extensions/browser/extension_registry_factory.h"
|
||||
#include "extensions/browser/lazy_background_task_queue_factory.h"
|
||||
#include "extensions/browser/process_manager.h"
|
||||
@@ -50,6 +51,12 @@ KeyedService* ProcessManagerFactory::BuildServiceInstanceFor(
|
||||
|
||||
BrowserContext* ProcessManagerFactory::GetBrowserContextToUse(
|
||||
BrowserContext* context) const {
|
||||
+ // CEF wants all extension state routed to the *Impl context.
|
||||
+ content::BrowserContext* cef_context =
|
||||
+ ExtensionsBrowserClient::Get()->GetCefImplContext(context);
|
||||
+ if (cef_context)
|
||||
+ return cef_context;
|
||||
+
|
||||
// ProcessManager::Create handles guest and incognito profiles, returning an
|
||||
// IncognitoProcessManager in incognito mode.
|
||||
return context;
|
@ -102,18 +102,18 @@ index 24ea3d4..4554f12 100644
|
||||
};
|
||||
|
||||
diff --git ui/views/animation/ink_drop_host_view.h ui/views/animation/ink_drop_host_view.h
|
||||
index 8ac475f..d052dec 100644
|
||||
index 8ac475f..ec58c2b 100644
|
||||
--- ui/views/animation/ink_drop_host_view.h
|
||||
+++ ui/views/animation/ink_drop_host_view.h
|
||||
@@ -136,6 +136,8 @@ class VIEWS_EXPORT InkDropHostView : public View, public InkDropHost {
|
||||
// of CreateInkDrop() delegates to this function.
|
||||
std::unique_ptr<InkDropImpl> CreateDefaultInkDropImpl();
|
||||
@@ -67,6 +67,8 @@ class VIEWS_EXPORT InkDropHostView : public View, public InkDropHost {
|
||||
// them.
|
||||
void AnimateInkDrop(InkDropState state, const ui::LocatedEvent* event);
|
||||
|
||||
+ InkDropMode ink_drop_mode() const { return ink_drop_mode_; }
|
||||
+
|
||||
private:
|
||||
class InkDropGestureHandler;
|
||||
friend class InkDropGestureHandler;
|
||||
protected:
|
||||
static constexpr int kInkDropSmallCornerRadius = 2;
|
||||
static constexpr int kInkDropLargeCornerRadius = 4;
|
||||
diff --git ui/views/controls/button/label_button.cc ui/views/controls/button/label_button.cc
|
||||
index 1d9e7b8..671d578 100644
|
||||
--- ui/views/controls/button/label_button.cc
|
||||
|
@ -194,7 +194,7 @@ index 3f1c7bf..2658da5 100644
|
||||
// a reference.
|
||||
corewm::TooltipWin* tooltip_;
|
||||
diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
||||
index e8a7a79..1c1057f 100644
|
||||
index e8a7a79..a5f4d0e 100644
|
||||
--- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
||||
+++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
|
||||
@@ -152,6 +152,7 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
|
||||
@ -250,7 +250,15 @@ index e8a7a79..1c1057f 100644
|
||||
return bounds_in_pixels_.origin();
|
||||
}
|
||||
|
||||
@@ -1391,9 +1400,15 @@ void DesktopWindowTreeHostX11::InitX11Window(
|
||||
@@ -1335,7 +1344,6 @@ void DesktopWindowTreeHostX11::InitX11Window(
|
||||
::Atom window_type;
|
||||
switch (params.type) {
|
||||
case Widget::InitParams::TYPE_MENU:
|
||||
- swa.override_redirect = True;
|
||||
window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_MENU");
|
||||
break;
|
||||
case Widget::InitParams::TYPE_TOOLTIP:
|
||||
@@ -1391,9 +1399,15 @@ void DesktopWindowTreeHostX11::InitX11Window(
|
||||
attribute_mask |= CWBorderPixel;
|
||||
swa.border_pixel = 0;
|
||||
|
||||
@ -267,7 +275,7 @@ index e8a7a79..1c1057f 100644
|
||||
bounds_in_pixels_.y(), bounds_in_pixels_.width(),
|
||||
bounds_in_pixels_.height(),
|
||||
0, // border width
|
||||
@@ -1998,6 +2013,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
||||
@@ -1998,6 +2012,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -373,6 +381,19 @@ index 63fcb9d..7237ae6 100644
|
||||
// Specifies the initial bounds of the Widget. Default is empty, which means
|
||||
// the NativeWidget may specify a default size. If the parent is specified,
|
||||
// |bounds| is in the parent's coordinate system. If the parent is not
|
||||
diff --git ui/views/widget/widget_hwnd_utils.cc ui/views/widget/widget_hwnd_utils.cc
|
||||
index 163e4b5..58f594db 100644
|
||||
--- ui/views/widget/widget_hwnd_utils.cc
|
||||
+++ ui/views/widget/widget_hwnd_utils.cc
|
||||
@@ -73,7 +73,7 @@ void CalculateWindowStylesFromInitParams(
|
||||
if (!widget_delegate->CanResize())
|
||||
*style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
|
||||
if (params.remove_standard_frame)
|
||||
- *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
||||
+ *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
|
||||
|
||||
if (native_widget_delegate->IsDialogBox()) {
|
||||
*style |= DS_MODALFRAME;
|
||||
diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
|
||||
index 559f968..f679144 100644
|
||||
--- ui/views/win/hwnd_message_handler.cc
|
||||
|
Reference in New Issue
Block a user