blob: 3931405d1ff69177a3ef9f574e7f5118e80007ff [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 Zhang5f468272017-12-07 23:59:147#include "content/browser/storage_partition_impl.h"
Chong Zhangd4c923642018-01-03 21:22:298#include "content/browser/url_loader_factory_getter.h"
Chong Zhang5f468272017-12-07 23:59:149#include "content/public/browser/browser_context.h"
Chong Zhangc583e672017-11-08 16:34:0810#include "content/public/browser/network_service_instance.h"
Chong Zhang5f468272017-12-07 23:59:1411#include "content/public/browser/web_contents.h"
Chong Zhangc583e672017-11-08 16:34:0812#include "content/public/common/content_features.h"
13#include "content/public/common/network_service.mojom.h"
Chong Zhangd4c923642018-01-03 21:22:2914#include "content/public/common/simple_url_loader.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"
Chong Zhangd4c923642018-01-03 21:22:2920#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Chong Zhangc583e672017-11-08 16:34:0821
22namespace content {
23
24namespace {
25
26mojom::NetworkContextPtr CreateNetworkContext() {
27 mojom::NetworkContextPtr network_context;
28 mojom::NetworkContextParamsPtr context_params =
29 mojom::NetworkContextParams::New();
30 GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
31 std::move(context_params));
32 return network_context;
33}
34
Chong Zhangd4c923642018-01-03 21:22:2935int LoadBasicRequestOnIOThread(
36 URLLoaderFactoryGetter* url_loader_factory_getter,
37 const GURL& url) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malek1df61792018-01-12 20:40:4539 auto request = std::make_unique<network::ResourceRequest>();
Chong Zhangd4c923642018-01-03 21:22:2940 request->url = url;
41
42 SimpleURLLoaderTestHelper simple_loader_helper;
43 // Wait for callback on UI thread to avoid nesting IO message loops.
44 simple_loader_helper.SetRunLoopQuitThread(BrowserThread::UI);
45
46 std::unique_ptr<content::SimpleURLLoader> simple_loader =
47 content::SimpleURLLoader::Create(std::move(request),
48 TRAFFIC_ANNOTATION_FOR_TESTS);
49
50 // |URLLoaderFactoryGetter::GetNetworkFactory()| can only be accessed on IO
51 // thread.
52 BrowserThread::PostTask(
53 BrowserThread::IO, FROM_HERE,
54 base::BindOnce(
55 [](content::SimpleURLLoader* loader,
56 URLLoaderFactoryGetter* factory_getter,
57 SimpleURLLoader::BodyAsStringCallback body_as_string_callback) {
58 loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
59 factory_getter->GetNetworkFactory(),
60 std::move(body_as_string_callback));
61 },
62 base::Unretained(simple_loader.get()),
63 base::Unretained(url_loader_factory_getter),
64 simple_loader_helper.GetCallback()));
65
66 simple_loader_helper.WaitForCallback();
67 return simple_loader->NetError();
68}
69
Chong Zhangc583e672017-11-08 16:34:0870} // namespace
71
72// This test source has been excluded from Android as Android doesn't have
73// out-of-process Network Service.
74class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
75 public:
76 NetworkServiceRestartBrowserTest() {
77 scoped_feature_list_.InitAndEnableFeature(features::kNetworkService);
78 EXPECT_TRUE(embedded_test_server()->Start());
79 }
80
Chong Zhangc40a6ce52017-12-10 03:00:2881 GURL GetTestURL() const {
Chong Zhang5f468272017-12-07 23:59:1482 // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
83 // See https://crbug.com/792255.
Chong Zhangc40a6ce52017-12-10 03:00:2884 return embedded_test_server()->GetURL("/echoheader");
Chong Zhangc583e672017-11-08 16:34:0885 }
86
Chong Zhangd4c923642018-01-03 21:22:2987 BrowserContext* browser_context() {
88 return shell()->web_contents()->GetBrowserContext();
89 }
90
Chong Zhangc583e672017-11-08 16:34:0891 private:
92 base::test::ScopedFeatureList scoped_feature_list_;
93
94 DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest);
95};
96
97IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
98 NetworkServiceProcessRecovery) {
99 mojom::NetworkContextPtr network_context = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28100 EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08101 EXPECT_TRUE(network_context.is_bound());
102 EXPECT_FALSE(network_context.encountered_error());
103
Chong Zhang5f468272017-12-07 23:59:14104 // Crash the NetworkService process. Existing interfaces should receive error
105 // notifications at some point.
Chong Zhangc583e672017-11-08 16:34:08106 SimulateNetworkServiceCrash();
Chong Zhang5f468272017-12-07 23:59:14107 // |network_context| will receive an error notification, but it's not
108 // guaranteed to have arrived at this point. Flush the pointer to make sure
109 // the notification has been received.
110 network_context.FlushForTesting();
Chong Zhangc583e672017-11-08 16:34:08111 EXPECT_TRUE(network_context.is_bound());
112 EXPECT_TRUE(network_context.encountered_error());
Chong Zhang5f468272017-12-07 23:59:14113 // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|.
Chong Zhangc40a6ce52017-12-10 03:00:28114 EXPECT_EQ(net::ERR_FAILED,
115 LoadBasicRequest(network_context.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08116
117 // NetworkService should restart automatically and return valid interface.
118 mojom::NetworkContextPtr network_context2 = CreateNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28119 EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL()));
Chong Zhangc583e672017-11-08 16:34:08120 EXPECT_TRUE(network_context2.is_bound());
121 EXPECT_FALSE(network_context2.encountered_error());
122}
123
Chong Zhang5f468272017-12-07 23:59:14124// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
125// after crash.
126IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
Chong Zhange0dfdb62017-12-09 18:25:14127 StoragePartitionImplGetNetworkContext) {
Chong Zhang5f468272017-12-07 23:59:14128 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
Chong Zhangd4c923642018-01-03 21:22:29129 BrowserContext::GetDefaultStoragePartition(browser_context()));
Chong Zhang5f468272017-12-07 23:59:14130
131 mojom::NetworkContext* old_network_context = partition->GetNetworkContext();
Chong Zhangc40a6ce52017-12-10 03:00:28132 EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14133
134 // Crash the NetworkService process. Existing interfaces should receive error
135 // notifications at some point.
136 SimulateNetworkServiceCrash();
137 // Flush the interface to make sure the error notification was received.
138 partition->FlushNetworkInterfaceForTesting();
139
140 // |partition->GetNetworkContext()| should return a valid new pointer after
141 // crash.
142 EXPECT_NE(old_network_context, partition->GetNetworkContext());
Chong Zhangc40a6ce52017-12-10 03:00:28143 EXPECT_EQ(net::OK,
144 LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
Chong Zhang5f468272017-12-07 23:59:14145}
146
Chong Zhangd4c923642018-01-03 21:22:29147// Make sure |URLLoaderFactoryGetter| returns valid interface after crash.
148IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
149 URLLoaderFactoryGetterGetNetworkFactory) {
150 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
151 BrowserContext::GetDefaultStoragePartition(browser_context()));
152 scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
153 partition->url_loader_factory_getter();
154 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
155 GetTestURL()));
156 // Crash the NetworkService process. Existing interfaces should receive error
157 // notifications at some point.
158 SimulateNetworkServiceCrash();
159 // Flush the interface to make sure the error notification was received.
160 partition->FlushNetworkInterfaceForTesting();
161 url_loader_factory_getter->FlushNetworkInterfaceOnIOThreadForTesting();
162
163 // |url_loader_factory_getter| should be able to get a valid new pointer after
164 // crash.
165 EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(url_loader_factory_getter.get(),
166 GetTestURL()));
167}
168
169// Make sure basic navigation works after crash.
170IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
171 NavigationURLLoaderBasic) {
172 StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
173 BrowserContext::GetDefaultStoragePartition(browser_context()));
174
175 EXPECT_TRUE(
176 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
177
178 // Crash the NetworkService process. Existing interfaces should receive error
179 // notifications at some point.
180 SimulateNetworkServiceCrash();
181 // Flush the interface to make sure the error notification was received.
182 partition->FlushNetworkInterfaceForTesting();
183 partition->url_loader_factory_getter()
184 ->FlushNetworkInterfaceOnIOThreadForTesting();
185
186 EXPECT_TRUE(
187 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
188}
189
Chong Zhangc583e672017-11-08 16:34:08190} // namespace content