summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_host.cc24
-rw-r--r--chrome/browser/extensions/extension_host.h26
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc6
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h4
-rw-r--r--chrome/common/extensions/extension.cc17
-rw-r--r--chrome/common/extensions/extension.h19
-rw-r--r--chrome/common/notification_type.h3
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/renderer/render_view.cc9
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) {