Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "base/test/scoped_feature_list.h" |
John Abd-El-Malek | a728915 | 2018-02-17 00:16:19 | [diff] [blame^] | 6 | #include "base/threading/thread_restrictions.h" |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 7 | #include "build/build_config.h" |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 8 | #include "content/browser/frame_host/render_frame_host_impl.h" |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 9 | #include "content/browser/storage_partition_impl.h" |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 10 | #include "content/browser/url_loader_factory_getter.h" |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 11 | #include "content/public/browser/browser_context.h" |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 12 | #include "content/public/browser/network_service_instance.h" |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 13 | #include "content/public/browser/web_contents.h" |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 14 | #include "content/public/common/content_switches.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 15 | #include "content/public/test/browser_test_utils.h" |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 16 | #include "content/public/test/content_browser_test.h" |
| 17 | #include "content/public/test/content_browser_test_utils.h" |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 18 | #include "content/public/test/simple_url_loader_test_helper.h" |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 19 | #include "content/shell/browser/shell.h" |
John Abd-El-Malek | a728915 | 2018-02-17 00:16:19 | [diff] [blame^] | 20 | #include "content/shell/browser/shell_browser_context.h" |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 21 | #include "net/dns/mock_host_resolver.h" |
| 22 | #include "net/test/embedded_test_server/http_request.h" |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 23 | #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
Yutaka Hirano | d8789f9 | 2018-01-30 09:59:51 | [diff] [blame] | 24 | #include "services/network/public/cpp/features.h" |
John Abd-El-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 25 | #include "services/network/public/cpp/simple_url_loader.h" |
Ken Rockot | 54311e6 | 2018-02-10 19:01:52 | [diff] [blame] | 26 | #include "services/network/public/mojom/network_service.mojom.h" |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 27 | |
| 28 | namespace content { |
| 29 | |
| 30 | namespace { |
| 31 | |
John Abd-El-Malek | 53670dd | 2018-01-18 22:07:21 | [diff] [blame] | 32 | network::mojom::NetworkContextPtr CreateNetworkContext() { |
| 33 | network::mojom::NetworkContextPtr network_context; |
| 34 | network::mojom::NetworkContextParamsPtr context_params = |
| 35 | network::mojom::NetworkContextParams::New(); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 36 | GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context), |
| 37 | std::move(context_params)); |
| 38 | return network_context; |
| 39 | } |
| 40 | |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 41 | int LoadBasicRequestOnIOThread( |
| 42 | URLLoaderFactoryGetter* url_loader_factory_getter, |
| 43 | const GURL& url) { |
| 44 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
John Abd-El-Malek | 1df6179 | 2018-01-12 20:40:45 | [diff] [blame] | 45 | auto request = std::make_unique<network::ResourceRequest>(); |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 46 | 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-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 52 | std::unique_ptr<network::SimpleURLLoader> simple_loader = |
| 53 | network::SimpleURLLoader::Create(std::move(request), |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 54 | 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-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 61 | [](network::SimpleURLLoader* loader, |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 62 | URLLoaderFactoryGetter* factory_getter, |
John Abd-El-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 63 | network::SimpleURLLoader::BodyAsStringCallback |
| 64 | body_as_string_callback) { |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 65 | 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-Malek | a728915 | 2018-02-17 00:16:19 | [diff] [blame^] | 77 | int 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 Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 94 | } // namespace |
| 95 | |
| 96 | // This test source has been excluded from Android as Android doesn't have |
| 97 | // out-of-process Network Service. |
| 98 | class NetworkServiceRestartBrowserTest : public ContentBrowserTest { |
| 99 | public: |
| 100 | NetworkServiceRestartBrowserTest() { |
Yutaka Hirano | d8789f9 | 2018-01-30 09:59:51 | [diff] [blame] | 101 | scoped_feature_list_.InitAndEnableFeature( |
| 102 | network::features::kNetworkService); |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | void SetUpOnMainThread() override { |
Chong Zhang | 5d9b3418 | 2018-01-30 16:20:57 | [diff] [blame] | 106 | embedded_test_server()->RegisterRequestMonitor( |
| 107 | base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest, |
| 108 | base::Unretained(this))); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 109 | EXPECT_TRUE(embedded_test_server()->Start()); |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 110 | ContentBrowserTest::SetUpOnMainThread(); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 111 | } |
| 112 | |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 113 | GURL GetTestURL() const { |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 114 | // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug. |
| 115 | // See https://crbug.com/792255. |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 116 | return embedded_test_server()->GetURL("/echoheader"); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 117 | } |
| 118 | |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 119 | BrowserContext* browser_context() { |
| 120 | return shell()->web_contents()->GetBrowserContext(); |
| 121 | } |
| 122 | |
Chong Zhang | 5d9b3418 | 2018-01-30 16:20:57 | [diff] [blame] | 123 | 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 Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 160 | private: |
Chong Zhang | 5d9b3418 | 2018-01-30 16:20:57 | [diff] [blame] | 161 | std::string last_request_relative_url_; |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 162 | base::test::ScopedFeatureList scoped_feature_list_; |
| 163 | |
| 164 | DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartBrowserTest); |
| 165 | }; |
| 166 | |
| 167 | IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, |
| 168 | NetworkServiceProcessRecovery) { |
John Abd-El-Malek | 53670dd | 2018-01-18 22:07:21 | [diff] [blame] | 169 | network::mojom::NetworkContextPtr network_context = CreateNetworkContext(); |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 170 | EXPECT_EQ(net::OK, LoadBasicRequest(network_context.get(), GetTestURL())); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 171 | EXPECT_TRUE(network_context.is_bound()); |
| 172 | EXPECT_FALSE(network_context.encountered_error()); |
| 173 | |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 174 | // Crash the NetworkService process. Existing interfaces should receive error |
| 175 | // notifications at some point. |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 176 | SimulateNetworkServiceCrash(); |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 177 | // |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 Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 181 | EXPECT_TRUE(network_context.is_bound()); |
| 182 | EXPECT_TRUE(network_context.encountered_error()); |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 183 | // Make sure we could get |net::ERR_FAILED| with an invalid |network_context|. |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 184 | EXPECT_EQ(net::ERR_FAILED, |
| 185 | LoadBasicRequest(network_context.get(), GetTestURL())); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 186 | |
| 187 | // NetworkService should restart automatically and return valid interface. |
John Abd-El-Malek | 53670dd | 2018-01-18 22:07:21 | [diff] [blame] | 188 | network::mojom::NetworkContextPtr network_context2 = CreateNetworkContext(); |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 189 | EXPECT_EQ(net::OK, LoadBasicRequest(network_context2.get(), GetTestURL())); |
Chong Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 190 | EXPECT_TRUE(network_context2.is_bound()); |
| 191 | EXPECT_FALSE(network_context2.encountered_error()); |
| 192 | } |
| 193 | |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 194 | // Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface |
| 195 | // after crash. |
| 196 | IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, |
Chong Zhang | e0dfdb6 | 2017-12-09 18:25:14 | [diff] [blame] | 197 | StoragePartitionImplGetNetworkContext) { |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 198 | StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 199 | BrowserContext::GetDefaultStoragePartition(browser_context())); |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 200 | |
John Abd-El-Malek | 53670dd | 2018-01-18 22:07:21 | [diff] [blame] | 201 | network::mojom::NetworkContext* old_network_context = |
| 202 | partition->GetNetworkContext(); |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 203 | EXPECT_EQ(net::OK, LoadBasicRequest(old_network_context, GetTestURL())); |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 204 | |
| 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 Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 214 | EXPECT_EQ(net::OK, |
| 215 | LoadBasicRequest(partition->GetNetworkContext(), GetTestURL())); |
Chong Zhang | 5f46827 | 2017-12-07 23:59:14 | [diff] [blame] | 216 | } |
| 217 | |
Chong Zhang | d4c92364 | 2018-01-03 21:22:29 | [diff] [blame] | 218 | // Make sure |URLLoaderFactoryGetter| returns valid interface after crash. |
| 219 | IN_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. |
| 241 | IN_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 Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 261 | // Make sure basic XHR works after crash. |
Chong Zhang | 5d9b3418 | 2018-01-30 16:20:57 | [diff] [blame] | 262 | IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) { |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 263 | StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
| 264 | BrowserContext::GetDefaultStoragePartition(browser_context())); |
| 265 | |
Chong Zhang | 5d9b3418 | 2018-01-30 16:20:57 | [diff] [blame] | 266 | EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); |
Chong Zhang | 7306b0b | 2018-01-24 05:59:24 | [diff] [blame] | 267 | 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-Malek | a728915 | 2018-02-17 00:16:19 | [diff] [blame^] | 284 | // Make sure the factory returned from |
| 285 | // |StoragePartition::GetURLLoaderFactoryForBrowserProcess()| continues to work |
| 286 | // after crashes. |
| 287 | IN_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. |
| 304 | IN_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 Zhang | c583e67 | 2017-11-08 16:34:08 | [diff] [blame] | 322 | } // namespace content |