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 <vector> 6 7#include "base/message_loop.h" 8#include "chrome/browser/history/history.h" 9#include "chrome/browser/prefs/pref_service.h" 10#include "chrome/browser/profiles/profile.h" 11#include "chrome/browser/ui/browser.h" 12#include "chrome/common/pref_names.h" 13#include "chrome/test/in_process_browser_test.h" 14#include "chrome/test/ui_test_utils.h" 15#include "content/browser/browser_thread.h" 16#include "googleurl/src/gurl.h" 17 18namespace { 19 20// Helper to debug intermittent test hangs/timeouts. 21// TODO(phajdan.jr): remove when http://crbug.com/57994 is fixed. 22void Checkpoint(const char* message, const base::TimeTicks& start_time) { 23 LOG(INFO) << message << " : " 24 << (base::TimeTicks::Now() - start_time).InMilliseconds() 25 << " ms" << std::flush; 26} 27 28// Note: WaitableEvent is not used for synchronization between the main thread 29// and history backend thread because the history subsystem posts tasks back 30// to the main thread. Had we tried to Signal an event in such a task 31// and Wait for it on the main thread, the task would not run at all because 32// the main thread would be blocked on the Wait call, resulting in a deadlock. 33 34// A task to be scheduled on the history backend thread. 35// Notifies the main thread after all history backend thread tasks have run. 36class WaitForHistoryTask : public HistoryDBTask { 37 public: 38 WaitForHistoryTask() { 39 } 40 41 virtual bool RunOnDBThread(history::HistoryBackend* backend, 42 history::HistoryDatabase* db) { 43 return true; 44 } 45 46 virtual void DoneRunOnMainThread() { 47 MessageLoop::current()->Quit(); 48 } 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask); 52}; 53 54// Enumerates all history contents on the backend thread. 55class HistoryEnumerator : public HistoryService::URLEnumerator { 56 public: 57 explicit HistoryEnumerator(HistoryService* history) { 58 EXPECT_TRUE(history); 59 if (!history) 60 return; 61 62 BrowserThread::PostTask( 63 BrowserThread::UI, 64 FROM_HERE, 65 NewRunnableMethod(history, &HistoryService::IterateURLs, this)); 66 ui_test_utils::RunMessageLoop(); 67 } 68 69 virtual void OnURL(const GURL& url) { 70 urls_.push_back(url); 71 } 72 73 virtual void OnComplete(bool success) { 74 BrowserThread::PostTask( 75 BrowserThread::UI, 76 FROM_HERE, 77 new MessageLoop::QuitTask()); 78 } 79 80 std::vector<GURL>& urls() { return urls_; } 81 82 private: 83 std::vector<GURL> urls_; 84 85 DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator); 86}; 87 88class HistoryBrowserTest : public InProcessBrowserTest { 89 protected: 90 PrefService* GetPrefs() { 91 return GetProfile()->GetPrefs(); 92 } 93 94 Profile* GetProfile() { 95 return browser()->GetProfile(); 96 } 97 98 HistoryService* GetHistoryService() { 99 return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS); 100 } 101 102 std::vector<GURL> GetHistoryContents() { 103 HistoryEnumerator enumerator(GetHistoryService()); 104 return enumerator.urls(); 105 } 106 107 GURL GetTestUrl() { 108 return ui_test_utils::GetTestUrl( 109 FilePath(FilePath::kCurrentDirectory), 110 FilePath(FILE_PATH_LITERAL("title2.html"))); 111 } 112 113 void WaitForHistoryBackendToRun() { 114 CancelableRequestConsumerTSimple<int> request_consumer; 115 scoped_refptr<HistoryDBTask> task(new WaitForHistoryTask()); 116 HistoryService* history = GetHistoryService(); 117 BrowserThread::PostTask(BrowserThread::UI, 118 FROM_HERE, 119 NewRunnableMethod(history, 120 &HistoryService::ScheduleDBTask, 121 task, 122 &request_consumer)); 123 ui_test_utils::RunMessageLoop(); 124 } 125 126 void ExpectEmptyHistory() { 127 std::vector<GURL> urls(GetHistoryContents()); 128 EXPECT_EQ(0U, urls.size()); 129 } 130}; 131 132// Test that the browser history is saved (default setting). 133IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) { 134 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled)); 135 136 EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS)); 137 EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS)); 138 139 ui_test_utils::WaitForHistoryToLoad(browser()); 140 ExpectEmptyHistory(); 141 142 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 143 WaitForHistoryBackendToRun(); 144 145 { 146 std::vector<GURL> urls(GetHistoryContents()); 147 ASSERT_EQ(1U, urls.size()); 148 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec()); 149 } 150} 151 152// Test that disabling saving browser history really works. 153// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed. 154IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) { 155 base::TimeTicks start_time = base::TimeTicks::Now(); 156 157 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true); 158 159 EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS)); 160 EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS)); 161 162 Checkpoint("Before waiting for history to load", start_time); 163 ui_test_utils::WaitForHistoryToLoad(browser()); 164 Checkpoint("After waiting for history to load", start_time); 165 ExpectEmptyHistory(); 166 Checkpoint("After checking history", start_time); 167 168 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 169 Checkpoint("After NavigateToURL", start_time); 170 WaitForHistoryBackendToRun(); 171 Checkpoint("After waiting for history backend to run", start_time); 172 ExpectEmptyHistory(); 173 Checkpoint("After second check", start_time); 174} 175 176// Test that changing the pref takes effect immediately 177// when the browser is running. 178// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed. 179IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) { 180 base::TimeTicks start_time = base::TimeTicks::Now(); 181 182 EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled)); 183 184 Checkpoint("Before waiting for history to load", start_time); 185 ui_test_utils::WaitForHistoryToLoad(browser()); 186 Checkpoint("After waiting for history to load", start_time); 187 188 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 189 Checkpoint("After first NavigateToURL", start_time); 190 WaitForHistoryBackendToRun(); 191 Checkpoint("After waiting for history backend to run", start_time); 192 193 { 194 std::vector<GURL> urls(GetHistoryContents()); 195 Checkpoint("After first GetHistoryContents", start_time); 196 ASSERT_EQ(1U, urls.size()); 197 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec()); 198 } 199 200 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true); 201 202 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 203 Checkpoint("After second NavigateToURL", start_time); 204 WaitForHistoryBackendToRun(); 205 Checkpoint("After waiting for history backend to run (2nd time)", start_time); 206 207 { 208 // No additional entries should be present in the history. 209 std::vector<GURL> urls(GetHistoryContents()); 210 Checkpoint("After second GetHistoryContents", start_time); 211 ASSERT_EQ(1U, urls.size()); 212 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec()); 213 } 214} 215 216// Test that changing the pref takes effect immediately 217// when the browser is running. 218IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) { 219 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true); 220 221 ui_test_utils::WaitForHistoryToLoad(browser()); 222 ExpectEmptyHistory(); 223 224 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 225 WaitForHistoryBackendToRun(); 226 ExpectEmptyHistory(); 227 228 GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false); 229 230 ui_test_utils::NavigateToURL(browser(), GetTestUrl()); 231 WaitForHistoryBackendToRun(); 232 233 { 234 std::vector<GURL> urls(GetHistoryContents()); 235 ASSERT_EQ(1U, urls.size()); 236 EXPECT_EQ(GetTestUrl().spec(), urls[0].spec()); 237 } 238} 239 240} // namespace 241