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