Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / errorpage_browsertest.cc
blobc20a756006576db4fa2c704d25932e7aa8371537
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/browsing_data/browsing_data_helper.h"
15 #include "chrome/browser/browsing_data/browsing_data_remover.h"
16 #include "chrome/browser/google/google_util.h"
17 #include "chrome/browser/net/url_request_mock_util.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_commands.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/render_frame_host.h"
30 #include "content/public/browser/render_view_host.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/browser/web_contents_observer.h"
33 #include "content/public/test/browser_test_utils.h"
34 #include "content/public/test/test_navigation_observer.h"
35 #include "content/test/net/url_request_failed_job.h"
36 #include "content/test/net/url_request_mock_http_job.h"
37 #include "grit/generated_resources.h"
38 #include "net/base/net_errors.h"
39 #include "net/base/net_util.h"
40 #include "net/http/failing_http_transaction_factory.h"
41 #include "net/http/http_cache.h"
42 #include "net/test/spawned_test_server/spawned_test_server.h"
43 #include "net/url_request/url_request_context.h"
44 #include "net/url_request/url_request_context_getter.h"
45 #include "net/url_request/url_request_filter.h"
46 #include "net/url_request/url_request_job.h"
47 #include "net/url_request/url_request_job_factory.h"
48 #include "net/url_request/url_request_test_job.h"
49 #include "net/url_request/url_request_test_util.h"
50 #include "ui/base/l10n/l10n_util.h"
52 using content::BrowserThread;
53 using content::NavigationController;
54 using content::URLRequestFailedJob;
55 using net::URLRequestJobFactory;
56 using net::URLRequestTestJob;
58 namespace {
60 // Returns true if |text| is displayed on the page |browser| is currently
61 // displaying. Uses "innerText", so will miss hidden text, and whitespace
62 // space handling may be weird.
63 bool WARN_UNUSED_RESULT IsDisplayingText(Browser* browser,
64 const std::string& text) {
65 std::string command = base::StringPrintf(
66 "var textContent = document.body.innerText;"
67 "var hasText = textContent.indexOf('%s') >= 0;"
68 "domAutomationController.send(hasText);",
69 text.c_str());
70 bool result = false;
71 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
72 browser->tab_strip_model()->GetActiveWebContents(), command, &result));
73 return result;
76 // Expands the more box on the currently displayed error page.
77 void ToggleHelpBox(Browser* browser) {
78 EXPECT_TRUE(content::ExecuteScript(
79 browser->tab_strip_model()->GetActiveWebContents(),
80 "document.getElementById('more-less-button').click();"));
83 // Returns true if |browser| is displaying the text representation of
84 // |error_code| on the current page.
85 bool WARN_UNUSED_RESULT IsDisplayingNetError(Browser* browser,
86 net::Error error_code) {
87 // Get the error as a string, and remove the leading "net::", which is not
88 // included on error pages.
89 std::string error_string = net::ErrorToString(error_code);
90 base::RemoveChars(error_string, "net:", &error_string);
92 return IsDisplayingText(browser, error_string);
95 // Checks that the local error page is being displayed, without remotely
96 // retrieved navigation corrections, and with the specified error code.
97 void ExpectDisplayingLocalErrorPage(Browser* browser, net::Error error_code) {
98 // Expand the help box so innerText will include text below the fold.
99 ToggleHelpBox(browser);
101 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
103 // Locally generated error pages should not have navigation corrections.
104 EXPECT_FALSE(IsDisplayingText(browser, "http://correction1/"));
105 EXPECT_FALSE(IsDisplayingText(browser, "http://correction2/"));
107 // Locally generated error pages should not have a populated search box.
108 bool search_box_populated = false;
109 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
110 browser->tab_strip_model()->GetActiveWebContents(),
111 "var searchText = document.getElementById('search-box').value;"
112 "domAutomationController.send(searchText == 'search query');",
113 &search_box_populated));
114 EXPECT_FALSE(search_box_populated);
117 // Checks that an error page with information retrieved from the navigation
118 // correction service is being displayed, with the specified specified error
119 // code.
120 void ExpectDisplayingNavigationCorrections(Browser* browser,
121 net::Error error_code) {
122 // Expand the help box so innerText will include text below the fold.
123 ToggleHelpBox(browser);
125 EXPECT_TRUE(IsDisplayingNetError(browser, error_code));
127 // Check that the mock navigation corrections are displayed.
128 EXPECT_TRUE(IsDisplayingText(browser, "http://correction1/"));
129 EXPECT_TRUE(IsDisplayingText(browser, "http://correction2/"));
131 // Check that the search box is populated correctly.
132 bool search_box_populated = false;
133 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
134 browser->tab_strip_model()->GetActiveWebContents(),
135 "var searchText = document.getElementById('search-box').value;"
136 "domAutomationController.send(searchText == 'search query');",
137 &search_box_populated));
138 EXPECT_TRUE(search_box_populated);
141 std::string GetLoadStaleButtonLabel() {
142 return l10n_util::GetStringUTF8(IDS_ERRORPAGES_BUTTON_LOAD_STALE);
145 // A protocol handler that fails a configurable number of requests, then
146 // succeeds all requests after that, keeping count of failures and successes.
147 class FailFirstNRequestsProtocolHandler
148 : public URLRequestJobFactory::ProtocolHandler {
149 public:
150 FailFirstNRequestsProtocolHandler(const GURL& url, int requests_to_fail)
151 : url_(url), requests_(0), failures_(0),
152 requests_to_fail_(requests_to_fail) {}
153 virtual ~FailFirstNRequestsProtocolHandler() {}
155 // This method deliberately violates pointer ownership rules:
156 // AddUrlProtocolHandler() takes a scoped_ptr, taking ownership of the
157 // supplied ProtocolHandler (i.e., |this|), but also having the caller retain
158 // a pointer to |this| so the caller can use the requests() and failures()
159 // accessors.
160 void AddUrlHandler() {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
162 scoped_ptr<URLRequestJobFactory::ProtocolHandler> scoped_handler(this);
163 net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
164 url_,
165 scoped_handler.Pass());
168 // net::URLRequestJobFactory::ProtocolHandler implementation
169 virtual net::URLRequestJob* MaybeCreateJob(
170 net::URLRequest* request,
171 net::NetworkDelegate* network_delegate) const OVERRIDE {
172 DCHECK_EQ(url_, request->url());
173 requests_++;
174 if (failures_ < requests_to_fail_) {
175 failures_++;
176 // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
177 // NetErrorHelperCore::GetErrorPageURL.
178 return new URLRequestFailedJob(request,
179 network_delegate,
180 net::ERR_CONNECTION_RESET);
181 } else {
182 return new URLRequestTestJob(request, network_delegate,
183 URLRequestTestJob::test_headers(),
184 URLRequestTestJob::test_data_1(),
185 true);
189 int requests() const { return requests_; }
190 int failures() const { return failures_; }
192 private:
193 const GURL url_;
194 // These are mutable because MaybeCreateJob is const but we want this state
195 // for testing.
196 mutable int requests_;
197 mutable int failures_;
198 int requests_to_fail_;
201 class ErrorPageTest : public InProcessBrowserTest {
202 public:
203 enum HistoryNavigationDirection {
204 HISTORY_NAVIGATE_BACK,
205 HISTORY_NAVIGATE_FORWARD,
208 // Needed for StaleCacheStatus and StaleCacheStatusFailedCorrections tests.
209 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
210 command_line->AppendSwitch(switches::kEnableOfflineLoadStaleCache);
213 // Navigates the active tab to a mock url created for the file at |file_path|.
214 void NavigateToFileURL(const base::FilePath::StringType& file_path) {
215 ui_test_utils::NavigateToURL(
216 browser(),
217 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path)));
220 // Navigates to the given URL and waits for |num_navigations| to occur, and
221 // the title to change to |expected_title|.
222 void NavigateToURLAndWaitForTitle(const GURL& url,
223 const std::string& expected_title,
224 int num_navigations) {
225 content::TitleWatcher title_watcher(
226 browser()->tab_strip_model()->GetActiveWebContents(),
227 base::ASCIIToUTF16(expected_title));
229 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
230 browser(), url, num_navigations);
232 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
233 title_watcher.WaitAndGetTitle());
236 // Navigates back in the history and waits for |num_navigations| to occur, and
237 // the title to change to |expected_title|.
238 void GoBackAndWaitForTitle(const std::string& expected_title,
239 int num_navigations) {
240 NavigateHistoryAndWaitForTitle(expected_title,
241 num_navigations,
242 HISTORY_NAVIGATE_BACK);
245 // Navigates forward in the history and waits for |num_navigations| to occur,
246 // and the title to change to |expected_title|.
247 void GoForwardAndWaitForTitle(const std::string& expected_title,
248 int num_navigations) {
249 NavigateHistoryAndWaitForTitle(expected_title,
250 num_navigations,
251 HISTORY_NAVIGATE_FORWARD);
254 void GoBackAndWaitForNavigations(int num_navigations) {
255 NavigateHistory(num_navigations, HISTORY_NAVIGATE_BACK);
258 void GoForwardAndWaitForNavigations(int num_navigations) {
259 NavigateHistory(num_navigations, HISTORY_NAVIGATE_FORWARD);
262 // Confirms that the javascript variable indicating whether or not we have
263 // a stale copy in the cache has been set to |expected|, and that the
264 // stale load button is or isn't there based on the same expectation.
265 testing::AssertionResult ProbeStaleCopyValue(bool expected) {
266 const char* js_cache_probe =
267 "try {\n"
268 " domAutomationController.send(\n"
269 " 'staleLoadButton' in templateData ? 'yes' : 'no');\n"
270 "} catch (e) {\n"
271 " domAutomationController.send(e.message);\n"
272 "}\n";
274 std::string result;
275 bool ret =
276 content::ExecuteScriptAndExtractString(
277 browser()->tab_strip_model()->GetActiveWebContents(),
278 js_cache_probe,
279 &result);
280 if (!ret) {
281 return testing::AssertionFailure()
282 << "Failing return from ExecuteScriptAndExtractString.";
285 if ((expected && "yes" == result) || (!expected && "no" == result))
286 return testing::AssertionSuccess();
288 return testing::AssertionFailure() << "Cache probe result is " << result;
291 testing::AssertionResult ReloadStaleCopyFromCache() {
292 const char* js_reload_script =
293 "try {\n"
294 " document.getElementById('stale-load-button').click();\n"
295 " domAutomationController.send('success');\n"
296 "} catch (e) {\n"
297 " domAutomationController.send(e.message);\n"
298 "}\n";
300 std::string result;
301 bool ret = content::ExecuteScriptAndExtractString(
302 browser()->tab_strip_model()->GetActiveWebContents(),
303 js_reload_script,
304 &result);
305 EXPECT_TRUE(ret);
306 if (!ret)
307 return testing::AssertionFailure();
308 return ("success" == result ? testing::AssertionSuccess() :
309 (testing::AssertionFailure() << "Exception message is " << result));
312 protected:
313 static void EnableMocks(const GURL& search_url) {
314 chrome_browser_net::SetUrlRequestMocksEnabled(true);
316 // Add a mock for the search engine the error page will use.
317 base::FilePath root_http;
318 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
319 content::URLRequestMockHTTPJob::AddHostnameToFileHandler(
320 search_url.host(), root_http.AppendASCII("title3.html"));
323 virtual void SetUpOnMainThread() OVERRIDE {
324 BrowserThread::PostTask(
325 BrowserThread::IO, FROM_HERE,
326 base::Bind(&ErrorPageTest::EnableMocks,
327 google_util::GetGoogleSearchURL(browser()->profile())));
330 // Returns a GURL that results in a DNS error.
331 GURL GetDnsErrorURL() const {
332 return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
335 private:
336 // Navigates the browser the indicated direction in the history and waits for
337 // |num_navigations| to occur and the title to change to |expected_title|.
338 void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
339 int num_navigations,
340 HistoryNavigationDirection direction) {
341 content::TitleWatcher title_watcher(
342 browser()->tab_strip_model()->GetActiveWebContents(),
343 base::ASCIIToUTF16(expected_title));
345 NavigateHistory(num_navigations, direction);
347 EXPECT_EQ(title_watcher.WaitAndGetTitle(),
348 base::ASCIIToUTF16(expected_title));
351 void NavigateHistory(int num_navigations,
352 HistoryNavigationDirection direction) {
353 content::TestNavigationObserver test_navigation_observer(
354 browser()->tab_strip_model()->GetActiveWebContents(),
355 num_navigations);
356 if (direction == HISTORY_NAVIGATE_BACK) {
357 chrome::GoBack(browser(), CURRENT_TAB);
358 } else if (direction == HISTORY_NAVIGATE_FORWARD) {
359 chrome::GoForward(browser(), CURRENT_TAB);
360 } else {
361 FAIL();
363 test_navigation_observer.Wait();
367 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
368 public:
369 explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
370 : content::WebContentsObserver(contents) {}
371 virtual ~TestFailProvisionalLoadObserver() {}
373 // This method is invoked when the provisional load failed.
374 virtual void DidFailProvisionalLoad(
375 int64 frame_id,
376 const base::string16& frame_unique_name,
377 bool is_main_frame,
378 const GURL& validated_url,
379 int error_code,
380 const base::string16& error_description,
381 content::RenderViewHost* render_view_host) OVERRIDE {
382 fail_url_ = validated_url;
385 const GURL& fail_url() const { return fail_url_; }
387 private:
388 GURL fail_url_;
390 DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
393 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
394 net::Error error) {
395 DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
396 net::HttpCache* cache(
397 getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
398 DCHECK(cache);
399 scoped_ptr<net::HttpTransactionFactory> factory(
400 new net::FailingHttpTransactionFactory(cache->GetSession(), error));
401 // Throw away old version; since this is a a browser test, we don't
402 // need to restore the old state.
403 cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
406 // See crbug.com/109669
407 #if defined(USE_AURA)
408 #define MAYBE_DNSError_Basic DISABLED_DNSError_Basic
409 #else
410 #define MAYBE_DNSError_Basic DNSError_Basic
411 #endif
412 // Test that a DNS error occuring in the main frame redirects to an error page.
413 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_DNSError_Basic) {
414 // The first navigation should fail, and the second one should be the error
415 // page.
416 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
417 browser(), GetDnsErrorURL(), 2);
418 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
421 // See crbug.com/109669
422 #if defined(USE_AURA)
423 #define MAYBE_DNSError_GoBack1 DISABLED_DNSError_GoBack1
424 #else
425 #define MAYBE_DNSError_GoBack1 DNSError_GoBack1
426 #endif
428 // Test that a DNS error occuring in the main frame does not result in an
429 // additional session history entry.
430 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_DNSError_GoBack1) {
431 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
432 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
433 browser(), GetDnsErrorURL(), 2);
434 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
435 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
438 // See crbug.com/109669
439 #if defined(USE_AURA)
440 #define MAYBE_DNSError_GoBack2 DISABLED_DNSError_GoBack2
441 #else
442 #define MAYBE_DNSError_GoBack2 DNSError_GoBack2
443 #endif
444 // Test that a DNS error occuring in the main frame does not result in an
445 // additional session history entry.
446 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
447 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
449 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
450 browser(), GetDnsErrorURL(), 2);
451 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
453 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
455 GoBackAndWaitForNavigations(2);
456 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
458 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
461 // See crbug.com/109669
462 #if defined(USE_AURA)
463 #define MAYBE_DNSError_GoBack2AndForward DISABLED_DNSError_GoBack2AndForward
464 #else
465 #define MAYBE_DNSError_GoBack2AndForward DNSError_GoBack2AndForward
466 #endif
467 // Test that a DNS error occuring in the main frame does not result in an
468 // additional session history entry.
469 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
470 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
472 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
473 browser(), GetDnsErrorURL(), 2);
474 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
476 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
478 GoBackAndWaitForNavigations(2);
479 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
481 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
483 GoForwardAndWaitForNavigations(2);
484 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
487 // See crbug.com/109669
488 #if defined(USE_AURA)
489 #define MAYBE_DNSError_GoBack2Forward2 DISABLED_DNSError_GoBack2Forward2
490 #else
491 #define MAYBE_DNSError_GoBack2Forward2 DNSError_GoBack2Forward2
492 #endif
493 // Test that a DNS error occuring in the main frame does not result in an
494 // additional session history entry.
495 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
496 NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
498 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
499 browser(), GetDnsErrorURL(), 2);
500 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
502 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
504 GoBackAndWaitForNavigations(2);
505 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
507 GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
509 GoForwardAndWaitForNavigations(2);
510 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
512 GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
515 // See crbug.com/109669
516 #if defined(USE_AURA)
517 #define MAYBE_DNSError_DoSearch DNSError_DoSearch
518 #else
519 #define MAYBE_DNSError_DoSearch DNSError_DoSearch
520 #endif
521 // Test that the search button on a DNS error page works.
522 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_DNSError_DoSearch) {
523 // The first navigation should fail, and the second one should be the error
524 // page.
525 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
526 browser(), GetDnsErrorURL(), 2);
527 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
529 // Do a search and make sure the browser ends up at the right page.
530 content::TestNavigationObserver nav_observer(
531 browser()->tab_strip_model()->GetActiveWebContents(),
533 content::TitleWatcher title_watcher(
534 browser()->tab_strip_model()->GetActiveWebContents(),
535 base::ASCIIToUTF16("Title Of More Awesomeness"));
536 ASSERT_TRUE(content::ExecuteScript(
537 browser()->tab_strip_model()->GetActiveWebContents(),
538 "document.getElementById('search-button').click();"));
539 nav_observer.Wait();
540 EXPECT_EQ(base::ASCIIToUTF16("Title Of More Awesomeness"),
541 title_watcher.WaitAndGetTitle());
543 // Check the path and query string.
544 std::string url;
545 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
546 browser()->tab_strip_model()->GetActiveWebContents(),
547 "domAutomationController.send(window.location.href);",
548 &url));
549 EXPECT_EQ("/search", GURL(url).path());
550 EXPECT_EQ("q=search%20query", GURL(url).query());
552 // Go back to the error page, to make sure the history is correct.
553 GoBackAndWaitForNavigations(2);
554 ExpectDisplayingNavigationCorrections(browser(), net::ERR_NAME_NOT_RESOLVED);
557 // Test that a DNS error occuring in an iframe does not result in showing
558 // navigation corrections.
559 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
560 NavigateToURLAndWaitForTitle(
561 content::URLRequestMockHTTPJob::GetMockUrl(
562 base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
563 "Blah",
565 // We expect to have two history entries, since we started off with navigation
566 // to "about:blank" and then navigated to "iframe_dns_error.html".
567 EXPECT_EQ(2,
568 browser()->tab_strip_model()->GetActiveWebContents()->
569 GetController().GetEntryCount());
572 // This test fails regularly on win_rel trybots. See crbug.com/121540
573 #if defined(OS_WIN)
574 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
575 #else
576 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
577 #endif
578 // Test that a DNS error occuring in an iframe does not result in an
579 // additional session history entry.
580 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
581 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
582 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
583 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
586 // This test fails regularly on win_rel trybots. See crbug.com/121540
588 // This fails on linux_aura bringup: http://crbug.com/163931
589 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
590 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
591 #else
592 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
593 #endif
594 // Test that a DNS error occuring in an iframe does not result in an
595 // additional session history entry.
596 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
597 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
598 NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
599 GoBackAndWaitForTitle("Title Of Awesomeness", 1);
600 GoForwardAndWaitForTitle("Blah", 1);
603 // Test that a DNS error occuring in an iframe, once the main document is
604 // completed loading, does not result in an additional session history entry.
605 // To ensure that the main document has completed loading, JavaScript is used to
606 // inject an iframe after loading is done.
607 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
608 content::WebContents* wc =
609 browser()->tab_strip_model()->GetActiveWebContents();
610 GURL fail_url =
611 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
613 // Load a regular web page, in which we will inject an iframe.
614 NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
616 // We expect to have two history entries, since we started off with navigation
617 // to "about:blank" and then navigated to "title2.html".
618 EXPECT_EQ(2, wc->GetController().GetEntryCount());
620 std::string script = "var frame = document.createElement('iframe');"
621 "frame.src = '" + fail_url.spec() + "';"
622 "document.body.appendChild(frame);";
624 TestFailProvisionalLoadObserver fail_observer(wc);
625 content::WindowedNotificationObserver load_observer(
626 content::NOTIFICATION_LOAD_STOP,
627 content::Source<NavigationController>(&wc->GetController()));
628 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
629 load_observer.Wait();
631 // Ensure we saw the expected failure.
632 EXPECT_EQ(fail_url, fail_observer.fail_url());
634 // Failed initial navigation of an iframe shouldn't be adding any history
635 // entries.
636 EXPECT_EQ(2, wc->GetController().GetEntryCount());
639 // Do the same test, but with an iframe that doesn't have initial URL
640 // assigned.
641 script = "var frame = document.createElement('iframe');"
642 "frame.id = 'target_frame';"
643 "document.body.appendChild(frame);";
645 content::WindowedNotificationObserver load_observer(
646 content::NOTIFICATION_LOAD_STOP,
647 content::Source<NavigationController>(&wc->GetController()));
648 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
649 load_observer.Wait();
652 script = "var f = document.getElementById('target_frame');"
653 "f.src = '" + fail_url.spec() + "';";
655 TestFailProvisionalLoadObserver fail_observer(wc);
656 content::WindowedNotificationObserver load_observer(
657 content::NOTIFICATION_LOAD_STOP,
658 content::Source<NavigationController>(&wc->GetController()));
659 wc->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
660 load_observer.Wait();
662 EXPECT_EQ(fail_url, fail_observer.fail_url());
663 EXPECT_EQ(2, wc->GetController().GetEntryCount());
667 // Checks that navigation corrections are not loaded when we receive an actual
668 // 404 page.
669 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
670 NavigateToURLAndWaitForTitle(
671 content::URLRequestMockHTTPJob::GetMockUrl(
672 base::FilePath(FILE_PATH_LITERAL("page404.html"))),
673 "SUCCESS",
677 // Checks that when an error occurs, the stale cache status of the page
678 // is correctly transferred, and that stale cached copied can be loaded
679 // from the javascript.
680 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
681 ASSERT_TRUE(test_server()->Start());
682 // Load cache with entry with "nocache" set, to create stale
683 // cache.
684 GURL test_url(test_server()->GetURL("files/nocache.html"));
685 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
687 // Reload same URL after forcing an error from the the network layer;
688 // confirm that the error page is told the cached copy exists.
689 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
690 browser()->profile()->GetRequestContext();
691 BrowserThread::PostTask(
692 BrowserThread::IO, FROM_HERE,
693 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
694 net::ERR_FAILED));
696 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
697 // With no navigation corrections to load, there's only one navigation.
698 browser(), test_url, 1);
699 EXPECT_TRUE(ProbeStaleCopyValue(true));
700 EXPECT_TRUE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
701 EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
702 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
704 // Confirm that loading the stale copy from the cache works.
705 content::TestNavigationObserver same_tab_observer(
706 browser()->tab_strip_model()->GetActiveWebContents(), 1);
707 ASSERT_TRUE(ReloadStaleCopyFromCache());
708 same_tab_observer.Wait();
709 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
710 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
712 // Clear the cache and reload the same URL; confirm the error page is told
713 // that there is no cached copy.
714 BrowsingDataRemover* remover =
715 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
716 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
717 BrowsingDataHelper::UNPROTECTED_WEB);
718 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
719 browser(), test_url, 1);
720 EXPECT_TRUE(ProbeStaleCopyValue(false));
721 EXPECT_FALSE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
724 class ErrorPageAutoReloadTest : public InProcessBrowserTest {
725 public:
726 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
727 command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
730 void InstallProtocolHandler(const GURL& url, int requests_to_fail) {
731 protocol_handler_ = new FailFirstNRequestsProtocolHandler(
732 url,
733 requests_to_fail);
734 // Tests don't need to wait for this task to complete before using the
735 // filter; any requests that might be affected by it will end up in the IO
736 // thread's message loop after this posted task anyway.
737 BrowserThread::PostTask(
738 BrowserThread::IO, FROM_HERE,
739 base::Bind(&ErrorPageAutoReloadTest::AddFilters,
740 base::Unretained(this)));
743 void NavigateToURLAndWaitForTitle(const GURL& url,
744 const std::string& expected_title,
745 int num_navigations) {
746 content::TitleWatcher title_watcher(
747 browser()->tab_strip_model()->GetActiveWebContents(),
748 base::ASCIIToUTF16(expected_title));
750 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
751 browser(), url, num_navigations);
753 EXPECT_EQ(base::ASCIIToUTF16(expected_title),
754 title_watcher.WaitAndGetTitle());
757 FailFirstNRequestsProtocolHandler* protocol_handler() {
758 return protocol_handler_;
761 private:
762 void AddFilters() {
763 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
764 // Note: in theory, AddUrlHandler gives ownership of |protocol_handler_| to
765 // URLRequestFilter. As soon as anything calls
766 // URLRequestFilter::ClearHandlers(), |protocol_handler_| can become
767 // invalid.
768 protocol_handler_->AddUrlHandler();
771 FailFirstNRequestsProtocolHandler* protocol_handler_;
774 IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, AutoReload) {
775 GURL test_url("http://error.page.auto.reload");
776 const int kRequestsToFail = 2;
777 InstallProtocolHandler(test_url, kRequestsToFail);
778 NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
779 // Note that the protocol handler updates these variables on the IO thread,
780 // but this function reads them on the main thread. The requests have to be
781 // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
782 // this becomes racey.
783 EXPECT_EQ(kRequestsToFail, protocol_handler()->failures());
784 EXPECT_EQ(kRequestsToFail + 1, protocol_handler()->requests());
787 // Protocol handler that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
788 class AddressUnreachableProtocolHandler
789 : public net::URLRequestJobFactory::ProtocolHandler {
790 public:
791 AddressUnreachableProtocolHandler() {}
792 virtual ~AddressUnreachableProtocolHandler() {}
794 // net::URLRequestJobFactory::ProtocolHandler:
795 virtual net::URLRequestJob* MaybeCreateJob(
796 net::URLRequest* request,
797 net::NetworkDelegate* network_delegate) const OVERRIDE {
798 return new URLRequestFailedJob(request,
799 network_delegate,
800 net::ERR_ADDRESS_UNREACHABLE);
803 private:
804 DISALLOW_COPY_AND_ASSIGN(AddressUnreachableProtocolHandler);
807 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all navigation
808 // correction requests. ERR_NAME_NOT_RESOLVED is more typical, but need to use
809 // a different error for the correction service and the original page to
810 // validate the right page is being displayed.
811 class ErrorPageNavigationCorrectionsFailTest : public ErrorPageTest {
812 public:
813 // InProcessBrowserTest:
814 virtual void SetUpOnMainThread() OVERRIDE {
815 BrowserThread::PostTask(
816 BrowserThread::IO, FROM_HERE,
817 base::Bind(&ErrorPageNavigationCorrectionsFailTest::AddFilters));
820 virtual void CleanUpOnMainThread() OVERRIDE {
821 BrowserThread::PostTask(
822 BrowserThread::IO, FROM_HERE,
823 base::Bind(&ErrorPageNavigationCorrectionsFailTest::RemoveFilters));
826 private:
827 // Adds a filter that causes all correction service requests to fail with
828 // ERR_ADDRESS_UNREACHABLE.
830 // Also adds the content::URLRequestFailedJob filter.
831 static void AddFilters() {
832 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
833 content::URLRequestFailedJob::AddUrlHandler();
835 net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
836 google_util::LinkDoctorBaseURL(),
837 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
838 new AddressUnreachableProtocolHandler()));
841 static void RemoveFilters() {
842 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
843 net::URLRequestFilter::GetInstance()->ClearHandlers();
847 // Make sure that when corrections fail to load, the network error page is
848 // successfully loaded.
849 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
850 FetchCorrectionsFails) {
851 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
852 browser(),
853 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
856 // Verify that the expected error page is being displayed.
857 ExpectDisplayingLocalErrorPage(browser(), net::ERR_NAME_NOT_RESOLVED);
860 // Checks that when an error occurs and a corrections fail to load, the stale
861 // cache status of the page is correctly transferred, and we can load the
862 // stale copy from the javascript. Most logic copied from StaleCacheStatus
863 // above.
864 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
865 StaleCacheStatusFailedCorrections) {
866 ASSERT_TRUE(test_server()->Start());
867 // Load cache with entry with "nocache" set, to create stale
868 // cache.
869 GURL test_url(test_server()->GetURL("files/nocache.html"));
870 NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
872 // Reload same URL after forcing an error from the the network layer;
873 // confirm that the error page is told the cached copy exists.
874 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
875 browser()->profile()->GetRequestContext();
876 BrowserThread::PostTask(
877 BrowserThread::IO, FROM_HERE,
878 base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
879 net::ERR_CONNECTION_FAILED));
881 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
882 browser(), test_url, 2);
883 EXPECT_TRUE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
884 EXPECT_TRUE(ProbeStaleCopyValue(true));
886 // Confirm that loading the stale copy from the cache works.
887 content::TestNavigationObserver same_tab_observer(
888 browser()->tab_strip_model()->GetActiveWebContents(), 1);
889 ASSERT_TRUE(ReloadStaleCopyFromCache());
890 same_tab_observer.Wait();
891 EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
892 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
894 // Clear the cache and reload the same URL; confirm the error page is told
895 // that there is no cached copy.
896 BrowsingDataRemover* remover =
897 BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
898 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
899 BrowsingDataHelper::UNPROTECTED_WEB);
900 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
901 browser(), test_url, 2);
902 EXPECT_TRUE(ProbeStaleCopyValue(false));
903 EXPECT_FALSE(IsDisplayingText(browser(), GetLoadStaleButtonLabel()));
906 // A test fixture that simulates failing requests for an IDN domain name.
907 class ErrorPageForIDNTest : public InProcessBrowserTest {
908 public:
909 // Target hostname in different forms.
910 static const char kHostname[];
911 static const char kHostnameJSUnicode[];
913 // InProcessBrowserTest:
914 virtual void SetUpOnMainThread() OVERRIDE {
915 // Clear AcceptLanguages to force punycode decoding.
916 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
917 std::string());
918 BrowserThread::PostTask(
919 BrowserThread::IO, FROM_HERE,
920 base::Bind(&ErrorPageForIDNTest::AddFilters));
923 virtual void CleanUpOnMainThread() OVERRIDE {
924 BrowserThread::PostTask(
925 BrowserThread::IO, FROM_HERE,
926 base::Bind(&ErrorPageForIDNTest::RemoveFilters));
929 private:
930 static void AddFilters() {
931 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
932 content::URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
935 static void RemoveFilters() {
936 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
937 net::URLRequestFilter::GetInstance()->ClearHandlers();
941 const char ErrorPageForIDNTest::kHostname[] =
942 "xn--d1abbgf6aiiy.xn--p1ai";
943 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
944 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
945 "\\u0440\\u0444";
947 // Make sure error page shows correct unicode for IDN.
948 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
949 // ERR_UNSAFE_PORT will not trigger navigation corrections.
950 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
951 browser(),
952 URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
953 kHostname),
956 ToggleHelpBox(browser());
957 EXPECT_TRUE(IsDisplayingText(browser(), kHostnameJSUnicode));
960 } // namespace