blob: 2aca979fbb5f11346287fc7a1132452071b3c548 [file] [log] [blame]
Chong Zhangc583e672017-11-08 16:34:081// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Sebastien Marchandf8cbfab2019-01-25 16:02:305#include "base/bind.h"
Makoto Shimazu2075b0d2018-09-21 09:04:226#include "base/callback.h"
7#include "base/run_loop.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:148#include "base/test/bind_test_util.h"
Chong Zhangc583e672017-11-08 16:34:089#include "base/test/scoped_feature_list.h"
Chong Zhang53047762018-05-02 21:24:0810#include "base/test/test_timeouts.h"
John Abd-El-Maleka7289152018-02-17 00:16:1911#include "base/threading/thread_restrictions.h"
Chong Zhangc583e672017-11-08 16:34:0812#include "build/build_config.h"
Chong Zhang7306b0b2018-01-24 05:59:2413#include "content/browser/frame_host/render_frame_host_impl.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:1414#include "content/browser/frame_host/render_frame_message_filter.h"
John Abd-El-Malek984dc002019-05-29 01:26:5915#include "content/browser/network_service_instance_impl.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:1416#include "content/browser/renderer_host/render_process_host_impl.h"
Makoto Shimazu2075b0d2018-09-21 09:04:2217#include "content/browser/service_worker/embedded_worker_instance.h"
18#include "content/browser/service_worker/embedded_worker_status.h"
19#include "content/browser/service_worker/service_worker_context_core_observer.h"
Chong Zhang5f468272017-12-07 23:59:1420#include "content/browser/storage_partition_impl.h"
Chong Zhangd4c923642018-01-03 21:22:2921#include "content/browser/url_loader_factory_getter.h"
Chong Zhang5f468272017-12-07 23:59:1422#include "content/public/browser/browser_context.h"
Gabriel Charette790754c2018-03-16 21:32:5923#include "content/public/browser/browser_thread.h"
Chong Zhangc583e672017-11-08 16:34:0824#include "content/public/browser/network_service_instance.h"
Chong Zhang5f468272017-12-07 23:59:1425#include "content/public/browser/web_contents.h"
Chong Zhang7306b0b2018-01-24 05:59:2426#include "content/public/common/content_switches.h"
Clark DuVall3290462e2019-02-16 02:19:5027#include "content/public/common/network_service_util.h"
Clark DuVallf742bcbd2018-11-07 17:16:2028#include "content/public/common/service_names.mojom.h"
Chong Zhangc40a6ce52017-12-10 03:00:2829#include "content/public/test/browser_test_utils.h"
Chong Zhangc583e672017-11-08 16:34:0830#include "content/public/test/content_browser_test.h"
31#include "content/public/test/content_browser_test_utils.h"
Chong Zhangd4c923642018-01-03 21:22:2932#include "content/public/test/simple_url_loader_test_helper.h"
Chong Zhang53047762018-05-02 21:24:0833#include "content/public/test/test_utils.h"
Chong Zhang5f468272017-12-07 23:59:1434#include "content/shell/browser/shell.h"
John Abd-El-Maleka7289152018-02-17 00:16:1935#include "content/shell/browser/shell_browser_context.h"
Chong Zhang83d0e4f2018-05-04 18:55:0936#include "content/test/storage_partition_test_utils.h"
Clark DuVallf742bcbd2018-11-07 17:16:2037#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
Chong Zhang7306b0b2018-01-24 05:59:2438#include "net/dns/mock_host_resolver.h"
39#include "net/test/embedded_test_server/http_request.h"
Chong Zhangd4c923642018-01-03 21:22:2940#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Yutaka Hiranod8789f92018-01-30 09:59:5141#include "services/network/public/cpp/features.h"
John Abd-El-Malekbdafede2018-02-06 15:10:3642#include "services/network/public/cpp/simple_url_loader.h"
Ken Rockot54311e62018-02-10 19:01:5243#include "services/network/public/mojom/network_service.mojom.h"
Clark DuVallf742bcbd2018-11-07 17:16:2044#include "services/network/public/mojom/network_service_test.mojom.h"
45#include "services/service_manager/public/cpp/connector.h"
Chong Zhangc583e672017-11-08 16:34:0846
Lukasz Anforowiczce4487b72018-10-23 18:05:5347#if BUILDFLAG(ENABLE_PLUGINS)
48#include "content/public/test/ppapi_test_utils.h"
49#endif
50
Chong Zhangc583e672017-11-08 16:34:0851namespace content {
52
53namespace {
54
Chong Zhang4dd97ebf2018-03-07 04:48:4855using SharedURLLoaderFactoryGetterCallback =
Chong Zhangb7c8d1ce2018-03-13 19:14:1156 base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;
Chong Zhang4dd97ebf2018-03-07 04:48:4857
John Abd-El-Malek53670dd2018-01-18 22:07:2158network::mojom::NetworkContextPtr CreateNetworkContext() {
59 network::mojom::NetworkContextPtr network_context;
60 network::mojom::NetworkContextParamsPtr context_params =
61 network::mojom::NetworkContextParams::New();
Chong Zhangc583e672017-11-08 16:34:0862 GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
63 std::move(context_params));
64 return network_context;
65}
66
John Abd-El-Maleka7289152018-02-17 00:16:1967int LoadBasicRequestOnUIThread(
68 network::mojom::URLLoaderFactory* url_loader_factory,
69 const GURL& url) {
70 DCHECK_CURRENTLY_ON(BrowserThread::UI);
71 auto request = std::make_unique<network::ResourceRequest>();
72 request->url = url;
73
74 SimpleURLLoaderTestHelper simple_loader_helper;
75 std::unique_ptr<network::SimpleURLLoader> simple_loader =
76 network::SimpleURLLoader::Create(std::move(request),
77 TRAFFIC_ANNOTATION_FOR_TESTS);
78 simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
79 url_loader_factory, simple_loader_helper.GetCallback());
80 simple_loader_helper.WaitForCallback();
81 return simple_loader->NetError();
82}
83
Chong Zhang53047762018-05-02 21:24:0884std::vector<network::mojom::NetworkUsagePtr> GetTotalNetworkUsages() {
85 std::vector<network::mojom::NetworkUsagePtr> network_usages;
86 base::RunLoop run_loop;
87 GetNetworkService()->GetTotalNetworkUsages(base::BindOnce(
88 [](std::vector<network::mojom::NetworkUsagePtr>* p_network_usages,
89 base::OnceClosure quit_closure,
90 std::vector<network::mojom::NetworkUsagePtr> returned_usages) {
91 *p_network_usages = std::move(returned_usages);
92 std::move(quit_closure).Run();
93 },
94 base::Unretained(&network_usages), run_loop.QuitClosure()));
95 run_loop.Run();
96 return network_usages;
97}
98
99bool CheckContainsProcessID(
100 const std::vector<network::mojom::NetworkUsagePtr>& usages,
101 int process_id) {
102 for (const auto& usage : usages) {
103 if ((int)usage->process_id == process_id)
104 return true;
105 }
106 return false;
107}
108
109// Wait until |condition| returns true.
110void WaitForCondition(base::RepeatingCallback<bool()> condition) {
111 while (!condition.Run()) {
112 base::RunLoop run_loop;
113 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
114 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
115 run_loop.Run();
116 }
117}
118
Makoto Shimazu2075b0d2018-09-21 09:04:22119class ServiceWorkerStatusObserver : public ServiceWorkerContextCoreObserver {
120 public:
121 void WaitForState(EmbeddedWorkerStatus expected_status) {
Makoto Shimazu2540a642018-11-15 06:24:44122 for (const auto& status : statuses_in_past_) {
123 if (status == expected_status)
124 return;
125 }
Makoto Shimazu2075b0d2018-09-21 09:04:22126
127 expected_status_ = expected_status;
128 base::RunLoop loop;
129 callback_ = loop.QuitClosure();
130 loop.Run();
131 }
132
133 private:
134 void OnRunningStateChanged(int64_t version_id,
135 EmbeddedWorkerStatus running_status) override {
Makoto Shimazu2540a642018-11-15 06:24:44136 statuses_in_past_.push_back(running_status);
Makoto Shimazu2075b0d2018-09-21 09:04:22137 if (expected_status_.has_value() &&
138 running_status == expected_status_.value()) {
139 std::move(callback_).Run();
140 }
141 }
142
143 base::Optional<EmbeddedWorkerStatus> expected_status_;
Makoto Shimazu2540a642018-11-15 06:24:44144 std::vector<EmbeddedWorkerStatus> statuses_in_past_;
Makoto Shimazu2075b0d2018-09-21 09:04:22145 base::OnceClosure callback_;
146};
147
Chong Zhangc583e672017-11-08 16:34:08148} // namespace
149
Chong Zhangc583e672017-11-08 16:34:08150class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
151 public:
152 NetworkServiceRestartBrowserTest() {
Yutaka Hiranod8789f92018-01-30 09:59:51153 scoped_feature_list_.InitAndEnableFeature(
154 network::features::kNetworkService);
Chong Zhang7306b0b2018-01-24 05:59:24155 }
156
Lukasz Anforowiczce4487b72018-10-23 18:05:53157 void SetUpCommandLine(base::CommandLine* command_line) override {
158#if BUILDFLAG(ENABLE_PLUGINS)
159 ASSERT_TRUE(ppapi::RegisterCorbTestPlugin(command_line));
160#endif
161 ContentBrowserTest::SetUpCommandLine(command_line);
162 }
163
Chong Zhang7306b0b2018-01-24 05:59:24164 void SetUpOnMainThread() override {
Chong Zhang5d9b34182018-01-30 16:20:57165 embedded_test_server()->RegisterRequestMonitor(
166 base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
167 base::Unretained(this)));
Lukasz Anforowiczce4487b72018-10-23 18:05:53168 host_resolver()->AddRule("*", "127.0.0.1");
Chong Zhangc583e672017-11-08 16:34:08169 EXPECT_TRUE(embedded_test_server()->Start());
Chong Zhang7306b0b2018-01-24 05:59:24170 ContentBrowserTest::SetUpOnMainThread();
Chong Zhangc583e672017-11-08 16:34:08171 }
172
Chong Zhangc40a6ce52017-12-10 03:00:28173 GURL GetTestURL() const {
Chong Zhang5f468272017-12-07 23:59:14174 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
175 // See https://crbug.com/792255.
Chong Zhangc40a6ce52017-12-10 03:00:28176 return embedded_test_server()->GetURL("/echoheader");
Chong Zhangc583e672017-11-08 16:34:08177 }
178
Chong Zhangd4c923642018-01-03 21:22:29179 BrowserContext* browser_context() {
180 return shell()->web_contents()->GetBrowserContext();
181 }
182
Chong Zhang5d9b34182018-01-30 16:20:57183 RenderFrameHostImpl* main_frame() {
184 return static_cast<RenderFrameHostImpl*>(
185 shell()->web_contents()->GetMainFrame());
186 }
187
Chong Zhang53047762018-05-02 21:24:08188 bool CheckCanLoadHttp(Shell* shell, const std::string& relative_url) {
Chong Zhang5d9b34182018-01-30 16:20:57189 GURL test_url = embedded_test_server()->GetURL(relative_url);
190 std::string script(
191 "var xhr = new XMLHttpRequest();"
192 "xhr.open('GET', '");
193 script += test_url.spec() +
194 "', true);"
195 "xhr.onload = function (e) {"
196 " if (xhr.readyState === 4) {"
197 " window.domAutomationController.send(xhr.status === 200);"
198 " }"
199 "};"
200 "xhr.onerror = function () {"
201 " window.domAutomationController.send(false);"
202 "};"
203 "xhr.send(null)";
204 bool xhr_result = false;
205 // The JS call will fail if disallowed because the process will be killed.
206 bool execute_result =
Chong Zhang53047762018-05-02 21:24:08207 ExecuteScriptAndExtractBool(shell, script, &xhr_result);
Chong Zhang5d9b34182018-01-30 16:20:57208 return xhr_result && execute_result;
209 }
210
Chong Zhang4513fab2018-02-28 18:50:18211 // Will reuse the single opened windows through the test case.
212 bool CheckCanLoadHttpInWindowOpen(const std::string& relative_url) {
213 GURL test_url = embedded_test_server()->GetURL(relative_url);
214 std::string inject_script = base::StringPrintf(
215 "var xhr = new XMLHttpRequest();"
216 "xhr.open('GET', '%s', true);"
217 "xhr.onload = function (e) {"
218 " if (xhr.readyState === 4) {"
219 " window.opener.domAutomationController.send(xhr.status === 200);"
220 " }"
221 "};"
222 "xhr.onerror = function () {"
223 " window.opener.domAutomationController.send(false);"
224 "};"
225 "xhr.send(null)",
226 test_url.spec().c_str());
227 std::string window_open_script = base::StringPrintf(
228 "var new_window = new_window || window.open('');"
229 "var inject_script = document.createElement('script');"
230 "inject_script.innerHTML = \"%s\";"
231 "new_window.document.body.appendChild(inject_script);",
232 inject_script.c_str());
233
234 bool xhr_result = false;
235 // The JS call will fail if disallowed because the process will be killed.
236 bool execute_result =
237 ExecuteScriptAndExtractBool(shell(), window_open_script, &xhr_result);
238 return xhr_result && execute_result;
239 }
240
241 // Workers will live throughout the test case unless terminated.
242 bool CheckCanWorkerFetch(const std::string& worker_name,
243 const std::string& relative_url) {
244 GURL worker_url =
245 embedded_test_server()->GetURL("/workers/worker_common.js");
246 GURL fetch_url = embedded_test_server()->GetURL(relative_url);
247 std::string script = base::StringPrintf(
248 "var workers = workers || {};"
249 "var worker_name = '%s';"
250 "workers[worker_name] = workers[worker_name] || new Worker('%s');"
251 "workers[worker_name].onmessage = evt => {"
252 " if (evt.data != 'wait')"
253 " window.domAutomationController.send(evt.data === 200);"
254 "};"
255 "workers[worker_name].postMessage(\"eval "
256 " fetch(new Request('%s'))"
257 " .then(res => postMessage(res.status))"
258 " .catch(error => postMessage(error.toString()));"
259 " 'wait'"
260 "\");",
261 worker_name.c_str(), worker_url.spec().c_str(),
262 fetch_url.spec().c_str());
263 bool fetch_result = false;
264 // The JS call will fail if disallowed because the process will be killed.
265 bool execute_result =
266 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
267 return fetch_result && execute_result;
268 }
269
270 // Terminate and delete the worker.
271 bool TerminateWorker(const std::string& worker_name) {
272 std::string script = base::StringPrintf(
273 "var workers = workers || {};"
274 "var worker_name = '%s';"
275 "if (workers[worker_name]) {"
276 " workers[worker_name].terminate();"
277 " delete workers[worker_name];"
278 " window.domAutomationController.send(true);"
279 "} else {"
280 " window.domAutomationController.send(false);"
281 "}",
282 worker_name.c_str());
283 bool fetch_result = false;
284 // The JS call will fail if disallowed because the process will be killed.
285 bool execute_result =
286 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
287 return fetch_result && execute_result;
288 }
289
Chong Zhang5d9b34182018-01-30 16:20:57290 // Called by |embedded_test_server()|.
291 void MonitorRequest(const net::test_server::HttpRequest& request) {
292 last_request_relative_url_ = request.relative_url;
293 }
294
295 std::string last_request_relative_url() const {
296 return last_request_relative_url_;
297 }
298
Chong Zhangc583e672017-11-08 16:34:08299 private:
Chong Zhang5d9b34182018-01-30 16:20:57300 std::string last_request_relative_url_;
Chong Zhangc583e672017-11-08 16:34:08301 base::test::ScopedFeatureList scoped_feature_list_;
302
303 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
304};
305
306IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
307 NetworkServiceProcessRecovery) {
Clark DuVall3290462e2019-02-16 02:19:50308 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36309 return;
John Abd-El-Malek53670dd2018-01-18 22:07:21310 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28311 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08312 EXPECT_TRUE(network_context.is_bound());
313 EXPECT_FALSE(network_context.encountered_error());
314
Chong Zhang5f468272017-12-07 23:59:14315 // Crash the NetworkService process. Existing interfaces should receive error
316 // notifications at some point.
Chong Zhangc583e672017-11-08 16:34:08317 SimulateNetworkServiceCrash();
Chong Zhang5f468272017-12-07 23:59:14318 // |network_context| will receive an error notification, but it's not
319 // guaranteed to have arrived at this point. Flush the pointer to make sure
320 // the notification has been received.
321 network_context.FlushForTesting();
Chong Zhangc583e672017-11-08 16:34:08322 EXPECT_TRUE(network_context.is_bound());
323 EXPECT_TRUE(network_context.encountered_error());
Chong Zhang5f468272017-12-07 23:59:14324 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
Chong Zhangc40a6ce52017-12-10 03:00:28325 EXPECT_EQ(net::ERR_FAILED,
326 LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08327
328 // NetworkService should restart automatically and return valid interface.
John Abd-El-Malek53670dd2018-01-18 22:07:21329 network::mojom::NetworkContextPtr network_context2 = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28330 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08331 EXPECT_TRUE(network_context2.is_bound());
332 EXPECT_FALSE(network_context2.encountered_error());
333}
334
Lukasz Anforowiczce4487b72018-10-23 18:05:53335void IncrementInt(int* i) {
336 *i = *i + 1;
337}
338
339// This test verifies basic functionality of RegisterNetworkServiceCrashHandler
340// and UnregisterNetworkServiceCrashHandler.
341IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, CrashHandlers) {
Clark DuVall3290462e2019-02-16 02:19:50342 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36343 return;
Lukasz Anforowiczce4487b72018-10-23 18:05:53344 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
345 EXPECT_TRUE(network_context.is_bound());
346
347 // Register 2 crash handlers.
348 int counter1 = 0;
349 int counter2 = 0;
Lukasz Anforowiczc195e912018-10-30 16:20:54350 auto handler1 = RegisterNetworkServiceCrashHandler(
Lukasz Anforowiczce4487b72018-10-23 18:05:53351 base::BindRepeating(&IncrementInt, base::Unretained(&counter1)));
Lukasz Anforowiczc195e912018-10-30 16:20:54352 auto handler2 = RegisterNetworkServiceCrashHandler(
Lukasz Anforowiczce4487b72018-10-23 18:05:53353 base::BindRepeating(&IncrementInt, base::Unretained(&counter2)));
354
355 // Crash the NetworkService process.
356 SimulateNetworkServiceCrash();
357 // |network_context| will receive an error notification, but it's not
358 // guaranteed to have arrived at this point. Flush the pointer to make sure
359 // the notification has been received.
360 network_context.FlushForTesting();
361 EXPECT_TRUE(network_context.is_bound());
362 EXPECT_TRUE(network_context.encountered_error());
363
364 // Verify the crash handlers executed.
365 EXPECT_EQ(1, counter1);
366 EXPECT_EQ(1, counter2);
367
368 // Revive the NetworkService process.
369 network_context = CreateNetworkContext();
370 EXPECT_TRUE(network_context.is_bound());
371
372 // Unregister one of the handlers.
Lukasz Anforowiczc195e912018-10-30 16:20:54373 handler2.reset();
Lukasz Anforowiczce4487b72018-10-23 18:05:53374
375 // Crash the NetworkService process.
376 SimulateNetworkServiceCrash();
377 // |network_context| will receive an error notification, but it's not
378 // guaranteed to have arrived at this point. Flush the pointer to make sure
379 // the notification has been received.
380 network_context.FlushForTesting();
381 EXPECT_TRUE(network_context.is_bound());
382 EXPECT_TRUE(network_context.encountered_error());
383
384 // Verify only the first crash handler executed.
385 EXPECT_EQ(2, counter1);
386 EXPECT_EQ(1, counter2);
Lukasz Anforowiczce4487b72018-10-23 18:05:53387}
388
Chong Zhang5f468272017-12-07 23:59:14389// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
390// after crash.
391IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Chong Zhange0dfdb62017-12-09 18:25:14392 StoragePartitionImplGetNetworkContext) {
Clark DuVall3290462e2019-02-16 02:19:50393 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36394 return;
Chong Zhang5f468272017-12-07 23:59:14395 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
Chong Zhangd4c923642018-01-03 21:22:29396 BrowserContext::GetDefaultStoragePartition(browser_context()));
Chong Zhang5f468272017-12-07 23:59:14397
John Abd-El-Malek53670dd2018-01-18 22:07:21398 network::mojom::NetworkContext* old_network_context =
399 partition->GetNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28400 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14401
402 // Crash the NetworkService process. Existing interfaces should receive error
403 // notifications at some point.
404 SimulateNetworkServiceCrash();
405 // Flush the interface to make sure the error notification was received.
406 partition->FlushNetworkInterfaceForTesting();
407
408 // |partition->GetNetworkContext()| should return a valid new pointer after
409 // crash.
410 EXPECT_NE(old_network_context, partition->GetNetworkContext());
Chong Zhangc40a6ce52017-12-10 03:00:28411 EXPECT_EQ(net::OK,
412 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14413}
414
Chong Zhangd4c923642018-01-03 21:22:29415// Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
416IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
417 URLLoaderFactoryGetterGetNetworkFactory) {
Clark DuVall3290462e2019-02-16 02:19:50418 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36419 return;
Chong Zhangd4c923642018-01-03 21:22:29420 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
421 BrowserContext::GetDefaultStoragePartition(browser_context()));
422 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
423 partition->url_loader_factory_getter();
Chong Zhang5271432a2018-03-01 23:31:02424
Chong Zhang83d0e4f2018-05-04 18:55:09425 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
426 url_loader_factory_getter.get());
427 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02428
Chong Zhangd4c923642018-01-03 21:22:29429 // Crash the NetworkService process. Existing interfaces should receive error
430 // notifications at some point.
431 SimulateNetworkServiceCrash();
432 // Flush the interface to make sure the error notification was received.
433 partition->FlushNetworkInterfaceForTesting();
434 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
435
436 // |url_loader_factory_getter| should be able to get a valid new pointer after
437 // crash.
Chong Zhang83d0e4f2018-05-04 18:55:09438 factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
439 url_loader_factory_getter.get());
440 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02441}
442
443// Make sure the factory returned from
444// |URLLoaderFactoryGetter::GetNetworkFactory()| continues to work after
445// crashes.
446IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
447 BrowserIOSharedURLLoaderFactory) {
Clark DuVall3290462e2019-02-16 02:19:50448 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36449 return;
Chong Zhang5271432a2018-03-01 23:31:02450 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
451 BrowserContext::GetDefaultStoragePartition(browser_context()));
452
Chong Zhang83d0e4f2018-05-04 18:55:09453 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
454 partition->url_loader_factory_getter().get());
Chong Zhang5271432a2018-03-01 23:31:02455
Chong Zhang83d0e4f2018-05-04 18:55:09456 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02457
458 // Crash the NetworkService process. Existing interfaces should receive error
459 // notifications at some point.
460 SimulateNetworkServiceCrash();
461 // Flush the interface to make sure the error notification was received.
462 partition->FlushNetworkInterfaceForTesting();
463 partition->url_loader_factory_getter()
464 ->FlushNetworkInterfaceOnIOThreadForTesting();
465
466 // |shared_factory| should continue to work.
Chong Zhang83d0e4f2018-05-04 18:55:09467 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02468}
469
470// Make sure the factory returned from
471// |URLLoaderFactoryGetter::GetNetworkFactory()| doesn't crash if
472// it's called after the StoragePartition is deleted.
Chong Zhangf8572182018-03-16 23:10:18473IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
474 BrowserIOSharedFactoryAfterStoragePartitionGone) {
Clark DuVall3290462e2019-02-16 02:19:50475 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36476 return;
Chong Zhang5271432a2018-03-01 23:31:02477 base::ScopedAllowBlockingForTesting allow_blocking;
478 std::unique_ptr<ShellBrowserContext> browser_context =
479 std::make_unique<ShellBrowserContext>(true, nullptr);
480 auto* partition = static_cast<StoragePartitionImpl*>(
481 BrowserContext::GetDefaultStoragePartition(browser_context.get()));
Chong Zhang83d0e4f2018-05-04 18:55:09482 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
483 partition->url_loader_factory_getter().get());
Chong Zhang5271432a2018-03-01 23:31:02484
Chong Zhang83d0e4f2018-05-04 18:55:09485 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02486
487 browser_context.reset();
488
489 EXPECT_EQ(net::ERR_FAILED,
Chong Zhang83d0e4f2018-05-04 18:55:09490 factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhangd4c923642018-01-03 21:22:29491}
492
493// Make sure basic navigation works after crash.
494IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
495 NavigationURLLoaderBasic) {
Clark DuVall3290462e2019-02-16 02:19:50496 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36497 return;
Chong Zhangd4c923642018-01-03 21:22:29498 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
499 BrowserContext::GetDefaultStoragePartition(browser_context()));
500
501 EXPECT_TRUE(
502 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
503
504 // Crash the NetworkService process. Existing interfaces should receive error
505 // notifications at some point.
506 SimulateNetworkServiceCrash();
507 // Flush the interface to make sure the error notification was received.
508 partition->FlushNetworkInterfaceForTesting();
509 partition->url_loader_factory_getter()
510 ->FlushNetworkInterfaceOnIOThreadForTesting();
511
512 EXPECT_TRUE(
513 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
514}
515
Chong Zhang7306b0b2018-01-24 05:59:24516// Make sure basic XHR works after crash.
Chong Zhang5d9b34182018-01-30 16:20:57517IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
Clark DuVall3290462e2019-02-16 02:19:50518 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36519 return;
Chong Zhang7306b0b2018-01-24 05:59:24520 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
521 BrowserContext::GetDefaultStoragePartition(browser_context()));
522
Chong Zhang5d9b34182018-01-30 16:20:57523 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
Chong Zhang53047762018-05-02 21:24:08524 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title1.html"));
Chong Zhang7306b0b2018-01-24 05:59:24525 EXPECT_EQ(last_request_relative_url(), "/title1.html");
526
527 // Crash the NetworkService process. Existing interfaces should receive error
528 // notifications at some point.
529 SimulateNetworkServiceCrash();
530 // Flush the interface to make sure the error notification was received.
531 partition->FlushNetworkInterfaceForTesting();
532 // Flush the interface to make sure the frame host has received error
533 // notification and the new URLLoaderFactoryBundle has been received by the
534 // frame.
535 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
536
Chong Zhang53047762018-05-02 21:24:08537 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
Chong Zhang7306b0b2018-01-24 05:59:24538 EXPECT_EQ(last_request_relative_url(), "/title2.html");
539}
540
John Abd-El-Maleka7289152018-02-17 00:16:19541// Make sure the factory returned from
542// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| continues to work
543// after crashes.
544IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserUIFactory) {
Clark DuVall3290462e2019-02-16 02:19:50545 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36546 return;
John Abd-El-Maleka7289152018-02-17 00:16:19547 auto* partition =
548 BrowserContext::GetDefaultStoragePartition(browser_context());
549 auto* factory = partition->GetURLLoaderFactoryForBrowserProcess().get();
550
551 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
552
553 SimulateNetworkServiceCrash();
554 // Flush the interface to make sure the error notification was received.
555 partition->FlushNetworkInterfaceForTesting();
556
557 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
558}
559
560// Make sure the factory returned from
561// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| doesn't crash if
562// it's called after the StoragePartition is deleted.
563IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
564 BrowserUIFactoryAfterStoragePartitionGone) {
Clark DuVall3290462e2019-02-16 02:19:50565 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36566 return;
John Abd-El-Maleka7289152018-02-17 00:16:19567 base::ScopedAllowBlockingForTesting allow_blocking;
568 std::unique_ptr<ShellBrowserContext> browser_context =
569 std::make_unique<ShellBrowserContext>(true, nullptr);
570 auto* partition =
571 BrowserContext::GetDefaultStoragePartition(browser_context.get());
Chong Zhangb7c8d1ce2018-03-13 19:14:11572 scoped_refptr<network::SharedURLLoaderFactory> factory(
John Abd-El-Maleka7289152018-02-17 00:16:19573 partition->GetURLLoaderFactoryForBrowserProcess());
574
575 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
576
577 browser_context.reset();
578
579 EXPECT_EQ(net::ERR_FAILED,
580 LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
581}
582
Chong Zhang83d0e4f2018-05-04 18:55:09583// Make sure the factory info returned from
584// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| can be
585// used after crashes.
Guido Urdaneta9cbbe382018-05-07 14:51:06586// Flaky on Windows. https://crbug.com/840127
587#if defined(OS_WIN)
588#define MAYBE_BrowserIOFactoryInfo DISABLED_BrowserIOFactoryInfo
589#else
590#define MAYBE_BrowserIOFactoryInfo BrowserIOFactoryInfo
591#endif
592IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
593 MAYBE_BrowserIOFactoryInfo) {
Clark DuVall3290462e2019-02-16 02:19:50594 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36595 return;
Chong Zhang4dd97ebf2018-03-07 04:48:48596 auto* partition =
597 BrowserContext::GetDefaultStoragePartition(browser_context());
Chong Zhang83d0e4f2018-05-04 18:55:09598 auto shared_url_loader_factory_info =
599 partition->GetURLLoaderFactoryForBrowserProcessIOThread();
Chong Zhang4dd97ebf2018-03-07 04:48:48600
601 SimulateNetworkServiceCrash();
602 // Flush the interface to make sure the error notification was received.
603 partition->FlushNetworkInterfaceForTesting();
604 static_cast<StoragePartitionImpl*>(partition)
605 ->url_loader_factory_getter()
606 ->FlushNetworkInterfaceOnIOThreadForTesting();
607
Chong Zhang83d0e4f2018-05-04 18:55:09608 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
609 std::move(shared_url_loader_factory_info));
610
611 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48612}
613
Chong Zhang83d0e4f2018-05-04 18:55:09614// Make sure the factory constructed from
615// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| continues
616// to work after crashes.
617IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
Clark DuVall3290462e2019-02-16 02:19:50618 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36619 return;
Chong Zhang4dd97ebf2018-03-07 04:48:48620 auto* partition =
Chong Zhang83d0e4f2018-05-04 18:55:09621 BrowserContext::GetDefaultStoragePartition(browser_context());
622 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
623 partition->GetURLLoaderFactoryForBrowserProcessIOThread());
Chong Zhang4dd97ebf2018-03-07 04:48:48624
Chong Zhang83d0e4f2018-05-04 18:55:09625 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48626
Chong Zhang83d0e4f2018-05-04 18:55:09627 SimulateNetworkServiceCrash();
628 // Flush the interface to make sure the error notification was received.
629 partition->FlushNetworkInterfaceForTesting();
630 static_cast<StoragePartitionImpl*>(partition)
631 ->url_loader_factory_getter()
632 ->FlushNetworkInterfaceOnIOThreadForTesting();
Chong Zhang4dd97ebf2018-03-07 04:48:48633
Chong Zhang83d0e4f2018-05-04 18:55:09634 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48635}
636
Chong Zhang4513fab2018-02-28 18:50:18637// Make sure the window from |window.open()| can load XHR after crash.
638IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, WindowOpenXHR) {
Clark DuVall3290462e2019-02-16 02:19:50639 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36640 return;
Chong Zhang4513fab2018-02-28 18:50:18641 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
642 BrowserContext::GetDefaultStoragePartition(browser_context()));
643
644 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
645 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title1.html"));
646 EXPECT_EQ(last_request_relative_url(), "/title1.html");
647
648 // Crash the NetworkService process. Existing interfaces should receive error
649 // notifications at some point.
650 SimulateNetworkServiceCrash();
651 // Flush the interface to make sure the error notification was received.
652 partition->FlushNetworkInterfaceForTesting();
653 // Flush the interface to make sure the frame host has received error
654 // notification and the new URLLoaderFactoryBundle has been received by the
655 // frame.
656 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
657
658 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title2.html"));
659 EXPECT_EQ(last_request_relative_url(), "/title2.html");
660}
661
662// Make sure worker fetch works after crash.
663IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, WorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50664 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36665 return;
Chong Zhang4513fab2018-02-28 18:50:18666 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
667 BrowserContext::GetDefaultStoragePartition(browser_context()));
668
669 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
670 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
671 EXPECT_EQ(last_request_relative_url(), "/title1.html");
672
673 // Crash the NetworkService process. Existing interfaces should receive error
674 // notifications at some point.
675 SimulateNetworkServiceCrash();
676 // Flush the interface to make sure the error notification was received.
677 partition->FlushNetworkInterfaceForTesting();
678 // Flush the interface to make sure the frame host has received error
679 // notification and the new URLLoaderFactoryBundle has been received by the
680 // frame.
681 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
682
683 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
684 EXPECT_EQ(last_request_relative_url(), "/title2.html");
685}
686
687// Make sure multiple workers are tracked correctly and work after crash.
688IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MultipleWorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50689 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36690 return;
Chong Zhang4513fab2018-02-28 18:50:18691 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
692 BrowserContext::GetDefaultStoragePartition(browser_context()));
693
694 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
695 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
696 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
697 EXPECT_EQ(last_request_relative_url(), "/title1.html");
698
699 // Crash the NetworkService process. Existing interfaces should receive error
700 // notifications at some point.
701 SimulateNetworkServiceCrash();
702 // Flush the interface to make sure the error notification was received.
703 partition->FlushNetworkInterfaceForTesting();
704 // Flush the interface to make sure the frame host has received error
705 // notification and the new URLLoaderFactoryBundle has been received by the
706 // frame.
707 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
708
709 // Both workers should work after crash.
710 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
711 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
712 EXPECT_EQ(last_request_relative_url(), "/title2.html");
713
714 // Terminate "worker1". "worker2" shouldn't be affected.
715 EXPECT_TRUE(TerminateWorker("worker1"));
716 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
717 EXPECT_EQ(last_request_relative_url(), "/title1.html");
718
719 // Crash the NetworkService process again. "worker2" should still work.
720 SimulateNetworkServiceCrash();
721 partition->FlushNetworkInterfaceForTesting();
722 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
723
724 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
725 EXPECT_EQ(last_request_relative_url(), "/title2.html");
726}
727
Makoto Shimazu775101a52018-09-26 04:46:52728// Make sure fetch from a page controlled by a service worker which doesn't have
729// a fetch handler works after crash.
Makoto Shimazu2540a642018-11-15 06:24:44730IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
731 FetchFromServiceWorkerControlledPage_NoFetchHandler) {
Clark DuVall3290462e2019-02-16 02:19:50732 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36733 return;
Makoto Shimazu775101a52018-09-26 04:46:52734 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
735 BrowserContext::GetDefaultStoragePartition(browser_context()));
736 ServiceWorkerStatusObserver observer;
737 ServiceWorkerContextWrapper* service_worker_context =
738 partition->GetServiceWorkerContext();
739 service_worker_context->AddObserver(&observer);
740
741 // Register a service worker which controls /service_worker/.
742 EXPECT_TRUE(NavigateToURL(shell(),
743 embedded_test_server()->GetURL(
744 "/service_worker/create_service_worker.html")));
745 EXPECT_EQ("DONE", EvalJs(shell(), "register('empty.js')"));
746
747 // Navigate to a controlled page.
748 EXPECT_TRUE(NavigateToURL(
749 shell(),
750 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
751
752 // Fetch from the controlled page.
753 const std::string script = "fetch_from_page('/echo');";
754 EXPECT_EQ("Echo", EvalJs(shell(), script));
755
756 // Crash the NetworkService process. Existing interfaces should receive error
757 // notifications at some point.
758 SimulateNetworkServiceCrash();
759 // Flush the interface to make sure the error notification was received.
760 partition->FlushNetworkInterfaceForTesting();
761
762 // Service worker should be stopped when network service crashes.
763 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
764
765 // Fetch from the controlled page again.
766 EXPECT_EQ("Echo", EvalJs(shell(), script));
767
768 service_worker_context->RemoveObserver(&observer);
769}
770
Makoto Shimazu775101a52018-09-26 04:46:52771// Make sure fetch from a page controlled by a service worker which has a fetch
772// handler but falls back to the network works after crash.
773IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Makoto Shimazu2540a642018-11-15 06:24:44774 FetchFromServiceWorkerControlledPage_PassThrough) {
Clark DuVall3290462e2019-02-16 02:19:50775 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36776 return;
Makoto Shimazu775101a52018-09-26 04:46:52777 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
778 BrowserContext::GetDefaultStoragePartition(browser_context()));
779 ServiceWorkerStatusObserver observer;
780 ServiceWorkerContextWrapper* service_worker_context =
781 partition->GetServiceWorkerContext();
782 service_worker_context->AddObserver(&observer);
783
784 // Register a service worker which controls /service_worker/.
785 EXPECT_TRUE(NavigateToURL(shell(),
786 embedded_test_server()->GetURL(
787 "/service_worker/create_service_worker.html")));
788 EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_pass_through.js')"));
789
790 // Navigate to a controlled page.
791 EXPECT_TRUE(NavigateToURL(
792 shell(),
793 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
794
795 // Fetch from the controlled page.
796 const std::string script = "fetch_from_page('/echo');";
797 EXPECT_EQ("Echo", EvalJs(shell(), script));
798
799 // Crash the NetworkService process. Existing interfaces should receive error
800 // notifications at some point.
801 SimulateNetworkServiceCrash();
802 // Flush the interface to make sure the error notification was received.
803 partition->FlushNetworkInterfaceForTesting();
804
805 // Service worker should be stopped when network service crashes.
806 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
807
808 // Fetch from the controlled page again.
809 EXPECT_EQ("Echo", EvalJs(shell(), script));
810
811 service_worker_context->RemoveObserver(&observer);
812}
813
Makoto Shimazu775101a52018-09-26 04:46:52814// Make sure fetch from a page controlled by a service worker which has a fetch
815// handler and responds with fetch() works after crash.
Makoto Shimazu2540a642018-11-15 06:24:44816IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
817 FetchFromServiceWorkerControlledPage_RespondWithFetch) {
Clark DuVall3290462e2019-02-16 02:19:50818 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36819 return;
Makoto Shimazu775101a52018-09-26 04:46:52820 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
821 BrowserContext::GetDefaultStoragePartition(browser_context()));
822 ServiceWorkerStatusObserver observer;
823 ServiceWorkerContextWrapper* service_worker_context =
824 partition->GetServiceWorkerContext();
825 service_worker_context->AddObserver(&observer);
826
827 // Register a service worker which controls /service_worker/.
828 EXPECT_TRUE(NavigateToURL(shell(),
829 embedded_test_server()->GetURL(
830 "/service_worker/create_service_worker.html")));
831 EXPECT_EQ("DONE",
832 EvalJs(shell(), "register('fetch_event_respond_with_fetch.js')"));
833
834 // Navigate to a controlled page.
835 EXPECT_TRUE(NavigateToURL(
836 shell(),
837 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
838
839 // Fetch from the controlled page.
840 const std::string script = "fetch_from_page('/echo');";
841 EXPECT_EQ("Echo", EvalJs(shell(), script));
842
843 // Crash the NetworkService process. Existing interfaces should receive error
844 // notifications at some point.
845 SimulateNetworkServiceCrash();
846 // Flush the interface to make sure the error notification was received.
847 partition->FlushNetworkInterfaceForTesting();
848
849 // Service worker should be stopped when network service crashes.
850 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
851
852 // Fetch from the controlled page again.
853 EXPECT_EQ("Echo", EvalJs(shell(), script));
854
855 service_worker_context->RemoveObserver(&observer);
856}
857
Makoto Shimazu2075b0d2018-09-21 09:04:22858// Make sure fetch from service worker context works after crash.
Makoto Shimazu6a96cb62018-09-21 11:39:13859IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50860 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36861 return;
Makoto Shimazu2075b0d2018-09-21 09:04:22862 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
863 BrowserContext::GetDefaultStoragePartition(browser_context()));
864 ServiceWorkerStatusObserver observer;
865 ServiceWorkerContextWrapper* service_worker_context =
866 partition->GetServiceWorkerContext();
867 service_worker_context->AddObserver(&observer);
868
869 const GURL page_url = embedded_test_server()->GetURL(
870 "/service_worker/fetch_from_service_worker.html");
871 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
872
873 // Navigate to the page and register a service worker.
874 EXPECT_TRUE(NavigateToURL(shell(), page_url));
875 EXPECT_EQ("ready", EvalJs(shell(), "setup();"));
876
877 // Fetch from the service worker.
878 const std::string script =
879 "fetch_from_service_worker('" + fetch_url.spec() + "');";
880 EXPECT_EQ("Echo", EvalJs(shell(), script));
881
882 // Crash the NetworkService process. Existing interfaces should receive error
883 // notifications at some point.
884 SimulateNetworkServiceCrash();
885 // Flush the interface to make sure the error notification was received.
886 partition->FlushNetworkInterfaceForTesting();
887
888 // Service worker should be stopped when network service crashes.
889 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
890
891 // Fetch from the service worker again.
892 EXPECT_EQ("Echo", EvalJs(shell(), script));
893
894 service_worker_context->RemoveObserver(&observer);
895}
896
Clark DuVallf742bcbd2018-11-07 17:16:20897// TODO(crbug.com/154571): Shared workers are not available on Android.
898#if defined(OS_ANDROID)
899#define MAYBE_SharedWorker DISABLED_SharedWorker
900#else
901#define MAYBE_SharedWorker SharedWorker
902#endif
Matt Falkenhagene6721962018-10-05 10:17:05903// Make sure shared workers terminate after crash.
Clark DuVallf742bcbd2018-11-07 17:16:20904IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MAYBE_SharedWorker) {
Clark DuVall3290462e2019-02-16 02:19:50905 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36906 return;
Makoto Shimazu2075b0d2018-09-21 09:04:22907 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
908 BrowserContext::GetDefaultStoragePartition(browser_context()));
909
910 const GURL page_url =
911 embedded_test_server()->GetURL("/workers/fetch_from_shared_worker.html");
912 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
913
914 // Navigate to the page and prepare a shared worker.
915 EXPECT_TRUE(NavigateToURL(shell(), page_url));
916
Matt Falkenhagene6721962018-10-05 10:17:05917 // Fetch from the shared worker to ensure it has started.
Finditc0f7c6202018-10-05 07:14:23918 const std::string script =
919 "fetch_from_shared_worker('" + fetch_url.spec() + "');";
920 EXPECT_EQ("Echo", EvalJs(shell(), script));
Makoto Shimazu2075b0d2018-09-21 09:04:22921
Matt Falkenhagene6721962018-10-05 10:17:05922 // There should be one worker host. We will later wait for it to terminate.
923 SharedWorkerServiceImpl* service = partition->GetSharedWorkerService();
924 EXPECT_EQ(1u, service->worker_hosts_.size());
925 base::RunLoop loop;
926 service->SetWorkerTerminationCallbackForTesting(loop.QuitClosure());
Makoto Shimazu2075b0d2018-09-21 09:04:22927
Matt Falkenhagene6721962018-10-05 10:17:05928 // Crash the NetworkService process.
929 SimulateNetworkServiceCrash();
930
931 // Wait for the worker to detect the crash and self-terminate.
932 loop.Run();
933 EXPECT_TRUE(service->worker_hosts_.empty());
Makoto Shimazu2075b0d2018-09-21 09:04:22934}
935
Chong Zhang53047762018-05-02 21:24:08936// Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
937// after process closed.
938IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
939 GetNetworkUsagesClosed) {
Clark DuVall3290462e2019-02-16 02:19:50940 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36941 return;
Chong Zhang53047762018-05-02 21:24:08942 EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
943 Shell* shell2 = CreateBrowser();
944 EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
945
946 int process_id1 =
947 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
948 int process_id2 =
949 shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
950
951 // Load resource on the renderer to make sure the traffic was recorded.
952 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
953 EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
954
955 // Both processes should have traffic recorded.
956 auto network_usages = GetTotalNetworkUsages();
957 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
958 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
959
960 // Closing |shell2| should cause the entry to be cleared.
961 shell2->Close();
962 shell2 = nullptr;
963
964 // Wait until the Network Service has noticed the change. We don't have a
965 // better way to force a flush on the Network Service side.
966 WaitForCondition(base::BindRepeating(
967 [](int process_id) {
968 auto usages = GetTotalNetworkUsages();
969 return !CheckContainsProcessID(usages, process_id);
970 },
971 process_id2));
972
973 network_usages = GetTotalNetworkUsages();
974 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
975 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
976}
977
978// Make sure |NetworkService::GetTotalNetworkUsages()| continues to work after
979// crash. See 'network_usage_accumulator_unittest' for quantified tests.
980IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
981 GetNetworkUsagesCrashed) {
Clark DuVall3290462e2019-02-16 02:19:50982 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36983 return;
Chong Zhang53047762018-05-02 21:24:08984 EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
985 Shell* shell2 = CreateBrowser();
986 EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
987
988 int process_id1 =
989 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
990 int process_id2 =
991 shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
992
993 // Load resource on the renderer to make sure the traffic was recorded.
994 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
995 EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
996
997 // Both processes should have traffic recorded.
998 auto network_usages = GetTotalNetworkUsages();
999 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1000 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
1001
1002 // Crashing Network Service should cause all entries to be cleared.
1003 SimulateNetworkServiceCrash();
1004 network_usages = GetTotalNetworkUsages();
1005 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id1));
1006 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1007
1008 // Should still be able to recored new traffic after crash.
1009 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
1010 network_usages = GetTotalNetworkUsages();
1011 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1012 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1013}
1014
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141015// Make sure cookie access doesn't hang or fail after a network process crash.
1016IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
Clark DuVall3290462e2019-02-16 02:19:501017 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361018 return;
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141019 auto* web_contents = shell()->web_contents();
Lukasz Anforowiczce4487b72018-10-23 18:05:531020 ASSERT_TRUE(
1021 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141022 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1023
1024 std::string cookie;
1025 EXPECT_TRUE(ExecuteScriptAndExtractString(
1026 web_contents, "window.domAutomationController.send(document.cookie);",
1027 &cookie));
1028 EXPECT_EQ("foo=bar", cookie);
1029
1030 SimulateNetworkServiceCrash();
1031
1032 auto* process = web_contents->GetMainFrame()->GetProcess();
1033 scoped_refptr<RenderFrameMessageFilter> filter(
1034 static_cast<RenderProcessHostImpl*>(process)
1035 ->render_frame_message_filter_for_testing());
1036 // Need to use FlushAsyncForTesting instead of FlushForTesting because the IO
1037 // thread doesn't support nested message loops.
1038 base::RunLoop run_loop;
1039 base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
1040 base::BindLambdaForTesting([&]() {
1041 filter->GetCookieManager()->FlushAsyncForTesting(
1042 run_loop.QuitClosure());
1043 }));
1044
1045 // content_shell uses in-memory cookie database, so the value saved earlier
1046 // won't persist across crashes. What matters is that new access works.
1047 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1048
1049 // This will hang without the fix.
1050 EXPECT_TRUE(ExecuteScriptAndExtractString(
1051 web_contents, "window.domAutomationController.send(document.cookie);",
1052 &cookie));
1053 EXPECT_EQ("foo=bar", cookie);
1054}
1055
Lukasz Anforowiczce4487b72018-10-23 18:05:531056#if BUILDFLAG(ENABLE_PLUGINS)
1057// Make sure that "trusted" plugins continue to be able to issue cross-origin
1058// requests after a network process crash.
1059IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Plugin) {
Clark DuVall3290462e2019-02-16 02:19:501060 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361061 return;
Lukasz Anforowiczce4487b72018-10-23 18:05:531062 auto* web_contents = shell()->web_contents();
1063 ASSERT_TRUE(NavigateToURL(web_contents,
1064 embedded_test_server()->GetURL("/title1.html")));
1065
1066 // Load the test plugin (see ppapi::RegisterFlashTestPlugin and
1067 // ppapi/tests/power_saver_test_plugin.cc).
1068 const char kLoadingScript[] = R"(
1069 var obj = document.createElement('object');
1070 obj.id = 'plugin';
1071 obj.data = 'test.swf';
1072 obj.type = 'application/x-shockwave-flash';
1073 obj.width = 400;
1074 obj.height = 400;
1075
1076 document.body.appendChild(obj);
1077 )";
1078 ASSERT_TRUE(ExecJs(web_contents, kLoadingScript));
1079
1080 // Ask the plugin to perform a cross-origin, CORB-eligible (i.e.
1081 // application/json + nosniff) URL request. Plugins with universal access
1082 // should not be subject to CORS/CORB and so the request should go through.
1083 // See also https://crbug.com/874515 and https://crbug.com/846339.
1084 GURL cross_origin_url = embedded_test_server()->GetURL(
1085 "cross.origin.com", "/site_isolation/nosniff.json");
1086 const char kFetchScriptTemplate[] = R"(
1087 new Promise(function (resolve, reject) {
1088 var obj = document.getElementById('plugin');
1089 function callback(event) {
1090 // Ignore plugin messages unrelated to requestUrl.
1091 if (!event.data.startsWith('requestUrl: '))
1092 return;
1093
1094 obj.removeEventListener('message', callback);
1095 resolve('msg-from-plugin: ' + event.data);
1096 };
1097 obj.addEventListener('message', callback);
1098 obj.postMessage('requestUrl: ' + $1);
1099 });
1100 )";
1101 std::string fetch_script = JsReplace(kFetchScriptTemplate, cross_origin_url);
1102 ASSERT_EQ(
1103 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1104 "runMe({ \"name\" : \"chromium\" });\n",
1105 EvalJs(web_contents, fetch_script));
1106
1107 // Crash the Network Service process and wait until host frame's
1108 // URLLoaderFactory has been refreshed.
1109 SimulateNetworkServiceCrash();
1110 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
1111
1112 // Try the fetch again - it should still work (i.e. the mechanism for relaxing
1113 // CORB for universal-access-plugins should be resilient to network process
1114 // crashes). See also https://crbug.com/891904.
1115 ASSERT_EQ(
1116 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1117 "runMe({ \"name\" : \"chromium\" });\n",
1118 EvalJs(web_contents, fetch_script));
1119}
1120#endif
1121
Clark DuVallf742bcbd2018-11-07 17:16:201122// TODO(crbug.com/901026): Fix deadlock on process startup on Android.
1123#if defined(OS_ANDROID)
1124#define MAYBE_SyncCallDuringRestart DISABLED_SyncCallDuringRestart
1125#else
1126#define MAYBE_SyncCallDuringRestart SyncCallDuringRestart
1127#endif
1128IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
1129 MAYBE_SyncCallDuringRestart) {
Clark DuVall3290462e2019-02-16 02:19:501130 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361131 return;
Clark DuVallf742bcbd2018-11-07 17:16:201132 network::mojom::NetworkServiceTestPtr network_service_test;
1133 base::RunLoop run_loop;
1134 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
1135 mojom::kNetworkServiceName, &network_service_test);
1136
1137 // Crash the network service, but do not wait for full startup.
1138 network_service_test.set_connection_error_handler(run_loop.QuitClosure());
1139 network_service_test->SimulateCrash();
1140 run_loop.Run();
1141
1142 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
1143 mojom::kNetworkServiceName, &network_service_test);
1144
1145 // Sync call should be fine, even though network process is still starting up.
1146 mojo::ScopedAllowSyncCallForTesting allow_sync_call;
1147 network_service_test->AddRules({});
1148}
1149
Chong Zhangc583e672017-11-08 16:34:081150} // namespace content