Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: chrome/browser/errorpage_browsertest.cc

Issue 2205903003: Move chrome/browser/errorpage_browsertest.cc to chrome/browser/net. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/net/errorpage_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include <memory>
6 #include <utility>
7
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/compiler_specific.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/logging.h"
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/path_service.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/synchronization/lock.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/browsing_data/browsing_data_helper.h"
22 #include "chrome/browser/browsing_data/browsing_data_remover.h"
23 #include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
24 #include "chrome/browser/net/net_error_diagnostics_dialog.h"
25 #include "chrome/browser/net/url_request_mock_util.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
28 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_commands.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/common/chrome_paths.h"
32 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/pref_names.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/ui_test_utils.h"
36 #include "components/error_page/common/error_page_switches.h"
37 #include "components/google/core/browser/google_util.h"
38 #include "components/prefs/pref_service.h"
39 #include "components/strings/grit/components_strings.h"
40 #include "content/public/browser/browser_thread.h"
41 #include "content/public/browser/notification_service.h"
42 #include "content/public/browser/notification_types.h"
43 #include "content/public/browser/render_frame_host.h"
44 #include "content/public/browser/render_view_host.h"
45 #include "content/public/browser/web_contents.h"
46 #include "content/public/browser/web_contents_observer.h"
47 #include "content/public/test/browser_test_utils.h"
48 #include "content/public/test/test_navigation_observer.h"
49 #include "net/base/filename_util.h"
50 #include "net/base/net_errors.h"
51 #include "net/http/failing_http_transaction_factory.h"
52 #include "net/http/http_cache.h"
53 #include "net/test/embedded_test_server/embedded_test_server.h"
54 #include "net/test/url_request/url_request_failed_job.h"
55 #include "net/test/url_request/url_request_mock_http_job.h"
56 #include "net/url_request/url_request_context.h"
57 #include "net/url_request/url_request_context_getter.h"
58 #include "net/url_request/url_request_filter.h"
59 #include "net/url_request/url_request_interceptor.h"
60 #include "net/url_request/url_request_job.h"
61 #include "net/url_request/url_request_test_job.h"
62 #include "net/url_request/url_request_test_util.h"
63 #include "policy/policy_constants.h"
64 #include "ui/base/l10n/l10n_util.h"
65
66 #if defined(OS_CHROMEOS)
67 #include "chrome/browser/browser_process.h"
68 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
69 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
70 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
71 #include "components/policy/core/common/policy_types.h"
72 #else
73 #include "chrome/browser/policy/profile_policy_connector_factory.h"
74 #endif
75 #include "components/policy/core/common/mock_configuration_policy_provider.h"
76
77 using content::BrowserThread;
78 using content::NavigationController;
79 using net::URLRequestFailedJob;
80 using net::URLRequestTestJob;
81
82 namespace {
83
84 // Returns true if |text| is displayed on the page |browser| is currently
85 // displaying. Uses "innerText", so will miss hidden text, and whitespace
86 // space handling may be weird.
87 bool WARN_UNUSED_RESULT IsDisplayingText(Browser* browser,
88 const std::string& text) {
89 std::string command = base::StringPrintf(
90 "var textContent = document.body.innerText;"
91 "var hasText = textContent.indexOf('%s') >= 0;"
92 "domAutomationController.send(hasText);",
93 text.c_str());
94 bool result = false;
95 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
96 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
97 return result;
98 }
99
100 // Expands the more box on the currently displayed error page.
101 void ToggleHelpBox(Browser* browser) {
102 EXPECT_TRUE(content::ExecuteScript(
103 browser->tab_strip_model()->GetActiveWebContents(),
104 "document.getElementById('details-button').click();"));
105 }
106
107 // Returns true if the diagnostics link suggestion is displayed.
108 bool WARN_UNUSED_RESULT IsDisplayingDiagnosticsLink(Browser* browser) {
109 std::string command = base::StringPrintf(
110 "var diagnose_link = document.getElementById('diagnose-link');"
111 "domAutomationController.send(diagnose_link != null);");
112 bool result = false;
113 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
114 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
115 return result;
116 }
117
118 // Checks that the local error page is being displayed, without remotely
119 // retrieved navigation corrections, and with the specified error string.
120 void ExpectDisplayingLocalErrorPage(Browser* browser,
121 const std::string& error_string) {
122 EXPECT_TRUE(IsDisplayingText(browser, error_string));
123
124 // Locally generated error pages should not have navigation corrections.
125 EXPECT_FALSE(IsDisplayingText(browser, "http://mock.http/title2.html"));
126
127 // Locally generated error pages should not have a link with search terms.
128 EXPECT_FALSE(IsDisplayingText(browser, "search query"));
129 }
130
131 // Checks that the local error page is being displayed, without remotely
132 // retrieved navigation corrections, and with the specified error code.
133 void ExpectDisplayingLocalErrorPage(Browser* browser, net::Error error_code) {
134 ExpectDisplayingLocalErrorPage(browser, net::ErrorToShortString(error_code));
135 }
136
137 // Checks that an error page with information retrieved from the navigation
138 // correction service is being displayed, with the specified specified error
139 // string.
140 void ExpectDisplayingNavigationCorrections(Browser* browser,
141 const std::string& error_string) {
142 EXPECT_TRUE(IsDisplayingText(browser, error_string));
143
144 // Check that the mock navigation corrections are displayed.
145 EXPECT_TRUE(IsDisplayingText(browser, "http://mock.http/title2.html"));
146
147 // Check that the search terms are displayed as a link.
148 EXPECT_TRUE(IsDisplayingText(browser, "search query"));
149
150 // The diagnostics button isn't displayed when corrections were
151 // retrieved from a remote server.
152 EXPECT_FALSE(IsDisplayingDiagnosticsLink(browser));
153 }
154
155 // Checks that an error page with information retrieved from the navigation
156 // correction service is being displayed, with the specified specified error
157 // code.
158 void ExpectDisplayingNavigationCorrections(Browser* browser,
159 net::Error error_code) {
160 ExpectDisplayingNavigationCorrections(browser,
161 net::ErrorToShortString(error_code));
162 }
163
164 std::string GetShowSavedButtonLabel() {
165 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY);
166 }
167
168 void AddInterceptorForURL(const GURL& url,
169 std::unique_ptr<net::URLRequestInterceptor> handler) {
170 DCHECK_CURRENTLY_ON(BrowserThread::IO);
171 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(url,
172 std::move(handler));
173 }
174
175 // An interceptor that fails a configurable number of requests, then succeeds
176 // all requests after that, keeping count of failures and successes.
177 class FailFirstNRequestsInterceptor : public net::URLRequestInterceptor {
178 public:
179 explicit FailFirstNRequestsInterceptor(int requests_to_fail)
180 : requests_(0), failures_(0), requests_to_fail_(requests_to_fail) {}
181 ~FailFirstNRequestsInterceptor() override {}
182
183 // net::URLRequestInterceptor implementation
184 net::URLRequestJob* MaybeInterceptRequest(
185 net::URLRequest* request,
186 net::NetworkDelegate* network_delegate) const override {
187 DCHECK_CURRENTLY_ON(BrowserThread::IO);
188 requests_++;
189 if (failures_ < requests_to_fail_) {
190 failures_++;
191 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
192 // NetErrorHelperCore::GetErrorPageURL.
193 return new URLRequestFailedJob(request,
194 network_delegate,
195 net::ERR_CONNECTION_RESET);
196 } else {
197 return new URLRequestTestJob(request, network_delegate,
198 URLRequestTestJob::test_headers(),
199 URLRequestTestJob::test_data_1(),
200 true);
201 }
202 }
203
204 int requests() const { return requests_; }
205 int failures() const { return failures_; }
206
207 private:
208 // These are mutable because MaybeCreateJob is const but we want this state
209 // for testing.
210 mutable int requests_;
211 mutable int failures_;
212 int requests_to_fail_;
213
214 DISALLOW_COPY_AND_ASSIGN(FailFirstNRequestsInterceptor);
215 };
216
217 // An interceptor that serves LinkDoctor responses. It also allows waiting
218 // until a certain number of requests have been sent.
219 // TODO(mmenke): Wait until responses have been received instead.
220 class LinkDoctorInterceptor : public net::URLRequestInterceptor {
221 public:
222 LinkDoctorInterceptor() : num_requests_(0),
223 requests_to_wait_for_(-1),
224 weak_factory_(this) {
225 }
226
227 ~LinkDoctorInterceptor() override {}
228
229 // net::URLRequestInterceptor implementation
230 net::URLRequestJob* MaybeInterceptRequest(
231 net::URLRequest* request,
232 net::NetworkDelegate* network_delegate) const override {
233 DCHECK_CURRENTLY_ON(BrowserThread::IO);
234
235 BrowserThread::PostTask(
236 BrowserThread::UI, FROM_HERE,
237 base::Bind(&LinkDoctorInterceptor::RequestCreated,
238 weak_factory_.GetWeakPtr()));
239
240 base::FilePath root_http;
241 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
242 return new net::URLRequestMockHTTPJob(
243 request,
244 network_delegate,
245 root_http.AppendASCII("mock-link-doctor.json"),
246 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
247 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
248 }
249
250 void WaitForRequests(int requests_to_wait_for) {
251 DCHECK_CURRENTLY_ON(BrowserThread::UI);
252 DCHECK_EQ(-1, requests_to_wait_for_);
253 DCHECK(!run_loop_);
254
255 if (requests_to_wait_for >= num_requests_)
256 return;
257
258 requests_to_wait_for_ = requests_to_wait_for;
259 run_loop_.reset(new base::RunLoop());
260 run_loop_->Run();
261 run_loop_.reset();
262 requests_to_wait_for_ = -1;
263 EXPECT_EQ(num_requests_, requests_to_wait_for);
264 }
265
266 // It is up to the caller to wait until all relevant requests has been
267 // created, either through calling WaitForRequests or some other manner,
268 // before calling this method.
269 int num_requests() const {
270 DCHECK_CURRENTLY_ON(BrowserThread::UI);
271 return num_requests_;
272 }
273
274 private:
275 void RequestCreated() {
276 DCHECK_CURRENTLY_ON(BrowserThread::UI);
277
278 num_requests_++;
279 if (num_requests_ == requests_to_wait_for_)
280 run_loop_->Quit();
281 }
282
283 // These are only used on the UI thread.
284 int num_requests_;
285 int requests_to_wait_for_;
286 std::unique_ptr<base::RunLoop> run_loop_;
287
288 // This prevents any risk of flake if any test doesn't wait for a request
289 // it sent. Mutable so it can be accessed from a const function.
290 mutable base::WeakPtrFactory<LinkDoctorInterceptor> weak_factory_;
291
292 DISALLOW_COPY_AND_ASSIGN(LinkDoctorInterceptor);
293 };
294
295 void InstallMockInterceptors(
296 const GURL& search_url,
297 std::unique_ptr<net::URLRequestInterceptor> link_doctor_interceptor) {
298 chrome_browser_net::SetUrlRequestMocksEnabled(true);
299
300 AddInterceptorForURL(google_util::LinkDoctorBaseURL(),
301 std::move(link_doctor_interceptor));
302
303 // Add a mock for the search engine the error page will use.
304 base::FilePath root_http;
305 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
306 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
307 search_url.scheme(), search_url.host(),
308 net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
309 root_http.AppendASCII("title3.html"),
310 BrowserThread::GetBlockingPool()));
311 }
312
313 class ErrorPageTest : public InProcessBrowserTest {
314 public:
315 enum HistoryNavigationDirection {
316 HISTORY_NAVIGATE_BACK,
317 HISTORY_NAVIGATE_FORWARD,
318 };
319
320 ErrorPageTest() : link_doctor_interceptor_(NULL) {}
321 ~ErrorPageTest() override {}
322
323 // Navigates the active tab to a mock url created for the file at |file_path|.
324 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
325 void SetUpCommandLine(base::CommandLine* command_line) override {
326 command_line->AppendSwitchASCII(
327 error_page::switches::kShowSavedCopy,
328 error_page::switches::kEnableShowSavedCopyPrimary);
329 }
330
331 // Navigates the active tab to a mock url created for the file at |path|.
332 void NavigateToFileURL(const std::string& path) {
333 ui_test_utils::NavigateToURL(browser(),
334 net::URLRequestMockHTTPJob::GetMockUrl(path));
335 }
336
337 // Navigates to the given URL and waits for |num_navigations| to occur, and
338 // the title to change to |expected_title|.
339 void NavigateToURLAndWaitForTitle(const GURL& url,
340 const std::string& expected_title,
341 int num_navigations) {
342 content::TitleWatcher title_watcher(
343 browser()->tab_strip_model()->GetActiveWebContents(),
344 base::ASCIIToUTF16(expected_title));
345
346 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
347 browser(), url, num_navigations);
348
349 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
350 title_watcher.WaitAndGetTitle());
351 }
352
353 // Navigates back in the history and waits for |num_navigations| to occur, and
354 // the title to change to |expected_title|.
355 void GoBackAndWaitForTitle(const std::string& expected_title,
356 int num_navigations) {
357 NavigateHistoryAndWaitForTitle(expected_title,
358 num_navigations,
359 HISTORY_NAVIGATE_BACK);
360 }
361
362 // Navigates forward in the history and waits for |num_navigations| to occur,
363 // and the title to change to |expected_title|.
364 void GoForwardAndWaitForTitle(const std::string& expected_title,
365 int num_navigations) {
366 NavigateHistoryAndWaitForTitle(expected_title,
367 num_navigations,
368 HISTORY_NAVIGATE_FORWARD);
369 }
370
371 void GoBackAndWaitForNavigations(int num_navigations) {
372 NavigateHistory(num_navigations, HISTORY_NAVIGATE_BACK);
373 }
374
375 void GoForwardAndWaitForNavigations(int num_navigations) {
376 NavigateHistory(num_navigations, HISTORY_NAVIGATE_FORWARD);
377 }
378
379 // Confirms that the javascript variable indicating whether or not we have
380 // a stale copy in the cache has been set to |expected|, and that the
381 // stale load button is or isn't there based on the same expectation.
382 testing::AssertionResult ProbeStaleCopyValue(bool expected) {
383 const char* js_cache_probe =
384 "try {\n"
385 " domAutomationController.send(\n"
386 " loadTimeData.valueExists('showSavedCopyButton') ?"
387 " 'yes' : 'no');\n"
388 "} catch (e) {\n"
389 " domAutomationController.send(e.message);\n"
390 "}\n";
391
392 std::string result;
393 bool ret =
394 content::ExecuteScriptAndExtractString(
395 browser()->tab_strip_model()->GetActiveWebContents(),
396 js_cache_probe,
397 &result);
398 if (!ret) {
399 return testing::AssertionFailure()
400 << "Failing return from ExecuteScriptAndExtractString.";
401 }
402
403 if ((expected && "yes" == result) || (!expected && "no" == result))
404 return testing::AssertionSuccess();
405
406 return testing::AssertionFailure() << "Cache probe result is " << result;
407 }
408
409 testing::AssertionResult ReloadStaleCopyFromCache() {
410 const char* js_reload_script =
411 "try {\n"
412 " document.getElementById('show-saved-copy-button').click();\n"
413 " domAutomationController.send('success');\n"
414 "} catch (e) {\n"
415 " domAutomationController.send(e.message);\n"
416 "}\n";
417
418 std::string result;
419 bool ret = content::ExecuteScriptAndExtractString(
420 browser()->tab_strip_model()->GetActiveWebContents(),
421 js_reload_script,
422 &result);
423 EXPECT_TRUE(ret);
424 if (!ret)
425 return testing::AssertionFailure();
426 return ("success" == result ? testing::AssertionSuccess() :
427 (testing::AssertionFailure() << "Exception message is " << result));
428 }
429
430 LinkDoctorInterceptor* link_doctor_interceptor() {
431 return link_doctor_interceptor_;
432 }
433
434 protected:
435 void SetUpOnMainThread() override {
436 link_doctor_interceptor_ = new LinkDoctorInterceptor();
437 std::unique_ptr<net::URLRequestInterceptor> owned_interceptor(
438 link_doctor_interceptor_);
439 // Ownership of the |interceptor_| is passed to an object the IO thread, but
440 // a pointer is kept in the test fixture. As soon as anything calls
441 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
442 UIThreadSearchTermsData search_terms_data(browser()->profile());
443 BrowserThread::PostTask(
444 BrowserThread::IO, FROM_HERE,
445 base::Bind(&InstallMockInterceptors,
446 GURL(search_terms_data.GoogleBaseURLValue()),
447 base::Passed(&owned_interceptor)));
448 }
449
450 // Returns a GURL that results in a DNS error.
451 GURL GetDnsErrorURL() const {
452 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
453 }
454
455 // Returns true if the platform has support for a diagnostics tool, which
456 // can be launched from the error page.
457 bool PlatformSupportsDiagnosticsTool() {
458 #if defined(OS_CHROMEOS)
459 // ChromeOS uses an extension instead of a diagnostics dialog.
460 return true;
461 #else
462 return CanShowNetworkDiagnosticsDialog();
463 #endif
464 }
465
466 private:
467 // Navigates the browser the indicated direction in the history and waits for
468 // |num_navigations| to occur and the title to change to |expected_title|.
469 void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
470 int num_navigations,
471 HistoryNavigationDirection direction) {
472 content::TitleWatcher title_watcher(
473 browser()->tab_strip_model()->GetActiveWebContents(),
474 base::ASCIIToUTF16(expected_title));
475
476 NavigateHistory(num_navigations, direction);
477
478 EXPECT_EQ(title_watcher.WaitAndGetTitle(),
479 base::ASCIIToUTF16(expected_title));
480 }
481
482 void NavigateHistory(int num_navigations,
483 HistoryNavigationDirection direction) {
484 content::TestNavigationObserver test_navigation_observer(
485 browser()->tab_strip_model()->GetActiveWebContents(),
486 num_navigations);
487 if (direction == HISTORY_NAVIGATE_BACK) {
488 chrome::GoBack(browser(), CURRENT_TAB);
489 } else if (direction == HISTORY_NAVIGATE_FORWARD) {
490 chrome::GoForward(browser(), CURRENT_TAB);
491 } else {
492 FAIL();
493 }
494 test_navigation_observer.Wait();
495 }
496
497 LinkDoctorInterceptor* link_doctor_interceptor_;
498 };
499
500 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
501 public:
502 explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
503 : content::WebContentsObserver(contents) {}
504 ~TestFailProvisionalLoadObserver() override {}
505
506 // This method is invoked when the provisional load failed.
507 void DidFailProvisionalLoad(
508 content::RenderFrameHost* render_frame_host,
509 const GURL& validated_url,
510 int error_code,
511 const base::string16& error_description,
512 bool was_ignored_by_handler) override {
513 fail_url_ = validated_url;
514 }
515
516 const GURL& fail_url() const { return fail_url_; }
517
518 private:
519 GURL fail_url_;
520
521 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
522 };
523
524 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
525 net::Error error) {
526 DCHECK_CURRENTLY_ON(BrowserThread::IO);
527 net::HttpCache* cache(
528 getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
529 DCHECK(cache);
530 std::unique_ptr<net::HttpTransactionFactory> factory(
531 new net::FailingHttpTransactionFactory(cache->GetSession(), error));
532 // Throw away old version; since this is a a browser test, we don't
533 // need to restore the old state.
534 cache->SetHttpNetworkTransactionFactoryForTesting(std::move(factory));
535 }
536
537 // Test an error with a file URL, and make sure it doesn't have a
538 // button to launch a network diagnostics tool.
539 IN_PROC_BROWSER_TEST_F(ErrorPageTest, FileNotFound) {
540 // Create an empty temp directory, to be sure there's no file in it.
541 base::ScopedTempDir temp_dir;
542 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
543 GURL non_existent_file_url =
544 net::FilePathToFileURL(temp_dir.path().AppendASCII("marmoset"));
545
546 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
547 browser(), non_existent_file_url, 1);
548
549 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FILE_NOT_FOUND);
550 // Should not request Link Doctor corrections for local errors.
551 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
552 // Only errors on HTTP/HTTPS pages should display a diagnostics button.
553 EXPECT_FALSE(IsDisplayingDiagnosticsLink(browser()));
554 }
555
556 // Check an network error page for ERR_FAILED. In particular, this should
557 // not trigger a link doctor error page.
558 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Failed) {
559 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
560 browser(), URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED), 1);
561
562 ExpectDisplayingLocalErrorPage(browser(), net::ERR_FAILED);
563 // Should not request Link Doctor corrections for this error.
564 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
565 }
566
567 // Test that a DNS error occuring in the main frame redirects to an error page.
568 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_Basic) {
569 // The first navigation should fail and load a blank page, while it fetches
570 // the Link Doctor response. The second navigation is the Link Doctor.
571 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
572 browser(), GetDnsErrorURL(), 2);
573 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
574 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
575 }
576
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_GoBack1) {
580 NavigateToFileURL("title2.html");
581 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
582 browser(), GetDnsErrorURL(), 2);
583 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
584 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
585 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
586 }
587
588 // Test that a DNS error occuring in the main frame does not result in an
589 // additional session history entry.
590 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
591 NavigateToFileURL("title2.html");
592
593 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
594 browser(), GetDnsErrorURL(), 2);
595 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
596 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
597
598 NavigateToFileURL("title3.html");
599
600 GoBackAndWaitForNavigations(2);
601 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
602 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
603
604 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
605 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
606 }
607
608 // Test that a DNS error occuring in the main frame does not result in an
609 // additional session history entry.
610 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
611 NavigateToFileURL("title2.html");
612
613 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
614 browser(), GetDnsErrorURL(), 2);
615 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
616 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
617
618 NavigateToFileURL("title3.html");
619
620 GoBackAndWaitForNavigations(2);
621 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
622 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
623
624 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
625
626 GoForwardAndWaitForNavigations(2);
627 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
628 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
629 }
630
631 // Test that a DNS error occuring in the main frame does not result in an
632 // additional session history entry.
633 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
634 NavigateToFileURL("title3.html");
635
636 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
637 browser(), GetDnsErrorURL(), 2);
638 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
639 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
640
641 NavigateToFileURL("title2.html");
642
643 GoBackAndWaitForNavigations(2);
644 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
645 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
646
647 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
648
649 GoForwardAndWaitForNavigations(2);
650 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
651 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
652
653 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
654 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
655 }
656
657 // Test that the search link on a DNS error page works.
658 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoSearch) {
659 // The first navigation should fail, and the second one should be the error
660 // page.
661 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
662 browser(), GetDnsErrorURL(), 2);
663 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
664 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
665
666 content::WebContents* web_contents =
667 browser()->tab_strip_model()->GetActiveWebContents();
668
669 // Do a search and make sure the browser ends up at the right page.
670 content::TestNavigationObserver nav_observer(web_contents, 1);
671 content::TitleWatcher title_watcher(
672 web_contents,
673 base::ASCIIToUTF16("Title Of More Awesomeness"));
674 // Can't use content::ExecuteScript because it waits for scripts to send
675 // notification that they've run, and scripts that trigger a navigation may
676 // not send that notification.
677 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
678 base::ASCIIToUTF16("document.getElementById('search-link').click();"));
679 nav_observer.Wait();
680 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
681 title_watcher.WaitAndGetTitle());
682
683 // There should have been another Link Doctor request, for tracking purposes.
684 // Have to wait for it, since the search page does not depend on having
685 // sent the tracking request.
686 link_doctor_interceptor()->WaitForRequests(2);
687 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
688
689 // Check the path and query string.
690 std::string url;
691 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
692 browser()->tab_strip_model()->GetActiveWebContents(),
693 "domAutomationController.send(window.location.href);",
694 &url));
695 EXPECT_EQ("/search", GURL(url).path());
696 EXPECT_EQ("q=search%20query", GURL(url).query());
697
698 // Go back to the error page, to make sure the history is correct.
699 GoBackAndWaitForNavigations(2);
700 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
701 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
702 }
703
704 // Test that the reload button on a DNS error page works.
705 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoReload) {
706 // The first navigation should fail, and the second one should be the error
707 // page.
708 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
709 browser(), GetDnsErrorURL(), 2);
710 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
711 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
712
713 content::WebContents* web_contents =
714 browser()->tab_strip_model()->GetActiveWebContents();
715
716 // Clicking the reload button should load the error page again, and there
717 // should be two commits, as before.
718 content::TestNavigationObserver nav_observer(web_contents, 2);
719 // Can't use content::ExecuteScript because it waits for scripts to send
720 // notification that they've run, and scripts that trigger a navigation may
721 // not send that notification.
722 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
723 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
724 nav_observer.Wait();
725 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
726
727 // There should have been two more requests to the correction service: One
728 // for the new error page, and one for tracking purposes. Have to make sure
729 // to wait for the tracking request, since the new error page does not depend
730 // on it.
731 link_doctor_interceptor()->WaitForRequests(3);
732 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
733 }
734
735 // Test that the reload button on a DNS error page works after a same page
736 // navigation on the error page. Error pages don't seem to do this, but some
737 // traces indicate this may actually happen. This test may hang on regression.
738 IN_PROC_BROWSER_TEST_F(ErrorPageTest,
739 DNSError_DoReloadAfterSamePageNavigation) {
740 // The first navigation should fail, and the second one should be the error
741 // page.
742 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
743 browser(), GetDnsErrorURL(), 2);
744 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
745 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
746
747 content::WebContents* web_contents =
748 browser()->tab_strip_model()->GetActiveWebContents();
749
750 // Do a same page navigation.
751 content::TestNavigationObserver nav_observer1(web_contents, 1);
752 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
753 base::ASCIIToUTF16("document.location='#';"));
754 // The same page navigation counts as a single navigation as far as the
755 // TestNavigationObserver is concerned.
756 nav_observer1.Wait();
757 // Page being displayed should not change.
758 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
759 // No new requests should have been issued.
760 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
761
762 // Clicking the reload button should load the error page again, and there
763 // should be two commits, as before.
764 content::TestNavigationObserver nav_observer2(web_contents, 2);
765 // Can't use content::ExecuteScript because it waits for scripts to send
766 // notification that they've run, and scripts that trigger a navigation may
767 // not send that notification.
768 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
769 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
770 nav_observer2.Wait();
771 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
772
773 // There should have been two more requests to the correction service: One
774 // for the new error page, and one for tracking purposes. Have to make sure
775 // to wait for the tracking request, since the new error page does not depend
776 // on it.
777 link_doctor_interceptor()->WaitForRequests(3);
778 EXPECT_EQ(3, link_doctor_interceptor()->num_requests());
779 }
780
781 // Test that clicking links on a DNS error page works.
782 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_DoClickLink) {
783 // The first navigation should fail, and the second one should be the error
784 // page.
785 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
786 browser(), GetDnsErrorURL(), 2);
787 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
788 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
789
790 content::WebContents* web_contents =
791 browser()->tab_strip_model()->GetActiveWebContents();
792
793 // Simulate a click on a link.
794
795 content::TitleWatcher title_watcher(
796 web_contents,
797 base::ASCIIToUTF16("Title Of Awesomeness"));
798 std::string link_selector =
799 "document.querySelector('a[href=\"http://mock.http/title2.html\"]')";
800 // The tracking request is triggered by onmousedown, so it catches middle
801 // mouse button clicks, as well as left clicks.
802 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
803 base::ASCIIToUTF16(link_selector + ".onmousedown();"));
804 // Can't use content::ExecuteScript because it waits for scripts to send
805 // notification that they've run, and scripts that trigger a navigation may
806 // not send that notification.
807 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
808 base::ASCIIToUTF16(link_selector + ".click();"));
809 EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
810 title_watcher.WaitAndGetTitle());
811
812 // There should have been a tracking request to the correction service. Have
813 // to make sure to wait the tracking request, since the new page does not
814 // depend on it.
815 link_doctor_interceptor()->WaitForRequests(2);
816 EXPECT_EQ(2, link_doctor_interceptor()->num_requests());
817 }
818
819 // Test that a DNS error occuring in an iframe does not result in showing
820 // navigation corrections.
821 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
822 NavigateToURLAndWaitForTitle(
823 net::URLRequestMockHTTPJob::GetMockUrl("iframe_dns_error.html"), "Blah",
824 1);
825 // We expect to have two history entries, since we started off with navigation
826 // to "about:blank" and then navigated to "iframe_dns_error.html".
827 EXPECT_EQ(2,
828 browser()->tab_strip_model()->GetActiveWebContents()->
829 GetController().GetEntryCount());
830 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
831 }
832
833 // This test fails regularly on win_rel trybots. See crbug.com/121540
834 #if defined(OS_WIN)
835 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
836 #else
837 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
838 #endif
839 // Test that a DNS error occuring in an iframe does not result in an
840 // additional session history entry.
841 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
842 NavigateToFileURL("title2.html");
843 NavigateToFileURL("iframe_dns_error.html");
844 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
845 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
846 }
847
848 // This test fails regularly on win_rel trybots. See crbug.com/121540
849 //
850 // This fails on linux_aura bringup: http://crbug.com/163931
851 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(US E_AURA))
852 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndF orward
853 #else
854 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
855 #endif
856 // Test that a DNS error occuring in an iframe does not result in an
857 // additional session history entry.
858 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
859 NavigateToFileURL("title2.html");
860 NavigateToFileURL("iframe_dns_error.html");
861 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
862 GoForwardAndWaitForTitle("Blah", 1);
863 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
864 }
865
866 // Test that a DNS error occuring in an iframe, once the main document is
867 // completed loading, does not result in an additional session history entry.
868 // To ensure that the main document has completed loading, JavaScript is used to
869 // inject an iframe after loading is done.
870 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
871 content::WebContents* wc =
872 browser()->tab_strip_model()->GetActiveWebContents();
873 GURL fail_url =
874 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
875
876 // Load a regular web page, in which we will inject an iframe.
877 NavigateToFileURL("title2.html");
878
879 // We expect to have two history entries, since we started off with navigation
880 // to "about:blank" and then navigated to "title2.html".
881 EXPECT_EQ(2, wc->GetController().GetEntryCount());
882
883 std::string script = "var frame = document.createElement('iframe');"
884 "frame.src = '" + fail_url.spec() + "';"
885 "document.body.appendChild(frame);";
886 {
887 TestFailProvisionalLoadObserver fail_observer(wc);
888 content::WindowedNotificationObserver load_observer(
889 content::NOTIFICATION_LOAD_STOP,
890 content::Source<NavigationController>(&wc->GetController()));
891 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
892 load_observer.Wait();
893
894 // Ensure we saw the expected failure.
895 EXPECT_EQ(fail_url, fail_observer.fail_url());
896
897 // Failed initial navigation of an iframe shouldn't be adding any history
898 // entries.
899 EXPECT_EQ(2, wc->GetController().GetEntryCount());
900 }
901
902 // Do the same test, but with an iframe that doesn't have initial URL
903 // assigned.
904 script = "var frame = document.createElement('iframe');"
905 "frame.id = 'target_frame';"
906 "document.body.appendChild(frame);";
907 {
908 content::WindowedNotificationObserver load_observer(
909 content::NOTIFICATION_LOAD_STOP,
910 content::Source<NavigationController>(&wc->GetController()));
911 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
912 load_observer.Wait();
913 }
914
915 script = "var f = document.getElementById('target_frame');"
916 "f.src = '" + fail_url.spec() + "';";
917 {
918 TestFailProvisionalLoadObserver fail_observer(wc);
919 content::WindowedNotificationObserver load_observer(
920 content::NOTIFICATION_LOAD_STOP,
921 content::Source<NavigationController>(&wc->GetController()));
922 wc->GetMainFrame()->ExecuteJavaScriptForTests(base::ASCIIToUTF16(script));
923 load_observer.Wait();
924
925 EXPECT_EQ(fail_url, fail_observer.fail_url());
926 EXPECT_EQ(2, wc->GetController().GetEntryCount());
927 }
928 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
929 }
930
931 // Checks that navigation corrections are not loaded when we receive an actual
932 // 404 page.
933 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
934 NavigateToURLAndWaitForTitle(
935 net::URLRequestMockHTTPJob::GetMockUrl("page404.html"), "SUCCESS", 1);
936 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
937 }
938
939 // Checks that navigation corrections are loaded in response to a 404 page with
940 // no body.
941 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Empty404) {
942 // The first navigation should fail and load a blank page, while it fetches
943 // the Link Doctor response. The second navigation is the Link Doctor.
944 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
945 browser(),
946 net::URLRequestMockHTTPJob::GetMockUrl("errorpage/empty404.html"), 2);
947 // This depends on the non-internationalized error ID string in
948 // localized_error.cc.
949 ExpectDisplayingNavigationCorrections(browser(), "HTTP ERROR 404");
950 EXPECT_EQ(1, link_doctor_interceptor()->num_requests());
951 }
952
953 // Checks that a local error page is shown in response to a 500 error page
954 // without a body.
955 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Empty500) {
956 NavigateToFileURL("errorpage/empty500.html");
957 // This depends on the non-internationalized error ID string in
958 // localized_error.cc.
959 ExpectDisplayingLocalErrorPage(browser(), "HTTP ERROR 500");
960 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
961 }
962
963 // Checks that when an error occurs, the stale cache status of the page
964 // is correctly transferred, and that stale cached copied can be loaded
965 // from the javascript.
966 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
967 ASSERT_TRUE(embedded_test_server()->Start());
968 // Load cache with entry with "nocache" set, to create stale
969 // cache.
970 GURL test_url(embedded_test_server()->GetURL("/nocache.html"));
971 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
972
973 // Reload same URL after forcing an error from the the network layer;
974 // confirm that the error page is told the cached copy exists.
975 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
976 browser()->profile()->GetRequestContext();
977 BrowserThread::PostTask(
978 BrowserThread::IO, FROM_HERE,
979 base::Bind(&InterceptNetworkTransactions,
980 base::RetainedRef(url_request_context_getter),
981 net::ERR_FAILED));
982
983 // With no navigation corrections to load, there's only one navigation.
984 ui_test_utils::NavigateToURL(browser(), test_url);
985 EXPECT_TRUE(ProbeStaleCopyValue(true));
986 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
987 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
988 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
989
990 // Confirm that loading the stale copy from the cache works.
991 content::TestNavigationObserver same_tab_observer(
992 browser()->tab_strip_model()->GetActiveWebContents(), 1);
993 ASSERT_TRUE(ReloadStaleCopyFromCache());
994 same_tab_observer.Wait();
995 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
996 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
997
998 // Reload the same URL with a post request; confirm the error page is told
999 // that there is no cached copy.
1000 ui_test_utils::NavigateToURLWithPost(browser(), test_url);
1001 EXPECT_TRUE(ProbeStaleCopyValue(false));
1002 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1003 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
1004
1005 // Clear the cache and reload the same URL; confirm the error page is told
1006 // that there is no cached copy.
1007 BrowsingDataRemover* remover =
1008 BrowsingDataRemoverFactory::GetForBrowserContext(browser()->profile());
1009 remover->Remove(BrowsingDataRemover::Unbounded(),
1010 BrowsingDataRemover::REMOVE_CACHE,
1011 BrowsingDataHelper::UNPROTECTED_WEB);
1012 ui_test_utils::NavigateToURL(browser(), test_url);
1013 EXPECT_TRUE(ProbeStaleCopyValue(false));
1014 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1015 EXPECT_EQ(0, link_doctor_interceptor()->num_requests());
1016 }
1017
1018 // Check that the easter egg is present and initialised and is not disabled.
1019 IN_PROC_BROWSER_TEST_F(ErrorPageTest, CheckEasterEggIsNotDisabled) {
1020 ui_test_utils::NavigateToURL(browser(),
1021 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
1022
1023 content::WebContents* web_contents =
1024 browser()->tab_strip_model()->GetActiveWebContents();
1025
1026 // Check for no disabled message container.
1027 std::string command = base::StringPrintf(
1028 "var hasDisableContainer = document.querySelectorAll('.snackbar').length;"
1029 "domAutomationController.send(hasDisableContainer);");
1030 int result;
1031 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
1032 web_contents, command, &result));
1033 EXPECT_EQ(0, result);
1034
1035 // Presence of the canvas container.
1036 command = base::StringPrintf(
1037 "var runnerCanvas = document.querySelectorAll('.runner-canvas').length;"
1038 "domAutomationController.send(runnerCanvas);");
1039 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
1040 web_contents, command, &result));
1041 EXPECT_EQ(1, result);
1042 }
1043
1044 class ErrorPageAutoReloadTest : public InProcessBrowserTest {
1045 public:
1046 void SetUpCommandLine(base::CommandLine* command_line) override {
1047 command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
1048 }
1049
1050 void InstallInterceptor(const GURL& url, int requests_to_fail) {
1051 interceptor_ = new FailFirstNRequestsInterceptor(requests_to_fail);
1052 std::unique_ptr<net::URLRequestInterceptor> owned_interceptor(interceptor_);
1053
1054 // Tests don't need to wait for this task to complete before using the
1055 // filter; any requests that might be affected by it will end up in the IO
1056 // thread's message loop after this posted task anyway.
1057 //
1058 // Ownership of the interceptor is passed to an object the IO thread, but a
1059 // pointer is kept in the test fixture. As soon as anything calls
1060 // URLRequestFilter::ClearHandlers(), |interceptor_| can become invalid.
1061 BrowserThread::PostTask(
1062 BrowserThread::IO, FROM_HERE,
1063 base::Bind(&AddInterceptorForURL, url,
1064 base::Passed(&owned_interceptor)));
1065 }
1066
1067 void NavigateToURLAndWaitForTitle(const GURL& url,
1068 const std::string& expected_title,
1069 int num_navigations) {
1070 content::TitleWatcher title_watcher(
1071 browser()->tab_strip_model()->GetActiveWebContents(),
1072 base::ASCIIToUTF16(expected_title));
1073
1074 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1075 browser(), url, num_navigations);
1076
1077 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
1078 title_watcher.WaitAndGetTitle());
1079 }
1080
1081 FailFirstNRequestsInterceptor* interceptor() {
1082 return interceptor_;
1083 }
1084
1085 private:
1086 FailFirstNRequestsInterceptor* interceptor_;
1087 };
1088
1089 // Fails on official mac_trunk build. See crbug.com/465789.
1090 #if defined(OFFICIAL_BUILD) && defined(OS_MACOSX)
1091 #define MAYBE_AutoReload DISABLED_AutoReload
1092 #else
1093 #define MAYBE_AutoReload AutoReload
1094 #endif
1095 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, MAYBE_AutoReload) {
1096 GURL test_url("http://error.page.auto.reload");
1097 const int kRequestsToFail = 2;
1098 InstallInterceptor(test_url, kRequestsToFail);
1099 NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
1100 // Note that the interceptor updates these variables on the IO thread,
1101 // but this function reads them on the main thread. The requests have to be
1102 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
1103 // this becomes racey.
1104 EXPECT_EQ(kRequestsToFail, interceptor()->failures());
1105 EXPECT_EQ(kRequestsToFail + 1, interceptor()->requests());
1106 }
1107
1108 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, ManualReloadNotSuppressed) {
1109 GURL test_url("http://error.page.auto.reload");
1110 const int kRequestsToFail = 3;
1111 InstallInterceptor(test_url, kRequestsToFail);
1112 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1113 browser(), test_url, 2);
1114
1115 EXPECT_EQ(2, interceptor()->failures());
1116 EXPECT_EQ(2, interceptor()->requests());
1117
1118 ToggleHelpBox(browser());
1119 EXPECT_TRUE(IsDisplayingText(browser(), l10n_util::GetStringUTF8(
1120 IDS_ERRORPAGES_SUGGESTION_CHECK_CONNECTION_HEADER)));
1121
1122 content::WebContents* web_contents =
1123 browser()->tab_strip_model()->GetActiveWebContents();
1124 content::TestNavigationObserver nav_observer(web_contents, 1);
1125 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
1126 base::ASCIIToUTF16("document.getElementById('reload-button').click();"));
1127 nav_observer.Wait();
1128 EXPECT_FALSE(IsDisplayingText(browser(), l10n_util::GetStringUTF8(
1129 IDS_ERRORPAGES_SUGGESTION_CHECK_CONNECTION_HEADER)));
1130 }
1131
1132 // Make sure that a same page navigation does not cause issues with the
1133 // auto-reload timer. Note that this test was added due to this case causing
1134 // a crash. On regression, this test may hang due to a crashed renderer.
1135 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, IgnoresSamePageNavigation) {
1136 GURL test_url("http://error.page.auto.reload");
1137 InstallInterceptor(test_url, 2);
1138
1139 // Wait for the error page and first autoreload, which happens immediately.
1140 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1141 browser(), test_url, 2);
1142
1143 EXPECT_EQ(2, interceptor()->failures());
1144 EXPECT_EQ(2, interceptor()->requests());
1145
1146 content::WebContents* web_contents =
1147 browser()->tab_strip_model()->GetActiveWebContents();
1148 content::TestNavigationObserver observer(web_contents, 1);
1149 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
1150 base::ASCIIToUTF16("document.location='#';"));
1151 // The same page navigation counts as a navigation as far as the
1152 // TestNavigationObserver is concerned.
1153 observer.Wait();
1154
1155 // No new requests should have been issued.
1156 EXPECT_EQ(2, interceptor()->failures());
1157 EXPECT_EQ(2, interceptor()->requests());
1158
1159 // Wait for the second auto reload, which succeeds.
1160 content::TestNavigationObserver observer2(web_contents, 1);
1161 observer2.Wait();
1162
1163 EXPECT_EQ(2, interceptor()->failures());
1164 EXPECT_EQ(3, interceptor()->requests());
1165 }
1166
1167 // Interceptor that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
1168 class AddressUnreachableInterceptor : public net::URLRequestInterceptor {
1169 public:
1170 AddressUnreachableInterceptor() {}
1171 ~AddressUnreachableInterceptor() override {}
1172
1173 // net::URLRequestInterceptor:
1174 net::URLRequestJob* MaybeInterceptRequest(
1175 net::URLRequest* request,
1176 net::NetworkDelegate* network_delegate) const override {
1177 return new URLRequestFailedJob(request,
1178 network_delegate,
1179 net::ERR_ADDRESS_UNREACHABLE);
1180 }
1181
1182 private:
1183 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableInterceptor);
1184 };
1185
1186 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
1187 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
1188 // a different error for the correction service and the original page to
1189 // validate the right page is being displayed.
1190 class ErrorPageNavigationCorrectionsFailTest : public ErrorPageTest {
1191 public:
1192 // InProcessBrowserTest:
1193 void SetUpOnMainThread() override {
1194 BrowserThread::PostTask(
1195 BrowserThread::IO, FROM_HERE,
1196 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters));
1197 }
1198
1199 void TearDownOnMainThread() override {
1200 BrowserThread::PostTask(
1201 BrowserThread::IO, FROM_HERE,
1202 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters));
1203 }
1204
1205 private:
1206 // Adds a filter that causes all correction service requests to fail with
1207 // ERR_ADDRESS_UNREACHABLE.
1208 //
1209 // Also adds the net::URLRequestFailedJob filter.
1210 static void AddFilters() {
1211 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1212 URLRequestFailedJob::AddUrlHandler();
1213
1214 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
1215 google_util::LinkDoctorBaseURL(),
1216 std::unique_ptr<net::URLRequestInterceptor>(
1217 new AddressUnreachableInterceptor()));
1218 }
1219
1220 static void RemoveFilters() {
1221 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1222 net::URLRequestFilter::GetInstance()->ClearHandlers();
1223 }
1224 };
1225
1226 // Make sure that when corrections fail to load, the network error page is
1227 // successfully loaded.
1228 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1229 FetchCorrectionsFails) {
1230 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1231 browser(),
1232 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
1233 2);
1234
1235 // Verify that the expected error page is being displayed.
1236 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED);
1237
1238 // Diagnostics button should be displayed, if available on this platform.
1239 EXPECT_EQ(PlatformSupportsDiagnosticsTool(),
1240 IsDisplayingDiagnosticsLink(browser()));
1241 }
1242
1243 // Checks that when an error occurs and a corrections fail to load, the stale
1244 // cache status of the page is correctly transferred, and we can load the
1245 // stale copy from the javascript. Most logic copied from StaleCacheStatus
1246 // above.
1247 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
1248 StaleCacheStatusFailedCorrections) {
1249 ASSERT_TRUE(embedded_test_server()->Start());
1250 // Load cache with entry with "nocache" set, to create stale
1251 // cache.
1252 GURL test_url(embedded_test_server()->GetURL("/nocache.html"));
1253 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
1254
1255 // Reload same URL after forcing an error from the the network layer;
1256 // confirm that the error page is told the cached copy exists.
1257 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1258 browser()->profile()->GetRequestContext();
1259 BrowserThread::PostTask(
1260 BrowserThread::IO, FROM_HERE,
1261 base::Bind(&InterceptNetworkTransactions,
1262 base::RetainedRef(url_request_context_getter),
1263 net::ERR_CONNECTION_FAILED));
1264
1265 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1266 browser(), test_url, 2);
1267 EXPECT_TRUE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1268 EXPECT_TRUE(ProbeStaleCopyValue(true));
1269
1270 // Confirm that loading the stale copy from the cache works.
1271 content::TestNavigationObserver same_tab_observer(
1272 browser()->tab_strip_model()->GetActiveWebContents(), 1);
1273 ASSERT_TRUE(ReloadStaleCopyFromCache());
1274 same_tab_observer.Wait();
1275 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
1276 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
1277
1278 // Clear the cache and reload the same URL; confirm the error page is told
1279 // that there is no cached copy.
1280 BrowsingDataRemover* remover =
1281 BrowsingDataRemoverFactory::GetForBrowserContext(browser()->profile());
1282 remover->Remove(BrowsingDataRemover::Unbounded(),
1283 BrowsingDataRemover::REMOVE_CACHE,
1284 BrowsingDataHelper::UNPROTECTED_WEB);
1285 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1286 browser(), test_url, 2);
1287 EXPECT_TRUE(ProbeStaleCopyValue(false));
1288 EXPECT_FALSE(IsDisplayingText(browser(), GetShowSavedButtonLabel()));
1289 }
1290
1291 class ErrorPageOfflineTest : public ErrorPageTest {
1292 protected:
1293
1294 void SetUpInProcessBrowserTestFixture() override {
1295 #if defined(OS_CHROMEOS)
1296 if (enroll_) {
1297 // Set up fake install attributes.
1298 std::unique_ptr<policy::StubEnterpriseInstallAttributes> attributes(
1299 new policy::StubEnterpriseInstallAttributes());
1300 attributes->SetDomain("example.com");
1301 attributes->SetRegistrationUser("user@example.com");
1302 policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
1303 attributes.release());
1304 }
1305 #endif
1306
1307 // Sets up a mock policy provider for user and device policies.
1308 EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
1309 .WillRepeatedly(testing::Return(true));
1310
1311 policy::PolicyMap policy_map;
1312 #if defined(OS_CHROMEOS)
1313 if (enroll_)
1314 SetEnterpriseUsersDefaults(&policy_map);
1315 #endif
1316 if (set_allow_dinosaur_easter_egg_) {
1317 policy_map.Set(
1318 policy::key::kAllowDinosaurEasterEgg, policy::POLICY_LEVEL_MANDATORY,
1319 policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
1320 base::WrapUnique(
1321 new base::FundamentalValue(value_of_allow_dinosaur_easter_egg_)),
1322 nullptr);
1323 }
1324 policy_provider_.UpdateChromePolicy(policy_map);
1325
1326 #if defined(OS_CHROMEOS)
1327 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
1328 &policy_provider_);
1329 #else
1330 policy::ProfilePolicyConnectorFactory::GetInstance()
1331 ->PushProviderForTesting(&policy_provider_);
1332 #endif
1333
1334 ErrorPageTest::SetUpInProcessBrowserTestFixture();
1335 }
1336
1337 std::string NavigateToPageAndReadText() {
1338 #if defined(OS_CHROMEOS)
1339 // Check enterprise enrollment
1340 policy::BrowserPolicyConnectorChromeOS* connector =
1341 g_browser_process->platform_part()
1342 ->browser_policy_connector_chromeos();
1343 EXPECT_EQ(enroll_, connector->IsEnterpriseManaged());
1344 #endif
1345
1346 ui_test_utils::NavigateToURL(
1347 browser(),
1348 URLRequestFailedJob::GetMockHttpUrl(net::ERR_INTERNET_DISCONNECTED));
1349
1350 content::WebContents* web_contents =
1351 browser()->tab_strip_model()->GetActiveWebContents();
1352
1353 std::string command = base::StringPrintf(
1354 "var hasText = document.querySelector('.snackbar');"
1355 "domAutomationController.send(hasText ? hasText.innerText : '');");
1356
1357 std::string result;
1358 EXPECT_TRUE(
1359 content::ExecuteScriptAndExtractString(web_contents, command, &result));
1360
1361 return result;
1362 }
1363
1364 // Whether to set AllowDinosaurEasterEgg policy
1365 bool set_allow_dinosaur_easter_egg_ = false;
1366
1367 // The value of AllowDinosaurEasterEgg policy we want to set
1368 bool value_of_allow_dinosaur_easter_egg_;
1369
1370 #if defined(OS_CHROMEOS)
1371 // Whether to enroll this CrOS device
1372 bool enroll_ = true;
1373 #endif
1374
1375 // Mock policy provider for both user and device policies.
1376 policy::MockConfigurationPolicyProvider policy_provider_;
1377 };
1378
1379 class ErrorPageOfflineTestWithAllowDinosaurTrue : public ErrorPageOfflineTest {
1380 protected:
1381 void SetUpInProcessBrowserTestFixture() override {
1382 set_allow_dinosaur_easter_egg_ = true;
1383 value_of_allow_dinosaur_easter_egg_ = true;
1384 ErrorPageOfflineTest::SetUpInProcessBrowserTestFixture();
1385 }
1386 };
1387
1388 class ErrorPageOfflineTestWithAllowDinosaurFalse : public ErrorPageOfflineTest {
1389 protected:
1390 void SetUpInProcessBrowserTestFixture() override {
1391 set_allow_dinosaur_easter_egg_ = true;
1392 value_of_allow_dinosaur_easter_egg_ = false;
1393 ErrorPageOfflineTest::SetUpInProcessBrowserTestFixture();
1394 }
1395 };
1396
1397 #if defined(OS_CHROMEOS)
1398 class ErrorPageOfflineTestUnEnrolledChromeOS : public ErrorPageOfflineTest {
1399 protected:
1400 void SetUpInProcessBrowserTestFixture() override {
1401 set_allow_dinosaur_easter_egg_ = false;
1402 enroll_ = false;
1403 ErrorPageOfflineTest::SetUpInProcessBrowserTestFixture();
1404 }
1405 };
1406 #endif
1407
1408 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTestWithAllowDinosaurTrue,
1409 CheckEasterEggIsAllowed) {
1410 std::string result = NavigateToPageAndReadText();
1411 EXPECT_EQ("", result);
1412 }
1413
1414 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTestWithAllowDinosaurFalse,
1415 CheckEasterEggIsDisabled) {
1416 std::string result = NavigateToPageAndReadText();
1417 std::string disabled_text =
1418 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED);
1419 EXPECT_EQ(disabled_text, result);
1420 }
1421
1422 #if defined(OS_CHROMEOS)
1423 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest, CheckEasterEggIsDisabled) {
1424 std::string result = NavigateToPageAndReadText();
1425 std::string disabled_text =
1426 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED);
1427 EXPECT_EQ(disabled_text, result);
1428 }
1429 #else
1430 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest, CheckEasterEggIsAllowed) {
1431 std::string result = NavigateToPageAndReadText();
1432 EXPECT_EQ("", result);
1433 }
1434 #endif
1435
1436 #if defined(OS_CHROMEOS)
1437 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTestUnEnrolledChromeOS,
1438 CheckEasterEggIsAllowed) {
1439 std::string result = NavigateToPageAndReadText();
1440 std::string disabled_text =
1441 l10n_util::GetStringUTF8(IDS_ERRORPAGE_FUN_DISABLED);
1442 EXPECT_EQ("", result);
1443 }
1444 #endif
1445
1446 // A test fixture that simulates failing requests for an IDN domain name.
1447 class ErrorPageForIDNTest : public InProcessBrowserTest {
1448 public:
1449 // Target hostname in different forms.
1450 static const char kHostname[];
1451 static const char kHostnameJSUnicode[];
1452
1453 // InProcessBrowserTest:
1454 void SetUpOnMainThread() override {
1455 // Clear AcceptLanguages to force punycode decoding.
1456 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
1457 std::string());
1458 BrowserThread::PostTask(
1459 BrowserThread::IO, FROM_HERE,
1460 base::Bind(&ErrorPageForIDNTest::AddFilters));
1461 }
1462
1463 void TearDownOnMainThread() override {
1464 BrowserThread::PostTask(
1465 BrowserThread::IO, FROM_HERE,
1466 base::Bind(&ErrorPageForIDNTest::RemoveFilters));
1467 }
1468
1469 private:
1470 static void AddFilters() {
1471 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1472 URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
1473 }
1474
1475 static void RemoveFilters() {
1476 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1477 net::URLRequestFilter::GetInstance()->ClearHandlers();
1478 }
1479 };
1480
1481 const char ErrorPageForIDNTest::kHostname[] =
1482 "xn--d1abbgf6aiiy.xn--p1ai";
1483 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
1484 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
1485 "\\u0440\\u0444";
1486
1487 // Make sure error page shows correct unicode for IDN.
1488 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
1489 // ERR_UNSAFE_PORT will not trigger navigation corrections.
1490 ui_test_utils::NavigateToURL(
1491 browser(),
1492 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
1493 kHostname));
1494 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode));
1495 }
1496
1497 } // namespace
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/net/errorpage_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698