1 // Copyright 2013 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 <set> 6 7 #include "base/bind.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/path_service.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/run_loop.h" 13 #include "base/threading/thread_restrictions.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/google/google_util.h" 16 #include "chrome/browser/io_thread.h" 17 #include "chrome/browser/net/dns_probe_test_util.h" 18 #include "chrome/browser/net/net_error_tab_helper.h" 19 #include "chrome/browser/net/url_request_mock_util.h" 20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/ui/browser.h" 22 #include "chrome/browser/ui/browser_commands.h" 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" 24 #include "chrome/common/chrome_paths.h" 25 #include "chrome/common/net/net_error_info.h" 26 #include "chrome/common/pref_names.h" 27 #include "chrome/test/base/in_process_browser_test.h" 28 #include "chrome/test/base/ui_test_utils.h" 29 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/web_contents.h" 31 #include "content/public/test/browser_test_utils.h" 32 #include "content/public/test/test_navigation_observer.h" 33 #include "content/test/net/url_request_failed_job.h" 34 #include "content/test/net/url_request_mock_http_job.h" 35 #include "net/base/net_errors.h" 36 #include "net/dns/dns_test_util.h" 37 #include "net/url_request/url_request_filter.h" 38 #include "net/url_request/url_request_job.h" 39 #include "net/url_request/url_request_job_factory.h" 40 41 using base::Bind; 42 using base::Callback; 43 using base::Closure; 44 using base::ConstRef; 45 using base::FilePath; 46 using base::MessageLoop; 47 using base::Unretained; 48 using chrome_common_net::DnsProbeStatus; 49 using content::BrowserThread; 50 using content::URLRequestFailedJob; 51 using content::URLRequestMockHTTPJob; 52 using content::WebContents; 53 using google_util::LinkDoctorBaseURL; 54 using net::MockDnsClientRule; 55 using net::NetworkDelegate; 56 using net::URLRequest; 57 using net::URLRequestFilter; 58 using net::URLRequestJob; 59 using net::URLRequestJobFactory; 60 using ui_test_utils::NavigateToURL; 61 using ui_test_utils::NavigateToURLBlockUntilNavigationsComplete; 62 63 namespace chrome_browser_net { 64 65 namespace { 66 67 // Postable function to run a Closure on the UI thread. Since 68 // BrowserThread::PostTask returns a bool, it can't directly be posted to 69 // another thread. 70 void RunClosureOnUIThread(const base::Closure& closure) { 71 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, closure); 72 } 73 74 // Wraps DnsProbeService and delays callbacks until someone calls 75 // CallDelayedCallbacks. This allows the DnsProbeBrowserTest to enforce a 76 // stricter ordering of events. 77 class DelayingDnsProbeService : public DnsProbeService { 78 public: 79 DelayingDnsProbeService() {} 80 81 virtual ~DelayingDnsProbeService() { 82 EXPECT_TRUE(delayed_probes_.empty()); 83 } 84 85 virtual void ProbeDns(const ProbeCallback& callback) OVERRIDE { 86 delayed_probes_.push_back(callback); 87 } 88 89 void StartDelayedProbes() { 90 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 91 92 std::vector<ProbeCallback> probes; 93 probes.swap(delayed_probes_); 94 95 for (std::vector<ProbeCallback>::const_iterator i = probes.begin(); 96 i != probes.end(); ++i) { 97 DnsProbeService::ProbeDns(*i); 98 } 99 } 100 101 int delayed_probe_count() const { 102 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 103 return delayed_probes_.size(); 104 } 105 106 private: 107 std::vector<ProbeCallback> delayed_probes_; 108 }; 109 110 FilePath GetMockLinkDoctorFilePath() { 111 FilePath root_http; 112 PathService::Get(chrome::DIR_TEST_DATA, &root_http); 113 return root_http.AppendASCII("mock-link-doctor.html"); 114 } 115 116 // A request that can be delayed until Resume() is called. Can also run a 117 // callback if destroyed without being resumed. Resume can be called either 118 // before or after a the request is started. 119 class DelayableRequest { 120 public: 121 // Called by a DelayableRequest if it was set to be delayed, and has been 122 // destroyed without Undelay being called. 123 typedef base::Callback<void(DelayableRequest* request)> DestructionCallback; 124 125 virtual void Resume() = 0; 126 127 protected: 128 virtual ~DelayableRequest() {} 129 }; 130 131 class DelayableURLRequestFailedJob : public URLRequestFailedJob, 132 public DelayableRequest { 133 public: 134 // |destruction_callback| is only called if a delayed request is destroyed 135 // without being resumed. 136 DelayableURLRequestFailedJob(net::URLRequest* request, 137 net::NetworkDelegate* network_delegate, 138 int net_error, 139 bool should_delay, 140 const DestructionCallback& destruction_callback) 141 : URLRequestFailedJob(request, network_delegate, net_error), 142 should_delay_(should_delay), 143 start_delayed_(false), 144 destruction_callback_(destruction_callback) {} 145 146 virtual void Start() OVERRIDE { 147 if (should_delay_) { 148 DCHECK(!start_delayed_); 149 start_delayed_ = true; 150 return; 151 } 152 URLRequestFailedJob::Start(); 153 } 154 155 virtual void Resume() OVERRIDE { 156 DCHECK(should_delay_); 157 should_delay_ = false; 158 if (start_delayed_) { 159 start_delayed_ = false; 160 Start(); 161 } 162 } 163 164 private: 165 virtual ~DelayableURLRequestFailedJob() { 166 if (should_delay_) 167 destruction_callback_.Run(this); 168 } 169 170 bool should_delay_; 171 bool start_delayed_; 172 const DestructionCallback destruction_callback_; 173 }; 174 175 class DelayableURLRequestMockHTTPJob : public URLRequestMockHTTPJob, 176 public DelayableRequest { 177 public: 178 DelayableURLRequestMockHTTPJob( 179 net::URLRequest* request, 180 net::NetworkDelegate* network_delegate, 181 const base::FilePath& file_path, 182 bool should_delay, 183 const DestructionCallback& destruction_callback) 184 : URLRequestMockHTTPJob(request, network_delegate, file_path), 185 should_delay_(should_delay), 186 start_delayed_(false), 187 destruction_callback_(destruction_callback) {} 188 189 virtual void Start() OVERRIDE { 190 if (should_delay_) { 191 DCHECK(!start_delayed_); 192 start_delayed_ = true; 193 return; 194 } 195 URLRequestMockHTTPJob::Start(); 196 } 197 198 virtual void Resume() OVERRIDE { 199 DCHECK(should_delay_); 200 should_delay_ = false; 201 if (start_delayed_) { 202 start_delayed_ = false; 203 Start(); 204 } 205 } 206 207 private: 208 virtual ~DelayableURLRequestMockHTTPJob() { 209 if (should_delay_) 210 destruction_callback_.Run(this); 211 } 212 213 bool should_delay_; 214 bool start_delayed_; 215 const DestructionCallback destruction_callback_; 216 }; 217 218 // ProtocolHandler for Link Doctor requests. Can cause requests to fail with 219 // an error, and/or delay a request until a test allows to continue. Also can 220 // run a callback when a delayed request is cancelled. 221 class BreakableLinkDoctorProtocolHandler 222 : public URLRequestJobFactory::ProtocolHandler { 223 public: 224 explicit BreakableLinkDoctorProtocolHandler( 225 const FilePath& mock_link_doctor_file_path) 226 : mock_link_doctor_file_path_(mock_link_doctor_file_path), 227 net_error_(net::OK), 228 delay_requests_(false), 229 on_request_destroyed_callback_( 230 base::Bind(&BreakableLinkDoctorProtocolHandler::OnRequestDestroyed, 231 base::Unretained(this))) { 232 } 233 234 virtual ~BreakableLinkDoctorProtocolHandler() { 235 // All delayed requests should have been resumed or cancelled by this point. 236 EXPECT_TRUE(delayed_requests_.empty()); 237 } 238 239 virtual URLRequestJob* MaybeCreateJob( 240 URLRequest* request, 241 NetworkDelegate* network_delegate) const OVERRIDE { 242 if (net_error_ != net::OK) { 243 DelayableURLRequestFailedJob* job = 244 new DelayableURLRequestFailedJob( 245 request, network_delegate, net_error_, delay_requests_, 246 on_request_destroyed_callback_); 247 if (delay_requests_) 248 delayed_requests_.insert(job); 249 return job; 250 } else { 251 DelayableURLRequestMockHTTPJob* job = 252 new DelayableURLRequestMockHTTPJob( 253 request, network_delegate, mock_link_doctor_file_path_, 254 delay_requests_, on_request_destroyed_callback_); 255 if (delay_requests_) 256 delayed_requests_.insert(job); 257 return job; 258 } 259 } 260 261 void set_net_error(int net_error) { net_error_ = net_error; } 262 263 void SetDelayRequests(bool delay_requests) { 264 delay_requests_ = delay_requests; 265 266 // Resume all delayed requests if no longer delaying requests. 267 if (!delay_requests) { 268 while (!delayed_requests_.empty()) { 269 DelayableRequest* request = *delayed_requests_.begin(); 270 delayed_requests_.erase(request); 271 request->Resume(); 272 } 273 } 274 } 275 276 // Runs |callback| once all delayed requests have been destroyed. Does not 277 // wait for delayed requests that have been resumed. 278 void SetRequestDestructionCallback(const base::Closure& callback) { 279 ASSERT_TRUE(delayed_request_destruction_callback_.is_null()); 280 if (delayed_requests_.empty()) { 281 callback.Run(); 282 return; 283 } 284 delayed_request_destruction_callback_ = callback; 285 } 286 287 void OnRequestDestroyed(DelayableRequest* request) { 288 ASSERT_EQ(1u, delayed_requests_.count(request)); 289 delayed_requests_.erase(request); 290 if (delayed_requests_.empty() && 291 !delayed_request_destruction_callback_.is_null()) { 292 delayed_request_destruction_callback_.Run(); 293 delayed_request_destruction_callback_.Reset(); 294 } 295 } 296 297 private: 298 const FilePath mock_link_doctor_file_path_; 299 int net_error_; 300 bool delay_requests_; 301 302 // Called when a request is destroyed. Memeber variable because 303 // MaybeCreateJob is "const", so calling base::Bind in that function does 304 // not work well. 305 const DelayableRequest::DestructionCallback on_request_destroyed_callback_; 306 307 // Mutable is needed because MaybeCreateJob is const. 308 mutable std::set<DelayableRequest*> delayed_requests_; 309 310 base::Closure delayed_request_destruction_callback_; 311 }; 312 313 class DnsProbeBrowserTestIOThreadHelper { 314 public: 315 DnsProbeBrowserTestIOThreadHelper(); 316 317 void SetUpOnIOThread(IOThread* io_thread); 318 void CleanUpOnIOThreadAndDeleteHelper(); 319 320 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result, 321 MockDnsClientRule::Result public_good_result); 322 void SetLinkDoctorNetError(int link_doctor_net_error); 323 void SetLinkDoctorDelayRequests(bool delay_requests); 324 void SetRequestDestructionCallback(const base::Closure& callback); 325 void StartDelayedProbes(int expected_delayed_probe_count); 326 327 private: 328 IOThread* io_thread_; 329 DnsProbeService* original_dns_probe_service_; 330 DelayingDnsProbeService* delaying_dns_probe_service_; 331 BreakableLinkDoctorProtocolHandler* protocol_handler_; 332 FilePath mock_link_doctor_file_path_; 333 }; 334 335 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper() 336 : io_thread_(NULL), 337 original_dns_probe_service_(NULL), 338 delaying_dns_probe_service_(NULL), 339 protocol_handler_(NULL), 340 mock_link_doctor_file_path_(GetMockLinkDoctorFilePath()) {} 341 342 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) { 343 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 344 CHECK(io_thread); 345 CHECK(!io_thread_); 346 CHECK(!original_dns_probe_service_); 347 CHECK(!delaying_dns_probe_service_); 348 CHECK(!protocol_handler_); 349 350 io_thread_ = io_thread; 351 352 delaying_dns_probe_service_ = new DelayingDnsProbeService(); 353 354 IOThread::Globals* globals = io_thread_->globals(); 355 original_dns_probe_service_ = globals->dns_probe_service.release(); 356 globals->dns_probe_service.reset(delaying_dns_probe_service_); 357 358 URLRequestFailedJob::AddUrlHandler(); 359 360 scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler( 361 new BreakableLinkDoctorProtocolHandler(mock_link_doctor_file_path_)); 362 protocol_handler_ = 363 static_cast<BreakableLinkDoctorProtocolHandler*>(protocol_handler.get()); 364 const GURL link_doctor_base_url = LinkDoctorBaseURL(); 365 const std::string link_doctor_host = link_doctor_base_url.host(); 366 URLRequestFilter::GetInstance()->AddHostnameProtocolHandler( 367 "http", link_doctor_host, protocol_handler.Pass()); 368 } 369 370 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper() { 371 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 372 373 URLRequestFilter::GetInstance()->ClearHandlers(); 374 375 IOThread::Globals* globals = io_thread_->globals(); 376 scoped_ptr<DnsProbeService> delaying_dns_probe_service( 377 globals->dns_probe_service.release()); 378 globals->dns_probe_service.reset(original_dns_probe_service_); 379 380 CHECK_EQ(delaying_dns_probe_service_, delaying_dns_probe_service.get()); 381 382 delete this; 383 } 384 385 void DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules( 386 MockDnsClientRule::Result system_result, 387 MockDnsClientRule::Result public_result) { 388 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 389 390 DnsProbeService* service = io_thread_->globals()->dns_probe_service.get(); 391 service->SetSystemClientForTesting( 392 CreateMockDnsClientForProbes(system_result)); 393 service->SetPublicClientForTesting( 394 CreateMockDnsClientForProbes(public_result)); 395 } 396 397 void DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError( 398 int link_doctor_net_error) { 399 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 400 401 protocol_handler_->set_net_error(link_doctor_net_error); 402 } 403 404 void DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorDelayRequests( 405 bool delay_requests) { 406 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 408 protocol_handler_->SetDelayRequests(delay_requests); 409 } 410 411 void DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback( 412 const base::Closure& callback) { 413 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 414 415 protocol_handler_->SetRequestDestructionCallback(callback); 416 } 417 418 void DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes( 419 int expected_delayed_probe_count) { 420 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 421 422 CHECK(delaying_dns_probe_service_); 423 424 int actual_delayed_probe_count = 425 delaying_dns_probe_service_->delayed_probe_count(); 426 EXPECT_EQ(expected_delayed_probe_count, actual_delayed_probe_count); 427 428 delaying_dns_probe_service_->StartDelayedProbes(); 429 } 430 431 class DnsProbeBrowserTest : public InProcessBrowserTest { 432 public: 433 DnsProbeBrowserTest(); 434 virtual ~DnsProbeBrowserTest(); 435 436 virtual void SetUpOnMainThread() OVERRIDE; 437 virtual void CleanUpOnMainThread() OVERRIDE; 438 439 protected: 440 // Sets the browser object that other methods apply to, and that has the 441 // DnsProbeStatus messages of its currently active tab monitored. 442 void SetActiveBrowser(Browser* browser); 443 444 void SetLinkDoctorBroken(bool broken); 445 void SetLinkDoctorDelayRequests(bool delay_requests); 446 void WaitForDelayedRequestDestruction(); 447 void SetMockDnsClientRules(MockDnsClientRule::Result system_result, 448 MockDnsClientRule::Result public_result); 449 450 // These functions are often used to wait for two navigations because the Link 451 // Doctor loads two pages: a blank page, so the user stops seeing the previous 452 // page, and then either the Link Doctor page or a regular error page. Often 453 // need to wait for both to finish in a row. 454 void NavigateToDnsError(int num_navigations); 455 void NavigateToOtherError(int num_navigations); 456 457 void StartDelayedProbes(int expected_delayed_probe_count); 458 DnsProbeStatus WaitForSentStatus(); 459 int pending_status_count() const { return dns_probe_status_queue_.size(); } 460 461 std::string Title(); 462 bool PageContains(const std::string& expected); 463 464 private: 465 void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status); 466 467 DnsProbeBrowserTestIOThreadHelper* helper_; 468 469 // Browser that methods apply to. 470 Browser* active_browser_; 471 // Helper that current has its DnsProbeStatus messages monitored. 472 NetErrorTabHelper* monitored_tab_helper_; 473 474 bool awaiting_dns_probe_status_; 475 // Queue of statuses received but not yet consumed by WaitForSentStatus(). 476 std::list<DnsProbeStatus> dns_probe_status_queue_; 477 }; 478 479 DnsProbeBrowserTest::DnsProbeBrowserTest() 480 : helper_(new DnsProbeBrowserTestIOThreadHelper()), 481 active_browser_(NULL), 482 monitored_tab_helper_(NULL), 483 awaiting_dns_probe_status_(false) { 484 } 485 486 DnsProbeBrowserTest::~DnsProbeBrowserTest() { 487 // No tests should have any unconsumed probe statuses. 488 EXPECT_EQ(0, pending_status_count()); 489 } 490 491 void DnsProbeBrowserTest::SetUpOnMainThread() { 492 NetErrorTabHelper::set_state_for_testing( 493 NetErrorTabHelper::TESTING_DEFAULT); 494 495 browser()->profile()->GetPrefs()->SetBoolean( 496 prefs::kAlternateErrorPagesEnabled, true); 497 498 BrowserThread::PostTask( 499 BrowserThread::IO, FROM_HERE, 500 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread, 501 Unretained(helper_), 502 g_browser_process->io_thread())); 503 504 SetActiveBrowser(browser()); 505 } 506 507 void DnsProbeBrowserTest::CleanUpOnMainThread() { 508 BrowserThread::PostTask( 509 BrowserThread::IO, FROM_HERE, 510 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper, 511 Unretained(helper_))); 512 513 NetErrorTabHelper::set_state_for_testing( 514 NetErrorTabHelper::TESTING_DEFAULT); 515 } 516 517 void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) { 518 // If currently watching a NetErrorTabHelper, stop doing so before start 519 // watching another. 520 if (monitored_tab_helper_) { 521 monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing( 522 NetErrorTabHelper::DnsProbeStatusSnoopCallback()); 523 } 524 active_browser_ = browser; 525 monitored_tab_helper_ = NetErrorTabHelper::FromWebContents( 526 active_browser_->tab_strip_model()->GetActiveWebContents()); 527 monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing( 528 Bind(&DnsProbeBrowserTest::OnDnsProbeStatusSent, Unretained(this))); 529 } 530 531 void DnsProbeBrowserTest::SetLinkDoctorBroken(bool broken) { 532 int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK; 533 534 BrowserThread::PostTask( 535 BrowserThread::IO, FROM_HERE, 536 Bind(&DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError, 537 Unretained(helper_), 538 net_error)); 539 } 540 541 void DnsProbeBrowserTest::SetLinkDoctorDelayRequests(bool delay_requests) { 542 BrowserThread::PostTask( 543 BrowserThread::IO, FROM_HERE, 544 Bind(&DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorDelayRequests, 545 Unretained(helper_), 546 delay_requests)); 547 } 548 549 void DnsProbeBrowserTest::WaitForDelayedRequestDestruction() { 550 base::RunLoop run_loop; 551 BrowserThread::PostTask( 552 BrowserThread::IO, FROM_HERE, 553 Bind(&DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback, 554 Unretained(helper_), 555 base::Bind(&RunClosureOnUIThread, 556 run_loop.QuitClosure()))); 557 run_loop.Run(); 558 } 559 560 void DnsProbeBrowserTest::NavigateToDnsError(int num_navigations) { 561 NavigateToURLBlockUntilNavigationsComplete( 562 active_browser_, 563 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED), 564 num_navigations); 565 } 566 567 void DnsProbeBrowserTest::NavigateToOtherError(int num_navigations) { 568 NavigateToURLBlockUntilNavigationsComplete( 569 active_browser_, 570 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED), 571 num_navigations); 572 } 573 574 void DnsProbeBrowserTest::SetMockDnsClientRules( 575 MockDnsClientRule::Result system_result, 576 MockDnsClientRule::Result public_result) { 577 BrowserThread::PostTask( 578 BrowserThread::IO, FROM_HERE, 579 Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules, 580 Unretained(helper_), 581 system_result, 582 public_result)); 583 } 584 585 void DnsProbeBrowserTest::StartDelayedProbes( 586 int expected_delayed_probe_count) { 587 BrowserThread::PostTask( 588 BrowserThread::IO, FROM_HERE, 589 Bind(&DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes, 590 Unretained(helper_), 591 expected_delayed_probe_count)); 592 } 593 594 DnsProbeStatus DnsProbeBrowserTest::WaitForSentStatus() { 595 CHECK(!awaiting_dns_probe_status_); 596 while (dns_probe_status_queue_.empty()) { 597 awaiting_dns_probe_status_ = true; 598 MessageLoop::current()->Run(); 599 awaiting_dns_probe_status_ = false; 600 } 601 602 CHECK(!dns_probe_status_queue_.empty()); 603 DnsProbeStatus status = dns_probe_status_queue_.front(); 604 dns_probe_status_queue_.pop_front(); 605 return status; 606 } 607 608 // Check title by roundtripping to renderer, to make sure any probe results 609 // sent before this have been applied. 610 std::string DnsProbeBrowserTest::Title() { 611 std::string title; 612 613 WebContents* contents = 614 active_browser_->tab_strip_model()->GetActiveWebContents(); 615 616 bool rv = content::ExecuteScriptAndExtractString( 617 contents, 618 "domAutomationController.send(document.title);", 619 &title); 620 if (!rv) 621 return ""; 622 623 return title; 624 } 625 626 // Check text by roundtripping to renderer, to make sure any probe results 627 // sent before this have been applied. 628 bool DnsProbeBrowserTest::PageContains(const std::string& expected) { 629 std::string text_content; 630 631 bool rv = content::ExecuteScriptAndExtractString( 632 active_browser_->tab_strip_model()->GetActiveWebContents(), 633 "domAutomationController.send(document.body.textContent);", 634 &text_content); 635 if (!rv) 636 return false; 637 638 return text_content.find(expected) != std::string::npos; 639 } 640 641 void DnsProbeBrowserTest::OnDnsProbeStatusSent( 642 DnsProbeStatus dns_probe_status) { 643 dns_probe_status_queue_.push_back(dns_probe_status); 644 if (awaiting_dns_probe_status_) 645 MessageLoop::current()->Quit(); 646 } 647 648 // Make sure probes don't break non-DNS error pages when Link Doctor loads. 649 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithWorkingLinkDoctor) { 650 SetLinkDoctorBroken(false); 651 652 NavigateToOtherError(2); 653 EXPECT_EQ("Mock Link Doctor", Title()); 654 } 655 656 // Make sure probes don't break non-DNS error pages when Link Doctor doesn't 657 // load. 658 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithBrokenLinkDoctor) { 659 SetLinkDoctorBroken(true); 660 661 NavigateToOtherError(2); 662 EXPECT_TRUE(PageContains("CONNECTION_REFUSED")); 663 } 664 665 // Make sure probes don't break DNS error pages when Link doctor loads. 666 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 667 NxdomainProbeResultWithWorkingLinkDoctor) { 668 SetLinkDoctorBroken(false); 669 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK); 670 671 NavigateToDnsError(2); 672 EXPECT_EQ("Mock Link Doctor", Title()); 673 674 // One status for committing a blank page before the Link Doctor, and one for 675 // when the Link Doctor is committed. 676 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 677 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 678 EXPECT_EQ(0, pending_status_count()); 679 EXPECT_EQ("Mock Link Doctor", Title()); 680 681 StartDelayedProbes(1); 682 683 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 684 WaitForSentStatus()); 685 EXPECT_EQ(0, pending_status_count()); 686 EXPECT_EQ("Mock Link Doctor", Title()); 687 } 688 689 // Make sure probes don't break Link Doctor when probes complete before the 690 // Link Doctor loads. 691 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 692 NxdomainProbeResultWithWorkingSlowLinkDoctor) { 693 SetLinkDoctorBroken(false); 694 SetLinkDoctorDelayRequests(true); 695 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK); 696 697 NavigateToDnsError(1); 698 // A blank page should be displayed while the Link Doctor page loads. 699 EXPECT_EQ("", Title()); 700 701 // A single probe should be triggered by the error page load, and it should 702 // be ignored. 703 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 704 EXPECT_EQ(0, pending_status_count()); 705 EXPECT_EQ("", Title()); 706 707 StartDelayedProbes(1); 708 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 709 WaitForSentStatus()); 710 EXPECT_EQ(0, pending_status_count()); 711 EXPECT_EQ("", Title()); 712 713 content::TestNavigationObserver observer( 714 browser()->tab_strip_model()->GetActiveWebContents(), 1); 715 // The Link Doctor page finishes loading. 716 SetLinkDoctorDelayRequests(false); 717 // Wait for it to commit. 718 observer.Wait(); 719 EXPECT_EQ("Mock Link Doctor", Title()); 720 721 // Committing the Link Doctor page should trigger sending the probe result 722 // again. 723 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 724 WaitForSentStatus()); 725 EXPECT_EQ("Mock Link Doctor", Title()); 726 } 727 728 // Make sure probes update DNS error page properly when they're supposed to. 729 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 730 NoInternetProbeResultWithBrokenLinkDoctor) { 731 SetLinkDoctorBroken(true); 732 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, 733 MockDnsClientRule::TIMEOUT); 734 735 NavigateToDnsError(2); 736 737 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 738 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 739 740 // PageContains runs the RunLoop, so make sure nothing hairy happens. 741 EXPECT_EQ(0, pending_status_count()); 742 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED")); 743 EXPECT_EQ(0, pending_status_count()); 744 745 StartDelayedProbes(1); 746 747 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 748 WaitForSentStatus()); 749 750 // PageContains runs the RunLoop, so make sure nothing hairy happens. 751 EXPECT_EQ(0, pending_status_count()); 752 EXPECT_TRUE(PageContains("DNS_PROBE_FINISHED_NO_INTERNET")); 753 } 754 755 // Make sure probes don't break Link Doctor when probes complete before the 756 // Link Doctor request returns an error. 757 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 758 NoInternetProbeResultWithSlowBrokenLinkDoctor) { 759 SetLinkDoctorBroken(true); 760 SetLinkDoctorDelayRequests(true); 761 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, 762 MockDnsClientRule::TIMEOUT); 763 764 NavigateToDnsError(1); 765 // A blank page should be displayed while the Link Doctor page loads. 766 EXPECT_EQ("", Title()); 767 768 // A single probe should be triggered by the error page load, and it should 769 // be ignored. 770 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 771 EXPECT_EQ(0, pending_status_count()); 772 EXPECT_EQ("", Title()); 773 774 StartDelayedProbes(1); 775 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 776 WaitForSentStatus()); 777 EXPECT_EQ("", Title()); 778 EXPECT_EQ(0, pending_status_count()); 779 780 content::TestNavigationObserver observer( 781 browser()->tab_strip_model()->GetActiveWebContents(), 1); 782 // The Link Doctor request fails. 783 SetLinkDoctorDelayRequests(false); 784 // Wait for the DNS error page to load instead. 785 observer.Wait(); 786 // The page committing should result in sending the probe results again. 787 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 788 WaitForSentStatus()); 789 790 EXPECT_EQ(0, pending_status_count()); 791 EXPECT_TRUE(PageContains("DNS_PROBE_FINISHED_NO_INTERNET")); 792 } 793 794 // Double-check to make sure sync failures don't explode. 795 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, SyncFailureWithBrokenLinkDoctor) { 796 SetLinkDoctorBroken(true); 797 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 798 799 NavigateToDnsError(2); 800 801 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 802 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 803 804 // PageContains runs the RunLoop, so make sure nothing hairy happens. 805 EXPECT_EQ(0, pending_status_count()); 806 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED")); 807 EXPECT_EQ(0, pending_status_count()); 808 809 StartDelayedProbes(1); 810 811 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 812 WaitForSentStatus()); 813 814 // PageContains runs the RunLoop, so make sure nothing hairy happens. 815 EXPECT_EQ(0, pending_status_count()); 816 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED")); 817 EXPECT_EQ(0, pending_status_count()); 818 } 819 820 // Test that pressing the stop button cancels loading the Link Doctor page. 821 // TODO(mmenke): Add a test for the cross process navigation case. 822 // TODO(mmenke): This test could flakily pass due to the timeout on downloading 823 // the Link Doctor page. Disable that timeout for browser tests. 824 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, LinkDoctorLoadStopped) { 825 SetLinkDoctorDelayRequests(true); 826 SetLinkDoctorBroken(true); 827 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 828 829 NavigateToDnsError(1); 830 831 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 832 StartDelayedProbes(1); 833 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 834 WaitForSentStatus()); 835 836 EXPECT_EQ("", Title()); 837 EXPECT_EQ(0, pending_status_count()); 838 839 chrome::Stop(browser()); 840 WaitForDelayedRequestDestruction(); 841 842 // End up displaying a blank page. 843 EXPECT_EQ("", Title()); 844 } 845 846 // Test that pressing the stop button cancels the load of the Link Doctor error 847 // page, and receiving a probe result afterwards does not swap in a DNS error 848 // page. 849 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, LinkDoctorLoadStoppedSlowProbe) { 850 SetLinkDoctorDelayRequests(true); 851 SetLinkDoctorBroken(true); 852 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 853 854 NavigateToDnsError(1); 855 856 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 857 858 EXPECT_EQ("", Title()); 859 EXPECT_EQ(0, pending_status_count()); 860 861 chrome::Stop(browser()); 862 WaitForDelayedRequestDestruction(); 863 864 EXPECT_EQ("", Title()); 865 EXPECT_EQ(0, pending_status_count()); 866 867 StartDelayedProbes(1); 868 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 869 WaitForSentStatus()); 870 871 EXPECT_EQ("", Title()); 872 } 873 874 // Make sure probes don't run for subframe DNS errors. 875 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) { 876 SetLinkDoctorBroken(false); 877 878 const FilePath::CharType kIframeDnsErrorHtmlName[] = 879 FILE_PATH_LITERAL("iframe_dns_error.html"); 880 881 NavigateToURL( 882 browser(), 883 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName))); 884 885 // By the time NavigateToURL returns, the browser will have seen the failed 886 // provisional load. If a probe was started (or considered but not run), 887 // then the NetErrorTabHelper would have sent a NetErrorInfo message. Thus, 888 // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't) 889 // start a probe for this DNS error. 890 EXPECT_EQ(0, pending_status_count()); 891 } 892 893 // Make sure browser sends NOT_RUN properly when probes are disabled. 894 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) { 895 // Disable probes (And Link Doctor). 896 browser()->profile()->GetPrefs()->SetBoolean( 897 prefs::kAlternateErrorPagesEnabled, false); 898 899 SetLinkDoctorBroken(true); 900 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 901 902 NavigateToDnsError(1); 903 904 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, WaitForSentStatus()); 905 906 // PageContains runs the RunLoop, so make sure nothing hairy happens. 907 EXPECT_EQ(0, pending_status_count()); 908 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED")); 909 } 910 911 // Test the case that Link Doctor is disabled, but DNS probes are enabled. This 912 // is the case with Chromium builds. 913 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, LinkDoctorDisabled) { 914 // Disable Link Doctor. 915 browser()->profile()->GetPrefs()->SetBoolean( 916 prefs::kAlternateErrorPagesEnabled, false); 917 // Requests to the Link Doctor should work if any are made, so the test fails 918 // if that happens unexpectedly. 919 SetLinkDoctorBroken(false); 920 // Normally disabling the LinkDoctor disables DNS probes, so force DNS probes 921 // to be enabled. 922 NetErrorTabHelper::set_state_for_testing( 923 NetErrorTabHelper::TESTING_FORCE_ENABLED); 924 925 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 926 927 // Just one commit and one sent status, since the Link Doctor is disabled. 928 NavigateToDnsError(1); 929 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 930 931 // PageContains runs the RunLoop, so make sure nothing hairy happens. 932 EXPECT_EQ(0, pending_status_count()); 933 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED")); 934 EXPECT_EQ(0, pending_status_count()); 935 936 StartDelayedProbes(1); 937 938 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 939 WaitForSentStatus()); 940 EXPECT_EQ(0, pending_status_count()); 941 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED")); 942 } 943 944 // Test incognito mode. Link Doctor should be disabled, but DNS probes are 945 // still enabled. 946 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, Incognito) { 947 // Requests to the Link Doctor should work if any are made, so the test will 948 // fail if one is requested unexpectedly. 949 SetLinkDoctorBroken(false); 950 951 Browser* incognito = CreateIncognitoBrowser(); 952 SetActiveBrowser(incognito); 953 954 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 955 956 // Just one commit and one sent status, since the Link Doctor is disabled. 957 NavigateToDnsError(1); 958 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 959 960 // PageContains runs the RunLoop, so make sure nothing hairy happens. 961 EXPECT_EQ(0, pending_status_count()); 962 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED")); 963 EXPECT_EQ(0, pending_status_count()); 964 965 StartDelayedProbes(1); 966 967 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 968 WaitForSentStatus()); 969 EXPECT_EQ(0, pending_status_count()); 970 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED")); 971 } 972 973 } // namespace 974 975 } // namespace chrome_browser_net 976