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 bool RunOnDBThread(history::HistoryBackend* backend,
47 history::HistoryDatabase* db) override {
51 void DoneRunOnMainThread() override { base::MessageLoop::current()->Quit(); }
54 ~WaitForHistoryTask() override {}
56 DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
61 class HistoryBrowserTest : public InProcessBrowserTest {
63 void SetUpCommandLine(CommandLine* command_line) override {
64 command_line->AppendSwitch(switches::kEnableFileCookies);
67 PrefService* GetPrefs() {
68 return GetProfile()->GetPrefs();
71 Profile* GetProfile() {
72 return browser()->profile();
75 std::vector<GURL> GetHistoryContents() {
76 ui_test_utils::HistoryEnumerator enumerator(GetProfile());
77 return enumerator.urls();
81 return ui_test_utils::GetTestUrl(
82 base::FilePath(base::FilePath::kCurrentDirectory),
83 base::FilePath(FILE_PATH_LITERAL("title2.html")));
86 void WaitForHistoryBackendToRun() {
87 base::CancelableTaskTracker task_tracker;
88 scoped_ptr<history::HistoryDBTask> task(new WaitForHistoryTask());
89 HistoryService* history =
90 HistoryServiceFactory::GetForProfile(GetProfile(),
91 Profile::EXPLICIT_ACCESS);
92 history->HistoryService::ScheduleDBTask(task.Pass(), &task_tracker);
93 content::RunMessageLoop();
96 void ExpectEmptyHistory() {
97 std::vector<GURL> urls(GetHistoryContents());
98 EXPECT_EQ(0U, urls.size());
101 void LoadAndWaitForURL(const GURL& url) {
102 base::string16 expected_title(base::ASCIIToUTF16("OK"));
103 content::TitleWatcher title_watcher(
104 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
105 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
106 ui_test_utils::NavigateToURL(browser(), url);
107 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
110 void LoadAndWaitForFile(const char* filename) {
111 GURL url = ui_test_utils::GetTestUrl(
112 base::FilePath().AppendASCII("History"),
113 base::FilePath().AppendASCII(filename));
114 LoadAndWaitForURL(url);
118 // Test that the browser history is saved (default setting).
119 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
120 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));
122 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
123 GetProfile(), Profile::EXPLICIT_ACCESS));
124 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
125 GetProfile(), Profile::IMPLICIT_ACCESS));
127 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
128 browser()->profile(), Profile::EXPLICIT_ACCESS));
129 ExpectEmptyHistory();
131 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
132 WaitForHistoryBackendToRun();
135 std::vector<GURL> urls(GetHistoryContents());
136 ASSERT_EQ(1U, urls.size());
137 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
141 // Test that disabling saving browser history really works.
142 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) {
143 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
145 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(
146 GetProfile(), Profile::EXPLICIT_ACCESS));
147 EXPECT_FALSE(HistoryServiceFactory::GetForProfile(
148 GetProfile(), Profile::IMPLICIT_ACCESS));
150 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
151 browser()->profile(), Profile::EXPLICIT_ACCESS));
152 ExpectEmptyHistory();
154 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
155 WaitForHistoryBackendToRun();
156 ExpectEmptyHistory();
159 // Test that changing the pref takes effect immediately
160 // when the browser is running.
161 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) {
162 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));
164 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
165 browser()->profile(), Profile::EXPLICIT_ACCESS));
167 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
168 WaitForHistoryBackendToRun();
171 std::vector<GURL> urls(GetHistoryContents());
172 ASSERT_EQ(1U, urls.size());
173 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
176 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
178 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
179 WaitForHistoryBackendToRun();
182 // No additional entries should be present in the history.
183 std::vector<GURL> urls(GetHistoryContents());
184 ASSERT_EQ(1U, urls.size());
185 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
189 // Test that changing the pref takes effect immediately
190 // when the browser is running.
191 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
192 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
194 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
195 browser()->profile(), Profile::EXPLICIT_ACCESS));
196 ExpectEmptyHistory();
198 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
199 WaitForHistoryBackendToRun();
200 ExpectEmptyHistory();
202 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);
204 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
205 WaitForHistoryBackendToRun();
208 std::vector<GURL> urls(GetHistoryContents());
209 ASSERT_EQ(1U, urls.size());
210 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
214 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength1) {
215 // Test the history length for the following page transitions.
217 LoadAndWaitForFile("history_length_test_page_1.html");
220 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength2) {
221 // Test the history length for the following page transitions.
222 // -open-> Page 2 -redirect-> Page 3.
223 LoadAndWaitForFile("history_length_test_page_2.html");
226 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, VerifyHistoryLength3) {
227 // Test the history length for the following page transitions.
228 // -open-> Page 1 -> open Page 2 -redirect Page 3. open Page 4
229 // -navigate_backward-> Page 3 -navigate_backward->Page 1
230 // -navigate_forward-> Page 3 -navigate_forward-> Page 4
231 LoadAndWaitForFile("history_length_test_page_1.html");
232 LoadAndWaitForFile("history_length_test_page_2.html");
233 LoadAndWaitForFile("history_length_test_page_4.html");
236 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
237 ConsiderRedirectAfterGestureAsUserInitiated) {
238 // Test the history length for the following page transition.
240 // -open-> Page 11 -slow_redirect-> Page 12.
242 // If redirect occurs after a user gesture, e.g., mouse click, the
243 // redirect is more likely to be user-initiated rather than automatic.
244 // Therefore, Page 11 should be in the history in addition to Page 12.
245 LoadAndWaitForFile("history_length_test_page_11.html");
247 content::SimulateMouseClick(
248 browser()->tab_strip_model()->GetActiveWebContents(), 0,
249 blink::WebMouseEvent::ButtonLeft);
250 LoadAndWaitForFile("history_length_test_page_11.html");
253 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
254 ConsiderSlowRedirectAsUserInitiated) {
255 // Test the history length for the following page transition.
257 // -open-> Page 21 -redirect-> Page 22.
259 // If redirect occurs more than 5 seconds later after the page is loaded,
260 // the redirect is likely to be user-initiated.
261 // Therefore, Page 21 should be in the history in addition to Page 22.
262 LoadAndWaitForFile("history_length_test_page_21.html");
265 // http://crbug.com/22111
266 #if defined(OS_LINUX)
267 #define MAYBE_HistorySearchXSS DISABLED_HistorySearchXSS
269 #define MAYBE_HistorySearchXSS HistorySearchXSS
271 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MAYBE_HistorySearchXSS) {
272 GURL url(std::string(chrome::kChromeUIHistoryURL) +
273 "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E");
274 ui_test_utils::NavigateToURL(browser(), url);
275 // Mainly, this is to ensure we send a synchronous message to the renderer
276 // so that we're not susceptible (less susceptible?) to a race condition.
277 // Should a race condition ever trigger, it won't result in flakiness.
278 int num = ui_test_utils::FindInPage(
279 browser()->tab_strip_model()->GetActiveWebContents(),
280 base::ASCIIToUTF16("<img"), true,
283 EXPECT_EQ(base::ASCIIToUTF16("History"),
284 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
287 // Verify that history persists after session restart.
288 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, PRE_HistoryPersists) {
289 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
290 std::vector<GURL> urls(GetHistoryContents());
291 ASSERT_EQ(1u, urls.size());
292 ASSERT_EQ(GetTestUrl(), urls[0]);
295 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, HistoryPersists) {
296 std::vector<GURL> urls(GetHistoryContents());
297 ASSERT_EQ(1u, urls.size());
298 ASSERT_EQ(GetTestUrl(), urls[0]);
301 // Invalid URLs should not go in history.
302 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, InvalidURLNoHistory) {
303 GURL non_existant = ui_test_utils::GetTestUrl(
304 base::FilePath().AppendASCII("History"),
305 base::FilePath().AppendASCII("non_existant_file.html"));
306 ui_test_utils::NavigateToURL(browser(), non_existant);
307 ExpectEmptyHistory();
310 // New tab page should not show up in history.
311 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NewTabNoHistory) {
312 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
313 ExpectEmptyHistory();
316 // Incognito browsing should not show up in history.
317 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, IncognitoNoHistory) {
318 ui_test_utils::NavigateToURL(CreateIncognitoBrowser(), GetTestUrl());
319 ExpectEmptyHistory();
322 // Multiple navigations to the same url should have a single history.
323 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NavigateMultiTimes) {
324 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
325 ui_test_utils::NavigateToURL(browser(), GetTestUrl());
326 std::vector<GURL> urls(GetHistoryContents());
327 ASSERT_EQ(1u, urls.size());
328 ASSERT_EQ(GetTestUrl(), urls[0]);
331 // Verify history with multiple windows and tabs.
332 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MultiTabsWindowsHistory) {
333 GURL url1 = GetTestUrl();
334 GURL url2 = ui_test_utils::GetTestUrl(
335 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title1.html")));
336 GURL url3 = ui_test_utils::GetTestUrl(
337 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
338 GURL url4 = ui_test_utils::GetTestUrl(
339 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("simple.html")));
341 ui_test_utils::NavigateToURL(browser(), url1);
342 Browser* browser2 = CreateBrowser(browser()->profile());
343 ui_test_utils::NavigateToURL(browser2, url2);
344 ui_test_utils::NavigateToURLWithDisposition(
345 browser2, url3, NEW_FOREGROUND_TAB,
346 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
347 ui_test_utils::NavigateToURLWithDisposition(
348 browser2, url4, NEW_FOREGROUND_TAB,
349 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
351 std::vector<GURL> urls(GetHistoryContents());
352 ASSERT_EQ(4u, urls.size());
353 ASSERT_EQ(url4, urls[0]);
354 ASSERT_EQ(url3, urls[1]);
355 ASSERT_EQ(url2, urls[2]);
356 ASSERT_EQ(url1, urls[3]);
359 // Downloaded URLs should not show up in history.
360 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, DownloadNoHistory) {
361 GURL download_url = ui_test_utils::GetTestUrl(
362 base::FilePath().AppendASCII("downloads"),
363 base::FilePath().AppendASCII("a_zip_file.zip"));
364 ui_test_utils::DownloadURL(browser(), download_url);
365 ExpectEmptyHistory();
368 // HTTP meta-refresh redirects should have separate history entries.
369 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, RedirectHistory) {
370 GURL redirector = ui_test_utils::GetTestUrl(
371 base::FilePath().AppendASCII("History"),
372 base::FilePath().AppendASCII("redirector.html"));
373 GURL landing_url = ui_test_utils::GetTestUrl(
374 base::FilePath().AppendASCII("History"),
375 base::FilePath().AppendASCII("landing.html"));
376 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
377 browser(), redirector, 2);
378 ASSERT_EQ(landing_url,
379 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
380 std::vector<GURL> urls(GetHistoryContents());
381 ASSERT_EQ(2u, urls.size());
382 ASSERT_EQ(landing_url, urls[0]);
383 ASSERT_EQ(redirector, urls[1]);
386 // Verify that navigation brings current page to top of history list.
387 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, NavigateBringPageToTop) {
388 GURL url1 = GetTestUrl();
389 GURL url2 = ui_test_utils::GetTestUrl(
390 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
392 ui_test_utils::NavigateToURL(browser(), url1);
393 ui_test_utils::NavigateToURL(browser(), url2);
395 std::vector<GURL> urls(GetHistoryContents());
396 ASSERT_EQ(2u, urls.size());
397 ASSERT_EQ(url2, urls[0]);
398 ASSERT_EQ(url1, urls[1]);
401 // Verify that reloading a page brings it to top of history list.
402 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, ReloadBringPageToTop) {
403 GURL url1 = GetTestUrl();
404 GURL url2 = ui_test_utils::GetTestUrl(
405 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
407 ui_test_utils::NavigateToURL(browser(), url1);
408 ui_test_utils::NavigateToURLWithDisposition(
409 browser(), url2, NEW_BACKGROUND_TAB,
410 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
412 std::vector<GURL> urls(GetHistoryContents());
413 ASSERT_EQ(2u, urls.size());
414 ASSERT_EQ(url2, urls[0]);
415 ASSERT_EQ(url1, urls[1]);
417 content::WebContents* tab =
418 browser()->tab_strip_model()->GetActiveWebContents();
419 tab->GetController().Reload(false);
420 content::WaitForLoadStop(tab);
422 urls = GetHistoryContents();
423 ASSERT_EQ(2u, urls.size());
424 ASSERT_EQ(url1, urls[0]);
425 ASSERT_EQ(url2, urls[1]);
428 // Verify that back/forward brings current page to top of history list.
429 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, BackForwardBringPageToTop) {
430 GURL url1 = GetTestUrl();
431 GURL url2 = ui_test_utils::GetTestUrl(
432 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("title3.html")));
434 ui_test_utils::NavigateToURL(browser(), url1);
435 ui_test_utils::NavigateToURL(browser(), url2);
437 content::WebContents* tab =
438 browser()->tab_strip_model()->GetActiveWebContents();
439 chrome::GoBack(browser(), CURRENT_TAB);
440 content::WaitForLoadStop(tab);
442 std::vector<GURL> urls(GetHistoryContents());
443 ASSERT_EQ(2u, urls.size());
444 ASSERT_EQ(url1, urls[0]);
445 ASSERT_EQ(url2, urls[1]);
447 chrome::GoForward(browser(), CURRENT_TAB);
448 content::WaitForLoadStop(tab);
449 urls = GetHistoryContents();
450 ASSERT_EQ(2u, urls.size());
451 ASSERT_EQ(url2, urls[0]);
452 ASSERT_EQ(url1, urls[1]);
455 // Verify that submitting form adds target page to history list.
456 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SubmitFormAddsTargetPage) {
457 GURL form = ui_test_utils::GetTestUrl(
458 base::FilePath().AppendASCII("History"),
459 base::FilePath().AppendASCII("form.html"));
460 GURL target = ui_test_utils::GetTestUrl(
461 base::FilePath().AppendASCII("History"),
462 base::FilePath().AppendASCII("target.html"));
463 ui_test_utils::NavigateToURL(browser(), form);
465 content::WebContents* web_contents =
466 browser()->tab_strip_model()->GetActiveWebContents();
467 base::string16 expected_title(base::ASCIIToUTF16("Target Page"));
468 content::TitleWatcher title_watcher(
469 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
470 ASSERT_TRUE(content::ExecuteScript(
471 web_contents, "document.getElementById('form').submit()"));
472 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
474 std::vector<GURL> urls(GetHistoryContents());
475 ASSERT_EQ(2u, urls.size());
476 ASSERT_EQ(target, urls[0]);
477 ASSERT_EQ(form, urls[1]);
480 // Verify history shortcut opens only one history tab per window. Also, make
481 // sure that existing history tab is activated.
482 IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, OneHistoryTabPerWindow) {
483 GURL history_url(chrome::kChromeUIHistoryURL);
485 // Even after navigate completes, the currently-active tab title is
486 // 'Loading...' for a brief time while the history page loads.
487 content::WebContents* web_contents =
488 browser()->tab_strip_model()->GetActiveWebContents();
489 base::string16 expected_title(base::ASCIIToUTF16("History"));
490 content::TitleWatcher title_watcher(web_contents, expected_title);
491 chrome::ExecuteCommand(browser(), IDC_SHOW_HISTORY);
492 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
494 ui_test_utils::NavigateToURLWithDisposition(
496 GURL(url::kAboutBlankURL),
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());