| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 14 #include "base/test/histogram_tester.h" |
| 14 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
| 15 #include "chrome/browser/extensions/browser_action_test_util.h" | 16 #include "chrome/browser/extensions/browser_action_test_util.h" |
| 16 #include "chrome/browser/extensions/extension_browsertest.h" | 17 #include "chrome/browser/extensions/extension_browsertest.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 18 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/test_extension_dir.h" | 19 #include "chrome/browser/extensions/test_extension_dir.h" |
| 19 #include "chrome/browser/ui/browser_commands.h" | 20 #include "chrome/browser/ui/browser_commands.h" |
| 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 21 #include "chrome/common/chrome_paths.h" | 22 #include "chrome/common/chrome_paths.h" |
| 22 #include "chrome/common/extensions/extension_process_policy.h" | 23 #include "chrome/common/extensions/extension_process_policy.h" |
| 23 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 IsIsolateExtensionsEnabled() | 247 IsIsolateExtensionsEnabled() |
| 247 ? if_enabled | 248 ? if_enabled |
| 248 : if_disabled; | 249 : if_disabled; |
| 249 } | 250 } |
| 250 | 251 |
| 251 content::WebContents* OpenPopup(content::RenderFrameHost* opener, | 252 content::WebContents* OpenPopup(content::RenderFrameHost* opener, |
| 252 const GURL& url) { | 253 const GURL& url) { |
| 253 content::WindowedNotificationObserver popup_observer( | 254 content::WindowedNotificationObserver popup_observer( |
| 254 chrome::NOTIFICATION_TAB_ADDED, | 255 chrome::NOTIFICATION_TAB_ADDED, |
| 255 content::NotificationService::AllSources()); | 256 content::NotificationService::AllSources()); |
| 256 EXPECT_TRUE(ExecuteScript(opener, "window.open('" + url.spec() + "')")); | 257 EXPECT_TRUE(ExecuteScript( |
| 258 opener, "window.popup = window.open('" + url.spec() + "')")); |
| 257 popup_observer.Wait(); | 259 popup_observer.Wait(); |
| 258 content::WebContents* popup = | 260 content::WebContents* popup = |
| 259 browser()->tab_strip_model()->GetActiveWebContents(); | 261 browser()->tab_strip_model()->GetActiveWebContents(); |
| 260 WaitForLoadStop(popup); | 262 WaitForLoadStop(popup); |
| 261 EXPECT_EQ(url, popup->GetMainFrame()->GetLastCommittedURL()); | 263 EXPECT_EQ(url, popup->GetMainFrame()->GetLastCommittedURL()); |
| 262 return popup; | 264 return popup; |
| 263 } | 265 } |
| 264 | 266 |
| 265 private: | 267 private: |
| 266 guest_view::TestGuestViewManagerFactory factory_; | 268 guest_view::TestGuestViewManagerFactory factory_; |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 EXPECT_TRUE(policy->CanRequestURL( | 729 EXPECT_TRUE(policy->CanRequestURL( |
| 728 main_frame->GetProcess()->GetID(), | 730 main_frame->GetProcess()->GetID(), |
| 729 GURL("filesystem:chrome-extension://some-extension-id/some-path"))); | 731 GURL("filesystem:chrome-extension://some-extension-id/some-path"))); |
| 730 EXPECT_TRUE(policy->CanRequestURL( | 732 EXPECT_TRUE(policy->CanRequestURL( |
| 731 extension_frame->GetProcess()->GetID(), | 733 extension_frame->GetProcess()->GetID(), |
| 732 GURL("chrome-extension://some-extension-id/resource.html"))); | 734 GURL("chrome-extension://some-extension-id/resource.html"))); |
| 733 EXPECT_TRUE(policy->CanRequestURL( | 735 EXPECT_TRUE(policy->CanRequestURL( |
| 734 main_frame->GetProcess()->GetID(), | 736 main_frame->GetProcess()->GetID(), |
| 735 GURL("chrome-extension://some-extension-id/resource.html"))); | 737 GURL("chrome-extension://some-extension-id/resource.html"))); |
| 736 | 738 |
| 737 if (extensions::IsIsolateExtensionsEnabled()) { | 739 if (IsIsolateExtensionsEnabled()) { |
| 738 EXPECT_TRUE(policy->CanCommitURL( | 740 EXPECT_TRUE(policy->CanCommitURL( |
| 739 extension_frame->GetProcess()->GetID(), | 741 extension_frame->GetProcess()->GetID(), |
| 740 GURL("blob:chrome-extension://some-extension-id/some-guid"))); | 742 GURL("blob:chrome-extension://some-extension-id/some-guid"))); |
| 741 EXPECT_FALSE(policy->CanCommitURL( | 743 EXPECT_FALSE(policy->CanCommitURL( |
| 742 main_frame->GetProcess()->GetID(), | 744 main_frame->GetProcess()->GetID(), |
| 743 GURL("blob:chrome-extension://some-extension-id/some-guid"))); | 745 GURL("blob:chrome-extension://some-extension-id/some-guid"))); |
| 744 EXPECT_TRUE(policy->CanCommitURL( | 746 EXPECT_TRUE(policy->CanCommitURL( |
| 745 extension_frame->GetProcess()->GetID(), | 747 extension_frame->GetProcess()->GetID(), |
| 746 GURL("chrome-extension://some-extension-id/resource.html"))); | 748 GURL("chrome-extension://some-extension-id/resource.html"))); |
| 747 EXPECT_FALSE(policy->CanCommitURL( | 749 EXPECT_FALSE(policy->CanCommitURL( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 EXPECT_FALSE(extension_origin.IsSameOriginWith( | 789 EXPECT_FALSE(extension_origin.IsSameOriginWith( |
| 788 popup->GetMainFrame()->GetLastCommittedOrigin())); | 790 popup->GetMainFrame()->GetLastCommittedOrigin())); |
| 789 EXPECT_NE("foo", GetTextContent(popup->GetMainFrame())); | 791 EXPECT_NE("foo", GetTextContent(popup->GetMainFrame())); |
| 790 | 792 |
| 791 EXPECT_EQ(IfExtensionsIsolated(1, 0), | 793 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 792 pm->GetRenderFrameHostsForExtension(extension->id()).size()); | 794 pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 793 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); | 795 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); |
| 794 } | 796 } |
| 795 | 797 |
| 796 // Navigate second subframe to each nested URL from the main frame (i.e., | 798 // Navigate second subframe to each nested URL from the main frame (i.e., |
| 797 // from non-extension process). | 799 // from non-extension process). This should be blocked in |
| 800 // --isolate-extensions, but allowed without --isolate-extensions due to |
| 801 // unblessed extension frames. |
| 798 // | 802 // |
| 799 // TODO(alexmos): Currently, this is still allowed due to unblessed extension | 803 // TODO(alexmos): This is also temporarily allowed under PlzNavigate, because |
| 800 // contexts, but in the future such subframe navigations from non-extension | 804 // currently this particular blocking happens in |
| 801 // processes should be blocked when unblessed contexts go away with | 805 // ChromeContentBrowserClientExtensionsPart::ShouldAllowOpenURL, which isn't |
| 802 // --isolate-extensions. | 806 // triggered below under PlzNavigate (since there'll be no transfer). Once |
| 807 // the blob/filesystem URL checks in ExtensionNavigationThrottle are updated |
| 808 // to apply to all frames and not just main frames, the PlzNavigate exception |
| 809 // below can be removed. See https://crbug.com/661324. |
| 803 for (size_t i = 0; i < arraysize(nested_urls); i++) { | 810 for (size_t i = 0; i < arraysize(nested_urls); i++) { |
| 804 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame2", nested_urls[i])); | 811 EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame2", nested_urls[i])); |
| 805 content::RenderFrameHost* second_frame = ChildFrameAt(main_frame, 1); | 812 content::RenderFrameHost* second_frame = ChildFrameAt(main_frame, 1); |
| 806 EXPECT_EQ(nested_urls[i], second_frame->GetLastCommittedURL()); | 813 if (IsIsolateExtensionsEnabled() && |
| 807 EXPECT_EQ(extension_origin, second_frame->GetLastCommittedOrigin()); | 814 !content::IsBrowserSideNavigationEnabled()) { |
| 808 EXPECT_EQ("foo", GetTextContent(second_frame)); | 815 EXPECT_NE(nested_urls[i], second_frame->GetLastCommittedURL()); |
| 809 EXPECT_EQ(IfExtensionsIsolated(2, 0), | 816 EXPECT_FALSE(extension_origin.IsSameOriginWith( |
| 810 pm->GetRenderFrameHostsForExtension(extension->id()).size()); | 817 second_frame->GetLastCommittedOrigin())); |
| 811 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); | 818 EXPECT_NE("foo", GetTextContent(second_frame)); |
| 819 EXPECT_EQ(IfExtensionsIsolated(1, 0), |
| 820 pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 821 EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); |
| 822 } else { |
| 823 EXPECT_EQ(nested_urls[i], second_frame->GetLastCommittedURL()); |
| 824 EXPECT_EQ(extension_origin, second_frame->GetLastCommittedOrigin()); |
| 825 EXPECT_EQ("foo", GetTextContent(second_frame)); |
| 826 EXPECT_EQ(IfExtensionsIsolated(2, 0), |
| 827 pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 828 EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); |
| 829 } |
| 830 EXPECT_TRUE( |
| 831 content::NavigateIframeToURL(tab, "frame2", GURL(url::kAboutBlankURL))); |
| 812 } | 832 } |
| 813 } | 833 } |
| 814 | 834 |
| 815 // Test that navigations to blob: and filesystem: URLs with extension origins | 835 // Test that navigations to blob: and filesystem: URLs with extension origins |
| 816 // are allowed when initiated from extension processes. See | 836 // are allowed when initiated from extension processes. See |
| 817 // https://crbug.com/645028 and https://crbug.com/644426. | 837 // https://crbug.com/645028 and https://crbug.com/644426. |
| 818 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, | 838 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
| 819 NestedURLNavigationsToExtensionAllowed) { | 839 NestedURLNavigationsToExtensionAllowed) { |
| 820 // Create a simple extension without a background page. | 840 // Create a simple extension without a background page. |
| 821 const Extension* extension = CreateExtension("Extension", false); | 841 const Extension* extension = CreateExtension("Extension", false); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 EXPECT_FALSE(app_origin.IsSameOriginWith( | 989 EXPECT_FALSE(app_origin.IsSameOriginWith( |
| 970 web_tab->GetMainFrame()->GetLastCommittedOrigin())); | 990 web_tab->GetMainFrame()->GetLastCommittedOrigin())); |
| 971 EXPECT_NE("foo", GetTextContent(web_tab->GetMainFrame())); | 991 EXPECT_NE("foo", GetTextContent(web_tab->GetMainFrame())); |
| 972 EXPECT_NE(web_tab->GetMainFrame()->GetProcess(), app_rfh->GetProcess()); | 992 EXPECT_NE(web_tab->GetMainFrame()->GetProcess(), app_rfh->GetProcess()); |
| 973 | 993 |
| 974 EXPECT_EQ(2u, pm->GetAllFrames().size()); | 994 EXPECT_EQ(2u, pm->GetAllFrames().size()); |
| 975 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(app->id()).size()); | 995 EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(app->id()).size()); |
| 976 } | 996 } |
| 977 } | 997 } |
| 978 | 998 |
| 999 // Test that a web frame can't navigate a proxy for an extension frame to a |
| 1000 // blob/filesystem extension URL. See https://crbug.com/656752. |
| 1001 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
| 1002 NestedURLNavigationsViaProxyBlocked) { |
| 1003 base::HistogramTester uma; |
| 1004 // Create a simple extension without a background page. |
| 1005 const Extension* extension = CreateExtension("Extension", false); |
| 1006 embedded_test_server()->ServeFilesFromDirectory(extension->path()); |
| 1007 ASSERT_TRUE(embedded_test_server()->Start()); |
| 1008 |
| 1009 // Navigate main tab to an empty web page. There should be no extension |
| 1010 // frames yet. |
| 1011 NavigateToURL(embedded_test_server()->GetURL("/empty.html")); |
| 1012 ProcessManager* pm = ProcessManager::Get(profile()); |
| 1013 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 1014 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 1015 |
| 1016 content::WebContents* tab = |
| 1017 browser()->tab_strip_model()->GetActiveWebContents(); |
| 1018 content::RenderFrameHost* main_frame = tab->GetMainFrame(); |
| 1019 |
| 1020 // Open a new about:blank popup from main frame. This should stay in the web |
| 1021 // process. |
| 1022 content::WebContents* popup = |
| 1023 OpenPopup(main_frame, GURL(url::kAboutBlankURL)); |
| 1024 EXPECT_NE(popup, tab); |
| 1025 ASSERT_EQ(2, browser()->tab_strip_model()->count()); |
| 1026 EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 1027 EXPECT_EQ(0u, pm->GetAllFrames().size()); |
| 1028 |
| 1029 // Navigate popup to an extension page. |
| 1030 const GURL extension_url(extension->url().Resolve("empty.html")); |
| 1031 content::TestNavigationObserver observer(popup); |
| 1032 EXPECT_TRUE( |
| 1033 ExecuteScript(popup, "location.href = '" + extension_url.spec() + "';")); |
| 1034 observer.Wait(); |
| 1035 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 1036 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 1037 content::RenderFrameHost* extension_frame = popup->GetMainFrame(); |
| 1038 |
| 1039 // Create valid blob and filesystem URLs in the extension's origin. |
| 1040 url::Origin extension_origin(extension_frame->GetLastCommittedOrigin()); |
| 1041 GURL blob_url(CreateBlobURL(extension_frame, "foo")); |
| 1042 EXPECT_EQ(extension_origin, url::Origin(blob_url)); |
| 1043 GURL filesystem_url(CreateFileSystemURL(extension_frame, "foo")); |
| 1044 EXPECT_EQ(extension_origin, url::Origin(filesystem_url)); |
| 1045 |
| 1046 // Have the web page navigate the popup to each nested URL with extension |
| 1047 // origin via the window reference it obtained earlier from window.open. |
| 1048 GURL nested_urls[] = {blob_url, filesystem_url}; |
| 1049 for (size_t i = 0; i < arraysize(nested_urls); i++) { |
| 1050 EXPECT_TRUE(ExecuteScript( |
| 1051 tab, "window.popup.location.href = '" + nested_urls[i].spec() + "';")); |
| 1052 WaitForLoadStop(popup); |
| 1053 |
| 1054 // This is a top-level navigation that should be blocked since it |
| 1055 // originates from a non-extension process. Ensure that the popup stays at |
| 1056 // the original page and doesn't navigate to the nested URL. |
| 1057 EXPECT_NE(nested_urls[i], popup->GetLastCommittedURL()); |
| 1058 EXPECT_NE("foo", GetTextContent(popup->GetMainFrame())); |
| 1059 |
| 1060 EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); |
| 1061 EXPECT_EQ(1u, pm->GetAllFrames().size()); |
| 1062 } |
| 1063 |
| 1064 // Verify that the blocking was recorded correctly in UMA. |
| 1065 uma.ExpectTotalCount("Extensions.ShouldAllowOpenURL.Failure", 2); |
| 1066 uma.ExpectBucketCount("Extensions.ShouldAllowOpenURL.Failure", |
| 1067 0 /* FAILURE_FILE_SYSTEM_URL */, 1); |
| 1068 uma.ExpectBucketCount("Extensions.ShouldAllowOpenURL.Failure", |
| 1069 1 /* FAILURE_BLOB_URL */, 1); |
| 1070 } |
| 1071 |
| 979 // Verify that a web popup created via window.open from an extension page can | 1072 // Verify that a web popup created via window.open from an extension page can |
| 980 // communicate with the extension page via window.opener. See | 1073 // communicate with the extension page via window.opener. See |
| 981 // https://crbug.com/590068. | 1074 // https://crbug.com/590068. |
| 982 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, | 1075 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
| 983 WebPopupFromExtensionMainFrameHasValidOpener) { | 1076 WebPopupFromExtensionMainFrameHasValidOpener) { |
| 984 // Create a simple extension without a background page. | 1077 // Create a simple extension without a background page. |
| 985 const Extension* extension = CreateExtension("Extension", false); | 1078 const Extension* extension = CreateExtension("Extension", false); |
| 986 embedded_test_server()->ServeFilesFromDirectory(extension->path()); | 1079 embedded_test_server()->ServeFilesFromDirectory(extension->path()); |
| 987 ASSERT_TRUE(embedded_test_server()->Start()); | 1080 ASSERT_TRUE(embedded_test_server()->Start()); |
| 988 | 1081 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 EXPECT_TRUE(ExecuteScriptAndExtractBool( | 1156 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| 1064 popup, "window.domAutomationController.send(!!window.opener)", | 1157 popup, "window.domAutomationController.send(!!window.opener)", |
| 1065 &is_opener_defined)); | 1158 &is_opener_defined)); |
| 1066 EXPECT_TRUE(is_opener_defined); | 1159 EXPECT_TRUE(is_opener_defined); |
| 1067 | 1160 |
| 1068 // Verify that postMessage to window.opener works. | 1161 // Verify that postMessage to window.opener works. |
| 1069 VerifyPostMessageToOpener(popup->GetMainFrame(), extension_frame); | 1162 VerifyPostMessageToOpener(popup->GetMainFrame(), extension_frame); |
| 1070 } | 1163 } |
| 1071 | 1164 |
| 1072 } // namespace extensions | 1165 } // namespace extensions |
| OLD | NEW |