Disable accessible touch exploration by default.
[chromium-blink-merge.git] / chrome / browser / errorpage_browsertest.cc
blob1d676a9731234f0124dc3fd8b197d6a35c376203
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/path_service.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/synchronization/lock.h"
16 #include "chrome/browser/browsing_data/browsing_data_helper.h"
17 #include "chrome/browser/browsing_data/browsing_data_remover.h"
18 #include "chrome/browser/google/google_profile_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/chrome_switches.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 "components/google/core/browser/google_util.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/notification_types.h"
33 #include "content/public/browser/render_frame_host.h"
34 #include "content/public/browser/render_view_host.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/test/browser_test_utils.h"
38 #include "content/public/test/test_navigation_observer.h"
39 #include "content/test/net/url_request_failed_job.h"
40 #include "content/test/net/url_request_mock_http_job.h"
41 #include "grit/generated_resources.h"
42 #include "net/base/net_errors.h"
43 #include "net/base/net_util.h"
44 #include "net/http/failing_http_transaction_factory.h"
45 #include "net/http/http_cache.h"
46 #include "net/test/spawned_test_server/spawned_test_server.h"
47 #include "net/url_request/url_request_context.h"
48 #include "net/url_request/url_request_context_getter.h"
49 #include "net/url_request/url_request_filter.h"
50 #include "net/url_request/url_request_interceptor.h"
51 #include "net/url_request/url_request_job.h"
52 #include "net/url_request/url_request_test_job.h"
53 #include "net/url_request/url_request_test_util.h"
54 #include "ui/base/l10n/l10n_util.h"
56 using content::BrowserThread;
57 using content::NavigationController;
58 using content::URLRequestFailedJob;
59 using net::URLRequestTestJob;
61 namespace {
63 // Returns true if |text| is displayed on the page |browser| is currently
64 // displaying. Uses "innerText", so will miss hidden text, and whitespace
65 // space handling may be weird.
66 bool WARN_UNUSED_RESULT IsDisplayingText(Browser* browser,
67 const std::string& text) {
68 std::string command = base::StringPrintf(
69 "var textContent = document.body.innerText;"
70 "var hasText = textContent.indexOf('%s') >= 0;"
71 "domAutomationController.send(hasText);",
72 text.c_str());
73 bool result = false;
74 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
75 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
76 return result;
79 // Expands the more box on the currently displayed error page.
80 void ToggleHelpBox(Browser* browser) {
81 EXPECT_TRUE(content::ExecuteScript(
82 browser->tab_strip_model()->GetActiveWebContents(),
83 "document.getElementById('more-less-button').click();"));
86 // Returns true if |browser| is displaying the text representation of
87 // |error_code| on the current page.
88 bool WARN_UNUSED_RESULT IsDisplayingNetError(Browser* browser,
89 net::Error error_code) {
90 // Get the error as a string, and remove the leading "net::", which is not
91 // included on error pages.
92 std::string error_string(net::ErrorToString(error_code));
93 DCHECK(StartsWithASCII(error_string, "net::", true));
94 error_string.erase(0, 5);
96 return IsDisplayingText(browser, error_string);
99 // Checks that the local error page is being displayed, without remotely
100 // retrieved navigation corrections, and with the specified error code.
101 void ExpectDisplayingLocalErrorPage(Browser* browser, net::Error error_code) {
102 // Expand the help box so innerText will include text below the fold.
103 ToggleHelpBox(browser);
105 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
107 // Locally generated error pages should not have navigation corrections.
108 EXPECT_FALSE(IsDisplayingText(browser, "http://correction1/"));
109 EXPECT_FALSE(IsDisplayingText(browser, "http://correction2/"));
111 // Locally generated error pages should not have a populated search box.
112 bool search_box_populated = false;
113 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
114 browser->tab_strip_model()->GetActiveWebContents(),
115 "var searchText = document.getElementById('search-box').value;"
116 "domAutomationController.send(searchText == 'search query');",
117 &search_box_populated));
118 EXPECT_FALSE(search_box_populated);
121 // Checks that an error page with information retrieved from the navigation
122 // correction service is being displayed, with the specified specified error
123 // code.
124 void ExpectDisplayingNavigationCorrections(Browser* browser,
125 net::Error error_code) {
126 // Expand the help box so innerText will include text below the fold.
127 ToggleHelpBox(browser);
129 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
131 // Check that the mock navigation corrections are displayed.
132 EXPECT_TRUE(IsDisplayingText(browser, "http://correction1/"));
133 EXPECT_TRUE(IsDisplayingText(browser, "http://correction2/"));
135 // Check that the search box is populated correctly.
136 bool search_box_populated = false;
137 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
138 browser->tab_strip_model()->GetActiveWebContents(),
139 "var searchText = document.getElementById('search-box').value;"
140 "domAutomationController.send(searchText == 'search query');",
141 &search_box_populated));
142 EXPECT_TRUE(search_box_populated);
145 std::string GetLoadStaleButtonLabel() {
146 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_LOAD_STALE);
149 void AddInterceptorForURL(
150 const GURL& url,
151 scoped_ptr<net::URLRequestInterceptor> handler) {
152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
153 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
154 url, handler.Pass());
157 // An interceptor that fails a configurable number of requests, then succeeds
158 // all requests after that, keeping count of failures and successes.
159 class FailFirstNRequestsInterceptor : public net::URLRequestInterceptor {
160 public:
161 explicit FailFirstNRequestsInterceptor(int requests_to_fail)
162 : requests_(0), failures_(0), requests_to_fail_(requests_to_fail) {}
163 virtual ~FailFirstNRequestsInterceptor() {}
165 // net::URLRequestInterceptor implementation
166 virtual net::URLRequestJob* MaybeInterceptRequest(
167 net::URLRequest* request,
168 net::NetworkDelegate* network_delegate) const OVERRIDE {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
170 requests_++;
171 if (failures_ < requests_to_fail_) {
172 failures_++;
173 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
174 // NetErrorHelperCore::GetErrorPageURL.
175 return new URLRequestFailedJob(request,
176 network_delegate,
177 net::ERR_CONNECTION_RESET);
178 } else {
179 return new URLRequestTestJob(request, network_delegate,
180 URLRequestTestJob::test_headers(),
181 URLRequestTestJob::test_data_1(),
182 true);
186 int requests() const { return requests_; }
187 int failures() const { return failures_; }
189 private:
190 // These are mutable because MaybeCreateJob is const but we want this state
191 // for testing.
192 mutable int requests_;
193 mutable int failures_;
194 int requests_to_fail_;
196 DISALLOW_COPY_AND_ASSIGN(FailFirstNRequestsInterceptor);
199 // An interceptor that serves LinkDoctor responses. It also allows waiting
200 // until a certain number of requests have been sent.
201 // TODO(mmenke): Wait until responses have been received instead.
202 class LinkDoctorInterceptor : public net::URLRequestInterceptor {
203 public:
204 LinkDoctorInterceptor() : num_requests_(0),
205 requests_to_wait_for_(-1),
206 weak_factory_(this) {
209 virtual ~LinkDoctorInterceptor() {}
211 // net::URLRequestInterceptor implementation
212 virtual net::URLRequestJob* MaybeInterceptRequest(
213 net::URLRequest* request,
214 net::NetworkDelegate* network_delegate) const OVERRIDE {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
217 BrowserThread::PostTask(
218 BrowserThread::UI, FROM_HERE,
219 base::Bind(&LinkDoctorInterceptor::RequestCreated,
220 weak_factory_.GetWeakPtr()));
222 base::FilePath root_http;
223 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
224 return new content::URLRequestMockHTTPJob(
225 request, network_delegate,
226 root_http.AppendASCII("mock-link-doctor.json"));
229 void WaitForRequests(int requests_to_wait_for) {
230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
231 DCHECK_EQ(-1, requests_to_wait_for_);
232 DCHECK(!run_loop_);
234 if (requests_to_wait_for >= num_requests_)
235 return;
237 requests_to_wait_for_ = requests_to_wait_for;
238 run_loop_.reset(new base::RunLoop());
239 run_loop_->Run();
240 run_loop_.reset();
241 requests_to_wait_for_ = -1;
242 EXPECT_EQ(num_requests_, requests_to_wait_for);
245 // It is up to the caller to wait until all relevant requests has been
246 // created, either through calling WaitForRequests or some other manner,
247 // before calling this method.
248 int num_requests() const {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250 return num_requests_;
253 private:
254 void RequestCreated() {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 num_requests_++;
258 if (num_requests_ == requests_to_wait_for_)
259 run_loop_->Quit();
262 // These are only used on the UI thread.
263 int num_requests_;
264 int requests_to_wait_for_;
265 scoped_ptr<base::RunLoop> run_loop_;
267 // This prevents any risk of flake if any test doesn't wait for a request
268 // it sent. Mutable so it can be accessed from a const function.
269 mutable base::WeakPtrFactory<LinkDoctorInterceptor> weak_factory_;
271 DISALLOW_COPY_AND_ASSIGN(LinkDoctorInterceptor);
274 void InstallMockInterceptors(
275 const GURL& search_url,
276 scoped_ptr<net::URLRequestInterceptor> link_doctor_interceptor) {
277 chrome_browser_net::SetUrlRequestMocksEnabled(true);
279 AddInterceptorForURL(google_util::LinkDoctorBaseURL(),
280 link_doctor_interceptor.Pass());
282 // Add a mock for the search engine the error page will use.
283 base::FilePath root_http;
284 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
285 content::URLRequestMockHTTPJob::AddHostnameToFileHandler(
286 search_url.host(), root_http.AppendASCII("title3.html"));
289 class ErrorPageTest : public InProcessBrowserTest {
290 public:
291 enum HistoryNavigationDirection {
292 HISTORY_NAVIGATE_BACK,
293 HISTORY_NAVIGATE_FORWARD,
296 ErrorPageTest() : link_doctor_interceptor_(NULL) {}
297 virtual ~ErrorPageTest() {}
299 // Navigates the active tab to a mock url created for the file at |file_path|.
300 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
301 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
302 command_line->AppendSwitch(switches::kEnableOfflineLoadStaleCache);
305 // Navigates the active tab to a mock url created for the file at |file_path|.
306 void NavigateToFileURL(const base::FilePath::StringType& file_path) {
307 ui_test_utils::NavigateToURL(
308 browser(),
309 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path)));
312 // Navigates to the given URL and waits for |num_navigations| to occur, and
313 // the title to change to |expected_title|.
314 void NavigateToURLAndWaitForTitle(const GURL& url,
315 const std::string& expected_title,
316 int num_navigations) {
317 content::TitleWatcher title_watcher(
318 browser()->tab_strip_model()->GetActiveWebContents(),
319 base::ASCIIToUTF16(expected_title));
321 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
322 browser(), url, num_navigations);
324 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
325 title_watcher.WaitAndGetTitle());
328 // Navigates back in the history and waits for |num_navigations| to occur, and
329 // the title to change to |expected_title|.
330 void GoBackAndWaitForTitle(const std::string& expected_title,
331 int num_navigations) {
332 NavigateHistoryAndWaitForTitle(expected_title,
333 num_navigations,
334 HISTORY_NAVIGATE_BACK);
337 // Navigates forward in the history and waits for |num_navigations| to occur,
338 // and the title to change to |expected_title|.
339 void GoForwardAndWaitForTitle(const std::string& expected_title,
340 int num_navigations) {
341 NavigateHistoryAndWaitForTitle(expected_title,
342 num_navigations,
343 HISTORY_NAVIGATE_FORWARD);
346 void GoBackAndWaitForNavigations(int num_navigations) {
347 NavigateHistory(num_navigations, HISTORY_NAVIGATE_BACK);
350 void GoForwardAndWaitForNavigations(int num_navigations) {
351 NavigateHistory(num_navigations, HISTORY_NAVIGATE_FORWARD);
354 // Confirms that the javascript variable indicating whether or not we have
355 // a stale copy in the cache has been set to |expected|, and that the
356 // stale load button is or isn't there based on the same expectation.
357 testing::AssertionResult ProbeStaleCopyValue(bool expected) {
358 const char* js_cache_probe =
359 "try {\n"
360 " domAutomationController.send(\n"
361 " 'staleLoadButton' in templateData ? 'yes' : 'no');\n"
362 "} catch (e) {\n"
363 " domAutomationController.send(e.message);\n"
364 "}\n";
366 std::string result;
367 bool ret =
368 content::ExecuteScriptAndExtractString(
369 browser()->tab_strip_model()->GetActiveWebContents(),
370 js_cache_probe,
371 &result);
372 if (!ret) {
373 return testing::AssertionFailure()
374 << "Failing return from ExecuteScriptAndExtractString.";
377 if ((expected && "yes" == result) || (!expected && "no" == result))
378 return testing::AssertionSuccess();
380 return testing::AssertionFailure() << "Cache probe result is " << result;
383 testing::AssertionResult ReloadStaleCopyFromCache() {
384 const char* js_reload_script =
385 "try {\n"
386 " document.getElementById('stale-load-button').click();\n"
387 " domAutomationController.send('success');\n"
388 "} catch (e) {\n"
389 " domAutomationController.send(e.message);\n"
390 "}\n";
392 std::string result;
393 bool ret = content::ExecuteScriptAndExtractString(
394 browser()->tab_strip_model()->GetActiveWebContents(),
395 js_reload_script,
396 &result);
397 EXPECT_TRUE(ret);
398 if (!ret)
399 return testing::AssertionFailure();
400 return ("success" == result ? testing::AssertionSuccess() :
401 (testing::AssertionFailure() << "Exception message is " << result));
404 LinkDoctorInterceptor* link_doctor_interceptor() {
405 return link_doctor_interceptor_;
408 protected:
409 virtual void SetUpOnMainThread() OVERRIDE {
410 link_doctor_interceptor_ = new LinkDoctorInterceptor();
411 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(
412 link_doctor_interceptor_);
413 // Ownership of the |interceptor_| is passed to an object the IO thread, but
414 // a pointer is kept in the test fixture. As soon as anything calls
415 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
416 BrowserThread::PostTask(
417 BrowserThread::IO, FROM_HERE,
418 base::Bind(&InstallMockInterceptors,
419 google_util::GetGoogleSearchURL(
420 google_profile_helper::GetGoogleHomePageURL(
421 browser()->profile())),
422 base::Passed(&owned_interceptor)));
425 // Returns a GURL that results in a DNS error.
426 GURL GetDnsErrorURL() const {
427 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
430 private:
431 // Navigates the browser the indicated direction in the history and waits for
432 // |num_navigations| to occur and the title to change to |expected_title|.
433 void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
434 int num_navigations,
435 HistoryNavigationDirection direction) {
436 content::TitleWatcher title_watcher(
437 browser()->tab_strip_model()->GetActiveWebContents(),
438 base::ASCIIToUTF16(expected_title));
440 NavigateHistory(num_navigations, direction);
442 EXPECT_EQ(title_watcher.WaitAndGetTitle(),
443 base::ASCIIToUTF16(expected_title));
446 void NavigateHistory(int num_navigations,
447 HistoryNavigationDirection direction) {
448 content::TestNavigationObserver test_navigation_observer(
449 browser()->tab_strip_model()->GetActiveWebContents(),
450 num_navigations);
451 if (direction == HISTORY_NAVIGATE_BACK) {
452 chrome::GoBack(browser(), CURRENT_TAB);
453 } else if (direction == HISTORY_NAVIGATE_FORWARD) {
454 chrome::GoForward(browser(), CURRENT_TAB);
455 } else {
456 FAIL();
458 test_navigation_observer.Wait();
461 LinkDoctorInterceptor* link_doctor_interceptor_;
464 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
465 public:
466 explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
467 : content::WebContentsObserver(contents) {}
468 virtual ~TestFailProvisionalLoadObserver() {}
470 // This method is invoked when the provisional load failed.
471 virtual void DidFailProvisionalLoad(
472 content::RenderFrameHost* render_frame_host,
473 const GURL& validated_url,
474 int error_code,
475 const base::string16& error_description) OVERRIDE {
476 fail_url_ = validated_url;
479 const GURL& fail_url() const { return fail_url_; }
481 private:
482 GURL fail_url_;
484 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
487 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
488 net::Error error) {
489 DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
490 net::HttpCache* cache(
491 getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
492 DCHECK(cache);
493 scoped_ptr<net::HttpTransactionFactory> factory(
494 new net::FailingHttpTransactionFactory(cache->GetSession(), error));
495 // Throw away old version; since this is a a browser test, we don't
496 // need to restore the old state.
497 cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
500 // Test that a DNS error occuring in the main frame redirects to an error page.
501 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_Basic) {
502 // The first navigation should fail, and the second one should be the error
503 // page.
504 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
505 browser(), GetDnsErrorURL(), 2);
506 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
507 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
510 // Test that a DNS error occuring in the main frame does not result in an
511 // additional session history entry.
512 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack1) {
513 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
514 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
515 browser(), GetDnsErrorURL(), 2);
516 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
517 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
518 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
521 // Test that a DNS error occuring in the main frame does not result in an
522 // additional session history entry.
523 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
524 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
526 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
527 browser(), GetDnsErrorURL(), 2);
528 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
529 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
531 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
533 GoBackAndWaitForNavigations(2);
534 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
535 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
537 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
538 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
541 // Test that a DNS error occuring in the main frame does not result in an
542 // additional session history entry.
543 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
544 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
546 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
547 browser(), GetDnsErrorURL(), 2);
548 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
549 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
551 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
553 GoBackAndWaitForNavigations(2);
554 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
555 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
557 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
559 GoForwardAndWaitForNavigations(2);
560 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
561 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
564 // Test that a DNS error occuring in the main frame does not result in an
565 // additional session history entry.
566 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
567 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
569 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
570 browser(), GetDnsErrorURL(), 2);
571 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
572 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
574 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
576 GoBackAndWaitForNavigations(2);
577 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
578 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
580 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
582 GoForwardAndWaitForNavigations(2);
583 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
584 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
586 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
587 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
590 // Test that the search button on a DNS error page works.
591 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoSearch) {
592 // The first navigation should fail, and the second one should be the error
593 // page.
594 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
595 browser(), GetDnsErrorURL(), 2);
596 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
597 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
599 content::WebContents* web_contents =
600 browser()->tab_strip_model()->GetActiveWebContents();
602 // Do a search and make sure the browser ends up at the right page.
603 content::TestNavigationObserver nav_observer(web_contents, 1);
604 content::TitleWatcher title_watcher(
605 web_contents,
606 base::ASCIIToUTF16("Title Of More Awesomeness"));
607 // Can't use content::ExecuteScript because it waits for scripts to send
608 // notification that they've run, and scripts that trigger a navigation may
609 // not send that notification.
610 web_contents->GetMainFrame()->ExecuteJavaScript(
611 base::ASCIIToUTF16("document.getElementById('search-button').click();"));
612 nav_observer.Wait();
613 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
614 title_watcher.WaitAndGetTitle());
616 // There should have been another Link Doctor request, for tracking purposes.
617 // Have to wait for it, since the search page does not depend on having
618 // sent the tracking request.
619 link_doctor_interceptor()->WaitForRequests(2);
620 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
622 // Check the path and query string.
623 std::string url;
624 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
625 browser()->tab_strip_model()->GetActiveWebContents(),
626 "domAutomationController.send(window.location.href);",
627 &url));
628 EXPECT_EQ("/search", GURL(url).path());
629 EXPECT_EQ("q=search%20query", GURL(url).query());
631 // Go back to the error page, to make sure the history is correct.
632 GoBackAndWaitForNavigations(2);
633 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
634 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
637 // Test that the reload button on a DNS error page works.
638 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoReload) {
639 // The first navigation should fail, and the second one should be the error
640 // page.
641 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
642 browser(), GetDnsErrorURL(), 2);
643 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
644 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
646 content::WebContents* web_contents =
647 browser()->tab_strip_model()->GetActiveWebContents();
649 // Clicking the reload button should load the error page again, and there
650 // should be two commits, as before.
651 content::TestNavigationObserver nav_observer(web_contents, 2);
652 // Can't use content::ExecuteScript because it waits for scripts to send
653 // notification that they've run, and scripts that trigger a navigation may
654 // not send that notification.
655 web_contents->GetMainFrame()->ExecuteJavaScript(
656 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
657 nav_observer.Wait();
658 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
660 // There should have two more requests to the correction service: One for the
661 // new error page, and one for tracking purposes. Have to make sure to wait
662 // for the tracking request, since the new error page does not depend on it.
663 link_doctor_interceptor()->WaitForRequests(3);
664 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
667 // Test that clicking links on a DNS error page works.
668 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoClickLink) {
669 // The first navigation should fail, and the second one should be the error
670 // page.
671 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
672 browser(), GetDnsErrorURL(), 2);
673 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
674 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
676 content::WebContents* web_contents =
677 browser()->tab_strip_model()->GetActiveWebContents();
679 // Simulate a click on a link.
681 content::TitleWatcher title_watcher(
682 web_contents,
683 base::ASCIIToUTF16("Title Of Awesomeness"));
684 std::string link_selector =
685 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
686 // The tracking request is triggered by onmousedown, so it catches middle
687 // mouse button clicks, as well as left clicks.
688 web_contents->GetMainFrame()->ExecuteJavaScript(
689 base::ASCIIToUTF16(link_selector + ".onmousedown();"));
690 // Can't use content::ExecuteScript because it waits for scripts to send
691 // notification that they've run, and scripts that trigger a navigation may
692 // not send that notification.
693 web_contents->GetMainFrame()->ExecuteJavaScript(
694 base::ASCIIToUTF16(link_selector + ".click();"));
695 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
696 title_watcher.WaitAndGetTitle());
698 // There should have been a tracking request to the correction service. Have
699 // to make sure to wait the tracking request, since the new page does not
700 // depend on it.
701 link_doctor_interceptor()->WaitForRequests(2);
702 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
705 // Test that a DNS error occuring in an iframe does not result in showing
706 // navigation corrections.
707 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
708 NavigateToURLAndWaitForTitle(
709 content::URLRequestMockHTTPJob::GetMockUrl(
710 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
711 "Blah",
713 // We expect to have two history entries, since we started off with navigation
714 // to "about:blank" and then navigated to "iframe_dns_error.html".
715 EXPECT_EQ(2,
716 browser()->tab_strip_model()->GetActiveWebContents()->
717 GetController().GetEntryCount());
718 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
721 // This test fails regularly on win_rel trybots. See crbug.com/121540
722 #if defined(OS_WIN)
723 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
724 #else
725 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
726 #endif
727 // Test that a DNS error occuring in an iframe does not result in an
728 // additional session history entry.
729 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
730 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
731 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
732 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
733 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
736 // This test fails regularly on win_rel trybots. See crbug.com/121540
738 // This fails on linux_aura bringup: http://crbug.com/163931
739 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
740 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
741 #else
742 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
743 #endif
744 // Test that a DNS error occuring in an iframe does not result in an
745 // additional session history entry.
746 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
747 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
748 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
749 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
750 GoForwardAndWaitForTitle("Blah", 1);
751 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
754 // Test that a DNS error occuring in an iframe, once the main document is
755 // completed loading, does not result in an additional session history entry.
756 // To ensure that the main document has completed loading, JavaScript is used to
757 // inject an iframe after loading is done.
758 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
759 content::WebContents* wc =
760 browser()->tab_strip_model()->GetActiveWebContents();
761 GURL fail_url =
762 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
764 // Load a regular web page, in which we will inject an iframe.
765 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
767 // We expect to have two history entries, since we started off with navigation
768 // to "about:blank" and then navigated to "title2.html".
769 EXPECT_EQ(2, wc->GetController().GetEntryCount());
771 std::string script = "var frame = document.createElement('iframe');"
772 "frame.src = '" + fail_url.spec() + "';"
773 "document.body.appendChild(frame);";
775 TestFailProvisionalLoadObserver fail_observer(wc);
776 content::WindowedNotificationObserver load_observer(
777 content::NOTIFICATION_LOAD_STOP,
778 content::Source<NavigationController>(&wc->GetController()));
779 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
780 load_observer.Wait();
782 // Ensure we saw the expected failure.
783 EXPECT_EQ(fail_url, fail_observer.fail_url());
785 // Failed initial navigation of an iframe shouldn't be adding any history
786 // entries.
787 EXPECT_EQ(2, wc->GetController().GetEntryCount());
790 // Do the same test, but with an iframe that doesn't have initial URL
791 // assigned.
792 script = "var frame = document.createElement('iframe');"
793 "frame.id = 'target_frame';"
794 "document.body.appendChild(frame);";
796 content::WindowedNotificationObserver load_observer(
797 content::NOTIFICATION_LOAD_STOP,
798 content::Source<NavigationController>(&wc->GetController()));
799 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
800 load_observer.Wait();
803 script = "var f = document.getElementById('target_frame');"
804 "f.src = '" + fail_url.spec() + "';";
806 TestFailProvisionalLoadObserver fail_observer(wc);
807 content::WindowedNotificationObserver load_observer(
808 content::NOTIFICATION_LOAD_STOP,
809 content::Source<NavigationController>(&wc->GetController()));
810 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
811 load_observer.Wait();
813 EXPECT_EQ(fail_url, fail_observer.fail_url());
814 EXPECT_EQ(2, wc->GetController().GetEntryCount());
816 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
819 // Checks that navigation corrections are not loaded when we receive an actual
820 // 404 page.
821 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
822 NavigateToURLAndWaitForTitle(
823 content::URLRequestMockHTTPJob::GetMockUrl(
824 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
825 "SUCCESS",
827 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
830 // Checks that when an error occurs, the stale cache status of the page
831 // is correctly transferred, and that stale cached copied can be loaded
832 // from the javascript.
833 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
834 ASSERT_TRUE(test_server()->Start());
835 // Load cache with entry with "nocache" set, to create stale
836 // cache.
837 GURL test_url(test_server()->GetURL("files/nocache.html"));
838 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
840 // Reload same URL after forcing an error from the the network layer;
841 // confirm that the error page is told the cached copy exists.
842 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
843 browser()->profile()->GetRequestContext();
844 BrowserThread::PostTask(
845 BrowserThread::IO, FROM_HERE,
846 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
847 net::ERR_FAILED));
849 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
850 // With no navigation corrections to load, there's only one navigation.
851 browser(), test_url, 1);
852 EXPECT_TRUE(ProbeStaleCopyValue(true));
853 EXPECT_TRUE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
854 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
855 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
857 // Confirm that loading the stale copy from the cache works.
858 content::TestNavigationObserver same_tab_observer(
859 browser()->tab_strip_model()->GetActiveWebContents(), 1);
860 ASSERT_TRUE(ReloadStaleCopyFromCache());
861 same_tab_observer.Wait();
862 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
863 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
865 // Clear the cache and reload the same URL; confirm the error page is told
866 // that there is no cached copy.
867 BrowsingDataRemover* remover =
868 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
869 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
870 BrowsingDataHelper::UNPROTECTED_WEB);
871 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
872 browser(), test_url, 1);
873 EXPECT_TRUE(ProbeStaleCopyValue(false));
874 EXPECT_FALSE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
875 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
878 class ErrorPageAutoReloadTest : public InProcessBrowserTest {
879 public:
880 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
881 command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
884 void InstallInterceptor(const GURL& url, int requests_to_fail) {
885 interceptor_ = new FailFirstNRequestsInterceptor(requests_to_fail);
886 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(interceptor_);
888 // Tests don't need to wait for this task to complete before using the
889 // filter; any requests that might be affected by it will end up in the IO
890 // thread's message loop after this posted task anyway.
892 // Ownership of the interceptor is passed to an object the IO thread, but a
893 // pointer is kept in the test fixture. As soon as anything calls
894 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
895 BrowserThread::PostTask(
896 BrowserThread::IO, FROM_HERE,
897 base::Bind(&AddInterceptorForURL, url,
898 base::Passed(&owned_interceptor)));
901 void NavigateToURLAndWaitForTitle(const GURL& url,
902 const std::string& expected_title,
903 int num_navigations) {
904 content::TitleWatcher title_watcher(
905 browser()->tab_strip_model()->GetActiveWebContents(),
906 base::ASCIIToUTF16(expected_title));
908 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
909 browser(), url, num_navigations);
911 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
912 title_watcher.WaitAndGetTitle());
915 FailFirstNRequestsInterceptor* interceptor() {
916 return interceptor_;
919 private:
920 FailFirstNRequestsInterceptor* interceptor_;
923 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, AutoReload) {
924 GURL test_url("http://error.page.auto.reload");
925 const int kRequestsToFail = 2;
926 InstallInterceptor(test_url, kRequestsToFail);
927 NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
928 // Note that the interceptor updates these variables on the IO thread,
929 // but this function reads them on the main thread. The requests have to be
930 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
931 // this becomes racey.
932 EXPECT_EQ(kRequestsToFail, interceptor()->failures());
933 EXPECT_EQ(kRequestsToFail + 1, interceptor()->requests());
936 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
937 class AddressUnreachableInterceptor : public net::URLRequestInterceptor {
938 public:
939 AddressUnreachableInterceptor() {}
940 virtual ~AddressUnreachableInterceptor() {}
942 // net::URLRequestInterceptor:
943 virtual net::URLRequestJob* MaybeInterceptRequest(
944 net::URLRequest* request,
945 net::NetworkDelegate* network_delegate) const OVERRIDE {
946 return new URLRequestFailedJob(request,
947 network_delegate,
948 net::ERR_ADDRESS_UNREACHABLE);
951 private:
952 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor);
955 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
956 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
957 // a different error for the correction service and the original page to
958 // validate the right page is being displayed.
959 class ErrorPageNavigationCorrectionsFailTest : public ErrorPageTest {
960 public:
961 // InProcessBrowserTest:
962 virtual void SetUpOnMainThread() OVERRIDE {
963 BrowserThread::PostTask(
964 BrowserThread::IO, FROM_HERE,
965 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters));
968 virtual void TearDownOnMainThread() OVERRIDE {
969 BrowserThread::PostTask(
970 BrowserThread::IO, FROM_HERE,
971 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters));
974 private:
975 // Adds a filter that causes all correction service requests to fail with
976 // ERR_ADDRESS_UNREACHABLE.
978 // Also adds the content::URLRequestFailedJob filter.
979 static void AddFilters() {
980 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
981 content::URLRequestFailedJob::AddUrlHandler();
983 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
984 google_util::LinkDoctorBaseURL(),
985 scoped_ptr<net::URLRequestInterceptor>(
986 new AddressUnreachableInterceptor()));
989 static void RemoveFilters() {
990 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
991 net::URLRequestFilter::GetInstance()->ClearHandlers();
995 // Make sure that when corrections fail to load, the network error page is
996 // successfully loaded.
997 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
998 FetchCorrectionsFails) {
999 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1000 browser(),
1001 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
1004 // Verify that the expected error page is being displayed.
1005 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED);
1008 // Checks that when an error occurs and a corrections fail to load, the stale
1009 // cache status of the page is correctly transferred, and we can load the
1010 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1011 // above.
1012 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1013 StaleCacheStatusFailedCorrections) {
1014 ASSERT_TRUE(test_server()->Start());
1015 // Load cache with entry with "nocache" set, to create stale
1016 // cache.
1017 GURL test_url(test_server()->GetURL("files/nocache.html"));
1018 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
1020 // Reload same URL after forcing an error from the the network layer;
1021 // confirm that the error page is told the cached copy exists.
1022 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1023 browser()->profile()->GetRequestContext();
1024 BrowserThread::PostTask(
1025 BrowserThread::IO, FROM_HERE,
1026 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
1027 net::ERR_CONNECTION_FAILED));
1029 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1030 browser(), test_url, 2);
1031 EXPECT_TRUE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
1032 EXPECT_TRUE(ProbeStaleCopyValue(true));
1034 // Confirm that loading the stale copy from the cache works.
1035 content::TestNavigationObserver same_tab_observer(
1036 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1037 ASSERT_TRUE(ReloadStaleCopyFromCache());
1038 same_tab_observer.Wait();
1039 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1040 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1042 // Clear the cache and reload the same URL; confirm the error page is told
1043 // that there is no cached copy.
1044 BrowsingDataRemover* remover =
1045 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
1046 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1047 BrowsingDataHelper::UNPROTECTED_WEB);
1048 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1049 browser(), test_url, 2);
1050 EXPECT_TRUE(ProbeStaleCopyValue(false));
1051 EXPECT_FALSE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
1054 // A test fixture that simulates failing requests for an IDN domain name.
1055 class ErrorPageForIDNTest : public InProcessBrowserTest {
1056 public:
1057 // Target hostname in different forms.
1058 static const char kHostname[];
1059 static const char kHostnameJSUnicode[];
1061 // InProcessBrowserTest:
1062 virtual void SetUpOnMainThread() OVERRIDE {
1063 // Clear AcceptLanguages to force punycode decoding.
1064 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
1065 std::string());
1066 BrowserThread::PostTask(
1067 BrowserThread::IO, FROM_HERE,
1068 base::Bind(&ErrorPageForIDNTest::AddFilters));
1071 virtual void TearDownOnMainThread() OVERRIDE {
1072 BrowserThread::PostTask(
1073 BrowserThread::IO, FROM_HERE,
1074 base::Bind(&ErrorPageForIDNTest::RemoveFilters));
1077 private:
1078 static void AddFilters() {
1079 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1080 content::URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
1083 static void RemoveFilters() {
1084 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1085 net::URLRequestFilter::GetInstance()->ClearHandlers();
1089 const char ErrorPageForIDNTest::kHostname[] =
1090 "xn--d1abbgf6aiiy.xn--p1ai";
1091 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
1092 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1093 "\\u0440\\u0444";
1095 // Make sure error page shows correct unicode for IDN.
1096 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
1097 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1098 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1099 browser(),
1100 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
1101 kHostname),
1104 ToggleHelpBox(browser());
1105 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode));
1108 } // namespace