blob: 59ba0a171bb06cd05f263b26c32130987299494f [file] [log] [blame]
Chong Zhangc583e672017-11-08 16:34:081// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Sebastien Marchandf8cbfab2019-01-25 16:02:305#include "base/bind.h"
Makoto Shimazu2075b0d2018-09-21 09:04:226#include "base/callback.h"
7#include "base/run_loop.h"
David Benjaminff93edd2019-06-19 22:51:588#include "base/synchronization/lock.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:149#include "base/test/bind_test_util.h"
Chong Zhangc583e672017-11-08 16:34:0810#include "base/test/scoped_feature_list.h"
Chong Zhang53047762018-05-02 21:24:0811#include "base/test/test_timeouts.h"
David Benjaminff93edd2019-06-19 22:51:5812#include "base/thread_annotations.h"
John Abd-El-Maleka7289152018-02-17 00:16:1913#include "base/threading/thread_restrictions.h"
Chong Zhangc583e672017-11-08 16:34:0814#include "build/build_config.h"
Chong Zhang7306b0b2018-01-24 05:59:2415#include "content/browser/frame_host/render_frame_host_impl.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:1416#include "content/browser/frame_host/render_frame_message_filter.h"
John Abd-El-Malek984dc002019-05-29 01:26:5917#include "content/browser/network_service_instance_impl.h"
John Abd-El-Malek1f61a5fd2018-09-21 01:13:1418#include "content/browser/renderer_host/render_process_host_impl.h"
Makoto Shimazu2075b0d2018-09-21 09:04:2219#include "content/browser/service_worker/embedded_worker_instance.h"
20#include "content/browser/service_worker/embedded_worker_status.h"
21#include "content/browser/service_worker/service_worker_context_core_observer.h"
Chong Zhang5f468272017-12-07 23:59:1422#include "content/browser/storage_partition_impl.h"
Chong Zhangd4c923642018-01-03 21:22:2923#include "content/browser/url_loader_factory_getter.h"
Chong Zhang5f468272017-12-07 23:59:1424#include "content/public/browser/browser_context.h"
Gabriel Charette790754c2018-03-16 21:32:5925#include "content/public/browser/browser_thread.h"
Chong Zhangc583e672017-11-08 16:34:0826#include "content/public/browser/network_service_instance.h"
Chong Zhang5f468272017-12-07 23:59:1427#include "content/public/browser/web_contents.h"
Chong Zhang7306b0b2018-01-24 05:59:2428#include "content/public/common/content_switches.h"
Clark DuVall3290462e2019-02-16 02:19:5029#include "content/public/common/network_service_util.h"
Clark DuVallf742bcbd2018-11-07 17:16:2030#include "content/public/common/service_names.mojom.h"
Chong Zhangc40a6ce52017-12-10 03:00:2831#include "content/public/test/browser_test_utils.h"
Chong Zhangc583e672017-11-08 16:34:0832#include "content/public/test/content_browser_test.h"
33#include "content/public/test/content_browser_test_utils.h"
Chong Zhangd4c923642018-01-03 21:22:2934#include "content/public/test/simple_url_loader_test_helper.h"
Chong Zhang53047762018-05-02 21:24:0835#include "content/public/test/test_utils.h"
Chong Zhang5f468272017-12-07 23:59:1436#include "content/shell/browser/shell.h"
John Abd-El-Maleka7289152018-02-17 00:16:1937#include "content/shell/browser/shell_browser_context.h"
Chong Zhang83d0e4f2018-05-04 18:55:0938#include "content/test/storage_partition_test_utils.h"
Clark DuVallf742bcbd2018-11-07 17:16:2039#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
Chong Zhang7306b0b2018-01-24 05:59:2440#include "net/dns/mock_host_resolver.h"
41#include "net/test/embedded_test_server/http_request.h"
Chong Zhangd4c923642018-01-03 21:22:2942#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Yutaka Hiranod8789f92018-01-30 09:59:5143#include "services/network/public/cpp/features.h"
John Abd-El-Malekbdafede2018-02-06 15:10:3644#include "services/network/public/cpp/simple_url_loader.h"
Ken Rockot54311e62018-02-10 19:01:5245#include "services/network/public/mojom/network_service.mojom.h"
Clark DuVallf742bcbd2018-11-07 17:16:2046#include "services/network/public/mojom/network_service_test.mojom.h"
47#include "services/service_manager/public/cpp/connector.h"
Chong Zhangc583e672017-11-08 16:34:0848
Lukasz Anforowiczce4487b72018-10-23 18:05:5349#if BUILDFLAG(ENABLE_PLUGINS)
50#include "content/public/test/ppapi_test_utils.h"
51#endif
52
Chong Zhangc583e672017-11-08 16:34:0853namespace content {
54
55namespace {
56
Chong Zhang4dd97ebf2018-03-07 04:48:4857using SharedURLLoaderFactoryGetterCallback =
Chong Zhangb7c8d1ce2018-03-13 19:14:1158 base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;
Chong Zhang4dd97ebf2018-03-07 04:48:4859
John Abd-El-Malek53670dd2018-01-18 22:07:2160network::mojom::NetworkContextPtr CreateNetworkContext() {
61 network::mojom::NetworkContextPtr network_context;
62 network::mojom::NetworkContextParamsPtr context_params =
63 network::mojom::NetworkContextParams::New();
Chong Zhangc583e672017-11-08 16:34:0864 GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
65 std::move(context_params));
66 return network_context;
67}
68
John Abd-El-Maleka7289152018-02-17 00:16:1969int LoadBasicRequestOnUIThread(
70 network::mojom::URLLoaderFactory* url_loader_factory,
71 const GURL& url) {
72 DCHECK_CURRENTLY_ON(BrowserThread::UI);
73 auto request = std::make_unique<network::ResourceRequest>();
74 request->url = url;
75
76 SimpleURLLoaderTestHelper simple_loader_helper;
77 std::unique_ptr<network::SimpleURLLoader> simple_loader =
78 network::SimpleURLLoader::Create(std::move(request),
79 TRAFFIC_ANNOTATION_FOR_TESTS);
80 simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
81 url_loader_factory, simple_loader_helper.GetCallback());
82 simple_loader_helper.WaitForCallback();
83 return simple_loader->NetError();
84}
85
Chong Zhang53047762018-05-02 21:24:0886std::vector<network::mojom::NetworkUsagePtr> GetTotalNetworkUsages() {
87 std::vector<network::mojom::NetworkUsagePtr> network_usages;
88 base::RunLoop run_loop;
89 GetNetworkService()->GetTotalNetworkUsages(base::BindOnce(
90 [](std::vector<network::mojom::NetworkUsagePtr>* p_network_usages,
91 base::OnceClosure quit_closure,
92 std::vector<network::mojom::NetworkUsagePtr> returned_usages) {
93 *p_network_usages = std::move(returned_usages);
94 std::move(quit_closure).Run();
95 },
96 base::Unretained(&network_usages), run_loop.QuitClosure()));
97 run_loop.Run();
98 return network_usages;
99}
100
101bool CheckContainsProcessID(
102 const std::vector<network::mojom::NetworkUsagePtr>& usages,
103 int process_id) {
104 for (const auto& usage : usages) {
105 if ((int)usage->process_id == process_id)
106 return true;
107 }
108 return false;
109}
110
111// Wait until |condition| returns true.
112void WaitForCondition(base::RepeatingCallback<bool()> condition) {
113 while (!condition.Run()) {
114 base::RunLoop run_loop;
115 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
116 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
117 run_loop.Run();
118 }
119}
120
Makoto Shimazu2075b0d2018-09-21 09:04:22121class ServiceWorkerStatusObserver : public ServiceWorkerContextCoreObserver {
122 public:
123 void WaitForState(EmbeddedWorkerStatus expected_status) {
Makoto Shimazu2540a642018-11-15 06:24:44124 for (const auto& status : statuses_in_past_) {
125 if (status == expected_status)
126 return;
127 }
Makoto Shimazu2075b0d2018-09-21 09:04:22128
129 expected_status_ = expected_status;
130 base::RunLoop loop;
131 callback_ = loop.QuitClosure();
132 loop.Run();
133 }
134
135 private:
136 void OnRunningStateChanged(int64_t version_id,
137 EmbeddedWorkerStatus running_status) override {
Makoto Shimazu2540a642018-11-15 06:24:44138 statuses_in_past_.push_back(running_status);
Makoto Shimazu2075b0d2018-09-21 09:04:22139 if (expected_status_.has_value() &&
140 running_status == expected_status_.value()) {
141 std::move(callback_).Run();
142 }
143 }
144
145 base::Optional<EmbeddedWorkerStatus> expected_status_;
Makoto Shimazu2540a642018-11-15 06:24:44146 std::vector<EmbeddedWorkerStatus> statuses_in_past_;
Makoto Shimazu2075b0d2018-09-21 09:04:22147 base::OnceClosure callback_;
148};
149
Chong Zhangc583e672017-11-08 16:34:08150} // namespace
151
Chong Zhangc583e672017-11-08 16:34:08152class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
153 public:
154 NetworkServiceRestartBrowserTest() {
Yutaka Hiranod8789f92018-01-30 09:59:51155 scoped_feature_list_.InitAndEnableFeature(
156 network::features::kNetworkService);
Chong Zhang7306b0b2018-01-24 05:59:24157 }
158
Lukasz Anforowiczce4487b72018-10-23 18:05:53159 void SetUpCommandLine(base::CommandLine* command_line) override {
160#if BUILDFLAG(ENABLE_PLUGINS)
161 ASSERT_TRUE(ppapi::RegisterCorbTestPlugin(command_line));
162#endif
163 ContentBrowserTest::SetUpCommandLine(command_line);
164 }
165
Chong Zhang7306b0b2018-01-24 05:59:24166 void SetUpOnMainThread() override {
Chong Zhang5d9b34182018-01-30 16:20:57167 embedded_test_server()->RegisterRequestMonitor(
168 base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
169 base::Unretained(this)));
Lukasz Anforowiczce4487b72018-10-23 18:05:53170 host_resolver()->AddRule("*", "127.0.0.1");
Chong Zhangc583e672017-11-08 16:34:08171 EXPECT_TRUE(embedded_test_server()->Start());
Chong Zhang7306b0b2018-01-24 05:59:24172 ContentBrowserTest::SetUpOnMainThread();
Chong Zhangc583e672017-11-08 16:34:08173 }
174
Chong Zhangc40a6ce52017-12-10 03:00:28175 GURL GetTestURL() const {
Chong Zhang5f468272017-12-07 23:59:14176 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
177 // See https://crbug.com/792255.
Chong Zhangc40a6ce52017-12-10 03:00:28178 return embedded_test_server()->GetURL("/echoheader");
Chong Zhangc583e672017-11-08 16:34:08179 }
180
Chong Zhangd4c923642018-01-03 21:22:29181 BrowserContext* browser_context() {
182 return shell()->web_contents()->GetBrowserContext();
183 }
184
Chong Zhang5d9b34182018-01-30 16:20:57185 RenderFrameHostImpl* main_frame() {
186 return static_cast<RenderFrameHostImpl*>(
187 shell()->web_contents()->GetMainFrame());
188 }
189
Chong Zhang53047762018-05-02 21:24:08190 bool CheckCanLoadHttp(Shell* shell, const std::string& relative_url) {
Chong Zhang5d9b34182018-01-30 16:20:57191 GURL test_url = embedded_test_server()->GetURL(relative_url);
192 std::string script(
193 "var xhr = new XMLHttpRequest();"
194 "xhr.open('GET', '");
195 script += test_url.spec() +
196 "', true);"
197 "xhr.onload = function (e) {"
198 " if (xhr.readyState === 4) {"
199 " window.domAutomationController.send(xhr.status === 200);"
200 " }"
201 "};"
202 "xhr.onerror = function () {"
203 " window.domAutomationController.send(false);"
204 "};"
205 "xhr.send(null)";
206 bool xhr_result = false;
207 // The JS call will fail if disallowed because the process will be killed.
208 bool execute_result =
Chong Zhang53047762018-05-02 21:24:08209 ExecuteScriptAndExtractBool(shell, script, &xhr_result);
Chong Zhang5d9b34182018-01-30 16:20:57210 return xhr_result && execute_result;
211 }
212
Chong Zhang4513fab2018-02-28 18:50:18213 // Will reuse the single opened windows through the test case.
214 bool CheckCanLoadHttpInWindowOpen(const std::string& relative_url) {
215 GURL test_url = embedded_test_server()->GetURL(relative_url);
216 std::string inject_script = base::StringPrintf(
217 "var xhr = new XMLHttpRequest();"
218 "xhr.open('GET', '%s', true);"
219 "xhr.onload = function (e) {"
220 " if (xhr.readyState === 4) {"
221 " window.opener.domAutomationController.send(xhr.status === 200);"
222 " }"
223 "};"
224 "xhr.onerror = function () {"
225 " window.opener.domAutomationController.send(false);"
226 "};"
227 "xhr.send(null)",
228 test_url.spec().c_str());
229 std::string window_open_script = base::StringPrintf(
230 "var new_window = new_window || window.open('');"
231 "var inject_script = document.createElement('script');"
232 "inject_script.innerHTML = \"%s\";"
233 "new_window.document.body.appendChild(inject_script);",
234 inject_script.c_str());
235
236 bool xhr_result = false;
237 // The JS call will fail if disallowed because the process will be killed.
238 bool execute_result =
239 ExecuteScriptAndExtractBool(shell(), window_open_script, &xhr_result);
240 return xhr_result && execute_result;
241 }
242
243 // Workers will live throughout the test case unless terminated.
244 bool CheckCanWorkerFetch(const std::string& worker_name,
245 const std::string& relative_url) {
246 GURL worker_url =
247 embedded_test_server()->GetURL("/workers/worker_common.js");
248 GURL fetch_url = embedded_test_server()->GetURL(relative_url);
249 std::string script = base::StringPrintf(
250 "var workers = workers || {};"
251 "var worker_name = '%s';"
252 "workers[worker_name] = workers[worker_name] || new Worker('%s');"
253 "workers[worker_name].onmessage = evt => {"
254 " if (evt.data != 'wait')"
255 " window.domAutomationController.send(evt.data === 200);"
256 "};"
257 "workers[worker_name].postMessage(\"eval "
258 " fetch(new Request('%s'))"
259 " .then(res => postMessage(res.status))"
260 " .catch(error => postMessage(error.toString()));"
261 " 'wait'"
262 "\");",
263 worker_name.c_str(), worker_url.spec().c_str(),
264 fetch_url.spec().c_str());
265 bool fetch_result = false;
266 // The JS call will fail if disallowed because the process will be killed.
267 bool execute_result =
268 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
269 return fetch_result && execute_result;
270 }
271
272 // Terminate and delete the worker.
273 bool TerminateWorker(const std::string& worker_name) {
274 std::string script = base::StringPrintf(
275 "var workers = workers || {};"
276 "var worker_name = '%s';"
277 "if (workers[worker_name]) {"
278 " workers[worker_name].terminate();"
279 " delete workers[worker_name];"
280 " window.domAutomationController.send(true);"
281 "} else {"
282 " window.domAutomationController.send(false);"
283 "}",
284 worker_name.c_str());
285 bool fetch_result = false;
286 // The JS call will fail if disallowed because the process will be killed.
287 bool execute_result =
288 ExecuteScriptAndExtractBool(shell(), script, &fetch_result);
289 return fetch_result && execute_result;
290 }
291
Chong Zhang5d9b34182018-01-30 16:20:57292 // Called by |embedded_test_server()|.
293 void MonitorRequest(const net::test_server::HttpRequest& request) {
David Benjaminff93edd2019-06-19 22:51:58294 base::AutoLock lock(last_request_lock_);
Chong Zhang5d9b34182018-01-30 16:20:57295 last_request_relative_url_ = request.relative_url;
296 }
297
298 std::string last_request_relative_url() const {
David Benjaminff93edd2019-06-19 22:51:58299 base::AutoLock lock(last_request_lock_);
Chong Zhang5d9b34182018-01-30 16:20:57300 return last_request_relative_url_;
301 }
302
Chong Zhangc583e672017-11-08 16:34:08303 private:
David Benjaminff93edd2019-06-19 22:51:58304 mutable base::Lock last_request_lock_;
305 std::string last_request_relative_url_ GUARDED_BY(last_request_lock_);
Chong Zhangc583e672017-11-08 16:34:08306 base::test::ScopedFeatureList scoped_feature_list_;
307
308 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
309};
310
311IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
312 NetworkServiceProcessRecovery) {
Clark DuVall3290462e2019-02-16 02:19:50313 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36314 return;
John Abd-El-Malek53670dd2018-01-18 22:07:21315 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28316 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08317 EXPECT_TRUE(network_context.is_bound());
318 EXPECT_FALSE(network_context.encountered_error());
319
Chong Zhang5f468272017-12-07 23:59:14320 // Crash the NetworkService process. Existing interfaces should receive error
321 // notifications at some point.
Chong Zhangc583e672017-11-08 16:34:08322 SimulateNetworkServiceCrash();
Chong Zhang5f468272017-12-07 23:59:14323 // |network_context| will receive an error notification, but it's not
324 // guaranteed to have arrived at this point. Flush the pointer to make sure
325 // the notification has been received.
326 network_context.FlushForTesting();
Chong Zhangc583e672017-11-08 16:34:08327 EXPECT_TRUE(network_context.is_bound());
328 EXPECT_TRUE(network_context.encountered_error());
Chong Zhang5f468272017-12-07 23:59:14329 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
Chong Zhangc40a6ce52017-12-10 03:00:28330 EXPECT_EQ(net::ERR_FAILED,
331 LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08332
333 // NetworkService should restart automatically and return valid interface.
John Abd-El-Malek53670dd2018-01-18 22:07:21334 network::mojom::NetworkContextPtr network_context2 = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28335 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08336 EXPECT_TRUE(network_context2.is_bound());
337 EXPECT_FALSE(network_context2.encountered_error());
338}
339
Lukasz Anforowiczce4487b72018-10-23 18:05:53340void IncrementInt(int* i) {
341 *i = *i + 1;
342}
343
344// This test verifies basic functionality of RegisterNetworkServiceCrashHandler
345// and UnregisterNetworkServiceCrashHandler.
346IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, CrashHandlers) {
Clark DuVall3290462e2019-02-16 02:19:50347 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36348 return;
Lukasz Anforowiczce4487b72018-10-23 18:05:53349 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
350 EXPECT_TRUE(network_context.is_bound());
351
352 // Register 2 crash handlers.
353 int counter1 = 0;
354 int counter2 = 0;
Lukasz Anforowiczc195e912018-10-30 16:20:54355 auto handler1 = RegisterNetworkServiceCrashHandler(
Lukasz Anforowiczce4487b72018-10-23 18:05:53356 base::BindRepeating(&IncrementInt, base::Unretained(&counter1)));
Lukasz Anforowiczc195e912018-10-30 16:20:54357 auto handler2 = RegisterNetworkServiceCrashHandler(
Lukasz Anforowiczce4487b72018-10-23 18:05:53358 base::BindRepeating(&IncrementInt, base::Unretained(&counter2)));
359
360 // Crash the NetworkService process.
361 SimulateNetworkServiceCrash();
362 // |network_context| will receive an error notification, but it's not
363 // guaranteed to have arrived at this point. Flush the pointer to make sure
364 // the notification has been received.
365 network_context.FlushForTesting();
366 EXPECT_TRUE(network_context.is_bound());
367 EXPECT_TRUE(network_context.encountered_error());
368
369 // Verify the crash handlers executed.
370 EXPECT_EQ(1, counter1);
371 EXPECT_EQ(1, counter2);
372
373 // Revive the NetworkService process.
374 network_context = CreateNetworkContext();
375 EXPECT_TRUE(network_context.is_bound());
376
377 // Unregister one of the handlers.
Lukasz Anforowiczc195e912018-10-30 16:20:54378 handler2.reset();
Lukasz Anforowiczce4487b72018-10-23 18:05:53379
380 // Crash the NetworkService process.
381 SimulateNetworkServiceCrash();
382 // |network_context| will receive an error notification, but it's not
383 // guaranteed to have arrived at this point. Flush the pointer to make sure
384 // the notification has been received.
385 network_context.FlushForTesting();
386 EXPECT_TRUE(network_context.is_bound());
387 EXPECT_TRUE(network_context.encountered_error());
388
389 // Verify only the first crash handler executed.
390 EXPECT_EQ(2, counter1);
391 EXPECT_EQ(1, counter2);
Lukasz Anforowiczce4487b72018-10-23 18:05:53392}
393
Chong Zhang5f468272017-12-07 23:59:14394// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
395// after crash.
396IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Chong Zhange0dfdb62017-12-09 18:25:14397 StoragePartitionImplGetNetworkContext) {
Clark DuVall3290462e2019-02-16 02:19:50398 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36399 return;
Chong Zhang5f468272017-12-07 23:59:14400 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
Chong Zhangd4c923642018-01-03 21:22:29401 BrowserContext::GetDefaultStoragePartition(browser_context()));
Chong Zhang5f468272017-12-07 23:59:14402
John Abd-El-Malek53670dd2018-01-18 22:07:21403 network::mojom::NetworkContext* old_network_context =
404 partition->GetNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28405 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14406
407 // Crash the NetworkService process. Existing interfaces should receive error
408 // notifications at some point.
409 SimulateNetworkServiceCrash();
410 // Flush the interface to make sure the error notification was received.
411 partition->FlushNetworkInterfaceForTesting();
412
413 // |partition->GetNetworkContext()| should return a valid new pointer after
414 // crash.
415 EXPECT_NE(old_network_context, partition->GetNetworkContext());
Chong Zhangc40a6ce52017-12-10 03:00:28416 EXPECT_EQ(net::OK,
417 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14418}
419
Chong Zhangd4c923642018-01-03 21:22:29420// Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
421IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
422 URLLoaderFactoryGetterGetNetworkFactory) {
Clark DuVall3290462e2019-02-16 02:19:50423 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36424 return;
Chong Zhangd4c923642018-01-03 21:22:29425 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
426 BrowserContext::GetDefaultStoragePartition(browser_context()));
427 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
428 partition->url_loader_factory_getter();
Chong Zhang5271432a2018-03-01 23:31:02429
Chong Zhang83d0e4f2018-05-04 18:55:09430 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
431 url_loader_factory_getter.get());
432 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02433
Chong Zhangd4c923642018-01-03 21:22:29434 // Crash the NetworkService process. Existing interfaces should receive error
435 // notifications at some point.
436 SimulateNetworkServiceCrash();
437 // Flush the interface to make sure the error notification was received.
438 partition->FlushNetworkInterfaceForTesting();
439 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
440
441 // |url_loader_factory_getter| should be able to get a valid new pointer after
442 // crash.
Chong Zhang83d0e4f2018-05-04 18:55:09443 factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
444 url_loader_factory_getter.get());
445 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02446}
447
448// Make sure the factory returned from
449// |URLLoaderFactoryGetter::GetNetworkFactory()| continues to work after
450// crashes.
451IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
452 BrowserIOSharedURLLoaderFactory) {
Clark DuVall3290462e2019-02-16 02:19:50453 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36454 return;
Chong Zhang5271432a2018-03-01 23:31:02455 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
456 BrowserContext::GetDefaultStoragePartition(browser_context()));
457
Chong Zhang83d0e4f2018-05-04 18:55:09458 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
459 partition->url_loader_factory_getter().get());
Chong Zhang5271432a2018-03-01 23:31:02460
Chong Zhang83d0e4f2018-05-04 18:55:09461 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02462
463 // Crash the NetworkService process. Existing interfaces should receive error
464 // notifications at some point.
465 SimulateNetworkServiceCrash();
466 // Flush the interface to make sure the error notification was received.
467 partition->FlushNetworkInterfaceForTesting();
468 partition->url_loader_factory_getter()
469 ->FlushNetworkInterfaceOnIOThreadForTesting();
470
471 // |shared_factory| should continue to work.
Chong Zhang83d0e4f2018-05-04 18:55:09472 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02473}
474
475// Make sure the factory returned from
476// |URLLoaderFactoryGetter::GetNetworkFactory()| doesn't crash if
477// it's called after the StoragePartition is deleted.
Chong Zhangf8572182018-03-16 23:10:18478IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
479 BrowserIOSharedFactoryAfterStoragePartitionGone) {
Clark DuVall3290462e2019-02-16 02:19:50480 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36481 return;
Chong Zhang5271432a2018-03-01 23:31:02482 base::ScopedAllowBlockingForTesting allow_blocking;
483 std::unique_ptr<ShellBrowserContext> browser_context =
484 std::make_unique<ShellBrowserContext>(true, nullptr);
485 auto* partition = static_cast<StoragePartitionImpl*>(
486 BrowserContext::GetDefaultStoragePartition(browser_context.get()));
Chong Zhang83d0e4f2018-05-04 18:55:09487 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
488 partition->url_loader_factory_getter().get());
Chong Zhang5271432a2018-03-01 23:31:02489
Chong Zhang83d0e4f2018-05-04 18:55:09490 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang5271432a2018-03-01 23:31:02491
492 browser_context.reset();
493
494 EXPECT_EQ(net::ERR_FAILED,
Chong Zhang83d0e4f2018-05-04 18:55:09495 factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhangd4c923642018-01-03 21:22:29496}
497
498// Make sure basic navigation works after crash.
499IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
500 NavigationURLLoaderBasic) {
Clark DuVall3290462e2019-02-16 02:19:50501 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36502 return;
Chong Zhangd4c923642018-01-03 21:22:29503 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
504 BrowserContext::GetDefaultStoragePartition(browser_context()));
505
506 EXPECT_TRUE(
507 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
508
509 // Crash the NetworkService process. Existing interfaces should receive error
510 // notifications at some point.
511 SimulateNetworkServiceCrash();
512 // Flush the interface to make sure the error notification was received.
513 partition->FlushNetworkInterfaceForTesting();
514 partition->url_loader_factory_getter()
515 ->FlushNetworkInterfaceOnIOThreadForTesting();
516
517 EXPECT_TRUE(
518 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
519}
520
Chong Zhang7306b0b2018-01-24 05:59:24521// Make sure basic XHR works after crash.
Chong Zhang5d9b34182018-01-30 16:20:57522IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
Clark DuVall3290462e2019-02-16 02:19:50523 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36524 return;
Chong Zhang7306b0b2018-01-24 05:59:24525 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
526 BrowserContext::GetDefaultStoragePartition(browser_context()));
527
Chong Zhang5d9b34182018-01-30 16:20:57528 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
Chong Zhang53047762018-05-02 21:24:08529 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title1.html"));
Chong Zhang7306b0b2018-01-24 05:59:24530 EXPECT_EQ(last_request_relative_url(), "/title1.html");
531
532 // Crash the NetworkService process. Existing interfaces should receive error
533 // notifications at some point.
534 SimulateNetworkServiceCrash();
535 // Flush the interface to make sure the error notification was received.
536 partition->FlushNetworkInterfaceForTesting();
537 // Flush the interface to make sure the frame host has received error
538 // notification and the new URLLoaderFactoryBundle has been received by the
539 // frame.
540 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
541
Chong Zhang53047762018-05-02 21:24:08542 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
Chong Zhang7306b0b2018-01-24 05:59:24543 EXPECT_EQ(last_request_relative_url(), "/title2.html");
544}
545
John Abd-El-Maleka7289152018-02-17 00:16:19546// Make sure the factory returned from
547// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| continues to work
548// after crashes.
549IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserUIFactory) {
Clark DuVall3290462e2019-02-16 02:19:50550 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36551 return;
John Abd-El-Maleka7289152018-02-17 00:16:19552 auto* partition =
553 BrowserContext::GetDefaultStoragePartition(browser_context());
554 auto* factory = partition->GetURLLoaderFactoryForBrowserProcess().get();
555
556 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
557
558 SimulateNetworkServiceCrash();
559 // Flush the interface to make sure the error notification was received.
560 partition->FlushNetworkInterfaceForTesting();
561
562 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
563}
564
565// Make sure the factory returned from
566// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| doesn't crash if
567// it's called after the StoragePartition is deleted.
568IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
569 BrowserUIFactoryAfterStoragePartitionGone) {
Clark DuVall3290462e2019-02-16 02:19:50570 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36571 return;
John Abd-El-Maleka7289152018-02-17 00:16:19572 base::ScopedAllowBlockingForTesting allow_blocking;
573 std::unique_ptr<ShellBrowserContext> browser_context =
574 std::make_unique<ShellBrowserContext>(true, nullptr);
575 auto* partition =
576 BrowserContext::GetDefaultStoragePartition(browser_context.get());
Chong Zhangb7c8d1ce2018-03-13 19:14:11577 scoped_refptr<network::SharedURLLoaderFactory> factory(
John Abd-El-Maleka7289152018-02-17 00:16:19578 partition->GetURLLoaderFactoryForBrowserProcess());
579
580 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
581
582 browser_context.reset();
583
584 EXPECT_EQ(net::ERR_FAILED,
585 LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
586}
587
Chong Zhang83d0e4f2018-05-04 18:55:09588// Make sure the factory info returned from
589// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| can be
590// used after crashes.
Guido Urdaneta9cbbe382018-05-07 14:51:06591// Flaky on Windows. https://crbug.com/840127
592#if defined(OS_WIN)
593#define MAYBE_BrowserIOFactoryInfo DISABLED_BrowserIOFactoryInfo
594#else
595#define MAYBE_BrowserIOFactoryInfo BrowserIOFactoryInfo
596#endif
597IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
598 MAYBE_BrowserIOFactoryInfo) {
Clark DuVall3290462e2019-02-16 02:19:50599 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36600 return;
Chong Zhang4dd97ebf2018-03-07 04:48:48601 auto* partition =
602 BrowserContext::GetDefaultStoragePartition(browser_context());
Chong Zhang83d0e4f2018-05-04 18:55:09603 auto shared_url_loader_factory_info =
604 partition->GetURLLoaderFactoryForBrowserProcessIOThread();
Chong Zhang4dd97ebf2018-03-07 04:48:48605
606 SimulateNetworkServiceCrash();
607 // Flush the interface to make sure the error notification was received.
608 partition->FlushNetworkInterfaceForTesting();
609 static_cast<StoragePartitionImpl*>(partition)
610 ->url_loader_factory_getter()
611 ->FlushNetworkInterfaceOnIOThreadForTesting();
612
Chong Zhang83d0e4f2018-05-04 18:55:09613 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
614 std::move(shared_url_loader_factory_info));
615
616 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48617}
618
Chong Zhang83d0e4f2018-05-04 18:55:09619// Make sure the factory constructed from
620// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| continues
621// to work after crashes.
622IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
Clark DuVall3290462e2019-02-16 02:19:50623 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36624 return;
Chong Zhang4dd97ebf2018-03-07 04:48:48625 auto* partition =
Chong Zhang83d0e4f2018-05-04 18:55:09626 BrowserContext::GetDefaultStoragePartition(browser_context());
627 auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
628 partition->GetURLLoaderFactoryForBrowserProcessIOThread());
Chong Zhang4dd97ebf2018-03-07 04:48:48629
Chong Zhang83d0e4f2018-05-04 18:55:09630 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48631
Chong Zhang83d0e4f2018-05-04 18:55:09632 SimulateNetworkServiceCrash();
633 // Flush the interface to make sure the error notification was received.
634 partition->FlushNetworkInterfaceForTesting();
635 static_cast<StoragePartitionImpl*>(partition)
636 ->url_loader_factory_getter()
637 ->FlushNetworkInterfaceOnIOThreadForTesting();
Chong Zhang4dd97ebf2018-03-07 04:48:48638
Chong Zhang83d0e4f2018-05-04 18:55:09639 EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
Chong Zhang4dd97ebf2018-03-07 04:48:48640}
641
Chong Zhang4513fab2018-02-28 18:50:18642// Make sure the window from |window.open()| can load XHR after crash.
643IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, WindowOpenXHR) {
Clark DuVall3290462e2019-02-16 02:19:50644 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36645 return;
Chong Zhang4513fab2018-02-28 18:50:18646 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
647 BrowserContext::GetDefaultStoragePartition(browser_context()));
648
649 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
650 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title1.html"));
651 EXPECT_EQ(last_request_relative_url(), "/title1.html");
652
653 // Crash the NetworkService process. Existing interfaces should receive error
654 // notifications at some point.
655 SimulateNetworkServiceCrash();
656 // Flush the interface to make sure the error notification was received.
657 partition->FlushNetworkInterfaceForTesting();
658 // Flush the interface to make sure the frame host has received error
659 // notification and the new URLLoaderFactoryBundle has been received by the
660 // frame.
661 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
662
663 EXPECT_TRUE(CheckCanLoadHttpInWindowOpen("/title2.html"));
664 EXPECT_EQ(last_request_relative_url(), "/title2.html");
665}
666
667// Make sure worker fetch works after crash.
668IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, WorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50669 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36670 return;
Chong Zhang4513fab2018-02-28 18:50:18671 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
672 BrowserContext::GetDefaultStoragePartition(browser_context()));
673
674 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
675 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
676 EXPECT_EQ(last_request_relative_url(), "/title1.html");
677
678 // Crash the NetworkService process. Existing interfaces should receive error
679 // notifications at some point.
680 SimulateNetworkServiceCrash();
681 // Flush the interface to make sure the error notification was received.
682 partition->FlushNetworkInterfaceForTesting();
683 // Flush the interface to make sure the frame host has received error
684 // notification and the new URLLoaderFactoryBundle has been received by the
685 // frame.
686 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
687
688 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
689 EXPECT_EQ(last_request_relative_url(), "/title2.html");
690}
691
692// Make sure multiple workers are tracked correctly and work after crash.
693IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MultipleWorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50694 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36695 return;
Chong Zhang4513fab2018-02-28 18:50:18696 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
697 BrowserContext::GetDefaultStoragePartition(browser_context()));
698
699 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
700 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title1.html"));
701 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
702 EXPECT_EQ(last_request_relative_url(), "/title1.html");
703
704 // Crash the NetworkService process. Existing interfaces should receive error
705 // notifications at some point.
706 SimulateNetworkServiceCrash();
707 // Flush the interface to make sure the error notification was received.
708 partition->FlushNetworkInterfaceForTesting();
709 // Flush the interface to make sure the frame host has received error
710 // notification and the new URLLoaderFactoryBundle has been received by the
711 // frame.
712 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
713
714 // Both workers should work after crash.
715 EXPECT_TRUE(CheckCanWorkerFetch("worker1", "/title2.html"));
716 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
717 EXPECT_EQ(last_request_relative_url(), "/title2.html");
718
719 // Terminate "worker1". "worker2" shouldn't be affected.
720 EXPECT_TRUE(TerminateWorker("worker1"));
721 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title1.html"));
722 EXPECT_EQ(last_request_relative_url(), "/title1.html");
723
724 // Crash the NetworkService process again. "worker2" should still work.
725 SimulateNetworkServiceCrash();
726 partition->FlushNetworkInterfaceForTesting();
727 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
728
729 EXPECT_TRUE(CheckCanWorkerFetch("worker2", "/title2.html"));
730 EXPECT_EQ(last_request_relative_url(), "/title2.html");
731}
732
Makoto Shimazu775101a52018-09-26 04:46:52733// Make sure fetch from a page controlled by a service worker which doesn't have
734// a fetch handler works after crash.
Makoto Shimazu2540a642018-11-15 06:24:44735IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
736 FetchFromServiceWorkerControlledPage_NoFetchHandler) {
Clark DuVall3290462e2019-02-16 02:19:50737 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36738 return;
Makoto Shimazu775101a52018-09-26 04:46:52739 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
740 BrowserContext::GetDefaultStoragePartition(browser_context()));
741 ServiceWorkerStatusObserver observer;
742 ServiceWorkerContextWrapper* service_worker_context =
743 partition->GetServiceWorkerContext();
744 service_worker_context->AddObserver(&observer);
745
746 // Register a service worker which controls /service_worker/.
747 EXPECT_TRUE(NavigateToURL(shell(),
748 embedded_test_server()->GetURL(
749 "/service_worker/create_service_worker.html")));
750 EXPECT_EQ("DONE", EvalJs(shell(), "register('empty.js')"));
751
752 // Navigate to a controlled page.
753 EXPECT_TRUE(NavigateToURL(
754 shell(),
755 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
756
757 // Fetch from the controlled page.
758 const std::string script = "fetch_from_page('/echo');";
759 EXPECT_EQ("Echo", EvalJs(shell(), script));
760
761 // Crash the NetworkService process. Existing interfaces should receive error
762 // notifications at some point.
763 SimulateNetworkServiceCrash();
764 // Flush the interface to make sure the error notification was received.
765 partition->FlushNetworkInterfaceForTesting();
766
767 // Service worker should be stopped when network service crashes.
768 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
769
770 // Fetch from the controlled page again.
771 EXPECT_EQ("Echo", EvalJs(shell(), script));
772
773 service_worker_context->RemoveObserver(&observer);
774}
775
Makoto Shimazu775101a52018-09-26 04:46:52776// Make sure fetch from a page controlled by a service worker which has a fetch
777// handler but falls back to the network works after crash.
778IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Makoto Shimazu2540a642018-11-15 06:24:44779 FetchFromServiceWorkerControlledPage_PassThrough) {
Clark DuVall3290462e2019-02-16 02:19:50780 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36781 return;
Makoto Shimazu775101a52018-09-26 04:46:52782 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
783 BrowserContext::GetDefaultStoragePartition(browser_context()));
784 ServiceWorkerStatusObserver observer;
785 ServiceWorkerContextWrapper* service_worker_context =
786 partition->GetServiceWorkerContext();
787 service_worker_context->AddObserver(&observer);
788
789 // Register a service worker which controls /service_worker/.
790 EXPECT_TRUE(NavigateToURL(shell(),
791 embedded_test_server()->GetURL(
792 "/service_worker/create_service_worker.html")));
793 EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_pass_through.js')"));
794
795 // Navigate to a controlled page.
796 EXPECT_TRUE(NavigateToURL(
797 shell(),
798 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
799
800 // Fetch from the controlled page.
801 const std::string script = "fetch_from_page('/echo');";
802 EXPECT_EQ("Echo", EvalJs(shell(), script));
803
804 // Crash the NetworkService process. Existing interfaces should receive error
805 // notifications at some point.
806 SimulateNetworkServiceCrash();
807 // Flush the interface to make sure the error notification was received.
808 partition->FlushNetworkInterfaceForTesting();
809
810 // Service worker should be stopped when network service crashes.
811 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
812
813 // Fetch from the controlled page again.
814 EXPECT_EQ("Echo", EvalJs(shell(), script));
815
816 service_worker_context->RemoveObserver(&observer);
817}
818
Makoto Shimazu775101a52018-09-26 04:46:52819// Make sure fetch from a page controlled by a service worker which has a fetch
820// handler and responds with fetch() works after crash.
Makoto Shimazu2540a642018-11-15 06:24:44821IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
822 FetchFromServiceWorkerControlledPage_RespondWithFetch) {
Clark DuVall3290462e2019-02-16 02:19:50823 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36824 return;
Makoto Shimazu775101a52018-09-26 04:46:52825 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
826 BrowserContext::GetDefaultStoragePartition(browser_context()));
827 ServiceWorkerStatusObserver observer;
828 ServiceWorkerContextWrapper* service_worker_context =
829 partition->GetServiceWorkerContext();
830 service_worker_context->AddObserver(&observer);
831
832 // Register a service worker which controls /service_worker/.
833 EXPECT_TRUE(NavigateToURL(shell(),
834 embedded_test_server()->GetURL(
835 "/service_worker/create_service_worker.html")));
836 EXPECT_EQ("DONE",
837 EvalJs(shell(), "register('fetch_event_respond_with_fetch.js')"));
838
839 // Navigate to a controlled page.
840 EXPECT_TRUE(NavigateToURL(
841 shell(),
842 embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
843
844 // Fetch from the controlled page.
845 const std::string script = "fetch_from_page('/echo');";
846 EXPECT_EQ("Echo", EvalJs(shell(), script));
847
848 // Crash the NetworkService process. Existing interfaces should receive error
849 // notifications at some point.
850 SimulateNetworkServiceCrash();
851 // Flush the interface to make sure the error notification was received.
852 partition->FlushNetworkInterfaceForTesting();
853
854 // Service worker should be stopped when network service crashes.
855 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
856
857 // Fetch from the controlled page again.
858 EXPECT_EQ("Echo", EvalJs(shell(), script));
859
860 service_worker_context->RemoveObserver(&observer);
861}
862
Makoto Shimazu2075b0d2018-09-21 09:04:22863// Make sure fetch from service worker context works after crash.
Makoto Shimazu6a96cb62018-09-21 11:39:13864IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) {
Clark DuVall3290462e2019-02-16 02:19:50865 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36866 return;
Makoto Shimazu2075b0d2018-09-21 09:04:22867 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
868 BrowserContext::GetDefaultStoragePartition(browser_context()));
869 ServiceWorkerStatusObserver observer;
870 ServiceWorkerContextWrapper* service_worker_context =
871 partition->GetServiceWorkerContext();
872 service_worker_context->AddObserver(&observer);
873
874 const GURL page_url = embedded_test_server()->GetURL(
875 "/service_worker/fetch_from_service_worker.html");
876 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
877
878 // Navigate to the page and register a service worker.
879 EXPECT_TRUE(NavigateToURL(shell(), page_url));
880 EXPECT_EQ("ready", EvalJs(shell(), "setup();"));
881
882 // Fetch from the service worker.
883 const std::string script =
884 "fetch_from_service_worker('" + fetch_url.spec() + "');";
885 EXPECT_EQ("Echo", EvalJs(shell(), script));
886
887 // Crash the NetworkService process. Existing interfaces should receive error
888 // notifications at some point.
889 SimulateNetworkServiceCrash();
890 // Flush the interface to make sure the error notification was received.
891 partition->FlushNetworkInterfaceForTesting();
892
893 // Service worker should be stopped when network service crashes.
894 observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
895
896 // Fetch from the service worker again.
897 EXPECT_EQ("Echo", EvalJs(shell(), script));
898
899 service_worker_context->RemoveObserver(&observer);
900}
901
Clark DuVallf742bcbd2018-11-07 17:16:20902// TODO(crbug.com/154571): Shared workers are not available on Android.
903#if defined(OS_ANDROID)
904#define MAYBE_SharedWorker DISABLED_SharedWorker
905#else
906#define MAYBE_SharedWorker SharedWorker
907#endif
Matt Falkenhagene6721962018-10-05 10:17:05908// Make sure shared workers terminate after crash.
Clark DuVallf742bcbd2018-11-07 17:16:20909IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MAYBE_SharedWorker) {
Clark DuVall3290462e2019-02-16 02:19:50910 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36911 return;
Makoto Shimazu2075b0d2018-09-21 09:04:22912 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
913 BrowserContext::GetDefaultStoragePartition(browser_context()));
914
915 const GURL page_url =
916 embedded_test_server()->GetURL("/workers/fetch_from_shared_worker.html");
917 const GURL fetch_url = embedded_test_server()->GetURL("/echo");
918
919 // Navigate to the page and prepare a shared worker.
920 EXPECT_TRUE(NavigateToURL(shell(), page_url));
921
Matt Falkenhagene6721962018-10-05 10:17:05922 // Fetch from the shared worker to ensure it has started.
Finditc0f7c6202018-10-05 07:14:23923 const std::string script =
924 "fetch_from_shared_worker('" + fetch_url.spec() + "');";
925 EXPECT_EQ("Echo", EvalJs(shell(), script));
Makoto Shimazu2075b0d2018-09-21 09:04:22926
Matt Falkenhagene6721962018-10-05 10:17:05927 // There should be one worker host. We will later wait for it to terminate.
928 SharedWorkerServiceImpl* service = partition->GetSharedWorkerService();
929 EXPECT_EQ(1u, service->worker_hosts_.size());
930 base::RunLoop loop;
931 service->SetWorkerTerminationCallbackForTesting(loop.QuitClosure());
Makoto Shimazu2075b0d2018-09-21 09:04:22932
Matt Falkenhagene6721962018-10-05 10:17:05933 // Crash the NetworkService process.
934 SimulateNetworkServiceCrash();
935
936 // Wait for the worker to detect the crash and self-terminate.
937 loop.Run();
938 EXPECT_TRUE(service->worker_hosts_.empty());
Makoto Shimazu2075b0d2018-09-21 09:04:22939}
940
Chong Zhang53047762018-05-02 21:24:08941// Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
942// after process closed.
943IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
944 GetNetworkUsagesClosed) {
Clark DuVall3290462e2019-02-16 02:19:50945 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36946 return;
Chong Zhang53047762018-05-02 21:24:08947 EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
948 Shell* shell2 = CreateBrowser();
949 EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
950
951 int process_id1 =
952 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
953 int process_id2 =
954 shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
955
956 // Load resource on the renderer to make sure the traffic was recorded.
957 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
958 EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
959
960 // Both processes should have traffic recorded.
961 auto network_usages = GetTotalNetworkUsages();
962 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
963 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
964
965 // Closing |shell2| should cause the entry to be cleared.
966 shell2->Close();
967 shell2 = nullptr;
968
969 // Wait until the Network Service has noticed the change. We don't have a
970 // better way to force a flush on the Network Service side.
971 WaitForCondition(base::BindRepeating(
972 [](int process_id) {
973 auto usages = GetTotalNetworkUsages();
974 return !CheckContainsProcessID(usages, process_id);
975 },
976 process_id2));
977
978 network_usages = GetTotalNetworkUsages();
979 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
980 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
981}
982
983// Make sure |NetworkService::GetTotalNetworkUsages()| continues to work after
984// crash. See 'network_usage_accumulator_unittest' for quantified tests.
985IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
986 GetNetworkUsagesCrashed) {
Clark DuVall3290462e2019-02-16 02:19:50987 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:36988 return;
Chong Zhang53047762018-05-02 21:24:08989 EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
990 Shell* shell2 = CreateBrowser();
991 EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
992
993 int process_id1 =
994 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
995 int process_id2 =
996 shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
997
998 // Load resource on the renderer to make sure the traffic was recorded.
999 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
1000 EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
1001
1002 // Both processes should have traffic recorded.
1003 auto network_usages = GetTotalNetworkUsages();
1004 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1005 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
1006
1007 // Crashing Network Service should cause all entries to be cleared.
1008 SimulateNetworkServiceCrash();
1009 network_usages = GetTotalNetworkUsages();
1010 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id1));
1011 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1012
1013 // Should still be able to recored new traffic after crash.
1014 EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
1015 network_usages = GetTotalNetworkUsages();
1016 EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
1017 EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
1018}
1019
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141020// Make sure cookie access doesn't hang or fail after a network process crash.
1021IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
Clark DuVall3290462e2019-02-16 02:19:501022 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361023 return;
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141024 auto* web_contents = shell()->web_contents();
Lukasz Anforowiczce4487b72018-10-23 18:05:531025 ASSERT_TRUE(
1026 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
John Abd-El-Malek1f61a5fd2018-09-21 01:13:141027 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1028
1029 std::string cookie;
1030 EXPECT_TRUE(ExecuteScriptAndExtractString(
1031 web_contents, "window.domAutomationController.send(document.cookie);",
1032 &cookie));
1033 EXPECT_EQ("foo=bar", cookie);
1034
1035 SimulateNetworkServiceCrash();
1036
1037 auto* process = web_contents->GetMainFrame()->GetProcess();
1038 scoped_refptr<RenderFrameMessageFilter> filter(
1039 static_cast<RenderProcessHostImpl*>(process)
1040 ->render_frame_message_filter_for_testing());
1041 // Need to use FlushAsyncForTesting instead of FlushForTesting because the IO
1042 // thread doesn't support nested message loops.
1043 base::RunLoop run_loop;
1044 base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
1045 base::BindLambdaForTesting([&]() {
1046 filter->GetCookieManager()->FlushAsyncForTesting(
1047 run_loop.QuitClosure());
1048 }));
1049
1050 // content_shell uses in-memory cookie database, so the value saved earlier
1051 // won't persist across crashes. What matters is that new access works.
1052 EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
1053
1054 // This will hang without the fix.
1055 EXPECT_TRUE(ExecuteScriptAndExtractString(
1056 web_contents, "window.domAutomationController.send(document.cookie);",
1057 &cookie));
1058 EXPECT_EQ("foo=bar", cookie);
1059}
1060
Lukasz Anforowiczce4487b72018-10-23 18:05:531061#if BUILDFLAG(ENABLE_PLUGINS)
1062// Make sure that "trusted" plugins continue to be able to issue cross-origin
1063// requests after a network process crash.
1064IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Plugin) {
Clark DuVall3290462e2019-02-16 02:19:501065 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361066 return;
Lukasz Anforowiczce4487b72018-10-23 18:05:531067 auto* web_contents = shell()->web_contents();
1068 ASSERT_TRUE(NavigateToURL(web_contents,
1069 embedded_test_server()->GetURL("/title1.html")));
1070
1071 // Load the test plugin (see ppapi::RegisterFlashTestPlugin and
1072 // ppapi/tests/power_saver_test_plugin.cc).
1073 const char kLoadingScript[] = R"(
1074 var obj = document.createElement('object');
1075 obj.id = 'plugin';
1076 obj.data = 'test.swf';
1077 obj.type = 'application/x-shockwave-flash';
1078 obj.width = 400;
1079 obj.height = 400;
1080
1081 document.body.appendChild(obj);
1082 )";
1083 ASSERT_TRUE(ExecJs(web_contents, kLoadingScript));
1084
1085 // Ask the plugin to perform a cross-origin, CORB-eligible (i.e.
1086 // application/json + nosniff) URL request. Plugins with universal access
1087 // should not be subject to CORS/CORB and so the request should go through.
1088 // See also https://crbug.com/874515 and https://crbug.com/846339.
1089 GURL cross_origin_url = embedded_test_server()->GetURL(
1090 "cross.origin.com", "/site_isolation/nosniff.json");
1091 const char kFetchScriptTemplate[] = R"(
1092 new Promise(function (resolve, reject) {
1093 var obj = document.getElementById('plugin');
1094 function callback(event) {
1095 // Ignore plugin messages unrelated to requestUrl.
1096 if (!event.data.startsWith('requestUrl: '))
1097 return;
1098
1099 obj.removeEventListener('message', callback);
1100 resolve('msg-from-plugin: ' + event.data);
1101 };
1102 obj.addEventListener('message', callback);
1103 obj.postMessage('requestUrl: ' + $1);
1104 });
1105 )";
1106 std::string fetch_script = JsReplace(kFetchScriptTemplate, cross_origin_url);
1107 ASSERT_EQ(
1108 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1109 "runMe({ \"name\" : \"chromium\" });\n",
1110 EvalJs(web_contents, fetch_script));
1111
1112 // Crash the Network Service process and wait until host frame's
1113 // URLLoaderFactory has been refreshed.
1114 SimulateNetworkServiceCrash();
1115 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
1116
1117 // Try the fetch again - it should still work (i.e. the mechanism for relaxing
1118 // CORB for universal-access-plugins should be resilient to network process
1119 // crashes). See also https://crbug.com/891904.
1120 ASSERT_EQ(
1121 "msg-from-plugin: requestUrl: RESPONSE BODY: "
1122 "runMe({ \"name\" : \"chromium\" });\n",
1123 EvalJs(web_contents, fetch_script));
1124}
1125#endif
1126
Clark DuVallf742bcbd2018-11-07 17:16:201127// TODO(crbug.com/901026): Fix deadlock on process startup on Android.
1128#if defined(OS_ANDROID)
1129#define MAYBE_SyncCallDuringRestart DISABLED_SyncCallDuringRestart
1130#else
1131#define MAYBE_SyncCallDuringRestart SyncCallDuringRestart
1132#endif
1133IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
1134 MAYBE_SyncCallDuringRestart) {
Clark DuVall3290462e2019-02-16 02:19:501135 if (IsInProcessNetworkService())
Clark DuVallc2227ae2018-11-28 22:26:361136 return;
Clark DuVallf742bcbd2018-11-07 17:16:201137 network::mojom::NetworkServiceTestPtr network_service_test;
1138 base::RunLoop run_loop;
1139 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
1140 mojom::kNetworkServiceName, &network_service_test);
1141
1142 // Crash the network service, but do not wait for full startup.
1143 network_service_test.set_connection_error_handler(run_loop.QuitClosure());
1144 network_service_test->SimulateCrash();
1145 run_loop.Run();
1146
1147 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
1148 mojom::kNetworkServiceName, &network_service_test);
1149
1150 // Sync call should be fine, even though network process is still starting up.
1151 mojo::ScopedAllowSyncCallForTesting allow_sync_call;
1152 network_service_test->AddRules({});
1153}
1154
Chong Zhangc583e672017-11-08 16:34:081155} // namespace content