- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / session_history_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/strings/string_util.h"
6 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/public/browser/navigation_controller.h"
9 #include "content/public/browser/notification_service.h"
10 #include "content/public/browser/notification_types.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/common/url_constants.h"
13 #include "content/public/test/browser_test_utils.h"
14 #include "content/public/test/test_utils.h"
15 #include "content/shell/browser/shell.h"
16 #include "content/test/content_browser_test.h"
17 #include "content/test/content_browser_test_utils.h"
18 #include "net/test/embedded_test_server/embedded_test_server.h"
19 #include "net/test/embedded_test_server/http_request.h"
20 #include "net/test/embedded_test_server/http_response.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace content {
24
25 namespace {
26
27 // Handles |request| by serving a response with title set to request contents.
28 scoped_ptr<net::test_server::HttpResponse> HandleEchoTitleRequest(
29     const std::string& echotitle_path,
30     const net::test_server::HttpRequest& request) {
31   if (!StartsWithASCII(request.relative_url, echotitle_path, true))
32     return scoped_ptr<net::test_server::HttpResponse>();
33
34   scoped_ptr<net::test_server::BasicHttpResponse> http_response(
35       new net::test_server::BasicHttpResponse);
36   http_response->set_code(net::HTTP_OK);
37   http_response->set_content(
38       base::StringPrintf(
39           "<html><head><title>%s</title></head></html>",
40           request.content.c_str()));
41   return http_response.PassAs<net::test_server::HttpResponse>();
42 }
43
44 }  // namespace
45
46 class SessionHistoryTest : public ContentBrowserTest {
47  protected:
48   SessionHistoryTest() {}
49
50   virtual void SetUpOnMainThread() OVERRIDE {
51     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
52     embedded_test_server()->RegisterRequestHandler(
53         base::Bind(&HandleEchoTitleRequest, "/echotitle"));
54
55     NavigateToURL(shell(), GURL(kAboutBlankURL));
56   }
57
58   // Simulate clicking a link.  Only works on the frames.html testserver page.
59   void ClickLink(std::string node_id) {
60     GURL url("javascript:clickLink('" + node_id + "')");
61     NavigateToURL(shell(), url);
62   }
63
64   // Simulate filling in form data.  Only works on the frames.html page with
65   // subframe = form.html, and on form.html itself.
66   void FillForm(std::string node_id, std::string value) {
67     GURL url("javascript:fillForm('" + node_id + "', '" + value + "')");
68     // This will return immediately, but since the JS executes synchronously
69     // on the renderer, it will complete before the next navigate message is
70     // processed.
71     NavigateToURL(shell(), url);
72   }
73
74   // Simulate submitting a form.  Only works on the frames.html page with
75   // subframe = form.html, and on form.html itself.
76   void SubmitForm(std::string node_id) {
77     GURL url("javascript:submitForm('" + node_id + "')");
78     NavigateToURL(shell(), url);
79   }
80
81   // Navigate session history using history.go(distance).
82   void JavascriptGo(std::string distance) {
83     GURL url("javascript:history.go('" + distance + "')");
84     NavigateToURL(shell(), url);
85   }
86
87   std::string GetTabTitle() {
88     return UTF16ToASCII(shell()->web_contents()->GetTitle());
89   }
90
91   GURL GetTabURL() {
92     return shell()->web_contents()->GetLastCommittedURL();
93   }
94
95   GURL GetURL(const std::string file) {
96     return embedded_test_server()->GetURL(
97         std::string("/session_history/") + file);
98   }
99
100   void NavigateAndCheckTitle(const char* filename,
101                              const std::string& expected_title) {
102     string16 expected_title16(ASCIIToUTF16(expected_title));
103     TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
104     NavigateToURL(shell(), GetURL(filename));
105     ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
106   }
107
108   bool CanGoBack() {
109     return shell()->web_contents()->GetController().CanGoBack();
110   }
111
112   bool CanGoForward() {
113     return shell()->web_contents()->GetController().CanGoForward();
114   }
115
116   void GoBack() {
117     WindowedNotificationObserver load_stop_observer(
118         NOTIFICATION_LOAD_STOP,
119         NotificationService::AllSources());
120     shell()->web_contents()->GetController().GoBack();
121     load_stop_observer.Wait();
122   }
123
124   void GoForward() {
125     WindowedNotificationObserver load_stop_observer(
126         NOTIFICATION_LOAD_STOP,
127         NotificationService::AllSources());
128     shell()->web_contents()->GetController().GoForward();
129     load_stop_observer.Wait();
130   }
131 };
132
133 // If this flakes, use http://crbug.com/61619 on windows and
134 // http://crbug.com/102094 on mac.
135 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, BasicBackForward) {
136   ASSERT_FALSE(CanGoBack());
137
138   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
139   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
140   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
141
142   // history is [blank, bot1, bot2, *bot3]
143
144   GoBack();
145   EXPECT_EQ("bot2", GetTabTitle());
146
147   GoBack();
148   EXPECT_EQ("bot1", GetTabTitle());
149
150   GoForward();
151   EXPECT_EQ("bot2", GetTabTitle());
152
153   GoBack();
154   EXPECT_EQ("bot1", GetTabTitle());
155
156   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
157
158   // history is [blank, bot1, *bot3]
159
160   ASSERT_FALSE(CanGoForward());
161   EXPECT_EQ("bot3", GetTabTitle());
162
163   GoBack();
164   EXPECT_EQ("bot1", GetTabTitle());
165
166   GoBack();
167   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
168
169   ASSERT_FALSE(CanGoBack());
170   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
171
172   GoForward();
173   EXPECT_EQ("bot1", GetTabTitle());
174
175   GoForward();
176   EXPECT_EQ("bot3", GetTabTitle());
177 }
178
179 // Test that back/forward works when navigating in subframes.
180 // If this flakes, use http://crbug.com/48833
181 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameBackForward) {
182   ASSERT_FALSE(CanGoBack());
183
184   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
185
186   ClickLink("abot2");
187   EXPECT_EQ("bot2", GetTabTitle());
188   GURL frames(GetURL("frames.html"));
189   EXPECT_EQ(frames, GetTabURL());
190
191   ClickLink("abot3");
192   EXPECT_EQ("bot3", GetTabTitle());
193   EXPECT_EQ(frames, GetTabURL());
194
195   // history is [blank, bot1, bot2, *bot3]
196
197   GoBack();
198   EXPECT_EQ("bot2", GetTabTitle());
199   EXPECT_EQ(frames, GetTabURL());
200
201   GoBack();
202   EXPECT_EQ("bot1", GetTabTitle());
203   EXPECT_EQ(frames, GetTabURL());
204
205   GoBack();
206   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
207   EXPECT_EQ(GURL(kAboutBlankURL), GetTabURL());
208
209   GoForward();
210   EXPECT_EQ("bot1", GetTabTitle());
211   EXPECT_EQ(frames, GetTabURL());
212
213   GoForward();
214   EXPECT_EQ("bot2", GetTabTitle());
215   EXPECT_EQ(frames, GetTabURL());
216
217   ClickLink("abot1");
218   EXPECT_EQ("bot1", GetTabTitle());
219   EXPECT_EQ(frames, GetTabURL());
220
221   // history is [blank, bot1, bot2, *bot1]
222
223   ASSERT_FALSE(CanGoForward());
224   EXPECT_EQ("bot1", GetTabTitle());
225   EXPECT_EQ(frames, GetTabURL());
226
227   GoBack();
228   EXPECT_EQ("bot2", GetTabTitle());
229   EXPECT_EQ(frames, GetTabURL());
230
231   GoBack();
232   EXPECT_EQ("bot1", GetTabTitle());
233   EXPECT_EQ(frames, GetTabURL());
234 }
235
236 // Test that back/forward preserves POST data and document state in subframes.
237 // If this flakes use http://crbug.com/61619
238 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameFormBackForward) {
239   ASSERT_FALSE(CanGoBack());
240
241   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
242
243   ClickLink("aform");
244   EXPECT_EQ("form", GetTabTitle());
245   GURL frames(GetURL("frames.html"));
246   EXPECT_EQ(frames, GetTabURL());
247
248   SubmitForm("isubmit");
249   EXPECT_EQ("text=&select=a", GetTabTitle());
250   EXPECT_EQ(frames, GetTabURL());
251
252   GoBack();
253   EXPECT_EQ("form", GetTabTitle());
254   EXPECT_EQ(frames, GetTabURL());
255
256   // history is [blank, bot1, *form, post]
257
258   ClickLink("abot2");
259   EXPECT_EQ("bot2", GetTabTitle());
260   EXPECT_EQ(frames, GetTabURL());
261
262   // history is [blank, bot1, form, *bot2]
263
264   GoBack();
265   EXPECT_EQ("form", GetTabTitle());
266   EXPECT_EQ(frames, GetTabURL());
267
268   SubmitForm("isubmit");
269   EXPECT_EQ("text=&select=a", GetTabTitle());
270   EXPECT_EQ(frames, GetTabURL());
271
272   // history is [blank, bot1, form, *post]
273
274   // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed:
275   // "returning to a POST result within a frame does a GET instead of a POST"
276   ClickLink("abot2");
277   EXPECT_EQ("bot2", GetTabTitle());
278   EXPECT_EQ(frames, GetTabURL());
279
280   GoBack();
281   EXPECT_EQ("text=&select=a", GetTabTitle());
282   EXPECT_EQ(frames, GetTabURL());
283 }
284
285 // TODO(mpcomplete): enable this when Bug 734372 is fixed:
286 // "Doing a session history navigation does not restore newly-created subframe
287 // document state"
288 // Test that back/forward preserves POST data and document state when navigating
289 // across frames (ie, from frame -> nonframe).
290 // Hangs, see http://crbug.com/45058.
291 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) {
292   ASSERT_FALSE(CanGoBack());
293
294   GURL frames(GetURL("frames.html"));
295   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
296
297   ClickLink("aform");
298   EXPECT_EQ("form", GetTabTitle());
299   EXPECT_EQ(frames, GetTabURL());
300
301   SubmitForm("isubmit");
302   EXPECT_EQ("text=&select=a", GetTabTitle());
303   EXPECT_EQ(frames, GetTabURL());
304
305   GoBack();
306   EXPECT_EQ("form", GetTabTitle());
307   EXPECT_EQ(frames, GetTabURL());
308
309   // history is [blank, bot1, *form, post]
310
311   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
312
313   // history is [blank, bot1, form, *bot2]
314
315   GoBack();
316   EXPECT_EQ("bot1", GetTabTitle());
317   EXPECT_EQ(frames, GetTabURL());
318
319   SubmitForm("isubmit");
320   EXPECT_EQ("text=&select=a", GetTabTitle());
321   EXPECT_EQ(frames, GetTabURL());
322 }
323
324 // Test that back/forward entries are created for reference fragment
325 // navigations. Bug 730379.
326 // If this flakes use http://crbug.com/61619.
327 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FragmentBackForward) {
328   embedded_test_server()->RegisterRequestHandler(
329       base::Bind(&HandleEchoTitleRequest, "/echotitle"));
330
331   ASSERT_FALSE(CanGoBack());
332
333   GURL fragment(GetURL("fragment.html"));
334   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html", "fragment"));
335
336   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#a", "fragment"));
337   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#b", "fragment"));
338   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#c", "fragment"));
339
340   // history is [blank, fragment, fragment#a, fragment#b, *fragment#c]
341
342   GoBack();
343   EXPECT_EQ(GetURL("fragment.html#b"), GetTabURL());
344
345   GoBack();
346   EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
347
348   GoBack();
349   EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
350
351   GoForward();
352   EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
353
354   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
355
356   // history is [blank, fragment, fragment#a, bot3]
357
358   ASSERT_FALSE(CanGoForward());
359   EXPECT_EQ(GetURL("bot3.html"), GetTabURL());
360
361   GoBack();
362   EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
363
364   GoBack();
365   EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
366 }
367
368 // Test that the javascript window.history object works.
369 // NOTE: history.go(N) does not do anything if N is outside the bounds of the
370 // back/forward list (such as trigger our start/stop loading events).  This
371 // means the test will hang if it attempts to navigate too far forward or back,
372 // since we'll be waiting forever for a load stop event.
373 //
374 // TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing
375 // about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug).
376 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, JavascriptHistory) {
377   ASSERT_FALSE(CanGoBack());
378
379   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
380   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
381   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
382
383   // history is [blank, bot1, bot2, *bot3]
384
385   JavascriptGo("-1");
386   EXPECT_EQ("bot2", GetTabTitle());
387
388   JavascriptGo("-1");
389   EXPECT_EQ("bot1", GetTabTitle());
390
391   JavascriptGo("1");
392   EXPECT_EQ("bot2", GetTabTitle());
393
394   JavascriptGo("-1");
395   EXPECT_EQ("bot1", GetTabTitle());
396
397   JavascriptGo("2");
398   EXPECT_EQ("bot3", GetTabTitle());
399
400   // history is [blank, bot1, bot2, *bot3]
401
402   JavascriptGo("-3");
403   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
404
405   ASSERT_FALSE(CanGoBack());
406   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
407
408   JavascriptGo("1");
409   EXPECT_EQ("bot1", GetTabTitle());
410
411   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
412
413   // history is [blank, bot1, *bot3]
414
415   ASSERT_FALSE(CanGoForward());
416   EXPECT_EQ("bot3", GetTabTitle());
417
418   JavascriptGo("-1");
419   EXPECT_EQ("bot1", GetTabTitle());
420
421   JavascriptGo("-1");
422   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
423
424   ASSERT_FALSE(CanGoBack());
425   EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle());
426
427   JavascriptGo("1");
428   EXPECT_EQ("bot1", GetTabTitle());
429
430   JavascriptGo("1");
431   EXPECT_EQ("bot3", GetTabTitle());
432
433   // TODO(creis): Test that JavaScript history navigations work across tab
434   // types.  For example, load about:network in a tab, then a real page, then
435   // try to go back and forward with JavaScript.  Bug 1136715.
436   // (Hard to test right now, because pages like about:network cause the
437   // TabProxy to hang.  This is because they do not appear to use the
438   // NotificationService.)
439 }
440
441 // This test is failing consistently. See http://crbug.com/22560
442 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationReplace) {
443   // Test that using location.replace doesn't leave the title of the old page
444   // visible.
445   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
446       "replace.html?bot1.html", "bot1"));
447 }
448
449 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationChangeInSubframe) {
450   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
451       "location_redirect.html", "Default Title"));
452
453   NavigateToURL(shell(), GURL("javascript:void(frames[0].navigate())"));
454   EXPECT_EQ("foo", GetTabTitle());
455
456   GoBack();
457   EXPECT_EQ("Default Title", GetTabTitle());
458 }
459
460 // http://code.google.com/p/chromium/issues/detail?id=56267
461 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
462   int length;
463   ASSERT_TRUE(ExecuteScriptAndExtractInt(
464       shell()->web_contents(),
465       "domAutomationController.send(history.length)",
466       &length));
467   EXPECT_EQ(1, length);
468
469   NavigateToURL(shell(), GetURL("title1.html"));
470
471   ASSERT_TRUE(ExecuteScriptAndExtractInt(
472       shell()->web_contents(),
473       "domAutomationController.send(history.length)",
474       &length));
475   EXPECT_EQ(2, length);
476
477   // Now test that history.length is updated when the navigation is committed.
478   NavigateToURL(shell(), GetURL("record_length.html"));
479
480   ASSERT_TRUE(ExecuteScriptAndExtractInt(
481       shell()->web_contents(),
482       "domAutomationController.send(history.length)",
483       &length));
484   EXPECT_EQ(3, length);
485
486   GoBack();
487   GoBack();
488
489   // Ensure history.length is properly truncated.
490   NavigateToURL(shell(), GetURL("title2.html"));
491
492   ASSERT_TRUE(ExecuteScriptAndExtractInt(
493       shell()->web_contents(),
494       "domAutomationController.send(history.length)",
495       &length));
496   EXPECT_EQ(2, length);
497 }
498
499 }  // namespace content