Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / errorpage_browsertest.cc
blob9f1dc791669703453b13fb82ebc14ac21b8f674d
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/net/url_request_mock_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/search_engines/ui_thread_search_terms_data.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/grit/generated_resources.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "components/google/core/browser/google_util.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_observer.h"
38 #include "content/public/test/browser_test_utils.h"
39 #include "content/public/test/test_navigation_observer.h"
40 #include "net/base/net_errors.h"
41 #include "net/base/net_util.h"
42 #include "net/http/failing_http_transaction_factory.h"
43 #include "net/http/http_cache.h"
44 #include "net/test/spawned_test_server/spawned_test_server.h"
45 #include "net/test/url_request/url_request_failed_job.h"
46 #include "net/test/url_request/url_request_mock_http_job.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 #if defined(OS_CHROMEOS)
57 #include "chrome/browser/browser_process.h"
58 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
59 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
60 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
61 #include "chrome/grit/generated_resources.h"
62 #include "components/policy/core/common/mock_configuration_policy_provider.h"
63 #include "components/policy/core/common/policy_types.h"
64 #include "content/public/test/browser_test_utils.h"
65 #include "ui/base/l10n/l10n_util.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 // Checks that the local error page is being displayed, without remotely
106 // retrieved navigation corrections, and with the specified error code.
107 void ExpectDisplayingLocalErrorPage(Browser* browser, net::Error error_code) {
108 // Expand the help box so innerText will include text below the fold.
109 ToggleHelpBox(browser);
111 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
113 // Locally generated error pages should not have navigation corrections.
114 EXPECT_FALSE(IsDisplayingText(browser, "http://correction1/"));
115 EXPECT_FALSE(IsDisplayingText(browser, "http://correction2/"));
117 // Locally generated error pages should not have a populated search box.
118 bool search_box_populated = false;
119 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
120 browser->tab_strip_model()->GetActiveWebContents(),
121 "var searchText = document.getElementById('search-box').value;"
122 "domAutomationController.send(searchText == 'search query');",
123 &search_box_populated));
124 EXPECT_FALSE(search_box_populated);
127 // Checks that an error page with information retrieved from the navigation
128 // correction service is being displayed, with the specified specified error
129 // code.
130 void ExpectDisplayingNavigationCorrections(Browser* browser,
131 net::Error error_code) {
132 // Expand the help box so innerText will include text below the fold.
133 ToggleHelpBox(browser);
135 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
137 // Check that the mock navigation corrections are displayed.
138 EXPECT_TRUE(IsDisplayingText(browser, "http://correction1/"));
139 EXPECT_TRUE(IsDisplayingText(browser, "http://correction2/"));
141 // Check that the search box is populated correctly.
142 bool search_box_populated = false;
143 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
144 browser->tab_strip_model()->GetActiveWebContents(),
145 "var searchText = document.getElementById('search-box').value;"
146 "domAutomationController.send(searchText == 'search query');",
147 &search_box_populated));
148 EXPECT_TRUE(search_box_populated);
151 std::string GetShowSavedButtonLabel() {
152 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY);
155 void AddInterceptorForURL(
156 const GURL& url,
157 scoped_ptr<net::URLRequestInterceptor> handler) {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
159 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
160 url, handler.Pass());
163 // An interceptor that fails a configurable number of requests, then succeeds
164 // all requests after that, keeping count of failures and successes.
165 class FailFirstNRequestsInterceptor : public net::URLRequestInterceptor {
166 public:
167 explicit FailFirstNRequestsInterceptor(int requests_to_fail)
168 : requests_(0), failures_(0), requests_to_fail_(requests_to_fail) {}
169 ~FailFirstNRequestsInterceptor() override {}
171 // net::URLRequestInterceptor implementation
172 net::URLRequestJob* MaybeInterceptRequest(
173 net::URLRequest* request,
174 net::NetworkDelegate* network_delegate) const override {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
176 requests_++;
177 if (failures_ < requests_to_fail_) {
178 failures_++;
179 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
180 // NetErrorHelperCore::GetErrorPageURL.
181 return new URLRequestFailedJob(request,
182 network_delegate,
183 net::ERR_CONNECTION_RESET);
184 } else {
185 return new URLRequestTestJob(request, network_delegate,
186 URLRequestTestJob::test_headers(),
187 URLRequestTestJob::test_data_1(),
188 true);
192 int requests() const { return requests_; }
193 int failures() const { return failures_; }
195 private:
196 // These are mutable because MaybeCreateJob is const but we want this state
197 // for testing.
198 mutable int requests_;
199 mutable int failures_;
200 int requests_to_fail_;
202 DISALLOW_COPY_AND_ASSIGN(FailFirstNRequestsInterceptor);
205 // An interceptor that serves LinkDoctor responses. It also allows waiting
206 // until a certain number of requests have been sent.
207 // TODO(mmenke): Wait until responses have been received instead.
208 class LinkDoctorInterceptor : public net::URLRequestInterceptor {
209 public:
210 LinkDoctorInterceptor() : num_requests_(0),
211 requests_to_wait_for_(-1),
212 weak_factory_(this) {
215 ~LinkDoctorInterceptor() override {}
217 // net::URLRequestInterceptor implementation
218 net::URLRequestJob* MaybeInterceptRequest(
219 net::URLRequest* request,
220 net::NetworkDelegate* network_delegate) const override {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
223 BrowserThread::PostTask(
224 BrowserThread::UI, FROM_HERE,
225 base::Bind(&LinkDoctorInterceptor::RequestCreated,
226 weak_factory_.GetWeakPtr()));
228 base::FilePath root_http;
229 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
230 return new net::URLRequestMockHTTPJob(
231 request,
232 network_delegate,
233 root_http.AppendASCII("mock-link-doctor.json"),
234 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
235 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
238 void WaitForRequests(int requests_to_wait_for) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 DCHECK_EQ(-1, requests_to_wait_for_);
241 DCHECK(!run_loop_);
243 if (requests_to_wait_for >= num_requests_)
244 return;
246 requests_to_wait_for_ = requests_to_wait_for;
247 run_loop_.reset(new base::RunLoop());
248 run_loop_->Run();
249 run_loop_.reset();
250 requests_to_wait_for_ = -1;
251 EXPECT_EQ(num_requests_, requests_to_wait_for);
254 // It is up to the caller to wait until all relevant requests has been
255 // created, either through calling WaitForRequests or some other manner,
256 // before calling this method.
257 int num_requests() const {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
259 return num_requests_;
262 private:
263 void RequestCreated() {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 num_requests_++;
267 if (num_requests_ == requests_to_wait_for_)
268 run_loop_->Quit();
271 // These are only used on the UI thread.
272 int num_requests_;
273 int requests_to_wait_for_;
274 scoped_ptr<base::RunLoop> run_loop_;
276 // This prevents any risk of flake if any test doesn't wait for a request
277 // it sent. Mutable so it can be accessed from a const function.
278 mutable base::WeakPtrFactory<LinkDoctorInterceptor> weak_factory_;
280 DISALLOW_COPY_AND_ASSIGN(LinkDoctorInterceptor);
283 void InstallMockInterceptors(
284 const GURL& search_url,
285 scoped_ptr<net::URLRequestInterceptor> link_doctor_interceptor) {
286 chrome_browser_net::SetUrlRequestMocksEnabled(true);
288 AddInterceptorForURL(google_util::LinkDoctorBaseURL(),
289 link_doctor_interceptor.Pass());
291 // Add a mock for the search engine the error page will use.
292 base::FilePath root_http;
293 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
294 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
295 search_url.scheme(), search_url.host(),
296 net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
297 root_http.AppendASCII("title3.html"),
298 BrowserThread::GetBlockingPool()));
301 class ErrorPageTest : public InProcessBrowserTest {
302 public:
303 enum HistoryNavigationDirection {
304 HISTORY_NAVIGATE_BACK,
305 HISTORY_NAVIGATE_FORWARD,
308 ErrorPageTest() : link_doctor_interceptor_(NULL) {}
309 ~ErrorPageTest() override {}
311 // Navigates the active tab to a mock url created for the file at |file_path|.
312 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
313 void SetUpCommandLine(base::CommandLine* command_line) override {
314 command_line->AppendSwitchASCII(switches::kShowSavedCopy,
315 switches::kEnableShowSavedCopyPrimary);
318 // Navigates the active tab to a mock url created for the file at |file_path|.
319 void NavigateToFileURL(const base::FilePath::StringType& file_path) {
320 ui_test_utils::NavigateToURL(
321 browser(),
322 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path)));
325 // Navigates to the given URL and waits for |num_navigations| to occur, and
326 // the title to change to |expected_title|.
327 void NavigateToURLAndWaitForTitle(const GURL& url,
328 const std::string& expected_title,
329 int num_navigations) {
330 content::TitleWatcher title_watcher(
331 browser()->tab_strip_model()->GetActiveWebContents(),
332 base::ASCIIToUTF16(expected_title));
334 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
335 browser(), url, num_navigations);
337 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
338 title_watcher.WaitAndGetTitle());
341 // Navigates back in the history and waits for |num_navigations| to occur, and
342 // the title to change to |expected_title|.
343 void GoBackAndWaitForTitle(const std::string& expected_title,
344 int num_navigations) {
345 NavigateHistoryAndWaitForTitle(expected_title,
346 num_navigations,
347 HISTORY_NAVIGATE_BACK);
350 // Navigates forward in the history and waits for |num_navigations| to occur,
351 // and the title to change to |expected_title|.
352 void GoForwardAndWaitForTitle(const std::string& expected_title,
353 int num_navigations) {
354 NavigateHistoryAndWaitForTitle(expected_title,
355 num_navigations,
356 HISTORY_NAVIGATE_FORWARD);
359 void GoBackAndWaitForNavigations(int num_navigations) {
360 NavigateHistory(num_navigations, HISTORY_NAVIGATE_BACK);
363 void GoForwardAndWaitForNavigations(int num_navigations) {
364 NavigateHistory(num_navigations, HISTORY_NAVIGATE_FORWARD);
367 // Confirms that the javascript variable indicating whether or not we have
368 // a stale copy in the cache has been set to |expected|, and that the
369 // stale load button is or isn't there based on the same expectation.
370 testing::AssertionResult ProbeStaleCopyValue(bool expected) {
371 const char* js_cache_probe =
372 "try {\n"
373 " domAutomationController.send(\n"
374 " loadTimeData.valueExists('showSavedCopyButton') ?"
375 " 'yes' : 'no');\n"
376 "} catch (e) {\n"
377 " domAutomationController.send(e.message);\n"
378 "}\n";
380 std::string result;
381 bool ret =
382 content::ExecuteScriptAndExtractString(
383 browser()->tab_strip_model()->GetActiveWebContents(),
384 js_cache_probe,
385 &result);
386 if (!ret) {
387 return testing::AssertionFailure()
388 << "Failing return from ExecuteScriptAndExtractString.";
391 if ((expected && "yes" == result) || (!expected && "no" == result))
392 return testing::AssertionSuccess();
394 return testing::AssertionFailure() << "Cache probe result is " << result;
397 testing::AssertionResult ReloadStaleCopyFromCache() {
398 const char* js_reload_script =
399 "try {\n"
400 " document.getElementById('show-saved-copy-button').click();\n"
401 " domAutomationController.send('success');\n"
402 "} catch (e) {\n"
403 " domAutomationController.send(e.message);\n"
404 "}\n";
406 std::string result;
407 bool ret = content::ExecuteScriptAndExtractString(
408 browser()->tab_strip_model()->GetActiveWebContents(),
409 js_reload_script,
410 &result);
411 EXPECT_TRUE(ret);
412 if (!ret)
413 return testing::AssertionFailure();
414 return ("success" == result ? testing::AssertionSuccess() :
415 (testing::AssertionFailure() << "Exception message is " << result));
418 LinkDoctorInterceptor* link_doctor_interceptor() {
419 return link_doctor_interceptor_;
422 protected:
423 void SetUpOnMainThread() override {
424 link_doctor_interceptor_ = new LinkDoctorInterceptor();
425 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(
426 link_doctor_interceptor_);
427 // Ownership of the |interceptor_| is passed to an object the IO thread, but
428 // a pointer is kept in the test fixture. As soon as anything calls
429 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
430 UIThreadSearchTermsData search_terms_data(browser()->profile());
431 BrowserThread::PostTask(
432 BrowserThread::IO, FROM_HERE,
433 base::Bind(&InstallMockInterceptors,
434 GURL(search_terms_data.GoogleBaseURLValue()),
435 base::Passed(&owned_interceptor)));
438 // Returns a GURL that results in a DNS error.
439 GURL GetDnsErrorURL() const {
440 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
443 private:
444 // Navigates the browser the indicated direction in the history and waits for
445 // |num_navigations| to occur and the title to change to |expected_title|.
446 void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
447 int num_navigations,
448 HistoryNavigationDirection direction) {
449 content::TitleWatcher title_watcher(
450 browser()->tab_strip_model()->GetActiveWebContents(),
451 base::ASCIIToUTF16(expected_title));
453 NavigateHistory(num_navigations, direction);
455 EXPECT_EQ(title_watcher.WaitAndGetTitle(),
456 base::ASCIIToUTF16(expected_title));
459 void NavigateHistory(int num_navigations,
460 HistoryNavigationDirection direction) {
461 content::TestNavigationObserver test_navigation_observer(
462 browser()->tab_strip_model()->GetActiveWebContents(),
463 num_navigations);
464 if (direction == HISTORY_NAVIGATE_BACK) {
465 chrome::GoBack(browser(), CURRENT_TAB);
466 } else if (direction == HISTORY_NAVIGATE_FORWARD) {
467 chrome::GoForward(browser(), CURRENT_TAB);
468 } else {
469 FAIL();
471 test_navigation_observer.Wait();
474 LinkDoctorInterceptor* link_doctor_interceptor_;
477 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
478 public:
479 explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
480 : content::WebContentsObserver(contents) {}
481 ~TestFailProvisionalLoadObserver() override {}
483 // This method is invoked when the provisional load failed.
484 void DidFailProvisionalLoad(
485 content::RenderFrameHost* render_frame_host,
486 const GURL& validated_url,
487 int error_code,
488 const base::string16& error_description,
489 bool was_ignored_by_handler) override {
490 fail_url_ = validated_url;
493 const GURL& fail_url() const { return fail_url_; }
495 private:
496 GURL fail_url_;
498 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
501 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
502 net::Error error) {
503 DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
504 net::HttpCache* cache(
505 getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
506 DCHECK(cache);
507 scoped_ptr<net::HttpTransactionFactory> factory(
508 new net::FailingHttpTransactionFactory(cache->GetSession(), error));
509 // Throw away old version; since this is a a browser test, we don't
510 // need to restore the old state.
511 cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
514 // Test that a DNS error occuring in the main frame redirects to an error page.
515 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_Basic) {
516 // The first navigation should fail, and the second one should be the error
517 // page.
518 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
519 browser(), GetDnsErrorURL(), 2);
520 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
521 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
524 // Test that a DNS error occuring in the main frame does not result in an
525 // additional session history entry.
526 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack1) {
527 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
528 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
529 browser(), GetDnsErrorURL(), 2);
530 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
531 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
532 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
535 // Test that a DNS error occuring in the main frame does not result in an
536 // additional session history entry.
537 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
538 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
540 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
541 browser(), GetDnsErrorURL(), 2);
542 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
543 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
545 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
547 GoBackAndWaitForNavigations(2);
548 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
549 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
551 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
552 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
555 // Test that a DNS error occuring in the main frame does not result in an
556 // additional session history entry.
557 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
558 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
560 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
561 browser(), GetDnsErrorURL(), 2);
562 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
563 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
565 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
567 GoBackAndWaitForNavigations(2);
568 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
569 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
571 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
573 GoForwardAndWaitForNavigations(2);
574 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
575 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
578 // Test that a DNS error occuring in the main frame does not result in an
579 // additional session history entry.
580 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
581 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
583 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
584 browser(), GetDnsErrorURL(), 2);
585 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
586 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
588 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
590 GoBackAndWaitForNavigations(2);
591 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
592 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
594 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
596 GoForwardAndWaitForNavigations(2);
597 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
598 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
600 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
601 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
604 // Test that the search button on a DNS error page works.
605 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoSearch) {
606 // The first navigation should fail, and the second one should be the error
607 // page.
608 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
609 browser(), GetDnsErrorURL(), 2);
610 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
611 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
613 content::WebContents* web_contents =
614 browser()->tab_strip_model()->GetActiveWebContents();
616 // Do a search and make sure the browser ends up at the right page.
617 content::TestNavigationObserver nav_observer(web_contents, 1);
618 content::TitleWatcher title_watcher(
619 web_contents,
620 base::ASCIIToUTF16("Title Of More Awesomeness"));
621 // Can't use content::ExecuteScript because it waits for scripts to send
622 // notification that they've run, and scripts that trigger a navigation may
623 // not send that notification.
624 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
625 base::ASCIIToUTF16("document.getElementById('search-button').click();"));
626 nav_observer.Wait();
627 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
628 title_watcher.WaitAndGetTitle());
630 // There should have been another Link Doctor request, for tracking purposes.
631 // Have to wait for it, since the search page does not depend on having
632 // sent the tracking request.
633 link_doctor_interceptor()->WaitForRequests(2);
634 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
636 // Check the path and query string.
637 std::string url;
638 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
639 browser()->tab_strip_model()->GetActiveWebContents(),
640 "domAutomationController.send(window.location.href);",
641 &url));
642 EXPECT_EQ("/search", GURL(url).path());
643 EXPECT_EQ("q=search%20query", GURL(url).query());
645 // Go back to the error page, to make sure the history is correct.
646 GoBackAndWaitForNavigations(2);
647 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
648 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
651 // Test that the reload button on a DNS error page works.
652 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoReload) {
653 // The first navigation should fail, and the second one should be the error
654 // page.
655 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
656 browser(), GetDnsErrorURL(), 2);
657 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
658 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
660 content::WebContents* web_contents =
661 browser()->tab_strip_model()->GetActiveWebContents();
663 // Clicking the reload button should load the error page again, and there
664 // should be two commits, as before.
665 content::TestNavigationObserver nav_observer(web_contents, 2);
666 // Can't use content::ExecuteScript because it waits for scripts to send
667 // notification that they've run, and scripts that trigger a navigation may
668 // not send that notification.
669 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
670 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
671 nav_observer.Wait();
672 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
674 // There should have two more requests to the correction service: One for the
675 // new error page, and one for tracking purposes. Have to make sure to wait
676 // for the tracking request, since the new error page does not depend on it.
677 link_doctor_interceptor()->WaitForRequests(3);
678 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
681 // Test that clicking links on a DNS error page works.
682 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoClickLink) {
683 // The first navigation should fail, and the second one should be the error
684 // page.
685 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
686 browser(), GetDnsErrorURL(), 2);
687 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
688 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
690 content::WebContents* web_contents =
691 browser()->tab_strip_model()->GetActiveWebContents();
693 // Simulate a click on a link.
695 content::TitleWatcher title_watcher(
696 web_contents,
697 base::ASCIIToUTF16("Title Of Awesomeness"));
698 std::string link_selector =
699 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
700 // The tracking request is triggered by onmousedown, so it catches middle
701 // mouse button clicks, as well as left clicks.
702 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
703 base::ASCIIToUTF16(link_selector + ".onmousedown();"));
704 // Can't use content::ExecuteScript because it waits for scripts to send
705 // notification that they've run, and scripts that trigger a navigation may
706 // not send that notification.
707 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
708 base::ASCIIToUTF16(link_selector + ".click();"));
709 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
710 title_watcher.WaitAndGetTitle());
712 // There should have been a tracking request to the correction service. Have
713 // to make sure to wait the tracking request, since the new page does not
714 // depend on it.
715 link_doctor_interceptor()->WaitForRequests(2);
716 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
719 // Test that a DNS error occuring in an iframe does not result in showing
720 // navigation corrections.
721 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
722 NavigateToURLAndWaitForTitle(
723 net::URLRequestMockHTTPJob::GetMockUrl(
724 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
725 "Blah",
727 // We expect to have two history entries, since we started off with navigation
728 // to "about:blank" and then navigated to "iframe_dns_error.html".
729 EXPECT_EQ(2,
730 browser()->tab_strip_model()->GetActiveWebContents()->
731 GetController().GetEntryCount());
732 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
735 // This test fails regularly on win_rel trybots. See crbug.com/121540
736 #if defined(OS_WIN)
737 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
738 #else
739 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
740 #endif
741 // Test that a DNS error occuring in an iframe does not result in an
742 // additional session history entry.
743 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
744 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
745 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
746 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
747 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
750 // This test fails regularly on win_rel trybots. See crbug.com/121540
752 // This fails on linux_aura bringup: http://crbug.com/163931
753 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
754 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
755 #else
756 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
757 #endif
758 // Test that a DNS error occuring in an iframe does not result in an
759 // additional session history entry.
760 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
761 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
762 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
763 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
764 GoForwardAndWaitForTitle("Blah", 1);
765 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
768 // Test that a DNS error occuring in an iframe, once the main document is
769 // completed loading, does not result in an additional session history entry.
770 // To ensure that the main document has completed loading, JavaScript is used to
771 // inject an iframe after loading is done.
772 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
773 content::WebContents* wc =
774 browser()->tab_strip_model()->GetActiveWebContents();
775 GURL fail_url =
776 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
778 // Load a regular web page, in which we will inject an iframe.
779 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
781 // We expect to have two history entries, since we started off with navigation
782 // to "about:blank" and then navigated to "title2.html".
783 EXPECT_EQ(2, wc->GetController().GetEntryCount());
785 std::string script = "var frame = document.createElement('iframe');"
786 "frame.src = '" + fail_url.spec() + "';"
787 "document.body.appendChild(frame);";
789 TestFailProvisionalLoadObserver fail_observer(wc);
790 content::WindowedNotificationObserver load_observer(
791 content::NOTIFICATION_LOAD_STOP,
792 content::Source<NavigationController>(&wc->GetController()));
793 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
794 load_observer.Wait();
796 // Ensure we saw the expected failure.
797 EXPECT_EQ(fail_url, fail_observer.fail_url());
799 // Failed initial navigation of an iframe shouldn't be adding any history
800 // entries.
801 EXPECT_EQ(2, wc->GetController().GetEntryCount());
804 // Do the same test, but with an iframe that doesn't have initial URL
805 // assigned.
806 script = "var frame = document.createElement('iframe');"
807 "frame.id = 'target_frame';"
808 "document.body.appendChild(frame);";
810 content::WindowedNotificationObserver load_observer(
811 content::NOTIFICATION_LOAD_STOP,
812 content::Source<NavigationController>(&wc->GetController()));
813 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
814 load_observer.Wait();
817 script = "var f = document.getElementById('target_frame');"
818 "f.src = '" + fail_url.spec() + "';";
820 TestFailProvisionalLoadObserver fail_observer(wc);
821 content::WindowedNotificationObserver load_observer(
822 content::NOTIFICATION_LOAD_STOP,
823 content::Source<NavigationController>(&wc->GetController()));
824 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
825 load_observer.Wait();
827 EXPECT_EQ(fail_url, fail_observer.fail_url());
828 EXPECT_EQ(2, wc->GetController().GetEntryCount());
830 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
833 // Checks that navigation corrections are not loaded when we receive an actual
834 // 404 page.
835 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
836 NavigateToURLAndWaitForTitle(
837 net::URLRequestMockHTTPJob::GetMockUrl(
838 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
839 "SUCCESS",
841 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
844 // Checks that when an error occurs, the stale cache status of the page
845 // is correctly transferred, and that stale cached copied can be loaded
846 // from the javascript.
847 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
848 ASSERT_TRUE(test_server()->Start());
849 // Load cache with entry with "nocache" set, to create stale
850 // cache.
851 GURL test_url(test_server()->GetURL("files/nocache.html"));
852 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
854 // Reload same URL after forcing an error from the the network layer;
855 // confirm that the error page is told the cached copy exists.
856 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
857 browser()->profile()->GetRequestContext();
858 BrowserThread::PostTask(
859 BrowserThread::IO, FROM_HERE,
860 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
861 net::ERR_FAILED));
863 // With no navigation corrections to load, there's only one navigation.
864 ui_test_utils::NavigateToURL(browser(), test_url);
865 EXPECT_TRUE(ProbeStaleCopyValue(true));
866 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
867 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
868 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
870 // Confirm that loading the stale copy from the cache works.
871 content::TestNavigationObserver same_tab_observer(
872 browser()->tab_strip_model()->GetActiveWebContents(), 1);
873 ASSERT_TRUE(ReloadStaleCopyFromCache());
874 same_tab_observer.Wait();
875 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
876 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
878 // Reload the same URL with a post request; confirm the error page is told
879 // that there is no cached copy.
880 ui_test_utils::NavigateToURLWithPost(browser(), test_url);
881 EXPECT_TRUE(ProbeStaleCopyValue(false));
882 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
883 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
885 // Clear the cache and reload the same URL; confirm the error page is told
886 // that there is no cached copy.
887 BrowsingDataRemover* remover =
888 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
889 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
890 BrowsingDataHelper::UNPROTECTED_WEB);
891 ui_test_utils::NavigateToURL(browser(), test_url);
892 EXPECT_TRUE(ProbeStaleCopyValue(false));
893 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
894 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
897 // Check that the easter egg is present and initialised and is not disabled.
898 IN_PROC_BROWSER_TEST_F(ErrorPageTest, CheckEasterEggIsNotDisabled) {
899 ui_test_utils::NavigateToURL(browser(),
900 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
902 content::WebContents* web_contents =
903 browser()->tab_strip_model()->GetActiveWebContents();
905 // Check for no disabled message container.
906 std::string command = base::StringPrintf(
907 "var hasDisableContainer = document.querySelectorAll('.snackbar').length;"
908 "domAutomationController.send(hasDisableContainer);");
909 int result;
910 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
911 web_contents, command, &result));
912 EXPECT_EQ(0, result);
914 // Presence of the canvas container.
915 command = base::StringPrintf(
916 "var runnerCanvas = document.querySelectorAll('.runner-canvas').length;"
917 "domAutomationController.send(runnerCanvas);");
918 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
919 web_contents, command, &result));
920 EXPECT_EQ(1, result);
923 class ErrorPageAutoReloadTest : public InProcessBrowserTest {
924 public:
925 void SetUpCommandLine(base::CommandLine* command_line) override {
926 command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
929 void InstallInterceptor(const GURL& url, int requests_to_fail) {
930 interceptor_ = new FailFirstNRequestsInterceptor(requests_to_fail);
931 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(interceptor_);
933 // Tests don't need to wait for this task to complete before using the
934 // filter; any requests that might be affected by it will end up in the IO
935 // thread's message loop after this posted task anyway.
937 // Ownership of the interceptor is passed to an object the IO thread, but a
938 // pointer is kept in the test fixture. As soon as anything calls
939 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
940 BrowserThread::PostTask(
941 BrowserThread::IO, FROM_HERE,
942 base::Bind(&AddInterceptorForURL, url,
943 base::Passed(&owned_interceptor)));
946 void NavigateToURLAndWaitForTitle(const GURL& url,
947 const std::string& expected_title,
948 int num_navigations) {
949 content::TitleWatcher title_watcher(
950 browser()->tab_strip_model()->GetActiveWebContents(),
951 base::ASCIIToUTF16(expected_title));
953 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
954 browser(), url, num_navigations);
956 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
957 title_watcher.WaitAndGetTitle());
960 FailFirstNRequestsInterceptor* interceptor() {
961 return interceptor_;
964 private:
965 FailFirstNRequestsInterceptor* interceptor_;
968 // Fails on official mac_trunk build. See crbug.com/465789.
969 #if defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
970 #define MAYBE_AutoReload DISABLED_AutoReload
971 #else
972 #define MAYBE_AutoReload AutoReload
973 #endif
974 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, MAYBE_AutoReload) {
975 GURL test_url("http://error.page.auto.reload");
976 const int kRequestsToFail = 2;
977 InstallInterceptor(test_url, kRequestsToFail);
978 NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
979 // Note that the interceptor updates these variables on the IO thread,
980 // but this function reads them on the main thread. The requests have to be
981 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
982 // this becomes racey.
983 EXPECT_EQ(kRequestsToFail, interceptor()->failures());
984 EXPECT_EQ(kRequestsToFail + 1, interceptor()->requests());
987 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, ManualReloadNotSuppressed) {
988 GURL test_url("http://error.page.auto.reload");
989 const int kRequestsToFail = 3;
990 InstallInterceptor(test_url, kRequestsToFail);
991 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
992 browser(), test_url, 2);
994 EXPECT_EQ(2, interceptor()->failures());
995 EXPECT_EQ(2, interceptor()->requests());
997 ToggleHelpBox(browser());
998 EXPECT_TRUE(IsDisplayingText(browser(), "error.page.auto.reload"));
1000 content::WebContents* web_contents =
1001 browser()->tab_strip_model()->GetActiveWebContents();
1002 content::TestNavigationObserver nav_observer(web_contents, 1);
1003 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
1004 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
1005 nav_observer.Wait();
1006 EXPECT_FALSE(IsDisplayingText(browser(), "error.page.auto.reload"));
1009 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
1010 class AddressUnreachableInterceptor : public net::URLRequestInterceptor {
1011 public:
1012 AddressUnreachableInterceptor() {}
1013 ~AddressUnreachableInterceptor() override {}
1015 // net::URLRequestInterceptor:
1016 net::URLRequestJob* MaybeInterceptRequest(
1017 net::URLRequest* request,
1018 net::NetworkDelegate* network_delegate) const override {
1019 return new URLRequestFailedJob(request,
1020 network_delegate,
1021 net::ERR_ADDRESS_UNREACHABLE);
1024 private:
1025 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor);
1028 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
1029 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
1030 // a different error for the correction service and the original page to
1031 // validate the right page is being displayed.
1032 class ErrorPageNavigationCorrectionsFailTest : public ErrorPageTest {
1033 public:
1034 // InProcessBrowserTest:
1035 void SetUpOnMainThread() override {
1036 BrowserThread::PostTask(
1037 BrowserThread::IO, FROM_HERE,
1038 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters));
1041 void TearDownOnMainThread() override {
1042 BrowserThread::PostTask(
1043 BrowserThread::IO, FROM_HERE,
1044 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters));
1047 private:
1048 // Adds a filter that causes all correction service requests to fail with
1049 // ERR_ADDRESS_UNREACHABLE.
1051 // Also adds the net::URLRequestFailedJob filter.
1052 static void AddFilters() {
1053 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1054 URLRequestFailedJob::AddUrlHandler();
1056 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
1057 google_util::LinkDoctorBaseURL(),
1058 scoped_ptr<net::URLRequestInterceptor>(
1059 new AddressUnreachableInterceptor()));
1062 static void RemoveFilters() {
1063 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1064 net::URLRequestFilter::GetInstance()->ClearHandlers();
1068 // Make sure that when corrections fail to load, the network error page is
1069 // successfully loaded.
1070 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1071 FetchCorrectionsFails) {
1072 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1073 browser(),
1074 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
1077 // Verify that the expected error page is being displayed.
1078 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED);
1081 // Checks that when an error occurs and a corrections fail to load, the stale
1082 // cache status of the page is correctly transferred, and we can load the
1083 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1084 // above.
1085 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1086 StaleCacheStatusFailedCorrections) {
1087 ASSERT_TRUE(test_server()->Start());
1088 // Load cache with entry with "nocache" set, to create stale
1089 // cache.
1090 GURL test_url(test_server()->GetURL("files/nocache.html"));
1091 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
1093 // Reload same URL after forcing an error from the the network layer;
1094 // confirm that the error page is told the cached copy exists.
1095 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1096 browser()->profile()->GetRequestContext();
1097 BrowserThread::PostTask(
1098 BrowserThread::IO, FROM_HERE,
1099 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
1100 net::ERR_CONNECTION_FAILED));
1102 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1103 browser(), test_url, 2);
1104 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1105 EXPECT_TRUE(ProbeStaleCopyValue(true));
1107 // Confirm that loading the stale copy from the cache works.
1108 content::TestNavigationObserver same_tab_observer(
1109 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1110 ASSERT_TRUE(ReloadStaleCopyFromCache());
1111 same_tab_observer.Wait();
1112 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1113 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1115 // Clear the cache and reload the same URL; confirm the error page is told
1116 // that there is no cached copy.
1117 BrowsingDataRemover* remover =
1118 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
1119 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1120 BrowsingDataHelper::UNPROTECTED_WEB);
1121 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1122 browser(), test_url, 2);
1123 EXPECT_TRUE(ProbeStaleCopyValue(false));
1124 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1127 #if defined(OS_CHROMEOS)
1128 class ErrorPageOfflineTest : public ErrorPageTest {
1129 protected:
1130 // Mock policy provider for both user and device policies.
1131 policy::MockConfigurationPolicyProvider policy_provider_;
1133 void SetUpInProcessBrowserTestFixture() override {
1134 // Set up fake install attributes.
1135 scoped_ptr<policy::StubEnterpriseInstallAttributes> attributes(
1136 new policy::StubEnterpriseInstallAttributes());
1137 attributes->SetDomain("example.com");
1138 attributes->SetRegistrationUser("user@example.com");
1139 policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
1140 attributes.release());
1142 // Sets up a mock policy provider for user and device policies.
1143 EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
1144 .WillRepeatedly(testing::Return(true));
1145 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
1146 &policy_provider_);
1148 ErrorPageTest::SetUpInProcessBrowserTestFixture();
1152 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest, CheckEasterEggIsDisabled) {
1153 // Check for enterprise enrollment.
1154 policy::BrowserPolicyConnectorChromeOS* connector =
1155 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1156 EXPECT_TRUE(connector->IsEnterpriseManaged());
1158 ui_test_utils::NavigateToURL(browser(),
1159 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
1161 content::WebContents* web_contents =
1162 browser()->tab_strip_model()->GetActiveWebContents();
1164 std::string command = base::StringPrintf(
1165 "var hasText = document.querySelector('.snackbar').innerText;"
1166 "domAutomationController.send(hasText);");
1167 std::string result = "";
1168 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1169 web_contents, command, &result));
1171 std::string disabled_text =
1172 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED);
1173 EXPECT_EQ(disabled_text, result);
1175 #endif
1177 // A test fixture that simulates failing requests for an IDN domain name.
1178 class ErrorPageForIDNTest : public InProcessBrowserTest {
1179 public:
1180 // Target hostname in different forms.
1181 static const char kHostname[];
1182 static const char kHostnameJSUnicode[];
1184 // InProcessBrowserTest:
1185 void SetUpOnMainThread() override {
1186 // Clear AcceptLanguages to force punycode decoding.
1187 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
1188 std::string());
1189 BrowserThread::PostTask(
1190 BrowserThread::IO, FROM_HERE,
1191 base::Bind(&ErrorPageForIDNTest::AddFilters));
1194 void TearDownOnMainThread() override {
1195 BrowserThread::PostTask(
1196 BrowserThread::IO, FROM_HERE,
1197 base::Bind(&ErrorPageForIDNTest::RemoveFilters));
1200 private:
1201 static void AddFilters() {
1202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1203 URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
1206 static void RemoveFilters() {
1207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1208 net::URLRequestFilter::GetInstance()->ClearHandlers();
1212 const char ErrorPageForIDNTest::kHostname[] =
1213 "xn--d1abbgf6aiiy.xn--p1ai";
1214 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
1215 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1216 "\\u0440\\u0444";
1218 // Make sure error page shows correct unicode for IDN.
1219 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
1220 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1221 ui_test_utils::NavigateToURL(
1222 browser(),
1223 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
1224 kHostname));
1226 ToggleHelpBox(browser());
1227 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode));
1230 } // namespace