diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-03 19:44:25 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-03 19:44:25 +0000 |
commit | e95ad331dcf3eed18d5851b4a97fc24d73a4b9cd (patch) | |
tree | f13a4b673087815f255e37eb46db445b1be3f71e /chrome | |
parent | 6aa881bebd77b8884229496d3d5592431dcd6227 (diff) | |
download | chromium_src-e95ad331dcf3eed18d5851b4a97fc24d73a4b9cd.zip chromium_src-e95ad331dcf3eed18d5851b4a97fc24d73a4b9cd.tar.gz chromium_src-e95ad331dcf3eed18d5851b4a97fc24d73a4b9cd.tar.bz2 |
Delay loading of ExtensionHosts until the background page is ready.
BUG=13912
TEST=no
Review URL: http://codereview.chromium.org/159756
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22302 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 24 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.h | 26 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 6 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host_delegate.h | 4 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 17 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 19 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 3 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 9 |
10 files changed, 109 insertions, 5 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 78ec493..cbd63a7 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -87,6 +87,7 @@ ExtensionHost::ExtensionHost(Extension* extension, SiteInstance* site_instance, : extension_(extension), profile_(site_instance->browsing_instance()->profile()), did_stop_loading_(false), + document_element_available_(false), url_(url) { render_view_host_ = new RenderViewHost( site_instance, this, MSG_ROUTING_NONE, NULL); @@ -132,7 +133,7 @@ bool ExtensionHost::IsRenderViewLive() const { void ExtensionHost::CreateRenderView(RenderWidgetHostView* host_view) { render_view_host_->set_view(host_view); render_view_host_->CreateRenderView(); - render_view_host_->NavigateToURL(url_); + NavigateToURL(url_); DCHECK(IsRenderViewLive()); NotificationService::current()->Notify( NotificationType::EXTENSION_PROCESS_CREATED, @@ -142,9 +143,24 @@ void ExtensionHost::CreateRenderView(RenderWidgetHostView* host_view) { void ExtensionHost::NavigateToURL(const GURL& url) { url_ = url; + + if (!is_background_page() && !extension_->GetBackgroundPageReady()) { + // Make sure the background page loads before any others. + registrar_.Add(this, NotificationType::EXTENSION_BACKGROUND_PAGE_READY, + Source<Extension>(extension_)); + return; + } render_view_host_->NavigateToURL(url_); } +void ExtensionHost::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::EXTENSION_BACKGROUND_PAGE_READY); + DCHECK(extension_->GetBackgroundPageReady()); + NavigateToURL(url_); +} + void ExtensionHost::RecoverCrashedExtension() { DCHECK(!IsRenderViewLive()); #if defined(TOOLKIT_VIEWS) @@ -222,6 +238,12 @@ void ExtensionHost::DidStopLoading(RenderViewHost* render_view_host) { did_stop_loading_ = true; } +void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { + document_element_available_ = true; + if (is_background_page()) + extension_->SetBackgroundPageReady(); +} + void ExtensionHost::RunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const GURL& frame_url, diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index 8961dfe..8a0c860 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -16,6 +16,7 @@ #elif defined(OS_LINUX) #include "chrome/browser/gtk/extension_view_gtk.h" #endif +#include "chrome/common/notification_registrar.h" class Browser; class Extension; @@ -32,7 +33,8 @@ struct WebPreferences; // in the browser UI, or it may be hidden. class ExtensionHost : public RenderViewHostDelegate, public RenderViewHostDelegate::View, - public ExtensionFunctionDispatcher::Delegate { + public ExtensionFunctionDispatcher::Delegate, + public NotificationObserver { public: // Enable DOM automation in created render view hosts. static void EnableDOMAutomation() { enable_dom_automation_ = true; } @@ -46,6 +48,9 @@ class ExtensionHost : public RenderViewHostDelegate, ExtensionView* view() const { return view_.get(); } #elif defined(OS_LINUX) ExtensionViewGtk* view() const { return view_.get(); } +#else + // TODO(port): implement + void* view() const { return NULL; } #endif // Create an ExtensionView and tie it to this host and |browser|. @@ -56,6 +61,9 @@ class ExtensionHost : public RenderViewHostDelegate, RenderProcessHost* render_process_host() const; SiteInstance* site_instance() const; bool did_stop_loading() const { return did_stop_loading_; } + bool document_element_available() const { + return document_element_available_; + } // Returns true if the render view is initialized and didn't crash. bool IsRenderViewLive() const; @@ -80,6 +88,8 @@ class ExtensionHost : public RenderViewHostDelegate, virtual void DidNavigate(RenderViewHost* render_view_host, const ViewHostMsg_FrameNavigate_Params& params); virtual void DidStopLoading(RenderViewHost* render_view_host); + virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host); + virtual WebPreferences GetWebkitPrefs(); virtual void ProcessDOMUIMessage(const std::string& message, const std::string& content, @@ -114,6 +124,11 @@ class ExtensionHost : public RenderViewHostDelegate, virtual void HandleMouseLeave(); virtual void UpdatePreferredWidth(int pref_width); + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: // Whether to allow DOM automation for created RenderViewHosts. This is used // for testing. @@ -125,6 +140,10 @@ class ExtensionHost : public RenderViewHostDelegate, // instead. virtual Browser* GetBrowser(); + // Returns true if we're hosting a background page. + // This isn't valid until CreateRenderView is called. + bool is_background_page() const { return !view(); } + // The extension that we're hosting in this view. Extension* extension_; @@ -147,9 +166,14 @@ class ExtensionHost : public RenderViewHostDelegate, // Whether the RenderWidget has reported that it has stopped loading. bool did_stop_loading_; + // True if the main frame has finished parsing. + bool document_element_available_; + // The URL being hosted. GURL url_; + NotificationRegistrar registrar_; + scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_; DISALLOW_COPY_AND_ASSIGN(ExtensionHost); diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index c8648a3..2bbedce 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -732,6 +732,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove) IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnMsgDidStartLoading) IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnMsgDidStopLoading) + IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame, + OnMsgDocumentAvailableInMainFrame) IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, OnMsgDidLoadResourceFromMemoryCache) IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad, @@ -1010,6 +1012,10 @@ void RenderViewHost::OnMsgDidStopLoading() { delegate_->DidStopLoading(this); } +void RenderViewHost::OnMsgDocumentAvailableInMainFrame() { + delegate_->DocumentAvailableInMainFrame(this); +} + void RenderViewHost::OnMsgDidLoadResourceFromMemoryCache( const GURL& url, const std::string& frame_origin, diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 521ed51..959b99b 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -463,6 +463,7 @@ class RenderViewHost : public RenderWidgetHost, const GURL& target_url); void OnMsgDidStartLoading(); void OnMsgDidStopLoading(); + void OnMsgDocumentAvailableInMainFrame(); void OnMsgDidLoadResourceFromMemoryCache(const GURL& url, const std::string& frame_origin, const std::string& main_frame_origin, diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 8ea6e16..564a6e80 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -431,6 +431,10 @@ class RenderViewHostDelegate { // notion of the throbber stopping. virtual void DidStopLoading(RenderViewHost* render_view_host) {} + // The RenderView's main frame document element is ready. This happens when + // the document has finished parsing. + virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) {} + // The page wants to open a URL with the specified disposition. virtual void RequestOpenURL(const GURL& url, const GURL& referrer, diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 99d78d3..c92223d 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -17,6 +17,7 @@ #include "chrome/common/extensions/extension_error_reporter.h" #include "chrome/common/extensions/extension_error_utils.h" #include "chrome/common/extensions/user_script.h" +#include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" #include "net/base/base64.h" #include "net/base/net_util.h" @@ -410,7 +411,8 @@ FilePath Extension::GetResourcePath(const FilePath& extension_path, return ret_val; } -Extension::Extension(const FilePath& path) : is_theme_(false) { +Extension::Extension(const FilePath& path) + : is_theme_(false), background_page_ready_(false) { DCHECK(path.IsAbsolute()); location_ = INVALID; @@ -921,3 +923,16 @@ std::set<FilePath> Extension::GetBrowserImages() { return image_paths; } + +bool Extension::GetBackgroundPageReady() { + return background_page_ready_ || background_url().is_empty(); +} + +void Extension::SetBackgroundPageReady() { + DCHECK(!background_url().is_empty()); + background_page_ready_ = true; + NotificationService::current()->Notify( + NotificationType::EXTENSION_BACKGROUND_PAGE_READY, + Source<Extension>(this), + NotificationService::NoDetails()); +} diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index dc95ef2..0571792 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -77,7 +77,8 @@ class Extension { // The mimetype used for extensions. static const char kMimeType[]; - Extension() : location_(INVALID), is_theme_(false) {} + Extension() + : location_(INVALID), is_theme_(false), background_page_ready_(false) {} explicit Extension(const FilePath& path); virtual ~Extension(); @@ -186,6 +187,16 @@ class Extension { // the browser might load (like themes and page action icons). std::set<FilePath> GetBrowserImages(); + + // Runtime data: + // Put dynamic data about the state of a running extension below. + + // Whether the background page, if any, is ready. We don't load other + // components until then. If there is no background page, we consider it to + // be ready. + bool GetBackgroundPageReady(); + void SetBackgroundPageReady(); + private: // Counter used to assign ids to extensions that are loaded using // --load-extension. @@ -281,6 +292,12 @@ class Extension { // URL for fetching an update manifest GURL update_url_; + + + // Runtime data: + + // True if the background page is ready. + bool background_page_ready_; FRIEND_TEST(ExtensionTest, LoadPageActionHelper); diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index f4c296b..ad99d89 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -624,6 +624,9 @@ class NotificationType { // Sent when the contents or order of toolstrips in the shelf model change. EXTENSION_SHELF_MODEL_CHANGED, + // Sent when a background page is ready so other components can load. + EXTENSION_BACKGROUND_PAGE_READY, + // Debugging --------------------------------------------------------------- // Count (must be last) ---------------------------------------------------- diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 029b3cb..1d22e66 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -764,6 +764,11 @@ IPC_BEGIN_MESSAGES(ViewHost) // noption of the throbber stopping. IPC_MESSAGE_ROUTED0(ViewHostMsg_DidStopLoading) + // Sent when the document element is available for the toplevel frame. This + // happens after the page starts loading, but before all resources are + // finished. + IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentAvailableInMainFrame) + // Sent when the renderer loads a resource from its memory cache. // The security info is non empty if the resource was originally loaded over // a secure connection. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 91126bd..54305ee 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -1475,12 +1475,19 @@ void RenderView::DocumentElementAvailable(WebFrame* frame) { // HACK. This is a temporary workaround to allow cross-origin XHR for Chrome // extensions. It grants full access to every origin, when we really want // to be able to restrict them more specifically. - if (frame->GetURL().SchemeIs(chrome::kExtensionScheme)) + GURL url = frame->GetURL(); + if (url.SchemeIs(chrome::kExtensionScheme)) frame->GrantUniversalAccess(); if (RenderThread::current()) // Will be NULL during unit tests. RenderThread::current()->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_START); + + // Notify the browser about non-blank documents loading in the top frame. + if (url.is_valid() && url.spec() != "about:blank") { + if (frame == webview()->GetMainFrame()) + Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_)); + } } void RenderView::DidCreateScriptContextForFrame(WebFrame* webframe) { |