blob: c9307c7905f49e308a6006299acbc71f309269ee [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
5#include "base/test/scoped_feature_list.h"
John Abd-El-Maleka7289152018-02-17 00:16:196#include "base/threading/thread_restrictions.h"
Chong Zhangc583e672017-11-08 16:34:087#include "build/build_config.h"
Chong Zhang7306b0b2018-01-24 05:59:248#include "content/browser/frame_host/render_frame_host_impl.h"
Chong Zhang5f468272017-12-07 23:59:149#include "content/browser/storage_partition_impl.h"
Chong Zhangd4c923642018-01-03 21:22:2910#include "content/browser/url_loader_factory_getter.h"
Chong Zhang5f468272017-12-07 23:59:1411#include "content/public/browser/browser_context.h"
Chong Zhangc583e672017-11-08 16:34:0812#include "content/public/browser/network_service_instance.h"
Chong Zhang5f468272017-12-07 23:59:1413#include "content/public/browser/web_contents.h"
Chong Zhang7306b0b2018-01-24 05:59:2414#include "content/public/common/content_switches.h"
Chong Zhangc40a6ce52017-12-10 03:00:2815#include "content/public/test/browser_test_utils.h"
Chong Zhangc583e672017-11-08 16:34:0816#include "content/public/test/content_browser_test.h"
17#include "content/public/test/content_browser_test_utils.h"
Chong Zhangd4c923642018-01-03 21:22:2918#include "content/public/test/simple_url_loader_test_helper.h"
Chong Zhang5f468272017-12-07 23:59:1419#include "content/shell/browser/shell.h"
John Abd-El-Maleka7289152018-02-17 00:16:1920#include "content/shell/browser/shell_browser_context.h"
Chong Zhang7306b0b2018-01-24 05:59:2421#include "net/dns/mock_host_resolver.h"
22#include "net/test/embedded_test_server/http_request.h"
Chong Zhangd4c923642018-01-03 21:22:2923#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Yutaka Hiranod8789f92018-01-30 09:59:5124#include "services/network/public/cpp/features.h"
John Abd-El-Malekbdafede2018-02-06 15:10:3625#include "services/network/public/cpp/simple_url_loader.h"
Ken Rockot54311e62018-02-10 19:01:5226#include "services/network/public/mojom/network_service.mojom.h"
Chong Zhangc583e672017-11-08 16:34:0827
28namespace content {
29
30namespace {
31
John Abd-El-Malek53670dd2018-01-18 22:07:2132network::mojom::NetworkContextPtr CreateNetworkContext() {
33 network::mojom::NetworkContextPtr network_context;
34 network::mojom::NetworkContextParamsPtr context_params =
35 network::mojom::NetworkContextParams::New();
Chong Zhangc583e672017-11-08 16:34:0836 GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
37 std::move(context_params));
38 return network_context;
39}
40
Chong Zhangd4c923642018-01-03 21:22:2941int LoadBasicRequestOnIOThread(
42 URLLoaderFactoryGetter* url_loader_factory_getter,
43 const GURL& url) {
44 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malek1df61792018-01-12 20:40:4545 auto request = std::make_unique<network::ResourceRequest>();
Chong Zhangd4c923642018-01-03 21:22:2946 request->url = url;
47
48 SimpleURLLoaderTestHelper simple_loader_helper;
49 // Wait for callback on UI thread to avoid nesting IO message loops.
50 simple_loader_helper.SetRunLoopQuitThread(BrowserThread::UI);
51
John Abd-El-Malekbdafede2018-02-06 15:10:3652 std::unique_ptr<network::SimpleURLLoader> simple_loader =
53 network::SimpleURLLoader::Create(std::move(request),
Chong Zhangd4c923642018-01-03 21:22:2954 TRAFFIC_ANNOTATION_FOR_TESTS);
55
56 // |URLLoaderFactoryGetter::GetNetworkFactory()| can only be accessed on IO
57 // thread.
58 BrowserThread::PostTask(
59 BrowserThread::IO, FROM_HERE,
60 base::BindOnce(
John Abd-El-Malekbdafede2018-02-06 15:10:3661 [](network::SimpleURLLoader* loader,
Chong Zhangd4c923642018-01-03 21:22:2962 URLLoaderFactoryGetter* factory_getter,
John Abd-El-Malekbdafede2018-02-06 15:10:3663 network::SimpleURLLoader::BodyAsStringCallback
64 body_as_string_callback) {
Chong Zhangd4c923642018-01-03 21:22:2965 loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
66 factory_getter->GetNetworkFactory(),
67 std::move(body_as_string_callback));
68 },
69 base::Unretained(simple_loader.get()),
70 base::Unretained(url_loader_factory_getter),
71 simple_loader_helper.GetCallback()));
72
73 simple_loader_helper.WaitForCallback();
74 return simple_loader->NetError();
75}
76
John Abd-El-Maleka7289152018-02-17 00:16:1977int LoadBasicRequestOnUIThread(
78 network::mojom::URLLoaderFactory* url_loader_factory,
79 const GURL& url) {
80 DCHECK_CURRENTLY_ON(BrowserThread::UI);
81 auto request = std::make_unique<network::ResourceRequest>();
82 request->url = url;
83
84 SimpleURLLoaderTestHelper simple_loader_helper;
85 std::unique_ptr<network::SimpleURLLoader> simple_loader =
86 network::SimpleURLLoader::Create(std::move(request),
87 TRAFFIC_ANNOTATION_FOR_TESTS);
88 simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
89 url_loader_factory, simple_loader_helper.GetCallback());
90 simple_loader_helper.WaitForCallback();
91 return simple_loader->NetError();
92}
93
Chong Zhangc583e672017-11-08 16:34:0894} // namespace
95
96// This test source has been excluded from Android as Android doesn't have
97// out-of-process Network Service.
98class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
99 public:
100 NetworkServiceRestartBrowserTest() {
Yutaka Hiranod8789f92018-01-30 09:59:51101 scoped_feature_list_.InitAndEnableFeature(
102 network::features::kNetworkService);
Chong Zhang7306b0b2018-01-24 05:59:24103 }
104
105 void SetUpOnMainThread() override {
Chong Zhang5d9b34182018-01-30 16:20:57106 embedded_test_server()->RegisterRequestMonitor(
107 base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
108 base::Unretained(this)));
Chong Zhangc583e672017-11-08 16:34:08109 EXPECT_TRUE(embedded_test_server()->Start());
Chong Zhang7306b0b2018-01-24 05:59:24110 ContentBrowserTest::SetUpOnMainThread();
Chong Zhangc583e672017-11-08 16:34:08111 }
112
Chong Zhangc40a6ce52017-12-10 03:00:28113 GURL GetTestURL() const {
Chong Zhang5f468272017-12-07 23:59:14114 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
115 // See https://crbug.com/792255.
Chong Zhangc40a6ce52017-12-10 03:00:28116 return embedded_test_server()->GetURL("/echoheader");
Chong Zhangc583e672017-11-08 16:34:08117 }
118
Chong Zhangd4c923642018-01-03 21:22:29119 BrowserContext* browser_context() {
120 return shell()->web_contents()->GetBrowserContext();
121 }
122
Chong Zhang5d9b34182018-01-30 16:20:57123 RenderFrameHostImpl* main_frame() {
124 return static_cast<RenderFrameHostImpl*>(
125 shell()->web_contents()->GetMainFrame());
126 }
127
128 bool CheckCanLoadHttp(const std::string& relative_url) {
129 GURL test_url = embedded_test_server()->GetURL(relative_url);
130 std::string script(
131 "var xhr = new XMLHttpRequest();"
132 "xhr.open('GET', '");
133 script += test_url.spec() +
134 "', true);"
135 "xhr.onload = function (e) {"
136 " if (xhr.readyState === 4) {"
137 " window.domAutomationController.send(xhr.status === 200);"
138 " }"
139 "};"
140 "xhr.onerror = function () {"
141 " window.domAutomationController.send(false);"
142 "};"
143 "xhr.send(null)";
144 bool xhr_result = false;
145 // The JS call will fail if disallowed because the process will be killed.
146 bool execute_result =
147 ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
148 return xhr_result && execute_result;
149 }
150
151 // Called by |embedded_test_server()|.
152 void MonitorRequest(const net::test_server::HttpRequest& request) {
153 last_request_relative_url_ = request.relative_url;
154 }
155
156 std::string last_request_relative_url() const {
157 return last_request_relative_url_;
158 }
159
Chong Zhangc583e672017-11-08 16:34:08160 private:
Chong Zhang5d9b34182018-01-30 16:20:57161 std::string last_request_relative_url_;
Chong Zhangc583e672017-11-08 16:34:08162 base::test::ScopedFeatureList scoped_feature_list_;
163
164 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
165};
166
167IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
168 NetworkServiceProcessRecovery) {
John Abd-El-Malek53670dd2018-01-18 22:07:21169 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28170 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08171 EXPECT_TRUE(network_context.is_bound());
172 EXPECT_FALSE(network_context.encountered_error());
173
Chong Zhang5f468272017-12-07 23:59:14174 // Crash the NetworkService process. Existing interfaces should receive error
175 // notifications at some point.
Chong Zhangc583e672017-11-08 16:34:08176 SimulateNetworkServiceCrash();
Chong Zhang5f468272017-12-07 23:59:14177 // |network_context| will receive an error notification, but it's not
178 // guaranteed to have arrived at this point. Flush the pointer to make sure
179 // the notification has been received.
180 network_context.FlushForTesting();
Chong Zhangc583e672017-11-08 16:34:08181 EXPECT_TRUE(network_context.is_bound());
182 EXPECT_TRUE(network_context.encountered_error());
Chong Zhang5f468272017-12-07 23:59:14183 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
Chong Zhangc40a6ce52017-12-10 03:00:28184 EXPECT_EQ(net::ERR_FAILED,
185 LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08186
187 // NetworkService should restart automatically and return valid interface.
John Abd-El-Malek53670dd2018-01-18 22:07:21188 network::mojom::NetworkContextPtr network_context2 = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28189 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08190 EXPECT_TRUE(network_context2.is_bound());
191 EXPECT_FALSE(network_context2.encountered_error());
192}
193
Chong Zhang5f468272017-12-07 23:59:14194// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
195// after crash.
196IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Chong Zhange0dfdb62017-12-09 18:25:14197 StoragePartitionImplGetNetworkContext) {
Chong Zhang5f468272017-12-07 23:59:14198 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
Chong Zhangd4c923642018-01-03 21:22:29199 BrowserContext::GetDefaultStoragePartition(browser_context()));
Chong Zhang5f468272017-12-07 23:59:14200
John Abd-El-Malek53670dd2018-01-18 22:07:21201 network::mojom::NetworkContext* old_network_context =
202 partition->GetNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28203 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14204
205 // Crash the NetworkService process. Existing interfaces should receive error
206 // notifications at some point.
207 SimulateNetworkServiceCrash();
208 // Flush the interface to make sure the error notification was received.
209 partition->FlushNetworkInterfaceForTesting();
210
211 // |partition->GetNetworkContext()| should return a valid new pointer after
212 // crash.
213 EXPECT_NE(old_network_context, partition->GetNetworkContext());
Chong Zhangc40a6ce52017-12-10 03:00:28214 EXPECT_EQ(net::OK,
215 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14216}
217
Chong Zhangd4c923642018-01-03 21:22:29218// Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
219IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
220 URLLoaderFactoryGetterGetNetworkFactory) {
221 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
222 BrowserContext::GetDefaultStoragePartition(browser_context()));
223 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
224 partition->url_loader_factory_getter();
225 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
226 GetTestURL()));
227 // Crash the NetworkService process. Existing interfaces should receive error
228 // notifications at some point.
229 SimulateNetworkServiceCrash();
230 // Flush the interface to make sure the error notification was received.
231 partition->FlushNetworkInterfaceForTesting();
232 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
233
234 // |url_loader_factory_getter| should be able to get a valid new pointer after
235 // crash.
236 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
237 GetTestURL()));
238}
239
240// Make sure basic navigation works after crash.
241IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
242 NavigationURLLoaderBasic) {
243 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
244 BrowserContext::GetDefaultStoragePartition(browser_context()));
245
246 EXPECT_TRUE(
247 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
248
249 // Crash the NetworkService process. Existing interfaces should receive error
250 // notifications at some point.
251 SimulateNetworkServiceCrash();
252 // Flush the interface to make sure the error notification was received.
253 partition->FlushNetworkInterfaceForTesting();
254 partition->url_loader_factory_getter()
255 ->FlushNetworkInterfaceOnIOThreadForTesting();
256
257 EXPECT_TRUE(
258 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
259}
260
Chong Zhang7306b0b2018-01-24 05:59:24261// Make sure basic XHR works after crash.
Chong Zhang5d9b34182018-01-30 16:20:57262IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
Chong Zhang7306b0b2018-01-24 05:59:24263 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
264 BrowserContext::GetDefaultStoragePartition(browser_context()));
265
Chong Zhang5d9b34182018-01-30 16:20:57266 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
Chong Zhang7306b0b2018-01-24 05:59:24267 EXPECT_TRUE(CheckCanLoadHttp("/title1.html"));
268 EXPECT_EQ(last_request_relative_url(), "/title1.html");
269
270 // Crash the NetworkService process. Existing interfaces should receive error
271 // notifications at some point.
272 SimulateNetworkServiceCrash();
273 // Flush the interface to make sure the error notification was received.
274 partition->FlushNetworkInterfaceForTesting();
275 // Flush the interface to make sure the frame host has received error
276 // notification and the new URLLoaderFactoryBundle has been received by the
277 // frame.
278 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
279
280 EXPECT_TRUE(CheckCanLoadHttp("/title2.html"));
281 EXPECT_EQ(last_request_relative_url(), "/title2.html");
282}
283
John Abd-El-Maleka7289152018-02-17 00:16:19284// Make sure the factory returned from
285// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| continues to work
286// after crashes.
287IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserUIFactory) {
288 auto* partition =
289 BrowserContext::GetDefaultStoragePartition(browser_context());
290 auto* factory = partition->GetURLLoaderFactoryForBrowserProcess().get();
291
292 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
293
294 SimulateNetworkServiceCrash();
295 // Flush the interface to make sure the error notification was received.
296 partition->FlushNetworkInterfaceForTesting();
297
298 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory, GetTestURL()));
299}
300
301// Make sure the factory returned from
302// |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| doesn't crash if
303// it's called after the StoragePartition is deleted.
304IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
305 BrowserUIFactoryAfterStoragePartitionGone) {
306 base::ScopedAllowBlockingForTesting allow_blocking;
307 std::unique_ptr<ShellBrowserContext> browser_context =
308 std::make_unique<ShellBrowserContext>(true, nullptr);
309 auto* partition =
310 BrowserContext::GetDefaultStoragePartition(browser_context.get());
311 scoped_refptr<content::SharedURLLoaderFactory> factory(
312 partition->GetURLLoaderFactoryForBrowserProcess());
313
314 EXPECT_EQ(net::OK, LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
315
316 browser_context.reset();
317
318 EXPECT_EQ(net::ERR_FAILED,
319 LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
320}
321
Chong Zhangc583e672017-11-08 16:34:08322} // namespace content