Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / errorpage_browsertest.cc
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 "base/bind.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/browsing_data/browsing_data_helper.h"
10 #include "chrome/browser/browsing_data/browsing_data_remover.h"
11 #include "chrome/browser/google/google_util.h"
12 #include "chrome/browser/net/url_request_mock_util.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_observer.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/public/test/test_navigation_observer.h"
26 #include "content/test/net/url_request_failed_job.h"
27 #include "content/test/net/url_request_mock_http_job.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/net_util.h"
30 #include "net/http/failing_http_transaction_factory.h"
31 #include "net/http/http_cache.h"
32 #include "net/test/spawned_test_server/spawned_test_server.h"
33 #include "net/url_request/url_request_context.h"
34 #include "net/url_request/url_request_context_getter.h"
35 #include "net/url_request/url_request_filter.h"
36 #include "net/url_request/url_request_job_factory.h"
37
38 using content::BrowserThread;
39 using content::NavigationController;
40 using content::URLRequestFailedJob;
41
42 namespace {
43
44 class ErrorPageTest : public InProcessBrowserTest {
45  public:
46   enum HistoryNavigationDirection {
47     HISTORY_NAVIGATE_BACK,
48     HISTORY_NAVIGATE_FORWARD,
49   };
50
51   // Navigates the active tab to a mock url created for the file at |file_path|.
52   void NavigateToFileURL(const base::FilePath::StringType& file_path) {
53     ui_test_utils::NavigateToURL(
54         browser(),
55         content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(file_path)));
56   }
57
58   // Navigates to the given URL and waits for |num_navigations| to occur, and
59   // the title to change to |expected_title|.
60   void NavigateToURLAndWaitForTitle(const GURL& url,
61                                     const std::string& expected_title,
62                                     int num_navigations) {
63     content::TitleWatcher title_watcher(
64         browser()->tab_strip_model()->GetActiveWebContents(),
65         base::ASCIIToUTF16(expected_title));
66
67     ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
68         browser(), url, num_navigations);
69
70     EXPECT_EQ(base::ASCIIToUTF16(expected_title),
71               title_watcher.WaitAndGetTitle());
72   }
73
74   // Navigates back in the history and waits for |num_navigations| to occur, and
75   // the title to change to |expected_title|.
76   void GoBackAndWaitForTitle(const std::string& expected_title,
77                              int num_navigations) {
78     NavigateHistoryAndWaitForTitle(expected_title,
79                                    num_navigations,
80                                    HISTORY_NAVIGATE_BACK);
81   }
82
83   // Navigates forward in the history and waits for |num_navigations| to occur,
84   // and the title to change to |expected_title|.
85   void GoForwardAndWaitForTitle(const std::string& expected_title,
86                                 int num_navigations) {
87     NavigateHistoryAndWaitForTitle(expected_title,
88                                    num_navigations,
89                                    HISTORY_NAVIGATE_FORWARD);
90   }
91
92   // Confirms that the javascript variable indicating whether or not we have
93   // a stale copy in the cache has been set to |expected|.
94   bool ProbeStaleCopyValue(bool expected) {
95     const char* js_cache_probe =
96         "(function () {\n"
97         "  if ('staleCopyInCache' in templateData) {\n"
98         "    domAutomationController.send(\n"
99         "      templateData.staleCopyInCache ? 'yes' : 'no');\n"
100         "  } else {\n"
101         "    domAutomationController.send('absent');\n"
102         "  }\n"
103         "})();";
104
105     std::string result;
106     bool ret =
107         content::ExecuteScriptAndExtractString(
108             browser()->tab_strip_model()->GetActiveWebContents(),
109             js_cache_probe,
110             &result);
111     EXPECT_TRUE(ret);
112     if (!ret)
113       return false;
114     EXPECT_EQ(expected ? "yes" : "no", result);
115     return ((expected ? "yes" : "no") == result);
116   }
117
118  protected:
119   virtual void SetUpOnMainThread() OVERRIDE {
120     BrowserThread::PostTask(
121         BrowserThread::IO, FROM_HERE,
122         base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
123   }
124
125   // Returns a GURL that results in a DNS error.
126   GURL GetDnsErrorURL() const {
127     return URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
128   }
129
130  private:
131   // Navigates the browser the indicated direction in the history and waits for
132   // |num_navigations| to occur and the title to change to |expected_title|.
133   void NavigateHistoryAndWaitForTitle(const std::string& expected_title,
134                                       int num_navigations,
135                                       HistoryNavigationDirection direction) {
136     content::TitleWatcher title_watcher(
137         browser()->tab_strip_model()->GetActiveWebContents(),
138         base::ASCIIToUTF16(expected_title));
139
140     content::TestNavigationObserver test_navigation_observer(
141         browser()->tab_strip_model()->GetActiveWebContents(),
142         num_navigations);
143     if (direction == HISTORY_NAVIGATE_BACK) {
144       chrome::GoBack(browser(), CURRENT_TAB);
145     } else if (direction == HISTORY_NAVIGATE_FORWARD) {
146       chrome::GoForward(browser(), CURRENT_TAB);
147     } else {
148       FAIL();
149     }
150     test_navigation_observer.Wait();
151
152     EXPECT_EQ(title_watcher.WaitAndGetTitle(),
153               base::ASCIIToUTF16(expected_title));
154   }
155 };
156
157 class TestFailProvisionalLoadObserver : public content::WebContentsObserver {
158  public:
159   explicit TestFailProvisionalLoadObserver(content::WebContents* contents)
160       : content::WebContentsObserver(contents) {}
161   virtual ~TestFailProvisionalLoadObserver() {}
162
163   // This method is invoked when the provisional load failed.
164   virtual void DidFailProvisionalLoad(
165       int64 frame_id,
166       const base::string16& frame_unique_name,
167       bool is_main_frame,
168       const GURL& validated_url,
169       int error_code,
170       const base::string16& error_description,
171       content::RenderViewHost* render_view_host) OVERRIDE {
172     fail_url_ = validated_url;
173   }
174
175   const GURL& fail_url() const { return fail_url_; }
176
177  private:
178   GURL fail_url_;
179
180   DISALLOW_COPY_AND_ASSIGN(TestFailProvisionalLoadObserver);
181 };
182
183 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
184                                   net::Error error) {
185   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
186   net::HttpCache* cache(
187       getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
188   DCHECK(cache);
189   scoped_ptr<net::HttpTransactionFactory> factory(
190       new net::FailingHttpTransactionFactory(cache->GetSession(), error));
191   // Throw away old version; since this is a a browser test, we don't
192   // need to restore the old state.
193   cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
194 }
195
196 // See crbug.com/109669
197 #if defined(USE_AURA) || defined(OS_WIN)
198 #define MAYBE_DNSError_Basic DISABLED_DNSError_Basic
199 #else
200 #define MAYBE_DNSError_Basic DNSError_Basic
201 #endif
202 // Test that a DNS error occuring in the main frame redirects to an error page.
203 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_DNSError_Basic) {
204   // The first navigation should fail, and the second one should be the error
205   // page.
206   NavigateToURLAndWaitForTitle(GetDnsErrorURL(), "Mock Link Doctor", 2);
207 }
208
209 // See crbug.com/109669
210 #if defined(USE_AURA)
211 #define MAYBE_DNSError_GoBack1 DISABLED_DNSError_GoBack1
212 #else
213 #define MAYBE_DNSError_GoBack1 DNSError_GoBack1
214 #endif
215
216 // Test that a DNS error occuring in the main frame does not result in an
217 // additional session history entry.
218 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_DNSError_GoBack1) {
219   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
220   NavigateToURLAndWaitForTitle(GetDnsErrorURL(), "Mock Link Doctor", 2);
221   GoBackAndWaitForTitle("Title Of Awesomeness", 1);
222 }
223
224 // See crbug.com/109669
225 #if defined(USE_AURA)
226 #define MAYBE_DNSError_GoBack2 DISABLED_DNSError_GoBack2
227 #else
228 #define MAYBE_DNSError_GoBack2 DNSError_GoBack2
229 #endif
230 // Test that a DNS error occuring in the main frame does not result in an
231 // additional session history entry.
232 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2) {
233   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
234
235   NavigateToURLAndWaitForTitle(GetDnsErrorURL(), "Mock Link Doctor", 2);
236   NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
237
238   GoBackAndWaitForTitle("Mock Link Doctor", 2);
239   GoBackAndWaitForTitle("Title Of Awesomeness", 1);
240 }
241
242 // See crbug.com/109669
243 #if defined(USE_AURA)
244 #define MAYBE_DNSError_GoBack2AndForward DISABLED_DNSError_GoBack2AndForward
245 #else
246 #define MAYBE_DNSError_GoBack2AndForward DNSError_GoBack2AndForward
247 #endif
248 // Test that a DNS error occuring in the main frame does not result in an
249 // additional session history entry.
250 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
251   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
252
253   NavigateToURLAndWaitForTitle(GetDnsErrorURL(), "Mock Link Doctor", 2);
254   NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
255
256   GoBackAndWaitForTitle("Mock Link Doctor", 2);
257   GoBackAndWaitForTitle("Title Of Awesomeness", 1);
258
259   GoForwardAndWaitForTitle("Mock Link Doctor", 2);
260 }
261
262 // See crbug.com/109669
263 #if defined(USE_AURA)
264 #define MAYBE_DNSError_GoBack2Forward2 DISABLED_DNSError_GoBack2Forward2
265 #else
266 #define MAYBE_DNSError_GoBack2Forward2 DNSError_GoBack2Forward2
267 #endif
268 // Test that a DNS error occuring in the main frame does not result in an
269 // additional session history entry.
270 IN_PROC_BROWSER_TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
271   NavigateToFileURL(FILE_PATH_LITERAL("title3.html"));
272
273   NavigateToURLAndWaitForTitle(GetDnsErrorURL(), "Mock Link Doctor", 2);
274   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
275
276   GoBackAndWaitForTitle("Mock Link Doctor", 2);
277   GoBackAndWaitForTitle("Title Of More Awesomeness", 1);
278
279   GoForwardAndWaitForTitle("Mock Link Doctor", 2);
280   GoForwardAndWaitForTitle("Title Of Awesomeness", 1);
281 }
282
283 // Test that a DNS error occuring in an iframe.
284 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
285   NavigateToURLAndWaitForTitle(
286       content::URLRequestMockHTTPJob::GetMockUrl(
287           base::FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))),
288       "Blah",
289       1);
290   // We expect to have two history entries, since we started off with navigation
291   // to "about:blank" and then navigated to "iframe_dns_error.html".
292   EXPECT_EQ(2,
293       browser()->tab_strip_model()->GetActiveWebContents()->
294           GetController().GetEntryCount());
295 }
296
297 // This test fails regularly on win_rel trybots. See crbug.com/121540
298 #if defined(OS_WIN)
299 #define MAYBE_IFrameDNSError_GoBack DISABLED_IFrameDNSError_GoBack
300 #else
301 #define MAYBE_IFrameDNSError_GoBack IFrameDNSError_GoBack
302 #endif
303 // Test that a DNS error occuring in an iframe does not result in an
304 // additional session history entry.
305 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBack) {
306   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
307   NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
308   GoBackAndWaitForTitle("Title Of Awesomeness", 1);
309 }
310
311 // This test fails regularly on win_rel trybots. See crbug.com/121540
312 //
313 // This fails on linux_aura bringup: http://crbug.com/163931
314 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
315 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
316 #else
317 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
318 #endif
319 // Test that a DNS error occuring in an iframe does not result in an
320 // additional session history entry.
321 IN_PROC_BROWSER_TEST_F(ErrorPageTest, MAYBE_IFrameDNSError_GoBackAndForward) {
322   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
323   NavigateToFileURL(FILE_PATH_LITERAL("iframe_dns_error.html"));
324   GoBackAndWaitForTitle("Title Of Awesomeness", 1);
325   GoForwardAndWaitForTitle("Blah", 1);
326 }
327
328 // Test that a DNS error occuring in an iframe, once the main document is
329 // completed loading, does not result in an additional session history entry.
330 // To ensure that the main document has completed loading, JavaScript is used to
331 // inject an iframe after loading is done.
332 IN_PROC_BROWSER_TEST_F(ErrorPageTest, IFrameDNSError_JavaScript) {
333   content::WebContents* wc =
334       browser()->tab_strip_model()->GetActiveWebContents();
335   GURL fail_url =
336       URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED);
337
338   // Load a regular web page, in which we will inject an iframe.
339   NavigateToFileURL(FILE_PATH_LITERAL("title2.html"));
340
341   // We expect to have two history entries, since we started off with navigation
342   // to "about:blank" and then navigated to "title2.html".
343   EXPECT_EQ(2, wc->GetController().GetEntryCount());
344
345   std::string script = "var frame = document.createElement('iframe');"
346                        "frame.src = '" + fail_url.spec() + "';"
347                        "document.body.appendChild(frame);";
348   {
349     TestFailProvisionalLoadObserver fail_observer(wc);
350     content::WindowedNotificationObserver load_observer(
351         content::NOTIFICATION_LOAD_STOP,
352         content::Source<NavigationController>(&wc->GetController()));
353     wc->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
354         base::string16(), base::ASCIIToUTF16(script));
355     load_observer.Wait();
356
357     // Ensure we saw the expected failure.
358     EXPECT_EQ(fail_url, fail_observer.fail_url());
359
360     // Failed initial navigation of an iframe shouldn't be adding any history
361     // entries.
362     EXPECT_EQ(2, wc->GetController().GetEntryCount());
363   }
364
365   // Do the same test, but with an iframe that doesn't have initial URL
366   // assigned.
367   script = "var frame = document.createElement('iframe');"
368            "frame.id = 'target_frame';"
369            "document.body.appendChild(frame);";
370   {
371     content::WindowedNotificationObserver load_observer(
372         content::NOTIFICATION_LOAD_STOP,
373         content::Source<NavigationController>(&wc->GetController()));
374     wc->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
375         base::string16(), base::ASCIIToUTF16(script));
376     load_observer.Wait();
377   }
378
379   script = "var f = document.getElementById('target_frame');"
380            "f.src = '" + fail_url.spec() + "';";
381   {
382     TestFailProvisionalLoadObserver fail_observer(wc);
383     content::WindowedNotificationObserver load_observer(
384         content::NOTIFICATION_LOAD_STOP,
385         content::Source<NavigationController>(&wc->GetController()));
386     wc->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
387         base::string16(), base::ASCIIToUTF16(script));
388     load_observer.Wait();
389
390     EXPECT_EQ(fail_url, fail_observer.fail_url());
391     EXPECT_EQ(2, wc->GetController().GetEntryCount());
392   }
393 }
394
395 // Checks that the Link Doctor is not loaded when we receive an actual 404 page.
396 IN_PROC_BROWSER_TEST_F(ErrorPageTest, Page404) {
397   NavigateToURLAndWaitForTitle(
398       content::URLRequestMockHTTPJob::GetMockUrl(
399           base::FilePath(FILE_PATH_LITERAL("page404.html"))),
400       "SUCCESS",
401       1);
402 }
403
404 // Checks that when an error occurs, the stale cache status of the page
405 // is correctly transferred.
406 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
407   ASSERT_TRUE(test_server()->Start());
408   // Load cache with entry with "nocache" set, to create stale
409   // cache.
410   GURL test_url(test_server()->GetURL("files/nocache.html"));
411   NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
412
413   // Reload same URL after forcing an error from the the network layer;
414   // confirm that the error page is told the cached copy exists.
415   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
416       browser()->profile()->GetRequestContext();
417   BrowserThread::PostTask(
418       BrowserThread::IO, FROM_HERE,
419       base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
420                  // Note that we can't use an error that'll invoke the link
421                  // doctor.  In normal network error conditions that would
422                  // work (because the link doctor fetch would also fail,
423                  // putting us back in the main offline path), but
424                  // SetUrlRequestMocksEnabled() has also specfied a link
425                  // doctor mock, which will be accessible because it
426                  // won't go through the network cache.
427                  net::ERR_FAILED));
428
429   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
430       // With no link doctor load, there's only one navigation.
431       browser(), test_url, 1);
432   EXPECT_TRUE(ProbeStaleCopyValue(true));
433
434   // Clear the cache and reload the same URL; confirm the error page is told
435   // that there is no cached copy.
436   BrowsingDataRemover* remover =
437       BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
438   remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
439                   BrowsingDataHelper::UNPROTECTED_WEB);
440   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
441       browser(), test_url, 1);
442   EXPECT_TRUE(ProbeStaleCopyValue(false));
443 }
444
445 // Returns Javascript code that executes plain text search for the page.
446 // Pass into content::ExecuteScriptAndExtractBool as |script| parameter.
447 std::string GetTextContentContainsStringScript(
448     const std::string& value_to_search) {
449   return base::StringPrintf(
450       "var textContent = document.body.textContent;"
451       "var hasError = textContent.indexOf('%s') >= 0;"
452       "domAutomationController.send(hasError);",
453       value_to_search.c_str());
454 }
455
456 // Protocol handler that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
457 class AddressUnreachableProtocolHandler
458     : public net::URLRequestJobFactory::ProtocolHandler {
459  public:
460   AddressUnreachableProtocolHandler() {}
461   virtual ~AddressUnreachableProtocolHandler() {}
462
463   // net::URLRequestJobFactory::ProtocolHandler:
464   virtual net::URLRequestJob* MaybeCreateJob(
465       net::URLRequest* request,
466       net::NetworkDelegate* network_delegate) const OVERRIDE {
467     return new URLRequestFailedJob(request,
468                                    network_delegate,
469                                    net::ERR_ADDRESS_UNREACHABLE);
470   }
471
472  private:
473   DISALLOW_COPY_AND_ASSIGN(AddressUnreachableProtocolHandler);
474 };
475
476 // A test fixture that returns ERR_ADDRESS_UNREACHABLE for all Link Doctor
477 // requests.  ERR_NAME_NOT_RESOLVED is more typical, but need to use a different
478 // error for the Link Doctor and the original page to validate the right page
479 // is being displayed.
480 class ErrorPageLinkDoctorFailTest : public ErrorPageTest {
481  public:
482   // InProcessBrowserTest:
483   virtual void SetUpOnMainThread() OVERRIDE {
484     BrowserThread::PostTask(
485         BrowserThread::IO, FROM_HERE,
486         base::Bind(&ErrorPageLinkDoctorFailTest::AddFilters));
487   }
488
489   virtual void CleanUpOnMainThread() OVERRIDE {
490     BrowserThread::PostTask(
491         BrowserThread::IO, FROM_HERE,
492         base::Bind(&ErrorPageLinkDoctorFailTest::RemoveFilters));
493   }
494
495  private:
496   // Adds a filter that causes all requests for the Link Doctor's scheme and
497   // host to fail with ERR_ADDRESS_UNREACHABLE.  Since the Link Doctor adds
498   // query strings, it's not enough to just fail exact matches.
499   //
500   // Also adds the content::URLRequestFailedJob filter.
501   static void AddFilters() {
502     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
503     content::URLRequestFailedJob::AddUrlHandler();
504
505     net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
506         google_util::LinkDoctorBaseURL().scheme(),
507         google_util::LinkDoctorBaseURL().host(),
508         scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
509             new AddressUnreachableProtocolHandler()));
510   }
511
512   static void RemoveFilters() {
513     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
514     net::URLRequestFilter::GetInstance()->ClearHandlers();
515   }
516 };
517
518 // Make sure that when the Link Doctor fails to load, the network error page is
519 // successfully loaded.
520 IN_PROC_BROWSER_TEST_F(ErrorPageLinkDoctorFailTest, LinkDoctorFail) {
521   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
522       browser(),
523       URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
524       2);
525
526   // Verify that the expected error page is being displayed.  Do this by making
527   // sure the original error code (ERR_NAME_NOT_RESOLVED) is displayed.
528   bool result = false;
529   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
530       browser()->tab_strip_model()->GetActiveWebContents(),
531       GetTextContentContainsStringScript("ERR_NAME_NOT_RESOLVED"),
532       &result));
533   EXPECT_TRUE(result);
534 }
535
536 // Checks that when an error occurs and a link doctor load fails, the stale
537 // cache status of the page is correctly transferred.  Most logic copied
538 // from StaleCacheStatus above.
539 IN_PROC_BROWSER_TEST_F(ErrorPageLinkDoctorFailTest,
540                        StaleCacheStatusFailedLinkDoctor) {
541   ASSERT_TRUE(test_server()->Start());
542   // Load cache with entry with "nocache" set, to create stale
543   // cache.
544   GURL test_url(test_server()->GetURL("files/nocache.html"));
545   NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
546
547   // Reload same URL after forcing an error from the the network layer;
548   // confirm that the error page is told the cached copy exists.
549   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
550       browser()->profile()->GetRequestContext();
551   BrowserThread::PostTask(
552       BrowserThread::IO, FROM_HERE,
553       base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
554                  net::ERR_CONNECTION_FAILED));
555
556   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
557       browser(), test_url, 2);
558   ProbeStaleCopyValue(true);
559
560   // Clear the cache and reload the same URL; confirm the error page is told
561   // that there is no cached copy.
562   BrowsingDataRemover* remover =
563       BrowsingDataRemover::CreateForUnboundedRange(browser()->profile());
564   remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
565                   BrowsingDataHelper::UNPROTECTED_WEB);
566   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
567       browser(), test_url, 2);
568   ProbeStaleCopyValue(false);
569 }
570
571 // A test fixture that simulates failing requests for an IDN domain name.
572 class ErrorPageForIDNTest : public InProcessBrowserTest {
573  public:
574   // Target hostname in different forms.
575   static const char kHostname[];
576   static const char kHostnameJSUnicode[];
577
578   // InProcessBrowserTest:
579   virtual void SetUpOnMainThread() OVERRIDE {
580     // Clear AcceptLanguages to force punycode decoding.
581     browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
582                                                 std::string());
583     BrowserThread::PostTask(
584         BrowserThread::IO, FROM_HERE,
585         base::Bind(&ErrorPageForIDNTest::AddFilters));
586   }
587
588   virtual void CleanUpOnMainThread() OVERRIDE {
589     BrowserThread::PostTask(
590         BrowserThread::IO, FROM_HERE,
591         base::Bind(&ErrorPageForIDNTest::RemoveFilters));
592   }
593
594  private:
595   static void AddFilters() {
596     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
597     content::URLRequestFailedJob::AddUrlHandlerForHostname(kHostname);
598   }
599
600   static void RemoveFilters() {
601     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
602     net::URLRequestFilter::GetInstance()->ClearHandlers();
603   }
604 };
605
606 const char ErrorPageForIDNTest::kHostname[] =
607     "xn--d1abbgf6aiiy.xn--p1ai";
608 const char ErrorPageForIDNTest::kHostnameJSUnicode[] =
609     "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
610     "\\u0440\\u0444";
611
612 // Make sure error page shows correct unicode for IDN.
613 IN_PROC_BROWSER_TEST_F(ErrorPageForIDNTest, IDN) {
614   // ERR_UNSAFE_PORT will not trigger the link doctor.
615   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
616       browser(),
617       URLRequestFailedJob::GetMockHttpUrlForHostname(net::ERR_UNSAFE_PORT,
618                                                      kHostname),
619       1);
620
621   bool result = false;
622   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
623       browser()->tab_strip_model()->GetActiveWebContents(),
624       GetTextContentContainsStringScript(kHostnameJSUnicode),
625       &result));
626   EXPECT_TRUE(result);
627 }
628
629 }  // namespace