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/io_thread.h" 16 #include "chrome/browser/net/dns_probe_test_util.h" 17 #include "chrome/browser/net/net_error_tab_helper.h" 18 #include "chrome/browser/net/url_request_mock_util.h" 19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/ui/browser.h" 21 #include "chrome/browser/ui/browser_commands.h" 22 #include "chrome/browser/ui/tabs/tab_strip_model.h" 23 #include "chrome/common/chrome_paths.h" 24 #include "chrome/common/net/net_error_info.h" 25 #include "chrome/common/pref_names.h" 26 #include "chrome/test/base/in_process_browser_test.h" 27 #include "chrome/test/base/ui_test_utils.h" 28 #include "components/google/core/browser/google_util.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 "net/base/net_errors.h" 34 #include "net/dns/dns_test_util.h" 35 #include "net/test/url_request/url_request_failed_job.h" 36 #include "net/test/url_request/url_request_mock_http_job.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_job.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 net::URLRequestFailedJob; 51 using net::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::URLRequestInterceptor; 59 using net::URLRequestJob; 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.json"); 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( 185 request, 186 network_delegate, 187 file_path, 188 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 189 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), 190 should_delay_(should_delay), 191 start_delayed_(false), 192 destruction_callback_(destruction_callback) {} 193 194 virtual void Start() OVERRIDE { 195 if (should_delay_) { 196 DCHECK(!start_delayed_); 197 start_delayed_ = true; 198 return; 199 } 200 URLRequestMockHTTPJob::Start(); 201 } 202 203 virtual void Resume() OVERRIDE { 204 DCHECK(should_delay_); 205 should_delay_ = false; 206 if (start_delayed_) { 207 start_delayed_ = false; 208 Start(); 209 } 210 } 211 212 private: 213 virtual ~DelayableURLRequestMockHTTPJob() { 214 if (should_delay_) 215 destruction_callback_.Run(this); 216 } 217 218 bool should_delay_; 219 bool start_delayed_; 220 const DestructionCallback destruction_callback_; 221 }; 222 223 // Interceptor for navigation correction requests. Can cause requests to 224 // fail with an error, and/or delay a request until a test allows to continue. 225 // Also can run a callback when a delayed request is cancelled. 226 class BreakableCorrectionInterceptor : public URLRequestInterceptor { 227 public: 228 explicit BreakableCorrectionInterceptor( 229 const FilePath& mock_corrections_file_path) 230 : mock_corrections_file_path_(mock_corrections_file_path), 231 net_error_(net::OK), 232 delay_requests_(false), 233 on_request_destroyed_callback_( 234 base::Bind(&BreakableCorrectionInterceptor::OnRequestDestroyed, 235 base::Unretained(this))) { 236 } 237 238 virtual ~BreakableCorrectionInterceptor() { 239 // All delayed requests should have been resumed or cancelled by this point. 240 EXPECT_TRUE(delayed_requests_.empty()); 241 } 242 243 virtual URLRequestJob* MaybeInterceptRequest( 244 URLRequest* request, 245 NetworkDelegate* network_delegate) const OVERRIDE { 246 if (net_error_ != net::OK) { 247 DelayableURLRequestFailedJob* job = 248 new DelayableURLRequestFailedJob( 249 request, network_delegate, net_error_, delay_requests_, 250 on_request_destroyed_callback_); 251 if (delay_requests_) 252 delayed_requests_.insert(job); 253 return job; 254 } else { 255 DelayableURLRequestMockHTTPJob* job = 256 new DelayableURLRequestMockHTTPJob( 257 request, network_delegate, mock_corrections_file_path_, 258 delay_requests_, on_request_destroyed_callback_); 259 if (delay_requests_) 260 delayed_requests_.insert(job); 261 return job; 262 } 263 } 264 265 void set_net_error(int net_error) { net_error_ = net_error; } 266 267 void SetDelayRequests(bool delay_requests) { 268 delay_requests_ = delay_requests; 269 270 // Resume all delayed requests if no longer delaying requests. 271 if (!delay_requests) { 272 while (!delayed_requests_.empty()) { 273 DelayableRequest* request = *delayed_requests_.begin(); 274 delayed_requests_.erase(request); 275 request->Resume(); 276 } 277 } 278 } 279 280 // Runs |callback| once all delayed requests have been destroyed. Does not 281 // wait for delayed requests that have been resumed. 282 void SetRequestDestructionCallback(const base::Closure& callback) { 283 ASSERT_TRUE(delayed_request_destruction_callback_.is_null()); 284 if (delayed_requests_.empty()) { 285 callback.Run(); 286 return; 287 } 288 delayed_request_destruction_callback_ = callback; 289 } 290 291 void OnRequestDestroyed(DelayableRequest* request) { 292 ASSERT_EQ(1u, delayed_requests_.count(request)); 293 delayed_requests_.erase(request); 294 if (delayed_requests_.empty() && 295 !delayed_request_destruction_callback_.is_null()) { 296 delayed_request_destruction_callback_.Run(); 297 delayed_request_destruction_callback_.Reset(); 298 } 299 } 300 301 private: 302 const FilePath mock_corrections_file_path_; 303 int net_error_; 304 bool delay_requests_; 305 306 // Called when a request is destroyed. Memeber variable because 307 // MaybeCreateJob is "const", so calling base::Bind in that function does 308 // not work well. 309 const DelayableRequest::DestructionCallback on_request_destroyed_callback_; 310 311 // Mutable is needed because MaybeCreateJob is const. 312 mutable std::set<DelayableRequest*> delayed_requests_; 313 314 base::Closure delayed_request_destruction_callback_; 315 }; 316 317 class DnsProbeBrowserTestIOThreadHelper { 318 public: 319 DnsProbeBrowserTestIOThreadHelper(); 320 321 void SetUpOnIOThread(IOThread* io_thread); 322 void CleanUpOnIOThreadAndDeleteHelper(); 323 324 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result, 325 MockDnsClientRule::Result public_good_result); 326 void SetCorrectionServiceNetError(int net_error); 327 void SetCorrectionServiceDelayRequests(bool delay_requests); 328 void SetRequestDestructionCallback(const base::Closure& callback); 329 void StartDelayedProbes(int expected_delayed_probe_count); 330 331 private: 332 IOThread* io_thread_; 333 DnsProbeService* original_dns_probe_service_; 334 DelayingDnsProbeService* delaying_dns_probe_service_; 335 BreakableCorrectionInterceptor* interceptor_; 336 FilePath mock_corrections_file_path_; 337 }; 338 339 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper() 340 : io_thread_(NULL), 341 original_dns_probe_service_(NULL), 342 delaying_dns_probe_service_(NULL), 343 interceptor_(NULL), 344 mock_corrections_file_path_(GetMockLinkDoctorFilePath()) {} 345 346 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) { 347 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 348 CHECK(io_thread); 349 CHECK(!io_thread_); 350 CHECK(!original_dns_probe_service_); 351 CHECK(!delaying_dns_probe_service_); 352 CHECK(!interceptor_); 353 354 io_thread_ = io_thread; 355 356 delaying_dns_probe_service_ = new DelayingDnsProbeService(); 357 358 IOThread::Globals* globals = io_thread_->globals(); 359 original_dns_probe_service_ = globals->dns_probe_service.release(); 360 globals->dns_probe_service.reset(delaying_dns_probe_service_); 361 362 URLRequestFailedJob::AddUrlHandler(); 363 364 interceptor_ = 365 new BreakableCorrectionInterceptor(mock_corrections_file_path_); 366 URLRequestFilter::GetInstance()->AddUrlInterceptor( 367 LinkDoctorBaseURL(), scoped_ptr<URLRequestInterceptor>(interceptor_)); 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::SetCorrectionServiceNetError( 398 int net_error) { 399 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 400 401 interceptor_->set_net_error(net_error); 402 } 403 404 void DnsProbeBrowserTestIOThreadHelper::SetCorrectionServiceDelayRequests( 405 bool delay_requests) { 406 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 408 interceptor_->SetDelayRequests(delay_requests); 409 } 410 411 void DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback( 412 const base::Closure& callback) { 413 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 414 415 interceptor_->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 TearDownOnMainThread() 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 SetCorrectionServiceBroken(bool broken); 445 void SetCorrectionServiceDelayRequests(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 two 451 // pages are loaded when navigation corrections are enabled: a blank page, so 452 // the user stops seeing the previous page, and then the error page, either 453 // with navigation corrections or without them (If the request failed). 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 // Checks that the local error page is being displayed, without navigation 465 // corrections, and with the specified status text. The status text should be 466 // either a network error or DNS probe status. 467 void ExpectDisplayingLocalErrorPage(const std::string& status_text); 468 469 // Checks that an error page with mock navigation corrections is being 470 // displayed, with the specified status text. The status text should be either 471 // a network error or DNS probe status. 472 void ExpectDisplayingCorrections(const std::string& status_text); 473 474 private: 475 void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status); 476 477 DnsProbeBrowserTestIOThreadHelper* helper_; 478 479 // Browser that methods apply to. 480 Browser* active_browser_; 481 // Helper that current has its DnsProbeStatus messages monitored. 482 NetErrorTabHelper* monitored_tab_helper_; 483 484 bool awaiting_dns_probe_status_; 485 // Queue of statuses received but not yet consumed by WaitForSentStatus(). 486 std::list<DnsProbeStatus> dns_probe_status_queue_; 487 }; 488 489 DnsProbeBrowserTest::DnsProbeBrowserTest() 490 : helper_(new DnsProbeBrowserTestIOThreadHelper()), 491 active_browser_(NULL), 492 monitored_tab_helper_(NULL), 493 awaiting_dns_probe_status_(false) { 494 } 495 496 DnsProbeBrowserTest::~DnsProbeBrowserTest() { 497 // No tests should have any unconsumed probe statuses. 498 EXPECT_EQ(0, pending_status_count()); 499 } 500 501 void DnsProbeBrowserTest::SetUpOnMainThread() { 502 NetErrorTabHelper::set_state_for_testing( 503 NetErrorTabHelper::TESTING_DEFAULT); 504 505 browser()->profile()->GetPrefs()->SetBoolean( 506 prefs::kAlternateErrorPagesEnabled, true); 507 508 BrowserThread::PostTask( 509 BrowserThread::IO, FROM_HERE, 510 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread, 511 Unretained(helper_), 512 g_browser_process->io_thread())); 513 514 SetActiveBrowser(browser()); 515 } 516 517 void DnsProbeBrowserTest::TearDownOnMainThread() { 518 BrowserThread::PostTask( 519 BrowserThread::IO, FROM_HERE, 520 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper, 521 Unretained(helper_))); 522 523 NetErrorTabHelper::set_state_for_testing( 524 NetErrorTabHelper::TESTING_DEFAULT); 525 } 526 527 void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) { 528 // If currently watching a NetErrorTabHelper, stop doing so before start 529 // watching another. 530 if (monitored_tab_helper_) { 531 monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing( 532 NetErrorTabHelper::DnsProbeStatusSnoopCallback()); 533 } 534 active_browser_ = browser; 535 monitored_tab_helper_ = NetErrorTabHelper::FromWebContents( 536 active_browser_->tab_strip_model()->GetActiveWebContents()); 537 monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing( 538 Bind(&DnsProbeBrowserTest::OnDnsProbeStatusSent, Unretained(this))); 539 } 540 541 void DnsProbeBrowserTest::SetCorrectionServiceBroken(bool broken) { 542 int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK; 543 544 BrowserThread::PostTask( 545 BrowserThread::IO, FROM_HERE, 546 Bind(&DnsProbeBrowserTestIOThreadHelper::SetCorrectionServiceNetError, 547 Unretained(helper_), 548 net_error)); 549 } 550 551 void DnsProbeBrowserTest::SetCorrectionServiceDelayRequests( 552 bool delay_requests) { 553 BrowserThread::PostTask( 554 BrowserThread::IO, FROM_HERE, 555 Bind(&DnsProbeBrowserTestIOThreadHelper:: 556 SetCorrectionServiceDelayRequests, 557 Unretained(helper_), 558 delay_requests)); 559 } 560 561 void DnsProbeBrowserTest::WaitForDelayedRequestDestruction() { 562 base::RunLoop run_loop; 563 BrowserThread::PostTask( 564 BrowserThread::IO, FROM_HERE, 565 Bind(&DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback, 566 Unretained(helper_), 567 base::Bind(&RunClosureOnUIThread, 568 run_loop.QuitClosure()))); 569 run_loop.Run(); 570 } 571 572 void DnsProbeBrowserTest::NavigateToDnsError(int num_navigations) { 573 NavigateToURLBlockUntilNavigationsComplete( 574 active_browser_, 575 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED), 576 num_navigations); 577 } 578 579 void DnsProbeBrowserTest::NavigateToOtherError(int num_navigations) { 580 NavigateToURLBlockUntilNavigationsComplete( 581 active_browser_, 582 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED), 583 num_navigations); 584 } 585 586 void DnsProbeBrowserTest::SetMockDnsClientRules( 587 MockDnsClientRule::Result system_result, 588 MockDnsClientRule::Result public_result) { 589 BrowserThread::PostTask( 590 BrowserThread::IO, FROM_HERE, 591 Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules, 592 Unretained(helper_), 593 system_result, 594 public_result)); 595 } 596 597 void DnsProbeBrowserTest::StartDelayedProbes( 598 int expected_delayed_probe_count) { 599 BrowserThread::PostTask( 600 BrowserThread::IO, FROM_HERE, 601 Bind(&DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes, 602 Unretained(helper_), 603 expected_delayed_probe_count)); 604 } 605 606 DnsProbeStatus DnsProbeBrowserTest::WaitForSentStatus() { 607 CHECK(!awaiting_dns_probe_status_); 608 while (dns_probe_status_queue_.empty()) { 609 awaiting_dns_probe_status_ = true; 610 MessageLoop::current()->Run(); 611 awaiting_dns_probe_status_ = false; 612 } 613 614 CHECK(!dns_probe_status_queue_.empty()); 615 DnsProbeStatus status = dns_probe_status_queue_.front(); 616 dns_probe_status_queue_.pop_front(); 617 return status; 618 } 619 620 // Check title by roundtripping to renderer, to make sure any probe results 621 // sent before this have been applied. 622 std::string DnsProbeBrowserTest::Title() { 623 std::string title; 624 625 WebContents* contents = 626 active_browser_->tab_strip_model()->GetActiveWebContents(); 627 628 bool rv = content::ExecuteScriptAndExtractString( 629 contents, 630 "domAutomationController.send(document.title);", 631 &title); 632 if (!rv) 633 return ""; 634 635 return title; 636 } 637 638 // Check text by roundtripping to renderer, to make sure any probe results 639 // sent before this have been applied. 640 bool DnsProbeBrowserTest::PageContains(const std::string& expected) { 641 std::string text_content; 642 643 bool rv = content::ExecuteScriptAndExtractString( 644 active_browser_->tab_strip_model()->GetActiveWebContents(), 645 "domAutomationController.send(document.body.textContent);", 646 &text_content); 647 if (!rv) 648 return false; 649 650 return text_content.find(expected) != std::string::npos; 651 } 652 653 void DnsProbeBrowserTest::ExpectDisplayingLocalErrorPage( 654 const std::string& status_text) { 655 EXPECT_FALSE(PageContains("http://correction1/")); 656 EXPECT_FALSE(PageContains("http://correction2/")); 657 EXPECT_TRUE(PageContains(status_text)); 658 } 659 660 void DnsProbeBrowserTest::ExpectDisplayingCorrections( 661 const std::string& status_text) { 662 EXPECT_TRUE(PageContains("http://correction1/")); 663 EXPECT_TRUE(PageContains("http://correction2/")); 664 EXPECT_TRUE(PageContains(status_text)); 665 } 666 667 void DnsProbeBrowserTest::OnDnsProbeStatusSent( 668 DnsProbeStatus dns_probe_status) { 669 dns_probe_status_queue_.push_back(dns_probe_status); 670 if (awaiting_dns_probe_status_) 671 MessageLoop::current()->Quit(); 672 } 673 674 // Make sure probes don't break non-DNS error pages when corrections load. 675 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithCorrectionsSuccess) { 676 SetCorrectionServiceBroken(false); 677 678 NavigateToOtherError(2); 679 ExpectDisplayingCorrections("ERR_CONNECTION_REFUSED"); 680 } 681 682 // Make sure probes don't break non-DNS error pages when corrections failed to 683 // load. 684 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithCorrectionsFailure) { 685 SetCorrectionServiceBroken(true); 686 687 NavigateToOtherError(2); 688 ExpectDisplayingLocalErrorPage("ERR_CONNECTION_REFUSED"); 689 } 690 691 // Make sure probes don't break DNS error pages when corrections load. 692 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 693 NxdomainProbeResultWithWorkingCorrections) { 694 SetCorrectionServiceBroken(false); 695 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK); 696 697 NavigateToDnsError(2); 698 ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED"); 699 700 // One status for committing a blank page before the corrections, and one for 701 // when the error page with corrections is committed. 702 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 703 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 704 EXPECT_EQ(0, pending_status_count()); 705 ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED"); 706 707 StartDelayedProbes(1); 708 709 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 710 WaitForSentStatus()); 711 EXPECT_EQ(0, pending_status_count()); 712 ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED"); 713 } 714 715 // Make sure probes don't break corrections when probes complete before the 716 // corrections load. 717 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 718 NxdomainProbeResultWithWorkingSlowCorrections) { 719 SetCorrectionServiceBroken(false); 720 SetCorrectionServiceDelayRequests(true); 721 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK); 722 723 NavigateToDnsError(1); 724 // A blank page should be displayed while the corrections are loaded. 725 EXPECT_EQ("", Title()); 726 727 // A single probe should be triggered by the error page load, and it should 728 // be ignored. 729 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 730 EXPECT_EQ(0, pending_status_count()); 731 EXPECT_EQ("", Title()); 732 733 StartDelayedProbes(1); 734 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 735 WaitForSentStatus()); 736 EXPECT_EQ(0, pending_status_count()); 737 EXPECT_EQ("", Title()); 738 739 content::TestNavigationObserver observer( 740 browser()->tab_strip_model()->GetActiveWebContents(), 1); 741 // The corrections finish loading. 742 SetCorrectionServiceDelayRequests(false); 743 // Wait for it to commit. 744 observer.Wait(); 745 ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED"); 746 747 // Committing the corections page should trigger sending the probe result 748 // again. 749 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN, 750 WaitForSentStatus()); 751 ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED"); 752 } 753 754 // Make sure probes update DNS error page properly when they're supposed to. 755 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 756 NoInternetProbeResultWithBrokenCorrections) { 757 SetCorrectionServiceBroken(true); 758 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, 759 MockDnsClientRule::TIMEOUT); 760 761 NavigateToDnsError(2); 762 763 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 764 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 765 766 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 767 EXPECT_EQ(0, pending_status_count()); 768 ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED"); 769 EXPECT_EQ(0, pending_status_count()); 770 771 StartDelayedProbes(1); 772 773 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 774 WaitForSentStatus()); 775 776 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 777 EXPECT_EQ(0, pending_status_count()); 778 ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_NO_INTERNET"); 779 } 780 781 // Make sure probes don't break corrections when probes complete before the 782 // corrections request returns an error. 783 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, 784 NoInternetProbeResultWithSlowBrokenCorrections) { 785 SetCorrectionServiceBroken(true); 786 SetCorrectionServiceDelayRequests(true); 787 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, 788 MockDnsClientRule::TIMEOUT); 789 790 NavigateToDnsError(1); 791 // A blank page should be displayed while the corrections load. 792 EXPECT_EQ("", Title()); 793 794 // A single probe should be triggered by the error page load, and it should 795 // be ignored. 796 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 797 EXPECT_EQ(0, pending_status_count()); 798 EXPECT_EQ("", Title()); 799 800 StartDelayedProbes(1); 801 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 802 WaitForSentStatus()); 803 EXPECT_EQ("", Title()); 804 EXPECT_EQ(0, pending_status_count()); 805 806 content::TestNavigationObserver observer( 807 browser()->tab_strip_model()->GetActiveWebContents(), 1); 808 // The corrections request fails. 809 SetCorrectionServiceDelayRequests(false); 810 // Wait for the DNS error page to load instead. 811 observer.Wait(); 812 // The page committing should result in sending the probe results again. 813 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 814 WaitForSentStatus()); 815 816 EXPECT_EQ(0, pending_status_count()); 817 ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_NO_INTERNET"); 818 } 819 820 // Double-check to make sure sync failures don't explode. 821 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, SyncFailureWithBrokenCorrections) { 822 SetCorrectionServiceBroken(true); 823 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 824 825 NavigateToDnsError(2); 826 827 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 828 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 829 830 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 831 EXPECT_EQ(0, pending_status_count()); 832 ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED"); 833 EXPECT_EQ(0, pending_status_count()); 834 835 StartDelayedProbes(1); 836 837 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 838 WaitForSentStatus()); 839 840 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 841 EXPECT_EQ(0, pending_status_count()); 842 ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED"); 843 EXPECT_EQ(0, pending_status_count()); 844 } 845 846 // Test that pressing the stop button cancels loading corrections. 847 // TODO(mmenke): Add a test for the cross process navigation case. 848 // TODO(mmenke): This test could flakily pass due to the timeout on downloading 849 // the corrections. Disable that timeout for browser tests. 850 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsLoadStopped) { 851 SetCorrectionServiceDelayRequests(true); 852 SetCorrectionServiceBroken(true); 853 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 854 855 NavigateToDnsError(1); 856 857 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 858 StartDelayedProbes(1); 859 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 860 WaitForSentStatus()); 861 862 EXPECT_EQ("", Title()); 863 EXPECT_EQ(0, pending_status_count()); 864 865 chrome::Stop(browser()); 866 WaitForDelayedRequestDestruction(); 867 868 // End up displaying a blank page. 869 EXPECT_EQ("", Title()); 870 } 871 872 // Test that pressing the stop button cancels the load of corrections, and 873 // receiving a probe result afterwards does not swap in a DNS error page. 874 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsLoadStoppedSlowProbe) { 875 SetCorrectionServiceDelayRequests(true); 876 SetCorrectionServiceBroken(true); 877 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 878 879 NavigateToDnsError(1); 880 881 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 882 883 EXPECT_EQ("", Title()); 884 EXPECT_EQ(0, pending_status_count()); 885 886 chrome::Stop(browser()); 887 WaitForDelayedRequestDestruction(); 888 889 EXPECT_EQ("", Title()); 890 EXPECT_EQ(0, pending_status_count()); 891 892 StartDelayedProbes(1); 893 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET, 894 WaitForSentStatus()); 895 896 EXPECT_EQ("", Title()); 897 } 898 899 // Make sure probes don't run for subframe DNS errors. 900 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) { 901 SetCorrectionServiceBroken(false); 902 903 const FilePath::CharType kIframeDnsErrorHtmlName[] = 904 FILE_PATH_LITERAL("iframe_dns_error.html"); 905 906 NavigateToURL( 907 browser(), 908 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName))); 909 910 // By the time NavigateToURL returns, the browser will have seen the failed 911 // provisional load. If a probe was started (or considered but not run), 912 // then the NetErrorTabHelper would have sent a NetErrorInfo message. Thus, 913 // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't) 914 // start a probe for this DNS error. 915 EXPECT_EQ(0, pending_status_count()); 916 } 917 918 // Make sure browser sends NOT_RUN properly when probes are disabled. 919 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) { 920 // Disable probes (And corrections). 921 browser()->profile()->GetPrefs()->SetBoolean( 922 prefs::kAlternateErrorPagesEnabled, false); 923 924 SetCorrectionServiceBroken(true); 925 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT); 926 927 NavigateToDnsError(1); 928 929 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, WaitForSentStatus()); 930 931 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 932 EXPECT_EQ(0, pending_status_count()); 933 ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED"); 934 } 935 936 // Test the case that corrections are disabled, but DNS probes are enabled. 937 // This is the case with Chromium builds. 938 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsDisabled) { 939 // Disable corrections. 940 browser()->profile()->GetPrefs()->SetBoolean( 941 prefs::kAlternateErrorPagesEnabled, false); 942 // Requests to the correction service should work if any are made, so the test 943 // fails if that happens unexpectedly. 944 SetCorrectionServiceBroken(false); 945 // Normally disabling corrections disables DNS probes, so force DNS probes 946 // to be enabled. 947 NetErrorTabHelper::set_state_for_testing( 948 NetErrorTabHelper::TESTING_FORCE_ENABLED); 949 950 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 951 952 // Just one commit and one sent status, since corrections are disabled. 953 NavigateToDnsError(1); 954 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 955 956 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 957 EXPECT_EQ(0, pending_status_count()); 958 ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED"); 959 EXPECT_EQ(0, pending_status_count()); 960 961 StartDelayedProbes(1); 962 963 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 964 WaitForSentStatus()); 965 EXPECT_EQ(0, pending_status_count()); 966 ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED"); 967 } 968 969 // Test incognito mode. Corrections should be disabled, but DNS probes are 970 // still enabled. 971 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, Incognito) { 972 // Requests to the correction service should work if any are made, so the test 973 // will fail if one is requested unexpectedly. 974 SetCorrectionServiceBroken(false); 975 976 Browser* incognito = CreateIncognitoBrowser(); 977 SetActiveBrowser(incognito); 978 979 SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL); 980 981 // Just one commit and one sent status, since the corrections are disabled. 982 NavigateToDnsError(1); 983 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus()); 984 985 // Checking the page runs the RunLoop, so make sure nothing hairy happens. 986 EXPECT_EQ(0, pending_status_count()); 987 ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED"); 988 EXPECT_EQ(0, pending_status_count()); 989 990 StartDelayedProbes(1); 991 992 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE, 993 WaitForSentStatus()); 994 EXPECT_EQ(0, pending_status_count()); 995 ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED"); 996 } 997 998 } // namespace 999 1000 } // namespace chrome_browser_net 1001