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.
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/history/history_db_task.h"
14 #include "chrome/browser/history/history_service.h"
15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chrome/test/base/ui_test_utils.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/test/browser_test_utils.h"
27 #include "content/public/test/test_browser_thread.h"
30 using content::BrowserThread;
34 // Note: WaitableEvent is not used for synchronization between the main thread
35 // and history backend thread because the history subsystem posts tasks back
36 // to the main thread. Had we tried to Signal an event in such a task
37 // and Wait for it on the main thread, the task would not run at all because
38 // the main thread would be blocked on the Wait call, resulting in a deadlock.
40 // A task to be scheduled on the history backend thread.
41 // Notifies the main thread after all history backend thread tasks have run.
42 class WaitForHistoryTask : public history::HistoryDBTask {
44 WaitForHistoryTask() {}
46 virtual bool RunOnDBThread(history::HistoryBackend* backend,
47 history::HistoryDatabase* db) OVERRIDE {
51 virtual void DoneRunOnMainThread() OVERRIDE {
52 base::MessageLoop::current()->Quit();
56 virtual ~WaitForHistoryTask() {}
58 DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
63 class HistoryBrowserTest : public InProcessBrowserTest {
65 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
66 command_line->AppendSwitch(switches::kEnableFileCookies);
69 PrefService* GetPrefs() {
70 return GetProfile()->GetPrefs();
73 Profile* GetProfile() {
74 return browser()->profile();
77 std::vector<GURL> GetHistoryContents() {
78 ui_test_utils::HistoryEnumerator enumerator(GetProfile());
79 return enumerator.urls();
83 return ui_test_utils::GetTestUrl(
84 base::FilePath(base::FilePath::kCurrentDirectory),
85 base::FilePath(FILE_PATH_LITERAL("title2.html")));
88 void WaitForHistoryBackendToRun() {
89 CancelableRequestConsumerTSimple<int> request_consumer;
90 scoped_refptr<history::HistoryDBTask> task(new WaitForHistoryTask());
91 HistoryService* history =
92 HistoryServiceFactory::GetForProfile(GetProfile(),
93 Profile::EXPLICIT_ACCESS);
94 history->HistoryService::ScheduleDBTask(task.get(), &request_consumer);
95 content::RunMessageLoop();
98 void ExpectEmptyHistory() {
99 std::vector<GURL> urls(GetHistoryContents());
100 EXPECT_EQ(0U, urls.size());
103 void LoadAndWaitForURL(const GURL& url) {
104 string16 expected_title(ASCIIToUTF16("OK"));
105 content::TitleWatcher title_watcher(
106 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
107 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
108 ui_test_utils::NavigateToURL(browser(), url);
109 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
112 void LoadAndWaitForFile(const char* filename) {
113 GURL url = ui_test_utils::GetTestUrl(
114 base::FilePath().AppendASCII("History"),
115 base::FilePath().AppendASCII(filename));
116 LoadAndWaitForURL(url);
120 // Test that the browser history is saved (default setting).
121 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
122 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));
124 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
125 GetProfile(), Profile::EXPLICIT_ACCESS));
126 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
127 GetProfile(), Profile::IMPLICIT_ACCESS));
129 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
130 browser()->profile(), Profile::EXPLICIT_ACCESS));
131 ExpectEmptyHistory();
133 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
134 WaitForHistoryBackendToRun();
137 std::vector<GURL> urls(GetHistoryContents());
138 ASSERT_EQ(1U, urls.size());
139 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
143 // Test that disabling saving browser history really works.
144 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) {
145 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
147 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
148 GetProfile(), Profile::EXPLICIT_ACCESS));
149 EXPECT_FALSE(HistoryServiceFactory::GetForProfile(
150 GetProfile(), Profile::IMPLICIT_ACCESS));
152 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
153 browser()->profile(), Profile::EXPLICIT_ACCESS));
154 ExpectEmptyHistory();
156 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
157 WaitForHistoryBackendToRun();
158 ExpectEmptyHistory();
161 // Test that changing the pref takes effect immediately
162 // when the browser is running.
163 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) {
164 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));
166 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
167 browser()->profile(), Profile::EXPLICIT_ACCESS));
169 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
170 WaitForHistoryBackendToRun();
173 std::vector<GURL> urls(GetHistoryContents());
174 ASSERT_EQ(1U, urls.size());
175 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
178 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
180 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
181 WaitForHistoryBackendToRun();
184 // No additional entries should be present in the history.
185 std::vector<GURL> urls(GetHistoryContents());
186 ASSERT_EQ(1U, urls.size());
187 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
191 // Test that changing the pref takes effect immediately
192 // when the browser is running.
193 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
194 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
196 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
197 browser()->profile(), Profile::EXPLICIT_ACCESS));
198 ExpectEmptyHistory();
200 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
201 WaitForHistoryBackendToRun();
202 ExpectEmptyHistory();
204 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);
206 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
207 WaitForHistoryBackendToRun();
210 std::vector<GURL> urls(GetHistoryContents());
211 ASSERT_EQ(1U, urls.size());
212 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
216 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength1) {
217 // Test the history length for the following page transitions.
219 LoadAndWaitForFile("history_length_test_page_1.html");
222 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength2) {
223 // Test the history length for the following page transitions.
224 // -open-> Page 2 -redirect-> Page 3.
225 LoadAndWaitForFile("history_length_test_page_2.html");
228 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength3) {
229 // Test the history length for the following page transitions.
230 // -open-> Page 1 -> open Page 2 -redirect Page 3. open Page 4
231 // -navigate_backward-> Page 3 -navigate_backward->Page 1
232 // -navigate_forward-> Page 3 -navigate_forward-> Page 4
233 LoadAndWaitForFile("history_length_test_page_1.html");
234 LoadAndWaitForFile("history_length_test_page_2.html");
235 LoadAndWaitForFile("history_length_test_page_4.html");
238 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
239 ConsiderRedirectAfterGestureAsUserInitiated) {
240 // Test the history length for the following page transition.
242 // -open-> Page 11 -slow_redirect-> Page 12.
244 // If redirect occurs after a user gesture, e.g., mouse click, the
245 // redirect is more likely to be user-initiated rather than automatic.
246 // Therefore, Page 11 should be in the history in addition to Page 12.
247 LoadAndWaitForFile("history_length_test_page_11.html");
249 content::SimulateMouseClick(
250 browser()->tab_strip_model()->GetActiveWebContents(), 0,
251 WebKit::WebMouseEvent::ButtonLeft);
252 LoadAndWaitForFile("history_length_test_page_11.html");
255 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
256 ConsiderSlowRedirectAsUserInitiated) {
257 // Test the history length for the following page transition.
259 // -open-> Page 21 -redirect-> Page 22.
261 // If redirect occurs more than 5 seconds later after the page is loaded,
262 // the redirect is likely to be user-initiated.
263 // Therefore, Page 21 should be in the history in addition to Page 22.
264 LoadAndWaitForFile("history_length_test_page_21.html");
267 // http://crbug.com/22111
268 #if defined(OS_LINUX)
269 #define MAYBE_HistorySearchXSS DISABLED_HistorySearchXSS
271 #define MAYBE_HistorySearchXSS HistorySearchXSS
273 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MAYBE_HistorySearchXSS) {
274 GURL url(std::string(chrome::kChromeUIHistoryURL) +
275 "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E");
276 ui_test_utils::NavigateToURL(browser(), url);
277 // Mainly, this is to ensure we send a synchronous message to the renderer
278 // so that we're not susceptible (less susceptible?) to a race condition.
279 // Should a race condition ever trigger, it won't result in flakiness.
280 int num = ui_test_utils::FindInPage(
281 browser()->tab_strip_model()->GetActiveWebContents(),
282 ASCIIToUTF16("<img"), true,
285 EXPECT_EQ(ASCIIToUTF16("History"),
286 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
289 // Verify that history persists after session restart.
290 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, PRE_HistoryPersists) {
291 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
292 std::vector<GURL> urls(GetHistoryContents());
293 ASSERT_EQ(1u, urls.size());
294 ASSERT_EQ(GetTestUrl(), urls[0]);
297 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, HistoryPersists) {
298 std::vector<GURL> urls(GetHistoryContents());
299 ASSERT_EQ(1u, urls.size());
300 ASSERT_EQ(GetTestUrl(), urls[0]);
303 // Invalid URLs should not go in history.
304 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, InvalidURLNoHistory) {
305 GURL non_existant = ui_test_utils::GetTestUrl(
306 base::FilePath().AppendASCII("History"),
307 base::FilePath().AppendASCII("non_existant_file.html"));
308 ui_test_utils::NavigateToURL(browser(), non_existant);
309 ExpectEmptyHistory();
312 // New tab page should not show up in history.
313 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NewTabNoHistory) {
314 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
315 ExpectEmptyHistory();
318 // Incognito browsing should not show up in history.
319 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, IncognitoNoHistory) {
320 ui_test_utils::NavigateToURL(CreateIncognitoBrowser(), GetTestUrl());
321 ExpectEmptyHistory();
324 // Multiple navigations to the same url should have a single history.
325 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NavigateMultiTimes) {
326 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
327 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
328 std::vector<GURL> urls(GetHistoryContents());
329 ASSERT_EQ(1u, urls.size());
330 ASSERT_EQ(GetTestUrl(), urls[0]);
333 // Verify history with multiple windows and tabs.
334 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MultiTabsWindowsHistory) {
335 GURL url1 = GetTestUrl();
336 GURL url2 = ui_test_utils::GetTestUrl(
337 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title1.html")));
338 GURL url3 = ui_test_utils::GetTestUrl(
339 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
340 GURL url4 = ui_test_utils::GetTestUrl(
341 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("simple.html")));
343 ui_test_utils::NavigateToURL(browser(), url1);
344 Browser* browser2 = CreateBrowser(browser()->profile());
345 ui_test_utils::NavigateToURL(browser2, url2);
346 ui_test_utils::NavigateToURLWithDisposition(
347 browser2, url3, NEW_FOREGROUND_TAB,
348 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
349 ui_test_utils::NavigateToURLWithDisposition(
350 browser2, url4, NEW_FOREGROUND_TAB,
351 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
353 std::vector<GURL> urls(GetHistoryContents());
354 ASSERT_EQ(4u, urls.size());
355 ASSERT_EQ(url4, urls[0]);
356 ASSERT_EQ(url3, urls[1]);
357 ASSERT_EQ(url2, urls[2]);
358 ASSERT_EQ(url1, urls[3]);
361 // Downloaded URLs should not show up in history.
362 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, DownloadNoHistory) {
363 GURL download_url = ui_test_utils::GetTestUrl(
364 base::FilePath().AppendASCII("downloads"),
365 base::FilePath().AppendASCII("a_zip_file.zip"));
366 ui_test_utils::DownloadURL(browser(), download_url);
367 ExpectEmptyHistory();
370 // HTTP meta-refresh redirects should have separate history entries.
371 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, RedirectHistory) {
372 GURL redirector = ui_test_utils::GetTestUrl(
373 base::FilePath().AppendASCII("History"),
374 base::FilePath().AppendASCII("redirector.html"));
375 GURL landing_url = ui_test_utils::GetTestUrl(
376 base::FilePath().AppendASCII("History"),
377 base::FilePath().AppendASCII("landing.html"));
378 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
379 browser(), redirector, 2);
380 ASSERT_EQ(landing_url,
381 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
382 std::vector<GURL> urls(GetHistoryContents());
383 ASSERT_EQ(2u, urls.size());
384 ASSERT_EQ(landing_url, urls[0]);
385 ASSERT_EQ(redirector, urls[1]);
388 // Verify that navigation brings current page to top of history list.
389 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NavigateBringPageToTop) {
390 GURL url1 = GetTestUrl();
391 GURL url2 = ui_test_utils::GetTestUrl(
392 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
394 ui_test_utils::NavigateToURL(browser(), url1);
395 ui_test_utils::NavigateToURL(browser(), url2);
397 std::vector<GURL> urls(GetHistoryContents());
398 ASSERT_EQ(2u, urls.size());
399 ASSERT_EQ(url2, urls[0]);
400 ASSERT_EQ(url1, urls[1]);
403 // Verify that reloading a page brings it to top of history list.
404 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, ReloadBringPageToTop) {
405 GURL url1 = GetTestUrl();
406 GURL url2 = ui_test_utils::GetTestUrl(
407 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
409 ui_test_utils::NavigateToURL(browser(), url1);
410 ui_test_utils::NavigateToURLWithDisposition(
411 browser(), url2, NEW_BACKGROUND_TAB,
412 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
414 std::vector<GURL> urls(GetHistoryContents());
415 ASSERT_EQ(2u, urls.size());
416 ASSERT_EQ(url2, urls[0]);
417 ASSERT_EQ(url1, urls[1]);
419 content::WebContents* tab =
420 browser()->tab_strip_model()->GetActiveWebContents();
421 tab->GetController().Reload(false);
422 content::WaitForLoadStop(tab);
424 urls = GetHistoryContents();
425 ASSERT_EQ(2u, urls.size());
426 ASSERT_EQ(url1, urls[0]);
427 ASSERT_EQ(url2, urls[1]);
430 // Verify that back/forward brings current page to top of history list.
431 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, BackForwardBringPageToTop) {
432 GURL url1 = GetTestUrl();
433 GURL url2 = ui_test_utils::GetTestUrl(
434 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
436 ui_test_utils::NavigateToURL(browser(), url1);
437 ui_test_utils::NavigateToURL(browser(), url2);
439 content::WebContents* tab =
440 browser()->tab_strip_model()->GetActiveWebContents();
441 chrome::GoBack(browser(), CURRENT_TAB);
442 content::WaitForLoadStop(tab);
444 std::vector<GURL> urls(GetHistoryContents());
445 ASSERT_EQ(2u, urls.size());
446 ASSERT_EQ(url1, urls[0]);
447 ASSERT_EQ(url2, urls[1]);
449 chrome::GoForward(browser(), CURRENT_TAB);
450 content::WaitForLoadStop(tab);
451 urls = GetHistoryContents();
452 ASSERT_EQ(2u, urls.size());
453 ASSERT_EQ(url2, urls[0]);
454 ASSERT_EQ(url1, urls[1]);
457 // Verify that submitting form adds target page to history list.
458 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SubmitFormAddsTargetPage) {
459 GURL form = ui_test_utils::GetTestUrl(
460 base::FilePath().AppendASCII("History"),
461 base::FilePath().AppendASCII("form.html"));
462 GURL target = ui_test_utils::GetTestUrl(
463 base::FilePath().AppendASCII("History"),
464 base::FilePath().AppendASCII("target.html"));
465 ui_test_utils::NavigateToURL(browser(), form);
467 content::WebContents* web_contents =
468 browser()->tab_strip_model()->GetActiveWebContents();
469 string16 expected_title(ASCIIToUTF16("Target Page"));
470 content::TitleWatcher title_watcher(
471 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
472 ASSERT_TRUE(content::ExecuteScript(
473 web_contents, "document.getElementById('form').submit()"));
474 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
476 std::vector<GURL> urls(GetHistoryContents());
477 ASSERT_EQ(2u, urls.size());
478 ASSERT_EQ(target, urls[0]);
479 ASSERT_EQ(form, urls[1]);
482 // Verify history shortcut opens only one history tab per window. Also, make
483 // sure that existing history tab is activated.
484 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, OneHistoryTabPerWindow) {
485 GURL history_url(chrome::kChromeUIHistoryURL);
487 // Even after navigate completes, the currently-active tab title is
488 // 'Loading...' for a brief time while the history page loads.
489 content::WebContents* web_contents =
490 browser()->tab_strip_model()->GetActiveWebContents();
491 string16 expected_title(ASCIIToUTF16("History"));
492 content::TitleWatcher title_watcher(web_contents, expected_title);
493 chrome::ExecuteCommand(browser(), IDC_SHOW_HISTORY);
494 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
496 ui_test_utils::NavigateToURLWithDisposition(
497 browser(), GURL(content::kAboutBlankURL), NEW_FOREGROUND_TAB,
498 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
499 chrome::ExecuteCommand(browser(), IDC_SHOW_HISTORY);
501 content::WebContents* active_web_contents =
502 browser()->tab_strip_model()->GetActiveWebContents();
503 ASSERT_EQ(web_contents, active_web_contents);
504 ASSERT_EQ(history_url, active_web_contents->GetURL());
506 content::WebContents* second_tab =
507 browser()->tab_strip_model()->GetWebContentsAt(1);
508 ASSERT_NE(history_url, second_tab->GetURL());