diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-29 17:32:24 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-29 17:32:24 +0000 |
commit | 6779aa1d281cce1b77c96d5fb77535c9838b0949 (patch) | |
tree | 2eef595d07ab6d858dfffc27202d5e00a80f6934 | |
parent | ba0483f513f5f28a7eeff34dafa4e89d2c232c61 (diff) | |
download | chromium_src-6779aa1d281cce1b77c96d5fb77535c9838b0949.zip chromium_src-6779aa1d281cce1b77c96d5fb77535c9838b0949.tar.gz chromium_src-6779aa1d281cce1b77c96d5fb77535c9838b0949.tar.bz2 |
Move the dispatching of extension messages out of RenderThread. This also moves a bunch of extension related state out of RenderThread.
Review URL: http://codereview.chromium.org/6765011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79699 0039d316-1c4b-4281-b951-d872f2087c98
22 files changed, 476 insertions, 290 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 14fedea..864f8b3 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -862,7 +862,7 @@ void BrowserRenderProcessHost::SendUserScriptsUpdate( } if (base::SharedMemory::IsHandleValid(handle_for_process)) { - Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process)); + Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); } } diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index ac81281..2ad02ff 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -59,6 +59,8 @@ 'renderer/extensions/chrome_app_bindings.h', 'renderer/extensions/event_bindings.cc', 'renderer/extensions/event_bindings.h', + 'renderer/extensions/extension_dispatcher.cc', + 'renderer/extensions/extension_dispatcher.h', 'renderer/extensions/extension_helper.cc', 'renderer/extensions/extension_helper.h', 'renderer/extensions/extension_process_bindings.cc', diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h index 2a6bcdb..f3091ba 100644 --- a/chrome/common/extensions/extension_messages.h +++ b/chrome/common/extensions/extension_messages.h @@ -5,6 +5,7 @@ // IPC messages for extensions. // Multiply-included message file, hence no include guard. +#include "base/shared_memory.h" #include "base/values.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_extent.h" @@ -200,6 +201,12 @@ IPC_MESSAGE_CONTROL1(ExtensionMsg_SetScriptingWhitelist, IPC_MESSAGE_ROUTED1(ExtensionMsg_ExecuteCode, ExtensionMsg_ExecuteCode_Params) +// Notification that the user scripts have been updated. It has one +// SharedMemoryHandle argument consisting of the pickled script data. This +// handle is valid in the context of the renderer. +IPC_MESSAGE_CONTROL1(ExtensionMsg_UpdateUserScripts, + base::SharedMemoryHandle) + // Requests application info for the page. The renderer responds back with // ExtensionHostMsg_DidGetApplicationInfo. IPC_MESSAGE_ROUTED1(ExtensionMsg_GetApplicationInfo, diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 61272d4..5212785 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -173,12 +173,6 @@ IPC_MESSAGE_CONTROL1(ViewMsg_VisitedLink_Add, std::vector<uint64>) // re-calculated. IPC_MESSAGE_CONTROL0(ViewMsg_VisitedLink_Reset) -// Notification that the user scripts have been updated. It has one -// SharedMemoryHandle argument consisting of the pickled script data. This -// handle is valid in the context of the renderer. -IPC_MESSAGE_CONTROL1(ViewMsg_UserScripts_UpdatedScripts, - base::SharedMemoryHandle) - // Sent when user prompting is required before a ViewHostMsg_GetCookies // message can complete. This message indicates that the renderer should // pump messages while waiting for cookies. diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 3ecc9ee..c2327602 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -12,8 +12,9 @@ #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/blocked_plugin.h" +#include "chrome/renderer/extensions/bindings_utils.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/localized_error.h" -#include "chrome/renderer/render_thread.h" #include "content/common/view_messages.h" #include "content/renderer/render_view.h" #include "grit/generated_resources.h" @@ -169,7 +170,7 @@ std::string ChromeContentRendererClient::GetNavigationErrorHtml( int resource_id; DictionaryValue error_strings; if (failed_url.is_valid() && !failed_url.SchemeIs(chrome::kExtensionScheme)) - extension = RenderThread::current()->GetExtensions()->GetByURL(failed_url); + extension = ExtensionDispatcher::Get()->extensions()->GetByURL(failed_url); if (extension) { LocalizedError::GetAppErrorStrings(error, failed_url, extension, &error_strings); @@ -228,4 +229,15 @@ std::string ChromeContentRendererClient::DetermineTextLanguage( return language; } +bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { + return !ExtensionDispatcher::Get()->is_extension_process(); +} + +bool ChromeContentRendererClient::AllowPopup(const GURL& creator) { + // Extensions and apps always allowed to create unrequested popups. The second + // check is necessary to include content scripts. + return ExtensionDispatcher::Get()->extensions()->GetByURL(creator) || + bindings_utils::GetInfoForCurrentContext(); +} + } // namespace chrome diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 4b39092..3489181 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -28,6 +28,8 @@ class ChromeContentRendererClient : public content::ContentRendererClient { const WebKit::WebURLRequest& failed_request, const WebKit::WebURLError& error); virtual std::string DetermineTextLanguage(const string16& text); + virtual bool RunIdleHandlerWhenWidgetsHidden(); + virtual bool AllowPopup(const GURL& creator); private: WebKit::WebPlugin* CreatePluginPlaceholder( diff --git a/chrome/renderer/extensions/chrome_app_bindings.cc b/chrome/renderer/extensions/chrome_app_bindings.cc index f6a169b..f5cdd38 100644 --- a/chrome/renderer/extensions/chrome_app_bindings.cc +++ b/chrome/renderer/extensions/chrome_app_bindings.cc @@ -8,7 +8,7 @@ #include "base/utf_string_conversions.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/renderer/extensions/bindings_utils.h" -#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "content/renderer/render_view.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "v8/include/v8.h" @@ -58,7 +58,7 @@ class ChromeAppExtensionWrapper : public v8::Extension { return v8::Boolean::New(false); bool has_web_extent = - RenderThread::current()->GetExtensions()->GetByURL(url) != NULL; + ExtensionDispatcher::Get()->extensions()->GetByURL(url) != NULL; return v8::Boolean::New(has_web_extent); } diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index 7dd83ca..0e41f64 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -11,6 +11,7 @@ #include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/js_only_v8_extensions.h" #include "chrome/renderer/render_thread.h" @@ -265,7 +266,7 @@ void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) { if (!ds) ds = frame->dataSource(); GURL url = ds->request().url(); - const ExtensionSet* extensions = GetRenderThread()->GetExtensions(); + const ExtensionSet* extensions = ExtensionDispatcher::Get()->extensions(); std::string extension_id = extensions->GetIdByURL(url); if (!extensions->ExtensionBindingsAllowed(url) && diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc new file mode 100644 index 0000000..cfaad3d --- /dev/null +++ b/chrome/renderer/extensions/extension_dispatcher.cc @@ -0,0 +1,219 @@ +// Copyright (c) 2011 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. + +#include "chrome/renderer/extensions/extension_dispatcher.h" + +#include "base/command_line.h" +#include "chrome/common/child_process_logging.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_messages.h" +#include "chrome/renderer/extension_groups.h" +#include "chrome/renderer/extensions/chrome_app_bindings.h" +#include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/extensions/extension_process_bindings.h" +#include "chrome/renderer/extensions/js_only_v8_extensions.h" +#include "chrome/renderer/extensions/renderer_extension_bindings.h" +#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/user_script_slave.h" +#include "v8/include/v8.h" + +namespace { +static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; +static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; +static ExtensionDispatcher* g_extension_dispatcher; +} + +ExtensionDispatcher* ExtensionDispatcher::Get() { + return g_extension_dispatcher; +} + +ExtensionDispatcher::ExtensionDispatcher() { + DCHECK(!g_extension_dispatcher); + g_extension_dispatcher = this; + + std::string type_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessType); + is_extension_process_ = type_str == switches::kExtensionProcess || + CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); + + if (is_extension_process_) { + RenderThread::current()->set_idle_notification_delay_in_s( + kInitialExtensionIdleHandlerDelayS); + } + + user_script_slave_.reset(new UserScriptSlave(&extensions_)); +} + +ExtensionDispatcher::~ExtensionDispatcher() { + g_extension_dispatcher = NULL; +} + +bool ExtensionDispatcher::OnControlMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ExtensionDispatcher, message) + IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnMessageInvoke) + IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames, OnSetFunctionNames) + IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnLoaded) + IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnUnloaded) + IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist, + OnSetScriptingWhitelist) + IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePageActions, OnPageActionsUpdated) + IPC_MESSAGE_HANDLER(ExtensionMsg_SetAPIPermissions, OnSetAPIPermissions) + IPC_MESSAGE_HANDLER(ExtensionMsg_SetHostPermissions, OnSetHostPermissions) + IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + +void ExtensionDispatcher::OnRenderProcessShutdown() { + delete this; +} + +void ExtensionDispatcher::WebKitInitialized() { + // For extensions, we want to ensure we call the IdleHandler every so often, + // even if the extension keeps up activity. + if (is_extension_process_) { + forced_idle_timer_.Start( + base::TimeDelta::FromSeconds(kMaxExtensionIdleHandlerDelayS), + RenderThread::current(), &RenderThread::IdleHandler); + } + + RegisterExtension(extensions_v8::ChromeAppExtension::Get(), false); + + // Add v8 extensions related to chrome extensions. + RegisterExtension(ExtensionProcessBindings::Get(), true); + RegisterExtension(BaseJsV8Extension::Get(), true); + RegisterExtension(JsonSchemaJsV8Extension::Get(), true); + RegisterExtension(EventBindings::Get(), true); + RegisterExtension(RendererExtensionBindings::Get(), true); + RegisterExtension(ExtensionApiTestV8Extension::Get(), true); +} + +bool ExtensionDispatcher::AllowScriptExtension( + const std::string& v8_extension_name, + const GURL& url, + int extension_group) { + // If the V8 extension is not restricted, allow it to run anywhere. + if (!restricted_v8_extensions_.count(v8_extension_name)) + return true; + + // Extension-only bindings should be restricted to content scripts and + // extension-blessed URLs. + if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS || + extensions_.ExtensionBindingsAllowed(url)) { + return true; + } + + return false; +} + +void ExtensionDispatcher::IdleNotification() { + if (is_extension_process_) { + // Dampen the forced delay as well if the extension stays idle for long + // periods of time. + int64 forced_delay_s = std::max(static_cast<int64>( + RenderThread::current()->idle_notification_delay_in_s()), + kMaxExtensionIdleHandlerDelayS); + forced_idle_timer_.Stop(); + forced_idle_timer_.Start( + base::TimeDelta::FromSeconds(forced_delay_s), + RenderThread::current(), &RenderThread::IdleHandler); + } +} + +void ExtensionDispatcher::OnSetFunctionNames( + const std::vector<std::string>& names) { + ExtensionProcessBindings::SetFunctionNames(names); +} + +void ExtensionDispatcher::OnMessageInvoke(const std::string& extension_id, + const std::string& function_name, + const ListValue& args, + const GURL& event_url) { + RendererExtensionBindings::Invoke( + extension_id, function_name, args, NULL, event_url); + + // Reset the idle handler each time there's any activity like event or message + // dispatch, for which Invoke is the chokepoint. + if (is_extension_process_) { + RenderThread::current()->ScheduleIdleHandler( + kInitialExtensionIdleHandlerDelayS); + } +} + +void ExtensionDispatcher::OnLoaded(const ExtensionMsg_Loaded_Params& params) { + scoped_refptr<const Extension> extension(params.ConvertToExtension()); + if (!extension) { + // This can happen if extension parsing fails for any reason. One reason + // this can legitimately happen is if the + // --enable-experimental-extension-apis changes at runtime, which happens + // during browser tests. Existing renderers won't know about the change. + return; + } + + extensions_.Insert(extension); +} + +void ExtensionDispatcher::OnUnloaded(const std::string& id) { + extensions_.Remove(id); +} + +void ExtensionDispatcher::OnSetScriptingWhitelist( + const Extension::ScriptingWhitelist& extension_ids) { + Extension::SetScriptingWhitelist(extension_ids); +} + +void ExtensionDispatcher::OnPageActionsUpdated( + const std::string& extension_id, + const std::vector<std::string>& page_actions) { + ExtensionProcessBindings::SetPageActions(extension_id, page_actions); +} + +void ExtensionDispatcher::OnSetAPIPermissions( + const std::string& extension_id, + const std::set<std::string>& permissions) { + ExtensionProcessBindings::SetAPIPermissions(extension_id, permissions); + + // This is called when starting a new extension page, so start the idle + // handler ticking. + RenderThread::current()->ScheduleIdleHandler( + kInitialExtensionIdleHandlerDelayS); + + UpdateActiveExtensions(); +} + +void ExtensionDispatcher::OnSetHostPermissions( + const GURL& extension_url, const std::vector<URLPattern>& permissions) { + ExtensionProcessBindings::SetHostPermissions(extension_url, permissions); +} + +void ExtensionDispatcher::OnUpdateUserScripts( + base::SharedMemoryHandle scripts) { + DCHECK(base::SharedMemory::IsHandleValid(scripts)) << "Bad scripts handle"; + user_script_slave_->UpdateScripts(scripts); + UpdateActiveExtensions(); +} + +void ExtensionDispatcher::UpdateActiveExtensions() { + // In single-process mode, the browser process reports the active extensions. + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) + return; + + std::set<std::string> active_extensions; + user_script_slave_->GetActiveExtensions(&active_extensions); + ExtensionProcessBindings::GetActiveExtensions(&active_extensions); + child_process_logging::SetActiveExtensions(active_extensions); +} + +void ExtensionDispatcher::RegisterExtension(v8::Extension* extension, + bool restrict_to_extensions) { + if (restrict_to_extensions) + restricted_v8_extensions_.insert(extension->name()); + + RenderThread::current()->RegisterExtension(extension); +} diff --git a/chrome/renderer/extensions/extension_dispatcher.h b/chrome/renderer/extensions/extension_dispatcher.h new file mode 100644 index 0000000..8f9cd53 --- /dev/null +++ b/chrome/renderer/extensions/extension_dispatcher.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_RENDERER_EXTENSIONS_EXTENSION_DISPATCHER_H_ +#define CHROME_RENDERER_EXTENSIONS_EXTENSION_DISPATCHER_H_ +#pragma once + +#include <set> +#include <string> +#include <vector> + +#include "base/shared_memory.h" +#include "base/timer.h" +#include "content/renderer/render_process_observer.h" +#include "chrome/common/extensions/extension_set.h" + +class GURL; +class ListValue; +class RenderThread; +class URLPattern; +class UserScriptSlave; +struct ExtensionMsg_Loaded_Params; + +namespace v8 { +class Extension; +} + +// Dispatches extension control messages sent to the renderer and stores +// renderer extension related state. Object will delete itself when the +// renderer shuts down. +class ExtensionDispatcher : public RenderProcessObserver { + public: + // Returns the ExtensionDispatcher for this process. + static ExtensionDispatcher* Get(); + + ExtensionDispatcher(); + virtual ~ExtensionDispatcher(); + + bool is_extension_process() const { return is_extension_process_; } + const ExtensionSet* extensions() const { return &extensions_; } + UserScriptSlave* user_script_slave() { return user_script_slave_.get(); } + + private: + friend class RenderViewTest; + + // RenderProcessObserver implementation: + virtual bool OnControlMessageReceived(const IPC::Message& message); + virtual void OnRenderProcessShutdown(); + virtual void WebKitInitialized(); + virtual bool AllowScriptExtension(const std::string& v8_extension_name, + const GURL& url, + int extension_group); + virtual void IdleNotification(); + + void OnMessageInvoke(const std::string& extension_id, + const std::string& function_name, + const ListValue& args, + const GURL& event_url); + void OnSetFunctionNames(const std::vector<std::string>& names); + void OnLoaded(const ExtensionMsg_Loaded_Params& params); + void OnUnloaded(const std::string& id); + void OnSetScriptingWhitelist( + const Extension::ScriptingWhitelist& extension_ids); + void OnPageActionsUpdated(const std::string& extension_id, + const std::vector<std::string>& page_actions); + void OnSetAPIPermissions(const std::string& extension_id, + const std::set<std::string>& permissions); + void OnSetHostPermissions(const GURL& extension_url, + const std::vector<URLPattern>& permissions); + void OnUpdateUserScripts(base::SharedMemoryHandle table); + + // Update the list of active extensions that will be reported when we crash. + void UpdateActiveExtensions(); + + // Calls RenderThread's RegisterExtension and keeps tracks of which v8 + // extension is for Chrome Extensions only. + void RegisterExtension(v8::Extension* extension, bool restrict_to_extensions); + + // True if this renderer is running extensions. + bool is_extension_process_; + + // Contains all loaded extensions. This is essentially the renderer + // counterpart to ExtensionService in the browser. It contains information + // about all extensions currently loaded by the browser. + ExtensionSet extensions_; + + scoped_ptr<UserScriptSlave> user_script_slave_; + + // Same as above, but on a longer timer and will run even if the process is + // not idle, to ensure that IdleHandle gets called eventually. + base::RepeatingTimer<RenderThread> forced_idle_timer_; + + // The v8 extensions which are restricted to extension-related contexts. + std::set<std::string> restricted_v8_extensions_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionDispatcher); +}; + +#endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_DISPATCHER_H_ diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 2e4adea..bedc77d 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -24,6 +24,7 @@ #include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/js_only_v8_extensions.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/user_script_slave.h" @@ -202,8 +203,7 @@ class ExtensionImpl : public ExtensionBase { return std::string(); // this can happen as a tab is closing. GURL url = renderview->webview()->mainFrame()->url(); - const ExtensionSet* extensions = - EventBindings::GetRenderThread()->GetExtensions(); + const ExtensionSet* extensions = ExtensionDispatcher::Get()->extensions(); if (!extensions->ExtensionBindingsAllowed(url)) return std::string(); @@ -518,7 +518,7 @@ class ExtensionImpl : public ExtensionBase { static v8::Handle<v8::Value> IsExtensionProcess(const v8::Arguments& args) { bool retval = false; if (EventBindings::GetRenderThread()) - retval = EventBindings::GetRenderThread()->IsExtensionProcess(); + retval = ExtensionDispatcher::Get()->is_extension_process(); return v8::Boolean::New(retval); } diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc index 0ae683d..c832177 100644 --- a/chrome/renderer/mock_render_thread.cc +++ b/chrome/renderer/mock_render_thread.cc @@ -23,17 +23,12 @@ MockRenderThread::MockRenderThread() widget_(NULL), reply_deserializer_(NULL), printer_(new MockPrinter), - is_extension_process_(false), print_dialog_user_response_(true) { } MockRenderThread::~MockRenderThread() { } -const ExtensionSet* MockRenderThread::GetExtensions() const { - return &extensions_; -} - // Called by the Widget. The routing_id must match the routing id assigned // to the Widget in reply to ViewHostMsg_CreateWidget message. void MockRenderThread::AddRoute(int32 routing_id, @@ -58,9 +53,6 @@ void MockRenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { filter->OnFilterRemoved(); } -bool MockRenderThread::IsExtensionProcess() const { - return is_extension_process_; -} bool MockRenderThread::IsIncognitoProcess() const { return false; diff --git a/chrome/renderer/mock_render_thread.h b/chrome/renderer/mock_render_thread.h index b30d31e..1d04b97 100644 --- a/chrome/renderer/mock_render_thread.h +++ b/chrome/renderer/mock_render_thread.h @@ -31,8 +31,6 @@ class MockRenderThread : public RenderThreadBase { MockRenderThread(); virtual ~MockRenderThread(); - virtual const ExtensionSet* GetExtensions() const; - // Provides access to the messages that have been received by this thread. IPC::TestSink& sink() { return sink_; } @@ -56,9 +54,7 @@ class MockRenderThread : public RenderThreadBase { virtual void WidgetHidden() { } virtual void WidgetRestored() { } - virtual bool IsExtensionProcess() const; virtual bool IsIncognitoProcess() const; - void SetExtensionProcess(bool value) { is_extension_process_ = value; } ////////////////////////////////////////////////////////////////////////// // The following functions are called by the test itself. @@ -144,12 +140,6 @@ class MockRenderThread : public RenderThreadBase { // A mock printer device used for printing tests. scoped_ptr<MockPrinter> printer_; - // Contains extensions currently loaded by browser. This is usually empty - // for MockRenderThread. - ExtensionSet extensions_; - - bool is_extension_process_; - // True to simulate user clicking print. False to cancel. bool print_dialog_user_response_; }; diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 24e61ed..e2c18c5 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -24,22 +24,14 @@ #include "base/values.h" #include "chrome/common/child_process_logging.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_localization_peer.h" -#include "chrome/common/extensions/extension_messages.h" -#include "chrome/common/extensions/extension_set.h" #include "chrome/common/render_messages.h" #include "chrome/common/spellcheck_messages.h" #include "chrome/common/safebrowsing_messages.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/automation/dom_automation_v8_extension.h" #include "chrome/renderer/devtools_agent_filter.h" -#include "chrome/renderer/extension_groups.h" -#include "chrome/renderer/extensions/chrome_app_bindings.h" -#include "chrome/renderer/extensions/event_bindings.h" -#include "chrome/renderer/extensions/extension_process_bindings.h" -#include "chrome/renderer/extensions/js_only_v8_extensions.h" -#include "chrome/renderer/extensions/renderer_extension_bindings.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/external_extension.h" #include "chrome/renderer/loadtimes_extension_bindings.h" #include "chrome/renderer/net/renderer_net_predictor.h" @@ -50,7 +42,6 @@ #include "chrome/renderer/searchbox_extension.h" #include "chrome/renderer/security_filter_peer.h" #include "chrome/renderer/spellchecker/spellcheck.h" -#include "chrome/renderer/user_script_slave.h" #include "content/common/appcache/appcache_dispatcher.h" #include "content/common/database_messages.h" #include "content/common/db_message_filter.h" @@ -63,6 +54,7 @@ #include "content/common/view_messages.h" #include "content/common/web_database_observer_impl.h" #include "content/plugin/npobject_util.h" +#include "content/renderer/content_renderer_client.h" #include "content/renderer/cookie_message_filter.h" #include "content/renderer/gpu_channel_host.h" #include "content/renderer/gpu_video_service_host.h" @@ -133,8 +125,6 @@ using WebKit::WebView; namespace { static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; -static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; -static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; // Keep the global RenderThread in a TLS slot so it is impossible to access // incorrectly from the wrong thread. @@ -289,11 +279,7 @@ void RenderThread::Init() { CoInitialize(0); #endif - std::string type_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kProcessType); // In single process the single process is all there is. - is_extension_process_ = type_str == switches::kExtensionProcess || - CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); is_incognito_process_ = false; suspend_webkit_shared_timer_ = true; notify_webkit_of_modal_loop_ = true; @@ -301,14 +287,12 @@ void RenderThread::Init() { cache_stats_task_pending_ = false; widget_count_ = 0; hidden_widget_count_ = 0; - idle_notification_delay_in_s_ = is_extension_process_ ? - kInitialExtensionIdleHandlerDelayS : kInitialIdleHandlerDelayS; + idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); resource_dispatcher()->set_observer(new RenderResourceObserver()); visited_link_slave_.reset(new VisitedLinkSlave()); - user_script_slave_.reset(new UserScriptSlave(&extensions_)); renderer_net_predictor_.reset(new RendererNetPredictor()); histogram_snapshots_.reset(new RendererHistogramSnapshots()); appcache_dispatcher_.reset(new AppCacheDispatcher(this)); @@ -329,6 +313,8 @@ void RenderThread::Init() { AddFilter(suicide_on_channel_error_filter_.get()); #endif + AddObserver(new ExtensionDispatcher()); + TRACE_EVENT_END("RenderThread::Init", 0, ""); } @@ -383,10 +369,6 @@ int32 RenderThread::RoutingIDForCurrentContext() { return routing_id; } -const ExtensionSet* RenderThread::GetExtensions() const { - return &extensions_; -} - bool RenderThread::Send(IPC::Message* msg) { // Certain synchronous messages cannot always be processed synchronously by // the browser, e.g., Chrome frame communicating with the embedding browser. @@ -508,20 +490,25 @@ void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { void RenderThread::WidgetHidden() { DCHECK(hidden_widget_count_ < widget_count_); hidden_widget_count_++; - if (!is_extension_process_ && - widget_count_ && hidden_widget_count_ == widget_count_) + + if (!content::GetContentClient()->renderer()-> + RunIdleHandlerWhenWidgetsHidden()) { + return; + } + + if (widget_count_ && hidden_widget_count_ == widget_count_) ScheduleIdleHandler(kInitialIdleHandlerDelayS); } void RenderThread::WidgetRestored() { DCHECK_GT(hidden_widget_count_, 0); hidden_widget_count_--; - if (!is_extension_process_) - idle_timer_.Stop(); -} + if (!content::GetContentClient()->renderer()-> + RunIdleHandlerWhenWidgetsHidden()) { + return; + } -bool RenderThread::IsExtensionProcess() const { - return is_extension_process_; + idle_timer_.Stop(); } bool RenderThread::IsIncognitoProcess() const { @@ -580,62 +567,6 @@ void RenderThread::OnSetZoomLevelForCurrentURL(const GURL& url, RenderView::ForEach(&zoomer); } -void RenderThread::OnUpdateUserScripts(base::SharedMemoryHandle scripts) { - DCHECK(base::SharedMemory::IsHandleValid(scripts)) << "Bad scripts handle"; - user_script_slave_->UpdateScripts(scripts); - UpdateActiveExtensions(); -} - -void RenderThread::OnSetExtensionFunctionNames( - const std::vector<std::string>& names) { - ExtensionProcessBindings::SetFunctionNames(names); -} - -void RenderThread::OnExtensionLoaded(const ExtensionMsg_Loaded_Params& params) { - scoped_refptr<const Extension> extension(params.ConvertToExtension()); - if (!extension) { - // This can happen if extension parsing fails for any reason. One reason - // this can legitimately happen is if the - // --enable-experimental-extension-apis changes at runtime, which happens - // during browser tests. Existing renderers won't know about the change. - return; - } - - extensions_.Insert(extension); -} - -void RenderThread::OnSetExtensionScriptingWhitelist( - const Extension::ScriptingWhitelist& extension_ids) { - Extension::SetScriptingWhitelist(extension_ids); -} - -void RenderThread::OnExtensionUnloaded(const std::string& id) { - extensions_.Remove(id); -} - -void RenderThread::OnPageActionsUpdated( - const std::string& extension_id, - const std::vector<std::string>& page_actions) { - ExtensionProcessBindings::SetPageActions(extension_id, page_actions); -} - -void RenderThread::OnExtensionSetAPIPermissions( - const std::string& extension_id, - const std::set<std::string>& permissions) { - ExtensionProcessBindings::SetAPIPermissions(extension_id, permissions); - - // This is called when starting a new extension page, so start the idle - // handler ticking. - ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); - - UpdateActiveExtensions(); -} - -void RenderThread::OnExtensionSetHostPermissions( - const GURL& extension_url, const std::vector<URLPattern>& permissions) { - ExtensionProcessBindings::SetHostPermissions(extension_url, permissions); -} - void RenderThread::OnDOMStorageEvent( const DOMStorageMsg_Event_Params& params) { if (!dom_storage_event_dispatcher_.get()) @@ -682,23 +613,8 @@ bool RenderThread::OnControlMessageReceived(const IPC::Message& msg) { #endif IPC_MESSAGE_HANDLER(ViewMsg_GetV8HeapStats, OnGetV8HeapStats) IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats, OnGetCacheResourceStats) - IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_UpdatedScripts, OnUpdateUserScripts) - // TODO(rafaelw): create an ExtensionDispatcher that handles extension - // messages seperates their handling from the RenderThread. - IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke) - IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames, - OnSetExtensionFunctionNames) - IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnExtensionLoaded) - IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnExtensionUnloaded) - IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist, - OnSetExtensionScriptingWhitelist) IPC_MESSAGE_HANDLER(ViewMsg_PurgeMemory, OnPurgeMemory) IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache) - IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePageActions, OnPageActionsUpdated) - IPC_MESSAGE_HANDLER(ExtensionMsg_SetAPIPermissions, - OnExtensionSetAPIPermissions) - IPC_MESSAGE_HANDLER(ExtensionMsg_SetHostPermissions, - OnExtensionSetHostPermissions) IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnDOMStorageEvent) IPC_MESSAGE_HANDLER(SpellCheckMsg_Init, OnInitSpellChecker) IPC_MESSAGE_HANDLER(SpellCheckMsg_WordAdded, OnSpellCheckWordAdded) @@ -842,17 +758,6 @@ void RenderThread::EnableSpdy(bool enable) { Send(new ViewHostMsg_EnableSpdy(enable)); } -void RenderThread::UpdateActiveExtensions() { - // In single-process mode, the browser process reports the active extensions. - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) - return; - - std::set<std::string> active_extensions; - user_script_slave_->GetActiveExtensions(&active_extensions); - ExtensionProcessBindings::GetActiveExtensions(&active_extensions); - child_process_logging::SetActiveExtensions(active_extensions); -} - void RenderThread::EstablishGpuChannel() { if (gpu_channel_.get()) { // Do nothing if we already have a GPU channel or are already @@ -911,14 +816,6 @@ void RenderThread::EnsureWebKitInitialized() { if (webkit_client_.get()) return; - // For extensions, we want to ensure we call the IdleHandler every so often, - // even if the extension keeps up activity. - if (is_extension_process_) { - forced_idle_timer_.Start( - base::TimeDelta::FromSeconds(kMaxExtensionIdleHandlerDelayS), - this, &RenderThread::IdleHandler); - } - v8::V8::SetCounterFunction(base::StatsTable::FindLocation); v8::V8::SetCreateHistogramFunction(CreateHistogram); v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); @@ -943,34 +840,25 @@ void RenderThread::EnsureWebKitInitialized() { WebString extension_scheme(ASCIIToUTF16(chrome::kExtensionScheme)); WebSecurityPolicy::registerURLSchemeAsSecure(extension_scheme); - RegisterExtension(extensions_v8::LoadTimesExtension::Get(), false); - RegisterExtension(extensions_v8::ChromeAppExtension::Get(), false); - RegisterExtension(extensions_v8::ExternalExtension::Get(), false); - RegisterExtension(extensions_v8::SearchBoxExtension::Get(), false); + RegisterExtension(extensions_v8::LoadTimesExtension::Get()); + RegisterExtension(extensions_v8::ExternalExtension::Get()); + RegisterExtension(extensions_v8::SearchBoxExtension::Get()); v8::Extension* search_extension = extensions_v8::SearchExtension::Get(); // search_extension is null if not enabled. if (search_extension) - RegisterExtension(search_extension, false); + RegisterExtension(search_extension); if (command_line.HasSwitch(switches::kEnableBenchmarking)) - RegisterExtension(extensions_v8::BenchmarkingExtension::Get(), false); + RegisterExtension(extensions_v8::BenchmarkingExtension::Get()); if (command_line.HasSwitch(switches::kPlaybackMode) || command_line.HasSwitch(switches::kRecordMode) || command_line.HasSwitch(switches::kNoJsRandomness)) { - RegisterExtension(extensions_v8::PlaybackExtension::Get(), false); + RegisterExtension(extensions_v8::PlaybackExtension::Get()); } if (command_line.HasSwitch(switches::kDomAutomationController)) - RegisterExtension(DomAutomationV8Extension::Get(), false); - - // Add v8 extensions related to chrome extensions. - RegisterExtension(ExtensionProcessBindings::Get(), true); - RegisterExtension(BaseJsV8Extension::Get(), true); - RegisterExtension(JsonSchemaJsV8Extension::Get(), true); - RegisterExtension(EventBindings::Get(), true); - RegisterExtension(RendererExtensionBindings::Get(), true); - RegisterExtension(ExtensionApiTestV8Extension::Get(), true); + RegisterExtension(DomAutomationV8Extension::Get()); web_database_observer_impl_.reset(new WebDatabaseObserverImpl(this)); WebKit::WebDatabase::setObserver(web_database_observer_impl_.get()); @@ -1030,6 +918,8 @@ void RenderThread::EnsureWebKitInitialized() { WebRuntimeFeatures::enableJavaScriptI18NAPI( !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); + + FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); } void RenderThread::IdleHandler() { @@ -1048,17 +938,8 @@ void RenderThread::IdleHandler() { // kInitialIdleHandlerDelayS in RenderThread::WidgetHidden. ScheduleIdleHandler(idle_notification_delay_in_s_ + 1.0 / (idle_notification_delay_in_s_ + 2.0)); - if (is_extension_process_) { - // Dampen the forced delay as well if the extension stays idle for long - // periods of time. - int64 forced_delay_s = - std::max(static_cast<int64>(idle_notification_delay_in_s_), - kMaxExtensionIdleHandlerDelayS); - forced_idle_timer_.Stop(); - forced_idle_timer_.Start( - base::TimeDelta::FromSeconds(forced_delay_s), - this, &RenderThread::IdleHandler); - } + + FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); } void RenderThread::ScheduleIdleHandler(double initial_delay_s) { @@ -1069,19 +950,6 @@ void RenderThread::ScheduleIdleHandler(double initial_delay_s) { this, &RenderThread::IdleHandler); } -void RenderThread::OnExtensionMessageInvoke(const std::string& extension_id, - const std::string& function_name, - const ListValue& args, - const GURL& event_url) { - RendererExtensionBindings::Invoke( - extension_id, function_name, args, NULL, event_url); - - // Reset the idle handler each time there's any activity like event or message - // dispatch, for which Invoke is the chokepoint. - if (is_extension_process_) - ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); -} - void RenderThread::OnPurgeMemory() { spellchecker_.reset(new SpellCheck()); @@ -1185,23 +1053,17 @@ bool RenderThread::AllowScriptExtension(const std::string& v8_extension_name, if (v8_extensions_.find(v8_extension_name) == v8_extensions_.end()) return true; - // If the V8 extension is not restricted, allow it to run anywhere. - bool restrict_to_extensions = v8_extensions_[v8_extension_name]; - if (!restrict_to_extensions) - return true; - - // Extension-only bindings should be restricted to content scripts and - // extension-blessed URLs. - if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS || - extensions_.ExtensionBindingsAllowed(url)) { - return true; + ObserverListBase<RenderProcessObserver>::Iterator it(observers_); + RenderProcessObserver* observer; + while ((observer = it.GetNext()) != NULL) { + if (observer->AllowScriptExtension(v8_extension_name, url, extension_group)) + return true; } return false; } -void RenderThread::RegisterExtension(v8::Extension* extension, - bool restrict_to_extensions) { +void RenderThread::RegisterExtension(v8::Extension* extension) { WebScriptController::registerExtension(extension); - v8_extensions_[extension->name()] = restrict_to_extensions; + v8_extensions_.insert(extension->name()); } diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 4b0ae29..670115f 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -6,7 +6,7 @@ #define CHROME_RENDERER_RENDER_THREAD_H_ #pragma once -#include <map> +#include <set> #include <string> #include <vector> @@ -15,7 +15,6 @@ #include "base/time.h" #include "base/timer.h" #include "build/build_config.h" -#include "chrome/common/extensions/extension_set.h" #include "chrome/renderer/chrome_content_renderer_client.h" #include "chrome/renderer/visitedlink_slave.h" #include "content/common/child_thread.h" @@ -28,11 +27,9 @@ class AppCacheDispatcher; class CookieMessageFilter; class DBMessageFilter; class DevToolsAgentFilter; -class ExtensionSet; class FilePath; class GpuChannelHost; class IndexedDBDispatcher; -class ListValue; class RendererHistogram; class RendererHistogramSnapshots; class RenderProcessObserver; @@ -40,15 +37,12 @@ class RendererNetPredictor; class RendererWebKitClientImpl; class SpellCheck; class SkBitmap; -class UserScriptSlave; -class URLPattern; class WebDatabaseObserverImpl; struct ContentSettings; struct RendererPreferences; struct DOMStorageMsg_Event_Params; struct GPUInfo; -struct ExtensionMsg_Loaded_Params; struct ViewMsg_New_Params; struct WebPreferences; @@ -103,11 +97,6 @@ class RenderThreadBase { public: virtual ~RenderThreadBase() {} - // Gets currently loaded extensions. This is essentially the renderer - // counterpart to ExtensionService in the browser. It contains information - // about all extensions currently loaded by the browser. - virtual const ExtensionSet* GetExtensions() const = 0; - virtual bool Send(IPC::Message* msg) = 0; // Called to add or remove a listener for a particular message routing ID. @@ -122,9 +111,6 @@ class RenderThreadBase { virtual void WidgetHidden() = 0; virtual void WidgetRestored() = 0; - // True if this process should be treated as an extension process. - virtual bool IsExtensionProcess() const = 0; - // True if this process is running in an incognito profile. virtual bool IsIncognitoProcess() const = 0; }; @@ -160,7 +146,6 @@ class RenderThread : public RenderThreadBase, static int32 RoutingIDForCurrentContext(); // Overridden from RenderThreadBase. - virtual const ExtensionSet* GetExtensions() const; virtual bool Send(IPC::Message* msg); virtual void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); virtual void RemoveRoute(int32 routing_id); @@ -168,7 +153,6 @@ class RenderThread : public RenderThreadBase, virtual void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter); virtual void WidgetHidden(); virtual void WidgetRestored(); - virtual bool IsExtensionProcess() const; virtual bool IsIncognitoProcess() const; void AddObserver(RenderProcessObserver* observer); @@ -186,10 +170,6 @@ class RenderThread : public RenderThreadBase, return visited_link_slave_.get(); } - UserScriptSlave* user_script_slave() const { - return user_script_slave_.get(); - } - AppCacheDispatcher* appcache_dispatcher() const { return appcache_dispatcher_.get(); } @@ -204,6 +184,13 @@ class RenderThread : public RenderThreadBase, bool plugin_refresh_allowed() const { return plugin_refresh_allowed_; } + double idle_notification_delay_in_s() const { + return idle_notification_delay_in_s_; + } + void set_idle_notification_delay_in_s(double idle_notification_delay_in_s) { + idle_notification_delay_in_s = idle_notification_delay_in_s; + } + // Do DNS prefetch resolution of a hostname. void Resolve(const char* name, size_t length); @@ -234,9 +221,6 @@ class RenderThread : public RenderThreadBase, // Sends a message to the browser to enable/disable spdy. void EnableSpdy(bool enable); - // Update the list of active extensions that will be reported when we crash. - void UpdateActiveExtensions(); - // Asynchronously establish a channel to the GPU plugin if not previously // established or if it has been lost (for example if the GPU plugin crashed). // Use GetGpuChannel() to determine when the channel is ready for use. @@ -270,6 +254,15 @@ class RenderThread : public RenderThreadBase, return webkit_client_.get(); } + // Schedule a call to IdleHandler with the given initial delay. + void ScheduleIdleHandler(double initial_delay_s); + + // A task we invoke periodically to assist with idle cleanup. + void IdleHandler(); + + // Registers the given V8 extension with WebKit. + void RegisterExtension(v8::Extension* extension); + private: virtual bool OnControlMessageReceived(const IPC::Message& msg); @@ -281,21 +274,7 @@ class RenderThread : public RenderThreadBase, void OnSetZoomLevelForCurrentURL(const GURL& url, double zoom_level); void OnSetContentSettingsForCurrentURL( const GURL& url, const ContentSettings& content_settings); - void OnUpdateUserScripts(base::SharedMemoryHandle table); - void OnSetExtensionFunctionNames(const std::vector<std::string>& names); - void OnExtensionLoaded(const ExtensionMsg_Loaded_Params& params); - void OnExtensionUnloaded(const std::string& id); - void OnSetExtensionScriptingWhitelist( - const Extension::ScriptingWhitelist& extension_ids); - void OnPageActionsUpdated(const std::string& extension_id, - const std::vector<std::string>& page_actions); void OnDOMStorageEvent(const DOMStorageMsg_Event_Params& params); - void OnExtensionSetAPIPermissions( - const std::string& extension_id, - const std::set<std::string>& permissions); - void OnExtensionSetHostPermissions( - const GURL& extension_url, - const std::vector<URLPattern>& permissions); void OnSetNextPageID(int32 next_page_id); void OnSetIsIncognitoProcess(bool is_incognito_process); void OnSetCSSColors(const std::vector<CSSColors::CSSColorMapping>& colors); @@ -314,10 +293,6 @@ class RenderThread : public RenderThreadBase, void OnGetRendererTcmalloc(); void OnGetV8HeapStats(); - void OnExtensionMessageInvoke(const std::string& extension_id, - const std::string& function_name, - const ListValue& args, - const GURL& event_url); void OnPurgeMemory(); void OnPurgePluginListCache(bool reload_pages); @@ -344,20 +319,9 @@ class RenderThread : public RenderThreadBase, // We initialize WebKit as late as possible. void EnsureWebKitInitialized(); - // A task we invoke periodically to assist with idle cleanup. - void IdleHandler(); - - // Schedule a call to IdleHandler with the given initial delay. - void ScheduleIdleHandler(double initial_delay_s); - - // Registers the given V8 extension with WebKit, and also tracks what pages - // it is allowed to run on. - void RegisterExtension(v8::Extension* extension, bool restrict_to_extensions); - // These objects live solely on the render thread. scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > task_factory_; scoped_ptr<VisitedLinkSlave> visited_link_slave_; - scoped_ptr<UserScriptSlave> user_script_slave_; scoped_ptr<RendererNetPredictor> renderer_net_predictor_; scoped_ptr<AppCacheDispatcher> appcache_dispatcher_; scoped_ptr<IndexedDBDispatcher> indexed_db_dispatcher_; @@ -392,9 +356,6 @@ class RenderThread : public RenderThreadBase, // The current value of the idle notification timer delay. double idle_notification_delay_in_s_; - // True if this renderer is running extensions. - bool is_extension_process_; - // True if this renderer is incognito. bool is_incognito_process_; @@ -404,23 +365,14 @@ class RenderThread : public RenderThreadBase, // Timer that periodically calls IdleHandler. base::RepeatingTimer<RenderThread> idle_timer_; - // Same as above, but on a longer timer and will run even if the process is - // not idle, to ensure that IdleHandle gets called eventually. - base::RepeatingTimer<RenderThread> forced_idle_timer_; - // The channel from the renderer process to the GPU process. scoped_refptr<GpuChannelHost> gpu_channel_; // A lazily initiated thread on which file operations are run. scoped_ptr<base::Thread> file_thread_; - // Map of registered v8 extensions. The key is the extension name. The value - // is true if the extension should be restricted to extension-related - // contexts. - std::map<std::string, bool> v8_extensions_; - - // Contains all loaded extensions. - ExtensionSet extensions_; + // Map of registered v8 extensions. The key is the extension name. + std::set<std::string> v8_extensions_; chrome::ChromeContentRendererClient renderer_client_; diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc index 1e15017..27798b0 100644 --- a/chrome/test/render_view_test.cc +++ b/chrome/test/render_view_test.cc @@ -12,6 +12,7 @@ #include "chrome/renderer/autofill/autofill_agent.h" #include "chrome/renderer/autofill/password_autofill_manager.h" #include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/js_only_v8_extensions.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" @@ -50,7 +51,7 @@ const int32 kRouteId = 5; const int32 kOpenerId = 7; } // namespace -RenderViewTest::RenderViewTest() { +RenderViewTest::RenderViewTest() : extension_dispatcher_(NULL) { } RenderViewTest::~RenderViewTest() { @@ -100,6 +101,7 @@ void RenderViewTest::SetUp() { gfx::GfxModule::SetResourceProvider(chrome::GfxResourceProvider); content::GetContentClient()->set_renderer(&content_renderer_client_); + extension_dispatcher_ = new ExtensionDispatcher(); sandbox_init_wrapper_.reset(new SandboxInitWrapper()); command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); params_.reset(new MainFunctionParams(*command_line_, *sandbox_init_wrapper_, @@ -184,6 +186,9 @@ void RenderViewTest::TearDown() { params_.reset(); command_line_.reset(); sandbox_init_wrapper_.reset(); + + extension_dispatcher_->OnRenderProcessShutdown(); + extension_dispatcher_ = NULL; } int RenderViewTest::SendKeyEvent(MockKeyboard::Layout layout, diff --git a/chrome/test/render_view_test.h b/chrome/test/render_view_test.h index 8eb6132..b70f042 100644 --- a/chrome/test/render_view_test.h +++ b/chrome/test/render_view_test.h @@ -26,6 +26,8 @@ namespace autofill { class AutofillAgent; class PasswordAutofillManager; } + +class ExtensionDispatcher; class MockRenderProcess; class RenderViewTest : public testing::Test { @@ -94,6 +96,7 @@ class RenderViewTest : public testing::Test { MessageLoop msg_loop_; content::ContentRendererClient content_renderer_client_; + ExtensionDispatcher* extension_dispatcher_; MockRenderThread render_thread_; scoped_ptr<MockRenderProcess> mock_process_; scoped_refptr<RenderView> view_; diff --git a/content/renderer/content_renderer_client.cc b/content/renderer/content_renderer_client.cc index 96a53f6..c876f85 100644 --- a/content/renderer/content_renderer_client.cc +++ b/content/renderer/content_renderer_client.cc @@ -33,4 +33,12 @@ std::string ContentRendererClient::DetermineTextLanguage(const string16& text) { return std::string(); } +bool ContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { + return true; +} + +bool ContentRendererClient::AllowPopup(const GURL& creator) { + return false; +} + } // namespace content diff --git a/content/renderer/content_renderer_client.h b/content/renderer/content_renderer_client.h index 4f41a78..268518e 100644 --- a/content/renderer/content_renderer_client.h +++ b/content/renderer/content_renderer_client.h @@ -11,6 +11,7 @@ #include "base/string16.h" #include "content/common/content_client.h" +class GURL; class RenderView; class SkBitmap; @@ -28,20 +29,31 @@ namespace content { class ContentRendererClient { public: virtual SkBitmap* GetSadPluginBitmap(); + virtual std::string GetDefaultEncoding(); + // Create a plugin in the given frame. Can return NULL, in which case // RenderView will create a plugin itself. virtual WebKit::WebPlugin* CreatePlugin( RenderView* render_view, WebKit::WebFrame* frame, const WebKit::WebPluginParams& params); + // Returns the html to display when a navigation error occurs. virtual std::string GetNavigationErrorHtml( const WebKit::WebURLRequest& failed_request, const WebKit::WebURLError& error); + // Returns the ISO 639_1 language code of the specified |text|, or 'unknown' // if it failed. virtual std::string DetermineTextLanguage(const string16& text); + + // Returns true if the renderer process should schedule the idle handler when + // all widgets are hidden. + virtual bool RunIdleHandlerWhenWidgetsHidden(); + + // Returns true if the given url can create popup windows. + virtual bool AllowPopup(const GURL& creator); }; } // namespace content diff --git a/content/renderer/render_process_observer.cc b/content/renderer/render_process_observer.cc index 3479d97..5796271 100644 --- a/content/renderer/render_process_observer.cc +++ b/content/renderer/render_process_observer.cc @@ -4,6 +4,9 @@ #include "content/renderer/render_process_observer.h" +RenderProcessObserver::RenderProcessObserver() { +} + RenderProcessObserver::~RenderProcessObserver() { } @@ -14,3 +17,16 @@ bool RenderProcessObserver::OnControlMessageReceived( void RenderProcessObserver::OnRenderProcessShutdown() { } + +void RenderProcessObserver::WebKitInitialized() { +} + +bool RenderProcessObserver::AllowScriptExtension( + const std::string& v8_extension_name, + const GURL& url, + int extension_group) { + return false; +} + +void RenderProcessObserver::IdleNotification() { +} diff --git a/content/renderer/render_process_observer.h b/content/renderer/render_process_observer.h index 9127246..5c7a7a9 100644 --- a/content/renderer/render_process_observer.h +++ b/content/renderer/render_process_observer.h @@ -9,9 +9,13 @@ #include "base/basictypes.h" #include "ipc/ipc_message.h" -// Base class for objects that want to filter control IPC messages. +class GURL; + +// Base class for objects that want to filter control IPC messages and get +// notified of events. class RenderProcessObserver { public: + RenderProcessObserver(); virtual ~RenderProcessObserver(); // Allows filtering of control messages. @@ -20,6 +24,16 @@ class RenderProcessObserver { // Notification that the render process is shutting down. virtual void OnRenderProcessShutdown(); + // Called right after the WebKit API is initialized. + virtual void WebKitInitialized(); + + // See WebViewClient::allowScriptExtension + virtual bool AllowScriptExtension(const std::string& v8_extension_name, + const GURL& url, + int extension_group); + + virtual void IdleNotification(); + private: DISALLOW_COPY_AND_ASSIGN(RenderProcessObserver); }; diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 04fd392..28f7b9d 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -48,8 +48,8 @@ #include "chrome/renderer/devtools_agent.h" #include "chrome/renderer/devtools_client.h" #include "chrome/renderer/extension_groups.h" -#include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_helper.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/extension_resource_request_policy.h" @@ -2573,12 +2573,8 @@ void RenderView::show(WebNavigationPolicy policy) { return; did_show_ = true; - // Extensions and apps always allowed to create unrequested popups. The second - // check is necessary to include content scripts. - if (render_thread_->GetExtensions()->GetByURL(creator_url_) || - bindings_utils::GetInfoForCurrentContext()) { + if (content::GetContentClient()->renderer()->AllowPopup(creator_url_)) opened_by_user_gesture_ = true; - } // Force new windows to a popup if they were not opened with a user gesture. if (!opened_by_user_gesture_) { @@ -2830,9 +2826,7 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( // window.opener) if the window navigates back. See crbug.com/65953. if (!should_fork && CrossesExtensionExtents( - render_thread_->GetExtensions(), - frame, - url)) { + ExtensionDispatcher::Get()->extensions(), frame, url)) { // Include the referrer in this case since we're going from a hosted web // page. (the packaged case is handled previously by the extension // navigation test) @@ -2841,7 +2835,7 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( if (is_content_initiated) { const Extension* extension = - render_thread_->GetExtensions()->GetByURL(url); + ExtensionDispatcher::Get()->extensions()->GetByURL(url); if (extension && extension->is_app()) { UMA_HISTOGRAM_ENUMERATION( extension_misc::kAppLaunchHistogram, @@ -3307,7 +3301,7 @@ void RenderView::didClearWindowObject(WebFrame* frame) { void RenderView::didCreateDocumentElement(WebFrame* frame) { if (RenderThread::current()) { // Will be NULL during unit tests. - RenderThread::current()->user_script_slave()->InjectScripts( + ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_START); } @@ -3350,7 +3344,7 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) { UpdateEncoding(frame, frame->view()->pageEncoding().utf8()); if (RenderThread::current()) { // Will be NULL during unit tests. - RenderThread::current()->user_script_slave()->InjectScripts( + ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_END); } @@ -3362,7 +3356,7 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) { void RenderView::OnUserScriptIdleTriggered(WebFrame* frame) { if (RenderThread::current()) { // Will be NULL during unit tests. - RenderThread::current()->user_script_slave()->InjectScripts( + ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_IDLE); } @@ -3448,7 +3442,7 @@ void RenderView::willSendRequest( !ExtensionResourceRequestPolicy::CanRequestResource( request_url, GURL(frame->url()), - render_thread_->GetExtensions())) { + ExtensionDispatcher::Get()->extensions())) { request.setURL(WebURL(GURL("chrome-extension://invalid/"))); } @@ -4993,7 +4987,8 @@ void RenderView::ExecuteCodeImpl( WebFrame* frame = *frame_it; if (params.is_javascript) { const Extension* extension = - render_thread_->GetExtensions()->GetByID(params.extension_id); + ExtensionDispatcher::Get()->extensions()->GetByID( + params.extension_id); // Since extension info is sent separately from user script info, they can // be out of sync. We just ignore this situation. |