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/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"
68 using content::BrowserThread
;
69 using content::NavigationController
;
70 using net::URLRequestFailedJob
;
71 using net::URLRequestTestJob
;
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);",
86 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
87 browser
->tab_strip_model()->GetActiveWebContents(), command
, &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
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(
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
{
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
));
177 if (failures_
< requests_to_fail_
) {
179 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
180 // NetErrorHelperCore::GetErrorPageURL.
181 return new URLRequestFailedJob(request
,
183 net::ERR_CONNECTION_RESET
);
185 return new URLRequestTestJob(request
, network_delegate
,
186 URLRequestTestJob::test_headers(),
187 URLRequestTestJob::test_data_1(),
192 int requests() const { return requests_
; }
193 int failures() const { return failures_
; }
196 // These are mutable because MaybeCreateJob is const but we want this state
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
{
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(
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_
);
243 if (requests_to_wait_for
>= num_requests_
)
246 requests_to_wait_for_
= requests_to_wait_for
;
247 run_loop_
.reset(new base::RunLoop());
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_
;
263 void RequestCreated() {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
267 if (num_requests_
== requests_to_wait_for_
)
271 // These are only used on the UI thread.
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
{
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(
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
,
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
,
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
=
373 " domAutomationController.send(\n"
374 " loadTimeData.valueExists('showSavedCopyButton') ?"
377 " domAutomationController.send(e.message);\n"
382 content::ExecuteScriptAndExtractString(
383 browser()->tab_strip_model()->GetActiveWebContents(),
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
=
400 " document.getElementById('show-saved-copy-button').click();\n"
401 " domAutomationController.send('success');\n"
403 " domAutomationController.send(e.message);\n"
407 bool ret
= content::ExecuteScriptAndExtractString(
408 browser()->tab_strip_model()->GetActiveWebContents(),
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_
;
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
);
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
,
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(),
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
);
471 test_navigation_observer
.Wait();
474 LinkDoctorInterceptor
* link_doctor_interceptor_
;
477 class TestFailProvisionalLoadObserver
: public content::WebContentsObserver
{
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
,
488 const base::string16
& error_description
) override
{
489 fail_url_
= validated_url
;
492 const GURL
& fail_url() const { return fail_url_
; }
497 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver
);
500 void InterceptNetworkTransactions(net::URLRequestContextGetter
* getter
,
502 DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO
));
503 net::HttpCache
* cache(
504 getter
->GetURLRequestContext()->http_transaction_factory()->GetCache());
506 scoped_ptr
<net::HttpTransactionFactory
> factory(
507 new net::FailingHttpTransactionFactory(cache
->GetSession(), error
));
508 // Throw away old version; since this is a a browser test, we don't
509 // need to restore the old state.
510 cache
->SetHttpNetworkTransactionFactoryForTesting(factory
.Pass());
513 // Test that a DNS error occuring in the main frame redirects to an error page.
514 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_Basic
) {
515 // The first navigation should fail, and the second one should be the error
517 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
518 browser(), GetDnsErrorURL(), 2);
519 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
520 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
523 // Test that a DNS error occuring in the main frame does not result in an
524 // additional session history entry.
525 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack1
) {
526 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
527 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
528 browser(), GetDnsErrorURL(), 2);
529 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
530 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
531 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
534 // Test that a DNS error occuring in the main frame does not result in an
535 // additional session history entry.
536 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2
) {
537 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
539 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
540 browser(), GetDnsErrorURL(), 2);
541 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
542 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
544 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
546 GoBackAndWaitForNavigations(2);
547 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
548 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
550 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
551 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
554 // Test that a DNS error occuring in the main frame does not result in an
555 // additional session history entry.
556 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2AndForward
) {
557 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
559 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
560 browser(), GetDnsErrorURL(), 2);
561 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
562 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
564 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
566 GoBackAndWaitForNavigations(2);
567 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
568 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
570 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
572 GoForwardAndWaitForNavigations(2);
573 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
574 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
577 // Test that a DNS error occuring in the main frame does not result in an
578 // additional session history entry.
579 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_GoBack2Forward2
) {
580 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
582 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
583 browser(), GetDnsErrorURL(), 2);
584 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
585 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
587 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
589 GoBackAndWaitForNavigations(2);
590 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
591 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
593 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
595 GoForwardAndWaitForNavigations(2);
596 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
597 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
599 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
600 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
603 // Test that the search button on a DNS error page works.
604 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoSearch
) {
605 // The first navigation should fail, and the second one should be the error
607 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
608 browser(), GetDnsErrorURL(), 2);
609 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
610 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
612 content::WebContents
* web_contents
=
613 browser()->tab_strip_model()->GetActiveWebContents();
615 // Do a search and make sure the browser ends up at the right page.
616 content::TestNavigationObserver
nav_observer(web_contents
, 1);
617 content::TitleWatcher
title_watcher(
619 base::ASCIIToUTF16("Title Of More Awesomeness"));
620 // Can't use content::ExecuteScript because it waits for scripts to send
621 // notification that they've run, and scripts that trigger a navigation may
622 // not send that notification.
623 web_contents
->GetMainFrame()->ExecuteJavaScript(
624 base::ASCIIToUTF16("document.getElementById('search-button').click();"));
626 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
627 title_watcher
.WaitAndGetTitle());
629 // There should have been another Link Doctor request, for tracking purposes.
630 // Have to wait for it, since the search page does not depend on having
631 // sent the tracking request.
632 link_doctor_interceptor()->WaitForRequests(2);
633 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
635 // Check the path and query string.
637 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
638 browser()->tab_strip_model()->GetActiveWebContents(),
639 "domAutomationController.send(window.location.href);",
641 EXPECT_EQ("/search", GURL(url
).path());
642 EXPECT_EQ("q=search%20query", GURL(url
).query());
644 // Go back to the error page, to make sure the history is correct.
645 GoBackAndWaitForNavigations(2);
646 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
647 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
650 // Test that the reload button on a DNS error page works.
651 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoReload
) {
652 // The first navigation should fail, and the second one should be the error
654 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
655 browser(), GetDnsErrorURL(), 2);
656 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
657 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
659 content::WebContents
* web_contents
=
660 browser()->tab_strip_model()->GetActiveWebContents();
662 // Clicking the reload button should load the error page again, and there
663 // should be two commits, as before.
664 content::TestNavigationObserver
nav_observer(web_contents
, 2);
665 // Can't use content::ExecuteScript because it waits for scripts to send
666 // notification that they've run, and scripts that trigger a navigation may
667 // not send that notification.
668 web_contents
->GetMainFrame()->ExecuteJavaScript(
669 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
671 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
673 // There should have two more requests to the correction service: One for the
674 // new error page, and one for tracking purposes. Have to make sure to wait
675 // for the tracking request, since the new error page does not depend on it.
676 link_doctor_interceptor()->WaitForRequests(3);
677 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
680 // Test that clicking links on a DNS error page works.
681 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, DNSError_DoClickLink
) {
682 // The first navigation should fail, and the second one should be the error
684 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
685 browser(), GetDnsErrorURL(), 2);
686 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED
);
687 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
689 content::WebContents
* web_contents
=
690 browser()->tab_strip_model()->GetActiveWebContents();
692 // Simulate a click on a link.
694 content::TitleWatcher
title_watcher(
696 base::ASCIIToUTF16("Title Of Awesomeness"));
697 std::string link_selector
=
698 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
699 // The tracking request is triggered by onmousedown, so it catches middle
700 // mouse button clicks, as well as left clicks.
701 web_contents
->GetMainFrame()->ExecuteJavaScript(
702 base::ASCIIToUTF16(link_selector
+ ".onmousedown();"));
703 // Can't use content::ExecuteScript because it waits for scripts to send
704 // notification that they've run, and scripts that trigger a navigation may
705 // not send that notification.
706 web_contents
->GetMainFrame()->ExecuteJavaScript(
707 base::ASCIIToUTF16(link_selector
+ ".click();"));
708 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
709 title_watcher
.WaitAndGetTitle());
711 // There should have been a tracking request to the correction service. Have
712 // to make sure to wait the tracking request, since the new page does not
714 link_doctor_interceptor()->WaitForRequests(2);
715 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
718 // Test that a DNS error occuring in an iframe does not result in showing
719 // navigation corrections.
720 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, IFrameDNSError_Basic
) {
721 NavigateToURLAndWaitForTitle(
722 net::URLRequestMockHTTPJob::GetMockUrl(
723 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
726 // We expect to have two history entries, since we started off with navigation
727 // to "about:blank" and then navigated to "iframe_dns_error.html".
729 browser()->tab_strip_model()->GetActiveWebContents()->
730 GetController().GetEntryCount());
731 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
734 // This test fails regularly on win_rel trybots. See crbug.com/121540
736 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
738 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
740 // Test that a DNS error occuring in an iframe does not result in an
741 // additional session history entry.
742 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, MAYBE_IFrameDNSError_GoBack
) {
743 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
744 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
745 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
746 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
749 // This test fails regularly on win_rel trybots. See crbug.com/121540
751 // This fails on linux_aura bringup: http://crbug.com/163931
752 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
753 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
755 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
757 // Test that a DNS error occuring in an iframe does not result in an
758 // additional session history entry.
759 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, MAYBE_IFrameDNSError_GoBackAndForward
) {
760 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
761 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
762 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
763 GoForwardAndWaitForTitle("Blah", 1);
764 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
767 // Test that a DNS error occuring in an iframe, once the main document is
768 // completed loading, does not result in an additional session history entry.
769 // To ensure that the main document has completed loading, JavaScript is used to
770 // inject an iframe after loading is done.
771 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, IFrameDNSError_JavaScript
) {
772 content::WebContents
* wc
=
773 browser()->tab_strip_model()->GetActiveWebContents();
775 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED
);
777 // Load a regular web page, in which we will inject an iframe.
778 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
780 // We expect to have two history entries, since we started off with navigation
781 // to "about:blank" and then navigated to "title2.html".
782 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
784 std::string script
= "var frame = document.createElement('iframe');"
785 "frame.src = '" + fail_url
.spec() + "';"
786 "document.body.appendChild(frame);";
788 TestFailProvisionalLoadObserver
fail_observer(wc
);
789 content::WindowedNotificationObserver
load_observer(
790 content::NOTIFICATION_LOAD_STOP
,
791 content::Source
<NavigationController
>(&wc
->GetController()));
792 wc
->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script
));
793 load_observer
.Wait();
795 // Ensure we saw the expected failure.
796 EXPECT_EQ(fail_url
, fail_observer
.fail_url());
798 // Failed initial navigation of an iframe shouldn't be adding any history
800 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
803 // Do the same test, but with an iframe that doesn't have initial URL
805 script
= "var frame = document.createElement('iframe');"
806 "frame.id = 'target_frame';"
807 "document.body.appendChild(frame);";
809 content::WindowedNotificationObserver
load_observer(
810 content::NOTIFICATION_LOAD_STOP
,
811 content::Source
<NavigationController
>(&wc
->GetController()));
812 wc
->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script
));
813 load_observer
.Wait();
816 script
= "var f = document.getElementById('target_frame');"
817 "f.src = '" + fail_url
.spec() + "';";
819 TestFailProvisionalLoadObserver
fail_observer(wc
);
820 content::WindowedNotificationObserver
load_observer(
821 content::NOTIFICATION_LOAD_STOP
,
822 content::Source
<NavigationController
>(&wc
->GetController()));
823 wc
->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script
));
824 load_observer
.Wait();
826 EXPECT_EQ(fail_url
, fail_observer
.fail_url());
827 EXPECT_EQ(2, wc
->GetController().GetEntryCount());
829 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
832 // Checks that navigation corrections are not loaded when we receive an actual
834 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, Page404
) {
835 NavigateToURLAndWaitForTitle(
836 net::URLRequestMockHTTPJob::GetMockUrl(
837 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
840 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
843 // Checks that when an error occurs, the stale cache status of the page
844 // is correctly transferred, and that stale cached copied can be loaded
845 // from the javascript.
846 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, StaleCacheStatus
) {
847 ASSERT_TRUE(test_server()->Start());
848 // Load cache with entry with "nocache" set, to create stale
850 GURL
test_url(test_server()->GetURL("files/nocache.html"));
851 NavigateToURLAndWaitForTitle(test_url
, "Nocache Test Page", 1);
853 // Reload same URL after forcing an error from the the network layer;
854 // confirm that the error page is told the cached copy exists.
855 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter
=
856 browser()->profile()->GetRequestContext();
857 BrowserThread::PostTask(
858 BrowserThread::IO
, FROM_HERE
,
859 base::Bind(&InterceptNetworkTransactions
, url_request_context_getter
,
862 // With no navigation corrections to load, there's only one navigation.
863 ui_test_utils::NavigateToURL(browser(), test_url
);
864 EXPECT_TRUE(ProbeStaleCopyValue(true));
865 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
866 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
867 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
869 // Confirm that loading the stale copy from the cache works.
870 content::TestNavigationObserver
same_tab_observer(
871 browser()->tab_strip_model()->GetActiveWebContents(), 1);
872 ASSERT_TRUE(ReloadStaleCopyFromCache());
873 same_tab_observer
.Wait();
874 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
875 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
877 // Reload the same URL with a post request; confirm the error page is told
878 // that there is no cached copy.
879 ui_test_utils::NavigateToURLWithPost(browser(), test_url
);
880 EXPECT_TRUE(ProbeStaleCopyValue(false));
881 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
882 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
884 // Clear the cache and reload the same URL; confirm the error page is told
885 // that there is no cached copy.
886 BrowsingDataRemover
* remover
=
887 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
888 remover
->Remove(BrowsingDataRemover::REMOVE_CACHE
,
889 BrowsingDataHelper::UNPROTECTED_WEB
);
890 ui_test_utils::NavigateToURL(browser(), test_url
);
891 EXPECT_TRUE(ProbeStaleCopyValue(false));
892 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
893 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
896 // Check that the easter egg is present and initialised and is not disabled.
897 IN_PROC_BROWSER_TEST_F(ErrorPageTest
, CheckEasterEggIsNotDisabled
) {
898 ui_test_utils::NavigateToURL(browser(),
899 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED
));
901 content::WebContents
* web_contents
=
902 browser()->tab_strip_model()->GetActiveWebContents();
904 // Check for no disabled message container.
905 std::string command
= base::StringPrintf(
906 "var hasDisableContainer = document.querySelectorAll('.snackbar').length;"
907 "domAutomationController.send(hasDisableContainer);");
909 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
910 web_contents
, command
, &result
));
911 EXPECT_EQ(0, result
);
913 // Presence of the canvas container.
914 command
= base::StringPrintf(
915 "var runnerCanvas = document.querySelectorAll('.runner-canvas').length;"
916 "domAutomationController.send(runnerCanvas);");
917 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
918 web_contents
, command
, &result
));
919 EXPECT_EQ(1, result
);
922 class ErrorPageAutoReloadTest
: public InProcessBrowserTest
{
924 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
925 command_line
->AppendSwitch(switches::kEnableOfflineAutoReload
);
928 void InstallInterceptor(const GURL
& url
, int requests_to_fail
) {
929 interceptor_
= new FailFirstNRequestsInterceptor(requests_to_fail
);
930 scoped_ptr
<net::URLRequestInterceptor
> owned_interceptor(interceptor_
);
932 // Tests don't need to wait for this task to complete before using the
933 // filter; any requests that might be affected by it will end up in the IO
934 // thread's message loop after this posted task anyway.
936 // Ownership of the interceptor is passed to an object the IO thread, but a
937 // pointer is kept in the test fixture. As soon as anything calls
938 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
939 BrowserThread::PostTask(
940 BrowserThread::IO
, FROM_HERE
,
941 base::Bind(&AddInterceptorForURL
, url
,
942 base::Passed(&owned_interceptor
)));
945 void NavigateToURLAndWaitForTitle(const GURL
& url
,
946 const std::string
& expected_title
,
947 int num_navigations
) {
948 content::TitleWatcher
title_watcher(
949 browser()->tab_strip_model()->GetActiveWebContents(),
950 base::ASCIIToUTF16(expected_title
));
952 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
953 browser(), url
, num_navigations
);
955 EXPECT_EQ(base::ASCIIToUTF16(expected_title
),
956 title_watcher
.WaitAndGetTitle());
959 FailFirstNRequestsInterceptor
* interceptor() {
964 FailFirstNRequestsInterceptor
* interceptor_
;
967 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest
, AutoReload
) {
968 GURL
test_url("http://error.page.auto.reload");
969 const int kRequestsToFail
= 2;
970 InstallInterceptor(test_url
, kRequestsToFail
);
971 NavigateToURLAndWaitForTitle(test_url
, "Test One", kRequestsToFail
+ 1);
972 // Note that the interceptor updates these variables on the IO thread,
973 // but this function reads them on the main thread. The requests have to be
974 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
975 // this becomes racey.
976 EXPECT_EQ(kRequestsToFail
, interceptor()->failures());
977 EXPECT_EQ(kRequestsToFail
+ 1, interceptor()->requests());
980 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest
, ManualReloadNotSuppressed
) {
981 GURL
test_url("http://error.page.auto.reload");
982 const int kRequestsToFail
= 3;
983 InstallInterceptor(test_url
, kRequestsToFail
);
984 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
985 browser(), test_url
, 2);
987 EXPECT_EQ(2, interceptor()->failures());
988 EXPECT_EQ(2, interceptor()->requests());
990 ToggleHelpBox(browser());
991 EXPECT_TRUE(IsDisplayingText(browser(), "error.page.auto.reload"));
993 content::WebContents
* web_contents
=
994 browser()->tab_strip_model()->GetActiveWebContents();
995 content::TestNavigationObserver
nav_observer(web_contents
, 1);
996 web_contents
->GetMainFrame()->ExecuteJavaScript(
997 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
999 EXPECT_FALSE(IsDisplayingText(browser(), "error.page.auto.reload"));
1002 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
1003 class AddressUnreachableInterceptor
: public net::URLRequestInterceptor
{
1005 AddressUnreachableInterceptor() {}
1006 ~AddressUnreachableInterceptor() override
{}
1008 // net::URLRequestInterceptor:
1009 net::URLRequestJob
* MaybeInterceptRequest(
1010 net::URLRequest
* request
,
1011 net::NetworkDelegate
* network_delegate
) const override
{
1012 return new URLRequestFailedJob(request
,
1014 net::ERR_ADDRESS_UNREACHABLE
);
1018 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor
);
1021 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
1022 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
1023 // a different error for the correction service and the original page to
1024 // validate the right page is being displayed.
1025 class ErrorPageNavigationCorrectionsFailTest
: public ErrorPageTest
{
1027 // InProcessBrowserTest:
1028 void SetUpOnMainThread() override
{
1029 BrowserThread::PostTask(
1030 BrowserThread::IO
, FROM_HERE
,
1031 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters
));
1034 void TearDownOnMainThread() override
{
1035 BrowserThread::PostTask(
1036 BrowserThread::IO
, FROM_HERE
,
1037 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters
));
1041 // Adds a filter that causes all correction service requests to fail with
1042 // ERR_ADDRESS_UNREACHABLE.
1044 // Also adds the net::URLRequestFailedJob filter.
1045 static void AddFilters() {
1046 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1047 URLRequestFailedJob::AddUrlHandler();
1049 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
1050 google_util::LinkDoctorBaseURL(),
1051 scoped_ptr
<net::URLRequestInterceptor
>(
1052 new AddressUnreachableInterceptor()));
1055 static void RemoveFilters() {
1056 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1057 net::URLRequestFilter::GetInstance()->ClearHandlers();
1061 // Make sure that when corrections fail to load, the network error page is
1062 // successfully loaded.
1063 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest
,
1064 FetchCorrectionsFails
) {
1065 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1067 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED
),
1070 // Verify that the expected error page is being displayed.
1071 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED
);
1074 // Checks that when an error occurs and a corrections fail to load, the stale
1075 // cache status of the page is correctly transferred, and we can load the
1076 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1078 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest
,
1079 StaleCacheStatusFailedCorrections
) {
1080 ASSERT_TRUE(test_server()->Start());
1081 // Load cache with entry with "nocache" set, to create stale
1083 GURL
test_url(test_server()->GetURL("files/nocache.html"));
1084 NavigateToURLAndWaitForTitle(test_url
, "Nocache Test Page", 1);
1086 // Reload same URL after forcing an error from the the network layer;
1087 // confirm that the error page is told the cached copy exists.
1088 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter
=
1089 browser()->profile()->GetRequestContext();
1090 BrowserThread::PostTask(
1091 BrowserThread::IO
, FROM_HERE
,
1092 base::Bind(&InterceptNetworkTransactions
, url_request_context_getter
,
1093 net::ERR_CONNECTION_FAILED
));
1095 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1096 browser(), test_url
, 2);
1097 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1098 EXPECT_TRUE(ProbeStaleCopyValue(true));
1100 // Confirm that loading the stale copy from the cache works.
1101 content::TestNavigationObserver
same_tab_observer(
1102 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1103 ASSERT_TRUE(ReloadStaleCopyFromCache());
1104 same_tab_observer
.Wait();
1105 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1106 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1108 // Clear the cache and reload the same URL; confirm the error page is told
1109 // that there is no cached copy.
1110 BrowsingDataRemover
* remover
=
1111 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
1112 remover
->Remove(BrowsingDataRemover::REMOVE_CACHE
,
1113 BrowsingDataHelper::UNPROTECTED_WEB
);
1114 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1115 browser(), test_url
, 2);
1116 EXPECT_TRUE(ProbeStaleCopyValue(false));
1117 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1120 #if defined(OS_CHROMEOS)
1121 class ErrorPageOfflineTest
: public ErrorPageTest
{
1123 // Mock policy provider for both user and device policies.
1124 policy::MockConfigurationPolicyProvider policy_provider_
;
1126 void SetUpInProcessBrowserTestFixture() override
{
1127 // Set up fake install attributes.
1128 scoped_ptr
<policy::StubEnterpriseInstallAttributes
> attributes(
1129 new policy::StubEnterpriseInstallAttributes());
1130 attributes
->SetDomain("example.com");
1131 attributes
->SetRegistrationUser("user@example.com");
1132 policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
1133 attributes
.release());
1135 // Sets up a mock policy provider for user and device policies.
1136 EXPECT_CALL(policy_provider_
, IsInitializationComplete(testing::_
))
1137 .WillRepeatedly(testing::Return(true));
1138 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
1141 ErrorPageTest::SetUpInProcessBrowserTestFixture();
1145 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest
, CheckEasterEggIsDisabled
) {
1146 // Check for enterprise enrollment.
1147 policy::BrowserPolicyConnectorChromeOS
* connector
=
1148 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
1149 EXPECT_TRUE(connector
->IsEnterpriseManaged());
1151 ui_test_utils::NavigateToURL(browser(),
1152 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED
));
1154 content::WebContents
* web_contents
=
1155 browser()->tab_strip_model()->GetActiveWebContents();
1157 std::string command
= base::StringPrintf(
1158 "var hasText = document.querySelector('.snackbar').innerText;"
1159 "domAutomationController.send(hasText);");
1160 std::string result
= "";
1161 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1162 web_contents
, command
, &result
));
1164 std::string disabled_text
=
1165 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED
);
1166 EXPECT_EQ(disabled_text
, result
);
1170 // A test fixture that simulates failing requests for an IDN domain name.
1171 class ErrorPageForIDNTest
: public InProcessBrowserTest
{
1173 // Target hostname in different forms.
1174 static const char kHostname
[];
1175 static const char kHostnameJSUnicode
[];
1177 // InProcessBrowserTest:
1178 void SetUpOnMainThread() override
{
1179 // Clear AcceptLanguages to force punycode decoding.
1180 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages
,
1182 BrowserThread::PostTask(
1183 BrowserThread::IO
, FROM_HERE
,
1184 base::Bind(&ErrorPageForIDNTest::AddFilters
));
1187 void TearDownOnMainThread() override
{
1188 BrowserThread::PostTask(
1189 BrowserThread::IO
, FROM_HERE
,
1190 base::Bind(&ErrorPageForIDNTest::RemoveFilters
));
1194 static void AddFilters() {
1195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1196 URLRequestFailedJob::AddUrlHandlerForHostname(kHostname
);
1199 static void RemoveFilters() {
1200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
1201 net::URLRequestFilter::GetInstance()->ClearHandlers();
1205 const char ErrorPageForIDNTest::kHostname
[] =
1206 "xn--d1abbgf6aiiy.xn--p1ai";
1207 const char ErrorPageForIDNTest::kHostnameJSUnicode
[] =
1208 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1211 // Make sure error page shows correct unicode for IDN.
1212 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest
, IDN
) {
1213 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1214 ui_test_utils::NavigateToURL(
1216 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT
,
1219 ToggleHelpBox(browser());
1220 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode
));