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.
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 "chrome/grit/generated_resources.h"
65 #include "components/policy/core/common/mock_configuration_policy_provider.h"
66 #include "components/policy/core/common/policy_types.h"
67 #include "content/public/test/browser_test_utils.h"
68 #include "ui/base/l10n/l10n_util.h"
71 using content::BrowserThread
;
72 using content::NavigationController
;
73 using net::URLRequestFailedJob
;
74 using net::URLRequestTestJob
;
78 // Returns true if |text| is displayed on the page |browser| is currently
79 // displaying. Uses "innerText", so will miss hidden text, and whitespace
80 // space handling may be weird.
81 bool WARN_UNUSED_RESULT
IsDisplayingText(Browser
* browser
,
82 const std::string
& text
) {
83 std::string command
= base::StringPrintf(
84 "var textContent = document.body.innerText;"
85 "var hasText = textContent.indexOf('%s') >= 0;"
86 "domAutomationController.send(hasText);",
89 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
90 browser
->tab_strip_model()->GetActiveWebContents(), command
, &result
));
94 // Expands the more box on the currently displayed error page.
95 void ToggleHelpBox(Browser
* browser
) {
96 EXPECT_TRUE(content::ExecuteScript(
97 browser
->tab_strip_model()->GetActiveWebContents(),
98 "document.getElementById('details-button').click();"));
101 // Returns true if |browser| is displaying the text representation of
102 // |error_code| on the current page.
103 bool WARN_UNUSED_RESULT
IsDisplayingNetError(Browser
* browser
,
104 net::Error error_code
) {
105 return IsDisplayingText(browser
, net::ErrorToShortString(error_code
));
108 // Returns true if the diagnostics button is displayed.
109 bool WARN_UNUSED_RESULT
IsDisplayingDiagnosticsButton(Browser
* browser
) {
110 std::string command
= base::StringPrintf(
111 "var diagnose_button = document.getElementById('diagnose-button');"
112 "domAutomationController.send(diagnose_button.style.display != 'none');");
114 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
115 browser
->tab_strip_model()->GetActiveWebContents(), command
, &result
));
119 // Checks that the local error page is being displayed, without remotely
120 // retrieved navigation corrections, and with the specified error code.
121 void ExpectDisplayingLocalErrorPage(Browser
* browser
, net::Error error_code
) {
122 // Expand the help box so innerText will include text below the fold.
123 ToggleHelpBox(browser
);
125 EXPECT_TRUE(IsDisplayingNetError(browser
, error_code
));
127 // Locally generated error pages should not have navigation corrections.
128 EXPECT_FALSE(IsDisplayingText(browser
, "http://correction1/"));
129 EXPECT_FALSE(IsDisplayingText(browser
, "http://correction2/"));
131 // Locally generated error pages should not have a populated search box.
132 bool search_box_populated
= false;
133 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
134 browser
->tab_strip_model()->GetActiveWebContents(),
135 "var searchText = document.getElementById('search-box').value;"
136 "domAutomationController.send(searchText == 'search query');",
137 &search_box_populated
));
138 EXPECT_FALSE(search_box_populated
);
141 // Checks that an error page with information retrieved from the navigation
142 // correction service is being displayed, with the specified specified error
144 void ExpectDisplayingNavigationCorrections(Browser
* browser
,
145 net::Error error_code
) {
146 // Expand the help box so innerText will include text below the fold.
147 ToggleHelpBox(browser
);
149 EXPECT_TRUE(IsDisplayingNetError(browser
, error_code
));
151 // Check that the mock navigation corrections are displayed.
152 EXPECT_TRUE(IsDisplayingText(browser
, "http://correction1/"));
153 EXPECT_TRUE(IsDisplayingText(browser
, "http://correction2/"));
155 // Check that the search box is populated correctly.
156 bool search_box_populated
= false;
157 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
158 browser
->tab_strip_model()->GetActiveWebContents(),
159 "var searchText = document.getElementById('search-box').value;"
160 "domAutomationController.send(searchText == 'search query');",
161 &search_box_populated
));
162 EXPECT_TRUE(search_box_populated
);
164 // The diagnostics button isn't displayed when corrections were
165 // retrieved from a remote server.
166 EXPECT_FALSE(IsDisplayingDiagnosticsButton(browser
));
169 std::string
GetShowSavedButtonLabel() {
170 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY
);
173 void AddInterceptorForURL(
175 scoped_ptr
<net::URLRequestInterceptor
> handler
) {
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
177 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
178 url
, handler
.Pass());
181 // An interceptor that fails a configurable number of requests, then succeeds
182 // all requests after that, keeping count of failures and successes.
183 class FailFirstNRequestsInterceptor
: public net::URLRequestInterceptor
{
185 explicit FailFirstNRequestsInterceptor(int requests_to_fail
)
186 : requests_(0), failures_(0), requests_to_fail_(requests_to_fail
) {}
187 ~FailFirstNRequestsInterceptor() override
{}
189 // net::URLRequestInterceptor implementation
190 net::URLRequestJob
* MaybeInterceptRequest(
191 net::URLRequest
* request
,
192 net::NetworkDelegate
* network_delegate
) const override
{
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
195 if (failures_
< requests_to_fail_
) {
197 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
198 // NetErrorHelperCore::GetErrorPageURL.
199 return new URLRequestFailedJob(request
,
201 net::ERR_CONNECTION_RESET
);
203 return new URLRequestTestJob(request
, network_delegate
,
204 URLRequestTestJob::test_headers(),
205 URLRequestTestJob::test_data_1(),
210 int requests() const { return requests_
; }
211 int failures() const { return failures_
; }
214 // These are mutable because MaybeCreateJob is const but we want this state
216 mutable int requests_
;
217 mutable int failures_
;
218 int requests_to_fail_
;
220 DISALLOW_COPY_AND_ASSIGN(FailFirstNRequestsInterceptor
);
223 // An interceptor that serves LinkDoctor responses. It also allows waiting
224 // until a certain number of requests have been sent.
225 // TODO(mmenke): Wait until responses have been received instead.
226 class LinkDoctorInterceptor
: public net::URLRequestInterceptor
{
228 LinkDoctorInterceptor() : num_requests_(0),
229 requests_to_wait_for_(-1),
230 weak_factory_(this) {
233 ~LinkDoctorInterceptor() override
{}
235 // net::URLRequestInterceptor implementation
236 net::URLRequestJob
* MaybeInterceptRequest(
237 net::URLRequest
* request
,
238 net::NetworkDelegate
* network_delegate
) const override
{
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
241 BrowserThread::PostTask(
242 BrowserThread::UI
, FROM_HERE
,
243 base::Bind(&LinkDoctorInterceptor::RequestCreated
,
244 weak_factory_
.GetWeakPtr()));
246 base::FilePath root_http
;
247 PathService::Get(chrome::DIR_TEST_DATA
, &root_http
);
248 return new net::URLRequestMockHTTPJob(
251 root_http
.AppendASCII("mock-link-doctor.json"),
252 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
253 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
256 void WaitForRequests(int requests_to_wait_for
) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
258 DCHECK_EQ(-1, requests_to_wait_for_
);
261 if (requests_to_wait_for
>= num_requests_
)
264 requests_to_wait_for_
= requests_to_wait_for
;
265 run_loop_
.reset(new base::RunLoop());
268 requests_to_wait_for_
= -1;
269 EXPECT_EQ(num_requests_
, requests_to_wait_for
);
272 // It is up to the caller to wait until all relevant requests has been
273 // created, either through calling WaitForRequests or some other manner,
274 // before calling this method.
275 int num_requests() const {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
277 return num_requests_
;
281 void RequestCreated() {
282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
285 if (num_requests_
== requests_to_wait_for_
)
289 // These are only used on the UI thread.
291 int requests_to_wait_for_
;
292 scoped_ptr
<base::RunLoop
> run_loop_
;
294 // This prevents any risk of flake if any test doesn't wait for a request
295 // it sent. Mutable so it can be accessed from a const function.
296 mutable base::WeakPtrFactory
<LinkDoctorInterceptor
> weak_factory_
;
298 DISALLOW_COPY_AND_ASSIGN(LinkDoctorInterceptor
);
301 void InstallMockInterceptors(
302 const GURL
& search_url
,
303 scoped_ptr
<net::URLRequestInterceptor
> link_doctor_interceptor
) {
304 chrome_browser_net::SetUrlRequestMocksEnabled(true);
306 AddInterceptorForURL(google_util::LinkDoctorBaseURL(),
307 link_doctor_interceptor
.Pass());
309 // Add a mock for the search engine the error page will use.
310 base::FilePath root_http
;
311 PathService::Get(chrome::DIR_TEST_DATA
, &root_http
);
312 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
313 search_url
.scheme(), search_url
.host(),
314 net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
315 root_http
.AppendASCII("title3.html"),
316 BrowserThread::GetBlockingPool()));
319 class ErrorPageTest
: public InProcessBrowserTest
{
321 enum HistoryNavigationDirection
{
322 HISTORY_NAVIGATE_BACK
,
323 HISTORY_NAVIGATE_FORWARD
,
326 ErrorPageTest() : link_doctor_interceptor_(NULL
) {}
327 ~ErrorPageTest() override
{}
329 // Navigates the active tab to a mock url created for the file at |file_path|.
330 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
331 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
332 command_line
->AppendSwitchASCII(switches::kShowSavedCopy
,
333 switches::kEnableShowSavedCopyPrimary
);
336 // Navigates the active tab to a mock url created for the file at |file_path|.
337 void NavigateToFileURL(const base::FilePath::StringType
& file_path
) {
338 ui_test_utils::NavigateToURL(
340 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path
)));
343 // Navigates to the given URL and waits for |num_navigations| to occur, and
344 // the title to change to |expected_title|.
345 void NavigateToURLAndWaitForTitle(const GURL
& url
,
346 const std::string
& expected_title
,
347 int num_navigations
) {
348 content::TitleWatcher
title_watcher(
349 browser()->tab_strip_model()->GetActiveWebContents(),
350 base::ASCIIToUTF16(expected_title
));
352 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
353 browser(), url
, num_navigations
);
355 EXPECT_EQ(base::ASCIIToUTF16(expected_title
),
356 title_watcher
.WaitAndGetTitle());
359 // Navigates back in the history and waits for |num_navigations| to occur, and
360 // the title to change to |expected_title|.
361 void GoBackAndWaitForTitle(const std::string
& expected_title
,
362 int num_navigations
) {
363 NavigateHistoryAndWaitForTitle(expected_title
,
365 HISTORY_NAVIGATE_BACK
);
368 // Navigates forward in the history and waits for |num_navigations| to occur,
369 // and the title to change to |expected_title|.
370 void GoForwardAndWaitForTitle(const std::string
& expected_title
,
371 int num_navigations
) {
372 NavigateHistoryAndWaitForTitle(expected_title
,
374 HISTORY_NAVIGATE_FORWARD
);
377 void GoBackAndWaitForNavigations(int num_navigations
) {
378 NavigateHistory(num_navigations
, HISTORY_NAVIGATE_BACK
);
381 void GoForwardAndWaitForNavigations(int num_navigations
) {
382 NavigateHistory(num_navigations
, HISTORY_NAVIGATE_FORWARD
);
385 // Confirms that the javascript variable indicating whether or not we have
386 // a stale copy in the cache has been set to |expected|, and that the
387 // stale load button is or isn't there based on the same expectation.
388 testing::AssertionResult
ProbeStaleCopyValue(bool expected
) {
389 const char* js_cache_probe
=
391 " domAutomationController.send(\n"
392 " loadTimeData.valueExists('showSavedCopyButton') ?"
395 " domAutomationController.send(e.message);\n"
400 content::ExecuteScriptAndExtractString(
401 browser()->tab_strip_model()->GetActiveWebContents(),
405 return testing::AssertionFailure()
406 << "Failing return from ExecuteScriptAndExtractString.";
409 if ((expected
&& "yes" == result
) || (!expected
&& "no" == result
))
410 return testing::AssertionSuccess();
412 return testing::AssertionFailure() << "Cache probe result is " << result
;
415 testing::AssertionResult
ReloadStaleCopyFromCache() {
416 const char* js_reload_script
=
418 " document.getElementById('show-saved-copy-button').click();\n"
419 " domAutomationController.send('success');\n"
421 " domAutomationController.send(e.message);\n"
425 bool ret
= content::ExecuteScriptAndExtractString(
426 browser()->tab_strip_model()->GetActiveWebContents(),
431 return testing::AssertionFailure();
432 return ("success" == result
? testing::AssertionSuccess() :
433 (testing::AssertionFailure() << "Exception message is " << result
));
436 LinkDoctorInterceptor
* link_doctor_interceptor() {
437 return link_doctor_interceptor_
;
441 void SetUpOnMainThread() override
{
442 link_doctor_interceptor_
= new LinkDoctorInterceptor();
443 scoped_ptr
<net::URLRequestInterceptor
> owned_interceptor(
444 link_doctor_interceptor_
);
445 // Ownership of the |interceptor_| is passed to an object the IO thread, but
446 // a pointer is kept in the test fixture. As soon as anything calls
447 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
448 UIThreadSearchTermsData
search_terms_data(browser()->profile());
449 BrowserThread::PostTask(
450 BrowserThread::IO
, FROM_HERE
,
451 base::Bind(&InstallMockInterceptors
,
452 GURL(search_terms_data
.GoogleBaseURLValue()),
453 base::Passed(&owned_interceptor
)));
456 // Returns a GURL that results in a DNS error.
457 GURL
GetDnsErrorURL() const {
458 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED
);
461 // Returns true if the platform has support for a diagnostics tool, which
462 // can be launched from the error page.
463 bool PlatformSupportsDiagnosticsTool() {
464 #if defined(OS_CHROMEOS)
465 // ChromeOS uses an extension instead of a diagnostics dialog.
468 return CanShowNetworkDiagnosticsDialog();
473 // Navigates the browser the indicated direction in the history and waits for
474 // |num_navigations| to occur and the title to change to |expected_title|.
475 void NavigateHistoryAndWaitForTitle(const std::string
& expected_title
,
477 HistoryNavigationDirection direction
) {
478 content::TitleWatcher
title_watcher(
479 browser()->tab_strip_model()->GetActiveWebContents(),
480 base::ASCIIToUTF16(expected_title
));
482 NavigateHistory(num_navigations
, direction
);
484 EXPECT_EQ(title_watcher
.WaitAndGetTitle(),
485 base::ASCIIToUTF16(expected_title
));
488 void NavigateHistory(int num_navigations
,
489 HistoryNavigationDirection direction
) {
490 content::TestNavigationObserver
test_navigation_observer(
491 browser()->tab_strip_model()->GetActiveWebContents(),
493 if (direction
== HISTORY_NAVIGATE_BACK
) {
494 chrome::GoBack(browser(), CURRENT_TAB
);
495 } else if (direction
== HISTORY_NAVIGATE_FORWARD
) {
496 chrome::GoForward(browser(), CURRENT_TAB
);
500 test_navigation_observer
.Wait();
503 LinkDoctorInterceptor
* link_doctor_interceptor_
;
506 class TestFailProvisionalLoadObserver
: public content::WebContentsObserver
{
508 explicit TestFailProvisionalLoadObserver(content::WebContents
* contents
)
509 : content::WebContentsObserver(contents
) {}
510 ~TestFailProvisionalLoadObserver() override
{}
512 // This method is invoked when the provisional load failed.
513 void DidFailProvisionalLoad(
514 content::RenderFrameHost
* render_frame_host
,
515 const GURL
& validated_url
,
517 const base::string16
& error_description
,
518 bool was_ignored_by_handler
) override
{
519 fail_url_
= validated_url
;
522 const GURL
& fail_url() const { return fail_url_
; }
527 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver
);
530 void InterceptNetworkTransactions(net::URLRequestContextGetter
* getter
,
532 DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO
));
533 net::HttpCache
* cache(
534 getter
->GetURLRequestContext()->http_transaction_factory()->GetCache());
536 scoped_ptr
<net::HttpTransactionFactory
> factory(
537 new net::FailingHttpTransactionFactory(cache
->GetSession(), error
));
538 // Throw away old version; since this is a a browser test, we don't
539 // need to restore the old state.
540 cache
->SetHttpNetworkTransactionFactoryForTesting(factory
.Pass());
543 // Test an error with a file URL, and make sure it doesn't have a
544 // button to launch a network diagnostics tool.
545 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, FileNotFound
) {
546 // Create an empty temp directory, to be sure there's no file in it.
547 base::ScopedTempDir temp_dir
;
548 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
549 GURL non_existent_file_url
=
550 net::FilePathToFileURL(temp_dir
.path().AppendASCII("marmoset"));
552 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
553 browser(), non_existent_file_url
, 1);
555 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FILE_NOT_FOUND
);
556 // Should not request Link Doctor corrections for local errors.
557 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
558 // Only errors on HTTP/HTTPS pages should display a diagnostics button.
559 EXPECT_FALSE(IsDisplayingDiagnosticsButton(browser()));
562 // Check an network error page for ERR_FAILED. In particular, this should
563 // not trigger a link doctor error page, and should have a diagnostics
564 // button, if available on the current platform.
565 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, Failed
) {
566 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
567 browser(), URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED
), 1);
569 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FAILED
);
570 // Should not request Link Doctor corrections for this error.
571 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
573 EXPECT_EQ(PlatformSupportsDiagnosticsTool(),
574 IsDisplayingDiagnosticsButton(browser()));
577 // Test that a DNS error occuring in the main frame redirects to an error page.
578 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_Basic
) {
579 // The first navigation should fail and load a blank page, while it fetches
580 // the Link Doctor response. The second navigation is the Link Doctor.
581 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
582 browser(), GetDnsErrorURL(), 2);
583 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
584 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
587 // Test that a DNS error occuring in the main frame does not result in an
588 // additional session history entry.
589 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack1
) {
590 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
591 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
592 browser(), GetDnsErrorURL(), 2);
593 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
594 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
595 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
598 // Test that a DNS error occuring in the main frame does not result in an
599 // additional session history entry.
600 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2
) {
601 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
603 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
604 browser(), GetDnsErrorURL(), 2);
605 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
606 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
608 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
610 GoBackAndWaitForNavigations(2);
611 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
612 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
614 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
615 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
618 // Test that a DNS error occuring in the main frame does not result in an
619 // additional session history entry.
620 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2AndForward
) {
621 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
623 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
624 browser(), GetDnsErrorURL(), 2);
625 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
626 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
628 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
630 GoBackAndWaitForNavigations(2);
631 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
632 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
634 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
636 GoForwardAndWaitForNavigations(2);
637 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
638 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
641 // Test that a DNS error occuring in the main frame does not result in an
642 // additional session history entry.
643 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2Forward2
) {
644 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
646 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
647 browser(), GetDnsErrorURL(), 2);
648 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
649 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
651 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
653 GoBackAndWaitForNavigations(2);
654 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
655 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
657 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
659 GoForwardAndWaitForNavigations(2);
660 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
661 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
663 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
664 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
667 // Test that the search button on a DNS error page works.
668 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoSearch
) {
669 // The first navigation should fail, and the second one should be the error
671 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
672 browser(), GetDnsErrorURL(), 2);
673 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
674 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
676 content::WebContents
* web_contents
=
677 browser()->tab_strip_model()->GetActiveWebContents();
679 // Do a search and make sure the browser ends up at the right page.
680 content::TestNavigationObserver
nav_observer(web_contents
, 1);
681 content::TitleWatcher
title_watcher(
683 base::ASCIIToUTF16("Title Of More Awesomeness"));
684 // Can't use content::ExecuteScript because it waits for scripts to send
685 // notification that they've run, and scripts that trigger a navigation may
686 // not send that notification.
687 web_contents
->GetMainFrame()->ExecuteJavaScriptForTests(
688 base::ASCIIToUTF16("document.getElementById('search-button').click();"));
690 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
691 title_watcher
.WaitAndGetTitle());
693 // There should have been another Link Doctor request, for tracking purposes.
694 // Have to wait for it, since the search page does not depend on having
695 // sent the tracking request.
696 link_doctor_interceptor()->WaitForRequests(2);
697 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
699 // Check the path and query string.
701 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
702 browser()->tab_strip_model()->GetActiveWebContents(),
703 "domAutomationController.send(window.location.href);",
705 EXPECT_EQ("/search", GURL(url
).path());
706 EXPECT_EQ("q=search%20query", GURL(url
).query());
708 // Go back to the error page, to make sure the history is correct.
709 GoBackAndWaitForNavigations(2);
710 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
711 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
714 // Test that the reload button on a DNS error page works.
715 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoReload
) {
716 // The first navigation should fail, and the second one should be the error
718 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
719 browser(), GetDnsErrorURL(), 2);
720 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
721 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
723 content::WebContents
* web_contents
=
724 browser()->tab_strip_model()->GetActiveWebContents();
726 // Clicking the reload button should load the error page again, and there
727 // should be two commits, as before.
728 content::TestNavigationObserver
nav_observer(web_contents
, 2);
729 // Can't use content::ExecuteScript because it waits for scripts to send
730 // notification that they've run, and scripts that trigger a navigation may
731 // not send that notification.
732 web_contents
->GetMainFrame()->ExecuteJavaScriptForTests(
733 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
735 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
737 // There should have two more requests to the correction service: One for the
738 // new error page, and one for tracking purposes. Have to make sure to wait
739 // for the tracking request, since the new error page does not depend on it.
740 link_doctor_interceptor()->WaitForRequests(3);
741 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
744 // Test that clicking links on a DNS error page works.
745 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoClickLink
) {
746 // The first navigation should fail, and the second one should be the error
748 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
749 browser(), GetDnsErrorURL(), 2);
750 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
751 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
753 content::WebContents
* web_contents
=
754 browser()->tab_strip_model()->GetActiveWebContents();
756 // Simulate a click on a link.
758 content::TitleWatcher
title_watcher(
760 base::ASCIIToUTF16("Title Of Awesomeness"));
761 std::string link_selector
=
762 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
763 // The tracking request is triggered by onmousedown, so it catches middle
764 // mouse button clicks, as well as left clicks.
765 web_contents
->GetMainFrame()->ExecuteJavaScriptForTests(
766 base::ASCIIToUTF16(link_selector
+ ".onmousedown();"));
767 // Can't use content::ExecuteScript because it waits for scripts to send
768 // notification that they've run, and scripts that trigger a navigation may
769 // not send that notification.
770 web_contents
->GetMainFrame()->ExecuteJavaScriptForTests(
771 base::ASCIIToUTF16(link_selector
+ ".click();"));
772 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
773 title_watcher
.WaitAndGetTitle());
775 // There should have been a tracking request to the correction service. Have
776 // to make sure to wait the tracking request, since the new page does not
778 link_doctor_interceptor()->WaitForRequests(2);
779 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
782 // Test that a DNS error occuring in an iframe does not result in showing
783 // navigation corrections.
784 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, IFrameDNSError_Basic
) {
785 NavigateToURLAndWaitForTitle(
786 net::URLRequestMockHTTPJob::GetMockUrl(
787 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
790 // We expect to have two history entries, since we started off with navigation
791 // to "about:blank" and then navigated to "iframe_dns_error.html".
793 browser()->tab_strip_model()->GetActiveWebContents()->
794 GetController().GetEntryCount());
795 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
798 // This test fails regularly on win_rel trybots. See crbug.com/121540
800 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
802 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
804 // Test that a DNS error occuring in an iframe does not result in an
805 // additional session history entry.
806 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, MAYBE_IFrameDNSError_GoBack
) {
807 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
808 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
809 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
810 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
813 // This test fails regularly on win_rel trybots. See crbug.com/121540
815 // This fails on linux_aura bringup: http://crbug.com/163931
816 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
817 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
819 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
821 // Test that a DNS error occuring in an iframe does not result in an
822 // additional session history entry.
823 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, MAYBE_IFrameDNSError_GoBackAndForward
) {
824 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
825 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
826 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
827 GoForwardAndWaitForTitle("Blah", 1);
828 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
831 // Test that a DNS error occuring in an iframe, once the main document is
832 // completed loading, does not result in an additional session history entry.
833 // To ensure that the main document has completed loading, JavaScript is used to
834 // inject an iframe after loading is done.
835 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, IFrameDNSError_JavaScript
) {
836 content::WebContents
* wc
=
837 browser()->tab_strip_model()->GetActiveWebContents();
839 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED
);
841 // Load a regular web page, in which we will inject an iframe.
842 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
844 // We expect to have two history entries, since we started off with navigation
845 // to "about:blank" and then navigated to "title2.html".
846 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
848 std::string script
= "var frame = document.createElement('iframe');"
849 "frame.src = '" + fail_url
.spec() + "';"
850 "document.body.appendChild(frame);";
852 TestFailProvisionalLoadObserver
fail_observer(wc
);
853 content::WindowedNotificationObserver
load_observer(
854 content::NOTIFICATION_LOAD_STOP
,
855 content::Source
<NavigationController
>(&wc
->GetController()));
856 wc
->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script
));
857 load_observer
.Wait();
859 // Ensure we saw the expected failure.
860 EXPECT_EQ(fail_url
, fail_observer
.fail_url());
862 // Failed initial navigation of an iframe shouldn't be adding any history
864 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
867 // Do the same test, but with an iframe that doesn't have initial URL
869 script
= "var frame = document.createElement('iframe');"
870 "frame.id = 'target_frame';"
871 "document.body.appendChild(frame);";
873 content::WindowedNotificationObserver
load_observer(
874 content::NOTIFICATION_LOAD_STOP
,
875 content::Source
<NavigationController
>(&wc
->GetController()));
876 wc
->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script
));
877 load_observer
.Wait();
880 script
= "var f = document.getElementById('target_frame');"
881 "f.src = '" + fail_url
.spec() + "';";
883 TestFailProvisionalLoadObserver
fail_observer(wc
);
884 content::WindowedNotificationObserver
load_observer(
885 content::NOTIFICATION_LOAD_STOP
,
886 content::Source
<NavigationController
>(&wc
->GetController()));
887 wc
->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script
));
888 load_observer
.Wait();
890 EXPECT_EQ(fail_url
, fail_observer
.fail_url());
891 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
893 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
896 // Checks that navigation corrections are not loaded when we receive an actual
898 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, Page404
) {
899 NavigateToURLAndWaitForTitle(
900 net::URLRequestMockHTTPJob::GetMockUrl(
901 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
904 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
907 // Checks that when an error occurs, the stale cache status of the page
908 // is correctly transferred, and that stale cached copied can be loaded
909 // from the javascript.
910 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, StaleCacheStatus
) {
911 ASSERT_TRUE(test_server()->Start());
912 // Load cache with entry with "nocache" set, to create stale
914 GURL
test_url(test_server()->GetURL("files/nocache.html"));
915 NavigateToURLAndWaitForTitle(test_url
, "Nocache Test Page", 1);
917 // Reload same URL after forcing an error from the the network layer;
918 // confirm that the error page is told the cached copy exists.
919 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter
=
920 browser()->profile()->GetRequestContext();
921 BrowserThread::PostTask(
922 BrowserThread::IO
, FROM_HERE
,
923 base::Bind(&InterceptNetworkTransactions
, url_request_context_getter
,
926 // With no navigation corrections to load, there's only one navigation.
927 ui_test_utils::NavigateToURL(browser(), test_url
);
928 EXPECT_TRUE(ProbeStaleCopyValue(true));
929 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
930 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
931 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
933 // Confirm that loading the stale copy from the cache works.
934 content::TestNavigationObserver
same_tab_observer(
935 browser()->tab_strip_model()->GetActiveWebContents(), 1);
936 ASSERT_TRUE(ReloadStaleCopyFromCache());
937 same_tab_observer
.Wait();
938 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
939 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
941 // Reload the same URL with a post request; confirm the error page is told
942 // that there is no cached copy.
943 ui_test_utils::NavigateToURLWithPost(browser(), test_url
);
944 EXPECT_TRUE(ProbeStaleCopyValue(false));
945 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
946 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
948 // Clear the cache and reload the same URL; confirm the error page is told
949 // that there is no cached copy.
950 BrowsingDataRemover
* remover
=
951 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
952 remover
->Remove(BrowsingDataRemover::REMOVE_CACHE
,
953 BrowsingDataHelper::UNPROTECTED_WEB
);
954 ui_test_utils::NavigateToURL(browser(), test_url
);
955 EXPECT_TRUE(ProbeStaleCopyValue(false));
956 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
957 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
960 // Check that the easter egg is present and initialised and is not disabled.
961 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, CheckEasterEggIsNotDisabled
) {
962 ui_test_utils::NavigateToURL(browser(),
963 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED
));
965 content::WebContents
* web_contents
=
966 browser()->tab_strip_model()->GetActiveWebContents();
968 // Check for no disabled message container.
969 std::string command
= base::StringPrintf(
970 "var hasDisableContainer = document.querySelectorAll('.snackbar').length;"
971 "domAutomationController.send(hasDisableContainer);");
973 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
974 web_contents
, command
, &result
));
975 EXPECT_EQ(0, result
);
977 // Presence of the canvas container.
978 command
= base::StringPrintf(
979 "var runnerCanvas = document.querySelectorAll('.runner-canvas').length;"
980 "domAutomationController.send(runnerCanvas);");
981 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
982 web_contents
, command
, &result
));
983 EXPECT_EQ(1, result
);
986 class ErrorPageAutoReloadTest
: public InProcessBrowserTest
{
988 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
989 command_line
->AppendSwitch(switches::kEnableOfflineAutoReload
);
992 void InstallInterceptor(const GURL
& url
, int requests_to_fail
) {
993 interceptor_
= new FailFirstNRequestsInterceptor(requests_to_fail
);
994 scoped_ptr
<net::URLRequestInterceptor
> owned_interceptor(interceptor_
);
996 // Tests don't need to wait for this task to complete before using the
997 // filter; any requests that might be affected by it will end up in the IO
998 // thread's message loop after this posted task anyway.
1000 // Ownership of the interceptor is passed to an object the IO thread, but a
1001 // pointer is kept in the test fixture. As soon as anything calls
1002 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
1003 BrowserThread::PostTask(
1004 BrowserThread::IO
, FROM_HERE
,
1005 base::Bind(&AddInterceptorForURL
, url
,
1006 base::Passed(&owned_interceptor
)));
1009 void NavigateToURLAndWaitForTitle(const GURL
& url
,
1010 const std::string
& expected_title
,
1011 int num_navigations
) {
1012 content::TitleWatcher
title_watcher(
1013 browser()->tab_strip_model()->GetActiveWebContents(),
1014 base::ASCIIToUTF16(expected_title
));
1016 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1017 browser(), url
, num_navigations
);
1019 EXPECT_EQ(base::ASCIIToUTF16(expected_title
),
1020 title_watcher
.WaitAndGetTitle());
1023 FailFirstNRequestsInterceptor
* interceptor() {
1024 return interceptor_
;
1028 FailFirstNRequestsInterceptor
* interceptor_
;
1031 // Fails on official mac_trunk build. See crbug.com/465789.
1032 #if defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
1033 #define MAYBE_AutoReload DISABLED_AutoReload
1035 #define MAYBE_AutoReload AutoReload
1037 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest
, MAYBE_AutoReload
) {
1038 GURL
test_url("http://error.page.auto.reload");
1039 const int kRequestsToFail
= 2;
1040 InstallInterceptor(test_url
, kRequestsToFail
);
1041 NavigateToURLAndWaitForTitle(test_url
, "Test One", kRequestsToFail
+ 1);
1042 // Note that the interceptor updates these variables on the IO thread,
1043 // but this function reads them on the main thread. The requests have to be
1044 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
1045 // this becomes racey.
1046 EXPECT_EQ(kRequestsToFail
, interceptor()->failures());
1047 EXPECT_EQ(kRequestsToFail
+ 1, interceptor()->requests());
1050 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest
, ManualReloadNotSuppressed
) {
1051 GURL
test_url("http://error.page.auto.reload");
1052 const int kRequestsToFail
= 3;
1053 InstallInterceptor(test_url
, kRequestsToFail
);
1054 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1055 browser(), test_url
, 2);
1057 EXPECT_EQ(2, interceptor()->failures());
1058 EXPECT_EQ(2, interceptor()->requests());
1060 ToggleHelpBox(browser());
1061 EXPECT_TRUE(IsDisplayingText(browser(), "error.page.auto.reload"));
1063 content::WebContents
* web_contents
=
1064 browser()->tab_strip_model()->GetActiveWebContents();
1065 content::TestNavigationObserver
nav_observer(web_contents
, 1);
1066 web_contents
->GetMainFrame()->ExecuteJavaScriptForTests(
1067 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
1068 nav_observer
.Wait();
1069 EXPECT_FALSE(IsDisplayingText(browser(), "error.page.auto.reload"));
1072 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
1073 class AddressUnreachableInterceptor
: public net::URLRequestInterceptor
{
1075 AddressUnreachableInterceptor() {}
1076 ~AddressUnreachableInterceptor() override
{}
1078 // net::URLRequestInterceptor:
1079 net::URLRequestJob
* MaybeInterceptRequest(
1080 net::URLRequest
* request
,
1081 net::NetworkDelegate
* network_delegate
) const override
{
1082 return new URLRequestFailedJob(request
,
1084 net::ERR_ADDRESS_UNREACHABLE
);
1088 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor
);
1091 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
1092 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
1093 // a different error for the correction service and the original page to
1094 // validate the right page is being displayed.
1095 class ErrorPageNavigationCorrectionsFailTest
: public ErrorPageTest
{
1097 // InProcessBrowserTest:
1098 void SetUpOnMainThread() override
{
1099 BrowserThread::PostTask(
1100 BrowserThread::IO
, FROM_HERE
,
1101 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters
));
1104 void TearDownOnMainThread() override
{
1105 BrowserThread::PostTask(
1106 BrowserThread::IO
, FROM_HERE
,
1107 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters
));
1111 // Adds a filter that causes all correction service requests to fail with
1112 // ERR_ADDRESS_UNREACHABLE.
1114 // Also adds the net::URLRequestFailedJob filter.
1115 static void AddFilters() {
1116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1117 URLRequestFailedJob::AddUrlHandler();
1119 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
1120 google_util::LinkDoctorBaseURL(),
1121 scoped_ptr
<net::URLRequestInterceptor
>(
1122 new AddressUnreachableInterceptor()));
1125 static void RemoveFilters() {
1126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1127 net::URLRequestFilter::GetInstance()->ClearHandlers();
1131 // Make sure that when corrections fail to load, the network error page is
1132 // successfully loaded.
1133 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest
,
1134 FetchCorrectionsFails
) {
1135 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1137 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED
),
1140 // Verify that the expected error page is being displayed.
1141 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED
);
1143 // Diagnostics button should be displayed, if avilable on this platform.
1144 EXPECT_EQ(PlatformSupportsDiagnosticsTool(),
1145 IsDisplayingDiagnosticsButton(browser()));
1148 // Checks that when an error occurs and a corrections fail to load, the stale
1149 // cache status of the page is correctly transferred, and we can load the
1150 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1152 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest
,
1153 StaleCacheStatusFailedCorrections
) {
1154 ASSERT_TRUE(test_server()->Start());
1155 // Load cache with entry with "nocache" set, to create stale
1157 GURL
test_url(test_server()->GetURL("files/nocache.html"));
1158 NavigateToURLAndWaitForTitle(test_url
, "Nocache Test Page", 1);
1160 // Reload same URL after forcing an error from the the network layer;
1161 // confirm that the error page is told the cached copy exists.
1162 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter
=
1163 browser()->profile()->GetRequestContext();
1164 BrowserThread::PostTask(
1165 BrowserThread::IO
, FROM_HERE
,
1166 base::Bind(&InterceptNetworkTransactions
, url_request_context_getter
,
1167 net::ERR_CONNECTION_FAILED
));
1169 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1170 browser(), test_url
, 2);
1171 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1172 EXPECT_TRUE(ProbeStaleCopyValue(true));
1174 // Confirm that loading the stale copy from the cache works.
1175 content::TestNavigationObserver
same_tab_observer(
1176 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1177 ASSERT_TRUE(ReloadStaleCopyFromCache());
1178 same_tab_observer
.Wait();
1179 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1180 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1182 // Clear the cache and reload the same URL; confirm the error page is told
1183 // that there is no cached copy.
1184 BrowsingDataRemover
* remover
=
1185 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
1186 remover
->Remove(BrowsingDataRemover::REMOVE_CACHE
,
1187 BrowsingDataHelper::UNPROTECTED_WEB
);
1188 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1189 browser(), test_url
, 2);
1190 EXPECT_TRUE(ProbeStaleCopyValue(false));
1191 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1194 #if defined(OS_CHROMEOS)
1195 class ErrorPageOfflineTest
: public ErrorPageTest
{
1197 // Mock policy provider for both user and device policies.
1198 policy::MockConfigurationPolicyProvider policy_provider_
;
1200 void SetUpInProcessBrowserTestFixture() override
{
1201 // Set up fake install attributes.
1202 scoped_ptr
<policy::StubEnterpriseInstallAttributes
> attributes(
1203 new policy::StubEnterpriseInstallAttributes());
1204 attributes
->SetDomain("example.com");
1205 attributes
->SetRegistrationUser("user@example.com");
1206 policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
1207 attributes
.release());
1209 // Sets up a mock policy provider for user and device policies.
1210 EXPECT_CALL(policy_provider_
, IsInitializationComplete(testing::_
))
1211 .WillRepeatedly(testing::Return(true));
1212 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
1215 ErrorPageTest::SetUpInProcessBrowserTestFixture();
1219 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest
, CheckEasterEggIsDisabled
) {
1220 // Check for enterprise enrollment.
1221 policy::BrowserPolicyConnectorChromeOS
* connector
=
1222 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1223 EXPECT_TRUE(connector
->IsEnterpriseManaged());
1225 ui_test_utils::NavigateToURL(browser(),
1226 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED
));
1228 content::WebContents
* web_contents
=
1229 browser()->tab_strip_model()->GetActiveWebContents();
1231 std::string command
= base::StringPrintf(
1232 "var hasText = document.querySelector('.snackbar').innerText;"
1233 "domAutomationController.send(hasText);");
1234 std::string result
= "";
1235 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1236 web_contents
, command
, &result
));
1238 std::string disabled_text
=
1239 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED
);
1240 EXPECT_EQ(disabled_text
, result
);
1244 // A test fixture that simulates failing requests for an IDN domain name.
1245 class ErrorPageForIDNTest
: public InProcessBrowserTest
{
1247 // Target hostname in different forms.
1248 static const char kHostname
[];
1249 static const char kHostnameJSUnicode
[];
1251 // InProcessBrowserTest:
1252 void SetUpOnMainThread() override
{
1253 // Clear AcceptLanguages to force punycode decoding.
1254 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages
,
1256 BrowserThread::PostTask(
1257 BrowserThread::IO
, FROM_HERE
,
1258 base::Bind(&ErrorPageForIDNTest::AddFilters
));
1261 void TearDownOnMainThread() override
{
1262 BrowserThread::PostTask(
1263 BrowserThread::IO
, FROM_HERE
,
1264 base::Bind(&ErrorPageForIDNTest::RemoveFilters
));
1268 static void AddFilters() {
1269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1270 URLRequestFailedJob::AddUrlHandlerForHostname(kHostname
);
1273 static void RemoveFilters() {
1274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1275 net::URLRequestFilter::GetInstance()->ClearHandlers();
1279 const char ErrorPageForIDNTest::kHostname
[] =
1280 "xn--d1abbgf6aiiy.xn--p1ai";
1281 const char ErrorPageForIDNTest::kHostnameJSUnicode
[] =
1282 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1285 // Make sure error page shows correct unicode for IDN.
1286 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest
, IDN
) {
1287 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1288 ui_test_utils::NavigateToURL(
1290 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT
,
1293 ToggleHelpBox(browser());
1294 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode
));