summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromium/content/browser/site_instance_impl.cc22
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc50
2 files changed, 71 insertions, 1 deletions
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index d5f3fcc1424..f4584ea8c32 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -427,10 +427,30 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
// This is useful for cases like file URLs.
if (!origin.unique()) {
// Prefer to use the scheme of |origin| rather than |url|, to correctly
- // cover blob: and filesystem: URIs (see also https://crbug.com/697111).
+ // cover blob:file: and filesystem:file: URIs (see also
+ // https://crbug.com/697111).
DCHECK(!origin.scheme().empty());
return GURL(origin.scheme() + ":");
} else if (url.has_scheme()) {
+ // In some cases, it is not safe to use just the scheme as a site URL, as
+ // that might allow two URLs created by different sites to to share a
+ // process. See https://crbug.com/863623.
+ //
+ // TODO(alexmos,creis): This should eventually be expanded to certain other
+ // schemes, such as data: and file:.
+ if (url.SchemeIsBlob()) {
+ // We get here for blob URLs of form blob:null/guid. Use the full URL
+ // with the guid in that case, which isolates all blob URLs with unique
+ // origins from each other. Remove hash from the URL, since
+ // same-document navigations shouldn't use a different site URL.
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
+ }
+ return url;
+ }
+
DCHECK(!url.scheme().empty());
return GURL(url.scheme() + ":");
}
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 92bff576b82..c4095dce2ec 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -13800,4 +13800,54 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
popup_subframe->current_frame_host()->GetSiteInstance()->GetSiteURL());
}
+// Ensure that when two cross-site frames have subframes with unique origins,
+// and those subframes create blob URLs and navigate to them, the blob URLs end
+// up in different processes. See https://crbug.com/863623.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ TwoBlobURLsWithNullOriginDontShareProcess) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/navigation_controller/page_with_data_iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* subframe = root->child_at(0);
+
+ // Create a blob URL in the subframe, and navigate to it.
+ TestNavigationObserver observer(shell()->web_contents());
+ std::string blob_script =
+ "var blob = new Blob(['foo'], {type : 'text/html'});"
+ "var url = URL.createObjectURL(blob);"
+ "location = url;";
+ EXPECT_TRUE(ExecuteScript(subframe, blob_script));
+ observer.Wait();
+ RenderFrameHostImpl* subframe_rfh = subframe->current_frame_host();
+ EXPECT_TRUE(subframe_rfh->GetLastCommittedURL().SchemeIsBlob());
+
+ // Open a cross-site popup and repeat these steps.
+ GURL popup_url(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/page_with_data_iframe.html"));
+ Shell* new_shell = OpenPopup(root, popup_url, "");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* popup_subframe = popup_root->child_at(0);
+
+ TestNavigationObserver popup_observer(new_shell->web_contents());
+ EXPECT_TRUE(ExecuteScript(popup_subframe, blob_script));
+ popup_observer.Wait();
+ RenderFrameHostImpl* popup_subframe_rfh =
+ popup_subframe->current_frame_host();
+ EXPECT_TRUE(popup_subframe_rfh->GetLastCommittedURL().SchemeIsBlob());
+
+ // Ensure that the two blob subframes don't share a process or SiteInstance.
+ EXPECT_NE(subframe->current_frame_host()->GetSiteInstance(),
+ popup_subframe->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(
+ subframe->current_frame_host()->GetSiteInstance()->GetProcess(),
+ popup_subframe->current_frame_host()->GetSiteInstance()->GetProcess());
+ EXPECT_NE(
+ subframe->current_frame_host()->GetSiteInstance()->GetSiteURL(),
+ popup_subframe->current_frame_host()->GetSiteInstance()->GetSiteURL());
+}
+
} // namespace content