diff options
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 101 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.h | 11 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_helper.cc | 12 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_helper.h | 2 | ||||
-rw-r--r-- | chrome/test/render_view_test.cc | 2 | ||||
-rw-r--r-- | chrome/test/render_view_test.h | 4 | ||||
-rw-r--r-- | content/renderer/DEPS | 4 | ||||
-rw-r--r-- | content/renderer/content_renderer_client.cc | 32 | ||||
-rw-r--r-- | content/renderer/content_renderer_client.h | 22 | ||||
-rw-r--r-- | content/renderer/render_view.cc | 99 | ||||
-rw-r--r-- | content/renderer/render_view_observer.h | 1 |
11 files changed, 202 insertions, 88 deletions
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index a997758..137a319 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -5,15 +5,24 @@ #include "chrome/renderer/chrome_content_renderer_client.h" #include "base/command_line.h" +#include "base/metrics/histogram.h" #include "base/values.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension_set.h" #include "chrome/common/jstemplate_builder.h" #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/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" +#include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/localized_error.h" #include "content/common/view_messages.h" #include "content/renderer/render_view.h" @@ -40,8 +49,37 @@ using WebKit::WebURLError; using WebKit::WebURLRequest; using WebKit::WebURLResponse; +namespace { + +// Returns true if the frame is navigating to an URL either into or out of an +// extension app's extent. +// TODO(creis): Temporary workaround for crbug.com/65953: Only return true if +// we would enter an extension app's extent from a non-app, or if we leave an +// extension with no web extent. We avoid swapping processes to exit a hosted +// app with a web extent for now, since we do not yet restore context (such +// as window.opener) if the window navigates back. +static bool CrossesExtensionExtents(WebFrame* frame, const GURL& new_url) { + const ExtensionSet* extensions = ExtensionDispatcher::Get()->extensions(); + // If the URL is still empty, this is a window.open navigation. Check the + // opener's URL. + GURL old_url(frame->url()); + if (old_url.is_empty() && frame->opener()) + old_url = frame->opener()->url(); + + bool old_url_is_hosted_app = extensions->GetByURL(old_url) && + !extensions->GetByURL(old_url)->web_extent().is_empty(); + return !extensions->InSameExtent(old_url, new_url) && + !old_url_is_hosted_app; +} + +} // namespcae + namespace chrome { +void ChromeContentRendererClient::RenderViewCreated(RenderView* render_view) { + new ExtensionHelper(render_view); +} + SkBitmap* ChromeContentRendererClient::GetSadPluginBitmap() { return ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SAD_PLUGIN); } @@ -255,4 +293,67 @@ bool ChromeContentRendererClient::AllowPopup(const GURL& creator) { bindings_utils::GetInfoForCurrentContext(); } +bool ChromeContentRendererClient::ShouldFork(WebFrame* frame, + const GURL& url, + bool is_content_initiated, + bool* send_referrer) { + // If the navigation would cross an app extent boundary, we also need + // to defer to the browser to ensure process isolation. + // TODO(erikkay) This is happening inside of a check to is_content_initiated + // which means that things like the back button won't trigger it. Is that + // OK? + // TODO(creis): For hosted apps, we currently only swap processes to enter + // the app and not exit it, since we currently lose context (e.g., + // window.opener) if the window navigates back. See crbug.com/65953. + if (!CrossesExtensionExtents(frame, url)) + return false; + + // 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) + *send_referrer = true; + + if (is_content_initiated) { + const Extension* extension = + ExtensionDispatcher::Get()->extensions()->GetByURL(url); + if (extension && extension->is_app()) { + UMA_HISTOGRAM_ENUMERATION( + extension_misc::kAppLaunchHistogram, + extension_misc::APP_LAUNCH_CONTENT_NAVIGATION, + extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); + } + } + + return true; +} + +bool ChromeContentRendererClient::WillSendRequest(WebKit::WebFrame* frame, + const GURL& url, + GURL* new_url) { + // If the request is for an extension resource, check whether it should be + // allowed. If not allowed, we reset the URL to something invalid to prevent + // the request and cause an error. + if (url.SchemeIs(chrome::kExtensionScheme) && + !ExtensionResourceRequestPolicy::CanRequestResource( + url, GURL(frame->url()), ExtensionDispatcher::Get()->extensions())) { + *new_url = GURL("chrome-extension://invalid/"); + return true; + } + + return false; +} + +void ChromeContentRendererClient::DidCreateScriptContext(WebFrame* frame) { + EventBindings::HandleContextCreated(frame, false); +} + +void ChromeContentRendererClient::DidDestroyScriptContext(WebFrame* frame) { + EventBindings::HandleContextDestroyed(frame); +} + +void ChromeContentRendererClient::DidCreateIsolatedScriptContext( + WebFrame* frame) { + EventBindings::HandleContextCreated(frame, true); +} + } // namespace chrome diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 4d90a92..d69d638 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -18,6 +18,7 @@ namespace chrome { class ChromeContentRendererClient : public content::ContentRendererClient { public: + virtual void RenderViewCreated(RenderView* render_view); virtual SkBitmap* GetSadPluginBitmap(); virtual std::string GetDefaultEncoding(); virtual WebKit::WebPlugin* CreatePlugin( @@ -30,6 +31,16 @@ class ChromeContentRendererClient : public content::ContentRendererClient { virtual std::string DetermineTextLanguage(const string16& text); virtual bool RunIdleHandlerWhenWidgetsHidden(); virtual bool AllowPopup(const GURL& creator); + virtual bool ShouldFork(WebKit::WebFrame* frame, + const GURL& url, + bool is_content_initiated, + bool* send_referrer); + virtual bool WillSendRequest(WebKit::WebFrame* frame, + const GURL& url, + GURL* new_url); + virtual void DidCreateScriptContext(WebKit::WebFrame* frame); + virtual void DidDestroyScriptContext(WebKit::WebFrame* frame); + virtual void DidCreateIsolatedScriptContext(WebKit::WebFrame* frame); private: WebKit::WebPlugin* CreatePluginPlaceholder( diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc index 7e01c40..62fda516 100644 --- a/chrome/renderer/extensions/extension_helper.cc +++ b/chrome/renderer/extensions/extension_helper.cc @@ -5,9 +5,11 @@ #include "chrome/renderer/extensions/extension_helper.h" #include "chrome/common/extensions/extension_messages.h" +#include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/user_script_idle_scheduler.h" +#include "chrome/renderer/user_script_slave.h" using WebKit::WebFrame; using WebKit::WebDataSource; @@ -30,6 +32,16 @@ bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) { return handled; } +void ExtensionHelper::DidFinishDocumentLoad(WebFrame* frame) { + ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( + frame, UserScript::DOCUMENT_END); +} + +void ExtensionHelper::DidCreateDocumentElement(WebFrame* frame) { + ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( + frame, UserScript::DOCUMENT_START); +} + void ExtensionHelper::FrameDetached(WebFrame* frame) { // This could be called before DidCreateDataSource, in which case the frame // won't be in the set. diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h index f7fb438..89d5427 100644 --- a/chrome/renderer/extensions/extension_helper.h +++ b/chrome/renderer/extensions/extension_helper.h @@ -22,6 +22,8 @@ class ExtensionHelper : public RenderViewObserver { private: // RenderViewObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message); + virtual void DidFinishDocumentLoad(WebKit::WebFrame* frame); + virtual void DidCreateDocumentElement(WebKit::WebFrame* frame); virtual void FrameDetached(WebKit::WebFrame* frame); virtual void DidCreateDataSource(WebKit::WebFrame* frame, WebKit::WebDataSource* ds); diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc index 27798b0..774042b0 100644 --- a/chrome/test/render_view_test.cc +++ b/chrome/test/render_view_test.cc @@ -100,7 +100,7 @@ void RenderViewTest::SetUp() { // Configure modules that need access to resources. gfx::GfxModule::SetResourceProvider(chrome::GfxResourceProvider); - content::GetContentClient()->set_renderer(&content_renderer_client_); + content::GetContentClient()->set_renderer(&chrome_content_renderer_client_); extension_dispatcher_ = new ExtensionDispatcher(); sandbox_init_wrapper_.reset(new SandboxInitWrapper()); command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); diff --git a/chrome/test/render_view_test.h b/chrome/test/render_view_test.h index b70f042..f71a042 100644 --- a/chrome/test/render_view_test.h +++ b/chrome/test/render_view_test.h @@ -16,9 +16,9 @@ #include "content/common/main_function_params.h" #include "content/common/native_web_keyboard_event.h" #include "content/common/sandbox_init_wrapper.h" -#include "content/renderer/content_renderer_client.h" #include "content/renderer/render_view.h" #include "content/renderer/renderer_webkitclient_impl.h" +#include "chrome/renderer/chrome_content_renderer_client.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" @@ -95,7 +95,7 @@ class RenderViewTest : public testing::Test { virtual void TearDown(); MessageLoop msg_loop_; - content::ContentRendererClient content_renderer_client_; + chrome::ChromeContentRendererClient chrome_content_renderer_client_; ExtensionDispatcher* extension_dispatcher_; MockRenderThread render_thread_; scoped_ptr<MockRenderProcess> mock_process_; diff --git a/content/renderer/DEPS b/content/renderer/DEPS index 03cc095..7c83852 100644 --- a/content/renderer/DEPS +++ b/content/renderer/DEPS @@ -1,3 +1,7 @@ include_rules = [
+ # The following directories have been refactored, so no new dependencies + # should be added from these directories. + "-chrome/renderer/extensions",
+
"+content/plugin", # For shared npruntime proxying code.
]
diff --git a/content/renderer/content_renderer_client.cc b/content/renderer/content_renderer_client.cc index c876f85..79573c4 100644 --- a/content/renderer/content_renderer_client.cc +++ b/content/renderer/content_renderer_client.cc @@ -6,8 +6,13 @@ #include "content/renderer/render_view.h" +using WebKit::WebFrame; + namespace content { +void ContentRendererClient::RenderViewCreated(RenderView* render_view) { +} + SkBitmap* ContentRendererClient::GetSadPluginBitmap() { return NULL; } @@ -16,9 +21,8 @@ std::string ContentRendererClient::GetDefaultEncoding() { return std::string(); } -WebKit::WebPlugin* ContentRendererClient::CreatePlugin( - RenderView* render_view, - WebKit::WebFrame* frame, +WebKit::WebPlugin* ContentRendererClient::CreatePlugin(RenderView* render_view, + WebFrame* frame, const WebKit::WebPluginParams& params) { return render_view->CreatePluginNoCheck(frame, params); } @@ -41,4 +45,26 @@ bool ContentRendererClient::AllowPopup(const GURL& creator) { return false; } +bool ContentRendererClient::ShouldFork(WebFrame* frame, + const GURL& url, + bool is_content_initiated, + bool* send_referrer) { + return false; +} + +bool ContentRendererClient::WillSendRequest(WebFrame* frame, + const GURL& url, + GURL* new_url) { + return false; +} + +void ContentRendererClient::DidCreateScriptContext(WebFrame* frame) { +} + +void ContentRendererClient::DidDestroyScriptContext(WebFrame* frame) { +} + +void ContentRendererClient::DidCreateIsolatedScriptContext(WebFrame* frame) { +} + } // namespace content diff --git a/content/renderer/content_renderer_client.h b/content/renderer/content_renderer_client.h index 268518e..e9bcbf9 100644 --- a/content/renderer/content_renderer_client.h +++ b/content/renderer/content_renderer_client.h @@ -28,8 +28,13 @@ namespace content { // Embedder API for participating in renderer logic. class ContentRendererClient { public: + // Notifies that a new RenderView has been created. + virtual void RenderViewCreated(RenderView* render_view); + + // Returns the bitmap to show when a plugin crashed, or NULL for none. virtual SkBitmap* GetSadPluginBitmap(); + // Returns the default text encoding. virtual std::string GetDefaultEncoding(); // Create a plugin in the given frame. Can return NULL, in which case @@ -54,6 +59,23 @@ class ContentRendererClient { // Returns true if the given url can create popup windows. virtual bool AllowPopup(const GURL& creator); + + // Returns true if we should fork a new process for the given navigation. + virtual bool ShouldFork(WebKit::WebFrame* frame, + const GURL& url, + bool is_content_initiated, + bool* send_referrer); + + // Notifies the embedder that the given frame is requesting the resource at + // |url|. If the function returns true, the url is changed to |new_url|. + virtual bool WillSendRequest(WebKit::WebFrame* frame, + const GURL& url, + GURL* new_url); + + // See the corresponding functions in WebKit::WebFrameClient. + virtual void DidCreateScriptContext(WebKit::WebFrame* frame); + virtual void DidDestroyScriptContext(WebKit::WebFrame* frame); + virtual void DidCreateIsolatedScriptContext(WebKit::WebFrame* frame); }; } // namespace content diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 29bb35f..75d8e6d 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -28,10 +28,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/devtools_messages.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_messages.h" -#include "chrome/common/extensions/extension_set.h" #include "chrome/common/json_value_serializer.h" #include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" @@ -46,12 +43,6 @@ #include "chrome/renderer/automation/dom_automation_controller.h" #include "chrome/renderer/devtools_agent.h" #include "chrome/renderer/devtools_client.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" -#include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/external_host_bindings.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/page_click_tracker.h" @@ -65,7 +56,6 @@ #include "chrome/renderer/spellchecker/spellcheck.h" #include "chrome/renderer/spellchecker/spellcheck_provider.h" #include "chrome/renderer/translate_helper.h" -#include "chrome/renderer/user_script_slave.h" #include "chrome/renderer/visitedlink_slave.h" #include "content/common/appcache/appcache_dispatcher.h" #include "content/common/clipboard_messages.h" @@ -391,28 +381,6 @@ static bool IsWhitelistedForContentSettings(WebFrame* frame) { return false; } -// Returns true if the frame is navigating to an URL either into or out of an -// extension app's extent. -// TODO(creis): Temporary workaround for crbug.com/65953: Only return true if -// we would enter an extension app's extent from a non-app, or if we leave an -// extension with no web extent. We avoid swapping processes to exit a hosted -// app with a web extent for now, since we do not yet restore context (such -// as window.opener) if the window navigates back. -static bool CrossesExtensionExtents(const ExtensionSet* extensions, - WebFrame* frame, - const GURL& new_url) { - // If the URL is still empty, this is a window.open navigation. Check the - // opener's URL. - GURL old_url(frame->url()); - if (old_url.is_empty() && frame->opener()) - old_url = frame->opener()->url(); - - bool old_url_is_hosted_app = extensions->GetByURL(old_url) && - !extensions->GetByURL(old_url)->web_extent().is_empty(); - return !extensions->InSameExtent(old_url, new_url) && - !old_url_is_hosted_app; -} - // Returns true if the parameter node is a textfield, text area or a content // editable div. static bool IsEditableNode(const WebNode& node) { @@ -647,7 +615,7 @@ RenderView::RenderView(RenderThreadBase* render_thread, // Observer for Malware DOM details messages. new safe_browsing::MalwareDOMDetails(this); - new ExtensionHelper(this); + content::GetContentClient()->renderer()->RenderViewCreated(this); } RenderView::~RenderView() { @@ -2722,33 +2690,10 @@ WebNavigationPolicy RenderView::decidePolicyForNavigation( frame->isViewSourceModeEnabled() || url.SchemeIs(chrome::kViewSourceScheme); - // If the navigation would cross an app extent boundary, we also need - // to defer to the browser to ensure process isolation. - // TODO(erikkay) This is happening inside of a check to is_content_initiated - // which means that things like the back button won't trigger it. Is that - // OK? - // TODO(creis): For hosted apps, we currently only swap processes to enter - // the app and not exit it, since we currently lose context (e.g., - // window.opener) if the window navigates back. See crbug.com/65953. - if (!should_fork && - CrossesExtensionExtents( - 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) - should_fork = true; - send_referrer = true; - - if (is_content_initiated) { - const Extension* extension = - ExtensionDispatcher::Get()->extensions()->GetByURL(url); - if (extension && extension->is_app()) { - UMA_HISTOGRAM_ENUMERATION( - extension_misc::kAppLaunchHistogram, - extension_misc::APP_LAUNCH_CONTENT_NAVIGATION, - extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); - } - } + if (!should_fork) { + // Give the embedder a chance. + should_fork = content::GetContentClient()->renderer()->ShouldFork( + frame, url, is_content_initiated, &send_referrer); } if (should_fork) { @@ -3198,17 +3143,15 @@ void RenderView::didClearWindowObject(WebFrame* frame) { } void RenderView::didCreateDocumentElement(WebFrame* frame) { - if (RenderThread::current()) { // Will be NULL during unit tests. - ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( - frame, UserScript::DOCUMENT_START); - } - // Notify the browser about non-blank documents loading in the top frame. GURL url = frame->url(); if (url.is_valid() && url.spec() != chrome::kAboutBlankURL) { if (frame == webview()->mainFrame()) Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_)); } + + FOR_EACH_OBSERVER(RenderViewObserver, observers_, + DidCreateDocumentElement(frame)); } void RenderView::didReceiveTitle(WebFrame* frame, const WebString& title) { @@ -3240,11 +3183,6 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) { // Check whether we have new encoding name. UpdateEncoding(frame, frame->view()->pageEncoding().utf8()); - - if (RenderThread::current()) { // Will be NULL during unit tests. - ExtensionDispatcher::Get()->user_script_slave()->InjectScripts( - frame, UserScript::DOCUMENT_END); - } } void RenderView::didHandleOnloadEvents(WebFrame* frame) { @@ -3309,16 +3247,12 @@ void RenderView::willSendRequest( WebDataSource* data_source = provisional_data_source ? provisional_data_source : top_data_source; - // If the request is for an extension resource, check whether it should be - // allowed. If not allowed, we reset the URL to something invalid to prevent - // the request and cause an error. + GURL request_url(request.url()); - if (request_url.SchemeIs(chrome::kExtensionScheme) && - !ExtensionResourceRequestPolicy::CanRequestResource( - request_url, - GURL(frame->url()), - ExtensionDispatcher::Get()->extensions())) { - request.setURL(WebURL(GURL("chrome-extension://invalid/"))); + GURL new_url; + if (content::GetContentClient()->renderer()->WillSendRequest( + frame, request_url, &new_url)) { + request.setURL(WebURL(new_url)); } if (data_source) { @@ -3491,15 +3425,16 @@ void RenderView::didExhaustMemoryAvailableForScript(WebFrame* frame) { } void RenderView::didCreateScriptContext(WebFrame* frame) { - EventBindings::HandleContextCreated(frame, false); + content::GetContentClient()->renderer()->DidCreateScriptContext(frame); } void RenderView::didDestroyScriptContext(WebFrame* frame) { - EventBindings::HandleContextDestroyed(frame); + content::GetContentClient()->renderer()->DidDestroyScriptContext(frame); } void RenderView::didCreateIsolatedScriptContext(WebFrame* frame) { - EventBindings::HandleContextCreated(frame, true); + content::GetContentClient()->renderer()->DidCreateIsolatedScriptContext( + frame); } bool RenderView::allowScriptExtension(WebFrame* frame, diff --git a/content/renderer/render_view_observer.h b/content/renderer/render_view_observer.h index 186270b..e8c7375 100644 --- a/content/renderer/render_view_observer.h +++ b/content/renderer/render_view_observer.h @@ -37,6 +37,7 @@ class RenderViewObserver : public IPC::Channel::Listener, const WebKit::WebURLError& error) {} virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame, bool is_new_navigation) {} + virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) {} virtual void FrameDetached(WebKit::WebFrame* frame) {} virtual void FrameWillClose(WebKit::WebFrame* frame) {} virtual void DidCreateDataSource(WebKit::WebFrame* frame, |