Chromium Code Reviews| Index: chrome/browser/extensions/process_manager_browsertest.cc |
| diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc |
| index 620e8779287d4b74d0820bb886b279f39f69cd43..4eb01637969e0c40940c1723ab6892c13bacad31 100644 |
| --- a/chrome/browser/extensions/process_manager_browsertest.cc |
| +++ b/chrome/browser/extensions/process_manager_browsertest.cc |
| @@ -9,25 +9,33 @@ |
| #include "base/callback.h" |
| #include "base/macros.h" |
| +#include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "chrome/browser/extensions/browser_action_test_util.h" |
| #include "chrome/browser/extensions/extension_browsertest.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/test_extension_dir.h" |
| +#include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/common/chrome_paths.h" |
| #include "chrome/common/extensions/extension_process_policy.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| +#include "components/guest_view/browser/test_guest_view_manager.h" |
| #include "content/public/browser/child_process_security_policy.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/common/browser_side_navigation_policy.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "content/public/test/test_utils.h" |
| +#include "extensions/browser/app_window/app_window.h" |
| +#include "extensions/browser/app_window/app_window_registry.h" |
| #include "extensions/browser/process_manager.h" |
| +#include "extensions/common/permissions/permissions_data.h" |
| #include "extensions/common/value_builder.h" |
| #include "extensions/test/background_page_watcher.h" |
| #include "net/dns/mock_host_resolver.h" |
| @@ -862,6 +870,96 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
| } |
| } |
| +// Test that navigations to blob: and filesystem: URLs with extension origins |
| +// are disallowed in an unprivileged, non-guest web process when the extension |
| +// origin corresponds to a Chrome app with the "webview" permission. See |
| +// https://crbug.com/656752. These requests should still be allowed inside |
| +// actual <webview> guest processes created by a Chrome app; this is checked in |
| +// WebViewTest.Shim_TestBlobURL. |
|
asargent_no_longer_on_chrome
2016/10/20 22:14:25
Maybe I'm missing something, but does this test ac
alexmos
2016/10/21 00:49:59
This test reuses a lot of functionality from the t
asargent_no_longer_on_chrome
2016/10/21 17:33:17
Ok, sounds good.
|
| +IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, |
| + NestedURLNavigationsToAppBlocked) { |
| + // TODO(alexmos): Re-enable this test for PlzNavigate after tightening |
| + // nested URL blocking for apps with the "webview" permission in |
| + // ExtensionNavigationThrottle and removing the corresponding check from |
| + // ChromeExtensionsNetworkDelegate. The latter is incompatible with |
| + // PlzNavigate. |
| + if (content::IsBrowserSideNavigationEnabled()) |
| + return; |
| + |
| + // Disabling web security is necessary to test the browser enforcement; |
| + // without it, the loads in this test would be blocked by |
| + // SecurityOrigin::canDisplay() as invalid local resource loads. |
| + PrefService* prefs = browser()->profile()->GetPrefs(); |
| + prefs->SetBoolean(prefs::kWebKitWebSecurityEnabled, false); |
| + |
| + // Load a simple app that has the "webview" permission. The app will also |
| + // open a <webview> when it's loaded. |
| + ASSERT_TRUE(embedded_test_server()->Start()); |
| + base::FilePath dir; |
| + PathService::Get(chrome::DIR_TEST_DATA, &dir); |
| + dir = dir.AppendASCII("extensions") |
| + .AppendASCII("platform_apps") |
| + .AppendASCII("web_view") |
| + .AppendASCII("simple"); |
| + const Extension* app = LoadAndLaunchApp(dir); |
| + EXPECT_TRUE(app->permissions_data()->HasAPIPermission( |
| + extensions::APIPermission::kWebView)); |
| + |
| + auto app_windows = AppWindowRegistry::Get(browser()->profile()) |
| + ->GetAppWindowsForApp(app->id()); |
| + EXPECT_EQ(1u, app_windows.size()); |
| + content::WebContents* app_tab = (*app_windows.begin())->web_contents(); |
| + content::RenderFrameHost* app_rfh = app_tab->GetMainFrame(); |
| + url::Origin app_origin(app_rfh->GetLastCommittedOrigin()); |
| + EXPECT_EQ(url::Origin(app->url()), app_rfh->GetLastCommittedOrigin()); |
| + |
| + // Wait for the app's guest WebContents to load. |
| + guest_view::TestGuestViewManager* guest_manager = |
| + static_cast<guest_view::TestGuestViewManager*>( |
| + guest_view::TestGuestViewManager::FromBrowserContext( |
| + browser()->profile())); |
| + content::WebContents* guest = guest_manager->WaitForSingleGuestCreated(); |
| + |
| + // Create valid blob and filesystem URLs in the app's origin. |
| + GURL blob_url(CreateBlobURL(app_rfh, "foo")); |
| + EXPECT_EQ(app_origin, url::Origin(blob_url)); |
| + GURL filesystem_url(CreateFileSystemURL(app_rfh, "foo")); |
| + EXPECT_EQ(app_origin, url::Origin(filesystem_url)); |
| + |
| + // Create a new tab, unrelated to the app, and navigate it to a web URL. |
| + chrome::NewTab(browser()); |
| + content::WebContents* web_tab = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + GURL web_url(embedded_test_server()->GetURL("/title1.html")); |
| + ui_test_utils::NavigateToURL(browser(), web_url); |
| + EXPECT_NE(web_tab, app_tab); |
| + EXPECT_NE(web_tab->GetMainFrame()->GetProcess(), app_rfh->GetProcess()); |
| + |
| + // The web process shouldn't have permission to request URLs in the app's |
| + // origin, but the guest process should. |
| + content::ChildProcessSecurityPolicy* policy = |
| + content::ChildProcessSecurityPolicy::GetInstance(); |
| + EXPECT_FALSE(policy->HasSpecificPermissionForOrigin( |
| + web_tab->GetRenderProcessHost()->GetID(), app_origin)); |
| + EXPECT_TRUE(policy->HasSpecificPermissionForOrigin( |
| + guest->GetRenderProcessHost()->GetID(), app_origin)); |
| + |
| + // Try navigating the web tab to each nested URL with the app's origin. This |
| + // should be blocked. |
| + GURL nested_urls[] = {blob_url, filesystem_url}; |
| + for (size_t i = 0; i < arraysize(nested_urls); i++) { |
| + content::TestNavigationObserver observer(web_tab); |
| + EXPECT_TRUE(ExecuteScript( |
| + web_tab, "location.href = '" + nested_urls[i].spec() + "';")); |
| + observer.Wait(); |
| + EXPECT_NE(nested_urls[i], web_tab->GetLastCommittedURL()); |
| + EXPECT_FALSE(app_origin.IsSameOriginWith( |
| + web_tab->GetMainFrame()->GetLastCommittedOrigin())); |
| + EXPECT_NE("foo", GetTextContent(web_tab->GetMainFrame())); |
| + EXPECT_NE(web_tab->GetMainFrame()->GetProcess(), app_rfh->GetProcess()); |
| + } |
| +} |
| + |
| // Verify that a web popup created via window.open from an extension page can |
| // communicate with the extension page via window.opener. See |
| // https://crbug.com/590068. |