blob: 9d0840129220b48e54f829cddb5eaaafd6d86a86 [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"
6#include "build/build_config.h"
Chong Zhang7306b0b2018-01-24 05:59:247#include "content/browser/frame_host/render_frame_host_impl.h"
Chong Zhang5f468272017-12-07 23:59:148#include "content/browser/storage_partition_impl.h"
Chong Zhangd4c923642018-01-03 21:22:299#include "content/browser/url_loader_factory_getter.h"
Chong Zhang5f468272017-12-07 23:59:1410#include "content/public/browser/browser_context.h"
Chong Zhangc583e672017-11-08 16:34:0811#include "content/public/browser/network_service_instance.h"
Chong Zhang5f468272017-12-07 23:59:1412#include "content/public/browser/web_contents.h"
Chong Zhang7306b0b2018-01-24 05:59:2413#include "content/public/common/content_switches.h"
Chong Zhangc40a6ce52017-12-10 03:00:2814#include "content/public/test/browser_test_utils.h"
Chong Zhangc583e672017-11-08 16:34:0815#include "content/public/test/content_browser_test.h"
16#include "content/public/test/content_browser_test_utils.h"
Chong Zhangd4c923642018-01-03 21:22:2917#include "content/public/test/simple_url_loader_test_helper.h"
Chong Zhang5f468272017-12-07 23:59:1418#include "content/shell/browser/shell.h"
Chong Zhang7306b0b2018-01-24 05:59:2419#include "net/dns/mock_host_resolver.h"
20#include "net/test/embedded_test_server/http_request.h"
Chong Zhangd4c923642018-01-03 21:22:2921#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Yutaka Hiranod8789f92018-01-30 09:59:5122#include "services/network/public/cpp/features.h"
John Abd-El-Malekbdafede2018-02-06 15:10:3623#include "services/network/public/cpp/simple_url_loader.h"
Ken Rockot54311e62018-02-10 19:01:5224#include "services/network/public/mojom/network_service.mojom.h"
Chong Zhangc583e672017-11-08 16:34:0825
26namespace content {
27
28namespace {
29
John Abd-El-Malek53670dd2018-01-18 22:07:2130network::mojom::NetworkContextPtr CreateNetworkContext() {
31 network::mojom::NetworkContextPtr network_context;
32 network::mojom::NetworkContextParamsPtr context_params =
33 network::mojom::NetworkContextParams::New();
Chong Zhangc583e672017-11-08 16:34:0834 GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
35 std::move(context_params));
36 return network_context;
37}
38
Chong Zhangd4c923642018-01-03 21:22:2939int LoadBasicRequestOnIOThread(
40 URLLoaderFactoryGetter* url_loader_factory_getter,
41 const GURL& url) {
42 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malek1df61792018-01-12 20:40:4543 auto request = std::make_unique<network::ResourceRequest>();
Chong Zhangd4c923642018-01-03 21:22:2944 request->url = url;
45
46 SimpleURLLoaderTestHelper simple_loader_helper;
47 // Wait for callback on UI thread to avoid nesting IO message loops.
48 simple_loader_helper.SetRunLoopQuitThread(BrowserThread::UI);
49
John Abd-El-Malekbdafede2018-02-06 15:10:3650 std::unique_ptr<network::SimpleURLLoader> simple_loader =
51 network::SimpleURLLoader::Create(std::move(request),
Chong Zhangd4c923642018-01-03 21:22:2952 TRAFFIC_ANNOTATION_FOR_TESTS);
53
54 // |URLLoaderFactoryGetter::GetNetworkFactory()| can only be accessed on IO
55 // thread.
56 BrowserThread::PostTask(
57 BrowserThread::IO, FROM_HERE,
58 base::BindOnce(
John Abd-El-Malekbdafede2018-02-06 15:10:3659 [](network::SimpleURLLoader* loader,
Chong Zhangd4c923642018-01-03 21:22:2960 URLLoaderFactoryGetter* factory_getter,
John Abd-El-Malekbdafede2018-02-06 15:10:3661 network::SimpleURLLoader::BodyAsStringCallback
62 body_as_string_callback) {
Chong Zhangd4c923642018-01-03 21:22:2963 loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
64 factory_getter->GetNetworkFactory(),
65 std::move(body_as_string_callback));
66 },
67 base::Unretained(simple_loader.get()),
68 base::Unretained(url_loader_factory_getter),
69 simple_loader_helper.GetCallback()));
70
71 simple_loader_helper.WaitForCallback();
72 return simple_loader->NetError();
73}
74
Chong Zhangc583e672017-11-08 16:34:0875} // namespace
76
77// This test source has been excluded from Android as Android doesn't have
78// out-of-process Network Service.
79class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
80 public:
81 NetworkServiceRestartBrowserTest() {
Yutaka Hiranod8789f92018-01-30 09:59:5182 scoped_feature_list_.InitAndEnableFeature(
83 network::features::kNetworkService);
Chong Zhang7306b0b2018-01-24 05:59:2484 }
85
86 void SetUpOnMainThread() override {
Chong Zhang5d9b34182018-01-30 16:20:5787 embedded_test_server()->RegisterRequestMonitor(
88 base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
89 base::Unretained(this)));
Chong Zhangc583e672017-11-08 16:34:0890 EXPECT_TRUE(embedded_test_server()->Start());
Chong Zhang7306b0b2018-01-24 05:59:2491 ContentBrowserTest::SetUpOnMainThread();
Chong Zhangc583e672017-11-08 16:34:0892 }
93
Chong Zhangc40a6ce52017-12-10 03:00:2894 GURL GetTestURL() const {
Chong Zhang5f468272017-12-07 23:59:1495 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
96 // See https://crbug.com/792255.
Chong Zhangc40a6ce52017-12-10 03:00:2897 return embedded_test_server()->GetURL("/echoheader");
Chong Zhangc583e672017-11-08 16:34:0898 }
99
Chong Zhangd4c923642018-01-03 21:22:29100 BrowserContext* browser_context() {
101 return shell()->web_contents()->GetBrowserContext();
102 }
103
Chong Zhang5d9b34182018-01-30 16:20:57104 RenderFrameHostImpl* main_frame() {
105 return static_cast<RenderFrameHostImpl*>(
106 shell()->web_contents()->GetMainFrame());
107 }
108
109 bool CheckCanLoadHttp(const std::string& relative_url) {
110 GURL test_url = embedded_test_server()->GetURL(relative_url);
111 std::string script(
112 "var xhr = new XMLHttpRequest();"
113 "xhr.open('GET', '");
114 script += test_url.spec() +
115 "', true);"
116 "xhr.onload = function (e) {"
117 " if (xhr.readyState === 4) {"
118 " window.domAutomationController.send(xhr.status === 200);"
119 " }"
120 "};"
121 "xhr.onerror = function () {"
122 " window.domAutomationController.send(false);"
123 "};"
124 "xhr.send(null)";
125 bool xhr_result = false;
126 // The JS call will fail if disallowed because the process will be killed.
127 bool execute_result =
128 ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
129 return xhr_result && execute_result;
130 }
131
132 // Called by |embedded_test_server()|.
133 void MonitorRequest(const net::test_server::HttpRequest& request) {
134 last_request_relative_url_ = request.relative_url;
135 }
136
137 std::string last_request_relative_url() const {
138 return last_request_relative_url_;
139 }
140
Chong Zhangc583e672017-11-08 16:34:08141 private:
Chong Zhang5d9b34182018-01-30 16:20:57142 std::string last_request_relative_url_;
Chong Zhangc583e672017-11-08 16:34:08143 base::test::ScopedFeatureList scoped_feature_list_;
144
145 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
146};
147
148IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
149 NetworkServiceProcessRecovery) {
John Abd-El-Malek53670dd2018-01-18 22:07:21150 network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28151 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08152 EXPECT_TRUE(network_context.is_bound());
153 EXPECT_FALSE(network_context.encountered_error());
154
Chong Zhang5f468272017-12-07 23:59:14155 // Crash the NetworkService process. Existing interfaces should receive error
156 // notifications at some point.
Chong Zhangc583e672017-11-08 16:34:08157 SimulateNetworkServiceCrash();
Chong Zhang5f468272017-12-07 23:59:14158 // |network_context| will receive an error notification, but it's not
159 // guaranteed to have arrived at this point. Flush the pointer to make sure
160 // the notification has been received.
161 network_context.FlushForTesting();
Chong Zhangc583e672017-11-08 16:34:08162 EXPECT_TRUE(network_context.is_bound());
163 EXPECT_TRUE(network_context.encountered_error());
Chong Zhang5f468272017-12-07 23:59:14164 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
Chong Zhangc40a6ce52017-12-10 03:00:28165 EXPECT_EQ(net::ERR_FAILED,
166 LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08167
168 // NetworkService should restart automatically and return valid interface.
John Abd-El-Malek53670dd2018-01-18 22:07:21169 network::mojom::NetworkContextPtr network_context2 = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28170 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08171 EXPECT_TRUE(network_context2.is_bound());
172 EXPECT_FALSE(network_context2.encountered_error());
173}
174
Chong Zhang5f468272017-12-07 23:59:14175// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
176// after crash.
177IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Chong Zhange0dfdb62017-12-09 18:25:14178 StoragePartitionImplGetNetworkContext) {
Chong Zhang5f468272017-12-07 23:59:14179 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
Chong Zhangd4c923642018-01-03 21:22:29180 BrowserContext::GetDefaultStoragePartition(browser_context()));
Chong Zhang5f468272017-12-07 23:59:14181
John Abd-El-Malek53670dd2018-01-18 22:07:21182 network::mojom::NetworkContext* old_network_context =
183 partition->GetNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28184 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14185
186 // Crash the NetworkService process. Existing interfaces should receive error
187 // notifications at some point.
188 SimulateNetworkServiceCrash();
189 // Flush the interface to make sure the error notification was received.
190 partition->FlushNetworkInterfaceForTesting();
191
192 // |partition->GetNetworkContext()| should return a valid new pointer after
193 // crash.
194 EXPECT_NE(old_network_context, partition->GetNetworkContext());
Chong Zhangc40a6ce52017-12-10 03:00:28195 EXPECT_EQ(net::OK,
196 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14197}
198
Chong Zhangd4c923642018-01-03 21:22:29199// Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
200IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
201 URLLoaderFactoryGetterGetNetworkFactory) {
202 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
203 BrowserContext::GetDefaultStoragePartition(browser_context()));
204 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
205 partition->url_loader_factory_getter();
206 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
207 GetTestURL()));
208 // Crash the NetworkService process. Existing interfaces should receive error
209 // notifications at some point.
210 SimulateNetworkServiceCrash();
211 // Flush the interface to make sure the error notification was received.
212 partition->FlushNetworkInterfaceForTesting();
213 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
214
215 // |url_loader_factory_getter| should be able to get a valid new pointer after
216 // crash.
217 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
218 GetTestURL()));
219}
220
221// Make sure basic navigation works after crash.
222IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
223 NavigationURLLoaderBasic) {
224 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
225 BrowserContext::GetDefaultStoragePartition(browser_context()));
226
227 EXPECT_TRUE(
228 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
229
230 // Crash the NetworkService process. Existing interfaces should receive error
231 // notifications at some point.
232 SimulateNetworkServiceCrash();
233 // Flush the interface to make sure the error notification was received.
234 partition->FlushNetworkInterfaceForTesting();
235 partition->url_loader_factory_getter()
236 ->FlushNetworkInterfaceOnIOThreadForTesting();
237
238 EXPECT_TRUE(
239 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
240}
241
Chong Zhang7306b0b2018-01-24 05:59:24242// Make sure basic XHR works after crash.
Chong Zhang5d9b34182018-01-30 16:20:57243IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
Chong Zhang7306b0b2018-01-24 05:59:24244 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
245 BrowserContext::GetDefaultStoragePartition(browser_context()));
246
Chong Zhang5d9b34182018-01-30 16:20:57247 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
Chong Zhang7306b0b2018-01-24 05:59:24248 EXPECT_TRUE(CheckCanLoadHttp("/title1.html"));
249 EXPECT_EQ(last_request_relative_url(), "/title1.html");
250
251 // Crash the NetworkService process. Existing interfaces should receive error
252 // notifications at some point.
253 SimulateNetworkServiceCrash();
254 // Flush the interface to make sure the error notification was received.
255 partition->FlushNetworkInterfaceForTesting();
256 // Flush the interface to make sure the frame host has received error
257 // notification and the new URLLoaderFactoryBundle has been received by the
258 // frame.
259 main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
260
261 EXPECT_TRUE(CheckCanLoadHttp("/title2.html"));
262 EXPECT_EQ(last_request_relative_url(), "/title2.html");
263}
264
Chong Zhangc583e672017-11-08 16:34:08265} // namespace content