summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-11 06:24:35 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-11 06:24:35 +0000
commit474a38fc5b87adffa43cb75d1cb81114ec5a0843 (patch)
treeb1ba7e3bb714a33485ed0037cacdad747a1b2244 /chrome
parent76b6d6a9d0bfd4331cd13c77aede5df81bccda97 (diff)
downloadchromium_src-474a38fc5b87adffa43cb75d1cb81114ec5a0843.zip
chromium_src-474a38fc5b87adffa43cb75d1cb81114ec5a0843.tar.gz
chromium_src-474a38fc5b87adffa43cb75d1cb81114ec5a0843.tar.bz2
Looks like this introduced leaks in sync ui tests. Sigh.
Revert "Move ExtensionFunctionDispatcher to ExtensionTabHelper. This" This reverts commit 4f08bad13a0cb2e40835869a9a7d9edb16a5be9a. Revert "Fix clang warning." This reverts commit 1663f72a9360677aad91a9417b44afd03a41181f. Revert "Fix chrome os" This reverts commit 1abb1afe1b78de4bc92a82fdd1e266166bc74707. TBR=mpcomplete@chromium.org git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84941 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chrome_content_browser_client.cc83
-rw-r--r--chrome/browser/chrome_content_browser_client.h3
-rw-r--r--chrome/browser/extensions/extension_bookmark_manager_api.cc19
-rw-r--r--chrome/browser/extensions/extension_bookmarks_module.cc2
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.cc13
-rw-r--r--chrome/browser/extensions/extension_function.cc56
-rw-r--r--chrome/browser/extensions/extension_function.h44
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc178
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.h71
-rw-r--r--chrome/browser/extensions/extension_host.cc64
-rw-r--r--chrome/browser/extensions/extension_host.h5
-rw-r--r--chrome/browser/extensions/extension_tab_helper.cc46
-rw-r--r--chrome/browser/extensions/extension_tab_helper.h12
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc2
-rw-r--r--chrome/browser/extensions/extension_web_ui.cc72
-rw-r--r--chrome/browser/extensions/extension_web_ui.h31
-rw-r--r--chrome/browser/extensions/extension_webstore_private_api.cc4
-rw-r--r--chrome/browser/extensions/extensions_ui.cc18
-rw-r--r--chrome/browser/memory_details.cc4
-rw-r--r--chrome/browser/notifications/balloon_host.cc57
-rw-r--r--chrome/browser/notifications/balloon_host.h11
-rw-r--r--chrome/browser/sidebar/sidebar_container.cc14
-rw-r--r--chrome/browser/ui/webui/options/extension_settings_handler.cc18
-rw-r--r--chrome/browser/visitedlink/visitedlink_unittest.cc4
-rw-r--r--chrome/renderer/extensions/extension_dispatcher.cc29
-rw-r--r--chrome/renderer/extensions/extension_dispatcher.h8
26 files changed, 448 insertions, 420 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8efed98..b7ce694 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -26,19 +26,13 @@
#include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "content/browser/browsing_instance.h"
-#include "content/browser/child_process_security_policy.h"
#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_view_host_notification_task.h"
#include "content/browser/resource_context.h"
-#include "content/browser/site_instance.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/worker_host/worker_process_host.h"
-#include "content/common/bindings_policy.h"
#include "net/base/cookie_monster.h"
#include "net/base/cookie_options.h"
#include "net/base/static_cookie_policy.h"
@@ -48,65 +42,6 @@
#include "chrome/browser/crash_handler_host_linux.h"
#endif // OS_LINUX
-namespace {
-
-void InitRenderViewHostForExtensions(RenderViewHost* render_view_host) {
- // Note that due to GetEffectiveURL(), even hosted apps will have a
- // chrome-extension:// URL for their site, so we can ignore that wrinkle here.
- SiteInstance* site_instance = render_view_host->site_instance();
- const GURL& site = site_instance->site();
- RenderProcessHost* process = render_view_host->process();
-
- if (!site.SchemeIs(chrome::kExtensionScheme))
- return;
-
- Profile* profile = site_instance->browsing_instance()->profile();
- ExtensionService* service = profile->GetExtensionService();
- if (!service)
- return;
-
- ExtensionProcessManager* process_manager =
- profile->GetExtensionProcessManager();
- CHECK(process_manager);
-
- // This can happen if somebody typos a chrome-extension:// URL.
- const Extension* extension = service->GetExtensionByURL(site);
- if (!extension)
- return;
-
- site_instance->GetProcess()->mark_is_extension_process();
-
- // Register the association between extension and process with
- // ExtensionProcessManager.
- process_manager->RegisterExtensionProcess(extension->id(), process->id());
-
- // Record which, if any, installed app is associated with this process.
- // TODO(aa): Totally lame to store this state in a global map in extension
- // service. Can we get it from EPM instead?
- if (extension->is_app())
- service->SetInstalledAppForRenderer(process->id(), extension);
-
- // Some extensions use chrome:// URLs.
- Extension::Type type = extension->GetType();
- if (type == Extension::TYPE_EXTENSION ||
- type == Extension::TYPE_PACKAGED_APP) {
- ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
- process->id(), chrome::kChromeUIScheme);
- }
-
- // Enable extension bindings for the renderer. Currently only extensions,
- // packaged apps, and hosted component apps use extension bindings.
- if (type == Extension::TYPE_EXTENSION ||
- type == Extension::TYPE_PACKAGED_APP ||
- (type == Extension::TYPE_HOSTED_APP &&
- extension->location() == Extension::COMPONENT)) {
- render_view_host->Send(new ExtensionMsg_ActivateExtension(extension->id()));
- render_view_host->AllowBindings(BindingsPolicy::EXTENSION);
- }
-}
-
-}
-
namespace chrome {
void ChromeContentBrowserClient::RenderViewHostCreated(
@@ -115,8 +50,24 @@ void ChromeContentBrowserClient::RenderViewHostCreated(
new DesktopNotificationHandler(render_view_host);
new DevToolsHandler(render_view_host);
new ExtensionMessageHandler(render_view_host);
+}
- InitRenderViewHostForExtensions(render_view_host);
+void ChromeContentBrowserClient::PreCreateRenderView(
+ RenderViewHost* render_view_host,
+ Profile* profile,
+ const GURL& url) {
+ // Tell the RenderViewHost whether it will be used for an extension process.
+ ExtensionService* service = profile->GetExtensionService();
+ if (service) {
+ bool is_extension_process = service->ExtensionBindingsAllowed(url);
+ render_view_host->set_is_extension_process(is_extension_process);
+
+ const Extension* installed_app = service->GetInstalledApp(url);
+ if (installed_app) {
+ service->SetInstalledAppForRenderer(
+ render_view_host->process()->id(), installed_app);
+ }
+ }
}
void ChromeContentBrowserClient::BrowserRenderProcessHostCreated(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 2ba3e24..ee81fd3 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -13,6 +13,9 @@ namespace chrome {
class ChromeContentBrowserClient : public content::ContentBrowserClient {
public:
virtual void RenderViewHostCreated(RenderViewHost* render_view_host);
+ virtual void PreCreateRenderView(RenderViewHost* render_view_host,
+ Profile* profile,
+ const GURL& url);
virtual void BrowserRenderProcessHostCreated(BrowserRenderProcessHost* host);
virtual void WorkerProcessHostCreated(WorkerProcessHost* host);
virtual content::WebUIFactory* GetWebUIFactory();
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 6d89d373..6f23fe8 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -365,13 +365,12 @@ bool StartDragBookmarkManagerFunction::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(
GetNodesFromArguments(model, args_.get(), 0, &nodes));
- if (render_view_host_->delegate()->GetRenderViewType() ==
+ if (dispatcher()->render_view_host()->delegate()->GetRenderViewType() ==
ViewType::TAB_CONTENTS) {
- TabContents* tab_contents =
- dispatcher()->delegate()->GetAssociatedTabContents();
- CHECK(tab_contents);
- bookmark_utils::DragBookmarks(profile(), nodes,
- tab_contents->GetNativeView());
+ ExtensionWebUI* web_ui =
+ static_cast<ExtensionWebUI*>(dispatcher()->delegate());
+ bookmark_utils::DragBookmarks(
+ profile(), nodes, web_ui->tab_contents()->GetNativeView());
return true;
} else {
@@ -407,14 +406,10 @@ bool DropBookmarkManagerFunction::RunImpl() {
else
drop_index = drop_parent->child_count();
- if (render_view_host_->delegate()->GetRenderViewType() ==
+ if (dispatcher()->render_view_host()->delegate()->GetRenderViewType() ==
ViewType::TAB_CONTENTS) {
- TabContents* tab_contents =
- dispatcher()->delegate()->GetAssociatedTabContents();
- CHECK(tab_contents);
ExtensionWebUI* web_ui =
- static_cast<ExtensionWebUI*>(tab_contents->web_ui());
- CHECK(web_ui);
+ static_cast<ExtensionWebUI*>(dispatcher()->delegate());
ExtensionBookmarkManagerEventRouter* router =
web_ui->extension_bookmark_manager_event_router();
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 37a814f..1777e79 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -856,7 +856,7 @@ void BookmarksIOFunction::ShowSelectFileDialog(SelectFileDialog::Type type,
file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
TabContents* tab_contents = dispatcher()->delegate()->
- GetAssociatedTabContents();
+ associated_tab_contents();
// |tab_contents| can be NULL (for background pages), which is fine. In such
// a case if file-selection dialogs are forbidden by policy, we will not
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc
index 6063d3c..bff14a5 100644
--- a/chrome/browser/extensions/extension_file_browser_private_api.cc
+++ b/chrome/browser/extensions/extension_file_browser_private_api.cc
@@ -352,7 +352,8 @@ void RequestLocalFileSystemFunction::RequestOnFileThread(
}
bool RequestLocalFileSystemFunction::RunImpl() {
- if (!dispatcher() || !render_view_host() || !render_view_host()->process())
+ if (!dispatcher() || !dispatcher()->render_view_host() ||
+ !dispatcher()->render_view_host()->process())
return false;
BrowserThread::PostTask(
@@ -360,7 +361,7 @@ bool RequestLocalFileSystemFunction::RunImpl() {
NewRunnableMethod(this,
&RequestLocalFileSystemFunction::RequestOnFileThread,
source_url_,
- render_view_host()->process()->id()));
+ dispatcher()->render_view_host()->process()->id()));
// Will finish asynchronously.
return true;
}
@@ -677,7 +678,7 @@ void ExecuteTasksFileBrowserFunction::RequestFileEntryOnFileThread(
new ExecuteTasksFileSystemCallbackDispatcher(
this,
profile(),
- render_view_host()->process()->id(),
+ dispatcher()->render_view_host()->process()->id(),
source_url,
GetExtension(),
task_id,
@@ -803,13 +804,13 @@ FileDialogFunction::Callback::Find(int32 tab_id) {
int32 FileDialogFunction::GetTabId() const {
- return dispatcher()->delegate()->GetAssociatedTabContents()->
+ return dispatcher()->delegate()->associated_tab_contents()->
controller().session_id().id();
}
const FileDialogFunction::Callback& FileDialogFunction::GetCallback() const {
if (!dispatcher() || !dispatcher()->delegate() ||
- !dispatcher()->delegate()->GetAssociatedTabContents()) {
+ !dispatcher()->delegate()->associated_tab_contents()) {
return Callback::null();
}
return Callback::Find(GetTabId());
@@ -817,7 +818,7 @@ const FileDialogFunction::Callback& FileDialogFunction::GetCallback() const {
void FileDialogFunction::CloseDialog(HtmlDialogView* dialog) {
DCHECK(dialog);
- TabContents* contents = dispatcher()->delegate()->GetAssociatedTabContents();
+ TabContents* contents = dispatcher()->delegate()->associated_tab_contents();
if (contents)
dialog->CloseContents(contents);
}
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index f390d72..9f0d065 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,31 +9,6 @@
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/extension_messages.h"
-#include "content/browser/renderer_host/render_process_host.h"
-#include "content/browser/renderer_host/render_view_host.h"
-#include "content/browser/user_metrics.h"
-#include "content/common/notification_source.h"
-#include "content/common/notification_type.h"
-#include "content/common/result_codes.h"
-
-ExtensionFunction::RenderViewHostTracker::RenderViewHostTracker(
- ExtensionFunction* function)
- : function_(function) {
- registrar_.Add(this,
- NotificationType::RENDER_VIEW_HOST_DELETED,
- Source<RenderViewHost>(function->render_view_host()));
-}
-
-void ExtensionFunction::RenderViewHostTracker::Observe(
- NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- CHECK(type == NotificationType::RENDER_VIEW_HOST_DELETED);
- CHECK(Source<RenderViewHost>(source).ptr() ==
- function_->render_view_host());
- function_->SetRenderViewHost(NULL);
-}
ExtensionFunction::ExtensionFunction()
: request_id_(-1),
@@ -46,11 +21,6 @@ ExtensionFunction::ExtensionFunction()
ExtensionFunction::~ExtensionFunction() {
}
-void ExtensionFunction::SetRenderViewHost(RenderViewHost* render_view_host) {
- render_view_host_ = render_view_host;
- tracker_.reset(render_view_host ? new RenderViewHostTracker(this) : NULL);
-}
-
const Extension* ExtensionFunction::GetExtension() {
ExtensionService* service = profile_->GetExtensionService();
DCHECK(service);
@@ -58,7 +28,7 @@ const Extension* ExtensionFunction::GetExtension() {
}
Browser* ExtensionFunction::GetCurrentBrowser() {
- return dispatcher()->GetCurrentBrowser(render_view_host_, include_incognito_);
+ return dispatcher()->GetCurrentBrowser(include_incognito_);
}
AsyncExtensionFunction::AsyncExtensionFunction()
@@ -91,28 +61,12 @@ void AsyncExtensionFunction::Run() {
}
void AsyncExtensionFunction::SendResponse(bool success) {
- if (!render_view_host_ || !dispatcher())
+ if (!dispatcher())
return;
if (bad_message_) {
- HandleBadMessage();
- return;
- }
-
- render_view_host_->Send(new ExtensionMsg_Response(
- render_view_host_->routing_id(), request_id_, success,
- GetResult(), GetError()));
-}
-
-void AsyncExtensionFunction::HandleBadMessage() {
- LOG(ERROR) << "bad extension message " << name_ << " : terminating renderer.";
- if (RenderProcessHost::run_renderer_in_process()) {
- // In single process mode it is better if we don't suicide but just crash.
- CHECK(false);
+ dispatcher()->HandleBadMessage(this);
} else {
- NOTREACHED();
- UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_EFD"));
- base::KillProcess(render_view_host_->process()->GetHandle(),
- ResultCodes::KILLED_BAD_MESSAGE, false);
+ dispatcher()->SendResponse(this, success);
}
}
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index 2148f8a..7913703 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -11,9 +11,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/browser_thread.h"
-#include "content/common/notification_observer.h"
-#include "content/common/notification_registrar.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
class ExtensionFunctionDispatcher;
@@ -40,14 +37,10 @@ class Value;
// Abstract base class for extension functions the ExtensionFunctionDispatcher
// knows how to dispatch to.
-class ExtensionFunction
- : public base::RefCountedThreadSafe<ExtensionFunction,
- BrowserThread::DeleteOnUIThread> {
+class ExtensionFunction : public base::RefCountedThreadSafe<ExtensionFunction> {
public:
ExtensionFunction();
- virtual ~ExtensionFunction();
-
// Specifies the name of the function.
void set_name(const std::string& name) { name_ = name; }
const std::string name() const { return name_; }
@@ -63,9 +56,6 @@ class ExtensionFunction
}
std::string extension_id() const { return extension_id_; }
- void SetRenderViewHost(RenderViewHost* render_view_host);
- RenderViewHost* render_view_host() const { return render_view_host_; }
-
// Specifies the raw arguments to the function, as a JSON value.
virtual void SetArgs(const ListValue* args) = 0;
@@ -112,6 +102,8 @@ class ExtensionFunction
protected:
friend class base::RefCountedThreadSafe<ExtensionFunction>;
+ virtual ~ExtensionFunction();
+
// Gets the extension that called this function. This can return NULL for
// async functions, for example if the extension is unloaded while the
// function is running.
@@ -138,9 +130,6 @@ class ExtensionFunction
// The peer to the dispatcher that will service this extension function call.
scoped_refptr<ExtensionFunctionDispatcher::Peer> peer_;
- // The RenderViewHost we will send responses too.
- RenderViewHost* render_view_host_;
-
// Id of this request, used to map the response back to the caller.
int request_id_;
@@ -169,26 +158,6 @@ class ExtensionFunction
// True if the call was made in response of user gesture.
bool user_gesture_;
- private:
- // Helper class to track the lifetime of ExtensionFunction's RenderViewHost
- // pointer and NULL it out when it dies. We use this separate class (instead
- // of implementing NotificationObserver on ExtensionFunction) because it is
- // common for subclasses of ExtensionFunction to be NotificationObservers, and
- // it would be an easy error to forget to call the base class's Observe()
- // method.
- class RenderViewHostTracker : public NotificationObserver {
- public:
- explicit RenderViewHostTracker(ExtensionFunction* extension_function);
- private:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
- ExtensionFunction* function_;
- NotificationRegistrar registrar_;
- };
-
- scoped_ptr<RenderViewHostTracker> tracker_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
};
@@ -235,13 +204,6 @@ class AsyncExtensionFunction : public ExtensionFunction {
// returning. The calling renderer process will be killed.
bool bad_message_;
- private:
- // Called when we receive an extension api request that is invalid in a way
- // that JSON validation in the renderer should have caught. This should never
- // happen and could be an attacker trying to exploit the browser, so we crash
- // the renderer instead.
- void HandleBadMessage();
-
DISALLOW_COPY_AND_ASSIGN(AsyncExtensionFunction);
};
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 8a27836..6a69d42 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/extensions/extension_omnibox_api.h"
#include "chrome/browser/extensions/extension_page_actions_module.h"
#include "chrome/browser/extensions/extension_preference_api.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_processes_api.h"
#include "chrome/browser/extensions/extension_proxy_api.h"
#include "chrome/browser/extensions/extension_rlz_module.h"
@@ -51,6 +52,9 @@
#include "content/browser/child_process_security_policy.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/user_metrics.h"
+#include "content/common/notification_service.h"
+#include "content/common/result_codes.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -381,19 +385,71 @@ void ExtensionFunctionDispatcher::ResetFunctions() {
FactoryRegistry::GetInstance()->ResetFunctions();
}
-ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile,
- Delegate* delegate)
- : profile_(profile),
+ExtensionFunctionDispatcher* ExtensionFunctionDispatcher::Create(
+ RenderViewHost* render_view_host,
+ Delegate* delegate,
+ const GURL& url) {
+ ExtensionService* service =
+ render_view_host->process()->profile()->GetExtensionService();
+ DCHECK(service);
+
+ if (!service->ExtensionBindingsAllowed(url))
+ return NULL;
+
+ const Extension* extension = service->GetExtensionByURL(url);
+ if (!extension)
+ extension = service->GetExtensionByWebExtent(url);
+
+ if (extension)
+ return new ExtensionFunctionDispatcher(render_view_host, delegate,
+ extension, url);
+ else
+ return NULL;
+}
+
+ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
+ RenderViewHost* render_view_host,
+ Delegate* delegate,
+ const Extension* extension,
+ const GURL& url)
+ : profile_(render_view_host->process()->profile()),
+ render_view_host_(render_view_host),
delegate_(delegate),
+ url_(url),
+ extension_id_(extension->id()),
ALLOW_THIS_IN_INITIALIZER_LIST(peer_(new Peer(this))) {
+ // TODO(erikkay) should we do something for these errors in Release?
+ DCHECK(extension);
+ DCHECK(url.SchemeIs(chrome::kExtensionScheme) ||
+ extension->location() == Extension::COMPONENT);
+
+ // Notify the ExtensionProcessManager that the view was created.
+ ExtensionProcessManager* epm = profile()->GetExtensionProcessManager();
+ epm->RegisterExtensionProcess(extension_id(),
+ render_view_host->process()->id());
+
+ // Activate this extension in the renderer. This must be done before any
+ // extension JavaScript code runs because it controls some privileges the
+ // extension code has in the renderer.
+ render_view_host->Send(new ExtensionMsg_ActivateExtension(extension->id()));
+
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED,
+ Source<Profile>(profile_),
+ Details<ExtensionFunctionDispatcher>(this));
}
ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
peer_->dispatcher_ = NULL;
+
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
+ Source<Profile>(profile_),
+ Details<ExtensionFunctionDispatcher>(this));
}
Browser* ExtensionFunctionDispatcher::GetCurrentBrowser(
- RenderViewHost* render_view_host, bool include_incognito) {
+ bool include_incognito) {
Browser* browser = delegate_->GetBrowser();
// If the delegate has an associated browser, that is always the right answer.
@@ -405,7 +461,7 @@ Browser* ExtensionFunctionDispatcher::GetCurrentBrowser(
// profile. Note that the profile may already be incognito, in which case
// we will search the incognito version only, regardless of the value of
// |include_incognito|.
- Profile* profile = render_view_host->process()->profile();
+ Profile* profile = render_view_host()->process()->profile();
browser = BrowserList::FindTabbedBrowser(profile, include_incognito);
// NOTE(rafaelw): This can return NULL in some circumstances. In particular,
@@ -417,84 +473,88 @@ Browser* ExtensionFunctionDispatcher::GetCurrentBrowser(
return browser;
}
-void ExtensionFunctionDispatcher::Dispatch(
- const ExtensionHostMsg_Request_Params& params,
- RenderViewHost* render_view_host) {
- // TODO(aa): It would be cool to use ExtensionProcessManager to track which
- // processes are extension processes rather than ChildProcessSecurityPolicy.
- // EPM has richer information: it not only knows which processes contain
- // at least one extension, but it knows which extensions are inside and what
- // permissions the have. So we would be able to enforce permissions more
- // granularly.
- if (!ChildProcessSecurityPolicy::GetInstance()->HasExtensionBindings(
- render_view_host->process()->id())) {
- // TODO(aa): Allow content scripts access to low-threat extension APIs.
- // See: crbug.com/80308.
- LOG(ERROR) << "Extension API called from non-extension process.";
- SendAccessDenied(render_view_host, params.request_id);
- return;
- }
-
- ExtensionService* service = profile()->GetExtensionService();
- if (!service)
- return;
-
- if (!service->ExtensionBindingsAllowed(params.source_url)) {
- LOG(ERROR) << "Extension bindings not allowed for URL: "
- << params.source_url.spec();
- SendAccessDenied(render_view_host, params.request_id);
- return;
- }
-
- // TODO(aa): When we allow content scripts to call extension APIs, we will
- // have to pass the extension ID explicitly here, not use the source URL.
- const Extension* extension = service->GetExtensionByURL(params.source_url);
- if (!extension)
- extension = service->GetExtensionByWebExtent(params.source_url);
- if (!extension) {
- LOG(ERROR) << "Extension does not exist for URL: "
- << params.source_url.spec();
- SendAccessDenied(render_view_host, params.request_id);
- return;
- }
+bool ExtensionFunctionDispatcher::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ExtensionFunctionDispatcher, message)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
- if (!extension->HasApiPermission(params.name)) {
- LOG(ERROR) << "Extension " << extension->id() << " does not have "
- << "permission to function: " << params.name;
- SendAccessDenied(render_view_host, params.request_id);
+void ExtensionFunctionDispatcher::OnRequest(
+ const ExtensionHostMsg_Request_Params& params) {
+ if (!ChildProcessSecurityPolicy::GetInstance()->
+ HasExtensionBindings(render_view_host_->process()->id())) {
+ // This can happen if someone uses window.open() to open an extension URL
+ // from a non-extension context.
+ render_view_host_->Send(new ExtensionMsg_Response(
+ render_view_host_->routing_id(), params.request_id, false,
+ std::string(), "Access to extension API denied."));
return;
}
scoped_refptr<ExtensionFunction> function(
FactoryRegistry::GetInstance()->NewFunction(params.name));
- function->SetRenderViewHost(render_view_host);
function->set_dispatcher_peer(peer_);
function->set_profile(profile_);
- function->set_extension_id(extension->id());
+ function->set_extension_id(extension_id());
function->SetArgs(&params.arguments);
function->set_source_url(params.source_url);
function->set_request_id(params.request_id);
function->set_has_callback(params.has_callback);
function->set_user_gesture(params.user_gesture);
+ ExtensionService* service = profile()->GetExtensionService();
+ DCHECK(service);
+ const Extension* extension = service->GetExtensionById(extension_id(), false);
+ DCHECK(extension);
function->set_include_incognito(service->CanCrossIncognito(extension));
+ if (!service->ExtensionBindingsAllowed(function->source_url()) ||
+ !extension->HasApiPermission(function->name())) {
+ render_view_host_->Send(new ExtensionMsg_Response(
+ render_view_host_->routing_id(), function->request_id(), false,
+ std::string(), "Access to extension API denied."));
+ return;
+ }
+
ExtensionsQuotaService* quota = service->quota_service();
- if (quota->Assess(extension->id(), function, &params.arguments,
+ if (quota->Assess(extension_id(), function, &params.arguments,
base::TimeTicks::Now())) {
// See crbug.com/39178.
ExternalProtocolHandler::PermitLaunchUrl();
function->Run();
} else {
- render_view_host->Send(new ExtensionMsg_Response(
- render_view_host->routing_id(), function->request_id(), false,
+ render_view_host_->Send(new ExtensionMsg_Response(
+ render_view_host_->routing_id(), function->request_id(), false,
std::string(), QuotaLimitHeuristic::kGenericOverQuotaError));
}
}
-void ExtensionFunctionDispatcher::SendAccessDenied(
- RenderViewHost* render_view_host, int request_id) {
- render_view_host->Send(new ExtensionMsg_Response(
- render_view_host->routing_id(), request_id, false, std::string(),
- "Access to extension API denied."));
+void ExtensionFunctionDispatcher::SendResponse(ExtensionFunction* function,
+ bool success) {
+ render_view_host_->Send(new ExtensionMsg_Response(
+ render_view_host_->routing_id(), function->request_id(), success,
+ function->GetResult(), function->GetError()));
+}
+
+void ExtensionFunctionDispatcher::HandleBadMessage(ExtensionFunction* api) {
+ LOG(ERROR) << "bad extension message " <<
+ api->name() <<
+ " : terminating renderer.";
+ if (RenderProcessHost::run_renderer_in_process()) {
+ // In single process mode it is better if we don't suicide but just crash.
+ CHECK(false);
+ } else {
+ NOTREACHED();
+ UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_EFD"));
+ base::KillProcess(render_view_host_->process()->GetHandle(),
+ ResultCodes::KILLED_BAD_MESSAGE, false);
+ }
+}
+
+Profile* ExtensionFunctionDispatcher::profile() {
+ return profile_;
}
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index d3b8d1c..9f91d9d 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "googleurl/src/gurl.h"
+#include "ipc/ipc_channel.h"
#include "ui/gfx/native_widget_types.h"
class Browser;
@@ -26,19 +27,9 @@ struct ExtensionHostMsg_Request_Params;
typedef ExtensionFunction* (*ExtensionFunctionFactory)();
// ExtensionFunctionDispatcher receives requests to execute functions from
-// Chrome extensions running in a RenderViewHost and dispatches them to the
+// Chromium extensions running in a RenderViewHost and dispatches them to the
// appropriate handler. It lives entirely on the UI thread.
-//
-// ExtensionFunctionDispatcher should be a member of some class that hosts
-// RenderViewHosts and wants them to be able to display extension content.
-// This class should also implement ExtensionFunctionDispatcher::Delegate.
-//
-// Note that a single ExtensionFunctionDispatcher does *not* correspond to a
-// single RVH, a single extension, or a single URL. This is by design so that
-// we can gracefully handle cases like TabContents, where the RVH, extension,
-// and URL can all change over the lifetime of the tab. Instead, these items
-// are all passed into each request.
-class ExtensionFunctionDispatcher {
+class ExtensionFunctionDispatcher : public IPC::Channel::Listener {
public:
class Delegate {
public:
@@ -54,7 +45,7 @@ class ExtensionFunctionDispatcher {
// context. For example, the TabContents in which an infobar or
// chrome-extension://<id> URL are being shown. Callers must check for a
// NULL return value (as in the case of a background page).
- virtual TabContents* GetAssociatedTabContents() const = 0;
+ virtual TabContents* associated_tab_contents() const = 0;
protected:
virtual ~Delegate() {}
@@ -85,19 +76,21 @@ class ExtensionFunctionDispatcher {
// Resets all functions to their initial implementation.
static void ResetFunctions();
- // Public constructor. Callers must ensure that:
- // - |delegate| outlives this object.
- // - This object outlives any RenderViewHost's passed to created
- // ExtensionFunctions.
- ExtensionFunctionDispatcher(Profile* profile, Delegate* delegate);
+ // Creates an instance for the specified RenderViewHost and URL. If the URL
+ // does not contain a valid extension, returns NULL.
+ static ExtensionFunctionDispatcher* Create(RenderViewHost* render_view_host,
+ Delegate* delegate,
+ const GURL& url);
~ExtensionFunctionDispatcher();
Delegate* delegate() { return delegate_; }
- // Message handlers.
- void Dispatch(const ExtensionHostMsg_Request_Params& params,
- RenderViewHost* sender);
+ // If |message| is an extension request, handle it. Returns true if handled.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // Send a response to a function.
+ void SendResponse(ExtensionFunction* api, bool success);
// Returns the current browser. Callers should generally prefer
// ExtensionFunction::GetCurrentBrowser() over this method, as that one
@@ -105,20 +98,46 @@ class ExtensionFunctionDispatcher {
//
// See the comments for ExtensionFunction::GetCurrentBrowser() for more
// details.
- Browser* GetCurrentBrowser(RenderViewHost* render_view_host,
- bool include_incognito);
+ Browser* GetCurrentBrowser(bool include_incognito);
+
+ // Handle a malformed message. Possibly the result of an attack, so kill
+ // the renderer.
+ void HandleBadMessage(ExtensionFunction* api);
+
+ // Gets the URL for the view we're displaying.
+ const GURL& url() { return url_; }
+
+ // Gets the ID for this extension.
+ const std::string extension_id() { return extension_id_; }
// The profile that this dispatcher is associated with.
- Profile* profile() { return profile_; }
+ Profile* profile();
+
+ // The RenderViewHost this dispatcher is associated with.
+ RenderViewHost* render_view_host() { return render_view_host_; }
private:
- // Helper to send an access denied error to the requesting render view.
- void SendAccessDenied(RenderViewHost* render_view_host, int request_id);
+ ExtensionFunctionDispatcher(RenderViewHost* render_view_host,
+ Delegate* delegate,
+ const Extension* extension,
+ const GURL& url);
+ // Message handlers.
+ void OnRequest(const ExtensionHostMsg_Request_Params& params);
+
+ // We need to keep a pointer to the profile because we use it in the dtor
+ // in sending EXTENSION_FUNCTION_DISPATCHER_DESTROYED, but by that point
+ // the render_view_host_ has been deleted.
Profile* profile_;
+ RenderViewHost* render_view_host_;
+
Delegate* delegate_;
+ GURL url_;
+
+ std::string extension_id_;
+
scoped_refptr<Peer> peer_;
};
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 318ca0b..7badebf 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -28,7 +28,6 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/view_types.h"
@@ -132,13 +131,17 @@ ExtensionHost::ExtensionHost(const Extension* extension,
did_stop_loading_(false),
document_element_available_(false),
url_(url),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- extension_function_dispatcher_(profile_, this)),
extension_host_type_(host_type),
associated_tab_contents_(NULL),
suppress_javascript_messages_(false) {
render_view_host_ = new RenderViewHost(site_instance, this, MSG_ROUTING_NONE,
NULL);
+ render_view_host_->set_is_extension_process(true);
+ if (extension->is_app()) {
+ profile()->GetExtensionService()->SetInstalledAppForRenderer(
+ render_view_host_->process()->id(), extension);
+ }
+ render_view_host_->AllowBindings(BindingsPolicy::EXTENSION);
if (enable_dom_automation_)
render_view_host_->AllowBindings(BindingsPolicy::DOM_AUTOMATION);
@@ -179,7 +182,7 @@ void ExtensionHost::CreateView(Browser* browser) {
#endif
}
-TabContents* ExtensionHost::GetAssociatedTabContents() const {
+TabContents* ExtensionHost::associated_tab_contents() const {
return associated_tab_contents_;
}
@@ -311,9 +314,6 @@ void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host,
if (!extension_)
return;
- // TODO(aa): This is suspicious. There can be multiple views in an extension,
- // and they aren't all going to use ExtensionHost. This should be in someplace
- // more central, like EPM maybe.
DCHECK_EQ(render_view_host_, render_view_host);
NotificationService::current()->Notify(
NotificationType::EXTENSION_PROCESS_TERMINATED,
@@ -327,7 +327,29 @@ void ExtensionHost::DidNavigate(RenderViewHost* render_view_host,
if (!PageTransition::IsMainFrame(params.transition))
return;
+ if (!params.url.SchemeIs(chrome::kExtensionScheme)) {
+ extension_function_dispatcher_.reset(NULL);
+ url_ = params.url;
+ return;
+ }
+
+ // This catches two bogus use cases:
+ // (1) URLs that look like chrome-extension://somethingbogus or
+ // chrome-extension://nosuchid/, in other words, no Extension would
+ // be found.
+ // (2) URLs that refer to a different extension than this one.
+ // In both cases, we preserve the old URL and reset the EFD to NULL. This
+ // will leave the host in kind of a bad state with poor UI and errors, but
+ // it's better than the alternative.
+ // TODO(erikkay) Perhaps we should display errors in developer mode.
+ if (params.url.host() != extension_id()) {
+ extension_function_dispatcher_.reset(NULL);
+ return;
+ }
+
url_ = params.url;
+ extension_function_dispatcher_.reset(
+ ExtensionFunctionDispatcher::Create(render_view_host_, this, url_));
}
void ExtensionHost::InsertInfobarCSS() {
@@ -443,8 +465,7 @@ gfx::NativeWindow ExtensionHost::GetMessageBoxRootWindow() {
return platform_util::GetTopLevel(native_view);
// Otherwise, try the active tab's view.
- Browser* browser = extension_function_dispatcher_.GetCurrentBrowser(
- render_view_host_, true);
+ Browser* browser = extension_function_dispatcher_->GetCurrentBrowser(true);
if (browser) {
TabContents* active_tab = browser->GetSelectedTabContents();
if (active_tab)
@@ -486,7 +507,7 @@ void ExtensionHost::Close(RenderViewHost* render_view_host) {
RendererPreferences ExtensionHost::GetRendererPrefs(Profile* profile) const {
RendererPreferences preferences;
- TabContents* associated_contents = GetAssociatedTabContents();
+ TabContents* associated_contents = associated_tab_contents();
if (associated_contents)
preferences =
static_cast<RenderViewHostDelegate*>(associated_contents)->
@@ -540,7 +561,7 @@ void ExtensionHost::CreateNewWindow(
params.window_container_type,
params.frame_name);
- TabContents* associated_contents = GetAssociatedTabContents();
+ TabContents* associated_contents = associated_tab_contents();
if (associated_contents && associated_contents->delegate())
associated_contents->delegate()->TabContentsCreated(new_contents);
}
@@ -595,7 +616,7 @@ void ExtensionHost::ShowCreatedWindow(int route_id,
// the case of extensions in 'spanning' incognito mode, they can mismatch.
// We don't want to end up putting a normal tab into an incognito window, or
// vice versa.
- TabContents* associated_contents = GetAssociatedTabContents();
+ TabContents* associated_contents = associated_tab_contents();
if (associated_contents &&
associated_contents->profile() == contents->profile()) {
associated_contents->AddNewContents(
@@ -753,19 +774,19 @@ ViewType::Type ExtensionHost::GetRenderViewType() const {
}
bool ExtensionHost::OnMessageReceived(const IPC::Message& message) {
+ if (extension_function_dispatcher_.get() &&
+ extension_function_dispatcher_->OnMessageReceived(message)) {
+ return true;
+ }
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message)
IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) {
- extension_function_dispatcher_.Dispatch(params, render_view_host_);
-}
-
const GURL& ExtensionHost::GetURL() const {
return url_;
}
@@ -774,6 +795,13 @@ void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) {
if (view_.get())
view_->RenderViewCreated();
+ // TODO(mpcomplete): This is duplicated in DidNavigate, which means that
+ // we'll create 2 EFDs for the first navigation. We should try to find a
+ // better way to unify them.
+ // See http://code.google.com/p/chromium/issues/detail?id=18240
+ extension_function_dispatcher_.reset(
+ ExtensionFunctionDispatcher::Create(render_view_host, this, url_));
+
if (extension_host_type_ == ViewType::EXTENSION_POPUP ||
extension_host_type_ == ViewType::EXTENSION_INFOBAR) {
render_view_host->EnablePreferredSizeChangedMode(
@@ -804,5 +832,5 @@ void ExtensionHost::OnRunFileChooser(
if (file_select_helper_.get() == NULL)
file_select_helper_.reset(new FileSelectHelper(profile()));
file_select_helper_->RunFileChooser(render_view_host_,
- GetAssociatedTabContents(), params);
+ associated_tab_contents(), params);
}
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 87b691c..311975d 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -86,7 +86,7 @@ class ExtensionHost : public RenderViewHostDelegate,
ViewType::Type extension_host_type() const { return extension_host_type_; }
// ExtensionFunctionDispatcher::Delegate
- virtual TabContents* GetAssociatedTabContents() const;
+ virtual TabContents* associated_tab_contents() const;
void set_associated_tab_contents(TabContents* associated_tab_contents) {
associated_tab_contents_ = associated_tab_contents;
}
@@ -229,7 +229,6 @@ class ExtensionHost : public RenderViewHostDelegate,
// Message handlers.
void OnRunFileChooser(const ViewHostMsg_RunFileChooser_Params& params);
- void OnRequest(const ExtensionHostMsg_Request_Params& params);
// Handles keyboard events that were not handled by HandleKeyboardEvent().
// Platform specific implementation may override this method to handle the
@@ -275,7 +274,7 @@ class ExtensionHost : public RenderViewHostDelegate,
NotificationRegistrar registrar_;
- ExtensionFunctionDispatcher extension_function_dispatcher_;
+ scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
// Only EXTENSION_INFOBAR, EXTENSION_POPUP, and EXTENSION_BACKGROUND_PAGE
// are used here, others are not hosted by ExtensionHost.
diff --git a/chrome/browser/extensions/extension_tab_helper.cc b/chrome/browser/extensions/extension_tab_helper.cc
index 8a1caa5..6f44f6c 100644
--- a/chrome/browser/extensions/extension_tab_helper.cc
+++ b/chrome/browser/extensions/extension_tab_helper.cc
@@ -6,15 +6,12 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
#include "chrome/common/extensions/extension_action.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/extension_resource.h"
-#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/navigation_controller.h"
#include "content/common/notification_service.h"
@@ -22,8 +19,6 @@
ExtensionTabHelper::ExtensionTabHelper(TabContentsWrapper* wrapper)
: TabContentsObserver(wrapper->tab_contents()),
extension_app_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- extension_function_dispatcher_(wrapper->profile(), this)),
wrapper_(wrapper) {
}
@@ -118,7 +113,6 @@ bool ExtensionTabHelper::OnMessageReceived(const IPC::Message& message) {
OnDidGetApplicationInfo)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_InstallApplication,
OnInstallApplication)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -137,12 +131,6 @@ void ExtensionTabHelper::OnInstallApplication(const WebApplicationInfo& info) {
wrapper_->delegate()->OnInstallApplication(wrapper_, info);
}
-void ExtensionTabHelper::OnRequest(
- const ExtensionHostMsg_Request_Params& request) {
- extension_function_dispatcher_.Dispatch(request,
- tab_contents()->render_view_host());
-}
-
void ExtensionTabHelper::UpdateExtensionAppIcon(const Extension* extension) {
extension_app_icon_.reset();
@@ -173,37 +161,3 @@ void ExtensionTabHelper::OnImageLoaded(SkBitmap* image,
tab_contents()->NotifyNavigationStateChanged(TabContents::INVALIDATE_TAB);
}
}
-
-Browser* ExtensionTabHelper::GetBrowser() {
- TabContents* contents = tab_contents();
- TabContentsIterator tab_iterator;
- for (; !tab_iterator.done(); ++tab_iterator) {
- if (contents == (*tab_iterator)->tab_contents())
- return tab_iterator.browser();
- }
-
- return NULL;
-}
-
-TabContents* ExtensionTabHelper::GetAssociatedTabContents() const {
- return tab_contents();
-}
-
-gfx::NativeWindow ExtensionTabHelper::GetCustomFrameNativeWindow() {
- if (GetBrowser())
- return NULL;
-
- // If there was no browser associated with the function dispatcher delegate,
- // then this WebUI may be hosted in an ExternalTabContainer, and a framing
- // window will be accessible through the tab_contents.
- TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
- if (tab_contents_delegate)
- return tab_contents_delegate->GetFrameNativeWindow();
- else
- return NULL;
-}
-
-gfx::NativeView ExtensionTabHelper::GetNativeViewOfHost() {
- RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
- return rwhv ? rwhv->GetNativeView() : NULL;
-}
diff --git a/chrome/browser/extensions/extension_tab_helper.h b/chrome/browser/extensions/extension_tab_helper.h
index 8a4b51e..46b0348 100644
--- a/chrome/browser/extensions/extension_tab_helper.h
+++ b/chrome/browser/extensions/extension_tab_helper.h
@@ -7,7 +7,6 @@
#pragma once
#include "content/browser/tab_contents/tab_contents_observer.h"
-#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/common/web_apps.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -18,7 +17,6 @@ struct WebApplicationInfo;
// Per-tab extension helper. Also handles non-extension apps.
class ExtensionTabHelper : public TabContentsObserver,
- public ExtensionFunctionDispatcher::Delegate,
public ImageLoadingTracker::Observer {
public:
explicit ExtensionTabHelper(TabContentsWrapper* wrapper);
@@ -79,16 +77,9 @@ class ExtensionTabHelper : public TabContentsObserver,
const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message);
- // ExtensionFunctionDispatcher::Delegate overrides.
- virtual Browser* GetBrowser();
- virtual gfx::NativeView GetNativeViewOfHost();
- virtual gfx::NativeWindow GetCustomFrameNativeWindow();
- virtual TabContents* GetAssociatedTabContents() const;
-
// Message handlers.
void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info);
void OnInstallApplication(const WebApplicationInfo& info);
- void OnRequest(const ExtensionHostMsg_Request_Params& params);
// App extensions related methods:
@@ -110,9 +101,6 @@ class ExtensionTabHelper : public TabContentsObserver,
// non-extension apps.
SkBitmap extension_app_icon_;
- // Process any extension messages coming from the tab.
- ExtensionFunctionDispatcher extension_function_dispatcher_;
-
// Used for loading extension_app_icon_.
scoped_ptr<ImageLoadingTracker> extension_app_image_loader_;
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 97654bf..a43d894 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -793,7 +793,7 @@ bool GetTabFunction::RunImpl() {
bool GetCurrentTabFunction::RunImpl() {
DCHECK(dispatcher());
- TabContents* contents = dispatcher()->delegate()->GetAssociatedTabContents();
+ TabContents* contents = dispatcher()->delegate()->associated_tab_contents();
if (contents)
result_.reset(ExtensionTabUtil::CreateTabValue(contents));
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index a816c76..e398c46 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -24,9 +24,11 @@
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/url_constants.h"
+#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/bindings_policy.h"
#include "content/common/page_transition_types.h"
+#include "ipc/ipc_message.h"
#include "net/base/file_stream.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
@@ -138,6 +140,7 @@ ExtensionWebUI::ExtensionWebUI(TabContents* tab_contents, const GURL& url)
// component apps like bookmark manager.
should_hide_url_ = !extension->is_hosted_app();
+ bindings_ = BindingsPolicy::EXTENSION;
// Bind externalHost to Extension WebUI loaded in Chrome Frame.
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kChromeFrame))
@@ -152,23 +155,86 @@ ExtensionWebUI::ExtensionWebUI(TabContents* tab_contents, const GURL& url)
should_hide_url_ = false;
}
}
+}
+
+ExtensionWebUI::~ExtensionWebUI() {}
+void ExtensionWebUI::ResetExtensionFunctionDispatcher(
+ RenderViewHost* render_view_host) {
+ // TODO(jcivelli): http://crbug.com/60608 we should get the URL out of the
+ // active entry of the navigation controller.
+ extension_function_dispatcher_.reset(
+ ExtensionFunctionDispatcher::Create(render_view_host, this, url_));
+ DCHECK(extension_function_dispatcher_.get());
+}
+
+void ExtensionWebUI::ResetExtensionBookmarkManagerEventRouter() {
// Hack: A few things we specialize just for the bookmark manager.
- if (extension->id() == extension_misc::kBookmarkManagerId) {
+ if (extension_function_dispatcher_->extension_id() ==
+ extension_misc::kBookmarkManagerId) {
extension_bookmark_manager_event_router_.reset(
- new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents));
+ new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents()));
link_transition_type_ = PageTransition::AUTO_BOOKMARK;
}
}
-ExtensionWebUI::~ExtensionWebUI() {}
+void ExtensionWebUI::RenderViewCreated(RenderViewHost* render_view_host) {
+ ResetExtensionFunctionDispatcher(render_view_host);
+ ResetExtensionBookmarkManagerEventRouter();
+}
+
+void ExtensionWebUI::RenderViewReused(RenderViewHost* render_view_host) {
+ ResetExtensionFunctionDispatcher(render_view_host);
+ ResetExtensionBookmarkManagerEventRouter();
+}
+
+bool ExtensionWebUI::OnMessageReceived(const IPC::Message& message) {
+ if (extension_function_dispatcher_.get())
+ return extension_function_dispatcher_->OnMessageReceived(message);
+
+ return false;
+}
+
+Browser* ExtensionWebUI::GetBrowser() {
+ TabContents* contents = tab_contents();
+ TabContentsIterator tab_iterator;
+ for (; !tab_iterator.done(); ++tab_iterator) {
+ if (contents == (*tab_iterator)->tab_contents())
+ return tab_iterator.browser();
+ }
+
+ return NULL;
+}
+
+TabContents* ExtensionWebUI::associated_tab_contents() const {
+ return tab_contents();
+}
ExtensionBookmarkManagerEventRouter*
ExtensionWebUI::extension_bookmark_manager_event_router() {
return extension_bookmark_manager_event_router_.get();
}
+gfx::NativeWindow ExtensionWebUI::GetCustomFrameNativeWindow() {
+ if (GetBrowser())
+ return NULL;
+
+ // If there was no browser associated with the function dispatcher delegate,
+ // then this WebUI may be hosted in an ExternalTabContainer, and a framing
+ // window will be accessible through the tab_contents.
+ TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
+ if (tab_contents_delegate)
+ return tab_contents_delegate->GetFrameNativeWindow();
+ else
+ return NULL;
+}
+
+gfx::NativeView ExtensionWebUI::GetNativeViewOfHost() {
+ RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
+ return rwhv ? rwhv->GetNativeView() : NULL;
+}
+
////////////////////////////////////////////////////////////////////////////////
// chrome:// URL overrides
diff --git a/chrome/browser/extensions/extension_web_ui.h b/chrome/browser/extensions/extension_web_ui.h
index 4aad170..3a3a80b 100644
--- a/chrome/browser/extensions/extension_web_ui.h
+++ b/chrome/browser/extensions/extension_web_ui.h
@@ -10,9 +10,11 @@
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/favicon/favicon_service.h"
#include "chrome/common/extensions/extension.h"
#include "content/browser/webui/web_ui.h"
+#include "ipc/ipc_channel.h"
class GURL;
class ListValue;
@@ -20,12 +22,15 @@ class PrefService;
class Profile;
class RenderViewHost;
class TabContents;
+struct ExtensionHostMsg_Request_Params;
// This class implements WebUI for extensions and allows extensions to put UI in
// the main tab contents area. For example, each extension can specify an
// "options_page", and that page is displayed in the tab contents area and is
// hosted by this class.
-class ExtensionWebUI : public WebUI {
+class ExtensionWebUI
+ : public WebUI,
+ public ExtensionFunctionDispatcher::Delegate {
public:
static const char kExtensionURLOverrides[];
@@ -33,6 +38,21 @@ class ExtensionWebUI : public WebUI {
virtual ~ExtensionWebUI();
+ ExtensionFunctionDispatcher* extension_function_dispatcher() const {
+ return extension_function_dispatcher_.get();
+ }
+
+ // WebUI
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void RenderViewCreated(RenderViewHost* render_view_host);
+ virtual void RenderViewReused(RenderViewHost* render_view_host);
+
+ // ExtensionFunctionDispatcher::Delegate
+ virtual Browser* GetBrowser();
+ virtual gfx::NativeView GetNativeViewOfHost();
+ virtual gfx::NativeWindow GetCustomFrameNativeWindow();
+ virtual TabContents* associated_tab_contents() const;
+
virtual ExtensionBookmarkManagerEventRouter*
extension_bookmark_manager_event_router();
@@ -67,6 +87,15 @@ class ExtensionWebUI : public WebUI {
ListValue* list,
Value* override);
+ // When the RenderViewHost changes (RenderViewCreated and RenderViewReused),
+ // we need to reset the ExtensionFunctionDispatcher so it's talking to the
+ // right one, as well as being linked to the correct URL.
+ void ResetExtensionFunctionDispatcher(RenderViewHost* render_view_host);
+
+ void ResetExtensionBookmarkManagerEventRouter();
+
+ scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
+
// TODO(aa): This seems out of place. Why is it not with the event routers for
// the other extension APIs?
scoped_ptr<ExtensionBookmarkManagerEventRouter>
diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc
index 7c46cff..8dbf650 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.cc
+++ b/chrome/browser/extensions/extension_webstore_private_api.cc
@@ -461,7 +461,7 @@ bool CompleteInstallFunction::RunImpl() {
// install flow. The above call to SetWhitelistedInstallId will bypass the
// normal permissions install dialog.
NavigationController& controller =
- dispatcher()->delegate()->GetAssociatedTabContents()->controller();
+ dispatcher()->delegate()->associated_tab_contents()->controller();
controller.LoadURL(url, source_url(), PageTransition::LINK);
return true;
@@ -519,7 +519,7 @@ bool PromptBrowserLoginFunction::RunImpl() {
// Login can currently only be invoked tab-modal. Since this is
// coming from the webstore, we should always have a tab, but check
// just in case.
- TabContents* tab = dispatcher()->delegate()->GetAssociatedTabContents();
+ TabContents* tab = dispatcher()->delegate()->associated_tab_contents();
if (!tab)
return false;
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index 37e4fd9..8022dc4 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -299,11 +300,13 @@ void ExtensionsDOMHandler::RegisterForNotifications() {
NotificationService::AllSources());
registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED,
+ NotificationService::AllSources());
registrar_.Add(this,
- NotificationType::NAV_ENTRY_COMMITTED,
+ NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
NotificationService::AllSources());
registrar_.Add(this,
- NotificationType::RENDER_VIEW_HOST_CREATED,
+ NotificationType::NAV_ENTRY_COMMITTED,
NotificationService::AllSources());
registrar_.Add(this,
NotificationType::RENDER_VIEW_HOST_DELETED,
@@ -628,11 +631,9 @@ void ExtensionsDOMHandler::Observe(NotificationType type,
// we don't know about the views for an extension at EXTENSION_LOADED, but
// if we only listen to EXTENSION_PROCESS_CREATED, we'll miss extensions
// that don't have a process at startup. Similarly, NAV_ENTRY_COMMITTED &
- // RENDER_VIEW_HOST_CREATED because we want to handle both
- // the case of navigating from a non-extension page to an extension page in
- // a TabContents (which will generate NAV_ENTRY_COMMITTED) as well as
- // extension content being shown in popups and balloons (which will generate
- // RENDER_VIEW_HOST_CREATED but no NAV_ENTRY_COMMITTED).
+ // EXTENSION_FUNCTION_DISPATCHER_CREATED because we want to handle both
+ // the case of live app pages (which don't have an EFD) and
+ // chrome-extension:// urls which are served in a TabContents.
//
// Doing it this way gets everything but causes the page to be rendered
// more than we need. It doesn't seem to result in any noticeable flicker.
@@ -648,7 +649,8 @@ void ExtensionsDOMHandler::Observe(NotificationType type,
case NotificationType::EXTENSION_PROCESS_CREATED:
case NotificationType::EXTENSION_UNLOADED:
case NotificationType::EXTENSION_UPDATE_DISABLED:
- case NotificationType::RENDER_VIEW_HOST_CREATED:
+ case NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED:
+ case NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED:
case NotificationType::NAV_ENTRY_COMMITTED:
case NotificationType::BACKGROUND_CONTENTS_NAVIGATED:
case NotificationType::EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED:
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index 074e42d..ea1c834 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -171,7 +171,7 @@ void MemoryDetails::CollectChildInfoOnUIThread() {
}
TabContents* contents = host_delegate->GetAsTabContents();
if (!contents) {
- if (host->process()->is_extension_process()) {
+ if (host->is_extension_process()) {
const Extension* extension =
extension_service->GetExtensionByURL(url);
if (extension) {
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 7219be0..3d600a0 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -3,13 +3,14 @@
// found in the LICENSE file.
#include "chrome/browser/notifications/balloon_host.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_preferences_util.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
-#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/browser_render_process_host.h"
@@ -29,12 +30,20 @@ BalloonHost::BalloonHost(Balloon* balloon)
balloon_(balloon),
initialized_(false),
should_notify_on_disconnect_(false),
- enable_web_ui_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- extension_function_dispatcher_(GetProfile(), this)) {
- CHECK(balloon_);
- site_instance_ = SiteInstance::CreateSiteInstanceForURL(balloon_->profile(),
- GetURL());
+ enable_web_ui_(false) {
+ DCHECK(balloon_);
+
+ // If the notification is for an extension URL, make sure to use the extension
+ // process to render it, so that it can communicate with other views in the
+ // extension.
+ const GURL& balloon_url = balloon_->notification().content_url();
+ if (balloon_url.SchemeIs(chrome::kExtensionScheme)) {
+ site_instance_ =
+ balloon_->profile()->GetExtensionProcessManager()->GetSiteInstanceForURL(
+ balloon_url);
+ } else {
+ site_instance_ = SiteInstance::CreateSiteInstance(balloon_->profile());
+ }
}
void BalloonHost::Shutdown() {
@@ -55,9 +64,7 @@ gfx::NativeView BalloonHost::GetNativeViewOfHost() {
return NULL;
}
-TabContents* BalloonHost::GetAssociatedTabContents() const {
- return NULL;
-}
+TabContents* BalloonHost::associated_tab_contents() const { return NULL; }
const string16& BalloonHost::GetSource() const {
return balloon_->notification().display_source();
@@ -126,16 +133,10 @@ RenderViewHostDelegate::View* BalloonHost::GetViewDelegate() {
}
bool BalloonHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BalloonHost, message)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
+ if (extension_function_dispatcher_.get())
+ return extension_function_dispatcher_->OnMessageReceived(message);
-void BalloonHost::OnRequest(const ExtensionHostMsg_Request_Params& params) {
- extension_function_dispatcher_.Dispatch(params, render_view_host_);
+ return false;
}
// RenderViewHostDelegate::View methods implemented to allow links to
@@ -195,8 +196,24 @@ void BalloonHost::Init() {
DCHECK(!render_view_host_) << "BalloonViewHost already initialized.";
RenderViewHost* rvh = new RenderViewHost(
site_instance_.get(), this, MSG_ROUTING_NONE, NULL);
- if (enable_web_ui_)
+ if (GetProfile()->GetExtensionService()) {
+ extension_function_dispatcher_.reset(
+ ExtensionFunctionDispatcher::Create(
+ rvh, this, balloon_->notification().content_url()));
+ }
+ if (extension_function_dispatcher_.get()) {
+ rvh->AllowBindings(BindingsPolicy::EXTENSION);
+ rvh->set_is_extension_process(true);
+ const Extension* installed_app =
+ GetProfile()->GetExtensionService()->GetInstalledApp(
+ balloon_->notification().content_url());
+ if (installed_app) {
+ GetProfile()->GetExtensionService()->SetInstalledAppForRenderer(
+ rvh->process()->id(), installed_app);
+ }
+ } else if (enable_web_ui_) {
rvh->AllowBindings(BindingsPolicy::WEB_UI);
+ }
// Do platform-specific initialization.
render_view_host_ = rvh;
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index 2a03506..9a70e61 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -44,7 +44,7 @@ class BalloonHost : public RenderViewHostDelegate,
// ExtensionFunctionDispatcher::Delegate overrides.
virtual Browser* GetBrowser();
virtual gfx::NativeView GetNativeViewOfHost();
- virtual TabContents* GetAssociatedTabContents() const;
+ virtual TabContents* associated_tab_contents() const;
RenderViewHost* render_view_host() const { return render_view_host_; }
@@ -137,9 +137,6 @@ class BalloonHost : public RenderViewHostDelegate,
// RenderViewHostDelegate
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // Message handlers
- void OnRequest(const ExtensionHostMsg_Request_Params& params);
-
// Called to send an event that the balloon has been disconnected from
// a renderer (if should_notify_on_disconnect_ is true).
void NotifyDisconnect();
@@ -161,12 +158,14 @@ class BalloonHost : public RenderViewHostDelegate,
// Common implementations of some RenderViewHostDelegate::View methods.
RenderViewHostDelegateViewHelper delegate_view_helper_;
+ // Handles requests to extension APIs. Will only be non-NULL if we are
+ // rendering a page from an extension.
+ scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
+
// A flag to enable Web UI.
bool enable_web_ui_;
NotificationRegistrar registrar_;
-
- ExtensionFunctionDispatcher extension_function_dispatcher_;
};
#endif // CHROME_BROWSER_NOTIFICATIONS_BALLOON_HOST_H_
diff --git a/chrome/browser/sidebar/sidebar_container.cc b/chrome/browser/sidebar/sidebar_container.cc
index d1e4a33..99c69a5 100644
--- a/chrome/browser/sidebar/sidebar_container.cc
+++ b/chrome/browser/sidebar/sidebar_container.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -16,6 +16,7 @@
#include "content/browser/tab_contents/navigation_entry.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/common/bindings_policy.h"
#include "googleurl/src/gurl.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -31,6 +32,17 @@ SidebarContainer::SidebarContainer(TabContents* tab,
// Create TabContents for sidebar.
sidebar_contents_.reset(
new TabContents(tab->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL));
+ sidebar_contents_->render_view_host()->set_is_extension_process(true);
+ const Extension* extension = GetExtension();
+ if (extension && extension->is_app()) {
+ ExtensionService* service = tab->profile()->GetExtensionService();
+ if (service) {
+ service->SetInstalledAppForRenderer(
+ sidebar_contents_->render_view_host()->process()->id(), extension);
+ }
+ }
+ sidebar_contents_->render_view_host()->AllowBindings(
+ BindingsPolicy::EXTENSION);
sidebar_contents_->set_delegate(this);
}
diff --git a/chrome/browser/ui/webui/options/extension_settings_handler.cc b/chrome/browser/ui/webui/options/extension_settings_handler.cc
index c1760b7..0aa8434 100644
--- a/chrome/browser/ui/webui/options/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/extension_settings_handler.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -406,11 +407,13 @@ void ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) {
NotificationService::AllSources());
registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED,
+ NotificationService::AllSources());
registrar_.Add(this,
- NotificationType::NAV_ENTRY_COMMITTED,
+ NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
NotificationService::AllSources());
registrar_.Add(this,
- NotificationType::RENDER_VIEW_HOST_CREATED,
+ NotificationType::NAV_ENTRY_COMMITTED,
NotificationService::AllSources());
registrar_.Add(this,
NotificationType::RENDER_VIEW_HOST_DELETED,
@@ -721,11 +724,9 @@ void ExtensionsDOMHandler::Observe(NotificationType type,
// we don't know about the views for an extension at EXTENSION_LOADED, but
// if we only listen to EXTENSION_PROCESS_CREATED, we'll miss extensions
// that don't have a process at startup. Similarly, NAV_ENTRY_COMMITTED &
- // RENDER_VIEW_HOST_CREATED because we want to handle both
- // the case of navigating from a non-extension page to an extension page in
- // a TabContents (which will generate NAV_ENTRY_COMMITTED) as well as
- // extension content being shown in popups and balloons (which will generate
- // RENDER_VIEW_CREATED but no NAV_ENTRY_COMMITTED).
+ // EXTENSION_FUNCTION_DISPATCHER_CREATED because we want to handle both
+ // the case of live app pages (which don't have an EFD) and
+ // chrome-extension:// urls which are served in a TabContents.
//
// Doing it this way gets everything but causes the page to be rendered
// more than we need. It doesn't seem to result in any noticeable flicker.
@@ -741,7 +742,8 @@ void ExtensionsDOMHandler::Observe(NotificationType type,
case NotificationType::EXTENSION_PROCESS_CREATED:
case NotificationType::EXTENSION_UNLOADED:
case NotificationType::EXTENSION_UPDATE_DISABLED:
- case NotificationType::RENDER_VIEW_HOST_CREATED:
+ case NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED:
+ case NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED:
case NotificationType::NAV_ENTRY_COMMITTED:
case NotificationType::BACKGROUND_CONTENTS_NAVIGATED:
case NotificationType::EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED:
diff --git a/chrome/browser/visitedlink/visitedlink_unittest.cc b/chrome/browser/visitedlink/visitedlink_unittest.cc
index 96bcd31..6f58ad7 100644
--- a/chrome/browser/visitedlink/visitedlink_unittest.cc
+++ b/chrome/browser/visitedlink/visitedlink_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -505,7 +505,7 @@ class VisitRelayingRenderProcessHost : public BrowserRenderProcessHost {
Source<RenderProcessHost>(this), NotificationService::NoDetails());
}
- virtual bool Init(bool is_accessibility_enabled) {
+ virtual bool Init(bool is_accessibility_enabled, bool is_extension_process) {
return true;
}
diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc
index 13339c3..a2bb8c0 100644
--- a/chrome/renderer/extensions/extension_dispatcher.cc
+++ b/chrome/renderer/extensions/extension_dispatcher.cc
@@ -35,8 +35,7 @@ using WebKit::WebFrame;
using WebKit::WebSecurityPolicy;
using WebKit::WebString;
-ExtensionDispatcher::ExtensionDispatcher()
- : is_webkit_initialized_(false) {
+ExtensionDispatcher::ExtensionDispatcher() {
std::string type_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
is_extension_process_ = type_str == switches::kExtensionProcess ||
@@ -89,17 +88,6 @@ void ExtensionDispatcher::WebKitInitialized() {
RegisterExtension(EventBindings::Get(this), true);
RegisterExtension(RendererExtensionBindings::Get(this), true);
RegisterExtension(ExtensionApiTestV8Extension::Get(), true);
-
- // Initialize host permissions for any extensions that were activated before
- // WebKit was initialized.
- for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
- iter != active_extension_ids_.end(); ++iter) {
- const Extension* extension = extensions_.GetByID(*iter);
- if (extension)
- InitHostPermissions(extension);
- }
-
- is_webkit_initialized_ = true;
}
void ExtensionDispatcher::IdleNotification() {
@@ -214,11 +202,6 @@ void ExtensionDispatcher::OnActivateExtension(
if (!extension)
return;
- if (is_webkit_initialized_)
- InitHostPermissions(extension);
-}
-
-void ExtensionDispatcher::InitHostPermissions(const Extension* extension) {
if (extension->HasApiPermission(Extension::kManagementPermission)) {
WebSecurityPolicy::addOriginAccessWhitelistEntry(
extension->url(),
@@ -227,7 +210,13 @@ void ExtensionDispatcher::InitHostPermissions(const Extension* extension) {
false);
}
- const URLPatternList& permissions = extension->host_permissions();
+ SetHostPermissions(extension->url(),
+ extension->host_permissions());
+}
+
+void ExtensionDispatcher::SetHostPermissions(
+ const GURL& extension_url,
+ const std::vector<URLPattern>& permissions) {
for (size_t i = 0; i < permissions.size(); ++i) {
const char* schemes[] = {
chrome::kHttpScheme,
@@ -238,7 +227,7 @@ void ExtensionDispatcher::InitHostPermissions(const Extension* extension) {
for (size_t j = 0; j < arraysize(schemes); ++j) {
if (permissions[i].MatchesScheme(schemes[j])) {
WebSecurityPolicy::addOriginAccessWhitelistEntry(
- extension->url(),
+ extension_url,
WebString::fromUTF8(schemes[j]),
WebString::fromUTF8(permissions[i].host()),
permissions[i].match_subdomains());
diff --git a/chrome/renderer/extensions/extension_dispatcher.h b/chrome/renderer/extensions/extension_dispatcher.h
index bce3c0f..c966d37 100644
--- a/chrome/renderer/extensions/extension_dispatcher.h
+++ b/chrome/renderer/extensions/extension_dispatcher.h
@@ -81,8 +81,9 @@ class ExtensionDispatcher : public RenderProcessObserver {
// extension is for Chrome Extensions only.
void RegisterExtension(v8::Extension* extension, bool restrict_to_extensions);
- // Sets up the host permissions for |extension|.
- void InitHostPermissions(const Extension* extension);
+ // Sets the host permissions for a particular extension.
+ void SetHostPermissions(const GURL& extension_url,
+ const std::vector<URLPattern>& permissions);
// True if this renderer is running extensions.
bool is_extension_process_;
@@ -107,9 +108,6 @@ class ExtensionDispatcher : public RenderProcessObserver {
// The extensions that are active in this process.
std::set<std::string> active_extension_ids_;
- // True once WebKit has been initialized (and it is therefore safe to poke).
- bool is_webkit_initialized_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionDispatcher);
};