Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include "base/base64.h" | 8 #include "base/base64.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/json/json_string_value_serializer.h" | 10 #include "base/json/json_string_value_serializer.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
| 13 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
| 16 #include "chrome/browser/net/predictor.h" | 16 #include "chrome/browser/net/predictor.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 19 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 20 #include "chrome/test/base/in_process_browser_test.h" | 21 #include "chrome/test/base/in_process_browser_test.h" |
| 21 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
| 22 #include "components/prefs/pref_service.h" | 23 #include "components/prefs/pref_service.h" |
| 23 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 25 #include "content/public/test/browser_test_utils.h" | |
| 24 #include "content/public/test/test_utils.h" | 26 #include "content/public/test/test_utils.h" |
| 25 #include "net/base/host_port_pair.h" | 27 #include "net/base/host_port_pair.h" |
| 26 #include "net/base/ip_endpoint.h" | 28 #include "net/base/ip_endpoint.h" |
| 27 #include "net/base/net_errors.h" | 29 #include "net/base/net_errors.h" |
| 28 #include "net/dns/host_resolver_proc.h" | 30 #include "net/dns/host_resolver_proc.h" |
| 29 #include "net/dns/mock_host_resolver.h" | 31 #include "net/dns/mock_host_resolver.h" |
| 30 #include "net/socket/stream_socket.h" | 32 #include "net/socket/stream_socket.h" |
| 31 #include "net/test/embedded_test_server/embedded_test_server.h" | 33 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 32 #include "net/test/embedded_test_server/embedded_test_server_connection_listener .h" | 34 #include "net/test/embedded_test_server/embedded_test_server_connection_listener .h" |
| 35 #include "net/test/embedded_test_server/http_request.h" | |
| 36 #include "net/test/embedded_test_server/http_response.h" | |
| 37 #include "net/url_request/url_request_filter.h" | |
| 38 #include "net/url_request/url_request_interceptor.h" | |
| 39 #include "net/url_request/url_request_test_job.h" | |
| 33 #include "testing/gmock/include/gmock/gmock.h" | 40 #include "testing/gmock/include/gmock/gmock.h" |
| 34 | 41 |
| 35 using content::BrowserThread; | 42 using content::BrowserThread; |
| 36 using testing::HasSubstr; | 43 using testing::HasSubstr; |
| 37 | 44 |
| 38 namespace { | 45 namespace { |
| 39 | 46 |
| 40 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; | 47 const char kBlinkPreconnectFeature[] = "LinkPreconnect"; |
| 41 const char kChromiumHostname[] = "chromium.org"; | 48 const char kChromiumHostname[] = "chromium.org"; |
| 42 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-" | 49 const char kInvalidLongHostname[] = "illegally-long-hostname-over-255-" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 64 base::AutoLock lock(lock_); | 71 base::AutoLock lock(lock_); |
| 65 uint16_t socket = GetPort(connection); | 72 uint16_t socket = GetPort(connection); |
| 66 EXPECT_TRUE(sockets_.find(socket) == sockets_.end()); | 73 EXPECT_TRUE(sockets_.find(socket) == sockets_.end()); |
| 67 | 74 |
| 68 sockets_[socket] = SOCKET_ACCEPTED; | 75 sockets_[socket] = SOCKET_ACCEPTED; |
| 69 task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure()); | 76 task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure()); |
| 70 } | 77 } |
| 71 | 78 |
| 72 // Get called from the EmbeddedTestServer thread to be notified that | 79 // Get called from the EmbeddedTestServer thread to be notified that |
| 73 // a connection was read from. | 80 // a connection was read from. |
| 74 void ReadFromSocket(const net::StreamSocket& connection) override { | 81 void ReadFromSocket(const net::StreamSocket& connection, int rv) override { |
| 75 base::AutoLock lock(lock_); | 82 base::AutoLock lock(lock_); |
|
mmenke
2016/04/15 15:44:03
This can be below the rv <= 0 check
Charlie Harrison
2016/04/20 12:36:42
Done.
| |
| 83 // Don't log a read if no data was transferred. This case often happens if | |
| 84 // the sockets of the test server are being flushed and disconnected. | |
| 85 if (rv <= 0) | |
| 86 return; | |
| 76 uint16_t socket = GetPort(connection); | 87 uint16_t socket = GetPort(connection); |
| 77 EXPECT_FALSE(sockets_.find(socket) == sockets_.end()); | 88 EXPECT_FALSE(sockets_.find(socket) == sockets_.end()); |
| 78 | 89 |
| 79 sockets_[socket] = SOCKET_READ_FROM; | 90 sockets_[socket] = SOCKET_READ_FROM; |
| 80 task_runner_->PostTask(FROM_HERE, read_loop_.QuitClosure()); | 91 task_runner_->PostTask(FROM_HERE, read_loop_.QuitClosure()); |
| 81 } | 92 } |
| 82 | 93 |
| 83 // Returns the number of sockets that were accepted by the server. | 94 // Returns the number of sockets that were accepted by the server. |
| 84 size_t GetAcceptedSocketCount() const { | 95 size_t GetAcceptedSocketCount() const { |
| 85 base::AutoLock lock(lock_); | 96 base::AutoLock lock(lock_); |
| 86 return sockets_.size(); | 97 return sockets_.size(); |
| 87 } | 98 } |
| 88 | 99 |
| 89 // Returns the number of sockets that were read from by the server. | 100 // Returns the number of sockets that were read from by the server. |
| 90 size_t GetReadSocketCount() const { | 101 size_t GetReadSocketCount() const { |
| 91 base::AutoLock lock(lock_); | |
| 92 size_t read_sockets = 0; | 102 size_t read_sockets = 0; |
|
mmenke
2016/04/15 15:44:02
Why did you remove the lock? If this coincides wi
Charlie Harrison
2016/04/20 12:36:43
This was a careless mistake probably from rearrang
| |
| 93 for (const auto& socket : sockets_) { | 103 for (const auto& socket : sockets_) { |
| 94 if (socket.second == SOCKET_READ_FROM) | 104 if (socket.second == SOCKET_READ_FROM) |
| 95 ++read_sockets; | 105 ++read_sockets; |
| 96 } | 106 } |
| 97 return read_sockets; | 107 return read_sockets; |
| 98 } | 108 } |
| 99 | 109 |
| 100 void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); } | 110 void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); } |
| 101 | 111 |
| 102 void WaitUntilFirstConnectionRead() { read_loop_.Run(); } | 112 void WaitUntilFirstConnectionRead() { read_loop_.Run(); } |
| 103 | 113 |
| 114 void ClearSockets() { | |
| 115 base::AutoLock lock(lock_); | |
| 116 sockets_.clear(); | |
| 117 } | |
| 118 | |
| 104 private: | 119 private: |
| 105 static uint16_t GetPort(const net::StreamSocket& connection) { | 120 static uint16_t GetPort(const net::StreamSocket& connection) { |
| 106 // Get the remote port of the peer, since the local port will always be the | 121 // Get the remote port of the peer, since the local port will always be the |
| 107 // port the test server is listening on. This isn't strictly correct - it's | 122 // port the test server is listening on. This isn't strictly correct - it's |
| 108 // possible for multiple peers to connect with the same remote port but | 123 // possible for multiple peers to connect with the same remote port but |
| 109 // different remote IPs - but the tests here assume that connections to the | 124 // different remote IPs - but the tests here assume that connections to the |
| 110 // test server (running on localhost) will always come from localhost, and | 125 // test server (running on localhost) will always come from localhost, and |
| 111 // thus the peer port is all thats needed to distinguish two connections. | 126 // thus the peer port is all thats needed to distinguish two connections. |
| 112 // This also would be problematic if the OS reused ports, but that's not | 127 // This also would be problematic if the OS reused ports, but that's not |
| 113 // something to worry about for these tests. | 128 // something to worry about for these tests. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 // requested and thus is running a nested message loop. | 210 // requested and thus is running a nested message loop. |
| 196 bool is_waiting_for_hostname_; | 211 bool is_waiting_for_hostname_; |
| 197 | 212 |
| 198 // A list of hostnames for which resolution has already been requested. Only | 213 // A list of hostnames for which resolution has already been requested. Only |
| 199 // to be accessed from the UI thread. | 214 // to be accessed from the UI thread. |
| 200 std::vector<std::string> requested_hostnames_; | 215 std::vector<std::string> requested_hostnames_; |
| 201 | 216 |
| 202 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder); | 217 DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder); |
| 203 }; | 218 }; |
| 204 | 219 |
| 220 // This class intercepts URLRequests and responds with 404s. | |
| 221 class NotFoundRequestInterceptor : public net::URLRequestInterceptor { | |
|
mmenke
2016/04/15 15:44:03
Give this a public constructor and destructor, and
Charlie Harrison
2016/04/20 12:36:43
Done.
| |
| 222 net::URLRequestJob* MaybeInterceptRequest( | |
| 223 net::URLRequest* request, | |
| 224 net::NetworkDelegate* network_delegate) const override { | |
| 225 const char kHeaders[] = | |
| 226 "HTTP/1.1 404 Not Found\n" | |
| 227 "\n"; | |
| 228 std::string headers(kHeaders, arraysize(kHeaders)); | |
| 229 | |
| 230 return new net::URLRequestTestJob(request, network_delegate, headers, "", | |
| 231 true); | |
|
mmenke
2016/04/15 15:44:02
URLRequestTestJobs are weird. Can we just use URL
Charlie Harrison
2016/04/20 12:36:43
Sure. I'm not sure what the best error is, but ABO
| |
| 232 } | |
| 233 }; | |
| 234 | |
| 205 } // namespace | 235 } // namespace |
| 206 | 236 |
| 207 namespace chrome_browser_net { | 237 namespace chrome_browser_net { |
| 208 | 238 |
| 209 class PredictorBrowserTest : public InProcessBrowserTest { | 239 class PredictorBrowserTest : public InProcessBrowserTest, |
| 240 public PredictorObserver { | |
| 210 public: | 241 public: |
| 211 PredictorBrowserTest() | 242 PredictorBrowserTest() |
| 212 : startup_url_("http://host1:1"), | 243 : startup_url_("http://host1:1"), |
| 213 referring_url_("http://host2:1"), | 244 referring_url_("http://host2:1"), |
| 214 target_url_("http://host3:1"), | 245 target_url_("http://host3:1"), |
| 215 host_resolution_request_recorder_(new HostResolutionRequestRecorder) { | 246 source_target_learned_(0), |
| 247 preconnected_target_(0), | |
| 248 preconnected_source_(0), | |
| 249 host_resolution_request_recorder_(new HostResolutionRequestRecorder), | |
| 250 target_test_server_(new net::EmbeddedTestServer()) {} | |
| 251 | |
| 252 protected: | |
| 253 // PredictorObserver: | |
| 254 void OnPreconnectUrl(const GURL& original_url, | |
|
mmenke
2016/04/15 15:44:02
I don't think these should be part of the test fix
Charlie Harrison
2016/04/20 12:36:42
Fair enough, done.
| |
| 255 const GURL& first_party_for_cookies, | |
| 256 UrlInfo::ResolutionMotivation motivation, | |
| 257 int count) override { | |
|
mmenke
2016/04/15 15:44:02
These are called on the IO thread, but you're acce
Charlie Harrison
2016/04/20 12:36:42
I added locks.
| |
| 258 if (original_url == target_test_server()->base_url()) | |
| 259 preconnected_target_ = std::max(preconnected_target_, count); | |
| 260 else if (original_url == embedded_test_server()->base_url()) | |
| 261 preconnected_source_ = std::max(preconnected_source_, count); | |
|
mmenke
2016/04/15 15:44:02
nit: Use braces in if/else (Style varies in Chrom
mmenke
2016/04/15 15:44:03
If we're preconnecting some other URL, should we f
mmenke
2016/04/15 15:44:03
If it's neither of those URLs, should we fail?
Charlie Harrison
2016/04/20 12:36:42
Done.
Charlie Harrison
2016/04/20 12:36:42
Yeah. Done.
Charlie Harrison
2016/04/20 12:36:43
Yupp, done.
| |
| 216 } | 262 } |
| 217 | 263 |
| 218 protected: | 264 void OnLearnFromNavigation(const GURL& referring_url, |
| 265 const GURL& target_url) override { | |
| 266 if (referring_url == embedded_test_server()->base_url() && | |
| 267 target_url == target_test_server()->base_url()) { | |
| 268 source_target_learned_++; | |
| 269 } | |
|
mmenke
2016/04/15 15:44:02
What if they aren't equal? Should we do something
Charlie Harrison
2016/04/20 12:36:42
I've added failure conditions.
| |
| 270 } | |
| 271 | |
| 219 void SetUpInProcessBrowserTestFixture() override { | 272 void SetUpInProcessBrowserTestFixture() override { |
| 220 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( | 273 scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( |
| 221 host_resolution_request_recorder_.get())); | 274 host_resolution_request_recorder_.get())); |
| 222 InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); | 275 InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); |
| 223 } | 276 } |
| 224 | 277 |
| 225 void SetUpCommandLine(base::CommandLine* command_line) override { | 278 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 226 command_line->AppendSwitch( | 279 command_line->AppendSwitch( |
| 227 switches::kEnableExperimentalWebPlatformFeatures); | 280 switches::kEnableExperimentalWebPlatformFeatures); |
| 228 command_line->AppendSwitchASCII( | 281 command_line->AppendSwitchASCII( |
| 229 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature); | 282 switches::kEnableBlinkFeatures, kBlinkPreconnectFeature); |
| 230 } | 283 } |
| 231 | 284 |
| 285 std::unique_ptr<net::test_server::HttpResponse> HandleRequest( | |
| 286 const net::test_server::HttpRequest& request) { | |
| 287 if (request.GetURL().path() != "/") | |
| 288 return nullptr; | |
| 289 std::unique_ptr<net::test_server::BasicHttpResponse> response( | |
| 290 new net::test_server::BasicHttpResponse); | |
| 291 response->set_code(net::HTTP_MOVED_PERMANENTLY); | |
| 292 response->AddCustomHeader( | |
| 293 "Location", target_test_server()->GetURL("/title1.html").spec()); | |
| 294 return std::move(response); | |
| 295 } | |
| 296 | |
| 232 void SetUpOnMainThread() override { | 297 void SetUpOnMainThread() override { |
| 298 embedded_test_server()->RegisterRequestHandler(base::Bind( | |
| 299 &PredictorBrowserTest::HandleRequest, base::Unretained(this))); | |
| 300 predictor()->SetObserver(this); | |
|
mmenke
2016/04/15 15:44:03
Calling this on the UI thread after the IOThread h
Charlie Harrison
2016/04/20 12:36:42
Done. The tests now call "InstallPredictorObserver
| |
| 301 predictor()->set_preconnect_enabled(true); | |
| 302 target_test_server_->ServeFilesFromSourceDirectory("chrome/test/data/"); | |
| 303 | |
| 233 connection_listener_.reset(new ConnectionListener()); | 304 connection_listener_.reset(new ConnectionListener()); |
| 305 target_connection_listener_.reset(new ConnectionListener()); | |
| 234 embedded_test_server()->SetConnectionListener(connection_listener_.get()); | 306 embedded_test_server()->SetConnectionListener(connection_listener_.get()); |
| 307 target_test_server_->SetConnectionListener( | |
| 308 target_connection_listener_.get()); | |
| 235 ASSERT_TRUE(embedded_test_server()->Start()); | 309 ASSERT_TRUE(embedded_test_server()->Start()); |
| 310 ASSERT_TRUE(target_test_server_->Start()); | |
| 311 | |
| 312 // Ignore all favicon requests. These are tricky to deal with because they | |
| 313 // are scheduled on the UI thread and are not accounted for in the load | |
| 314 // event. The interceptor will respond with 404s, and we won't connect any | |
| 315 // sockets to the test server. | |
|
mmenke
2016/04/15 15:44:03
nit avoid "we" in comments.
Charlie Harrison
2016/04/20 12:36:43
Done. Removed all "we"s in comments in this file.
| |
| 316 BrowserThread::PostTask( | |
| 317 BrowserThread::IO, FROM_HERE, | |
| 318 base::Bind(&PredictorBrowserTest::AddUrlInterceptor, | |
| 319 target_test_server()->GetURL("/favicon.ico"))); | |
|
mmenke
2016/04/13 17:50:23
Do we still learn from these requests? Just wonde
Charlie Harrison
2016/04/13 18:16:00
I think we do still learn from these. They are a h
| |
| 236 } | 320 } |
| 237 | 321 |
| 238 void TearDownOnMainThread() override { | 322 void TearDownOnMainThread() override { |
| 239 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); | 323 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); |
| 240 } | 324 } |
| 241 | 325 |
| 242 // Navigates to a data URL containing the given content, with a MIME type of | 326 // Navigates to a data URL containing the given content, with a MIME type of |
| 243 // text/html. | 327 // text/html. |
| 244 void NavigateToDataURLWithContent(const std::string& content) { | 328 void NavigateToDataURLWithContent(const std::string& content) { |
| 245 std::string encoded_content; | 329 std::string encoded_content; |
| 246 base::Base64Encode(content, &encoded_content); | 330 base::Base64Encode(content, &encoded_content); |
| 247 std::string data_uri_content = "data:text/html;base64," + encoded_content; | 331 std::string data_uri_content = "data:text/html;base64," + encoded_content; |
| 248 ui_test_utils::NavigateToURL(browser(), GURL(data_uri_content)); | 332 ui_test_utils::NavigateToURL(browser(), GURL(data_uri_content)); |
| 249 } | 333 } |
| 250 | 334 |
| 251 void TearDownInProcessBrowserTestFixture() override { | 335 void TearDownInProcessBrowserTestFixture() override { |
| 252 InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); | 336 InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); |
| 253 scoped_host_resolver_proc_.reset(); | 337 scoped_host_resolver_proc_.reset(); |
| 254 } | 338 } |
| 255 | 339 |
| 256 void LearnAboutInitialNavigation(const GURL& url) { | 340 void LearnAboutInitialNavigation(const GURL& url) { |
| 257 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); | 341 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 258 BrowserThread::PostTask(BrowserThread::IO, | |
| 259 FROM_HERE, | |
| 260 base::Bind(&Predictor::LearnAboutInitialNavigation, | 342 base::Bind(&Predictor::LearnAboutInitialNavigation, |
| 261 base::Unretained(predictor), | 343 base::Unretained(predictor()), url)); |
| 262 url)); | |
| 263 content::RunAllPendingInMessageLoop(BrowserThread::IO); | 344 content::RunAllPendingInMessageLoop(BrowserThread::IO); |
| 264 } | 345 } |
| 265 | 346 |
| 266 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) { | 347 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) { |
| 267 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); | 348 BrowserThread::PostTask( |
| 268 BrowserThread::PostTask(BrowserThread::IO, | 349 BrowserThread::IO, FROM_HERE, |
| 269 FROM_HERE, | 350 base::Bind(&Predictor::LearnFromNavigation, |
| 270 base::Bind(&Predictor::LearnFromNavigation, | 351 base::Unretained(predictor()), referring_url, target_url)); |
| 271 base::Unretained(predictor), | |
| 272 referring_url, | |
| 273 target_url)); | |
| 274 content::RunAllPendingInMessageLoop(BrowserThread::IO); | 352 content::RunAllPendingInMessageLoop(BrowserThread::IO); |
| 275 } | 353 } |
| 276 | 354 |
| 277 void PrepareFrameSubresources(const GURL& url) { | 355 void PrepareFrameSubresources(const GURL& url) { |
| 278 Predictor* predictor = browser()->profile()->GetNetworkPredictor(); | 356 predictor()->PredictFrameSubresources(url, GURL()); |
| 279 predictor->PredictFrameSubresources(url, GURL()); | |
| 280 } | 357 } |
| 281 | 358 |
| 282 void GetListFromPrefsAsString(const char* list_path, | 359 void GetListFromPrefsAsString(const char* list_path, |
| 283 std::string* value_as_string) const { | 360 std::string* value_as_string) const { |
| 284 PrefService* prefs = browser()->profile()->GetPrefs(); | 361 PrefService* prefs = browser()->profile()->GetPrefs(); |
| 285 const base::ListValue* list_value = prefs->GetList(list_path); | 362 const base::ListValue* list_value = prefs->GetList(list_path); |
| 286 JSONStringValueSerializer serializer(value_as_string); | 363 JSONStringValueSerializer serializer(value_as_string); |
| 287 serializer.Serialize(*list_value); | 364 serializer.Serialize(*list_value); |
| 288 } | 365 } |
| 289 | 366 |
| 290 bool HasHostBeenRequested(const std::string& hostname) const { | 367 bool HasHostBeenRequested(const std::string& hostname) const { |
| 291 return host_resolution_request_recorder_->HasHostBeenRequested(hostname); | 368 return host_resolution_request_recorder_->HasHostBeenRequested(hostname); |
| 292 } | 369 } |
| 293 | 370 |
| 294 void WaitUntilHostHasBeenRequested(const std::string& hostname) { | 371 void WaitUntilHostHasBeenRequested(const std::string& hostname) { |
| 295 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname); | 372 host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname); |
| 296 } | 373 } |
| 297 | 374 |
| 298 int RequestedHostnameCount() const { | 375 int RequestedHostnameCount() const { |
| 299 return host_resolution_request_recorder_->RequestedHostnameCount(); | 376 return host_resolution_request_recorder_->RequestedHostnameCount(); |
| 300 } | 377 } |
| 301 | 378 |
| 379 net::EmbeddedTestServer* target_test_server() { | |
| 380 return target_test_server_.get(); | |
| 381 } | |
| 382 | |
| 383 Predictor* predictor() { return browser()->profile()->GetNetworkPredictor(); } | |
| 384 | |
| 385 // Navigate to an html file and request async fetches. Wait until the fetches | |
| 386 // complete before continuing. | |
| 387 void NavigateToCrossSiteHTMLURL(int num_cors, | |
| 388 int num_non_cors, | |
|
mmenke
2016/04/15 15:44:02
Think we should rename cors/non_cors to match the
mmenke
2016/04/15 20:27:17
Oh...The fact that non_cors does not mean same sit
Charlie Harrison
2016/04/20 12:36:43
Ok, I will update with a comment.
Charlie Harrison
2016/04/20 12:36:43
So actually the non cors perform a fetch() to the
| |
| 389 const char* file_suffix) { | |
| 390 const GURL& base_url = target_test_server()->base_url(); | |
| 391 std::string url = base::StringPrintf( | |
|
mmenke
2016/04/15 15:44:03
Not a url - this is a path. As-is, the GetURL(url
Charlie Harrison
2016/04/20 12:36:42
Done.
| |
| 392 "/predictor/" | |
| 393 "predictor_cross_site%s.html?subresourceHost=%s&" | |
| 394 "numCORSResources=%d&numNonCORSResources=%d", | |
| 395 file_suffix, base_url.spec().c_str(), num_cors, num_non_cors); | |
| 396 ui_test_utils::NavigateToURL(browser(), | |
| 397 embedded_test_server()->GetURL(url)); | |
| 398 bool result = false; | |
| 399 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( | |
| 400 browser()->tab_strip_model()->GetActiveWebContents(), "sendFetches()", | |
| 401 &result)); | |
| 402 EXPECT_TRUE(result); | |
| 403 } | |
| 404 | |
| 405 // Simulate the target server restarting. Delete all sockets and reset members | |
| 406 // tracking preconnects. | |
| 407 void ResetTarget() { | |
| 408 preconnected_target_ = 0; | |
| 409 target_test_server()->FlushAllSocketsAndConnectionsOnUIThread(); | |
| 410 target_connection_listener_->ClearSockets(); | |
| 411 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 412 } | |
| 413 | |
| 414 static void AddUrlInterceptor(const GURL url) { | |
| 415 net::URLRequestFilter::GetInstance()->AddUrlInterceptor( | |
| 416 url, make_scoped_ptr(new NotFoundRequestInterceptor())); | |
| 417 } | |
| 418 | |
| 302 const GURL startup_url_; | 419 const GURL startup_url_; |
| 303 const GURL referring_url_; | 420 const GURL referring_url_; |
| 304 const GURL target_url_; | 421 const GURL target_url_; |
| 305 scoped_ptr<ConnectionListener> connection_listener_; | 422 std::unique_ptr<ConnectionListener> connection_listener_; |
| 423 std::unique_ptr<ConnectionListener> target_connection_listener_; | |
| 424 | |
| 425 int source_target_learned_; | |
| 426 int preconnected_target_; | |
| 427 int preconnected_source_; | |
| 306 | 428 |
| 307 private: | 429 private: |
| 308 scoped_refptr<HostResolutionRequestRecorder> | 430 scoped_refptr<HostResolutionRequestRecorder> |
| 309 host_resolution_request_recorder_; | 431 host_resolution_request_recorder_; |
| 310 scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_; | 432 std::unique_ptr<net::ScopedDefaultHostResolverProc> |
| 433 scoped_host_resolver_proc_; | |
| 434 std::unique_ptr<net::EmbeddedTestServer> target_test_server_; | |
|
mmenke
2016/04/15 15:44:02
Think this needs a comment. I suggest calling it
Charlie Harrison
2016/04/20 12:36:42
Done. Renamed to "cross_site_test_server".
| |
| 311 }; | 435 }; |
| 312 | 436 |
| 437 // Test the html test harness used to initiate cross site fetches. These | |
| 438 // initiate cross site subresource requests (CORS and non-CORS) to the target | |
| 439 // test server. Inspect the predictor's internal state to make sure that they | |
| 440 // are properly logged. | |
| 441 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNonCORSUseOneSocket) { | |
| 442 NavigateToCrossSiteHTMLURL(0, 1, ""); | |
|
mmenke
2016/04/15 15:44:03
Suggest you should add comments with the variable
Charlie Harrison
2016/04/20 12:36:42
Done.
| |
| 443 EXPECT_EQ(1u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 444 EXPECT_EQ(1, source_target_learned_); | |
| 445 EXPECT_EQ(2, preconnected_source_); | |
| 446 } | |
| 447 | |
| 448 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNonCORSUseThreeSockets) { | |
| 449 NavigateToCrossSiteHTMLURL(0, 3, ""); | |
| 450 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 451 EXPECT_EQ(3, source_target_learned_); | |
| 452 EXPECT_EQ(2, preconnected_source_); | |
| 453 } | |
| 454 | |
| 455 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 456 CrossSiteCORSAndNonCORSUseOneSocket) { | |
| 457 NavigateToCrossSiteHTMLURL(1, 1, ""); | |
|
mmenke
2016/04/15 20:27:17
Why do we care so much about the cors vs. non-cors
Charlie Harrison
2016/04/20 12:36:42
It was originally because these separate into priv
| |
| 458 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 459 EXPECT_EQ(2, source_target_learned_); | |
| 460 EXPECT_EQ(2, preconnected_source_); | |
| 461 } | |
| 462 | |
| 463 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteCORSUseTwoSockets) { | |
| 464 NavigateToCrossSiteHTMLURL(2, 0, ""); | |
| 465 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 466 EXPECT_EQ(2, source_target_learned_); | |
| 467 EXPECT_EQ(2, preconnected_source_); | |
| 468 } | |
| 469 | |
| 470 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteNoReferrerNoLearning) { | |
| 471 NavigateToCrossSiteHTMLURL(1, 0, "_no_referrer"); | |
| 472 EXPECT_EQ(1u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 473 EXPECT_EQ(0, source_target_learned_); | |
| 474 EXPECT_EQ(2, preconnected_source_); | |
| 475 } | |
| 476 | |
| 477 // The following tests confirm that we accurately predict preconnects after | |
| 478 // learning from navigations. Note that every "learned" connection adds ~.33 to | |
| 479 // the expected connection number, which starts at 2. Every preconnect we | |
| 480 // perform multiplies the expected connections by .66. One additional complexity | |
| 481 // is that if we've learned to preconnect to host B on a navigation from host A, | |
| 482 // we add a preconnect if the host part of A and B match (ignoring port). This | |
| 483 // logic could probably be removed. | |
|
mmenke
2016/04/15 20:27:16
Oh wow...that's funky. Could we have a test where
Charlie Harrison
2016/04/20 12:36:43
Added a test using localhost.
| |
| 484 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 485 CrossSiteSimplePredictionAfterOneNavigation) { | |
| 486 NavigateToCrossSiteHTMLURL(2, 0, ""); | |
| 487 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 488 EXPECT_EQ(2, source_target_learned_); | |
| 489 EXPECT_EQ(2, preconnected_source_); | |
| 490 | |
| 491 ResetTarget(); | |
| 492 | |
| 493 // Navigate again and confirm we preconnect. Note that because the two | |
| 494 // embedded test servers have the same host_piece, we preconnect an additional | |
| 495 // time. This gives us ceil(2.66) + 1 = 4 preconnects. | |
| 496 ui_test_utils::NavigateToURL(browser(), | |
| 497 embedded_test_server()->GetURL("/title1.html")); | |
| 498 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 499 EXPECT_EQ(4, preconnected_target_); | |
| 500 } | |
| 501 | |
| 502 // Expect that the predictor correctly predicts subframe navigations. | |
| 503 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeCrossSitePrediction) { | |
| 504 ui_test_utils::NavigateToURL( | |
| 505 browser(), embedded_test_server()->GetURL( | |
| 506 "/predictor/predictor_cross_site_subframe_nav.html")); | |
| 507 bool result = false; | |
| 508 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( | |
| 509 browser()->tab_strip_model()->GetActiveWebContents(), | |
| 510 base::StringPrintf( | |
| 511 "navigateSubframe('%s')", | |
| 512 target_test_server()->GetURL("/title1.html").spec().c_str()), | |
| 513 &result)); | |
| 514 EXPECT_TRUE(result); | |
| 515 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 516 EXPECT_EQ(1, source_target_learned_); | |
| 517 EXPECT_EQ(2, preconnected_source_); | |
| 518 | |
| 519 ResetTarget(); | |
| 520 | |
| 521 // Navigate again and confirm we preconnect. Note that because the two | |
| 522 // embedded test servers have the same host_piece, we preconnect an additional | |
| 523 // time. This gives us ceil(2 + .33) + 1 = 4 preconnects. | |
| 524 ui_test_utils::NavigateToURL(browser(), | |
| 525 embedded_test_server()->GetURL("/title1.html")); | |
| 526 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 527 EXPECT_EQ(4, preconnected_target_); | |
|
mmenke
2016/04/15 20:27:17
How about also having a test where you just re-nav
Charlie Harrison
2016/04/20 12:36:42
Hm, so this test classifies the subframe as "subre
| |
| 528 } | |
| 529 | |
| 530 // This test navigates to an html file with a tag: | |
| 531 // <meta name="referrer" content="never"> | |
|
mmenke
2016/04/15 20:27:17
Is this really desired behavior, or just testing a
Charlie Harrison
2016/04/20 12:36:42
Well, the referrer tag is pretty architecturally i
| |
| 532 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 533 CrossSiteNoReferrerNoPredictionAfterOneNavigation) { | |
| 534 NavigateToCrossSiteHTMLURL(2, 0, "_no_referrer"); | |
| 535 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 536 EXPECT_EQ(0, source_target_learned_); | |
| 537 EXPECT_EQ(2, preconnected_source_); | |
| 538 | |
| 539 ResetTarget(); | |
| 540 | |
| 541 // Navigate again and confirm that no preconnects occurred. | |
| 542 ui_test_utils::NavigateToURL(browser(), | |
| 543 embedded_test_server()->GetURL("/title1.html")); | |
| 544 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 545 EXPECT_EQ(0, preconnected_target_); | |
| 546 } | |
| 547 | |
| 548 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 549 CrossSiteCORSSimplePredictionAfterTwoNavigations) { | |
| 550 NavigateToCrossSiteHTMLURL(0, 1, ""); | |
| 551 NavigateToCrossSiteHTMLURL(0, 1, ""); | |
| 552 | |
| 553 ResetTarget(); | |
| 554 | |
| 555 // Navigate again and confirm we preconnect. Note that because the two | |
| 556 // embedded test servers have the same host_piece, we preconnect an additional | |
| 557 // time. This gives us (2 + .33)*.66 + .33 + 1 ~= 2.87. | |
|
mmenke
2016/04/15 20:27:17
nit: --we (x3). Well, one's an "us".
Charlie Harrison
2016/04/20 12:36:42
Done.
| |
| 558 ui_test_utils::NavigateToURL(browser(), | |
| 559 embedded_test_server()->GetURL("/title1.html")); | |
| 560 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 561 EXPECT_EQ(3, preconnected_target_); | |
| 562 } | |
| 563 | |
| 564 IN_PROC_BROWSER_TEST_F( | |
| 565 PredictorBrowserTest, | |
| 566 CrossSiteCORSAndNonCORSSimplePredictionAfterTwoNavigations) { | |
| 567 NavigateToCrossSiteHTMLURL(1, 1, ""); | |
| 568 NavigateToCrossSiteHTMLURL(1, 1, ""); | |
| 569 | |
| 570 ResetTarget(); | |
| 571 | |
| 572 // Navigate again and confirm we preconnect. Note that because the two | |
| 573 // embedded test servers have the same host_piece, we preconnect an additional | |
| 574 // time. This gives us (((2 + .66)*.66) + .66) + 1 ~= 3.4 | |
| 575 ui_test_utils::NavigateToURL(browser(), | |
| 576 embedded_test_server()->GetURL("/title1.html")); | |
| 577 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 578 EXPECT_EQ(4, preconnected_target_); | |
| 579 } | |
| 580 | |
| 581 // The first navigation uses a subresource. Subsequent navigations don't use | |
| 582 // that subresource. This tests how the predictor forgets about these bad | |
| 583 // navigations. | |
| 584 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ForgetBadPrediction) { | |
| 585 NavigateToCrossSiteHTMLURL(1, 0, ""); | |
| 586 | |
| 587 ResetTarget(); | |
| 588 | |
| 589 ui_test_utils::NavigateToURL(browser(), | |
| 590 embedded_test_server()->GetURL("/title1.html")); | |
| 591 // ceil(2 + .33) + 1 = 4. | |
| 592 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 593 EXPECT_EQ(4, preconnected_target_); | |
| 594 | |
| 595 ResetTarget(); | |
| 596 | |
| 597 ui_test_utils::NavigateToURL(browser(), | |
| 598 embedded_test_server()->GetURL("/title1.html")); | |
| 599 | |
| 600 // ceil((2 + .33) * .66) + 1 = 3. | |
| 601 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 602 EXPECT_EQ(3, preconnected_target_); | |
| 603 | |
| 604 ResetTarget(); | |
| 605 | |
| 606 ui_test_utils::NavigateToURL(browser(), | |
| 607 embedded_test_server()->GetURL("/title1.html")); | |
| 608 // ceil((2 + .33) * .66 * .66) + 1 = 3. | |
| 609 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 610 EXPECT_EQ(3, preconnected_target_); | |
| 611 | |
| 612 ResetTarget(); | |
| 613 | |
| 614 ui_test_utils::NavigateToURL(browser(), | |
| 615 embedded_test_server()->GetURL("/title1.html")); | |
| 616 // Finally, (2 + .33) * .66^3 ~= .67. Not enough for a preconnect. | |
| 617 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 618 EXPECT_EQ(0, preconnected_target_); | |
| 619 } | |
| 620 | |
| 621 // The predictor does not follow redirects if the original url had a non-empty | |
| 622 // path (a path that was more than just "/"). | |
| 623 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 624 CrossSiteRedirectNoPredictionWithPath) { | |
| 625 ui_test_utils::NavigateToURL( | |
| 626 browser(), | |
| 627 embedded_test_server()->GetURL(base::StringPrintf( | |
| 628 "/server-redirect?%s", | |
| 629 target_test_server()->GetURL("/title1.html").spec().c_str()))); | |
| 630 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 631 EXPECT_EQ(0, source_target_learned_); | |
| 632 EXPECT_EQ(2, preconnected_source_); | |
| 633 | |
| 634 ResetTarget(); | |
| 635 | |
| 636 ui_test_utils::NavigateToURL(browser(), | |
| 637 embedded_test_server()->GetURL("/title1.html")); | |
| 638 EXPECT_EQ(0u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 639 EXPECT_EQ(0, preconnected_target_); | |
| 640 } | |
| 641 | |
| 642 // The predictor does follow redirects if the original url had an empty path | |
| 643 // (a path that was more than just "/"). Here we use the registered "/" path to | |
| 644 // redirect to the target test server. | |
| 645 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 646 CrossSiteRedirectPredictionWithNoPath) { | |
| 647 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/")); | |
| 648 EXPECT_EQ(2u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 649 EXPECT_EQ(1, source_target_learned_); | |
| 650 EXPECT_EQ(2, preconnected_source_); | |
| 651 | |
| 652 ResetTarget(); | |
| 653 | |
| 654 ui_test_utils::NavigateToURL(browser(), | |
| 655 embedded_test_server()->GetURL("/title1.html")); | |
| 656 // We preconnect 4 sockets because ceil(2 + .33) + 1 = 4. | |
| 657 EXPECT_EQ(4u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 658 EXPECT_EQ(4, preconnected_target_); | |
| 659 } | |
| 660 | |
| 661 // Perform the "/" redirect twice and make sure the predictor updates twice. | |
| 662 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, | |
| 663 CrossSiteTwoRedirectsPredictionWithNoPath) { | |
| 664 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/")); | |
| 665 EXPECT_EQ(1, source_target_learned_); | |
| 666 EXPECT_EQ(2, preconnected_source_); | |
| 667 | |
| 668 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/")); | |
| 669 EXPECT_EQ(2, source_target_learned_); | |
| 670 EXPECT_EQ(2, preconnected_source_); | |
| 671 | |
| 672 ResetTarget(); | |
| 673 | |
| 674 ui_test_utils::NavigateToURL(browser(), | |
| 675 embedded_test_server()->GetURL("/title1.html")); | |
| 676 // 3 preconnects expected because (2 + .33) * .66 + .33 + 1 ~= 2.87. | |
| 677 EXPECT_EQ(3u, target_connection_listener_->GetAcceptedSocketCount()); | |
| 678 EXPECT_EQ(3, preconnected_target_); | |
| 679 } | |
| 680 | |
| 313 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) { | 681 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) { |
| 314 // Prepare state that will be serialized on this shut-down and read on next | 682 // Prepare state that will be serialized on this shut-down and read on next |
| 315 // start-up. | 683 // start-up. |
| 316 LearnAboutInitialNavigation(startup_url_); | 684 LearnAboutInitialNavigation(startup_url_); |
| 317 LearnFromNavigation(referring_url_, target_url_); | 685 LearnFromNavigation(referring_url_, target_url_); |
| 318 } | 686 } |
| 319 | 687 |
| 320 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) { | 688 IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) { |
| 321 // Make sure that the Preferences file is actually wiped of all DNS prefetch | 689 // Make sure that the Preferences file is actually wiped of all DNS prefetch |
| 322 // related data after start-up. | 690 // related data after start-up. |
| 323 std::string cleared_startup_list; | 691 std::string cleared_startup_list; |
| 324 std::string cleared_referral_list; | 692 std::string cleared_referral_list; |
| 325 GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, | 693 GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, |
| 326 &cleared_startup_list); | 694 &cleared_startup_list); |
| 327 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, | 695 GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, |
| 328 &cleared_referral_list); | 696 &cleared_referral_list); |
| 329 | 697 |
| 330 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host()))); | 698 EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host()))); |
| 331 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); | 699 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); |
| 332 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); | 700 EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); |
| 333 | 701 |
| 334 // But also make sure this data has been first loaded into the Predictor, by | 702 // But also make sure this data has been first loaded into the Predictor, by |
| 335 // inspecting that the Predictor starts making the expected hostname requests. | 703 // inspecting that the Predictor starts making the expected hostname requests. |
| 704 predictor()->set_preconnect_enabled(false); | |
| 336 PrepareFrameSubresources(referring_url_); | 705 PrepareFrameSubresources(referring_url_); |
| 337 WaitUntilHostHasBeenRequested(startup_url_.host()); | 706 WaitUntilHostHasBeenRequested(startup_url_.host()); |
| 338 WaitUntilHostHasBeenRequested(target_url_.host()); | 707 WaitUntilHostHasBeenRequested(target_url_.host()); |
| 339 } | 708 } |
| 340 | 709 |
| 341 // Flaky on Windows: http://crbug.com/469120 | 710 // Flaky on Windows: http://crbug.com/469120 |
| 342 #if defined(OS_WIN) | 711 #if defined(OS_WIN) |
| 343 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch | 712 #define MAYBE_DnsPrefetch DISABLED_DnsPrefetch |
| 344 #else | 713 #else |
| 345 #define MAYBE_DnsPrefetch DnsPrefetch | 714 #define MAYBE_DnsPrefetch DnsPrefetch |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 // Second navigation to content with an img. | 824 // Second navigation to content with an img. |
| 456 std::string img_content = | 825 std::string img_content = |
| 457 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; | 826 "<img src=\"" + preconnect_url.spec() + "test.gif\">"; |
| 458 NavigateToDataURLWithContent(img_content); | 827 NavigateToDataURLWithContent(img_content); |
| 459 connection_listener_->WaitUntilFirstConnectionRead(); | 828 connection_listener_->WaitUntilFirstConnectionRead(); |
| 460 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); | 829 EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); |
| 461 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); | 830 EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); |
| 462 } | 831 } |
| 463 | 832 |
| 464 } // namespace chrome_browser_net | 833 } // namespace chrome_browser_net |
| OLD | NEW |