session_history_uitest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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/string_util.h"
6#include "chrome/common/url_constants.h"
7#include "chrome/test/automation/tab_proxy.h"
8#include "chrome/test/automation/browser_proxy.h"
9#include "chrome/test/ui/ui_test.h"
10#include "grit/generated_resources.h"
11#include "net/base/net_util.h"
12#include "net/test/test_server.h"
13
14namespace {
15
16class SessionHistoryTest : public UITest {
17 protected:
18  SessionHistoryTest()
19      : test_server_(net::TestServer::TYPE_HTTP,
20                     FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {
21    dom_automation_enabled_ = true;
22  }
23
24  virtual void SetUp() {
25    UITest::SetUp();
26
27    window_ = automation()->GetBrowserWindow(0);
28    ASSERT_TRUE(window_.get());
29
30    tab_ = window_->GetActiveTab();
31    ASSERT_TRUE(tab_.get());
32  }
33
34  // Simulate clicking a link.  Only works on the frames.html testserver page.
35  void ClickLink(std::string node_id) {
36    GURL url("javascript:clickLink('" + node_id + "')");
37    ASSERT_TRUE(tab_->NavigateToURL(url));
38  }
39
40  // Simulate filling in form data.  Only works on the frames.html page with
41  // subframe = form.html, and on form.html itself.
42  void FillForm(std::string node_id, std::string value) {
43    GURL url("javascript:fillForm('" + node_id + "', '" + value + "')");
44    // This will return immediately, but since the JS executes synchronously
45    // on the renderer, it will complete before the next navigate message is
46    // processed.
47    ASSERT_TRUE(tab_->NavigateToURLAsync(url));
48  }
49
50  // Simulate submitting a form.  Only works on the frames.html page with
51  // subframe = form.html, and on form.html itself.
52  void SubmitForm(std::string node_id) {
53    GURL url("javascript:submitForm('" + node_id + "')");
54    ASSERT_TRUE(tab_->NavigateToURL(url));
55  }
56
57  // Navigate session history using history.go(distance).
58  void JavascriptGo(std::string distance) {
59    GURL url("javascript:history.go('" + distance + "')");
60    ASSERT_TRUE(tab_->NavigateToURL(url));
61  }
62
63  std::wstring GetTabTitle() {
64    std::wstring title;
65    EXPECT_TRUE(tab_->GetTabTitle(&title));
66    return title;
67  }
68
69  GURL GetTabURL() {
70    GURL url;
71    EXPECT_TRUE(tab_->GetCurrentURL(&url));
72    return url;
73  }
74
75 protected:
76  scoped_refptr<BrowserProxy> window_;
77  scoped_refptr<TabProxy> tab_;
78
79  net::TestServer test_server_;
80};
81
82#if defined(OS_WIN)
83// See http://crbug.com/61619
84#define MAYBE_BasicBackForward FLAKY_BasicBackForward
85#else
86#define MAYBE_BasicBackForward BasicBackForward
87#endif
88
89TEST_F(SessionHistoryTest, MAYBE_BasicBackForward) {
90  ASSERT_TRUE(test_server_.Start());
91
92  // about:blank should be loaded first.
93  ASSERT_FALSE(tab_->GoBack());
94  EXPECT_EQ(L"", GetTabTitle());
95
96  ASSERT_TRUE(tab_->NavigateToURL(
97      test_server_.GetURL("files/session_history/bot1.html")));
98  EXPECT_EQ(L"bot1", GetTabTitle());
99
100  ASSERT_TRUE(tab_->NavigateToURL(
101      test_server_.GetURL("files/session_history/bot2.html")));
102  EXPECT_EQ(L"bot2", GetTabTitle());
103
104  ASSERT_TRUE(tab_->NavigateToURL(
105      test_server_.GetURL("files/session_history/bot3.html")));
106  EXPECT_EQ(L"bot3", GetTabTitle());
107
108  // history is [blank, bot1, bot2, *bot3]
109
110  ASSERT_TRUE(tab_->GoBack());
111  EXPECT_EQ(L"bot2", GetTabTitle());
112
113  ASSERT_TRUE(tab_->GoBack());
114  EXPECT_EQ(L"bot1", GetTabTitle());
115
116  ASSERT_TRUE(tab_->GoForward());
117  EXPECT_EQ(L"bot2", GetTabTitle());
118
119  ASSERT_TRUE(tab_->GoBack());
120  EXPECT_EQ(L"bot1", GetTabTitle());
121
122  ASSERT_TRUE(tab_->NavigateToURL(
123      test_server_.GetURL("files/session_history/bot3.html")));
124  EXPECT_EQ(L"bot3", GetTabTitle());
125
126  // history is [blank, bot1, *bot3]
127
128  ASSERT_FALSE(tab_->GoForward());
129  EXPECT_EQ(L"bot3", GetTabTitle());
130
131  ASSERT_TRUE(tab_->GoBack());
132  EXPECT_EQ(L"bot1", GetTabTitle());
133
134  ASSERT_TRUE(tab_->GoBack());
135  EXPECT_EQ(L"", GetTabTitle());
136
137  ASSERT_FALSE(tab_->GoBack());
138  EXPECT_EQ(L"", GetTabTitle());
139
140  ASSERT_TRUE(tab_->GoForward());
141  EXPECT_EQ(L"bot1", GetTabTitle());
142
143  ASSERT_TRUE(tab_->GoForward());
144  EXPECT_EQ(L"bot3", GetTabTitle());
145}
146
147#if defined(OS_WIN)
148// See http://crbug.com/61619
149#define MAYBE_FrameBackForward FLAKY_FrameBackForward
150#else
151#define MAYBE_FrameBackForward FrameBackForward
152#endif
153
154// Test that back/forward works when navigating in subframes.
155TEST_F(SessionHistoryTest, MAYBE_FrameBackForward) {
156  ASSERT_TRUE(test_server_.Start());
157
158  // about:blank should be loaded first.
159  GURL home(homepage());
160  ASSERT_FALSE(tab_->GoBack());
161  EXPECT_EQ(L"", GetTabTitle());
162  EXPECT_EQ(home, GetTabURL());
163
164  GURL frames(test_server_.GetURL("files/session_history/frames.html"));
165  ASSERT_TRUE(tab_->NavigateToURL(frames));
166  EXPECT_EQ(L"bot1", GetTabTitle());
167  EXPECT_EQ(frames, GetTabURL());
168
169  ClickLink("abot2");
170  EXPECT_EQ(L"bot2", GetTabTitle());
171  EXPECT_EQ(frames, GetTabURL());
172
173  ClickLink("abot3");
174  EXPECT_EQ(L"bot3", GetTabTitle());
175  EXPECT_EQ(frames, GetTabURL());
176
177  // history is [blank, bot1, bot2, *bot3]
178
179  ASSERT_TRUE(tab_->GoBack());
180  EXPECT_EQ(L"bot2", GetTabTitle());
181  EXPECT_EQ(frames, GetTabURL());
182
183  ASSERT_TRUE(tab_->GoBack());
184  EXPECT_EQ(L"bot1", GetTabTitle());
185  EXPECT_EQ(frames, GetTabURL());
186
187  ASSERT_TRUE(tab_->GoBack());
188  EXPECT_EQ(L"", GetTabTitle());
189  EXPECT_EQ(home, GetTabURL());
190
191  ASSERT_TRUE(tab_->GoForward());
192  EXPECT_EQ(L"bot1", GetTabTitle());
193  EXPECT_EQ(frames, GetTabURL());
194
195  ASSERT_TRUE(tab_->GoForward());
196  EXPECT_EQ(L"bot2", GetTabTitle());
197  EXPECT_EQ(frames, GetTabURL());
198
199  ClickLink("abot1");
200  EXPECT_EQ(L"bot1", GetTabTitle());
201  EXPECT_EQ(frames, GetTabURL());
202
203  // history is [blank, bot1, bot2, *bot1]
204
205  ASSERT_FALSE(tab_->GoForward());
206  EXPECT_EQ(L"bot1", GetTabTitle());
207  EXPECT_EQ(frames, GetTabURL());
208
209  ASSERT_TRUE(tab_->GoBack());
210  EXPECT_EQ(L"bot2", GetTabTitle());
211  EXPECT_EQ(frames, GetTabURL());
212
213  ASSERT_TRUE(tab_->GoBack());
214  EXPECT_EQ(L"bot1", GetTabTitle());
215  EXPECT_EQ(frames, GetTabURL());
216}
217
218#if defined(OS_WIN)
219// See http://crbug.com/61619
220#define MAYBE_FrameFormBackForward FLAKY_FrameFormBackForward
221#else
222#define MAYBE_FrameFormBackForward FrameFormBackForward
223#endif
224
225// Test that back/forward preserves POST data and document state in subframes.
226TEST_F(SessionHistoryTest, MAYBE_FrameFormBackForward) {
227  ASSERT_TRUE(test_server_.Start());
228
229  // about:blank should be loaded first.
230  ASSERT_FALSE(tab_->GoBack());
231  EXPECT_EQ(L"", GetTabTitle());
232
233  GURL frames(test_server_.GetURL("files/session_history/frames.html"));
234  ASSERT_TRUE(tab_->NavigateToURL(frames));
235  EXPECT_EQ(L"bot1", GetTabTitle());
236
237  ClickLink("aform");
238  EXPECT_EQ(L"form", GetTabTitle());
239  EXPECT_EQ(frames, GetTabURL());
240
241  SubmitForm("isubmit");
242  EXPECT_EQ(L"text=&select=a", GetTabTitle());
243  EXPECT_EQ(frames, GetTabURL());
244
245  ASSERT_TRUE(tab_->GoBack());
246  EXPECT_EQ(L"form", GetTabTitle());
247  EXPECT_EQ(frames, GetTabURL());
248
249  // history is [blank, bot1, *form, post]
250
251  ClickLink("abot2");
252  EXPECT_EQ(L"bot2", GetTabTitle());
253  EXPECT_EQ(frames, GetTabURL());
254
255  // history is [blank, bot1, form, *bot2]
256
257  ASSERT_TRUE(tab_->GoBack());
258  EXPECT_EQ(L"form", GetTabTitle());
259  EXPECT_EQ(frames, GetTabURL());
260
261  SubmitForm("isubmit");
262  EXPECT_EQ(L"text=&select=a", GetTabTitle());
263  EXPECT_EQ(frames, GetTabURL());
264
265  // history is [blank, bot1, form, *post]
266
267  if (false) {
268    // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed:
269    // "returning to a POST result within a frame does a GET instead of a POST"
270    ClickLink("abot2");
271    EXPECT_EQ(L"bot2", GetTabTitle());
272    EXPECT_EQ(frames, GetTabURL());
273
274    ASSERT_TRUE(tab_->GoBack());
275    EXPECT_EQ(L"text=&select=a", GetTabTitle());
276    EXPECT_EQ(frames, GetTabURL());
277  }
278}
279
280// TODO(mpcomplete): enable this when Bug 734372 is fixed:
281// "Doing a session history navigation does not restore newly-created subframe
282// document state"
283// Test that back/forward preserves POST data and document state when navigating
284// across frames (ie, from frame -> nonframe).
285// Hangs, see http://crbug.com/45058.
286TEST_F(SessionHistoryTest, DISABLED_CrossFrameFormBackForward) {
287  ASSERT_TRUE(test_server_.Start());
288
289  // about:blank should be loaded first.
290  ASSERT_FALSE(tab_->GoBack());
291  EXPECT_EQ(L"", GetTabTitle());
292
293  GURL frames(test_server_.GetURL("files/session_history/frames.html"));
294  ASSERT_TRUE(tab_->NavigateToURL(frames));
295  EXPECT_EQ(L"bot1", GetTabTitle());
296
297  ClickLink("aform");
298  EXPECT_EQ(L"form", GetTabTitle());
299  EXPECT_EQ(frames, GetTabURL());
300
301  SubmitForm("isubmit");
302  EXPECT_EQ(L"text=&select=a", GetTabTitle());
303  EXPECT_EQ(frames, GetTabURL());
304
305  ASSERT_TRUE(tab_->GoBack());
306  EXPECT_EQ(L"form", GetTabTitle());
307  EXPECT_EQ(frames, GetTabURL());
308
309  // history is [blank, bot1, *form, post]
310
311  // ClickLink(L"abot2");
312  GURL bot2("files/session_history/bot2.html");
313  ASSERT_TRUE(tab_->NavigateToURL(bot2));
314  EXPECT_EQ(L"bot2", GetTabTitle());
315  EXPECT_EQ(bot2, GetTabURL());
316
317  // history is [blank, bot1, form, *bot2]
318
319  ASSERT_TRUE(tab_->GoBack());
320  EXPECT_EQ(L"form", GetTabTitle());
321  EXPECT_EQ(frames, GetTabURL());
322
323  SubmitForm("isubmit");
324  EXPECT_EQ(L"text=&select=a", GetTabTitle());
325  EXPECT_EQ(frames, GetTabURL());
326}
327
328
329#if defined(OS_WIN)
330// See http://crbug.com/61619
331#define MAYBE_FragmentBackForward FLAKY_FragmentBackForward
332#else
333#define MAYBE_FragmentBackForward FragmentBackForward
334#endif
335
336// Test that back/forward entries are created for reference fragment
337// navigations. Bug 730379.
338TEST_F(SessionHistoryTest, MAYBE_FragmentBackForward) {
339  ASSERT_TRUE(test_server_.Start());
340
341  // about:blank should be loaded first.
342  ASSERT_FALSE(tab_->GoBack());
343  EXPECT_EQ(L"", GetTabTitle());
344
345  GURL fragment(test_server_.GetURL("files/session_history/fragment.html"));
346  ASSERT_TRUE(tab_->NavigateToURL(fragment));
347  EXPECT_EQ(L"fragment", GetTabTitle());
348  EXPECT_EQ(fragment, GetTabURL());
349
350  GURL::Replacements ref_params;
351
352  ref_params.SetRef("a", url_parse::Component(0, 1));
353  GURL fragment_a(fragment.ReplaceComponents(ref_params));
354  ASSERT_TRUE(tab_->NavigateToURL(fragment_a));
355  EXPECT_EQ(L"fragment", GetTabTitle());
356  EXPECT_EQ(fragment_a, GetTabURL());
357
358  ref_params.SetRef("b", url_parse::Component(0, 1));
359  GURL fragment_b(fragment.ReplaceComponents(ref_params));
360  ASSERT_TRUE(tab_->NavigateToURL(fragment_b));
361  EXPECT_EQ(L"fragment", GetTabTitle());
362  EXPECT_EQ(fragment_b, GetTabURL());
363
364  ref_params.SetRef("c", url_parse::Component(0, 1));
365  GURL fragment_c(fragment.ReplaceComponents(ref_params));
366  ASSERT_TRUE(tab_->NavigateToURL(fragment_c));
367  EXPECT_EQ(L"fragment", GetTabTitle());
368  EXPECT_EQ(fragment_c, GetTabURL());
369
370  // history is [blank, fragment, fragment#a, fragment#b, *fragment#c]
371
372  ASSERT_TRUE(tab_->GoBack());
373  EXPECT_EQ(fragment_b, GetTabURL());
374
375  ASSERT_TRUE(tab_->GoBack());
376  EXPECT_EQ(fragment_a, GetTabURL());
377
378  ASSERT_TRUE(tab_->GoBack());
379  EXPECT_EQ(fragment, GetTabURL());
380
381  ASSERT_TRUE(tab_->GoForward());
382  EXPECT_EQ(fragment_a, GetTabURL());
383
384  GURL bot3(test_server_.GetURL("files/session_history/bot3.html"));
385  ASSERT_TRUE(tab_->NavigateToURL(bot3));
386  EXPECT_EQ(L"bot3", GetTabTitle());
387  EXPECT_EQ(bot3, GetTabURL());
388
389  // history is [blank, fragment, fragment#a, bot3]
390
391  ASSERT_FALSE(tab_->GoForward());
392  EXPECT_EQ(bot3, GetTabURL());
393
394  ASSERT_TRUE(tab_->GoBack());
395  EXPECT_EQ(fragment_a, GetTabURL());
396
397  ASSERT_TRUE(tab_->GoBack());
398  EXPECT_EQ(fragment, GetTabURL());
399}
400
401// Test that the javascript window.history object works.
402// NOTE: history.go(N) does not do anything if N is outside the bounds of the
403// back/forward list (such as trigger our start/stop loading events).  This
404// means the test will hang if it attempts to navigate too far forward or back,
405// since we'll be waiting forever for a load stop event.
406//
407// TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing
408// about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug).
409TEST_F(SessionHistoryTest, FLAKY_JavascriptHistory) {
410  ASSERT_TRUE(test_server_.Start());
411
412  // about:blank should be loaded first.
413  ASSERT_FALSE(tab_->GoBack());
414  EXPECT_EQ(L"", GetTabTitle());
415
416  ASSERT_TRUE(tab_->NavigateToURL(
417      test_server_.GetURL("files/session_history/bot1.html")));
418  EXPECT_EQ(L"bot1", GetTabTitle());
419
420  ASSERT_TRUE(tab_->NavigateToURL(
421      test_server_.GetURL("files/session_history/bot2.html")));
422  EXPECT_EQ(L"bot2", GetTabTitle());
423
424  ASSERT_TRUE(tab_->NavigateToURL(
425      test_server_.GetURL("files/session_history/bot3.html")));
426  EXPECT_EQ(L"bot3", GetTabTitle());
427
428  // history is [blank, bot1, bot2, *bot3]
429
430  JavascriptGo("-1");
431  EXPECT_EQ(L"bot2", GetTabTitle());
432
433  JavascriptGo("-1");
434  EXPECT_EQ(L"bot1", GetTabTitle());
435
436  JavascriptGo("1");
437  EXPECT_EQ(L"bot2", GetTabTitle());
438
439  JavascriptGo("-1");
440  EXPECT_EQ(L"bot1", GetTabTitle());
441
442  JavascriptGo("2");
443  EXPECT_EQ(L"bot3", GetTabTitle());
444
445  // history is [blank, bot1, bot2, *bot3]
446
447  JavascriptGo("-3");
448  EXPECT_EQ(L"", GetTabTitle());
449
450  ASSERT_FALSE(tab_->GoBack());
451  EXPECT_EQ(L"", GetTabTitle());
452
453  JavascriptGo("1");
454  EXPECT_EQ(L"bot1", GetTabTitle());
455
456  ASSERT_TRUE(tab_->NavigateToURL(
457      test_server_.GetURL("files/session_history/bot3.html")));
458  EXPECT_EQ(L"bot3", GetTabTitle());
459
460  // history is [blank, bot1, *bot3]
461
462  ASSERT_FALSE(tab_->GoForward());
463  EXPECT_EQ(L"bot3", GetTabTitle());
464
465  JavascriptGo("-1");
466  EXPECT_EQ(L"bot1", GetTabTitle());
467
468  JavascriptGo("-1");
469  EXPECT_EQ(L"", GetTabTitle());
470
471  ASSERT_FALSE(tab_->GoBack());
472  EXPECT_EQ(L"", GetTabTitle());
473
474  JavascriptGo("1");
475  EXPECT_EQ(L"bot1", GetTabTitle());
476
477  JavascriptGo("1");
478  EXPECT_EQ(L"bot3", GetTabTitle());
479
480  // TODO(creis): Test that JavaScript history navigations work across tab
481  // types.  For example, load about:network in a tab, then a real page, then
482  // try to go back and forward with JavaScript.  Bug 1136715.
483  // (Hard to test right now, because pages like about:network cause the
484  // TabProxy to hang.  This is because they do not appear to use the
485  // NotificationService.)
486}
487
488// This test is failing consistently. See http://crbug.com/22560
489TEST_F(SessionHistoryTest, FAILS_LocationReplace) {
490  ASSERT_TRUE(test_server_.Start());
491
492  // Test that using location.replace doesn't leave the title of the old page
493  // visible.
494  ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
495      "files/session_history/replace.html?no-title.html")));
496  EXPECT_EQ(L"", GetTabTitle());
497}
498
499// This test is flaky. See bug 22111.
500TEST_F(SessionHistoryTest, FLAKY_HistorySearchXSS) {
501  // about:blank should be loaded first.
502  ASSERT_FALSE(tab_->GoBack());
503  EXPECT_EQ(L"", GetTabTitle());
504
505  GURL url(std::string(chrome::kChromeUIHistoryURL) +
506      "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E");
507  ASSERT_TRUE(tab_->NavigateToURL(url));
508  // Mainly, this is to ensure we send a synchronous message to the renderer
509  // so that we're not susceptible (less susceptible?) to a race condition.
510  // Should a race condition ever trigger, it won't result in flakiness.
511  int num = tab_->FindInPage(L"<img", FWD, CASE_SENSITIVE, false, NULL);
512  EXPECT_GT(num, 0);
513  EXPECT_EQ(L"History", GetTabTitle());
514}
515
516#if defined(OS_WIN)
517// See http://crbug.com/61619
518#define MAYBE_LocationChangeInSubframe FLAKY_LocationChangeInSubframe
519#else
520#define MAYBE_LocationChangeInSubframe LocationChangeInSubframe
521#endif
522
523TEST_F(SessionHistoryTest, MAYBE_LocationChangeInSubframe) {
524  ASSERT_TRUE(test_server_.Start());
525
526  ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
527      "files/session_history/location_redirect.html")));
528  EXPECT_EQ(L"Default Title", GetTabTitle());
529
530  ASSERT_TRUE(tab_->NavigateToURL(GURL(
531      "javascript:void(frames[0].navigate())")));
532  EXPECT_EQ(L"foo", GetTabTitle());
533
534  ASSERT_TRUE(tab_->GoBack());
535  EXPECT_EQ(L"Default Title", GetTabTitle());
536}
537
538// http://code.google.com/p/chromium/issues/detail?id=56267
539TEST_F(SessionHistoryTest, DISABLED_HistoryLength) {
540  ASSERT_TRUE(test_server_.Start());
541
542  int length;
543  ASSERT_TRUE(tab_->ExecuteAndExtractInt(
544      L"", L"domAutomationController.send(history.length)", &length));
545  EXPECT_EQ(1, length);
546
547  ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title1.html")));
548
549  ASSERT_TRUE(tab_->ExecuteAndExtractInt(
550      L"", L"domAutomationController.send(history.length)", &length));
551  EXPECT_EQ(2, length);
552
553  // Now test that history.length is updated when the navigation is committed.
554  ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
555      "files/session_history/record_length.html")));
556  ASSERT_TRUE(tab_->ExecuteAndExtractInt(
557      L"", L"domAutomationController.send(history.length)", &length));
558  EXPECT_EQ(3, length);
559  ASSERT_TRUE(tab_->ExecuteAndExtractInt(
560      L"", L"domAutomationController.send(history_length)", &length));
561  EXPECT_EQ(3, length);
562
563  ASSERT_TRUE(tab_->GoBack());
564  ASSERT_TRUE(tab_->GoBack());
565
566  // Ensure history.length is properly truncated.
567  ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title2.html")));
568  ASSERT_TRUE(tab_->ExecuteAndExtractInt(
569      L"", L"domAutomationController.send(history.length)", &length));
570  EXPECT_EQ(2, length);
571}
572
573}  // namespace
574