summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 17:10:26 +0000
committercreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 17:10:26 +0000
commit58436a1770176ece2c02b28a57bba2a89db5d58b (patch)
treefdc8965e47e515b0d39d98f05f0280fefc7456a3 /content
parent8f8167ed2bd7ef7c76ed7d7b5f21bae175da5953 (diff)
downloadchromium_src-58436a1770176ece2c02b28a57bba2a89db5d58b.zip
chromium_src-58436a1770176ece2c02b28a57bba2a89db5d58b.tar.gz
chromium_src-58436a1770176ece2c02b28a57bba2a89db5d58b.tar.bz2
Use a new scheme for swapping out RenderViews.
BUG=118664 TEST=none Review URL: http://codereview.chromium.org/9720004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/render_view_host_manager_browsertest.cc78
-rw-r--r--content/public/common/url_constants.cc6
-rw-r--r--content/public/common/url_constants.h3
-rw-r--r--content/renderer/render_thread_impl.cc14
-rw-r--r--content/renderer/render_thread_impl.h4
-rw-r--r--content/renderer/render_view_impl.cc17
-rw-r--r--content/test/render_view_test.cc5
7 files changed, 119 insertions, 8 deletions
diff --git a/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
index 79a9032..fe220b2 100644
--- a/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
@@ -42,6 +42,84 @@ class RenderViewHostManagerTest : public InProcessBrowserTest {
}
};
+// Web pages should not have script access to the swapped out page.
+IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, NoScriptAccessAfterSwapOut) {
+ // Start two servers with different sites.
+ ASSERT_TRUE(test_server()->Start());
+ net::TestServer https_server(
+ net::TestServer::TYPE_HTTPS,
+ net::TestServer::kLocalhost,
+ FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+ ASSERT_TRUE(https_server.Start());
+
+ // Load a page with links that open in a new window.
+ std::string replacement_path;
+ ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+ "files/click-noreferrer-links.html",
+ https_server.host_port_pair(),
+ &replacement_path));
+ ui_test_utils::NavigateToURL(browser(),
+ test_server()->GetURL(replacement_path));
+
+ // Get the original SiteInstance for later comparison.
+ scoped_refptr<SiteInstance> orig_site_instance(
+ browser()->GetSelectedWebContents()->GetSiteInstance());
+ EXPECT_TRUE(orig_site_instance != NULL);
+
+ // Open a same-site link in a new tab.
+ ui_test_utils::WindowedNotificationObserver new_tab_observer(
+ content::NOTIFICATION_TAB_ADDED,
+ content::Source<content::WebContentsDelegate>(browser()));
+ bool success = false;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedWebContents()->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(clickSameSiteTargetedLink());",
+ &success));
+ EXPECT_TRUE(success);
+ new_tab_observer.Wait();
+
+ // Opens in new tab.
+ EXPECT_EQ(2, browser()->tab_count());
+ EXPECT_EQ(1, browser()->active_index());
+
+ // Wait for the navigation in the new tab to finish, if it hasn't.
+ ui_test_utils::WaitForLoadStop(browser()->GetSelectedWebContents());
+ EXPECT_EQ("/files/title2.html",
+ browser()->GetSelectedWebContents()->GetURL().path());
+ EXPECT_EQ(1, browser()->active_index());
+
+ // Should have the same SiteInstance.
+ scoped_refptr<SiteInstance> blank_site_instance(
+ browser()->GetSelectedWebContents()->GetSiteInstance());
+ EXPECT_EQ(orig_site_instance, blank_site_instance);
+
+ // We should have access to the opened tab's location.
+ browser()->ActivateTabAt(0, true);
+ success = false;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedWebContents()->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(testScriptAccessToWindow());",
+ &success));
+ EXPECT_TRUE(success);
+
+ // Now navigate the new tab to a different site.
+ browser()->ActivateTabAt(1, true);
+ ui_test_utils::NavigateToURL(browser(),
+ https_server.GetURL("files/title1.html"));
+ scoped_refptr<SiteInstance> new_site_instance(
+ browser()->GetSelectedWebContents()->GetSiteInstance());
+ EXPECT_NE(orig_site_instance, new_site_instance);
+
+ // We should no longer have script access to the opened tab's location.
+ browser()->ActivateTabAt(0, true);
+ success = false;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedWebContents()->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(testScriptAccessToWindow());",
+ &success));
+ EXPECT_FALSE(success);
+}
+
// Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
// and target=_blank should create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index ee82d1e..49f9711 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -39,6 +39,7 @@ const char kHttpsScheme[] = "https";
const char kJavaScriptScheme[] = "javascript";
const char kMailToScheme[] = "mailto";
const char kMetadataScheme[] = "metadata";
+const char kSwappedOutScheme[] = "swappedout";
const char kViewSourceScheme[] = "view-source";
const char kStandardSchemeSeparator[] = "://";
@@ -57,6 +58,11 @@ const char kChromeUIShorthangURL[] = "chrome://shorthang";
// have a chrome:// scheme that might let it be confused with a WebUI page.
const char kUnreachableWebDataURL[] = "data:text/html,chromewebdata";
+// This URL is loaded when a page is swapped out and replaced by a page in a
+// different renderer process. It must have a unique origin that cannot be
+// scripted by other pages in the process.
+const char kSwappedOutURL[] = "swappedout://";
+
} // namespace chrome
namespace content {
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 0470195..2df75c8 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -31,6 +31,7 @@ CONTENT_EXPORT extern const char kHttpsScheme[];
CONTENT_EXPORT extern const char kJavaScriptScheme[];
CONTENT_EXPORT extern const char kMailToScheme[];
CONTENT_EXPORT extern const char kMetadataScheme[];
+CONTENT_EXPORT extern const char kSwappedOutScheme[];
CONTENT_EXPORT extern const char kViewSourceScheme[];
// Used to separate a standard scheme and the hostname: "://".
@@ -50,6 +51,8 @@ CONTENT_EXPORT extern const char kChromeUIShorthangURL[];
// Special URL used to start a navigation to an error page.
extern const char kUnreachableWebDataURL[];
+// Special URL used to swap out a view being rendered by another process.
+extern const char kSwappedOutURL[];
} // namespace chrome
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index a7277f8..19905c6 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -20,6 +20,7 @@
#include "base/shared_memory.h"
#include "base/string_number_conversions.h" // Temporary
#include "base/threading/thread_local.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/win/scoped_com_initializer.h"
#include "content/common/appcache/appcache_dispatcher.h"
@@ -41,6 +42,7 @@
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/renderer_preferences.h"
+#include "content/public/common/url_constants.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_process_observer.h"
#include "content/public/renderer/render_view_visitor.h"
@@ -72,6 +74,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageEventDispatcher.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
@@ -100,6 +103,7 @@ using WebKit::WebFrame;
using WebKit::WebNetworkStateNotifier;
using WebKit::WebRuntimeFeatures;
using WebKit::WebScriptController;
+using WebKit::WebSecurityPolicy;
using WebKit::WebString;
using WebKit::WebStorageEventDispatcher;
using WebKit::WebView;
@@ -470,6 +474,8 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
WebScriptController::enableV8SingleThreadMode();
+ RenderThreadImpl::RegisterSchemes();
+
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
webkit_glue::EnableWebCoreLogChannels(
@@ -586,6 +592,14 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
}
}
+void RenderThreadImpl::RegisterSchemes() {
+ // swappedout: pages should not be accessible, and should also
+ // be treated as empty documents that can commit synchronously.
+ WebString swappedout_scheme(ASCIIToUTF16(chrome::kSwappedOutScheme));
+ WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(swappedout_scheme);
+ WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme);
+}
+
void RenderThreadImpl::RecordUserMetrics(const std::string& action) {
Send(new ViewHostMsg_UserMetricsRecordAction(action));
}
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 4b24657..df6bf55 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -86,6 +86,10 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread,
// execution context (corresponding to WebFrame::frameForCurrentContext).
static int32 RoutingIDForCurrentContext();
+ // When initializing WebKit, ensure that any schemes needed for the content
+ // module are registered properly. Static to allow sharing with tests.
+ static void RegisterSchemes();
+
// content::RenderThread implementation:
virtual bool Send(IPC::Message* msg) OVERRIDE;
virtual MessageLoop* GetMessageLoop() OVERRIDE;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 18c5238..7cc0a21 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -2247,10 +2247,10 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
if (is_swapped_out_) {
// It is possible for in-progress navigations to arrive here just after we
// are swapped out, including iframes. We should cancel them.
- if (request.url() != GURL("about:swappedout"))
+ if (request.url() != GURL(chrome::kSwappedOutURL))
return WebKit::WebNavigationPolicyIgnore;
- // Allow about:swappedout to complete.
+ // Allow chrome::kSwappedOutURL to complete.
return default_policy;
}
@@ -2781,13 +2781,13 @@ void RenderViewImpl::didCommitProvisionalLoad(WebFrame* frame,
// We bump our Page ID to correspond with the new session history entry.
page_id_ = next_page_id_++;
- // Don't update history_page_ids_ (etc) for about:swappedout, since we
- // don't want to forget the entry that was there, and since we will
- // never come back to about:swappedout. Note that we have to call
+ // Don't update history_page_ids_ (etc) for chrome::kSwappedOutURL, since
+ // we don't want to forget the entry that was there, and since we will
+ // never come back to chrome::kSwappedOutURL. Note that we have to call
// UpdateSessionHistory and update page_id_ even in this case, so that
// the current entry gets a state update and so that we don't send a
// state update to the wrong entry when we swap back in.
- if (GetLoadingUrl(frame) != GURL("about:swappedout")) {
+ if (GetLoadingUrl(frame) != GURL(chrome::kSwappedOutURL)) {
// Advance our offset in session history, applying the length limit.
// There is now no forward history.
history_list_offset_++;
@@ -4378,11 +4378,12 @@ void RenderViewImpl::OnSwapOut(const ViewMsg_SwapOut_Params& params) {
// run a second time, thanks to a check in FrameLoader::stopLoading.
// We use loadRequest instead of loadHTMLString because the former commits
// synchronously. Otherwise a new navigation can interrupt the navigation
- // to about:swappedout. If that happens to be to the page we had been
+ // to chrome::kSwappedOutURL. If that happens to be to the page we had been
// showing, then WebKit will never send a commit and we'll be left spinning.
// TODO(creis): Need to add a better way to do this that avoids running the
// beforeunload handler. For now, we just run it a second time silently.
- WebURLRequest request(GURL("about:swappedout"));
+ GURL swappedOutURL(chrome::kSwappedOutURL);
+ WebURLRequest request(swappedOutURL);
webview()->mainFrame()->loadRequest(request);
}
diff --git a/content/test/render_view_test.cc b/content/test/render_view_test.cc
index db3d3f4..e52b157 100644
--- a/content/test/render_view_test.cc
+++ b/content/test/render_view_test.cc
@@ -8,6 +8,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/common/renderer_preferences.h"
+#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_main_platform_delegate.h"
#include "content/test/mock_render_process.h"
@@ -146,6 +147,10 @@ void RenderViewTest::SetUp() {
webkit_glue::SetJavaScriptFlags(" --expose-gc");
WebKit::initialize(&webkit_platform_support_);
+ // Ensure that we register any necessary schemes when initializing WebKit,
+ // since we are using a MockRenderThread.
+ RenderThreadImpl::RegisterSchemes();
+
mock_process_.reset(new MockRenderProcess);
// This needs to pass the mock render thread to the view.