diff options
28 files changed, 322 insertions, 112 deletions
diff --git a/chrome/browser/extensions/extension_debugger_api.cc b/chrome/browser/extensions/extension_debugger_api.cc index 4fab1b0..8706483 100644 --- a/chrome/browser/extensions/extension_debugger_api.cc +++ b/chrome/browser/extensions/extension_debugger_api.cc @@ -34,6 +34,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host_delegate.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_client.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "webkit/glue/webkit_glue.h" @@ -377,7 +378,7 @@ bool DebuggerFunction::InitTabContents() { } contents_ = wrapper->web_contents(); - if (ChromeWebUIControllerFactory::GetInstance()->HasWebUIScheme( + if (content::GetContentClient()->HasWebUIScheme( contents_->GetURL())) { error_ = ExtensionErrorUtils::FormatErrorMessage( keys::kAttachToWebUIError, diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index ae8cbdf..79be013 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -54,6 +54,7 @@ #include "chrome/common/url_constants.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" +#include "content/public/common/content_client.h" #include "googleurl/src/gurl.h" #if defined(OS_CHROMEOS) @@ -382,12 +383,6 @@ bool ChromeWebUIControllerFactory::UseWebUIBindingsForURL( UseWebUIForURL(browser_context, url); } -bool ChromeWebUIControllerFactory::HasWebUIScheme(const GURL& url) const { - return url.SchemeIs(chrome::kChromeDevToolsScheme) || - url.SchemeIs(chrome::kChromeInternalScheme) || - url.SchemeIs(chrome::kChromeUIScheme); -} - bool ChromeWebUIControllerFactory::IsURLAcceptableForWebUI( content::BrowserContext* browser_context, const GURL& url) const { @@ -463,7 +458,7 @@ RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes( return NULL; } - if (!HasWebUIScheme(page_url)) + if (!content::GetContentClient()->HasWebUIScheme(page_url)) return NULL; #if defined(OS_WIN) diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h index db53d01..e8891e42 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h @@ -1,9 +1,9 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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_BROWSER_UI_WEBUI_CHROME_WEB_UI_FACTORY_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROME_WEB_UI_FACTORY_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROME_WEB_UI_CONTROLLER_FACTORY_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROME_WEB_UI_CONTROLLER_FACTORY_H_ #pragma once #include "base/basictypes.h" @@ -24,7 +24,6 @@ class ChromeWebUIControllerFactory : public content::WebUIControllerFactory { const GURL& url) const OVERRIDE; virtual bool UseWebUIBindingsForURL(content::BrowserContext* browser_context, const GURL& url) const OVERRIDE; - virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool IsURLAcceptableForWebUI(content::BrowserContext* browser_context, const GURL& url) const OVERRIDE; virtual content::WebUIController* CreateWebUIControllerForURL( @@ -54,4 +53,4 @@ class ChromeWebUIControllerFactory : public content::WebUIControllerFactory { DISALLOW_COPY_AND_ASSIGN(ChromeWebUIControllerFactory); }; -#endif // CHROME_BROWSER_UI_WEBUI_CHROME_WEB_UI_FACTORY_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROME_WEB_UI_CONTROLLER_FACTORY_H_ diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index f4353d0..23f834a 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc @@ -19,6 +19,7 @@ #include "chrome/common/chrome_version_info.h" #include "chrome/common/render_messages.h" #include "content/public/common/pepper_plugin_info.h" +#include "content/public/common/url_constants.h" #include "grit/common_resources.h" #include "remoting/client/plugin/pepper_entrypoints.h" #include "ui/base/l10n/l10n_util.h" @@ -346,6 +347,12 @@ void ChromeContentClient::AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) { } +bool ChromeContentClient::HasWebUIScheme(const GURL& url) const { + return url.SchemeIs(chrome::kChromeDevToolsScheme) || + url.SchemeIs(chrome::kChromeInternalScheme) || + url.SchemeIs(chrome::kChromeUIScheme); +} + bool ChromeContentClient::CanHandleWhileSwappedOut( const IPC::Message& msg) { // Any Chrome-specific messages (apart from those listed in diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h index deb2d8e..31819b9 100644 --- a/chrome/common/chrome_content_client.h +++ b/chrome/common/chrome_content_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -23,6 +23,7 @@ class ChromeContentClient : public content::ContentClient { std::vector<content::PepperPluginInfo>* plugins) OVERRIDE; virtual void AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) OVERRIDE; + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) OVERRIDE; virtual std::string GetUserAgent(bool* overriding) const OVERRIDE; virtual string16 GetLocalizedString(int message_id) const OVERRIDE; diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 3ddafd7..916ecc0 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -698,12 +698,6 @@ bool ChromeContentRendererClient::ShouldFork(WebFrame* frame, return true; } - // Navigating to a new chrome:// scheme (in a new tab) from within a - // chrome:// page must be a browser navigation so that the browser can - // register the new associated data source. - if (url.SchemeIs(kChromeUIScheme)) - return true; - return false; } diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index 97e3e98..fb72207 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc @@ -21,6 +21,7 @@ #include "content/public/common/content_constants.h" #include "content/public/common/url_constants.h" #include "content/test/test_browser_context.h" +#include "content/test/test_content_client.h" #include "googleurl/src/url_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -52,14 +53,11 @@ class SiteInstanceTestWebUIControllerFactory } virtual bool UseWebUIForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); - } - virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { - return url.SchemeIs(chrome::kChromeUIScheme); + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool IsURLAcceptableForWebUI(BrowserContext* browser_context, const GURL& url) const OVERRIDE { @@ -67,6 +65,16 @@ class SiteInstanceTestWebUIControllerFactory } }; +class SiteInstanceTestClient : public TestContentClient { + public: + SiteInstanceTestClient() { + } + + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { + return url.SchemeIs(chrome::kChromeUIScheme); + } +}; + class SiteInstanceTestBrowserClient : public content::MockContentBrowserClient { public: SiteInstanceTestBrowserClient() @@ -102,10 +110,13 @@ class SiteInstanceTest : public testing::Test { public: SiteInstanceTest() : ui_thread_(BrowserThread::UI, &message_loop_), + old_client_(NULL), old_browser_client_(NULL) { } virtual void SetUp() { + old_client_ = content::GetContentClient(); + content::SetContentClient(&client_); old_browser_client_ = content::GetContentClient()->browser(); content::GetContentClient()->set_browser(&browser_client_); url_util::AddStandardScheme(kPrivilegedScheme); @@ -114,6 +125,7 @@ class SiteInstanceTest : public testing::Test { virtual void TearDown() { content::GetContentClient()->set_browser(old_browser_client_); + content::SetContentClient(old_client_); } void set_privileged_process_id(int process_id) { @@ -124,7 +136,9 @@ class SiteInstanceTest : public testing::Test { MessageLoopForUI message_loop_; BrowserThreadImpl ui_thread_; + SiteInstanceTestClient client_; SiteInstanceTestBrowserClient browser_client_; + content::ContentClient* old_client_; content::ContentBrowserClient* old_browser_client_; }; diff --git a/content/browser/tab_contents/render_view_host_manager_unittest.cc b/content/browser/tab_contents/render_view_host_manager_unittest.cc index 6f3fd02..35c3499 100644 --- a/content/browser/tab_contents/render_view_host_manager_unittest.cc +++ b/content/browser/tab_contents/render_view_host_manager_unittest.cc @@ -22,6 +22,7 @@ #include "content/public/common/page_transition_types.h" #include "content/public/common/url_constants.h" #include "content/test/test_browser_context.h" +#include "content/test/test_content_client.h" #include "content/test/test_notification_tracker.h" #include "testing/gtest/include/gtest/gtest.h" #include "googleurl/src/url_util.h" @@ -45,8 +46,6 @@ using content::WebUIController; namespace { -const char kChromeUISchemeButNotWebUIURL[] = "chrome://not-webui"; - class RenderViewHostManagerTestWebUIControllerFactory : public content::WebUIControllerFactory { public: @@ -62,7 +61,8 @@ class RenderViewHostManagerTestWebUIControllerFactory // WebUIFactory implementation. virtual WebUIController* CreateWebUIControllerForURL( WebUI* web_ui, const GURL& url) const OVERRIDE { - if (!(should_create_webui_ && HasWebUIScheme(url))) + if (!(should_create_webui_ && + content::GetContentClient()->HasWebUIScheme(url))) return NULL; return new WebUIController(web_ui); } @@ -74,17 +74,12 @@ class RenderViewHostManagerTestWebUIControllerFactory virtual bool UseWebUIForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); - } - - virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { - return url.SchemeIs(chrome::kChromeUIScheme) && - url.spec() != kChromeUISchemeButNotWebUIURL; + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool IsURLAcceptableForWebUI(BrowserContext* browser_context, @@ -98,6 +93,16 @@ class RenderViewHostManagerTestWebUIControllerFactory DISALLOW_COPY_AND_ASSIGN(RenderViewHostManagerTestWebUIControllerFactory); }; +class RenderViewHostManagerTestClient : public TestContentClient { + public: + RenderViewHostManagerTestClient() { + } + + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { + return url.SchemeIs(chrome::kChromeUIScheme); + } +}; + class RenderViewHostManagerTestBrowserClient : public content::MockContentBrowserClient { public: @@ -127,6 +132,8 @@ class RenderViewHostManagerTest public: virtual void SetUp() OVERRIDE { RenderViewHostTestHarness::SetUp(); + old_client_ = content::GetContentClient(); + content::SetContentClient(&client_); old_browser_client_ = content::GetContentClient()->browser(); content::GetContentClient()->set_browser(&browser_client_); url_util::AddStandardScheme(chrome::kChromeUIScheme); @@ -135,6 +142,7 @@ class RenderViewHostManagerTest virtual void TearDown() OVERRIDE { RenderViewHostTestHarness::TearDown(); content::GetContentClient()->set_browser(old_browser_client_); + content::SetContentClient(old_client_); } void set_should_create_webui(bool should_create_webui) { @@ -172,7 +180,9 @@ class RenderViewHostManagerTest } private: + RenderViewHostManagerTestClient client_; RenderViewHostManagerTestBrowserClient browser_client_; + content::ContentClient* old_client_; content::ContentBrowserClient* old_browser_client_; }; @@ -674,34 +684,6 @@ TEST_F(RenderViewHostManagerTest, WebUI) { manager.DidNavigateMainFrame(host); } -// Tests that chrome: URLs that are not Web UI pages do not get grouped into -// Web UI renderers, even if --process-per-tab is enabled. In that mode, we -// still swap processes if ShouldSwapProcessesForNavigation is true. -// Regression test for bug 46290. -TEST_F(RenderViewHostManagerTest, NonWebUIChromeURLs) { - BrowserThreadImpl thread(BrowserThread::UI, &message_loop_); - SiteInstance* instance = SiteInstance::Create(browser_context()); - TestTabContents tab_contents(browser_context(), instance); - RenderViewHostManager manager(&tab_contents, &tab_contents); - manager.Init(browser_context(), instance, MSG_ROUTING_NONE); - - // NTP is a Web UI page. - const GURL kNtpUrl(chrome::kTestNewTabURL); - NavigationEntryImpl ntp_entry(NULL /* instance */, -1 /* page_id */, kNtpUrl, - content::Referrer(), string16() /* title */, - content::PAGE_TRANSITION_TYPED, - false /* is_renderer_init */); - - // A URL with the Chrome UI scheme, that isn't handled by Web UI. - GURL about_url(kChromeUISchemeButNotWebUIURL); - NavigationEntryImpl about_entry( - NULL /* instance */, -1 /* page_id */, about_url, - content::Referrer(), string16() /* title */, - content::PAGE_TRANSITION_TYPED, false /* is_renderer_init */); - - EXPECT_TRUE(ShouldSwapProcesses(&manager, &ntp_entry, &about_entry)); -} - // Tests that we don't end up in an inconsistent state if a page does a back and // then reload. http://crbug.com/51680 TEST_F(RenderViewHostManagerTest, PageDoesBackAndReload) { diff --git a/content/browser/tab_contents/tab_contents_unittest.cc b/content/browser/tab_contents/tab_contents_unittest.cc index 4301d11..27cf97da 100644 --- a/content/browser/tab_contents/tab_contents_unittest.cc +++ b/content/browser/tab_contents/tab_contents_unittest.cc @@ -25,6 +25,7 @@ #include "content/public/common/content_constants.h" #include "content/public/common/url_constants.h" #include "content/test/test_browser_thread.h" +#include "content/test/test_content_client.h" #include "googleurl/src/url_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/glue/webkit_glue.h" @@ -50,7 +51,7 @@ class TabContentsTestWebUIControllerFactory public: virtual WebUIController* CreateWebUIControllerForURL( content::WebUI* web_ui, const GURL& url) const OVERRIDE { - if (!HasWebUIScheme(url)) + if (!content::GetContentClient()->HasWebUIScheme(url)) return NULL; return new WebUIController(web_ui); @@ -63,21 +64,27 @@ class TabContentsTestWebUIControllerFactory virtual bool UseWebUIForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context, const GURL& url) const OVERRIDE { - return HasWebUIScheme(url); - } - - virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { - return url.SchemeIs("tabcontentstest"); + return content::GetContentClient()->HasWebUIScheme(url); } virtual bool IsURLAcceptableForWebUI( BrowserContext* browser_context, const GURL& url) const { - return HasWebUIScheme(url); + return content::GetContentClient()->HasWebUIScheme(url); + } +}; + +class TabContentsTestClient : public TestContentClient { + public: + TabContentsTestClient() { + } + + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE { + return url.SchemeIs("tabcontentstest"); } }; @@ -261,6 +268,7 @@ class TabContentsTest : public RenderViewHostImplTestHarness { public: TabContentsTest() : ui_thread_(BrowserThread::UI, &message_loop_), + old_client_(NULL), old_browser_client_(NULL) { } @@ -269,6 +277,8 @@ class TabContentsTest : public RenderViewHostImplTestHarness { // We must register it similarly to kChromeUIScheme. url_util::AddStandardScheme("tabcontentstest"); + old_client_ = content::GetContentClient(); + content::SetContentClient(&client_); old_browser_client_ = content::GetContentClient()->browser(); content::GetContentClient()->set_browser(&browser_client_); RenderViewHostTestHarness::SetUp(); @@ -276,12 +286,15 @@ class TabContentsTest : public RenderViewHostImplTestHarness { virtual void TearDown() { content::GetContentClient()->set_browser(old_browser_client_); + content::SetContentClient(old_client_); RenderViewHostTestHarness::TearDown(); } private: + TabContentsTestClient client_; TabContentsTestBrowserClient browser_client_; content::TestBrowserThread ui_thread_; + content::ContentClient* old_client_; content::ContentBrowserClient* old_browser_client_; }; diff --git a/content/public/browser/web_ui_controller_factory.h b/content/public/browser/web_ui_controller_factory.h index fe5853e..412006e 100644 --- a/content/public/browser/web_ui_controller_factory.h +++ b/content/public/browser/web_ui_controller_factory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -35,6 +35,8 @@ class CONTENT_EXPORT WebUIControllerFactory { const GURL& url) const = 0; // Shorthand for the above, but returns a simple yes/no. + // See also ContentClient::HasWebUIScheme, which only checks the scheme + // (faster) and can be used to determine security policy. virtual bool UseWebUIForURL(BrowserContext* browser_context, const GURL& url) const = 0; @@ -42,11 +44,6 @@ class CONTENT_EXPORT WebUIControllerFactory { virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context, const GURL& url) const = 0; - // Returns true if the url has a scheme for WebUI. This differs from the above - // in that it only checks the scheme; it is faster and can be used to - // determine security policy. - virtual bool HasWebUIScheme(const GURL& url) const = 0; - // Returns true if the given URL can be loaded by Web UI system. This allows // URLs with WebUI types (as above) and also URLs that can be loaded by // normal tabs such as javascript: URLs or about:hang. diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h index 4e6612d..dd27412 100644 --- a/content/public/common/content_client.h +++ b/content/public/common/content_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -94,6 +94,10 @@ class CONTENT_EXPORT ContentClient { virtual void AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) = 0; + // Returns true if the url has a scheme for WebUI. See also + // WebUIControllerFactory::UseWebUIForURL in the browser process. + virtual bool HasWebUIScheme(const GURL& url) const = 0; + // Returns whether the given message should be processed in the browser on // behalf of a swapped out renderer. virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) = 0; diff --git a/content/renderer/media/audio_renderer_impl_unittest.cc b/content/renderer/media/audio_renderer_impl_unittest.cc index 3123090..5320b1a 100644 --- a/content/renderer/media/audio_renderer_impl_unittest.cc +++ b/content/renderer/media/audio_renderer_impl_unittest.cc @@ -37,6 +37,8 @@ class MockRenderProcess : public RenderProcess { const gfx::Rect& rect) { return NULL; } virtual void ReleaseTransportDIB(TransportDIB* memory) {} virtual bool UseInProcessPlugins() const { return false; } + virtual void AddBindings(int bindings) {} + virtual int GetEnabledBindings() const { return 0; } virtual bool HasInitializedMediaLibrary() const { return false; } private: diff --git a/content/renderer/render_process.h b/content/renderer/render_process.h index 8ae6611..681b898 100644 --- a/content/renderer/render_process.h +++ b/content/renderer/render_process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -48,6 +48,13 @@ class RenderProcess : public ChildProcess { // Returns true if plugisn should be loaded in-process. virtual bool UseInProcessPlugins() const = 0; + // Keep track of the cumulative set of enabled bindings for this process, + // across any view. + virtual void AddBindings(int bindings) = 0; + + // The cumulative set of enabled bindings for this process. + virtual int GetEnabledBindings() const = 0; + // Returns a pointer to the RenderProcess singleton instance. Assuming that // we're actually a renderer or a renderer test, this static cast will // be correct. diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index fbb6417..ca56ce6 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc @@ -38,7 +38,8 @@ RenderProcessImpl::RenderProcessImpl() : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( FROM_HERE, base::TimeDelta::FromSeconds(5), this, &RenderProcessImpl::ClearTransportDIBCache)), - transport_dib_next_sequence_number_(0) { + transport_dib_next_sequence_number_(0), + enabled_bindings_(0) { in_process_plugins_ = InProcessPlugins(); for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) shared_mem_cache_[i] = NULL; @@ -98,6 +99,14 @@ bool RenderProcessImpl::InProcessPlugins() { #endif } +void RenderProcessImpl::AddBindings(int bindings) { + enabled_bindings_ |= bindings; +} + +int RenderProcessImpl::GetEnabledBindings() const { + return enabled_bindings_; +} + // ----------------------------------------------------------------------------- // Platform specific code for dealing with bitmap transport... diff --git a/content/renderer/render_process_impl.h b/content/renderer/render_process_impl.h index 8761844..ff78b1c 100644 --- a/content/renderer/render_process_impl.h +++ b/content/renderer/render_process_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -28,6 +28,8 @@ class RenderProcessImpl : public RenderProcess { const gfx::Rect& rect) OVERRIDE; virtual void ReleaseTransportDIB(TransportDIB* memory) OVERRIDE; virtual bool UseInProcessPlugins() const OVERRIDE; + virtual void AddBindings(int bindings) OVERRIDE; + virtual int GetEnabledBindings() const OVERRIDE; // Like UseInProcessPlugins(), but called before RenderProcess is created // and does not allow overriding by tests. This just checks the command line @@ -70,6 +72,10 @@ class RenderProcessImpl : public RenderProcess { bool in_process_plugins_; + // Bitwise-ORed set of extra bindings that have been enabled anywhere in this + // process. See BindingsPolicy for details. + int enabled_bindings_; + DISALLOW_COPY_AND_ASSIGN(RenderProcessImpl); }; diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 4f8c761..7a9525c 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc @@ -10,6 +10,7 @@ #include "content/common/intents_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/common/bindings_policy.h" #include "content/renderer/render_view_impl.h" #include "content/test/render_view_test.h" #include "net/base/net_errors.h" @@ -18,6 +19,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntentServiceInfo.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h" #include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/range/range.h" #include "ui/gfx/codec/jpeg_codec.h" @@ -59,6 +61,102 @@ TEST_F(RenderViewImplTest, OnNavStateChanged) { ViewHostMsg_UpdateState::ID)); } +TEST_F(RenderViewImplTest, DecideNavigationPolicy) { + // Navigations to normal HTTP URLs can be handled locally. + WebKit::WebURLRequest request(GURL("http://foo.com")); + WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation( + GetMainFrame(), + request, + WebKit::WebNavigationTypeLinkClicked, + WebKit::WebNode(), + WebKit::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyCurrentTab, policy); + + // Verify that form posts to WebUI URLs will be sent to the browser process. + WebKit::WebURLRequest form_request(GURL("chrome://foo")); + form_request.setHTTPMethod("POST"); + policy = view()->decidePolicyForNavigation( + GetMainFrame(), + form_request, + WebKit::WebNavigationTypeFormSubmitted, + WebKit::WebNode(), + WebKit::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + + // Verify that popup links to WebUI URLs also are sent to browser. + WebKit::WebURLRequest popup_request(GURL("chrome://foo")); + policy = view()->decidePolicyForNavigation( + GetMainFrame(), + popup_request, + WebKit::WebNavigationTypeLinkClicked, + WebKit::WebNode(), + WebKit::WebNavigationPolicyNewForegroundTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); +} + +TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { + // Enable bindings to simulate a WebUI view. + view()->OnAllowBindings(content::BINDINGS_POLICY_WEB_UI); + + // Navigations to normal HTTP URLs will be sent to browser process. + WebKit::WebURLRequest request(GURL("http://foo.com")); + WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation( + GetMainFrame(), + request, + WebKit::WebNavigationTypeLinkClicked, + WebKit::WebNode(), + WebKit::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + + // Navigations to WebUI URLs will also be sent to browser process. + WebKit::WebURLRequest webui_request(GURL("chrome://foo")); + policy = view()->decidePolicyForNavigation( + GetMainFrame(), + webui_request, + WebKit::WebNavigationTypeLinkClicked, + WebKit::WebNode(), + WebKit::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + + // Verify that form posts to data URLs will be sent to the browser process. + WebKit::WebURLRequest data_request(GURL("data:text/html,foo")); + data_request.setHTTPMethod("POST"); + policy = view()->decidePolicyForNavigation( + GetMainFrame(), + data_request, + WebKit::WebNavigationTypeFormSubmitted, + WebKit::WebNode(), + WebKit::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + + // Verify that a popup that creates a view first and then navigates to a + // normal HTTP URL will be sent to the browser process, even though the + // new view does not have any enabled_bindings_. + WebKit::WebURLRequest popup_request(GURL("http://foo.com")); + WebKit::WebView* new_web_view = view()->createView( + GetMainFrame(), popup_request, WebKit::WebWindowFeatures(), "foo", + WebKit::WebNavigationPolicyNewForegroundTab); + RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view); + policy = new_view->decidePolicyForNavigation( + new_web_view->mainFrame(), + popup_request, + WebKit::WebNavigationTypeLinkClicked, + WebKit::WebNode(), + WebKit::WebNavigationPolicyNewForegroundTab, + false); + EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + + // Clean up after the new view so we don't leak it. + new_view->Close(); + new_view->Release(); +} + // Ensure the RenderViewImpl sends an ACK to a SwapOut request, even if it is // already swapped out. http://crbug.com/93427. TEST_F(RenderViewImplTest, SendSwapOutACK) { diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index b1bb198..09ce2cd 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -40,6 +40,7 @@ #include "content/common/request_extra_data.h" #include "content/common/view_messages.h" #include "content/public/common/bindings_policy.h" +#include "content/public/common/content_client.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" #include "content/public/common/context_menu_params.h" @@ -2316,32 +2317,45 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( // Detect when we're crossing a permission-based boundary (e.g. into or out of // an extension or app origin, leaving a WebUI page, etc). We only care about - // top-level navigations within the current tab (as opposed to, for example, - // opening a new window). But we sometimes navigate to about:blank to clear a - // tab, and we want to still allow that. + // top-level navigations (not iframes). But we sometimes navigate to + // about:blank to clear a tab, and we want to still allow that. // - // Note: we do this only for GET requests because our mechanism for switching - // processes only issues GET requests. In particular, POST requests don't - // work, because this mechanism does not preserve form POST data. If it - // becomes necessary to support process switching for POST requests, we will - // need to send the request's httpBody data up to the browser process, and - // issue a special POST navigation in WebKit (via + // Note: this is known to break POST submissions when crossing process + // boundaries until http://crbug.com/101395 is fixed. This is better for + // security than loading a WebUI, extension or app page in the wrong process. + // POST requests don't work because this mechanism does not preserve form + // POST data. We will need to send the request's httpBody data up to the + // browser process, and issue a special POST navigation in WebKit (via // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl // for examples of how to send the httpBody data. if (!frame->parent() && is_content_initiated && - default_policy == WebKit::WebNavigationPolicyCurrentTab && - request.httpMethod() == "GET" && !url.SchemeIs(chrome::kAboutScheme)) { + !url.SchemeIs(chrome::kAboutScheme)) { bool send_referrer = false; + + // All navigations to WebUI URLs or within WebUI-enabled RenderProcesses + // must be handled by the browser process so that the correct bindings and + // data sources can be registered. + // Similarly, navigations to view-source URLs or within ViewSource mode + // must be handled by the browser process. + int cumulative_bindings = + RenderProcess::current()->GetEnabledBindings(); bool should_fork = - (enabled_bindings_ & content::BINDINGS_POLICY_WEB_UI) || - frame->isViewSourceModeEnabled() || - url.SchemeIs(chrome::kViewSourceScheme); + content::GetContentClient()->HasWebUIScheme(url) || + (cumulative_bindings & content::BINDINGS_POLICY_WEB_UI) || + url.SchemeIs(chrome::kViewSourceScheme) || + frame->isViewSourceModeEnabled(); if (!should_fork) { // Give the embedder a chance. - bool is_initial_navigation = page_id_ == -1; - should_fork = content::GetContentClient()->renderer()->ShouldFork( - frame, url, is_initial_navigation, &send_referrer); + // For now, we skip this for POST submissions. This is because + // http://crbug.com/101395 is more likely to cause compatibility issues + // with hosted apps and extensions than WebUI pages. We will remove this + // check when cross-process POST submissions are supported. + if (request.httpMethod() == "GET") { + bool is_initial_navigation = page_id_ == -1; + should_fork = content::GetContentClient()->renderer()->ShouldFork( + frame, url, is_initial_navigation, &send_referrer); + } } if (should_fork) { @@ -4074,6 +4088,9 @@ void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath, void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) { enabled_bindings_ |= enabled_bindings_flags; + + // Keep track of the total bindings accumulated in this process. + RenderProcess::current()->AddBindings(enabled_bindings_flags); } void RenderViewImpl::OnSetWebUIProperty(const std::string& name, diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index a104ebe..50997d3 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -693,6 +693,7 @@ class RenderViewImpl : public RenderWidget, FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange); FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase); FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate); + FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DecideNavigationPolicyForWebUI); FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DontIgnoreBackAfterNavEntryLimit); FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ImeComposition); @@ -778,7 +779,7 @@ class RenderViewImpl : public RenderWidget, // The documentation for these functions should be in // render_messages_internal.h for the message that the function is handling. - void OnAllowBindings(int enabled_bindings_flags); + CONTENT_EXPORT void OnAllowBindings(int enabled_bindings_flags); void OnAllowScriptToClose(bool script_can_close); void OnAsyncFileOpened(base::PlatformFileError error_code, IPC::PlatformFileForTransit file_for_transit, diff --git a/content/shell/shell_content_client.cc b/content/shell/shell_content_client.cc index 5870451..c8ba1eb 100644 --- a/content/shell/shell_content_client.cc +++ b/content/shell/shell_content_client.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -27,6 +27,11 @@ void ShellContentClient::AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) { } +bool ShellContentClient::HasWebUIScheme(const GURL& url) const { + // There are no WebUI URLs in content_shell. + return false; +} + bool ShellContentClient::CanHandleWhileSwappedOut(const IPC::Message& msg) { return false; } diff --git a/content/shell/shell_content_client.h b/content/shell/shell_content_client.h index 21ea340..834bde8 100644 --- a/content/shell/shell_content_client.h +++ b/content/shell/shell_content_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -21,6 +21,7 @@ class ShellContentClient : public ContentClient { std::vector<content::PepperPluginInfo>* plugins) OVERRIDE; virtual void AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) OVERRIDE; + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) OVERRIDE; virtual std::string GetUserAgent(bool* overriding) const OVERRIDE; virtual string16 GetLocalizedString(int message_id) const OVERRIDE; diff --git a/content/test/mock_render_process.cc b/content/test/mock_render_process.cc index 0bce202..3b2d03f 100644 --- a/content/test/mock_render_process.cc +++ b/content/test/mock_render_process.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -8,7 +8,8 @@ #include "ui/gfx/surface/transport_dib.h" MockRenderProcess::MockRenderProcess() - : transport_dib_next_sequence_number_(0) { + : transport_dib_next_sequence_number_(0), + enabled_bindings_(0) { } MockRenderProcess::~MockRenderProcess() { @@ -37,6 +38,14 @@ bool MockRenderProcess::UseInProcessPlugins() const { return true; } +void MockRenderProcess::AddBindings(int bindings) { + enabled_bindings_ |= bindings; +} + +int MockRenderProcess::GetEnabledBindings() const { + return enabled_bindings_; +} + bool MockRenderProcess::HasInitializedMediaLibrary() const { return false; } diff --git a/content/test/mock_render_process.h b/content/test/mock_render_process.h index 589556f..25a66ca 100644 --- a/content/test/mock_render_process.h +++ b/content/test/mock_render_process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -21,10 +21,13 @@ class MockRenderProcess : public RenderProcess { const gfx::Rect& rect) OVERRIDE; virtual void ReleaseTransportDIB(TransportDIB* memory) OVERRIDE; virtual bool UseInProcessPlugins() const OVERRIDE; + virtual void AddBindings(int bindings) OVERRIDE; + virtual int GetEnabledBindings() const OVERRIDE; virtual bool HasInitializedMediaLibrary() const; private: uint32 transport_dib_next_sequence_number_; + int enabled_bindings_; DISALLOW_COPY_AND_ASSIGN(MockRenderProcess); }; diff --git a/content/test/mock_render_thread.cc b/content/test/mock_render_thread.cc index ce74409..b716d04 100644 --- a/content/test/mock_render_thread.cc +++ b/content/test/mock_render_thread.cc @@ -13,7 +13,7 @@ namespace content { MockRenderThread::MockRenderThread() - : routing_id_(0), surface_id_(0), opener_id_(0) { + : routing_id_(0), surface_id_(0), opener_id_(0), new_window_routing_id_(0) { } MockRenderThread::~MockRenderThread() { @@ -73,13 +73,17 @@ IPC::SyncMessageFilter* MockRenderThread::GetSyncMessageFilter() { void MockRenderThread::AddRoute(int32 routing_id, IPC::Channel::Listener* listener) { - EXPECT_EQ(routing_id_, routing_id); - widget_ = listener; + // We may hear this for views created from OnMsgCreateWindow as well, + // in which case we don't want to track the new widget. + if (routing_id_ == routing_id) + widget_ = listener; } void MockRenderThread::RemoveRoute(int32 routing_id) { - EXPECT_EQ(routing_id_, routing_id); - widget_ = NULL; + // We may hear this for views created from OnMsgCreateWindow as well, + // in which case we don't want to track the new widget. + if (routing_id_ == routing_id) + widget_ = NULL; } int MockRenderThread::GenerateRoutingID() { @@ -180,6 +184,17 @@ void MockRenderThread::OnMsgCreateWidget(int opener_id, *surface_id = surface_id_; } +// The View expects to be returned a valid route_id different from its own. +void MockRenderThread::OnMsgCreateWindow( + const ViewHostMsg_CreateWindow_Params& params, + int* route_id, + int* surface_id, + int64* cloned_session_storage_namespace_id) { + *route_id = new_window_routing_id_; + *surface_id = surface_id_; + *cloned_session_storage_namespace_id = 0; +} + bool MockRenderThread::OnMessageReceived(const IPC::Message& msg) { // Save the message in the sink. sink_.OnMessageReceived(msg); @@ -188,6 +203,7 @@ bool MockRenderThread::OnMessageReceived(const IPC::Message& msg) { bool msg_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(MockRenderThread, msg, msg_is_ok) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() return handled; diff --git a/content/test/mock_render_thread.h b/content/test/mock_render_thread.h index d89ea73..120fa16 100644 --- a/content/test/mock_render_thread.h +++ b/content/test/mock_render_thread.h @@ -12,6 +12,8 @@ #include "ipc/ipc_test_sink.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h" +struct ViewHostMsg_CreateWindow_Params; + namespace IPC { class MessageReplyDeserializer; } @@ -19,8 +21,9 @@ class MessageReplyDeserializer; namespace content { // This class is a very simple mock of RenderThread. It simulates an IPC channel -// which supports only two messages: +// which supports only three messages: // ViewHostMsg_CreateWidget : sync message sent by the Widget. +// ViewHostMsg_CreateWindow : sync message sent by the Widget. // ViewMsg_Close : async, send to the Widget. class MockRenderThread : public content::RenderThread { public: @@ -91,6 +94,10 @@ class MockRenderThread : public content::RenderThread { return widget_ ? true : false; } + void set_new_window_routing_id(int32 id) { + new_window_routing_id_ = id; + } + // Simulates the Widget receiving a close message. This should result // on releasing the internal reference counts and destroying the internal // state. @@ -107,6 +114,15 @@ class MockRenderThread : public content::RenderThread { int* route_id, int* surface_id); + // The View expects to be returned a valid route_id different from its own. + // We do not keep track of the newly created widget in MockRenderThread, + // so it must be cleaned up on its own. + void OnMsgCreateWindow( + const ViewHostMsg_CreateWindow_Params& params, + int* route_id, + int* surface_id, + int64* cloned_session_storage_namespace_id); + #if defined(OS_WIN) void OnDuplicateSection(base::SharedMemoryHandle renderer_handle, base::SharedMemoryHandle* browser_handle); @@ -124,9 +140,13 @@ class MockRenderThread : public content::RenderThread { int32 opener_id_; // We only keep track of one Widget, we learn its pointer when it - // adds a new route. + // adds a new route. We do not keep track of Widgets created with + // OnMsgCreateWindow. IPC::Channel::Listener* widget_; + // Routing id that will be assigned to a CreateWindow Widget. + int32 new_window_routing_id_; + // The last known good deserializer for sync messages. scoped_ptr<IPC::MessageReplyDeserializer> reply_deserializer_; }; diff --git a/content/test/render_view_test.cc b/content/test/render_view_test.cc index 4a78be6..d4b22be 100644 --- a/content/test/render_view_test.cc +++ b/content/test/render_view_test.cc @@ -47,6 +47,7 @@ using WebKit::WebURLRequest; namespace { const int32 kOpenerId = 7; const int32 kRouteId = 5; +const int32 kNewWindowRouteId = 6; const int32 kSurfaceId = 42; #if defined(USE_AURA) && defined(USE_X11) @@ -133,6 +134,7 @@ void RenderViewTest::SetUp() { render_thread_.reset(new MockRenderThread()); render_thread_->set_routing_id(kRouteId); render_thread_->set_surface_id(kSurfaceId); + render_thread_->set_new_window_routing_id(kNewWindowRouteId); command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); params_.reset(new content::MainFunctionParams(*command_line_)); diff --git a/content/test/test_content_client.cc b/content/test/test_content_client.cc index fb572ce..455f2e9 100644 --- a/content/test/test_content_client.cc +++ b/content/test/test_content_client.cc @@ -35,6 +35,10 @@ void TestContentClient::AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) { } +bool TestContentClient::HasWebUIScheme(const GURL& url) const { + return false; +} + bool TestContentClient::CanHandleWhileSwappedOut(const IPC::Message& msg) { // TestContentClient does not need to handle any additional messages. return false; diff --git a/content/test/test_content_client.h b/content/test/test_content_client.h index 0ff830f..88df6d9 100644 --- a/content/test/test_content_client.h +++ b/content/test/test_content_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -22,6 +22,7 @@ class TestContentClient : public content::ContentClient { std::vector<content::PepperPluginInfo>* plugins) OVERRIDE; virtual void AddNPAPIPlugins( webkit::npapi::PluginList* plugin_list) OVERRIDE; + virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) OVERRIDE; virtual std::string GetUserAgent(bool* overriding) const OVERRIDE; virtual string16 GetLocalizedString(int message_id) const OVERRIDE; diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc index 08f5717..b132617 100644 --- a/content/test/webrtc_audio_device_test.cc +++ b/content/test/webrtc_audio_device_test.cc @@ -53,6 +53,8 @@ class WebRTCMockRenderProcess : public RenderProcess { } virtual void ReleaseTransportDIB(TransportDIB* memory) {} virtual bool UseInProcessPlugins() const { return false; } + virtual void AddBindings(int bindings) {} + virtual int GetEnabledBindings() const { return 0; } virtual bool HasInitializedMediaLibrary() const { return false; } private: |