Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / errorpage_browsertest.cc
blobd68cef96badd87bb61cdc062ee4c18c20e5d7bc1
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/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/path_service.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/synchronization/lock.h"
17 #include "chrome/browser/browsing_data/browsing_data_helper.h"
18 #include "chrome/browser/browsing_data/browsing_data_remover.h"
19 #include "chrome/browser/net/net_error_diagnostics_dialog.h"
20 #include "chrome/browser/net/url_request_mock_util.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_commands.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/grit/generated_resources.h"
30 #include "chrome/test/base/in_process_browser_test.h"
31 #include "chrome/test/base/ui_test_utils.h"
32 #include "components/google/core/browser/google_util.h"
33 #include "content/public/browser/browser_thread.h"
34 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/notification_types.h"
36 #include "content/public/browser/render_frame_host.h"
37 #include "content/public/browser/render_view_host.h"
38 #include "content/public/browser/web_contents.h"
39 #include "content/public/browser/web_contents_observer.h"
40 #include "content/public/test/browser_test_utils.h"
41 #include "content/public/test/test_navigation_observer.h"
42 #include "net/base/filename_util.h"
43 #include "net/base/net_errors.h"
44 #include "net/base/net_util.h"
45 #include "net/http/failing_http_transaction_factory.h"
46 #include "net/http/http_cache.h"
47 #include "net/test/spawned_test_server/spawned_test_server.h"
48 #include "net/test/url_request/url_request_failed_job.h"
49 #include "net/test/url_request/url_request_mock_http_job.h"
50 #include "net/url_request/url_request_context.h"
51 #include "net/url_request/url_request_context_getter.h"
52 #include "net/url_request/url_request_filter.h"
53 #include "net/url_request/url_request_interceptor.h"
54 #include "net/url_request/url_request_job.h"
55 #include "net/url_request/url_request_test_job.h"
56 #include "net/url_request/url_request_test_util.h"
57 #include "ui/base/l10n/l10n_util.h"
59 #if defined(OS_CHROMEOS)
60 #include "chrome/browser/browser_process.h"
61 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
62 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
63 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
64 #include "components/policy/core/common/mock_configuration_policy_provider.h"
65 #include "components/policy/core/common/policy_types.h"
66 #endif
68 using content::BrowserThread;
69 using content::NavigationController;
70 using net::URLRequestFailedJob;
71 using net::URLRequestTestJob;
73 namespace {
75 // Returns true if |text| is displayed on the page |browser| is currently
76 // displaying. Uses "innerText", so will miss hidden text, and whitespace
77 // space handling may be weird.
78 bool WARN_UNUSED_RESULT IsDisplayingText(Browser* browser,
79 const std::string& text) {
80 std::string command = base::StringPrintf(
81 "var textContent = document.body.innerText;"
82 "var hasText = textContent.indexOf('%s') >= 0;"
83 "domAutomationController.send(hasText);",
84 text.c_str());
85 bool result = false;
86 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
87 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
88 return result;
91 // Expands the more box on the currently displayed error page.
92 void ToggleHelpBox(Browser* browser) {
93 EXPECT_TRUE(content::ExecuteScript(
94 browser->tab_strip_model()->GetActiveWebContents(),
95 "document.getElementById('details-button').click();"));
98 // Returns true if |browser| is displaying the text representation of
99 // |error_code| on the current page.
100 bool WARN_UNUSED_RESULT IsDisplayingNetError(Browser* browser,
101 net::Error error_code) {
102 return IsDisplayingText(browser, net::ErrorToShortString(error_code));
105 // Returns true if the diagnostics button is displayed.
106 bool WARN_UNUSED_RESULT IsDisplayingDiagnosticsButton(Browser* browser) {
107 std::string command = base::StringPrintf(
108 "var diagnose_button = document.getElementById('diagnose-button');"
109 "domAutomationController.send(diagnose_button.style.display != 'none');");
110 bool result = false;
111 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
112 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
113 return result;
116 // Checks that the local error page is being displayed, without remotely
117 // retrieved navigation corrections, and with the specified error code.
118 void ExpectDisplayingLocalErrorPage(Browser* browser, net::Error error_code) {
119 // Expand the help box so innerText will include text below the fold.
120 ToggleHelpBox(browser);
122 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
124 // Locally generated error pages should not have navigation corrections.
125 EXPECT_FALSE(IsDisplayingText(browser, "http://correction1/"));
126 EXPECT_FALSE(IsDisplayingText(browser, "http://correction2/"));
128 // Locally generated error pages should not have a populated search box.
129 bool search_box_populated = false;
130 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
131 browser->tab_strip_model()->GetActiveWebContents(),
132 "var searchText = document.getElementById('search-box').value;"
133 "domAutomationController.send(searchText == 'search query');",
134 &search_box_populated));
135 EXPECT_FALSE(search_box_populated);
138 // Checks that an error page with information retrieved from the navigation
139 // correction service is being displayed, with the specified specified error
140 // code.
141 void ExpectDisplayingNavigationCorrections(Browser* browser,
142 net::Error error_code) {
143 // Expand the help box so innerText will include text below the fold.
144 ToggleHelpBox(browser);
146 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
148 // Check that the mock navigation corrections are displayed.
149 EXPECT_TRUE(IsDisplayingText(browser, "http://correction1/"));
150 EXPECT_TRUE(IsDisplayingText(browser, "http://correction2/"));
152 // Check that the search box is populated correctly.
153 bool search_box_populated = false;
154 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
155 browser->tab_strip_model()->GetActiveWebContents(),
156 "var searchText = document.getElementById('search-box').value;"
157 "domAutomationController.send(searchText == 'search query');",
158 &search_box_populated));
159 EXPECT_TRUE(search_box_populated);
161 // The diagnostics button isn't displayed when corrections were
162 // retrieved from a remote server.
163 EXPECT_FALSE(IsDisplayingDiagnosticsButton(browser));
166 std::string GetShowSavedButtonLabel() {
167 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY);
170 void AddInterceptorForURL(
171 const GURL& url,
172 scoped_ptr<net::URLRequestInterceptor> handler) {
173 DCHECK_CURRENTLY_ON(BrowserThread::IO);
174 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
175 url, handler.Pass());
178 // An interceptor that fails a configurable number of requests, then succeeds
179 // all requests after that, keeping count of failures and successes.
180 class FailFirstNRequestsInterceptor : public net::URLRequestInterceptor {
181 public:
182 explicit FailFirstNRequestsInterceptor(int requests_to_fail)
183 : requests_(0), failures_(0), requests_to_fail_(requests_to_fail) {}
184 ~FailFirstNRequestsInterceptor() override {}
186 // net::URLRequestInterceptor implementation
187 net::URLRequestJob* MaybeInterceptRequest(
188 net::URLRequest* request,
189 net::NetworkDelegate* network_delegate) const override {
190 DCHECK_CURRENTLY_ON(BrowserThread::IO);
191 requests_++;
192 if (failures_ < requests_to_fail_) {
193 failures_++;
194 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
195 // NetErrorHelperCore::GetErrorPageURL.
196 return new URLRequestFailedJob(request,
197 network_delegate,
198 net::ERR_CONNECTION_RESET);
199 } else {
200 return new URLRequestTestJob(request, network_delegate,
201 URLRequestTestJob::test_headers(),
202 URLRequestTestJob::test_data_1(),
203 true);
207 int requests() const { return requests_; }
208 int failures() const { return failures_; }
210 private:
211 // These are mutable because MaybeCreateJob is const but we want this state
212 // for testing.
213 mutable int requests_;
214 mutable int failures_;
215 int requests_to_fail_;
217 DISALLOW_COPY_AND_ASSIGN(FailFirstNRequestsInterceptor);
220 // An interceptor that serves LinkDoctor responses. It also allows waiting
221 // until a certain number of requests have been sent.
222 // TODO(mmenke): Wait until responses have been received instead.
223 class LinkDoctorInterceptor : public net::URLRequestInterceptor {
224 public:
225 LinkDoctorInterceptor() : num_requests_(0),
226 requests_to_wait_for_(-1),
227 weak_factory_(this) {
230 ~LinkDoctorInterceptor() override {}
232 // net::URLRequestInterceptor implementation
233 net::URLRequestJob* MaybeInterceptRequest(
234 net::URLRequest* request,
235 net::NetworkDelegate* network_delegate) const override {
236 DCHECK_CURRENTLY_ON(BrowserThread::IO);
238 BrowserThread::PostTask(
239 BrowserThread::UI, FROM_HERE,
240 base::Bind(&LinkDoctorInterceptor::RequestCreated,
241 weak_factory_.GetWeakPtr()));
243 base::FilePath root_http;
244 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
245 return new net::URLRequestMockHTTPJob(
246 request,
247 network_delegate,
248 root_http.AppendASCII("mock-link-doctor.json"),
249 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
250 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
253 void WaitForRequests(int requests_to_wait_for) {
254 DCHECK_CURRENTLY_ON(BrowserThread::UI);
255 DCHECK_EQ(-1, requests_to_wait_for_);
256 DCHECK(!run_loop_);
258 if (requests_to_wait_for >= num_requests_)
259 return;
261 requests_to_wait_for_ = requests_to_wait_for;
262 run_loop_.reset(new base::RunLoop());
263 run_loop_->Run();
264 run_loop_.reset();
265 requests_to_wait_for_ = -1;
266 EXPECT_EQ(num_requests_, requests_to_wait_for);
269 // It is up to the caller to wait until all relevant requests has been
270 // created, either through calling WaitForRequests or some other manner,
271 // before calling this method.
272 int num_requests() const {
273 DCHECK_CURRENTLY_ON(BrowserThread::UI);
274 return num_requests_;
277 private:
278 void RequestCreated() {
279 DCHECK_CURRENTLY_ON(BrowserThread::UI);
281 num_requests_++;
282 if (num_requests_ == requests_to_wait_for_)
283 run_loop_->Quit();
286 // These are only used on the UI thread.
287 int num_requests_;
288 int requests_to_wait_for_;
289 scoped_ptr<base::RunLoop> run_loop_;
291 // This prevents any risk of flake if any test doesn't wait for a request
292 // it sent. Mutable so it can be accessed from a const function.
293 mutable base::WeakPtrFactory<LinkDoctorInterceptor> weak_factory_;
295 DISALLOW_COPY_AND_ASSIGN(LinkDoctorInterceptor);
298 void InstallMockInterceptors(
299 const GURL& search_url,
300 scoped_ptr<net::URLRequestInterceptor> link_doctor_interceptor) {
301 chrome_browser_net::SetUrlRequestMocksEnabled(true);
303 AddInterceptorForURL(google_util::LinkDoctorBaseURL(),
304 link_doctor_interceptor.Pass());
306 // Add a mock for the search engine the error page will use.
307 base::FilePath root_http;
308 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
309 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
310 search_url.scheme(), search_url.host(),
311 net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
312 root_http.AppendASCII("title3.html"),
313 BrowserThread::GetBlockingPool()));
316 class ErrorPageTest : public InProcessBrowserTest {
317 public:
318 enum HistoryNavigationDirection {
319 HISTORY_NAVIGATE_BACK,
320 HISTORY_NAVIGATE_FORWARD,
323 ErrorPageTest() : link_doctor_interceptor_(NULL) {}
324 ~ErrorPageTest() override {}
326 // Navigates the active tab to a mock url created for the file at |file_path|.
327 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
328 void SetUpCommandLine(base::CommandLine* command_line) override {
329 command_line->AppendSwitchASCII(switches::kShowSavedCopy,
330 switches::kEnableShowSavedCopyPrimary);
333 // Navigates the active tab to a mock url created for the file at |file_path|.
334 void NavigateToFileURL(const base::FilePath::StringType& file_path) {
335 ui_test_utils::NavigateToURL(
336 browser(),
337 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path)));
340 // Navigates to the given URL and waits for |num_navigations| to occur, and
341 // the title to change to |expected_title|.
342 void NavigateToURLAndWaitForTitle(const GURL& url,
343 const std::string& expected_title,
344 int num_navigations) {
345 content::TitleWatcher title_watcher(
346 browser()->tab_strip_model()->GetActiveWebContents(),
347 base::ASCIIToUTF16(expected_title));
349 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
350 browser(), url, num_navigations);
352 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
353 title_watcher.WaitAndGetTitle());
356 // Navigates back in the history and waits for |num_navigations| to occur, and
357 // the title to change to |expected_title|.
358 void GoBackAndWaitForTitle(const std::string& expected_title,
359 int num_navigations) {
360 NavigateHistoryAndWaitForTitle(expected_title,
361 num_navigations,
362 HISTORY_NAVIGATE_BACK);
365 // Navigates forward in the history and waits for |num_navigations| to occur,
366 // and the title to change to |expected_title|.
367 void GoForwardAndWaitForTitle(const std::string& expected_title,
368 int num_navigations) {
369 NavigateHistoryAndWaitForTitle(expected_title,
370 num_navigations,
371 HISTORY_NAVIGATE_FORWARD);
374 void GoBackAndWaitForNavigations(int num_navigations) {
375 NavigateHistory(num_navigations, HISTORY_NAVIGATE_BACK);
378 void GoForwardAndWaitForNavigations(int num_navigations) {
379 NavigateHistory(num_navigations, HISTORY_NAVIGATE_FORWARD);
382 // Confirms that the javascript variable indicating whether or not we have
383 // a stale copy in the cache has been set to |expected|, and that the
384 // stale load button is or isn't there based on the same expectation.
385 testing::AssertionResult ProbeStaleCopyValue(bool expected) {
386 const char* js_cache_probe =
387 "try {\n"
388 " domAutomationController.send(\n"
389 " loadTimeData.valueExists('showSavedCopyButton') ?"
390 " 'yes' : 'no');\n"
391 "} catch (e) {\n"
392 " domAutomationController.send(e.message);\n"
393 "}\n";
395 std::string result;
396 bool ret =
397 content::ExecuteScriptAndExtractString(
398 browser()->tab_strip_model()->GetActiveWebContents(),
399 js_cache_probe,
400 &result);
401 if (!ret) {
402 return testing::AssertionFailure()
403 << "Failing return from ExecuteScriptAndExtractString.";
406 if ((expected && "yes" == result) || (!expected && "no" == result))
407 return testing::AssertionSuccess();
409 return testing::AssertionFailure() << "Cache probe result is " << result;
412 testing::AssertionResult ReloadStaleCopyFromCache() {
413 const char* js_reload_script =
414 "try {\n"
415 " document.getElementById('show-saved-copy-button').click();\n"
416 " domAutomationController.send('success');\n"
417 "} catch (e) {\n"
418 " domAutomationController.send(e.message);\n"
419 "}\n";
421 std::string result;
422 bool ret = content::ExecuteScriptAndExtractString(
423 browser()->tab_strip_model()->GetActiveWebContents(),
424 js_reload_script,
425 &result);
426 EXPECT_TRUE(ret);
427 if (!ret)
428 return testing::AssertionFailure();
429 return ("success" == result ? testing::AssertionSuccess() :
430 (testing::AssertionFailure() << "Exception message is " << result));
433 LinkDoctorInterceptor* link_doctor_interceptor() {
434 return link_doctor_interceptor_;
437 protected:
438 void SetUpOnMainThread() override {
439 link_doctor_interceptor_ = new LinkDoctorInterceptor();
440 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(
441 link_doctor_interceptor_);
442 // Ownership of the |interceptor_| is passed to an object the IO thread, but
443 // a pointer is kept in the test fixture. As soon as anything calls
444 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
445 UIThreadSearchTermsData search_terms_data(browser()->profile());
446 BrowserThread::PostTask(
447 BrowserThread::IO, FROM_HERE,
448 base::Bind(&InstallMockInterceptors,
449 GURL(search_terms_data.GoogleBaseURLValue()),
450 base::Passed(&owned_interceptor)));
453 // Returns a GURL that results in a DNS error.
454 GURL GetDnsErrorURL() const {
455 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
458 // Returns true if the platform has support for a diagnostics tool, which
459 // can be launched from the error page.
460 bool PlatformSupportsDiagnosticsTool() {
461 #if defined(OS_CHROMEOS)
462 // ChromeOS uses an extension instead of a diagnostics dialog.
463 return true;
464 #else
465 return CanShowNetworkDiagnosticsDialog();
466 #endif
469 private:
470 // Navigates the browser the indicated direction in the history and waits for
471 // |num_navigations| to occur and the title to change to |expected_title|.
472 void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
473 int num_navigations,
474 HistoryNavigationDirection direction) {
475 content::TitleWatcher title_watcher(
476 browser()->tab_strip_model()->GetActiveWebContents(),
477 base::ASCIIToUTF16(expected_title));
479 NavigateHistory(num_navigations, direction);
481 EXPECT_EQ(title_watcher.WaitAndGetTitle(),
482 base::ASCIIToUTF16(expected_title));
485 void NavigateHistory(int num_navigations,
486 HistoryNavigationDirection direction) {
487 content::TestNavigationObserver test_navigation_observer(
488 browser()->tab_strip_model()->GetActiveWebContents(),
489 num_navigations);
490 if (direction == HISTORY_NAVIGATE_BACK) {
491 chrome::GoBack(browser(), CURRENT_TAB);
492 } else if (direction == HISTORY_NAVIGATE_FORWARD) {
493 chrome::GoForward(browser(), CURRENT_TAB);
494 } else {
495 FAIL();
497 test_navigation_observer.Wait();
500 LinkDoctorInterceptor* link_doctor_interceptor_;
503 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
504 public:
505 explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
506 : content::WebContentsObserver(contents) {}
507 ~TestFailProvisionalLoadObserver() override {}
509 // This method is invoked when the provisional load failed.
510 void DidFailProvisionalLoad(
511 content::RenderFrameHost* render_frame_host,
512 const GURL& validated_url,
513 int error_code,
514 const base::string16& error_description,
515 bool was_ignored_by_handler) override {
516 fail_url_ = validated_url;
519 const GURL& fail_url() const { return fail_url_; }
521 private:
522 GURL fail_url_;
524 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
527 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
528 net::Error error) {
529 DCHECK_CURRENTLY_ON(BrowserThread::IO);
530 net::HttpCache* cache(
531 getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
532 DCHECK(cache);
533 scoped_ptr<net::HttpTransactionFactory> factory(
534 new net::FailingHttpTransactionFactory(cache->GetSession(), error));
535 // Throw away old version; since this is a a browser test, we don't
536 // need to restore the old state.
537 cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
540 // Test an error with a file URL, and make sure it doesn't have a
541 // button to launch a network diagnostics tool.
542 IN_PROC_BROWSER_TEST_F(ErrorPageTest, FileNotFound) {
543 // Create an empty temp directory, to be sure there's no file in it.
544 base::ScopedTempDir temp_dir;
545 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
546 GURL non_existent_file_url =
547 net::FilePathToFileURL(temp_dir.path().AppendASCII("marmoset"));
549 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
550 browser(), non_existent_file_url, 1);
552 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FILE_NOT_FOUND);
553 // Should not request Link Doctor corrections for local errors.
554 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
555 // Only errors on HTTP/HTTPS pages should display a diagnostics button.
556 EXPECT_FALSE(IsDisplayingDiagnosticsButton(browser()));
559 // Check an network error page for ERR_FAILED. In particular, this should
560 // not trigger a link doctor error page, and should have a diagnostics
561 // button, if available on the current platform.
562 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Failed) {
563 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
564 browser(), URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED), 1);
566 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FAILED);
567 // Should not request Link Doctor corrections for this error.
568 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
570 EXPECT_EQ(PlatformSupportsDiagnosticsTool(),
571 IsDisplayingDiagnosticsButton(browser()));
574 // Test that a DNS error occuring in the main frame redirects to an error page.
575 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_Basic) {
576 // The first navigation should fail and load a blank page, while it fetches
577 // the Link Doctor response. The second navigation is the Link Doctor.
578 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
579 browser(), GetDnsErrorURL(), 2);
580 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
581 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
584 // Test that a DNS error occuring in the main frame does not result in an
585 // additional session history entry.
586 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack1) {
587 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
588 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
589 browser(), GetDnsErrorURL(), 2);
590 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
591 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
592 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
595 // Test that a DNS error occuring in the main frame does not result in an
596 // additional session history entry.
597 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
598 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
600 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
601 browser(), GetDnsErrorURL(), 2);
602 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
603 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
605 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
607 GoBackAndWaitForNavigations(2);
608 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
609 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
611 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
612 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
615 // Test that a DNS error occuring in the main frame does not result in an
616 // additional session history entry.
617 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
618 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
620 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
621 browser(), GetDnsErrorURL(), 2);
622 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
623 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
625 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
627 GoBackAndWaitForNavigations(2);
628 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
629 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
631 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
633 GoForwardAndWaitForNavigations(2);
634 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
635 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
638 // Test that a DNS error occuring in the main frame does not result in an
639 // additional session history entry.
640 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
641 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
643 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
644 browser(), GetDnsErrorURL(), 2);
645 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
646 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
648 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
650 GoBackAndWaitForNavigations(2);
651 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
652 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
654 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
656 GoForwardAndWaitForNavigations(2);
657 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
658 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
660 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
661 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
664 // Test that the search button on a DNS error page works.
665 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoSearch) {
666 // The first navigation should fail, and the second one should be the error
667 // page.
668 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
669 browser(), GetDnsErrorURL(), 2);
670 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
671 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
673 content::WebContents* web_contents =
674 browser()->tab_strip_model()->GetActiveWebContents();
676 // Do a search and make sure the browser ends up at the right page.
677 content::TestNavigationObserver nav_observer(web_contents, 1);
678 content::TitleWatcher title_watcher(
679 web_contents,
680 base::ASCIIToUTF16("Title Of More Awesomeness"));
681 // Can't use content::ExecuteScript because it waits for scripts to send
682 // notification that they've run, and scripts that trigger a navigation may
683 // not send that notification.
684 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
685 base::ASCIIToUTF16("document.getElementById('search-button').click();"));
686 nav_observer.Wait();
687 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
688 title_watcher.WaitAndGetTitle());
690 // There should have been another Link Doctor request, for tracking purposes.
691 // Have to wait for it, since the search page does not depend on having
692 // sent the tracking request.
693 link_doctor_interceptor()->WaitForRequests(2);
694 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
696 // Check the path and query string.
697 std::string url;
698 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
699 browser()->tab_strip_model()->GetActiveWebContents(),
700 "domAutomationController.send(window.location.href);",
701 &url));
702 EXPECT_EQ("/search", GURL(url).path());
703 EXPECT_EQ("q=search%20query", GURL(url).query());
705 // Go back to the error page, to make sure the history is correct.
706 GoBackAndWaitForNavigations(2);
707 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
708 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
711 // Test that the reload button on a DNS error page works.
712 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoReload) {
713 // The first navigation should fail, and the second one should be the error
714 // page.
715 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
716 browser(), GetDnsErrorURL(), 2);
717 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
718 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
720 content::WebContents* web_contents =
721 browser()->tab_strip_model()->GetActiveWebContents();
723 // Clicking the reload button should load the error page again, and there
724 // should be two commits, as before.
725 content::TestNavigationObserver nav_observer(web_contents, 2);
726 // Can't use content::ExecuteScript because it waits for scripts to send
727 // notification that they've run, and scripts that trigger a navigation may
728 // not send that notification.
729 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
730 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
731 nav_observer.Wait();
732 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
734 // There should have two more requests to the correction service: One for the
735 // new error page, and one for tracking purposes. Have to make sure to wait
736 // for the tracking request, since the new error page does not depend on it.
737 link_doctor_interceptor()->WaitForRequests(3);
738 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
741 // Test that clicking links on a DNS error page works.
742 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoClickLink) {
743 // The first navigation should fail, and the second one should be the error
744 // page.
745 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
746 browser(), GetDnsErrorURL(), 2);
747 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
748 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
750 content::WebContents* web_contents =
751 browser()->tab_strip_model()->GetActiveWebContents();
753 // Simulate a click on a link.
755 content::TitleWatcher title_watcher(
756 web_contents,
757 base::ASCIIToUTF16("Title Of Awesomeness"));
758 std::string link_selector =
759 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
760 // The tracking request is triggered by onmousedown, so it catches middle
761 // mouse button clicks, as well as left clicks.
762 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
763 base::ASCIIToUTF16(link_selector + ".onmousedown();"));
764 // Can't use content::ExecuteScript because it waits for scripts to send
765 // notification that they've run, and scripts that trigger a navigation may
766 // not send that notification.
767 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
768 base::ASCIIToUTF16(link_selector + ".click();"));
769 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
770 title_watcher.WaitAndGetTitle());
772 // There should have been a tracking request to the correction service. Have
773 // to make sure to wait the tracking request, since the new page does not
774 // depend on it.
775 link_doctor_interceptor()->WaitForRequests(2);
776 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
779 // Test that a DNS error occuring in an iframe does not result in showing
780 // navigation corrections.
781 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
782 NavigateToURLAndWaitForTitle(
783 net::URLRequestMockHTTPJob::GetMockUrl(
784 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
785 "Blah",
787 // We expect to have two history entries, since we started off with navigation
788 // to "about:blank" and then navigated to "iframe_dns_error.html".
789 EXPECT_EQ(2,
790 browser()->tab_strip_model()->GetActiveWebContents()->
791 GetController().GetEntryCount());
792 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
795 // This test fails regularly on win_rel trybots. See crbug.com/121540
796 #if defined(OS_WIN)
797 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
798 #else
799 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
800 #endif
801 // Test that a DNS error occuring in an iframe does not result in an
802 // additional session history entry.
803 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
804 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
805 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
806 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
807 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
810 // This test fails regularly on win_rel trybots. See crbug.com/121540
812 // This fails on linux_aura bringup: http://crbug.com/163931
813 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
814 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
815 #else
816 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
817 #endif
818 // Test that a DNS error occuring in an iframe does not result in an
819 // additional session history entry.
820 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
821 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
822 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
823 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
824 GoForwardAndWaitForTitle("Blah", 1);
825 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
828 // Test that a DNS error occuring in an iframe, once the main document is
829 // completed loading, does not result in an additional session history entry.
830 // To ensure that the main document has completed loading, JavaScript is used to
831 // inject an iframe after loading is done.
832 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
833 content::WebContents* wc =
834 browser()->tab_strip_model()->GetActiveWebContents();
835 GURL fail_url =
836 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
838 // Load a regular web page, in which we will inject an iframe.
839 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
841 // We expect to have two history entries, since we started off with navigation
842 // to "about:blank" and then navigated to "title2.html".
843 EXPECT_EQ(2, wc->GetController().GetEntryCount());
845 std::string script = "var frame = document.createElement('iframe');"
846 "frame.src = '" + fail_url.spec() + "';"
847 "document.body.appendChild(frame);";
849 TestFailProvisionalLoadObserver fail_observer(wc);
850 content::WindowedNotificationObserver load_observer(
851 content::NOTIFICATION_LOAD_STOP,
852 content::Source<NavigationController>(&wc->GetController()));
853 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
854 load_observer.Wait();
856 // Ensure we saw the expected failure.
857 EXPECT_EQ(fail_url, fail_observer.fail_url());
859 // Failed initial navigation of an iframe shouldn't be adding any history
860 // entries.
861 EXPECT_EQ(2, wc->GetController().GetEntryCount());
864 // Do the same test, but with an iframe that doesn't have initial URL
865 // assigned.
866 script = "var frame = document.createElement('iframe');"
867 "frame.id = 'target_frame';"
868 "document.body.appendChild(frame);";
870 content::WindowedNotificationObserver load_observer(
871 content::NOTIFICATION_LOAD_STOP,
872 content::Source<NavigationController>(&wc->GetController()));
873 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
874 load_observer.Wait();
877 script = "var f = document.getElementById('target_frame');"
878 "f.src = '" + fail_url.spec() + "';";
880 TestFailProvisionalLoadObserver fail_observer(wc);
881 content::WindowedNotificationObserver load_observer(
882 content::NOTIFICATION_LOAD_STOP,
883 content::Source<NavigationController>(&wc->GetController()));
884 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
885 load_observer.Wait();
887 EXPECT_EQ(fail_url, fail_observer.fail_url());
888 EXPECT_EQ(2, wc->GetController().GetEntryCount());
890 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
893 // Checks that navigation corrections are not loaded when we receive an actual
894 // 404 page.
895 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
896 NavigateToURLAndWaitForTitle(
897 net::URLRequestMockHTTPJob::GetMockUrl(
898 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
899 "SUCCESS",
901 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
904 // Checks that when an error occurs, the stale cache status of the page
905 // is correctly transferred, and that stale cached copied can be loaded
906 // from the javascript.
907 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
908 ASSERT_TRUE(test_server()->Start());
909 // Load cache with entry with "nocache" set, to create stale
910 // cache.
911 GURL test_url(test_server()->GetURL("files/nocache.html"));
912 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
914 // Reload same URL after forcing an error from the the network layer;
915 // confirm that the error page is told the cached copy exists.
916 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
917 browser()->profile()->GetRequestContext();
918 BrowserThread::PostTask(
919 BrowserThread::IO, FROM_HERE,
920 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
921 net::ERR_FAILED));
923 // With no navigation corrections to load, there's only one navigation.
924 ui_test_utils::NavigateToURL(browser(), test_url);
925 EXPECT_TRUE(ProbeStaleCopyValue(true));
926 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
927 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
928 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
930 // Confirm that loading the stale copy from the cache works.
931 content::TestNavigationObserver same_tab_observer(
932 browser()->tab_strip_model()->GetActiveWebContents(), 1);
933 ASSERT_TRUE(ReloadStaleCopyFromCache());
934 same_tab_observer.Wait();
935 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
936 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
938 // Reload the same URL with a post request; confirm the error page is told
939 // that there is no cached copy.
940 ui_test_utils::NavigateToURLWithPost(browser(), test_url);
941 EXPECT_TRUE(ProbeStaleCopyValue(false));
942 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
943 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
945 // Clear the cache and reload the same URL; confirm the error page is told
946 // that there is no cached copy.
947 BrowsingDataRemover* remover =
948 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
949 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
950 BrowsingDataHelper::UNPROTECTED_WEB);
951 ui_test_utils::NavigateToURL(browser(), test_url);
952 EXPECT_TRUE(ProbeStaleCopyValue(false));
953 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
954 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
957 // Check that the easter egg is present and initialised and is not disabled.
958 IN_PROC_BROWSER_TEST_F(ErrorPageTest, CheckEasterEggIsNotDisabled) {
959 ui_test_utils::NavigateToURL(browser(),
960 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
962 content::WebContents* web_contents =
963 browser()->tab_strip_model()->GetActiveWebContents();
965 // Check for no disabled message container.
966 std::string command = base::StringPrintf(
967 "var hasDisableContainer = document.querySelectorAll('.snackbar').length;"
968 "domAutomationController.send(hasDisableContainer);");
969 int result;
970 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
971 web_contents, command, &result));
972 EXPECT_EQ(0, result);
974 // Presence of the canvas container.
975 command = base::StringPrintf(
976 "var runnerCanvas = document.querySelectorAll('.runner-canvas').length;"
977 "domAutomationController.send(runnerCanvas);");
978 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
979 web_contents, command, &result));
980 EXPECT_EQ(1, result);
983 class ErrorPageAutoReloadTest : public InProcessBrowserTest {
984 public:
985 void SetUpCommandLine(base::CommandLine* command_line) override {
986 command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
989 void InstallInterceptor(const GURL& url, int requests_to_fail) {
990 interceptor_ = new FailFirstNRequestsInterceptor(requests_to_fail);
991 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(interceptor_);
993 // Tests don't need to wait for this task to complete before using the
994 // filter; any requests that might be affected by it will end up in the IO
995 // thread's message loop after this posted task anyway.
997 // Ownership of the interceptor is passed to an object the IO thread, but a
998 // pointer is kept in the test fixture. As soon as anything calls
999 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
1000 BrowserThread::PostTask(
1001 BrowserThread::IO, FROM_HERE,
1002 base::Bind(&AddInterceptorForURL, url,
1003 base::Passed(&owned_interceptor)));
1006 void NavigateToURLAndWaitForTitle(const GURL& url,
1007 const std::string& expected_title,
1008 int num_navigations) {
1009 content::TitleWatcher title_watcher(
1010 browser()->tab_strip_model()->GetActiveWebContents(),
1011 base::ASCIIToUTF16(expected_title));
1013 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1014 browser(), url, num_navigations);
1016 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
1017 title_watcher.WaitAndGetTitle());
1020 FailFirstNRequestsInterceptor* interceptor() {
1021 return interceptor_;
1024 private:
1025 FailFirstNRequestsInterceptor* interceptor_;
1028 // Fails on official mac_trunk build. See crbug.com/465789.
1029 #if defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
1030 #define MAYBE_AutoReload DISABLED_AutoReload
1031 #else
1032 #define MAYBE_AutoReload AutoReload
1033 #endif
1034 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, MAYBE_AutoReload) {
1035 GURL test_url("http://error.page.auto.reload");
1036 const int kRequestsToFail = 2;
1037 InstallInterceptor(test_url, kRequestsToFail);
1038 NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
1039 // Note that the interceptor updates these variables on the IO thread,
1040 // but this function reads them on the main thread. The requests have to be
1041 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
1042 // this becomes racey.
1043 EXPECT_EQ(kRequestsToFail, interceptor()->failures());
1044 EXPECT_EQ(kRequestsToFail + 1, interceptor()->requests());
1047 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, ManualReloadNotSuppressed) {
1048 GURL test_url("http://error.page.auto.reload");
1049 const int kRequestsToFail = 3;
1050 InstallInterceptor(test_url, kRequestsToFail);
1051 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1052 browser(), test_url, 2);
1054 EXPECT_EQ(2, interceptor()->failures());
1055 EXPECT_EQ(2, interceptor()->requests());
1057 ToggleHelpBox(browser());
1058 EXPECT_TRUE(IsDisplayingText(browser(), "error.page.auto.reload"));
1060 content::WebContents* web_contents =
1061 browser()->tab_strip_model()->GetActiveWebContents();
1062 content::TestNavigationObserver nav_observer(web_contents, 1);
1063 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
1064 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
1065 nav_observer.Wait();
1066 EXPECT_FALSE(IsDisplayingText(browser(), "error.page.auto.reload"));
1069 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
1070 class AddressUnreachableInterceptor : public net::URLRequestInterceptor {
1071 public:
1072 AddressUnreachableInterceptor() {}
1073 ~AddressUnreachableInterceptor() override {}
1075 // net::URLRequestInterceptor:
1076 net::URLRequestJob* MaybeInterceptRequest(
1077 net::URLRequest* request,
1078 net::NetworkDelegate* network_delegate) const override {
1079 return new URLRequestFailedJob(request,
1080 network_delegate,
1081 net::ERR_ADDRESS_UNREACHABLE);
1084 private:
1085 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor);
1088 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
1089 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
1090 // a different error for the correction service and the original page to
1091 // validate the right page is being displayed.
1092 class ErrorPageNavigationCorrectionsFailTest : public ErrorPageTest {
1093 public:
1094 // InProcessBrowserTest:
1095 void SetUpOnMainThread() override {
1096 BrowserThread::PostTask(
1097 BrowserThread::IO, FROM_HERE,
1098 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters));
1101 void TearDownOnMainThread() override {
1102 BrowserThread::PostTask(
1103 BrowserThread::IO, FROM_HERE,
1104 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters));
1107 private:
1108 // Adds a filter that causes all correction service requests to fail with
1109 // ERR_ADDRESS_UNREACHABLE.
1111 // Also adds the net::URLRequestFailedJob filter.
1112 static void AddFilters() {
1113 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1114 URLRequestFailedJob::AddUrlHandler();
1116 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
1117 google_util::LinkDoctorBaseURL(),
1118 scoped_ptr<net::URLRequestInterceptor>(
1119 new AddressUnreachableInterceptor()));
1122 static void RemoveFilters() {
1123 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1124 net::URLRequestFilter::GetInstance()->ClearHandlers();
1128 // Make sure that when corrections fail to load, the network error page is
1129 // successfully loaded.
1130 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1131 FetchCorrectionsFails) {
1132 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1133 browser(),
1134 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
1137 // Verify that the expected error page is being displayed.
1138 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED);
1140 // Diagnostics button should be displayed, if avilable on this platform.
1141 EXPECT_EQ(PlatformSupportsDiagnosticsTool(),
1142 IsDisplayingDiagnosticsButton(browser()));
1145 // Checks that when an error occurs and a corrections fail to load, the stale
1146 // cache status of the page is correctly transferred, and we can load the
1147 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1148 // above.
1149 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1150 StaleCacheStatusFailedCorrections) {
1151 ASSERT_TRUE(test_server()->Start());
1152 // Load cache with entry with "nocache" set, to create stale
1153 // cache.
1154 GURL test_url(test_server()->GetURL("files/nocache.html"));
1155 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
1157 // Reload same URL after forcing an error from the the network layer;
1158 // confirm that the error page is told the cached copy exists.
1159 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1160 browser()->profile()->GetRequestContext();
1161 BrowserThread::PostTask(
1162 BrowserThread::IO, FROM_HERE,
1163 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
1164 net::ERR_CONNECTION_FAILED));
1166 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1167 browser(), test_url, 2);
1168 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1169 EXPECT_TRUE(ProbeStaleCopyValue(true));
1171 // Confirm that loading the stale copy from the cache works.
1172 content::TestNavigationObserver same_tab_observer(
1173 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1174 ASSERT_TRUE(ReloadStaleCopyFromCache());
1175 same_tab_observer.Wait();
1176 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1177 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1179 // Clear the cache and reload the same URL; confirm the error page is told
1180 // that there is no cached copy.
1181 BrowsingDataRemover* remover =
1182 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
1183 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1184 BrowsingDataHelper::UNPROTECTED_WEB);
1185 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1186 browser(), test_url, 2);
1187 EXPECT_TRUE(ProbeStaleCopyValue(false));
1188 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1191 #if defined(OS_CHROMEOS)
1192 class ErrorPageOfflineTest : public ErrorPageTest {
1193 protected:
1194 // Mock policy provider for both user and device policies.
1195 policy::MockConfigurationPolicyProvider policy_provider_;
1197 void SetUpInProcessBrowserTestFixture() override {
1198 // Set up fake install attributes.
1199 scoped_ptr<policy::StubEnterpriseInstallAttributes> attributes(
1200 new policy::StubEnterpriseInstallAttributes());
1201 attributes->SetDomain("example.com");
1202 attributes->SetRegistrationUser("user@example.com");
1203 policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
1204 attributes.release());
1206 // Sets up a mock policy provider for user and device policies.
1207 EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
1208 .WillRepeatedly(testing::Return(true));
1209 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
1210 &policy_provider_);
1212 ErrorPageTest::SetUpInProcessBrowserTestFixture();
1216 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest, CheckEasterEggIsDisabled) {
1217 // Check for enterprise enrollment.
1218 policy::BrowserPolicyConnectorChromeOS* connector =
1219 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1220 EXPECT_TRUE(connector->IsEnterpriseManaged());
1222 ui_test_utils::NavigateToURL(browser(),
1223 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
1225 content::WebContents* web_contents =
1226 browser()->tab_strip_model()->GetActiveWebContents();
1228 std::string command = base::StringPrintf(
1229 "var hasText = document.querySelector('.snackbar').innerText;"
1230 "domAutomationController.send(hasText);");
1231 std::string result = "";
1232 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1233 web_contents, command, &result));
1235 std::string disabled_text =
1236 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED);
1237 EXPECT_EQ(disabled_text, result);
1239 #endif
1241 // A test fixture that simulates failing requests for an IDN domain name.
1242 class ErrorPageForIDNTest : public InProcessBrowserTest {
1243 public:
1244 // Target hostname in different forms.
1245 static const char kHostname[];
1246 static const char kHostnameJSUnicode[];
1248 // InProcessBrowserTest:
1249 void SetUpOnMainThread() override {
1250 // Clear AcceptLanguages to force punycode decoding.
1251 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
1252 std::string());
1253 BrowserThread::PostTask(
1254 BrowserThread::IO, FROM_HERE,
1255 base::Bind(&ErrorPageForIDNTest::AddFilters));
1258 void TearDownOnMainThread() override {
1259 BrowserThread::PostTask(
1260 BrowserThread::IO, FROM_HERE,
1261 base::Bind(&ErrorPageForIDNTest::RemoveFilters));
1264 private:
1265 static void AddFilters() {
1266 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1267 URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
1270 static void RemoveFilters() {
1271 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1272 net::URLRequestFilter::GetInstance()->ClearHandlers();
1276 const char ErrorPageForIDNTest::kHostname[] =
1277 "xn--d1abbgf6aiiy.xn--p1ai";
1278 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
1279 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1280 "\\u0440\\u0444";
1282 // Make sure error page shows correct unicode for IDN.
1283 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
1284 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1285 ui_test_utils::NavigateToURL(
1286 browser(),
1287 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
1288 kHostname));
1290 ToggleHelpBox(browser());
1291 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode));
1294 } // namespace