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 41using base::Bind; 42using base::Callback; 43using base::Closure; 44using base::ConstRef; 45using base::FilePath; 46using base::MessageLoop; 47using base::Unretained; 48using chrome_common_net::DnsProbeStatus; 49using content::BrowserThread; 50using content::URLRequestFailedJob; 51using content::URLRequestMockHTTPJob; 52using content::WebContents; 53using google_util::LinkDoctorBaseURL; 54using net::MockDnsClientRule; 55using net::NetworkDelegate; 56using net::URLRequest; 57using net::URLRequestFilter; 58using net::URLRequestJob; 59using net::URLRequestJobFactory; 60using ui_test_utils::NavigateToURL; 61using ui_test_utils::NavigateToURLBlockUntilNavigationsComplete; 62 63namespace chrome_browser_net { 64 65namespace { 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. 70void 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. 77class 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 110FilePath 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. 119class 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 131class 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 175class 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. 221class 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 313class 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 335DnsProbeBrowserTestIOThreadHelper::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 342void 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 370void 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 385void 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 397void 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 404void DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorDelayRequests( 405 bool delay_requests) { 406 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 408 protocol_handler_->SetDelayRequests(delay_requests); 409} 410 411void DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback( 412 const base::Closure& callback) { 413 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 414 415 protocol_handler_->SetRequestDestructionCallback(callback); 416} 417 418void 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 431class 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 479DnsProbeBrowserTest::DnsProbeBrowserTest() 480 : helper_(new DnsProbeBrowserTestIOThreadHelper()), 481 active_browser_(NULL), 482 monitored_tab_helper_(NULL), 483 awaiting_dns_probe_status_(false) { 484} 485 486DnsProbeBrowserTest::~DnsProbeBrowserTest() { 487 // No tests should have any unconsumed probe statuses. 488 EXPECT_EQ(0, pending_status_count()); 489} 490 491void 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 507void 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 517void 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 531void 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 541void 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 549void 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 560void DnsProbeBrowserTest::NavigateToDnsError(int num_navigations) { 561 NavigateToURLBlockUntilNavigationsComplete( 562 active_browser_, 563 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED), 564 num_navigations); 565} 566 567void DnsProbeBrowserTest::NavigateToOtherError(int num_navigations) { 568 NavigateToURLBlockUntilNavigationsComplete( 569 active_browser_, 570 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED), 571 num_navigations); 572} 573 574void 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 585void 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 594DnsProbeStatus 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. 610std::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. 628bool 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 641void 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. 649IN_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. 658IN_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. 666IN_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. 691IN_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. 729IN_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. 757IN_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. 795IN_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. 824IN_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. 849IN_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. 875IN_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. 894IN_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. 913IN_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. 946IN_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