1 // 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
5 #include "base/bind.h"
6 #include "base/callback.h"
7 #include "base/files/file_util.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/synchronization/lock.h"
11 #include "base/test/bind.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "base/test/scoped_command_line.h"
14 #include "base/test/scoped_environment_variable_override.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/thread_annotations.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "build/build_config.h"
20 #include "content/browser/network_service_instance_impl.h"
21 #include "content/browser/renderer_host/render_frame_host_impl.h"
22 #include "content/browser/renderer_host/render_frame_message_filter.h"
23 #include "content/browser/renderer_host/render_process_host_impl.h"
24 #include "content/browser/service_worker/embedded_worker_instance.h"
25 #include "content/browser/service_worker/embedded_worker_status.h"
26 #include "content/browser/service_worker/service_worker_context_core_observer.h"
27 #include "content/browser/storage_partition_impl.h"
28 #include "content/browser/url_loader_factory_getter.h"
29 #include "content/browser/worker_host/test_shared_worker_service_impl.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/network_service_instance.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/common/content_switches.h"
35 #include "content/public/common/network_service_util.h"
36 #include "content/public/test/browser_test.h"
37 #include "content/public/test/browser_test_utils.h"
38 #include "content/public/test/content_browser_test.h"
39 #include "content/public/test/content_browser_test_utils.h"
40 #include "content/public/test/simple_url_loader_test_helper.h"
41 #include "content/public/test/test_utils.h"
42 #include "content/shell/browser/shell.h"
43 #include "content/shell/browser/shell_browser_context.h"
44 #include "content/test/did_commit_navigation_interceptor.h"
45 #include "content/test/io_thread_shared_url_loader_factory_owner.h"
46 #include "content/test/storage_partition_test_helpers.h"
47 #include "mojo/public/cpp/bindings/pending_remote.h"
48 #include "mojo/public/cpp/bindings/remote.h"
49 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
50 #include "net/dns/mock_host_resolver.h"
51 #include "net/test/embedded_test_server/http_request.h"
52 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
53 #include "services/network/public/cpp/simple_url_loader.h"
54 #include "services/network/public/mojom/network_service.mojom.h"
55 #include "services/network/public/mojom/network_service_test.mojom.h"
56 #include "third_party/blink/public/common/features.h"
57
58 #if BUILDFLAG(ENABLE_PLUGINS)
59 #include "content/public/test/ppapi_test_utils.h"
60 #endif
61
62 namespace content {
63
64 namespace {
65
66 using SharedURLLoaderFactoryGetterCallback =
67 base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;
68
CreateNetworkContext()69 mojo::PendingRemote<network::mojom::NetworkContext> CreateNetworkContext() {
70 mojo::PendingRemote<network::mojom::NetworkContext> network_context;
71 network::mojom::NetworkContextParamsPtr context_params =
72 network::mojom::NetworkContextParams::New();
73 context_params->cert_verifier_params =
74 GetCertVerifierParams(network::mojom::CertVerifierCreationParams::New());
75 GetNetworkService()->CreateNetworkContext(
76 network_context.InitWithNewPipeAndPassReceiver(),
77 std::move(context_params));
78 return network_context;
79 }
80
LoadBasicRequestOnUIThread(network::mojom::URLLoaderFactory * url_loader_factory,const GURL & url)81 int LoadBasicRequestOnUIThread(
82 network::mojom::URLLoaderFactory* url_loader_factory,
83 const GURL& url) {
84 DCHECK_CURRENTLY_ON(BrowserThread::UI);
85 auto request = std::make_unique<network::ResourceRequest>();
86 request->url = url;
87
88 SimpleURLLoaderTestHelper simple_loader_helper;
89 std::unique_ptr<network::SimpleURLLoader> simple_loader =
90 network::SimpleURLLoader::Create(std::move(request),
91 TRAFFIC_ANNOTATION_FOR_TESTS);
92 simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
93 url_loader_factory, simple_loader_helper.GetCallback());
94 simple_loader_helper.WaitForCallback();
95 return simple_loader->NetError();
96 }
97
GetTotalNetworkUsages()98 std::vector<network::mojom::NetworkUsagePtr> GetTotalNetworkUsages() {
99 std::vector<network::mojom::NetworkUsagePtr> network_usages;
100 base::RunLoop run_loop;
101 GetNetworkService()->GetTotalNetworkUsages(base::BindOnce(
102 [](std::vector<network::mojom::NetworkUsagePtr>* p_network_usages,
103 base::OnceClosure quit_closure,
104 std::vector<network::mojom::NetworkUsagePtr> returned_usages) {
105 *p_network_usages = std::move(returned_usages);
106 std::move(quit_closure).Run();
107 },
108 base::Unretained(&network_usages), run_loop.QuitClosure()));
109 run_loop.Run();
110 return network_usages;
111 }
112
CheckContainsProcessID(const std::vector<network::mojom::NetworkUsagePtr> & usages,int process_id)113 bool CheckContainsProcessID(
114 const std::vector<network::mojom::NetworkUsagePtr>& usages,
115 int process_id) {
116 for (const auto& usage : usages) {
117 if ((int)usage->process_id == process_id)
118 return true;
119 }
120 return false;
121 }
122
123 // Wait until |condition| returns true.
WaitForCondition(base::RepeatingCallback<bool ()> condition)124 void WaitForCondition(base::RepeatingCallback<bool()> condition) {
125 while (!condition.Run()) {
126 base::RunLoop run_loop;
127 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
128 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
129 run_loop.Run();
130 }
131 }
132
133 class ServiceWorkerStatusObserver : public ServiceWorkerContextCoreObserver {
134 public:
WaitForStopped()135 void WaitForStopped() {
136 if (stopped_)
137 return;
138
139 base::RunLoop loop;
140 callback_ = loop.QuitClosure();
141 loop.Run();
142 }
143
144 private:
OnStopped(int64_t version_id)145 void OnStopped(int64_t version_id) override {
146 stopped_ = true;
147
148 if (callback_)
149 std::move(callback_).Run();
150 }
151
152 bool stopped_ = false;
153 base::OnceClosure callback_;
154 };
155
156 } // namespace
157
158 class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
159 public:
NetworkServiceRestartBrowserTest()160 NetworkServiceRestartBrowserTest() {}
161
SetUpCommandLine(base::CommandLine * command_line)162 void SetUpCommandLine(base::CommandLine* command_line) override {
163 #if BUILDFLAG(ENABLE_PLUGINS)
164 ASSERT_TRUE(ppapi::RegisterCorbTestPlugin(command_line));
165 #endif
166 ContentBrowserTest::SetUpCommandLine(command_line);
167 }
168
SetUpOnMainThread()169 void SetUpOnMainThread() override {
170 embedded_test_server()->RegisterRequestMonitor(
171 base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
172 base::Unretained(this)));
173 host_resolver()->AddRule("*", "127.0.0.1");
174 EXPECT_TRUE(embedded_test_server()->Start());
175 ContentBrowserTest::SetUpOnMainThread();
176 }
177
GetTestURL() const178 GURL GetTestURL() const {
179 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
180 // See https://crbug.com/792255.
181 return embedded_test_server()->GetURL("/echoheader");
182 }
183
browser_context()184 BrowserContext* browser_context() {
185 return shell()->web_contents()->GetBrowserContext();
186 }
187
main_frame()188 RenderFrameHostImpl* main_frame() {
189 return static_cast<RenderFrameHostImpl*>(
190 shell()->web_contents()->GetMainFrame());
191 }
192
CheckCanLoadHttp(Shell * shell,const std::string & relative_url)193 bool CheckCanLoadHttp(Shell* shell, const std::string& relative_url) {
194 GURL test_url = embedded_test_server()->GetURL(relative_url);
195 std::string script(
196 "var xhr = new XMLHttpRequest();"
197 "xhr.open('GET', '");
198 script += test_url.spec() +
199 "', true);"
200 "xhr.onload = function (e) {"
201 " if (xhr.readyState === 4) {"
202 " window.domAutomationController.send(xhr.status === 200);"
203 " }"
204 "};"
205 "xhr.onerror = function () {"
206 " window.domAutomationController.send(false);"
207 "};"
208 "xhr.send(null)";
209 bool xhr_result = false;
210 // The JS call will fail if disallowed because the process will be killed.
211 bool execute_result =
212 ExecuteScriptAndExtractBool(shell, script, &xhr_result);
213 return xhr_result && execute_result;
214 }
215
216 // Will reuse the single opened windows through the test case.
CheckCanLoadHttpInWindowOpen(const std::string & relative_url)217 bool CheckCanLoadHttpInWindowOpen(const std::string& relative_url) {
218 GURL test_url = embedded_test_server()->GetURL(relative_url);
219 std::string inject_script = base::StringPrintf(
220 "var xhr = new XMLHttpRequest();"
221 "xhr.open('GET', '%s', true);"
222 "xhr.onload = function (e) {"
223 " if (xhr.readyState === 4) {"
224 " window.opener.domAutomationController.send(xhr.status === 200);"
225 " }"
226 "};"
227 "xhr.onerror = function () {"
228 " window.opener.domAutomationController.send(false);"
229 "};"
230 "xhr.send(null)",
231 test_url.spec().c_str());
232 std::string window_open_script = base::StringPrintf(
233 "var new_window = new_window || window.open('');"
234 "var inject_script = document.createElement('script');"
235 "inject_script.innerHTML = \"%s\";"
236 "new_window.document.body.appendChild(inject_script);",
237 inject_script.c_str());
238
239 bool xhr_result = false;
240 // The JS call will fail if disallowed because the process will be killed.
241 bool execute_result =
242 ExecuteScriptAndExtractBool(shell(), window_open_script, &xhr_result);
243 return xhr_result && execute_result;
244 }
245
246 // Workers will live throughout the test case unless terminated.
CheckCanWorkerFetch(const std::string & worker_name,const std::string & relative_url)247 bool CheckCanWorkerFetch(const std::string& worker_name,
248 const std::string& relative_url) {
249 GURL worker_url =
250 embedded_test_server()->GetURL("/workers/worker_common.js");
251 GURL fetch_url = embedded_test_server()->GetURL(relative_url);
252 std::string script = base::StringPrintf(
253 "var workers = workers || {};"
254 "var worker_name = '%s';"
255 "workers[worker_name] = workers[worker_name] || new Worker('%s');"
256 "workers[worker_name].onmessage = evt => {"
257 " if (evt.data != 'wait')"
258 " window.domAutomationController.send(evt.data === 200);"
259 "};"
260 "workers[worker_name].postMessage(\"eval "
261 " fetch(new Request('%s'))"
262 " .then(res => postMessage(res.status))"
263 " .catch(error => postMessage(error.toString()));"
264 " 'wait'"
265 "\");",
266 worker_name.c_str(), worker_url.spec().c_str(),
267 fetch_url.spec().c_str());
268 bool fetch_result = false;
269 // The JS call will fail if disallowed because the process will be killed.
270 bool execute_result =
271 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
272 return fetch_result && execute_result;
273 }
274
275 // Terminate and delete the worker.
TerminateWorker(const std::string & worker_name)276 bool TerminateWorker(const std::string& worker_name) {
277 std::string script = base::StringPrintf(
278 "var workers = workers || {};"
279 "var worker_name = '%s';"
280 "if (workers[worker_name]) {"
281 " workers[worker_name].terminate();"
282 " delete workers[worker_name];"
283 " window.domAutomationController.send(true);"
284 "} else {"
285 " window.domAutomationController.send(false);"
286 "}",
287 worker_name.c_str());
288 bool fetch_result = false;
289 // The JS call will fail if disallowed because the process will be killed.
290 bool execute_result =
291 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
292 return fetch_result && execute_result;
293 }
294
295 // Called by |embedded_test_server()|.
MonitorRequest(const net::test_server::HttpRequest & request)296 void MonitorRequest(const net::test_server::HttpRequest& request) {
297 base::AutoLock lock(last_request_lock_);
298 last_request_relative_url_ = request.relative_url;
299 }
300
last_request_relative_url() const301 std::string last_request_relative_url() const {
302 base::AutoLock lock(last_request_lock_);
303 return last_request_relative_url_;
304 }
305
306 private:
307 mutable base::Lock last_request_lock_;
308 std::string last_request_relative_url_ GUARDED_BY(last_request_lock_);
309
310 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
311 };
312
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,NetworkServiceProcessRecovery)313 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
314 NetworkServiceProcessRecovery) {
315 if (IsInProcessNetworkService())
316 return;
317 mojo::Remote<network::mojom::NetworkContext> network_context(
318 CreateNetworkContext());
319 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
320 EXPECT_TRUE(network_context.is_bound());
321 EXPECT_TRUE(network_context.is_connected());
322
323 // Crash the NetworkService process. Existing interfaces should receive error
324 // notifications at some point.
325 SimulateNetworkServiceCrash();
326 // |network_context| will receive an error notification, but it's not
327 // guaranteed to have arrived at this point. Flush the remote to make sure
328 // the notification has been received.
329 network_context.FlushForTesting();
330 EXPECT_TRUE(network_context.is_bound());
331 EXPECT_FALSE(network_context.is_connected());
332 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
333 EXPECT_EQ(net::ERR_FAILED,
334 LoadBasicRequest(network_context.get(), GetTestURL()));
335
336 // NetworkService should restart automatically and return valid interface.
337 mojo::Remote<network::mojom::NetworkContext> network_context2(
338 CreateNetworkContext());
339 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
340 EXPECT_TRUE(network_context2.is_bound());
341 EXPECT_TRUE(network_context2.is_connected());
342 }
343
IncrementInt(int * i)344 void IncrementInt(int* i) {
345 *i = *i + 1;
346 }
347
348 // This test verifies basic functionality of RegisterNetworkServiceCrashHandler
349 // and UnregisterNetworkServiceCrashHandler.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,CrashHandlers)350 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, CrashHandlers) {
351 if (IsInProcessNetworkService())
352 return;
353 mojo::Remote<network::mojom::NetworkContext> network_context(
354 CreateNetworkContext());
355 EXPECT_TRUE(network_context.is_bound());
356
357 // Register 2 crash handlers.
358 int counter1 = 0;
359 int counter2 = 0;
360 auto handler1 = RegisterNetworkServiceCrashHandler(
361 base::BindRepeating(&IncrementInt, base::Unretained(&counter1)));
362 auto handler2 = RegisterNetworkServiceCrashHandler(
363 base::BindRepeating(&IncrementInt, base::Unretained(&counter2)));
364
365 // Crash the NetworkService process.
366 SimulateNetworkServiceCrash();
367 // |network_context| will receive an error notification, but it's not
368 // guaranteed to have arrived at this point. Flush the remote to make sure
369 // the notification has been received.
370 network_context.FlushForTesting();
371 EXPECT_TRUE(network_context.is_bound());
372 EXPECT_FALSE(network_context.is_connected());
373
374 // Verify the crash handlers executed.
375 EXPECT_EQ(1, counter1);
376 EXPECT_EQ(1, counter2);
377
378 // Revive the NetworkService process.
379 network_context.reset();
380 network_context.Bind(CreateNetworkContext());
381 EXPECT_TRUE(network_context.is_bound());
382
383 // Unregister one of the handlers.
384 handler2.reset();
385
386 // Crash the NetworkService process.
387 SimulateNetworkServiceCrash();
388 // |network_context| will receive an error notification, but it's not
389 // guaranteed to have arrived at this point. Flush the remote to make sure
390 // the notification has been received.
391 network_context.FlushForTesting();
392 EXPECT_TRUE(network_context.is_bound());
393 EXPECT_FALSE(network_context.is_connected());
394
395 // Verify only the first crash handler executed.
396 EXPECT_EQ(2, counter1);
397 EXPECT_EQ(1, counter2);
398 }
399
400 // Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
401 // after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,StoragePartitionImplGetNetworkContext)402 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
403 StoragePartitionImplGetNetworkContext) {
404 if (IsInProcessNetworkService())
405 return;
406 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
407 BrowserContext::GetDefaultStoragePartition(browser_context()));
408
409 network::mojom::NetworkContext* old_network_context =
410 partition->GetNetworkContext();
411 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
412
413 // Crash the NetworkService process. Existing interfaces should receive error
414 // notifications at some point.
415 SimulateNetworkServiceCrash();
416 // Flush the interface to make sure the error notification was received.
417 partition->FlushNetworkInterfaceForTesting();
418
419 // |partition->GetNetworkContext()| should return a valid new pointer after
420 // crash.
421 EXPECT_NE(old_network_context, partition->GetNetworkContext());
422 EXPECT_EQ(net::OK,
423 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
424 }
425
426 // Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,URLLoaderFactoryGetterGetNetworkFactory)427 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
428 URLLoaderFactoryGetterGetNetworkFactory) {
429 if (IsInProcessNetworkService())
430 return;
431 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
432 BrowserContext::GetDefaultStoragePartition(browser_context()));
433 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
434 partition->url_loader_factory_getter();
435
436 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
437 url_loader_factory_getter.get());
438 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
439
440 // Crash the NetworkService process. Existing interfaces should receive error
441 // notifications at some point.
442 SimulateNetworkServiceCrash();
443 // Flush the interface to make sure the error notification was received.
444 partition->FlushNetworkInterfaceForTesting();
445 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
446
447 // |url_loader_factory_getter| should be able to get a valid new pointer after
448 // crash.
449 factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
450 url_loader_factory_getter.get());
451 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
452 }
453
454 // Make sure the factory returned from
455 // |URLLoaderFactoryGetter::GetNetworkFactory()| continues to work after
456 // crashes.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BrowserIOSharedURLLoaderFactory)457 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
458 BrowserIOSharedURLLoaderFactory) {
459 if (IsInProcessNetworkService())
460 return;
461 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
462 BrowserContext::GetDefaultStoragePartition(browser_context()));
463
464 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
465 partition->url_loader_factory_getter().get());
466
467 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
468
469 // Crash the NetworkService process. Existing interfaces should receive error
470 // notifications at some point.
471 SimulateNetworkServiceCrash();
472 // Flush the interface to make sure the error notification was received.
473 partition->FlushNetworkInterfaceForTesting();
474 partition->url_loader_factory_getter()
475 ->FlushNetworkInterfaceOnIOThreadForTesting();
476
477 // |shared_factory| should continue to work.
478 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
479 }
480
481 // Make sure the factory returned from
482 // |URLLoaderFactoryGetter::GetNetworkFactory()| doesn't crash if
483 // it's called after the StoragePartition is deleted.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BrowserIOSharedFactoryAfterStoragePartitionGone)484 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
485 BrowserIOSharedFactoryAfterStoragePartitionGone) {
486 if (IsInProcessNetworkService())
487 return;
488 base::ScopedAllowBlockingForTesting allow_blocking;
489 std::unique_ptr<ShellBrowserContext> browser_context =
490 std::make_unique<ShellBrowserContext>(true);
491 auto* partition = static_cast<StoragePartitionImpl*>(
492 BrowserContext::GetDefaultStoragePartition(browser_context.get()));
493 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
494 partition->url_loader_factory_getter().get());
495
496 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
497
498 browser_context.reset();
499
500 EXPECT_EQ(net::ERR_FAILED,
501 factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
502 }
503
504 // Make sure basic navigation works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,NavigationURLLoaderBasic)505 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
506 NavigationURLLoaderBasic) {
507 if (IsInProcessNetworkService())
508 return;
509 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
510 BrowserContext::GetDefaultStoragePartition(browser_context()));
511
512 EXPECT_TRUE(
513 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
514
515 // Crash the NetworkService process. Existing interfaces should receive error
516 // notifications at some point.
517 SimulateNetworkServiceCrash();
518 // Flush the interface to make sure the error notification was received.
519 partition->FlushNetworkInterfaceForTesting();
520 partition->url_loader_factory_getter()
521 ->FlushNetworkInterfaceOnIOThreadForTesting();
522
523 EXPECT_TRUE(
524 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
525 }
526
527 // Make sure basic XHR works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BasicXHR)528 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
529 if (IsInProcessNetworkService())
530 return;
531 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
532 BrowserContext::GetDefaultStoragePartition(browser_context()));
533
534 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
535 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title1.html"));
536 EXPECT_EQ(last_request_relative_url(), "/title1.html");
537
538 // Crash the NetworkService process. Existing interfaces should receive error
539 // notifications at some point.
540 SimulateNetworkServiceCrash();
541 // Flush the interface to make sure the error notification was received.
542 partition->FlushNetworkInterfaceForTesting();
543 // Flush the interface to make sure the frame host has received error
544 // notification and the new URLLoaderFactoryBundle has been received by the
545 // frame.
546 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
547
548 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
549 EXPECT_EQ(last_request_relative_url(), "/title2.html");
550 }
551
552 // Make sure the factory returned from
553 // |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| continues to work
554 // after crashes.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BrowserUIFactory)555 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserUIFactory) {
556 if (IsInProcessNetworkService())
557 return;
558 auto* partition =
559 BrowserContext::GetDefaultStoragePartition(browser_context());
560 auto* factory = partition->GetURLLoaderFactoryForBrowserProcess().get();
561
562 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
563
564 SimulateNetworkServiceCrash();
565 // Flush the interface to make sure the error notification was received.
566 partition->FlushNetworkInterfaceForTesting();
567
568 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
569 }
570
571 // Make sure the factory returned from
572 // |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| doesn't crash if
573 // it's called after the StoragePartition is deleted.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BrowserUIFactoryAfterStoragePartitionGone)574 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
575 BrowserUIFactoryAfterStoragePartitionGone) {
576 if (IsInProcessNetworkService())
577 return;
578 base::ScopedAllowBlockingForTesting allow_blocking;
579 std::unique_ptr<ShellBrowserContext> browser_context =
580 std::make_unique<ShellBrowserContext>(true);
581 auto* partition =
582 BrowserContext::GetDefaultStoragePartition(browser_context.get());
583 scoped_refptr<network::SharedURLLoaderFactory> factory(
584 partition->GetURLLoaderFactoryForBrowserProcess());
585
586 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
587
588 browser_context.reset();
589
590 EXPECT_EQ(net::ERR_FAILED,
591 LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
592 }
593
594 // Make sure the factory pending factory returned from
595 // |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| can be
596 // used after crashes.
597 // Flaky on Windows. https://crbug.com/840127
598 #if defined(OS_WIN)
599 #define MAYBE_BrowserIOPendingFactory DISABLED_BrowserIOPendingFactory
600 #else
601 #define MAYBE_BrowserIOPendingFactory BrowserIOPendingFactory
602 #endif
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,MAYBE_BrowserIOPendingFactory)603 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
604 MAYBE_BrowserIOPendingFactory) {
605 if (IsInProcessNetworkService())
606 return;
607 auto* partition =
608 BrowserContext::GetDefaultStoragePartition(browser_context());
609 auto pending_shared_url_loader_factory =
610 partition->GetURLLoaderFactoryForBrowserProcessIOThread();
611
612 SimulateNetworkServiceCrash();
613 // Flush the interface to make sure the error notification was received.
614 partition->FlushNetworkInterfaceForTesting();
615 static_cast<StoragePartitionImpl*>(partition)
616 ->url_loader_factory_getter()
617 ->FlushNetworkInterfaceOnIOThreadForTesting();
618
619 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
620 std::move(pending_shared_url_loader_factory));
621
622 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
623 }
624
625 // Make sure the factory constructed from
626 // |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| continues
627 // to work after crashes.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,BrowserIOFactory)628 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
629 if (IsInProcessNetworkService())
630 return;
631 auto* partition =
632 BrowserContext::GetDefaultStoragePartition(browser_context());
633 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
634 partition->GetURLLoaderFactoryForBrowserProcessIOThread());
635
636 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
637
638 SimulateNetworkServiceCrash();
639 // Flush the interface to make sure the error notification was received.
640 partition->FlushNetworkInterfaceForTesting();
641 static_cast<StoragePartitionImpl*>(partition)
642 ->url_loader_factory_getter()
643 ->FlushNetworkInterfaceOnIOThreadForTesting();
644
645 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
646 }
647
648 // Make sure the window from |window.open()| can load XHR after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,WindowOpenXHR)649 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, WindowOpenXHR) {
650 if (IsInProcessNetworkService())
651 return;
652 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
653 BrowserContext::GetDefaultStoragePartition(browser_context()));
654
655 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
656 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title1.html"));
657 EXPECT_EQ(last_request_relative_url(), "/title1.html");
658
659 // Crash the NetworkService process. Existing interfaces should receive error
660 // notifications at some point.
661 SimulateNetworkServiceCrash();
662 // Flush the interface to make sure the error notification was received.
663 partition->FlushNetworkInterfaceForTesting();
664 // Flush the interface to make sure the frame host has received error
665 // notification and the new URLLoaderFactoryBundle has been received by the
666 // frame.
667 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
668
669 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title2.html"));
670 EXPECT_EQ(last_request_relative_url(), "/title2.html");
671 }
672
673 // Run tests with PlzDedicatedWorker.
674 // TODO(https://crbug.com/906991): Merge this test fixture into
675 // NetworkServiceRestartBrowserTest once PlzDedicatedWorker is enabled by
676 // default.
677 class NetworkServiceRestartForWorkerBrowserTest
678 : public NetworkServiceRestartBrowserTest,
679 public ::testing::WithParamInterface<bool> {
680 public:
NetworkServiceRestartForWorkerBrowserTest()681 NetworkServiceRestartForWorkerBrowserTest() {
682 if (GetParam()) {
683 scoped_feature_list_.InitAndEnableFeature(
684 blink::features::kPlzDedicatedWorker);
685 } else {
686 scoped_feature_list_.InitAndDisableFeature(
687 blink::features::kPlzDedicatedWorker);
688 }
689 }
690
691 private:
692 base::test::ScopedFeatureList scoped_feature_list_;
693 };
694
695 INSTANTIATE_TEST_SUITE_P(All,
696 NetworkServiceRestartForWorkerBrowserTest,
697 ::testing::Values(false, true));
698
699 // Make sure worker fetch works after crash.
IN_PROC_BROWSER_TEST_P(NetworkServiceRestartForWorkerBrowserTest,WorkerFetch)700 IN_PROC_BROWSER_TEST_P(NetworkServiceRestartForWorkerBrowserTest, WorkerFetch) {
701 if (IsInProcessNetworkService())
702 return;
703 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
704 BrowserContext::GetDefaultStoragePartition(browser_context()));
705
706 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
707 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
708 EXPECT_EQ(last_request_relative_url(), "/title1.html");
709
710 // Crash the NetworkService process. Existing interfaces should receive error
711 // notifications at some point.
712 SimulateNetworkServiceCrash();
713 // Flush the interface to make sure the error notification was received.
714 partition->FlushNetworkInterfaceForTesting();
715 // Flush the interface to make sure the frame host has received error
716 // notification and the new URLLoaderFactoryBundle has been received by the
717 // frame.
718 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
719
720 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
721 EXPECT_EQ(last_request_relative_url(), "/title2.html");
722 }
723
724 // Make sure multiple workers are tracked correctly and work after crash.
IN_PROC_BROWSER_TEST_P(NetworkServiceRestartForWorkerBrowserTest,MultipleWorkerFetch)725 IN_PROC_BROWSER_TEST_P(NetworkServiceRestartForWorkerBrowserTest,
726 MultipleWorkerFetch) {
727 if (IsInProcessNetworkService())
728 return;
729 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
730 BrowserContext::GetDefaultStoragePartition(browser_context()));
731
732 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
733 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
734 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
735 EXPECT_EQ(last_request_relative_url(), "/title1.html");
736
737 // Crash the NetworkService process. Existing interfaces should receive error
738 // notifications at some point.
739 SimulateNetworkServiceCrash();
740 // Flush the interface to make sure the error notification was received.
741 partition->FlushNetworkInterfaceForTesting();
742 // Flush the interface to make sure the frame host has received error
743 // notification and the new URLLoaderFactoryBundle has been received by the
744 // frame.
745 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
746
747 // Both workers should work after crash.
748 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
749 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
750 EXPECT_EQ(last_request_relative_url(), "/title2.html");
751
752 // Terminate "worker1". "worker2" shouldn't be affected.
753 EXPECT_TRUE(TerminateWorker("worker1"));
754 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
755 EXPECT_EQ(last_request_relative_url(), "/title1.html");
756
757 // Crash the NetworkService process again. "worker2" should still work.
758 SimulateNetworkServiceCrash();
759 partition->FlushNetworkInterfaceForTesting();
760 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
761
762 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
763 EXPECT_EQ(last_request_relative_url(), "/title2.html");
764 }
765
766 // Make sure fetch from a page controlled by a service worker which doesn't have
767 // a fetch handler works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,FetchFromServiceWorkerControlledPage_NoFetchHandler)768 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
769 FetchFromServiceWorkerControlledPage_NoFetchHandler) {
770 if (IsInProcessNetworkService())
771 return;
772 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
773 BrowserContext::GetDefaultStoragePartition(browser_context()));
774 ServiceWorkerStatusObserver observer;
775 ServiceWorkerContextWrapper* service_worker_context =
776 partition->GetServiceWorkerContext();
777 service_worker_context->AddObserver(&observer);
778
779 // Register a service worker which controls /service_worker/.
780 EXPECT_TRUE(NavigateToURL(shell(),
781 embedded_test_server()->GetURL(
782 "/service_worker/create_service_worker.html")));
783 EXPECT_EQ("DONE", EvalJs(shell(), "register('empty.js')"));
784
785 // Navigate to a controlled page.
786 EXPECT_TRUE(NavigateToURL(
787 shell(),
788 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
789
790 // Fetch from the controlled page.
791 const std::string script = "fetch_from_page('/echo');";
792 EXPECT_EQ("Echo", EvalJs(shell(), script));
793
794 // Crash the NetworkService process. Existing interfaces should receive error
795 // notifications at some point.
796 SimulateNetworkServiceCrash();
797 // Flush the interface to make sure the error notification was received.
798 partition->FlushNetworkInterfaceForTesting();
799
800 // Service worker should be stopped when network service crashes.
801 observer.WaitForStopped();
802
803 // Fetch from the controlled page again.
804 EXPECT_EQ("Echo", EvalJs(shell(), script));
805
806 service_worker_context->RemoveObserver(&observer);
807 }
808
809 // Make sure fetch from a page controlled by a service worker which has a fetch
810 // handler but falls back to the network works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,FetchFromServiceWorkerControlledPage_PassThrough)811 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
812 FetchFromServiceWorkerControlledPage_PassThrough) {
813 if (IsInProcessNetworkService())
814 return;
815 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
816 BrowserContext::GetDefaultStoragePartition(browser_context()));
817 ServiceWorkerStatusObserver observer;
818 ServiceWorkerContextWrapper* service_worker_context =
819 partition->GetServiceWorkerContext();
820 service_worker_context->AddObserver(&observer);
821
822 // Register a service worker which controls /service_worker/.
823 EXPECT_TRUE(NavigateToURL(shell(),
824 embedded_test_server()->GetURL(
825 "/service_worker/create_service_worker.html")));
826 EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_pass_through.js')"));
827
828 // Navigate to a controlled page.
829 EXPECT_TRUE(NavigateToURL(
830 shell(),
831 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
832
833 // Fetch from the controlled page.
834 const std::string script = "fetch_from_page('/echo');";
835 EXPECT_EQ("Echo", EvalJs(shell(), script));
836
837 // Crash the NetworkService process. Existing interfaces should receive error
838 // notifications at some point.
839 SimulateNetworkServiceCrash();
840 // Flush the interface to make sure the error notification was received.
841 partition->FlushNetworkInterfaceForTesting();
842
843 // Service worker should be stopped when network service crashes.
844 observer.WaitForStopped();
845
846 // Fetch from the controlled page again.
847 EXPECT_EQ("Echo", EvalJs(shell(), script));
848
849 service_worker_context->RemoveObserver(&observer);
850 }
851
852 // Make sure fetch from a page controlled by a service worker which has a fetch
853 // handler and responds with fetch() works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,FetchFromServiceWorkerControlledPage_RespondWithFetch)854 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
855 FetchFromServiceWorkerControlledPage_RespondWithFetch) {
856 if (IsInProcessNetworkService())
857 return;
858 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
859 BrowserContext::GetDefaultStoragePartition(browser_context()));
860 ServiceWorkerStatusObserver observer;
861 ServiceWorkerContextWrapper* service_worker_context =
862 partition->GetServiceWorkerContext();
863 service_worker_context->AddObserver(&observer);
864
865 // Register a service worker which controls /service_worker/.
866 EXPECT_TRUE(NavigateToURL(shell(),
867 embedded_test_server()->GetURL(
868 "/service_worker/create_service_worker.html")));
869 EXPECT_EQ("DONE",
870 EvalJs(shell(), "register('fetch_event_respond_with_fetch.js')"));
871
872 // Navigate to a controlled page.
873 EXPECT_TRUE(NavigateToURL(
874 shell(),
875 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
876
877 // Fetch from the controlled page.
878 const std::string script = "fetch_from_page('/echo');";
879 EXPECT_EQ("Echo", EvalJs(shell(), script));
880
881 // Crash the NetworkService process. Existing interfaces should receive error
882 // notifications at some point.
883 SimulateNetworkServiceCrash();
884 // Flush the interface to make sure the error notification was received.
885 partition->FlushNetworkInterfaceForTesting();
886
887 // Service worker should be stopped when network service crashes.
888 observer.WaitForStopped();
889
890 // Fetch from the controlled page again.
891 EXPECT_EQ("Echo", EvalJs(shell(), script));
892
893 service_worker_context->RemoveObserver(&observer);
894 }
895
896 // Make sure fetch from service worker context works after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,ServiceWorkerFetch)897 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) {
898 if (IsInProcessNetworkService())
899 return;
900 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
901 BrowserContext::GetDefaultStoragePartition(browser_context()));
902 ServiceWorkerStatusObserver observer;
903 ServiceWorkerContextWrapper* service_worker_context =
904 partition->GetServiceWorkerContext();
905 service_worker_context->AddObserver(&observer);
906
907 const GURL page_url = embedded_test_server()->GetURL(
908 "/service_worker/fetch_from_service_worker.html");
909 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
910
911 // Navigate to the page and register a service worker.
912 EXPECT_TRUE(NavigateToURL(shell(), page_url));
913 EXPECT_EQ("ready", EvalJs(shell(), "setup();"));
914
915 // Fetch from the service worker.
916 const std::string script =
917 "fetch_from_service_worker('" + fetch_url.spec() + "');";
918 EXPECT_EQ("Echo", EvalJs(shell(), script));
919
920 // Crash the NetworkService process. Existing interfaces should receive error
921 // notifications at some point.
922 SimulateNetworkServiceCrash();
923 // Flush the interface to make sure the error notification was received.
924 partition->FlushNetworkInterfaceForTesting();
925
926 // Service worker should be stopped when network service crashes.
927 observer.WaitForStopped();
928
929 // Fetch from the service worker again.
930 EXPECT_EQ("Echo", EvalJs(shell(), script));
931
932 service_worker_context->RemoveObserver(&observer);
933 }
934
935 // TODO(crbug.com/154571): Shared workers are not available on Android.
936 #if defined(OS_ANDROID)
937 #define MAYBE_SharedWorker DISABLED_SharedWorker
938 #else
939 #define MAYBE_SharedWorker SharedWorker
940 #endif
941 // Make sure shared workers terminate after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,MAYBE_SharedWorker)942 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MAYBE_SharedWorker) {
943 if (IsInProcessNetworkService())
944 return;
945 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
946 BrowserContext::GetDefaultStoragePartition(browser_context()));
947
948 InjectTestSharedWorkerService(partition);
949
950 const GURL page_url =
951 embedded_test_server()->GetURL("/workers/fetch_from_shared_worker.html");
952 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
953
954 // Navigate to the page and prepare a shared worker.
955 EXPECT_TRUE(NavigateToURL(shell(), page_url));
956
957 // Fetch from the shared worker to ensure it has started.
958 const std::string script =
959 "fetch_from_shared_worker('" + fetch_url.spec() + "');";
960 EXPECT_EQ("Echo", EvalJs(shell(), script));
961
962 // There should be one worker host. We will later wait for it to terminate.
963 TestSharedWorkerServiceImpl* service =
964 static_cast<TestSharedWorkerServiceImpl*>(
965 partition->GetSharedWorkerService());
966 EXPECT_EQ(1u, service->worker_hosts_.size());
967 base::RunLoop loop;
968 service->SetWorkerTerminationCallback(loop.QuitClosure());
969
970 // Crash the NetworkService process.
971 SimulateNetworkServiceCrash();
972
973 // Wait for the worker to detect the crash and self-terminate.
974 loop.Run();
975 EXPECT_TRUE(service->worker_hosts_.empty());
976 }
977
978 // Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
979 // after process closed.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,GetNetworkUsagesClosed)980 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
981 GetNetworkUsagesClosed) {
982 if (IsInProcessNetworkService())
983 return;
984 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 // Closing |shell2| should cause the entry to be cleared.
1003 shell2->Close();
1004 shell2 = nullptr;
1005
1006 // Wait until the Network Service has noticed the change. We don't have a
1007 // better way to force a flush on the Network Service side.
1008 WaitForCondition(base::BindRepeating(
1009 [](int process_id) {
1010 auto usages = GetTotalNetworkUsages();
1011 return !CheckContainsProcessID(usages, process_id);
1012 },
1013 process_id2));
1014
1015 network_usages = GetTotalNetworkUsages();
1016 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1017 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1018 }
1019
1020 // Make sure that kSSLKeyLogFileHistogram is correctly recorded when the
1021 // network service instance is started and the SSLKEYLOGFILE env var is set or
1022 // the "--ssl-key-log-file" arg is set.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,SSLKeyLogFileMetrics)1023 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, SSLKeyLogFileMetrics) {
1024 if (IsInProcessNetworkService())
1025 return;
1026 // Actions on temporary files are blocking.
1027 base::ScopedAllowBlockingForTesting scoped_allow_blocking;
1028 base::FilePath log_file_path;
1029 base::CreateTemporaryFile(&log_file_path);
1030
1031 #if defined(OS_WIN)
1032 // On Windows, FilePath::value() returns base::string16, so convert.
1033 std::string log_file_path_str = base::UTF16ToUTF8(log_file_path.value());
1034 #else
1035 std::string log_file_path_str = log_file_path.value();
1036 #endif
1037
1038 // Test that env var causes the histogram to be recorded.
1039 {
1040 base::test::ScopedEnvironmentVariableOverride scoped_env("SSLKEYLOGFILE",
1041 log_file_path_str);
1042 base::HistogramTester histograms;
1043 // Restart network service to cause SSLKeyLogger to be re-initialized.
1044 SimulateNetworkServiceCrash();
1045 histograms.ExpectBucketCount(kSSLKeyLogFileHistogram,
1046 SSLKeyLogFileAction::kLogFileEnabled, 1);
1047 histograms.ExpectBucketCount(kSSLKeyLogFileHistogram,
1048 SSLKeyLogFileAction::kEnvVarFound, 1);
1049 }
1050
1051 // Test that the command-line switch causes the histogram to be recorded.
1052 {
1053 base::test::ScopedCommandLine scoped_command_line;
1054 scoped_command_line.GetProcessCommandLine()->AppendSwitchPath(
1055 "ssl-key-log-file", log_file_path);
1056 base::HistogramTester histograms;
1057 // Restart network service to cause SSLKeyLogger to be re-initialized.
1058 SimulateNetworkServiceCrash();
1059 histograms.ExpectBucketCount(kSSLKeyLogFileHistogram,
1060 SSLKeyLogFileAction::kLogFileEnabled, 1);
1061 histograms.ExpectBucketCount(kSSLKeyLogFileHistogram,
1062 SSLKeyLogFileAction::kSwitchFound, 1);
1063 }
1064 }
1065
1066 // Make sure |NetworkService::GetTotalNetworkUsages()| continues to work after
1067 // crash. See 'network_usage_accumulator_unittest' for quantified tests.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,GetNetworkUsagesCrashed)1068 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
1069 GetNetworkUsagesCrashed) {
1070 if (IsInProcessNetworkService())
1071 return;
1072 EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
1073 Shell* shell2 = CreateBrowser();
1074 EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
1075
1076 int process_id1 =
1077 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
1078 int process_id2 =
1079 shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
1080
1081 // Load resource on the renderer to make sure the traffic was recorded.
1082 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
1083 EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
1084
1085 // Both processes should have traffic recorded.
1086 auto network_usages = GetTotalNetworkUsages();
1087 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1088 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
1089
1090 // Crashing Network Service should cause all entries to be cleared.
1091 SimulateNetworkServiceCrash();
1092 network_usages = GetTotalNetworkUsages();
1093 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id1));
1094 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1095
1096 // Should still be able to recored new traffic after crash.
1097 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
1098 network_usages = GetTotalNetworkUsages();
1099 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1100 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1101 }
1102
1103 // Make sure cookie access doesn't hang or fail after a network process crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,Cookies)1104 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
1105 if (IsInProcessNetworkService())
1106 return;
1107 auto* web_contents = shell()->web_contents();
1108 ASSERT_TRUE(
1109 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
1110 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1111
1112 std::string cookie;
1113 EXPECT_TRUE(ExecuteScriptAndExtractString(
1114 web_contents, "window.domAutomationController.send(document.cookie);",
1115 &cookie));
1116 EXPECT_EQ("foo=bar", cookie);
1117
1118 SimulateNetworkServiceCrash();
1119
1120 // content_shell uses in-memory cookie database, so the value saved earlier
1121 // won't persist across crashes. What matters is that new access works.
1122 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1123
1124 // This will hang without the fix.
1125 EXPECT_TRUE(ExecuteScriptAndExtractString(
1126 web_contents, "window.domAutomationController.send(document.cookie);",
1127 &cookie));
1128 EXPECT_EQ("foo=bar", cookie);
1129 }
1130
1131 #if BUILDFLAG(ENABLE_PLUGINS)
1132 // Make sure that "trusted" plugins continue to be able to issue cross-origin
1133 // requests after a network process crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,Plugin)1134 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Plugin) {
1135 if (IsInProcessNetworkService())
1136 return;
1137 auto* web_contents = shell()->web_contents();
1138 ASSERT_TRUE(NavigateToURL(web_contents,
1139 embedded_test_server()->GetURL("/title1.html")));
1140
1141 // Load the test plugin (see ppapi::RegisterCorbTestPlugin).
1142 const char kLoadingScript[] = R"(
1143 var obj = document.createElement('object');
1144 obj.id = 'plugin';
1145 obj.data = 'test.swf';
1146 obj.type = 'application/x-shockwave-flash';
1147 obj.width = 400;
1148 obj.height = 400;
1149
1150 document.body.appendChild(obj);
1151 )";
1152 ASSERT_TRUE(ExecJs(web_contents, kLoadingScript));
1153
1154 // Ask the plugin to perform a cross-origin, CORB-eligible (i.e.
1155 // application/json + nosniff) URL request. Plugins with universal access
1156 // should not be subject to CORS/CORB and so the request should go through.
1157 // See also https://crbug.com/874515 and https://crbug.com/846339.
1158 GURL cross_origin_url = embedded_test_server()->GetURL(
1159 "cross.origin.com", "/site_isolation/nosniff.json");
1160 const char kFetchScriptTemplate[] = R"(
1161 new Promise(function (resolve, reject) {
1162 var obj = document.getElementById('plugin');
1163 function callback(event) {
1164 // Ignore plugin messages unrelated to requestUrl.
1165 if (!event.data.startsWith('requestUrl: '))
1166 return;
1167
1168 obj.removeEventListener('message', callback);
1169 resolve('msg-from-plugin: ' + event.data);
1170 };
1171 obj.addEventListener('message', callback);
1172 obj.postMessage('requestUrl: ' + $1);
1173 });
1174 )";
1175 std::string fetch_script = JsReplace(kFetchScriptTemplate, cross_origin_url);
1176 ASSERT_EQ(
1177 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1178 "runMe({ \"name\" : \"chromium\" });\n",
1179 EvalJs(web_contents, fetch_script));
1180
1181 // Crash the Network Service process and wait until host frame's
1182 // URLLoaderFactory has been refreshed.
1183 SimulateNetworkServiceCrash();
1184 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
1185
1186 // Try the fetch again - it should still work (i.e. the mechanism for relaxing
1187 // CORB for universal-access-plugins should be resilient to network process
1188 // crashes). See also https://crbug.com/891904.
1189 ASSERT_EQ(
1190 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1191 "runMe({ \"name\" : \"chromium\" });\n",
1192 EvalJs(web_contents, fetch_script));
1193 }
1194 #endif
1195
1196 // TODO(crbug.com/901026): Fix deadlock on process startup on Android.
1197 #if defined(OS_ANDROID)
1198 #define MAYBE_SyncCallDuringRestart DISABLED_SyncCallDuringRestart
1199 #else
1200 #define MAYBE_SyncCallDuringRestart SyncCallDuringRestart
1201 #endif
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,MAYBE_SyncCallDuringRestart)1202 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
1203 MAYBE_SyncCallDuringRestart) {
1204 if (IsInProcessNetworkService())
1205 return;
1206 base::RunLoop run_loop;
1207 mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
1208 content::GetNetworkService()->BindTestInterface(
1209 network_service_test.BindNewPipeAndPassReceiver());
1210
1211 // Crash the network service, but do not wait for full startup.
1212 network_service_test.set_disconnect_handler(run_loop.QuitClosure());
1213 network_service_test->SimulateCrash();
1214 run_loop.Run();
1215
1216 network_service_test.reset();
1217 content::GetNetworkService()->BindTestInterface(
1218 network_service_test.BindNewPipeAndPassReceiver());
1219
1220 // Sync call should be fine, even though network process is still starting up.
1221 mojo::ScopedAllowSyncCallForTesting allow_sync_call;
1222 network_service_test->AddRules({});
1223 }
1224
1225 // Tests handling of a NetworkService crash that happens after a navigation
1226 // triggers sending a Commit IPC to the renderer process, but before a DidCommit
1227 // IPC from the renderer process is handled. See also
1228 // https://crbug.com/1056949#c75.
1229 //
1230 // TODO(lukasza): https://crbug.com/1129592: Flaky on Android. No flakiness
1231 // observed whatsoever on Windows, Linux or CrOS.
1232 #if defined(OS_ANDROID)
1233 #define MAYBE_BetweenCommitNavigationAndDidCommit \
1234 DISABLED_BetweenCommitNavigationAndDidCommit
1235 #else
1236 #define MAYBE_BetweenCommitNavigationAndDidCommit \
1237 BetweenCommitNavigationAndDidCommit
1238 #endif
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,MAYBE_BetweenCommitNavigationAndDidCommit)1239 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
1240 MAYBE_BetweenCommitNavigationAndDidCommit) {
1241 if (IsInProcessNetworkService())
1242 return;
1243
1244 GURL initial_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
1245 EXPECT_TRUE(NavigateToURL(shell(), initial_url));
1246
1247 // Crash the NetworkService while CommitNavigation IPC is in-flight and before
1248 // DidCommit IPC is handled. This tests how RenderFrameHostImpl recreates the
1249 // URLLoaderFactory after NetworkService crash. In particular,
1250 // RenderFrameHostImpl::UpdateSubresourceLoaderFactories needs to use the
1251 // |request_initiator_origin_lock| associated with the in-flight IPC (because
1252 // the |RFHI::last_committed_origin_| won't be updated until DidCommit IPC is
1253 // handled).
1254 auto pre_did_commit_lambda = [&](RenderFrameHost* frame) {
1255 // Crash the NetworkService process. Existing interfaces should receive
1256 // error notifications at some point.
1257 SimulateNetworkServiceCrash();
1258
1259 // Flush the interface to make sure the error notification was received.
1260 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
1261 BrowserContext::GetDefaultStoragePartition(browser_context()));
1262 partition->FlushNetworkInterfaceForTesting();
1263 };
1264 CommitMessageDelayer::DidCommitCallback pre_did_commit_callback =
1265 base::BindLambdaForTesting(std::move(pre_did_commit_lambda));
1266 GURL final_page_url(
1267 embedded_test_server()->GetURL("bar.com", "/title2.html"));
1268 CommitMessageDelayer did_commit_delayer(shell()->web_contents(),
1269 final_page_url,
1270 std::move(pre_did_commit_callback));
1271 ASSERT_TRUE(ExecJs(shell(), JsReplace("location = $1", final_page_url)));
1272 did_commit_delayer.Wait();
1273
1274 // Test if subresources requests work fine (e.g. if |request_initiator|
1275 // matches |request_initiator_origin_lock|).
1276 GURL final_resource_url(
1277 embedded_test_server()->GetURL("bar.com", "/site_isolation/json.txt"));
1278 EXPECT_EQ(
1279 "{ \"name\" : \"chromium\" }\n",
1280 EvalJs(shell(), JsReplace("fetch($1).then(response => response.text())",
1281 final_resource_url)));
1282 }
1283
1284 } // namespace content
1285