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
18 namespace {
19
20 // Helper to debug intermittent test hangs/timeouts.
21 // TODO(phajdan.jr): remove when http://crbug.com/57994 is fixed.
Checkpoint(const char * message,const base::TimeTicks & start_time)22 void 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.
36 class WaitForHistoryTask : public HistoryDBTask {
37 public:
WaitForHistoryTask()38 WaitForHistoryTask() {
39 }
40
RunOnDBThread(history::HistoryBackend * backend,history::HistoryDatabase * db)41 virtual bool RunOnDBThread(history::HistoryBackend* backend,
42 history::HistoryDatabase* db) {
43 return true;
44 }
45
DoneRunOnMainThread()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.
55 class HistoryEnumerator : public HistoryService::URLEnumerator {
56 public:
HistoryEnumerator(HistoryService * history)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
OnURL(const GURL & url)69 virtual void OnURL(const GURL& url) {
70 urls_.push_back(url);
71 }
72
OnComplete(bool success)73 virtual void OnComplete(bool success) {
74 BrowserThread::PostTask(
75 BrowserThread::UI,
76 FROM_HERE,
77 new MessageLoop::QuitTask());
78 }
79
urls()80 std::vector<GURL>& urls() { return urls_; }
81
82 private:
83 std::vector<GURL> urls_;
84
85 DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
86 };
87
88 class HistoryBrowserTest : public InProcessBrowserTest {
89 protected:
GetPrefs()90 PrefService* GetPrefs() {
91 return GetProfile()->GetPrefs();
92 }
93
GetProfile()94 Profile* GetProfile() {
95 return browser()->GetProfile();
96 }
97
GetHistoryService()98 HistoryService* GetHistoryService() {
99 return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
100 }
101
GetHistoryContents()102 std::vector<GURL> GetHistoryContents() {
103 HistoryEnumerator enumerator(GetHistoryService());
104 return enumerator.urls();
105 }
106
GetTestUrl()107 GURL GetTestUrl() {
108 return ui_test_utils::GetTestUrl(
109 FilePath(FilePath::kCurrentDirectory),
110 FilePath(FILE_PATH_LITERAL("title2.html")));
111 }
112
WaitForHistoryBackendToRun()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
ExpectEmptyHistory()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).
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,SavingHistoryEnabled)133 IN_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.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,SavingHistoryDisabled)154 IN_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.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,SavingHistoryEnabledThenDisabled)179 IN_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.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,SavingHistoryDisabledThenEnabled)218 IN_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