diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc index 84d13a1e7265e..adb3af782cee5 100644 --- a/content/browser/service_worker/service_worker_client_utils.cc +++ b/content/browser/service_worker/service_worker_client_utils.cc @@ -285,8 +285,21 @@ void NavigateClientOnUI(const GURL& url, return; } - int frame_tree_node_id = rfhi->frame_tree_node()->frame_tree_node_id(); + // Reject the navigate() call if there is an ongoing browser-initiated + // navigation. Not rejecting it would allow websites to prevent the user from + // navigating away. See https://crbug.com/930154. + NavigationRequest* ongoing_navigation_request = + rfhi->frame_tree_node()->frame_tree()->root()->navigation_request(); + if (ongoing_navigation_request && + ongoing_navigation_request->browser_initiated()) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(std::move(callback), ChildProcessHost::kInvalidUniqueID, + MSG_ROUTING_NONE)); + return; + } + int frame_tree_node_id = rfhi->frame_tree_node()->frame_tree_node_id(); Navigator* navigator = rfhi->frame_tree_node()->navigator(); navigator->RequestOpenURL( rfhi, url, url::Origin::Create(script_url), false /* uses_post */, diff --git a/content/browser/service_worker/service_worker_clients_api_browsertest.cc b/content/browser/service_worker/service_worker_clients_api_browsertest.cc index 02029fe4100c8..e24d7bd1558d2 100644 --- a/content/browser/service_worker/service_worker_clients_api_browsertest.cc +++ b/content/browser/service_worker/service_worker_clients_api_browsertest.cc @@ -258,6 +258,36 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerClientsApiBrowserTest, EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); } +// Tests a WindowClient.navigate() call during a browser-initiated navigation. +// Regression test for https://crbug.com/930154. +IN_PROC_BROWSER_TEST_F(ServiceWorkerClientsApiBrowserTest, + NavigateDuringBrowserNavigation) { + // Load a page that registers a service worker. + EXPECT_TRUE(NavigateToURL(shell(), + embedded_test_server()->GetURL( + "/service_worker/create_service_worker.html"))); + EXPECT_EQ("DONE", EvalJs(shell(), "register('client_api_worker.js');")); + + // Load the test page. + EXPECT_TRUE(NavigateToURL( + shell(), + embedded_test_server()->GetURL("/service_worker/request_navigate.html"))); + + // Start a browser-initiated navigation. + GURL url(embedded_test_server()->GetURL("/title1.html")); + TestNavigationManager navigation(shell()->web_contents(), url); + shell()->LoadURL(url); + EXPECT_TRUE(navigation.WaitForRequestStart()); + + // Have the service worker call client.navigate() to try to go to another + // URL. It should fail. + EXPECT_EQ("navigate failed", EvalJs(shell(), "requestToNavigate();")); + + // The browser-initiated navigation should finish. + navigation.WaitForNavigationFinished(); // Resume navigation. + EXPECT_TRUE(navigation.was_successful()); +} + // Tests a successful Clients.openWindow() call. IN_PROC_BROWSER_TEST_F(ServiceWorkerClientsApiBrowserTest, OpenWindow) { ActivatedServiceWorkerObserver observer; diff --git a/content/test/data/service_worker/client_api_worker.js b/content/test/data/service_worker/client_api_worker.js index 9127c181fc078..12cfeb2d6e187 100644 --- a/content/test/data/service_worker/client_api_worker.js +++ b/content/test/data/service_worker/client_api_worker.js @@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -self.addEventListener('message', event => { +self.addEventListener('message', async (event) => { if (event.data.command == 'navigate') { const url = event.data.url; - event.source.navigate(url); + try { + await event.source.navigate(url); + } catch (err) { + event.source.postMessage('navigate failed'); + } } }); diff --git a/content/test/data/service_worker/request_navigate.html b/content/test/data/service_worker/request_navigate.html new file mode 100644 index 0000000000000..c7a097abe8e59 --- /dev/null +++ b/content/test/data/service_worker/request_navigate.html @@ -0,0 +1,17 @@ + + +Request navigate +