- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / typed_urls_helper.cc
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.
4
5 #include "chrome/browser/sync/test/integration/typed_urls_helper.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/common/cancelable_request.h"
12 #include "chrome/browser/history/history_backend.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/history/history_types.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
19 #include "chrome/browser/sync/test/integration/sync_test.h"
20
21 using sync_datatype_helper::test;
22
23 namespace {
24
25 class FlushHistoryDBQueueTask : public history::HistoryDBTask {
26  public:
27   explicit FlushHistoryDBQueueTask(base::WaitableEvent* event)
28       : wait_event_(event) {}
29   virtual bool RunOnDBThread(history::HistoryBackend* backend,
30                              history::HistoryDatabase* db) OVERRIDE {
31     wait_event_->Signal();
32     return true;
33   }
34
35   virtual void DoneRunOnMainThread() OVERRIDE {}
36
37  private:
38   virtual ~FlushHistoryDBQueueTask() {}
39
40   base::WaitableEvent* wait_event_;
41 };
42
43 class GetTypedUrlsTask : public history::HistoryDBTask {
44  public:
45   GetTypedUrlsTask(history::URLRows* rows, base::WaitableEvent* event)
46       : rows_(rows), wait_event_(event) {}
47
48   virtual bool RunOnDBThread(history::HistoryBackend* backend,
49                              history::HistoryDatabase* db) OVERRIDE {
50     // Fetch the typed URLs.
51     backend->GetAllTypedURLs(rows_);
52     wait_event_->Signal();
53     return true;
54   }
55
56   virtual void DoneRunOnMainThread() OVERRIDE {}
57
58  private:
59   virtual ~GetTypedUrlsTask() {}
60
61   history::URLRows* rows_;
62   base::WaitableEvent* wait_event_;
63 };
64
65 class GetUrlTask : public history::HistoryDBTask {
66  public:
67   GetUrlTask(const GURL& url,
68              history::URLRow* row,
69              bool* found,
70              base::WaitableEvent* event)
71       : url_(url), row_(row), wait_event_(event), found_(found) {}
72
73   virtual bool RunOnDBThread(history::HistoryBackend* backend,
74                              history::HistoryDatabase* db) OVERRIDE {
75     // Fetch the typed URLs.
76     *found_ = backend->GetURL(url_, row_);
77     wait_event_->Signal();
78     return true;
79   }
80
81   virtual void DoneRunOnMainThread() OVERRIDE {}
82
83  private:
84   virtual ~GetUrlTask() {}
85
86   GURL url_;
87   history::URLRow* row_;
88   base::WaitableEvent* wait_event_;
89   bool* found_;
90 };
91
92 class GetVisitsTask : public history::HistoryDBTask {
93  public:
94   GetVisitsTask(history::URLID id,
95                 history::VisitVector* visits,
96                 base::WaitableEvent* event)
97       : id_(id), visits_(visits), wait_event_(event) {}
98
99   virtual bool RunOnDBThread(history::HistoryBackend* backend,
100                              history::HistoryDatabase* db) OVERRIDE {
101     // Fetch the visits.
102     backend->GetVisitsForURL(id_, visits_);
103     wait_event_->Signal();
104     return true;
105   }
106
107   virtual void DoneRunOnMainThread() OVERRIDE {}
108
109  private:
110   virtual ~GetVisitsTask() {}
111
112   history::URLID id_;
113   history::VisitVector* visits_;
114   base::WaitableEvent* wait_event_;
115 };
116
117 class RemoveVisitsTask : public history::HistoryDBTask {
118  public:
119   RemoveVisitsTask(const history::VisitVector& visits,
120                    base::WaitableEvent* event)
121       : visits_(visits), wait_event_(event) {}
122
123   virtual bool RunOnDBThread(history::HistoryBackend* backend,
124                              history::HistoryDatabase* db) OVERRIDE {
125     // Fetch the visits.
126     backend->RemoveVisits(visits_);
127     wait_event_->Signal();
128     return true;
129   }
130
131   virtual void DoneRunOnMainThread() OVERRIDE {}
132
133  private:
134   virtual ~RemoveVisitsTask() {}
135
136   const history::VisitVector& visits_;
137   base::WaitableEvent* wait_event_;
138 };
139
140 // Waits for the history DB thread to finish executing its current set of
141 // tasks.
142 void WaitForHistoryDBThread(int index) {
143   CancelableRequestConsumer cancelable_consumer;
144   HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(
145       test()->GetProfile(index));
146   base::WaitableEvent wait_event(true, false);
147   service->ScheduleDBTask(new FlushHistoryDBQueueTask(&wait_event),
148                           &cancelable_consumer);
149   wait_event.Wait();
150 }
151
152 // Creates a URLRow in the specified HistoryService with the passed transition
153 // type.
154 void AddToHistory(HistoryService* service,
155                   const GURL& url,
156                   content::PageTransition transition,
157                   history::VisitSource source,
158                   const base::Time& timestamp) {
159   service->AddPage(url,
160                    timestamp,
161                    NULL, // scope
162                    1234, // page_id
163                    GURL(),  // referrer
164                    history::RedirectList(),
165                    transition,
166                    source,
167                    false);
168   service->SetPageTitle(url, ASCIIToUTF16(url.spec() + " - title"));
169 }
170
171 history::URLRows GetTypedUrlsFromHistoryService(HistoryService* service) {
172   CancelableRequestConsumer cancelable_consumer;
173   history::URLRows rows;
174   base::WaitableEvent wait_event(true, false);
175   service->ScheduleDBTask(new GetTypedUrlsTask(&rows, &wait_event),
176                           &cancelable_consumer);
177   wait_event.Wait();
178   return rows;
179 }
180
181 bool GetUrlFromHistoryService(HistoryService* service,
182                               const GURL& url, history::URLRow* row) {
183   CancelableRequestConsumer cancelable_consumer;
184   base::WaitableEvent wait_event(true, false);
185   bool found;
186   service->ScheduleDBTask(new GetUrlTask(url, row, &found, &wait_event),
187                           &cancelable_consumer);
188   wait_event.Wait();
189   return found;
190 }
191
192 history::VisitVector GetVisitsFromHistoryService(HistoryService* service,
193                                                  history::URLID id) {
194   CancelableRequestConsumer cancelable_consumer;
195   base::WaitableEvent wait_event(true, false);
196   history::VisitVector visits;
197   service->ScheduleDBTask(new GetVisitsTask(id, &visits, &wait_event),
198                           &cancelable_consumer);
199   wait_event.Wait();
200   return visits;
201 }
202
203 void RemoveVisitsFromHistoryService(HistoryService* service,
204                                     const history::VisitVector& visits) {
205   CancelableRequestConsumer cancelable_consumer;
206   base::WaitableEvent wait_event(true, false);
207   service->ScheduleDBTask(new RemoveVisitsTask(visits, &wait_event),
208                           &cancelable_consumer);
209   wait_event.Wait();
210 }
211
212 static base::Time* timestamp = NULL;
213
214 }  // namespace
215
216 namespace typed_urls_helper {
217
218 history::URLRows GetTypedUrlsFromClient(int index) {
219   HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(
220       test()->GetProfile(index));
221   return GetTypedUrlsFromHistoryService(service);
222 }
223
224 bool GetUrlFromClient(int index, const GURL& url, history::URLRow* row) {
225   HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(
226       test()->GetProfile(index));
227   return GetUrlFromHistoryService(service, url, row);
228 }
229
230 history::VisitVector GetVisitsFromClient(int index, history::URLID id) {
231   HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(
232       test()->GetProfile(index));
233   return GetVisitsFromHistoryService(service, id);
234 }
235
236 void RemoveVisitsFromClient(int index, const history::VisitVector& visits) {
237   HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(
238       test()->GetProfile(index));
239   RemoveVisitsFromHistoryService(service, visits);
240 }
241
242 base::Time GetTimestamp() {
243   // The history subsystem doesn't like identical timestamps for page visits,
244   // and it will massage the visit timestamps if we try to use identical
245   // values, which can lead to spurious errors. So make sure all timestamps
246   // are unique.
247   if (!::timestamp)
248     ::timestamp = new base::Time(base::Time::Now());
249   base::Time original = *::timestamp;
250   *::timestamp += base::TimeDelta::FromMilliseconds(1);
251   return original;
252 }
253
254 void AddUrlToHistory(int index, const GURL& url) {
255   AddUrlToHistoryWithTransition(index, url, content::PAGE_TRANSITION_TYPED,
256                                 history::SOURCE_BROWSED);
257 }
258 void AddUrlToHistoryWithTransition(int index,
259                                    const GURL& url,
260                                    content::PageTransition transition,
261                                    history::VisitSource source) {
262   base::Time timestamp = GetTimestamp();
263   AddUrlToHistoryWithTimestamp(index, url, transition, source, timestamp);
264 }
265 void AddUrlToHistoryWithTimestamp(int index,
266                                   const GURL& url,
267                                   content::PageTransition transition,
268                                   history::VisitSource source,
269                                   const base::Time& timestamp) {
270   AddToHistory(HistoryServiceFactory::GetForProfileWithoutCreating(
271                    test()->GetProfile(index)),
272                url,
273                transition,
274                source,
275                timestamp);
276   if (test()->use_verifier())
277     AddToHistory(
278         HistoryServiceFactory::GetForProfile(test()->verifier(),
279                                              Profile::IMPLICIT_ACCESS),
280         url,
281         transition,
282         source,
283         timestamp);
284
285   // Wait until the AddPage() request has completed so we know the change has
286   // filtered down to the sync observers (don't need to wait for the
287   // verifier profile since it doesn't sync).
288   WaitForHistoryDBThread(index);
289 }
290
291 void DeleteUrlFromHistory(int index, const GURL& url) {
292   HistoryServiceFactory::GetForProfileWithoutCreating(
293       test()->GetProfile(index))->DeleteURL(url);
294   if (test()->use_verifier())
295     HistoryServiceFactory::GetForProfile(test()->verifier(),
296                                          Profile::IMPLICIT_ACCESS)->
297         DeleteURL(url);
298   WaitForHistoryDBThread(index);
299 }
300
301 void DeleteUrlsFromHistory(int index, const std::vector<GURL>& urls) {
302   HistoryServiceFactory::GetForProfileWithoutCreating(
303       test()->GetProfile(index))->DeleteURLsForTest(urls);
304   if (test()->use_verifier())
305     HistoryServiceFactory::GetForProfile(test()->verifier(),
306                                          Profile::IMPLICIT_ACCESS)->
307         DeleteURLsForTest(urls);
308   WaitForHistoryDBThread(index);
309 }
310
311 void AssertURLRowVectorsAreEqual(const history::URLRows& left,
312                                  const history::URLRows& right) {
313   ASSERT_EQ(left.size(), right.size());
314   for (size_t i = 0; i < left.size(); ++i) {
315     // URLs could be out-of-order, so look for a matching URL in the second
316     // array.
317     bool found = false;
318     for (size_t j = 0; j < right.size(); ++j) {
319       if (left[i].url() == right[j].url()) {
320         AssertURLRowsAreEqual(left[i], right[j]);
321         found = true;
322         break;
323       }
324     }
325     ASSERT_TRUE(found);
326   }
327 }
328
329 bool AreVisitsEqual(const history::VisitVector& visit1,
330                     const history::VisitVector& visit2) {
331   if (visit1.size() != visit2.size())
332     return false;
333   for (size_t i = 0; i < visit1.size(); ++i) {
334     if (visit1[i].transition != visit2[i].transition)
335       return false;
336     if (visit1[i].visit_time != visit2[i].visit_time)
337       return false;
338   }
339   return true;
340 }
341
342 bool AreVisitsUnique(const history::VisitVector& visits) {
343   base::Time t = base::Time::FromInternalValue(0);
344   for (size_t i = 0; i < visits.size(); ++i) {
345     if (t == visits[i].visit_time)
346       return false;
347     t = visits[i].visit_time;
348   }
349   return true;
350 }
351
352 void AssertURLRowsAreEqual(
353     const history::URLRow& left, const history::URLRow& right) {
354   ASSERT_EQ(left.url(), right.url());
355   ASSERT_EQ(left.title(), right.title());
356   ASSERT_EQ(left.visit_count(), right.visit_count());
357   ASSERT_EQ(left.typed_count(), right.typed_count());
358   ASSERT_EQ(left.last_visit(), right.last_visit());
359   ASSERT_EQ(left.hidden(), right.hidden());
360 }
361
362 void AssertAllProfilesHaveSameURLsAsVerifier() {
363   HistoryService* verifier_service =
364       HistoryServiceFactory::GetForProfile(test()->verifier(),
365                                            Profile::IMPLICIT_ACCESS);
366   history::URLRows verifier_urls =
367       GetTypedUrlsFromHistoryService(verifier_service);
368   for (int i = 0; i < test()->num_clients(); ++i) {
369     history::URLRows urls = GetTypedUrlsFromClient(i);
370     AssertURLRowVectorsAreEqual(verifier_urls, urls);
371   }
372 }
373
374 }  // namespace typed_urls_helper