Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / history / redirect_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 // Navigates the browser to server and client redirect pages and makes sure
6 // that the correct redirects are reflected in the history database. Errors
7 // here might indicate that WebKit changed the calls our glue layer gets in
8 // the case of redirects. It may also mean problems with the history system.
9
10 #include "base/bind.h"
11 #include "base/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/task/cancelable_task_tracker.h"
19 #include "base/test/test_timeouts.h"
20 #include "base/threading/platform_thread.h"
21 #include "chrome/browser/history/history_service.h"
22 #include "chrome/browser/history/history_service_factory.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/browser/ui/view_ids.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "chrome/test/base/ui_test_utils.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/test/browser_test_utils.h"
31 #include "content/public/test/test_navigation_observer.h"
32 #include "net/base/filename_util.h"
33 #include "net/test/spawned_test_server/spawned_test_server.h"
34 #include "ui/events/event_constants.h"
35
36 class RedirectTest : public InProcessBrowserTest {
37  public:
38   RedirectTest() {}
39
40   std::vector<GURL> GetRedirects(const GURL& url) {
41     HistoryService* history_service =
42         HistoryServiceFactory::GetForProfile(browser()->profile(),
43                                              Profile::EXPLICIT_ACCESS);
44
45     // Schedule a history query for redirects. The response will be sent
46     // asynchronously from the callback the history system uses to notify us
47     // that it's done: OnRedirectQueryComplete.
48     std::vector<GURL> rv;
49     history_service->QueryRedirectsFrom(
50         url,
51         base::Bind(&RedirectTest::OnRedirectQueryComplete,
52                    base::Unretained(this),
53                    &rv),
54         &tracker_);
55     content::RunMessageLoop();
56     return rv;
57   }
58
59  protected:
60   void OnRedirectQueryComplete(std::vector<GURL>* rv,
61                                const history::RedirectList* redirects) {
62     rv->insert(rv->end(), redirects->begin(), redirects->end());
63     base::MessageLoop::current()->PostTask(FROM_HERE,
64                                            base::MessageLoop::QuitClosure());
65   }
66
67   // Tracker for asynchronous history queries.
68   base::CancelableTaskTracker tracker_;
69 };
70
71 // Tests a single server redirect
72 IN_PROC_BROWSER_TEST_F(RedirectTest, Server) {
73   ASSERT_TRUE(test_server()->Start());
74   GURL final_url = test_server()->GetURL(std::string());
75   GURL first_url = test_server()->GetURL(
76       "server-redirect?" + final_url.spec());
77
78   ui_test_utils::NavigateToURL(browser(), first_url);
79
80   std::vector<GURL> redirects = GetRedirects(first_url);
81
82   ASSERT_EQ(1U, redirects.size());
83   EXPECT_EQ(final_url.spec(), redirects[0].spec());
84 }
85
86 // Tests a single client redirect.
87 IN_PROC_BROWSER_TEST_F(RedirectTest, Client) {
88   ASSERT_TRUE(test_server()->Start());
89
90   GURL final_url = test_server()->GetURL(std::string());
91   GURL first_url = test_server()->GetURL(
92       "client-redirect?" + final_url.spec());
93
94   // The client redirect appears as two page visits in the browser.
95   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
96       browser(), first_url, 2);
97
98   std::vector<GURL> redirects = GetRedirects(first_url);
99
100   ASSERT_EQ(1U, redirects.size());
101   EXPECT_EQ(final_url.spec(), redirects[0].spec());
102
103   // The address bar should display the final URL.
104   EXPECT_EQ(final_url,
105             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
106
107   // Navigate one more time.
108   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
109       browser(), first_url, 2);
110
111   // The address bar should still display the final URL.
112   EXPECT_EQ(final_url,
113             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
114 }
115
116 // http://code.google.com/p/chromium/issues/detail?id=62772
117 IN_PROC_BROWSER_TEST_F(RedirectTest, ClientEmptyReferer) {
118   ASSERT_TRUE(test_server()->Start());
119
120   // Create the file contents, which will do a redirect to the
121   // test server.
122   GURL final_url = test_server()->GetURL(std::string());
123   ASSERT_TRUE(final_url.is_valid());
124   std::string file_redirect_contents = base::StringPrintf(
125       "<html>"
126       "<head></head>"
127       "<body onload=\"document.location='%s'\"></body>"
128       "</html>",
129       final_url.spec().c_str());
130
131   // Write the contents to a temporary file.
132   base::ScopedTempDir temp_directory;
133   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
134   base::FilePath temp_file;
135   ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.path(),
136                                              &temp_file));
137   ASSERT_EQ(static_cast<int>(file_redirect_contents.size()),
138             base::WriteFile(temp_file,
139                             file_redirect_contents.data(),
140                             file_redirect_contents.size()));
141
142   // Navigate to the file through the browser. The client redirect will appear
143   // as two page visits in the browser.
144   GURL first_url = net::FilePathToFileURL(temp_file);
145   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
146       browser(), first_url, 2);
147
148   std::vector<GURL> redirects = GetRedirects(first_url);
149   ASSERT_EQ(1U, redirects.size());
150   EXPECT_EQ(final_url.spec(), redirects[0].spec());
151 }
152
153 // Tests to make sure a location change when a pending redirect exists isn't
154 // flagged as a redirect.
155 IN_PROC_BROWSER_TEST_F(RedirectTest, ClientCancelled) {
156   GURL first_url = ui_test_utils::GetTestUrl(
157       base::FilePath(),
158       base::FilePath().AppendASCII("cancelled_redirect_test.html"));
159   ui_test_utils::NavigateToURL(browser(), first_url);
160
161   content::WebContents* web_contents =
162       browser()->tab_strip_model()->GetActiveWebContents();
163   content::TestNavigationObserver navigation_observer(web_contents);
164
165   // Simulate a click to force to make a user-initiated location change;
166   // otherwise, a non user-initiated in-page location change will be treated
167   // as client redirect and the redirect will be recoreded, which can cause
168   // this test failed.
169   content::SimulateMouseClick(web_contents, 0,
170       blink::WebMouseEvent::ButtonLeft);
171   navigation_observer.Wait();
172
173   std::vector<GURL> redirects = GetRedirects(first_url);
174
175   // There should be no redirects from first_url, because the anchor location
176   // change that occurs should not be flagged as a redirect and the meta-refresh
177   // won't have fired yet.
178   ASSERT_EQ(0U, redirects.size());
179   EXPECT_EQ("myanchor", web_contents->GetURL().ref());
180 }
181
182 // Tests a client->server->server redirect
183 IN_PROC_BROWSER_TEST_F(RedirectTest, ClientServerServer) {
184   ASSERT_TRUE(test_server()->Start());
185
186   GURL final_url = test_server()->GetURL(std::string());
187   GURL next_to_last = test_server()->GetURL(
188       "server-redirect?" + final_url.spec());
189   GURL second_url = test_server()->GetURL(
190       "server-redirect?" + next_to_last.spec());
191   GURL first_url = test_server()->GetURL(
192       "client-redirect?" + second_url.spec());
193
194   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
195       browser(), first_url, 2);
196
197   std::vector<GURL> redirects = GetRedirects(first_url);
198   ASSERT_EQ(3U, redirects.size());
199   EXPECT_EQ(second_url.spec(), redirects[0].spec());
200   EXPECT_EQ(next_to_last.spec(), redirects[1].spec());
201   EXPECT_EQ(final_url.spec(), redirects[2].spec());
202 }
203
204 // Tests that the "#reference" gets preserved across server redirects.
205 IN_PROC_BROWSER_TEST_F(RedirectTest, ServerReference) {
206   ASSERT_TRUE(test_server()->Start());
207
208   const std::string ref("reference");
209
210   GURL final_url = test_server()->GetURL(std::string());
211   GURL initial_url = test_server()->GetURL(
212       "server-redirect?" + final_url.spec() + "#" + ref);
213
214   ui_test_utils::NavigateToURL(browser(), initial_url);
215
216   EXPECT_EQ(ref,
217             browser()->tab_strip_model()->GetActiveWebContents()->
218                 GetURL().ref());
219 }
220
221 // Test that redirect from http:// to file:// :
222 // A) does not crash the browser or confuse the redirect chain, see bug 1080873
223 // B) does not take place.
224 //
225 // Flaky on XP and Vista, http://crbug.com/69390.
226 IN_PROC_BROWSER_TEST_F(RedirectTest, NoHttpToFile) {
227   ASSERT_TRUE(test_server()->Start());
228   GURL file_url = ui_test_utils::GetTestUrl(
229       base::FilePath(), base::FilePath().AppendASCII("http_to_file.html"));
230
231   GURL initial_url = test_server()->GetURL(
232       "client-redirect?" + file_url.spec());
233
234   ui_test_utils::NavigateToURL(browser(), initial_url);
235   // We make sure the title doesn't match the title from the file, because the
236   // nav should not have taken place.
237   EXPECT_NE(base::ASCIIToUTF16("File!"),
238             browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
239 }
240
241 // Ensures that non-user initiated location changes (within page) are
242 // flagged as client redirects. See bug 1139823.
243 IN_PROC_BROWSER_TEST_F(RedirectTest, ClientFragments) {
244   ASSERT_TRUE(test_server()->Start());
245   GURL first_url = ui_test_utils::GetTestUrl(
246       base::FilePath(), base::FilePath().AppendASCII("ref_redirect.html"));
247   ui_test_utils::NavigateToURL(browser(), first_url);
248   std::vector<GURL> redirects = GetRedirects(first_url);
249   EXPECT_EQ(1U, redirects.size());
250   EXPECT_EQ(first_url.spec() + "#myanchor", redirects[0].spec());
251 }
252
253 // TODO(timsteele): This is disabled because our current testserver can't
254 // handle multiple requests in parallel, making it hang on the first request
255 // to /slow?60. It's unable to serve our second request for files/title2.html
256 // until /slow? completes, which doesn't give the desired behavior. We could
257 // alternatively load the second page from disk, but we would need to start
258 // the browser for this testcase with --process-per-tab, and I don't think
259 // we can do this at test-case-level granularity at the moment.
260 // http://crbug.com/45056
261 IN_PROC_BROWSER_TEST_F(RedirectTest,
262        DISABLED_ClientCancelledByNewNavigationAfterProvisionalLoad) {
263   // We want to initiate a second navigation after the provisional load for
264   // the client redirect destination has started, but before this load is
265   // committed. To achieve this, we tell the browser to load a slow page,
266   // which causes it to start a provisional load, and while it is waiting
267   // for the response (which means it hasn't committed the load for the client
268   // redirect destination page yet), we issue a new navigation request.
269   ASSERT_TRUE(test_server()->Start());
270
271   GURL final_url = test_server()->GetURL("files/title2.html");
272   GURL slow = test_server()->GetURL("slow?60");
273   GURL first_url = test_server()->GetURL(
274       "client-redirect?" + slow.spec());
275
276   content::WebContents* web_contents =
277       browser()->tab_strip_model()->GetActiveWebContents();
278   content::TestNavigationObserver observer(web_contents, 2);
279
280   ui_test_utils::NavigateToURLWithDisposition(
281       browser(), first_url, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
282   // We don't sleep here - the first navigation won't have been committed yet
283   // because we told the server to wait a minute. This means the browser has
284   // started it's provisional load for the client redirect destination page but
285   // hasn't completed. Our time is now!
286   ui_test_utils::NavigateToURLWithDisposition(
287       browser(), final_url, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
288   observer.Wait();
289
290   // Check to make sure the navigation did in fact take place and we are
291   // at the expected page.
292   EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
293             browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
294
295   bool final_navigation_not_redirect = true;
296   std::vector<GURL> redirects = GetRedirects(first_url);
297   // Check to make sure our request for files/title2.html doesn't get flagged
298   // as a client redirect from the first (/client-redirect?) page.
299   for (std::vector<GURL>::iterator it = redirects.begin();
300        it != redirects.end(); ++it) {
301     if (final_url.spec() == it->spec()) {
302       final_navigation_not_redirect = false;
303       break;
304     }
305   }
306   EXPECT_TRUE(final_navigation_not_redirect);
307 }