Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / history / android / android_provider_backend_unittest.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/history/android/android_provider_backend.h"
6
7 #include <vector>
8
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/favicon/favicon_changed_details.h"
18 #include "chrome/browser/history/android/android_time.h"
19 #include "chrome/browser/history/chrome_history_client.h"
20 #include "chrome/browser/history/chrome_history_client_factory.h"
21 #include "chrome/browser/history/history_backend.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/test/base/testing_browser_process.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "chrome/test/base/testing_profile_manager.h"
27 #include "components/bookmarks/browser/bookmark_model.h"
28 #include "components/bookmarks/test/bookmark_test_helpers.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "content/public/test/test_utils.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 using base::Time;
35 using base::TimeDelta;
36 using base::UTF8ToUTF16;
37 using content::BrowserThread;
38
39 namespace history {
40
41 namespace {
42
43 struct BookmarkCacheRow {
44  public:
45   BookmarkCacheRow()
46       : url_id_(0),
47         bookmark_(false),
48         favicon_id_(0) {
49   }
50   URLID url_id_;
51   Time create_time_;
52   Time last_visit_time_;
53   bool bookmark_;
54   favicon_base::FaviconID favicon_id_;
55 };
56
57 }  // namespace
58
59 class AndroidProviderBackendDelegate : public HistoryBackend::Delegate {
60  public:
61   AndroidProviderBackendDelegate() {}
62
63   virtual void NotifyProfileError(sql::InitStatus init_status) OVERRIDE {}
64   virtual void SetInMemoryBackend(
65       scoped_ptr<InMemoryHistoryBackend> backend) OVERRIDE {}
66   virtual void BroadcastNotifications(
67       int type,
68       scoped_ptr<HistoryDetails> details) OVERRIDE {
69     switch (type) {
70       case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
71         deleted_details_.reset(
72             static_cast<URLsDeletedDetails*>(details.release()));
73         break;
74       case chrome::NOTIFICATION_FAVICON_CHANGED:
75         favicon_details_.reset(
76             static_cast<FaviconChangedDetails*>(details.release()));
77         break;
78       case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
79         modified_details_.reset(
80             static_cast<URLsModifiedDetails*>(details.release()));
81         break;
82     }
83   }
84   virtual void DBLoaded() OVERRIDE {}
85   virtual void NotifyVisitDBObserversOnAddVisit(
86       const history::BriefVisitInfo& info) OVERRIDE {}
87
88   URLsDeletedDetails* deleted_details() const {
89     return deleted_details_.get();
90   }
91
92   URLsModifiedDetails* modified_details() const {
93     return modified_details_.get();
94   }
95
96   FaviconChangedDetails* favicon_details() const {
97     return favicon_details_.get();
98   }
99
100   void ResetDetails() {
101     deleted_details_.reset();
102     modified_details_.reset();
103     favicon_details_.reset();
104   }
105
106  private:
107   scoped_ptr<URLsDeletedDetails> deleted_details_;
108   scoped_ptr<URLsModifiedDetails> modified_details_;
109   scoped_ptr<FaviconChangedDetails> favicon_details_;
110
111   DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendDelegate);
112 };
113
114 class AndroidProviderBackendTest : public testing::Test {
115  public:
116   AndroidProviderBackendTest()
117       : profile_manager_(
118           TestingBrowserProcess::GetGlobal()),
119         bookmark_model_(NULL),
120         ui_thread_(BrowserThread::UI, &message_loop_),
121         file_thread_(BrowserThread::FILE, &message_loop_) {
122   }
123   virtual ~AndroidProviderBackendTest() {}
124
125  protected:
126   virtual void SetUp() OVERRIDE {
127     // Setup the testing profile, so the bookmark_model_sql_handler could
128     // get the bookmark model from it.
129     ASSERT_TRUE(profile_manager_.SetUp());
130     // It seems that the name has to be chrome::kInitialProfile, so it
131     // could be found by ProfileManager::GetLastUsedProfile().
132     TestingProfile* testing_profile = profile_manager_.CreateTestingProfile(
133         chrome::kInitialProfile);
134     testing_profile->CreateBookmarkModel(true);
135     bookmark_model_ = BookmarkModelFactory::GetForProfile(testing_profile);
136     history_client_ =
137         ChromeHistoryClientFactory::GetForProfile(testing_profile);
138     test::WaitForBookmarkModelToLoad(bookmark_model_);
139     ASSERT_TRUE(bookmark_model_);
140
141     // Get the BookmarkModel from LastUsedProfile, this is the same way that
142     // how the BookmarkModelSQLHandler gets the BookmarkModel.
143     Profile* profile = ProfileManager::GetLastUsedProfile();
144     ASSERT_TRUE(profile);
145
146     // Setup the database directory and files.
147     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
148
149     history_db_name_ = temp_dir_.path().AppendASCII(chrome::kHistoryFilename);
150     thumbnail_db_name_ = temp_dir_.path().AppendASCII(
151         chrome::kFaviconsFilename);
152     android_cache_db_name_ = temp_dir_.path().AppendASCII(
153         "TestAndroidCache.db");
154   }
155
156   void AddBookmark(const GURL& url) {
157     const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
158     ASSERT_TRUE(mobile_node);
159     ASSERT_TRUE(bookmark_model_->AddURL(mobile_node, 0, base::string16(), url));
160   }
161
162   bool GetAndroidURLsRows(std::vector<AndroidURLRow>* rows,
163                           AndroidProviderBackend* backend) {
164     sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE,
165         "SELECT id, raw_url, url_id FROM android_urls ORDER BY url_id ASC"));
166
167     while (statement.Step()) {
168       AndroidURLRow row;
169       row.id = statement.ColumnInt64(0);
170       row.raw_url = statement.ColumnString(1);
171       row.url_id = statement.ColumnInt64(2);
172       rows->push_back(row);
173     }
174     return true;
175   }
176
177   bool GetBookmarkCacheRows(std::vector<BookmarkCacheRow>* rows,
178                             AndroidProviderBackend* backend) {
179     sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE,
180         "SELECT created_time, last_visit_time, url_id, bookmark, favicon_id "
181         "FROM android_cache_db.bookmark_cache ORDER BY url_id ASC"));
182
183     while (statement.Step()) {
184       BookmarkCacheRow row;
185       row.create_time_ = FromDatabaseTime(statement.ColumnInt64(0));
186       row.last_visit_time_ = FromDatabaseTime(statement.ColumnInt64(1));
187       row.url_id_ = statement.ColumnInt64(2);
188       row.bookmark_ = statement.ColumnBool(3);
189       row.favicon_id_ = statement.ColumnInt64(4);
190       rows->push_back(row);
191     }
192     return true;
193   }
194
195   AndroidProviderBackendDelegate delegate_;
196   scoped_refptr<HistoryBackend> history_backend_;
197   HistoryDatabase history_db_;
198   ThumbnailDatabase thumbnail_db_;
199   base::ScopedTempDir temp_dir_;
200   base::FilePath android_cache_db_name_;
201   base::FilePath history_db_name_;
202   base::FilePath thumbnail_db_name_;
203
204   TestingProfileManager profile_manager_;
205   BookmarkModel* bookmark_model_;
206   base::MessageLoopForUI message_loop_;
207   content::TestBrowserThread ui_thread_;
208   content::TestBrowserThread file_thread_;
209   ChromeHistoryClient* history_client_;
210
211   DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendTest);
212 };
213
214 TEST_F(AndroidProviderBackendTest, UpdateTables) {
215   GURL url1("http://www.cnn.com");
216   URLID url_id1 = 0;
217   std::vector<VisitInfo> visits1;
218   Time last_visited1 = Time::Now() - TimeDelta::FromDays(1);
219   Time created1 = last_visited1 - TimeDelta::FromDays(20);
220   visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK));
221   visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
222                               content::PAGE_TRANSITION_LINK));
223   visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK));
224
225   GURL url2("http://www.example.com");
226   URLID url_id2 = 0;
227   std::vector<VisitInfo> visits2;
228   Time last_visited2 = Time::Now();
229   Time created2 = last_visited2 - TimeDelta::FromDays(10);
230   visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK));
231   visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
232                               content::PAGE_TRANSITION_LINK));
233   visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK));
234
235   // Add a bookmark which is not in the history.
236   GURL url3("http://www.bookmark.com");
237   base::string16 title3(UTF8ToUTF16("bookmark"));
238   ASSERT_TRUE(bookmark_model_->AddURL(bookmark_model_->bookmark_bar_node(), 0,
239                                       title3, url3));
240   // Only use the HistoryBackend to generate the test data.
241   // HistoryBackend will shutdown after that.
242   {
243   scoped_refptr<HistoryBackend> history_backend;
244   history_backend = new HistoryBackend(
245       temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
246   history_backend->Init(std::string(), false);
247   history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
248   history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
249   URLRow url_row;
250
251   ASSERT_TRUE(history_backend->GetURL(url1, &url_row));
252   url_id1 = url_row.id();
253   ASSERT_TRUE(history_backend->GetURL(url2, &url_row));
254   url_id2 = url_row.id();
255
256   // Set favicon to url2.
257   std::vector<unsigned char> data;
258   data.push_back('1');
259   favicon_base::FaviconRawBitmapData bitmap_data_element;
260   bitmap_data_element.bitmap_data = new base::RefCountedBytes(data);
261   bitmap_data_element.pixel_size = gfx::Size();
262   bitmap_data_element.icon_url = GURL();
263   std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
264   favicon_bitmap_data.push_back(bitmap_data_element);
265
266   history_backend->SetFavicons(
267       url2, favicon_base::FAVICON, favicon_bitmap_data);
268   history_backend->Closing();
269   }
270
271   // The history_db_name and thumbnail_db_name files should be created by
272   // HistoryBackend. We need to open the same database files.
273   ASSERT_TRUE(base::PathExists(history_db_name_));
274   ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
275
276   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
277   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
278   // Set url1 as bookmark.
279   AddBookmark(url1);
280   scoped_ptr<AndroidProviderBackend> backend(
281       new AndroidProviderBackend(android_cache_db_name_,
282                                  &history_db_,
283                                  &thumbnail_db_,
284                                  history_client_,
285                                  &delegate_));
286
287   ASSERT_TRUE(backend->EnsureInitializedAndUpdated());
288
289   // First verify that the bookmark which was not in the history has been added
290   // to history database.
291   URLRow url_row;
292   ASSERT_TRUE(history_db_.GetRowForURL(url3, &url_row));
293   URLID url_id3 = url_row.id();
294   ASSERT_EQ(url3, url_row.url());
295   ASSERT_EQ(title3, url_row.title());
296
297   std::vector<AndroidURLRow> android_url_rows;
298   ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get()));
299   ASSERT_EQ(3u, android_url_rows.size());
300   std::vector<AndroidURLRow>::iterator i = android_url_rows.begin();
301   EXPECT_EQ(url_id1, i->url_id);
302   EXPECT_EQ(url1.spec(), i->raw_url);
303   i++;
304   EXPECT_EQ(url_id2, i->url_id);
305   EXPECT_EQ(url2.spec(), i->raw_url);
306   i++;
307   EXPECT_EQ(url_id3, i->url_id);
308   EXPECT_EQ(url3.spec(), i->raw_url);
309
310   std::vector<BookmarkCacheRow> bookmark_cache_rows;
311   ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get()));
312   ASSERT_EQ(3u, bookmark_cache_rows.size());
313   std::vector<BookmarkCacheRow>::const_iterator j = bookmark_cache_rows.begin();
314   EXPECT_EQ(url_id1, j->url_id_);
315   EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_));
316   EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_));
317   EXPECT_EQ(0, j->favicon_id_);
318   EXPECT_TRUE(j->bookmark_);
319   j++;
320   EXPECT_EQ(url_id2, j->url_id_);
321   EXPECT_EQ(ToDatabaseTime(last_visited2), ToDatabaseTime(j->last_visit_time_));
322   EXPECT_EQ(ToDatabaseTime(created2), ToDatabaseTime(j->create_time_));
323   EXPECT_NE(0, j->favicon_id_);
324   EXPECT_FALSE(j->bookmark_);
325
326   // Delete url2 from database.
327   ASSERT_TRUE(history_db_.DeleteURLRow(url_id2));
328   VisitVector visit_rows;
329   ASSERT_TRUE(history_db_.GetMostRecentVisitsForURL(url_id2, 10,
330                                                     &visit_rows));
331   ASSERT_EQ(3u, visit_rows.size());
332   for (VisitVector::const_iterator v = visit_rows.begin();
333        v != visit_rows.end(); v++)
334     history_db_.DeleteVisit(*v);
335
336   backend->UpdateTables();
337
338   android_url_rows.clear();
339   ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get()));
340   ASSERT_EQ(2u, android_url_rows.size());
341   i = android_url_rows.begin();
342   EXPECT_EQ(url_id1, i->url_id);
343   EXPECT_EQ(url1.spec(), i->raw_url);
344   ++i;
345   EXPECT_EQ(url_id3, i->url_id);
346   EXPECT_EQ(url3.spec(), i->raw_url);
347
348   bookmark_cache_rows.clear();
349   ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get()));
350   ASSERT_EQ(2u, bookmark_cache_rows.size());
351   j = bookmark_cache_rows.begin();
352   EXPECT_EQ(url_id1, j->url_id_);
353   EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_));
354   EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_));
355   EXPECT_EQ(0, j->favicon_id_);
356   EXPECT_TRUE(j->bookmark_);
357   ++j;
358   EXPECT_EQ(url_id3, j->url_id_);
359   EXPECT_EQ(base::Time::UnixEpoch(), j->last_visit_time_);
360   EXPECT_EQ(base::Time::UnixEpoch(), j->create_time_);
361   EXPECT_EQ(0, j->favicon_id_);
362   EXPECT_TRUE(j->bookmark_);
363 }
364
365 TEST_F(AndroidProviderBackendTest, QueryHistoryAndBookmarks) {
366   GURL url1("http://www.cnn.com");
367   URLID url_id1 = 0;
368   const base::string16 title1(UTF8ToUTF16("cnn"));
369   std::vector<VisitInfo> visits1;
370   Time last_visited1 = Time::Now() - TimeDelta::FromDays(1);
371   Time created1 = last_visited1 - TimeDelta::FromDays(20);
372   visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK));
373   visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
374                               content::PAGE_TRANSITION_LINK));
375   visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK));
376
377   GURL url2("http://www.example.com");
378   URLID url_id2 = 0;
379   std::vector<VisitInfo> visits2;
380   const base::string16 title2(UTF8ToUTF16("example"));
381   Time last_visited2 = Time::Now();
382   Time created2 = last_visited2 - TimeDelta::FromDays(10);
383   visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK));
384   visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
385                               content::PAGE_TRANSITION_LINK));
386   visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK));
387
388   // Only use the HistoryBackend to generate the test data.
389   // HistoryBackend will shutdown after that.
390   {
391   scoped_refptr<HistoryBackend> history_backend;
392   history_backend = new HistoryBackend(
393       temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
394   history_backend->Init(std::string(), false);
395   history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
396   history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
397   URLRow url_row;
398
399   ASSERT_TRUE(history_backend->GetURL(url1, &url_row));
400   url_id1 = url_row.id();
401   url_row.set_title(title1);
402   ASSERT_TRUE(history_backend->UpdateURL(url_id1, url_row));
403
404   ASSERT_TRUE(history_backend->GetURL(url2, &url_row));
405   url_id2 = url_row.id();
406   url_row.set_title(title2);
407   ASSERT_TRUE(history_backend->UpdateURL(url_id2, url_row));
408
409   // Set favicon to url2.
410   std::vector<unsigned char> data;
411   data.push_back('1');
412   favicon_base::FaviconRawBitmapData bitmap_data_element;
413   bitmap_data_element.bitmap_data = new base::RefCountedBytes(data);
414   bitmap_data_element.pixel_size = gfx::Size();
415   bitmap_data_element.icon_url = GURL();
416   std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
417   favicon_bitmap_data.push_back(bitmap_data_element);
418
419   history_backend->SetFavicons(
420       url2, favicon_base::FAVICON, favicon_bitmap_data);
421   history_backend->Closing();
422   }
423
424   // The history_db_name and thumbnail_db_name files should be created by
425   // HistoryBackend. We need to open the same database files.
426   ASSERT_TRUE(base::PathExists(history_db_name_));
427   ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
428
429   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
430   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
431   // Set url1 as bookmark.
432   AddBookmark(url1);
433
434   scoped_ptr<AndroidProviderBackend> backend(
435       new AndroidProviderBackend(android_cache_db_name_,
436                                  &history_db_,
437                                  &thumbnail_db_,
438                                  history_client_,
439                                  &delegate_));
440
441   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
442
443   projections.push_back(HistoryAndBookmarkRow::ID);
444   projections.push_back(HistoryAndBookmarkRow::URL);
445   projections.push_back(HistoryAndBookmarkRow::TITLE);
446   projections.push_back(HistoryAndBookmarkRow::CREATED);
447   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
448   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
449   projections.push_back(HistoryAndBookmarkRow::FAVICON);
450   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
451
452   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
453       projections, std::string(), std::vector<base::string16>(),
454       std::string("url ASC")));
455   ASSERT_TRUE(statement->statement()->Step());
456   ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
457   EXPECT_EQ(title1, statement->statement()->ColumnString16(2));
458   EXPECT_EQ(ToDatabaseTime(created1),
459             statement->statement()->ColumnInt64(3));
460   EXPECT_EQ(ToDatabaseTime(last_visited1),
461             statement->statement()->ColumnInt64(4));
462   EXPECT_EQ(3, statement->statement()->ColumnInt(5));
463   EXPECT_EQ(6, statement->favicon_index());
464   // No favicon.
465   EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
466   EXPECT_TRUE(statement->statement()->ColumnBool(7));
467
468   ASSERT_TRUE(statement->statement()->Step());
469   EXPECT_EQ(title2, statement->statement()->ColumnString16(2));
470   ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
471   EXPECT_EQ(ToDatabaseTime(created2),
472             statement->statement()->ColumnInt64(3));
473   EXPECT_EQ(ToDatabaseTime(last_visited2),
474             statement->statement()->ColumnInt64(4));
475   EXPECT_EQ(3, statement->statement()->ColumnInt(5));
476   std::vector<unsigned char> favicon2;
477   EXPECT_EQ(6, statement->favicon_index());
478   // Has favicon.
479   EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
480   EXPECT_FALSE(statement->statement()->ColumnBool(7));
481
482   // No more row.
483   EXPECT_FALSE(statement->statement()->Step());
484
485   // Query by bookmark
486   statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=1",
487       std::vector<base::string16>(), std::string("url ASC")));
488   // Only URL1 is returned.
489   ASSERT_TRUE(statement->statement()->Step());
490   ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
491   EXPECT_FALSE(statement->statement()->Step());
492
493   statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=0",
494       std::vector<base::string16>(), std::string("url ASC")));
495   // Only URL2 is returned.
496   ASSERT_TRUE(statement->statement()->Step());
497   ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
498   EXPECT_FALSE(statement->statement()->Step());
499 }
500
501 TEST_F(AndroidProviderBackendTest, InsertHistoryAndBookmark) {
502   HistoryAndBookmarkRow row1;
503   row1.set_raw_url("cnn.com");
504   row1.set_url(GURL("http://cnn.com"));
505   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
506   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
507   row1.set_visit_count(10);
508   row1.set_is_bookmark(true);
509   row1.set_title(UTF8ToUTF16("cnn"));
510
511   HistoryAndBookmarkRow row2;
512   row2.set_raw_url("http://www.example.com");
513   row2.set_url(GURL("http://www.example.com"));
514   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
515   row2.set_is_bookmark(false);
516   row2.set_title(UTF8ToUTF16("example"));
517   std::vector<unsigned char> data;
518   data.push_back('1');
519   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
520
521   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
522   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
523   scoped_ptr<AndroidProviderBackend> backend(
524       new AndroidProviderBackend(android_cache_db_name_,
525                                  &history_db_,
526                                  &thumbnail_db_,
527                                  history_client_,
528                                  &delegate_));
529
530   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
531   EXPECT_FALSE(delegate_.deleted_details());
532   ASSERT_TRUE(delegate_.modified_details());
533   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
534   EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url());
535   EXPECT_EQ(row1.last_visit_time(),
536             delegate_.modified_details()->changed_urls[0].last_visit());
537   EXPECT_EQ(row1.visit_count(),
538             delegate_.modified_details()->changed_urls[0].visit_count());
539   EXPECT_EQ(row1.title(),
540             delegate_.modified_details()->changed_urls[0].title());
541   EXPECT_FALSE(delegate_.favicon_details());
542   content::RunAllPendingInMessageLoop();
543   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
544   const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
545   ASSERT_TRUE(child);
546   EXPECT_EQ(row1.title(), child->GetTitle());
547   EXPECT_EQ(row1.url(), child->url());
548
549   delegate_.ResetDetails();
550   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
551   EXPECT_FALSE(delegate_.deleted_details());
552   ASSERT_TRUE(delegate_.modified_details());
553   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
554   EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url());
555   EXPECT_EQ(row2.last_visit_time(),
556             delegate_.modified_details()->changed_urls[0].last_visit());
557   EXPECT_EQ(row2.title(),
558             delegate_.modified_details()->changed_urls[0].title());
559   ASSERT_TRUE(delegate_.favicon_details());
560   ASSERT_EQ(1u, delegate_.favicon_details()->urls.size());
561   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
562               delegate_.favicon_details()->urls.find(row2.url()));
563
564   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
565   projections.push_back(HistoryAndBookmarkRow::ID);
566   projections.push_back(HistoryAndBookmarkRow::URL);
567   projections.push_back(HistoryAndBookmarkRow::TITLE);
568   projections.push_back(HistoryAndBookmarkRow::CREATED);
569   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
570   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
571   projections.push_back(HistoryAndBookmarkRow::FAVICON);
572   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
573
574   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
575       projections, std::string(), std::vector<base::string16>(),
576       std::string("url ASC")));
577   ASSERT_TRUE(statement->statement()->Step());
578   ASSERT_EQ(row1.raw_url(), statement->statement()->ColumnString(1));
579   EXPECT_EQ(row1.title(), statement->statement()->ColumnString16(2));
580   EXPECT_EQ(ToDatabaseTime(row1.created()),
581             statement->statement()->ColumnInt64(3));
582   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
583             statement->statement()->ColumnInt64(4));
584   EXPECT_EQ(row1.visit_count(), statement->statement()->ColumnInt(5));
585   EXPECT_EQ(6, statement->favicon_index());
586   // No favicon.
587   EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
588
589   // TODO: Find a way to test the bookmark was added in BookmarkModel.
590   // The bookmark was added in UI thread, there is no good way to test it.
591   EXPECT_TRUE(statement->statement()->ColumnBool(7));
592
593   ASSERT_TRUE(statement->statement()->Step());
594   EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2));
595   EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1)));
596   EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
597             statement->statement()->ColumnInt64(3));
598   EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
599             statement->statement()->ColumnInt64(4));
600   EXPECT_EQ(1, statement->statement()->ColumnInt(5));
601   EXPECT_EQ(6, statement->favicon_index());
602   // Has favicon.
603   EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
604   // TODO: Find a way to test the bookmark was added in BookmarkModel.
605   // The bookmark was added in UI thread, there is no good way to test it.
606   EXPECT_FALSE(statement->statement()->ColumnBool(7));
607
608   // No more row.
609   EXPECT_FALSE(statement->statement()->Step());
610 }
611
612 TEST_F(AndroidProviderBackendTest, DeleteHistoryAndBookmarks) {
613   HistoryAndBookmarkRow row1;
614   row1.set_raw_url("cnn.com");
615   row1.set_url(GURL("http://cnn.com"));
616   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
617   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
618   row1.set_visit_count(10);
619   row1.set_is_bookmark(true);
620   row1.set_title(UTF8ToUTF16("cnn"));
621
622   HistoryAndBookmarkRow row2;
623   row2.set_raw_url("http://www.example.com");
624   row2.set_url(GURL("http://www.example.com"));
625   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
626   row2.set_is_bookmark(false);
627   row2.set_title(UTF8ToUTF16("example"));
628   std::vector<unsigned char> data;
629   data.push_back('1');
630   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
631
632   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
633   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
634
635   scoped_ptr<AndroidProviderBackend> backend(
636       new AndroidProviderBackend(android_cache_db_name_,
637                                  &history_db_,
638                                  &thumbnail_db_,
639                                  history_client_,
640                                  &delegate_));
641
642   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
643   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
644   // Verify the row1 has been added in bookmark model.
645   content::RunAllPendingInMessageLoop();
646   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
647   const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
648   ASSERT_TRUE(child);
649   EXPECT_EQ(row1.title(), child->GetTitle());
650   EXPECT_EQ(row1.url(), child->url());
651
652   // Delete the row1.
653   std::vector<base::string16> args;
654   int deleted_count = 0;
655   delegate_.ResetDetails();
656   ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
657                                                  &deleted_count));
658   EXPECT_EQ(1, deleted_count);
659   // Verify the row1 was removed from bookmark model.
660   content::RunAllPendingInMessageLoop();
661   ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count());
662
663   // Verify notifications
664   ASSERT_TRUE(delegate_.deleted_details());
665   EXPECT_FALSE(delegate_.modified_details());
666   EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
667   EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url());
668   EXPECT_EQ(row1.last_visit_time(),
669             delegate_.deleted_details()->rows[0].last_visit());
670   EXPECT_EQ(row1.title(),
671             delegate_.deleted_details()->rows[0].title());
672   EXPECT_FALSE(delegate_.favicon_details());
673
674   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
675   projections.push_back(HistoryAndBookmarkRow::ID);
676   projections.push_back(HistoryAndBookmarkRow::URL);
677   projections.push_back(HistoryAndBookmarkRow::TITLE);
678   projections.push_back(HistoryAndBookmarkRow::CREATED);
679   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
680   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
681   projections.push_back(HistoryAndBookmarkRow::FAVICON);
682   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
683
684   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
685       projections, std::string(), std::vector<base::string16>(),
686       std::string("url ASC")));
687   ASSERT_TRUE(statement->statement()->Step());
688
689   EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2));
690   EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1)));
691   EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
692             statement->statement()->ColumnInt64(3));
693   EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
694             statement->statement()->ColumnInt64(4));
695   EXPECT_EQ(1, statement->statement()->ColumnInt(5));
696   EXPECT_EQ(6, statement->favicon_index());
697   // Has favicon.
698   EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
699   // TODO: Find a way to test the bookmark was added in BookmarkModel.
700   // The bookmark was added in UI thread, there is no good way to test it.
701   EXPECT_FALSE(statement->statement()->ColumnBool(7));
702   // No more row.
703   EXPECT_FALSE(statement->statement()->Step());
704
705   deleted_count = 0;
706   // Delete row2.
707   delegate_.ResetDetails();
708   ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("bookmark = 0",
709                   std::vector<base::string16>(), &deleted_count));
710   // Verify notifications
711   ASSERT_TRUE(delegate_.deleted_details());
712   EXPECT_FALSE(delegate_.modified_details());
713   EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
714   EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url());
715   EXPECT_EQ(row2.last_visit_time(),
716             delegate_.deleted_details()->rows[0].last_visit());
717   EXPECT_EQ(row2.title(),
718             delegate_.deleted_details()->rows[0].title());
719   ASSERT_TRUE(delegate_.favicon_details());
720   ASSERT_EQ(1u, delegate_.favicon_details()->urls.size());
721   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
722               delegate_.favicon_details()->urls.find(row2.url()));
723
724   ASSERT_EQ(1, deleted_count);
725   scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks(
726       projections, std::string(), std::vector<base::string16>(),
727       std::string("url ASC")));
728   ASSERT_FALSE(statement1->statement()->Step());
729 }
730
731 TEST_F(AndroidProviderBackendTest, IsValidHistoryAndBookmarkRow) {
732   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
733   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
734   scoped_ptr<AndroidProviderBackend> backend(
735       new AndroidProviderBackend(android_cache_db_name_,
736                                  &history_db_,
737                                  &thumbnail_db_,
738                                  history_client_,
739                                  &delegate_));
740
741   // The created time and last visit time are too close to have required visit
742   // count.
743   HistoryAndBookmarkRow row1;
744   row1.set_raw_url("cnn.com");
745   row1.set_url(GURL("http://cnn.com"));
746   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
747   row1.set_created(Time::FromInternalValue(
748       row1.last_visit_time().ToInternalValue() - 1));
749   row1.set_visit_count(10);
750   row1.set_is_bookmark(true);
751   row1.set_title(UTF8ToUTF16("cnn"));
752   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row1));
753
754   // Have different created time and last visit time, but only have 1 visit
755   // count.
756   HistoryAndBookmarkRow row2;
757   row2.set_raw_url("http://www.example.com");
758   row2.set_url(GURL("http://www.example.com"));
759   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
760   row2.set_created(Time::Now() - TimeDelta::FromDays(11));
761   row2.set_visit_count(1);
762   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row2));
763
764   // Have created time in the future.
765   HistoryAndBookmarkRow row3;
766   row3.set_raw_url("http://www.example.com");
767   row3.set_url(GURL("http://www.example.com"));
768   row3.set_created(Time::Now() + TimeDelta::FromDays(11));
769   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row3));
770
771   // Have last vist time in the future.
772   HistoryAndBookmarkRow row4;
773   row4.set_raw_url("http://www.example.com");
774   row4.set_url(GURL("http://www.example.com"));
775   row4.set_last_visit_time(Time::Now() + TimeDelta::FromDays(11));
776   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row4));
777
778   // Created time is larger than last visit time.
779   HistoryAndBookmarkRow row5;
780   row5.set_raw_url("http://www.example.com");
781   row5.set_url(GURL("http://www.example.com"));
782   row5.set_last_visit_time(Time::Now());
783   row5.set_created(Time::Now() + TimeDelta::FromDays(11));
784   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row5));
785
786   // Visit count is zero, and last visit time is not zero.
787   HistoryAndBookmarkRow row6;
788   row6.set_raw_url("http://www.example.com");
789   row6.set_url(GURL("http://www.example.com"));
790   row6.set_visit_count(0);
791   row6.set_last_visit_time(Time::Now());
792   row6.set_created(Time::Now() - TimeDelta::FromDays(1));
793   EXPECT_FALSE(backend->InsertHistoryAndBookmark(row6));
794
795   // Visit count is zero, and create time is not zero.
796   HistoryAndBookmarkRow row7;
797   row7.set_raw_url("http://www.example.com");
798   row7.set_url(GURL("http://www.example.com"));
799   row7.set_visit_count(0);
800   row7.set_last_visit_time(Time::Now());
801   row7.set_created(Time::UnixEpoch());
802   EXPECT_TRUE(backend->InsertHistoryAndBookmark(row7));
803 }
804
805 TEST_F(AndroidProviderBackendTest, UpdateURL) {
806   HistoryAndBookmarkRow row1;
807   row1.set_raw_url("cnn.com");
808   row1.set_url(GURL("http://cnn.com"));
809   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
810   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
811   row1.set_visit_count(10);
812   row1.set_is_bookmark(true);
813   row1.set_title(UTF8ToUTF16("cnn"));
814
815   HistoryAndBookmarkRow row2;
816   row2.set_raw_url("http://www.example.com");
817   row2.set_url(GURL("http://www.example.com"));
818   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
819   row2.set_is_bookmark(false);
820   row2.set_title(UTF8ToUTF16("example"));
821   std::vector<unsigned char> data;
822   data.push_back('1');
823   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
824
825   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
826   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
827   scoped_ptr<AndroidProviderBackend> backend(
828       new AndroidProviderBackend(android_cache_db_name_,
829                                  &history_db_,
830                                  &thumbnail_db_,
831                                  history_client_,
832                                  &delegate_));
833
834   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
835   ASSERT_TRUE(id1);
836   AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
837   ASSERT_TRUE(id2);
838
839   // Verify the row1 has been added in bookmark model.
840   content::RunAllPendingInMessageLoop();
841   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
842   const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
843   ASSERT_TRUE(child);
844   EXPECT_EQ(row1.title(), child->GetTitle());
845   EXPECT_EQ(row1.url(), child->url());
846
847   // Make sure the url has correctly insertted.
848   URLID url_id1 = history_db_.GetRowForURL(row1.url(), NULL);
849   ASSERT_TRUE(url_id1);
850   URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL);
851   ASSERT_TRUE(url_id2);
852
853   // Make sure we have the correct visit rows in visit table.
854   VisitVector visits;
855   ASSERT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
856   ASSERT_EQ(10u, visits.size());
857   visits.clear();
858   ASSERT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
859   ASSERT_EQ(1u, visits.size());
860
861   int update_count;
862   std::vector<base::string16> update_args;
863   // Try to update the mutiple rows with the same URL, this should failed.
864   HistoryAndBookmarkRow update_row1;
865   update_row1.set_raw_url("newwebiste.com");
866   update_row1.set_url(GURL("http://newwebsite.com"));
867   update_args.clear();
868   ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row1, std::string(),
869                                                   update_args, &update_count));
870
871   // Only update one URL.
872   update_args.clear();
873   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
874   delegate_.ResetDetails();
875   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
876                                                  update_args, &update_count));
877   // Verify notifications, Update involves insert and delete URLS.
878   ASSERT_TRUE(delegate_.deleted_details());
879   EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
880   EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url());
881   EXPECT_EQ(row1.last_visit_time(),
882             delegate_.deleted_details()->rows[0].last_visit());
883   EXPECT_EQ(row1.title(),
884             delegate_.deleted_details()->rows[0].title());
885   ASSERT_TRUE(delegate_.modified_details());
886   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
887   EXPECT_EQ(update_row1.url(),
888             delegate_.modified_details()->changed_urls[0].url());
889   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
890             ToDatabaseTime(
891                 delegate_.modified_details()->changed_urls[0].last_visit()));
892   EXPECT_EQ(row1.title(),
893             delegate_.modified_details()->changed_urls[0].title());
894   EXPECT_FALSE(delegate_.favicon_details());
895
896   EXPECT_EQ(1, update_count);
897   // We shouldn't find orignal url anymore.
898   EXPECT_FALSE(history_db_.GetRowForURL(row1.url(), NULL));
899   visits.clear();
900   EXPECT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
901   EXPECT_EQ(0u, visits.size());
902   // Verify new URL.
903   URLRow new_row;
904   EXPECT_TRUE(history_db_.GetRowForURL(update_row1.url(), &new_row));
905   EXPECT_EQ(10, new_row.visit_count());
906   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
907             ToDatabaseTime(new_row.last_visit()));
908   visits.clear();
909   EXPECT_TRUE(history_db_.GetVisitsForURL(new_row.id(), &visits));
910   EXPECT_EQ(10u, visits.size());
911   AndroidURLRow android_url_row1;
912   ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row.id(), &android_url_row1));
913   // Android URL ID shouldn't change.
914   EXPECT_EQ(id1, android_url_row1.id);
915
916   // Verify the bookmark model was updated.
917   content::RunAllPendingInMessageLoop();
918   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
919   const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0);
920   ASSERT_TRUE(child1);
921   EXPECT_EQ(row1.title(), child1->GetTitle());
922   EXPECT_EQ(update_row1.url(), child1->url());
923
924   // Update the URL with visit count, created time, and last visit time.
925   HistoryAndBookmarkRow update_row2;
926   update_row2.set_raw_url("somethingelse.com");
927   update_row2.set_url(GURL("http://somethingelse.com"));
928   update_row2.set_last_visit_time(Time::Now());
929   update_row2.set_created(Time::Now() - TimeDelta::FromDays(20));
930   update_row2.set_visit_count(10);
931
932   update_args.clear();
933   update_args.push_back(UTF8ToUTF16(row2.raw_url()));
934   delegate_.ResetDetails();
935   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
936                                                  update_args, &update_count));
937   // Verify notifications, Update involves insert and delete URLS.
938   ASSERT_TRUE(delegate_.deleted_details());
939   EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
940   EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url());
941   EXPECT_EQ(row2.last_visit_time(),
942             delegate_.deleted_details()->rows[0].last_visit());
943   EXPECT_EQ(row2.title(),
944             delegate_.deleted_details()->rows[0].title());
945   ASSERT_TRUE(delegate_.modified_details());
946   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
947   EXPECT_EQ(update_row2.url(),
948             delegate_.modified_details()->changed_urls[0].url());
949   EXPECT_EQ(ToDatabaseTime(update_row2.last_visit_time()),
950             ToDatabaseTime(
951                 delegate_.modified_details()->changed_urls[0].last_visit()));
952   EXPECT_EQ(update_row2.visit_count(),
953             delegate_.modified_details()->changed_urls[0].visit_count());
954   ASSERT_TRUE(delegate_.favicon_details());
955   ASSERT_EQ(2u, delegate_.favicon_details()->urls.size());
956   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
957               delegate_.favicon_details()->urls.find(row2.url()));
958   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
959               delegate_.favicon_details()->urls.find(update_row2.url()));
960
961   EXPECT_EQ(1, update_count);
962   // We shouldn't find orignal url anymore.
963   EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL));
964   visits.clear();
965   EXPECT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
966   EXPECT_EQ(0u, visits.size());
967
968   // Verify new URL.
969   URLRow new_row2;
970   ASSERT_TRUE(history_db_.GetRowForURL(update_row2.url(), &new_row2));
971   EXPECT_EQ(10, new_row2.visit_count());
972   EXPECT_EQ(update_row2.last_visit_time(), new_row2.last_visit());
973   visits.clear();
974   EXPECT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
975   EXPECT_EQ(10u, visits.size());
976   AndroidURLRow android_url_row2;
977   ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row2.id(), &android_url_row2));
978   // Android URL ID shouldn't change.
979   EXPECT_EQ(id2, android_url_row2.id);
980
981   ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
982   ASSERT_EQ(10u, visits.size());
983   EXPECT_EQ(update_row2.created(), visits[0].visit_time);
984   EXPECT_EQ(update_row2.last_visit_time(), visits[9].visit_time);
985 }
986
987 TEST_F(AndroidProviderBackendTest, UpdateVisitCount) {
988   HistoryAndBookmarkRow row1;
989   row1.set_raw_url("cnn.com");
990   row1.set_url(GURL("http://cnn.com"));
991   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
992   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
993   row1.set_visit_count(10);
994   row1.set_is_bookmark(true);
995   row1.set_title(UTF8ToUTF16("cnn"));
996
997   HistoryAndBookmarkRow row2;
998   row2.set_raw_url("http://www.example.com");
999   row2.set_url(GURL("http://www.example.com"));
1000   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1001   row2.set_is_bookmark(false);
1002   row2.set_title(UTF8ToUTF16("example"));
1003   std::vector<unsigned char> data;
1004   data.push_back('1');
1005   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1006
1007   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1008   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1009   scoped_ptr<AndroidProviderBackend> backend(
1010       new AndroidProviderBackend(android_cache_db_name_,
1011                                  &history_db_,
1012                                  &thumbnail_db_,
1013                                  history_client_,
1014                                  &delegate_));
1015
1016   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1017   ASSERT_TRUE(id1);
1018   AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1019   ASSERT_TRUE(id2);
1020
1021   int update_count;
1022   std::vector<base::string16> update_args;
1023   // Update the visit_count to a value less than current one.
1024   HistoryAndBookmarkRow update_row1;
1025   update_row1.set_visit_count(5);
1026   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1027   delegate_.ResetDetails();
1028   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1029                                                  update_args, &update_count));
1030   // Verify notifications, Update involves modified URL.
1031   EXPECT_FALSE(delegate_.deleted_details());
1032   ASSERT_TRUE(delegate_.modified_details());
1033   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1034   EXPECT_EQ(row1.url(),
1035             delegate_.modified_details()->changed_urls[0].url());
1036   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1037             ToDatabaseTime(
1038                 delegate_.modified_details()->changed_urls[0].last_visit()));
1039   EXPECT_EQ(update_row1.visit_count(),
1040             delegate_.modified_details()->changed_urls[0].visit_count());
1041   EXPECT_FALSE(delegate_.favicon_details());
1042
1043   // All visits should be removed, and 5 new visit insertted.
1044   URLRow new_row1;
1045   ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1));
1046   EXPECT_EQ(5, new_row1.visit_count());
1047   VisitVector visits;
1048   ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits));
1049   ASSERT_EQ(5u, visits.size());
1050   EXPECT_EQ(row1.last_visit_time(), visits[4].visit_time);
1051   EXPECT_GT(row1.last_visit_time(), visits[0].visit_time);
1052
1053   // Update the visit_count to a value equal to current one.
1054   HistoryAndBookmarkRow update_row2;
1055   update_row2.set_visit_count(1);
1056   update_args.clear();
1057   update_args.push_back(UTF8ToUTF16(row2.raw_url()));
1058   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
1059                                                  update_args, &update_count));
1060   // All shouldn't have any change.
1061   URLRow new_row2;
1062   ASSERT_TRUE(history_db_.GetRowForURL(row2.url(), &new_row2));
1063   EXPECT_EQ(1, new_row2.visit_count());
1064
1065   ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
1066   ASSERT_EQ(1u, visits.size());
1067   EXPECT_EQ(row2.last_visit_time(), visits[0].visit_time);
1068 }
1069
1070 TEST_F(AndroidProviderBackendTest, UpdateLastVisitTime) {
1071   HistoryAndBookmarkRow row1;
1072   row1.set_raw_url("cnn.com");
1073   row1.set_url(GURL("http://cnn.com"));
1074   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1075   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1076   row1.set_visit_count(10);
1077   row1.set_is_bookmark(true);
1078   row1.set_title(UTF8ToUTF16("cnn"));
1079
1080   HistoryAndBookmarkRow row2;
1081   row2.set_raw_url("http://www.example.com");
1082   row2.set_url(GURL("http://www.example.com"));
1083   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1084   row2.set_is_bookmark(false);
1085   row2.set_title(UTF8ToUTF16("example"));
1086   std::vector<unsigned char> data;
1087   data.push_back('1');
1088   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1089
1090   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1091   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1092   scoped_ptr<AndroidProviderBackend> backend(
1093       new AndroidProviderBackend(android_cache_db_name_,
1094                                  &history_db_,
1095                                  &thumbnail_db_,
1096                                  history_client_,
1097                                  &delegate_));
1098
1099   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1100   ASSERT_TRUE(id1);
1101   AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1102   ASSERT_TRUE(id2);
1103
1104   int update_count;
1105   std::vector<base::string16> update_args;
1106   // Update the last visit time to a value greater than current one.
1107   HistoryAndBookmarkRow update_row1;
1108   update_row1.set_last_visit_time(Time::Now());
1109   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1110   delegate_.ResetDetails();
1111   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1112                                                  update_args, &update_count));
1113   // Verify notifications, Update involves modified URL.
1114   EXPECT_FALSE(delegate_.deleted_details());
1115   ASSERT_TRUE(delegate_.modified_details());
1116   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1117   EXPECT_EQ(row1.url(),
1118             delegate_.modified_details()->changed_urls[0].url());
1119   EXPECT_EQ(ToDatabaseTime(update_row1.last_visit_time()),
1120             ToDatabaseTime(
1121                 delegate_.modified_details()->changed_urls[0].last_visit()));
1122   EXPECT_FALSE(delegate_.favicon_details());
1123
1124   URLRow new_row1;
1125   ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1));
1126   EXPECT_EQ(11, new_row1.visit_count());
1127   EXPECT_EQ(update_row1.last_visit_time(), new_row1.last_visit());
1128   VisitVector visits;
1129   ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits));
1130   // 1 new visit insertted.
1131   ASSERT_EQ(11u, visits.size());
1132   EXPECT_EQ(update_row1.last_visit_time(), visits[10].visit_time);
1133   EXPECT_EQ(row1.last_visit_time(), visits[9].visit_time);
1134
1135   // Update the visit_tim to a value less than to current one.
1136   HistoryAndBookmarkRow update_row2;
1137   update_row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1138   update_args.clear();
1139   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1140   ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
1141                                                   update_args, &update_count));
1142 }
1143
1144 TEST_F(AndroidProviderBackendTest, UpdateFavicon) {
1145   HistoryAndBookmarkRow row1;
1146   row1.set_raw_url("cnn.com");
1147   row1.set_url(GURL("http://cnn.com"));
1148   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1149   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1150   row1.set_visit_count(10);
1151   row1.set_is_bookmark(true);
1152   row1.set_title(UTF8ToUTF16("cnn"));
1153
1154   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1155   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1156   scoped_ptr<AndroidProviderBackend> backend(
1157       new AndroidProviderBackend(android_cache_db_name_,
1158                                  &history_db_,
1159                                  &thumbnail_db_,
1160                                  history_client_,
1161                                  &delegate_));
1162
1163   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1164   ASSERT_TRUE(id1);
1165
1166   int update_count;
1167   std::vector<base::string16> update_args;
1168   // Update the last visit time to a value greater than current one.
1169   HistoryAndBookmarkRow update_row1;
1170
1171   // Set favicon.
1172   std::vector<unsigned char> data;
1173   data.push_back('1');
1174   update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data));
1175   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1176   delegate_.ResetDetails();
1177   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1178                                                  update_args, &update_count));
1179   // Verify notifications.
1180   EXPECT_FALSE(delegate_.deleted_details());
1181   EXPECT_FALSE(delegate_.modified_details());
1182   ASSERT_TRUE(delegate_.favicon_details());
1183   ASSERT_EQ(1u, delegate_.favicon_details()->urls.size());
1184   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
1185               delegate_.favicon_details()->urls.find(row1.url()));
1186
1187   std::vector<IconMapping> icon_mappings;
1188   EXPECT_TRUE(thumbnail_db_.GetIconMappingsForPageURL(
1189       row1.url(), favicon_base::FAVICON, &icon_mappings));
1190   EXPECT_EQ(1u, icon_mappings.size());
1191   std::vector<FaviconBitmap> favicon_bitmaps;
1192   EXPECT_TRUE(thumbnail_db_.GetFaviconBitmaps(icon_mappings[0].icon_id,
1193                                               &favicon_bitmaps));
1194   EXPECT_EQ(1u, favicon_bitmaps.size());
1195   EXPECT_TRUE(favicon_bitmaps[0].bitmap_data.get());
1196   EXPECT_EQ(1u, favicon_bitmaps[0].bitmap_data->size());
1197   EXPECT_EQ('1', *favicon_bitmaps[0].bitmap_data->front());
1198
1199   // Remove favicon.
1200   HistoryAndBookmarkRow update_row2;
1201
1202   // Set favicon.
1203   update_row1.set_favicon(new base::RefCountedBytes());
1204   update_args.clear();
1205   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1206   delegate_.ResetDetails();
1207   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1208                                                  update_args, &update_count));
1209   // Verify notifications.
1210   EXPECT_FALSE(delegate_.deleted_details());
1211   EXPECT_FALSE(delegate_.modified_details());
1212   ASSERT_TRUE(delegate_.favicon_details());
1213   ASSERT_EQ(1u, delegate_.favicon_details()->urls.size());
1214   ASSERT_TRUE(delegate_.favicon_details()->urls.end() !=
1215               delegate_.favicon_details()->urls.find(row1.url()));
1216
1217   EXPECT_FALSE(thumbnail_db_.GetIconMappingsForPageURL(
1218       row1.url(), favicon_base::FAVICON, NULL));
1219 }
1220
1221 TEST_F(AndroidProviderBackendTest, UpdateSearchTermTable) {
1222   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1223   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1224   scoped_ptr<AndroidProviderBackend> backend(
1225       new AndroidProviderBackend(android_cache_db_name_,
1226                                  &history_db_,
1227                                  &thumbnail_db_,
1228                                  history_client_,
1229                                  &delegate_));
1230   // Insert a keyword search item to verify if the update succeeds.
1231   HistoryAndBookmarkRow row1;
1232   row1.set_raw_url("cnn.com");
1233   row1.set_url(GURL("http://cnn.com"));
1234   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1235   row1.set_title(UTF8ToUTF16("cnn"));
1236   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1237   base::string16 term = UTF8ToUTF16("Search term 1");
1238   URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1239   ASSERT_TRUE(url_id);
1240   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1241   ASSERT_TRUE(backend->UpdateSearchTermTable());
1242   SearchTermRow keyword_cache;
1243   SearchTermID id = history_db_.GetSearchTerm(term, &keyword_cache);
1244   ASSERT_TRUE(id);
1245   EXPECT_EQ(term, keyword_cache.term);
1246   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1247             ToDatabaseTime(keyword_cache.last_visit_time));
1248
1249   // Add another row.
1250   HistoryAndBookmarkRow row2;
1251   row2.set_raw_url("google.com");
1252   row2.set_url(GURL("http://google.com"));
1253   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(2));
1254   row2.set_title(UTF8ToUTF16("cnn"));
1255   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1256   url_id = history_db_.GetRowForURL(row2.url(), NULL);
1257   ASSERT_TRUE(url_id);
1258   base::string16 term2 = UTF8ToUTF16("Search term 2");
1259   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term2));
1260   ASSERT_TRUE(backend->UpdateSearchTermTable());
1261   SearchTermID search_id1 = history_db_.GetSearchTerm(term,
1262                                                            &keyword_cache);
1263   // The id shouldn't changed.
1264   ASSERT_EQ(id, search_id1);
1265   EXPECT_EQ(term, keyword_cache.term);
1266   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1267             ToDatabaseTime(keyword_cache.last_visit_time));
1268   // Verify the row just inserted.
1269   SearchTermID id2 = history_db_.GetSearchTerm(term2, &keyword_cache);
1270   ASSERT_TRUE(id2);
1271   EXPECT_EQ(term2, keyword_cache.term);
1272   EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
1273             ToDatabaseTime(keyword_cache.last_visit_time));
1274
1275   // Add 3rd row and associate it with term.
1276   HistoryAndBookmarkRow row3;
1277   row3.set_raw_url("search.com");
1278   row3.set_url(GURL("http://search.com"));
1279   row3.set_last_visit_time(Time::Now());
1280   row3.set_title(UTF8ToUTF16("search"));
1281   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row3));
1282   url_id = history_db_.GetRowForURL(row3.url(), NULL);
1283   ASSERT_TRUE(url_id);
1284   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1285   ASSERT_TRUE(backend->UpdateSearchTermTable());
1286   // Verify id not changed and last_visit_time updated.
1287   ASSERT_EQ(search_id1, history_db_.GetSearchTerm(term, &keyword_cache));
1288   EXPECT_EQ(ToDatabaseTime(row3.last_visit_time()),
1289             ToDatabaseTime(keyword_cache.last_visit_time));
1290   // The id of term2 wasn't changed.
1291   EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL));
1292
1293   // Remove the term.
1294   ASSERT_TRUE(history_db_.DeleteKeywordSearchTerm(term));
1295   ASSERT_TRUE(backend->UpdateSearchTermTable());
1296   // The cache of term should removed.
1297   ASSERT_FALSE(history_db_.GetSearchTerm(term, NULL));
1298   // The id of term2 wasn't changed.
1299   EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL));
1300 }
1301
1302 TEST_F(AndroidProviderBackendTest, QuerySearchTerms) {
1303   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1304   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1305   scoped_ptr<AndroidProviderBackend> backend(
1306       new AndroidProviderBackend(android_cache_db_name_,
1307                                  &history_db_,
1308                                  &thumbnail_db_,
1309                                  history_client_,
1310                                  &delegate_));
1311   // Insert a keyword search item to verify if we can find it.
1312   HistoryAndBookmarkRow row1;
1313   row1.set_raw_url("cnn.com");
1314   row1.set_url(GURL("http://cnn.com"));
1315   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1316   row1.set_title(UTF8ToUTF16("cnn"));
1317   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1318   base::string16 term = UTF8ToUTF16("Search term 1");
1319   URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1320   ASSERT_TRUE(url_id);
1321   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1322
1323   std::vector<SearchRow::ColumnID> projections;
1324   projections.push_back(SearchRow::ID);
1325   projections.push_back(SearchRow::SEARCH_TERM);
1326   projections.push_back(SearchRow::SEARCH_TIME);
1327   scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1328       projections, std::string(), std::vector<base::string16>(),
1329       std::string()));
1330   ASSERT_TRUE(statement.get());
1331   ASSERT_TRUE(statement->statement()->Step());
1332   EXPECT_TRUE(statement->statement()->ColumnInt64(0));
1333   EXPECT_EQ(term, statement->statement()->ColumnString16(1));
1334   EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1335             statement->statement()->ColumnInt64(2));
1336   EXPECT_FALSE(statement->statement()->Step());
1337 }
1338
1339 TEST_F(AndroidProviderBackendTest, UpdateSearchTerms) {
1340   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1341   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1342   scoped_ptr<AndroidProviderBackend> backend(
1343       new AndroidProviderBackend(android_cache_db_name_,
1344                                  &history_db_,
1345                                  &thumbnail_db_,
1346                                  history_client_,
1347                                  &delegate_));
1348   // Insert a keyword.
1349   HistoryAndBookmarkRow row1;
1350   row1.set_raw_url("cnn.com");
1351   row1.set_url(GURL("http://cnn.com"));
1352   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1353   row1.set_title(UTF8ToUTF16("cnn"));
1354   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1355   base::string16 term = UTF8ToUTF16("Search term 1");
1356   URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1357   ASSERT_TRUE(url_id);
1358   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1359
1360   // Get the SearchTermID of the row we just inserted.
1361   std::vector<SearchRow::ColumnID> projections;
1362   projections.push_back(SearchRow::ID);
1363   projections.push_back(SearchRow::SEARCH_TIME);
1364   projections.push_back(SearchRow::SEARCH_TERM);
1365   std::vector<base::string16> args;
1366   args.push_back(term);
1367   scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1368       projections, "search = ?", args, std::string()));
1369   ASSERT_TRUE(statement.get());
1370   ASSERT_TRUE(statement->statement()->Step());
1371   SearchTermID id = statement->statement()->ColumnInt64(0);
1372   ASSERT_TRUE(id);
1373   EXPECT_FALSE(statement->statement()->Step());
1374
1375   // Update the search term and time.
1376   base::string16 update_term = UTF8ToUTF16("Update search term");
1377   args.clear();
1378   args.push_back(term);
1379   SearchRow search_row;
1380   search_row.set_search_term(update_term);
1381   search_row.set_url(GURL("http://google.com"));
1382   search_row.set_template_url_id(1);
1383   search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1));
1384   int update_count = 0;
1385   ASSERT_TRUE(backend->UpdateSearchTerms(search_row, "search = ?", args,
1386                                          &update_count));
1387   EXPECT_EQ(1, update_count);
1388
1389   // Verify if the search term updated.
1390   // The origin term should be removed.
1391   std::vector<KeywordSearchTermRow> rows;
1392   ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows));
1393   EXPECT_TRUE(rows.empty());
1394   // The new term should be inserted.
1395   ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(update_term, &rows));
1396   ASSERT_EQ(1u, rows.size());
1397   // The history of urls shouldn't be removed.
1398   ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), NULL));
1399   // The new URL is inserted.
1400   ASSERT_TRUE(history_db_.GetRowForURL(search_row.url(), NULL));
1401
1402   // Verfiy the AndoridSearchID isn't changed.
1403   args.clear();
1404   args.push_back(update_term);
1405   statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
1406                                             std::string()));
1407   ASSERT_TRUE(statement.get());
1408   ASSERT_TRUE(statement->statement()->Step());
1409   // The id didn't change.
1410   EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1411   // The search time was updated.
1412   EXPECT_EQ(ToDatabaseTime(search_row.search_time()),
1413             statement->statement()->ColumnInt64(1));
1414   // The search term was updated.
1415   EXPECT_EQ(update_term, statement->statement()->ColumnString16(2));
1416   EXPECT_FALSE(statement->statement()->Step());
1417
1418   // Only update the search time.
1419   SearchRow update_time;
1420   update_time.set_search_time(Time::Now());
1421   // Update it by id.
1422   args.clear();
1423   std::ostringstream oss;
1424   oss << id;
1425   args.push_back(UTF8ToUTF16(oss.str()));
1426   update_count = 0;
1427   ASSERT_TRUE(backend->UpdateSearchTerms(update_time, "_id = ?", args,
1428                                          &update_count));
1429   EXPECT_EQ(1, update_count);
1430
1431   // Verify the update.
1432   statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1433                                             std::string()));
1434   ASSERT_TRUE(statement.get());
1435   ASSERT_TRUE(statement->statement()->Step());
1436   // The id didn't change.
1437   EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1438   // The search time was updated.
1439   EXPECT_EQ(ToDatabaseTime(update_time.search_time()),
1440             statement->statement()->ColumnInt64(1));
1441   // The search term didn't change.
1442   EXPECT_EQ(update_term, statement->statement()->ColumnString16(2));
1443   EXPECT_FALSE(statement->statement()->Step());
1444 }
1445
1446 TEST_F(AndroidProviderBackendTest, DeleteSearchTerms) {
1447   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1448   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1449   scoped_ptr<AndroidProviderBackend> backend(
1450       new AndroidProviderBackend(android_cache_db_name_,
1451                                  &history_db_,
1452                                  &thumbnail_db_,
1453                                  history_client_,
1454                                  &delegate_));
1455   // Insert a keyword.
1456   HistoryAndBookmarkRow row1;
1457   row1.set_raw_url("cnn.com");
1458   row1.set_url(GURL("http://cnn.com"));
1459   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1460   row1.set_title(UTF8ToUTF16("cnn"));
1461   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1462   base::string16 term = UTF8ToUTF16("Search term 1");
1463   URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1464   ASSERT_TRUE(url_id);
1465   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1466
1467   // Get the SearchTermID of the row we just inserted.
1468   std::vector<SearchRow::ColumnID> projections;
1469   projections.push_back(SearchRow::ID);
1470   projections.push_back(SearchRow::SEARCH_TIME);
1471   projections.push_back(SearchRow::SEARCH_TERM);
1472   std::vector<base::string16> args;
1473   args.push_back(term);
1474   scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1475       projections, "search = ?", args, std::string()));
1476   ASSERT_TRUE(statement.get());
1477   ASSERT_TRUE(statement->statement()->Step());
1478   SearchTermID id1 = statement->statement()->ColumnInt64(0);
1479   ASSERT_TRUE(id1);
1480   EXPECT_FALSE(statement->statement()->Step());
1481
1482   // Insert a keyword.
1483   HistoryAndBookmarkRow row2;
1484   row2.set_raw_url("google.com");
1485   row2.set_url(GURL("http://google.com"));
1486   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1487   row2.set_title(UTF8ToUTF16("google"));
1488   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1489   base::string16 term2 = UTF8ToUTF16("Search term 2");
1490   URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL);
1491   ASSERT_TRUE(url_id2);
1492   ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id2, 1, term2));
1493
1494   // Get the SearchTermID of the row we just inserted.
1495   projections.clear();
1496   projections.push_back(SearchRow::ID);
1497   projections.push_back(SearchRow::SEARCH_TIME);
1498   projections.push_back(SearchRow::SEARCH_TERM);
1499   args.clear();
1500   args.push_back(term2);
1501   statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
1502                                             std::string()));
1503   ASSERT_TRUE(statement.get());
1504   ASSERT_TRUE(statement->statement()->Step());
1505   SearchTermID id2 = statement->statement()->ColumnInt64(0);
1506   ASSERT_TRUE(id2);
1507   EXPECT_FALSE(statement->statement()->Step());
1508
1509   // Delete the first one.
1510   args.clear();
1511   args.push_back(term);
1512   int deleted_count = 0;
1513   ASSERT_TRUE(backend->DeleteSearchTerms("search = ?", args, &deleted_count));
1514   EXPECT_EQ(1, deleted_count);
1515   std::vector<KeywordSearchTermRow> rows;
1516   ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows));
1517   EXPECT_TRUE(rows.empty());
1518   // Verify we can't get the first term.
1519   args.clear();
1520   std::ostringstream oss;
1521   oss << id1;
1522   args.push_back(UTF8ToUTF16(oss.str()));
1523   statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1524                                             std::string()));
1525   ASSERT_TRUE(statement.get());
1526   EXPECT_FALSE(statement->statement()->Step());
1527
1528   // The second one is still there.
1529   args.clear();
1530   std::ostringstream oss1;
1531   oss1 << id2;
1532   args.push_back(UTF8ToUTF16(oss1.str()));
1533   statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1534                                             std::string()));
1535   ASSERT_TRUE(statement.get());
1536   EXPECT_TRUE(statement->statement()->Step());
1537   EXPECT_EQ(id2, statement->statement()->ColumnInt64(0));
1538   EXPECT_FALSE(statement->statement()->Step());
1539
1540   // Remove all search terms in no condition.
1541   deleted_count = 0;
1542   args.clear();
1543   ASSERT_TRUE(backend->DeleteSearchTerms(std::string(), args, &deleted_count));
1544   EXPECT_EQ(1, deleted_count);
1545
1546   // Verify the second one was removed.
1547   args.clear();
1548   args.push_back(UTF8ToUTF16(oss1.str()));
1549   statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1550                                             std::string()));
1551   ASSERT_TRUE(statement.get());
1552   EXPECT_FALSE(statement->statement()->Step());
1553 }
1554
1555 TEST_F(AndroidProviderBackendTest, InsertSearchTerm) {
1556   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1557   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1558   scoped_ptr<AndroidProviderBackend> backend(
1559       new AndroidProviderBackend(android_cache_db_name_,
1560                                  &history_db_,
1561                                  &thumbnail_db_,
1562                                  history_client_,
1563                                  &delegate_));
1564   SearchRow search_row;
1565   search_row.set_search_term(UTF8ToUTF16("google"));
1566   search_row.set_url(GURL("http://google.com"));
1567   search_row.set_template_url_id(1);
1568   search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1));
1569
1570   SearchTermID id = backend->InsertSearchTerm(search_row);
1571   ASSERT_TRUE(id);
1572
1573   std::vector<SearchRow::ColumnID> projections;
1574   projections.push_back(SearchRow::ID);
1575   projections.push_back(SearchRow::SEARCH_TIME);
1576   projections.push_back(SearchRow::SEARCH_TERM);
1577   std::vector<base::string16> args;
1578   std::ostringstream oss;
1579   oss << id;
1580   args.push_back(UTF8ToUTF16(oss.str()));
1581   scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1582       projections, "_id = ?", args, std::string()));
1583   ASSERT_TRUE(statement.get());
1584   ASSERT_TRUE(statement->statement()->Step());
1585   EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1586   EXPECT_EQ(ToDatabaseTime(search_row.search_time()),
1587             statement->statement()->ColumnInt64(1));
1588   EXPECT_EQ(search_row.search_term(),
1589             statement->statement()->ColumnString16(2));
1590   EXPECT_FALSE(statement->statement()->Step());
1591 }
1592
1593 TEST_F(AndroidProviderBackendTest, DeleteHistory) {
1594   HistoryAndBookmarkRow row1;
1595   row1.set_raw_url("cnn.com");
1596   row1.set_url(GURL("http://cnn.com"));
1597   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1598   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1599   row1.set_visit_count(10);
1600   row1.set_is_bookmark(true);
1601   row1.set_title(UTF8ToUTF16("cnn"));
1602
1603   HistoryAndBookmarkRow row2;
1604   row2.set_raw_url("http://www.example.com");
1605   row2.set_url(GURL("http://www.example.com"));
1606   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1607   row2.set_is_bookmark(false);
1608   row2.set_title(UTF8ToUTF16("example"));
1609   std::vector<unsigned char> data;
1610   data.push_back('1');
1611   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1612
1613   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1614   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1615   scoped_ptr<AndroidProviderBackend> backend(
1616       new AndroidProviderBackend(android_cache_db_name_,
1617                                  &history_db_,
1618                                  &thumbnail_db_,
1619                                  history_client_,
1620                                  &delegate_));
1621
1622   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1623   ASSERT_TRUE(id1);
1624   AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1625   ASSERT_TRUE(id2);
1626
1627   // Verify the row1 has been added in bookmark model.
1628   content::RunAllPendingInMessageLoop();
1629   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1630   const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
1631   ASSERT_TRUE(child);
1632   EXPECT_EQ(row1.title(), child->GetTitle());
1633   EXPECT_EQ(row1.url(), child->url());
1634
1635   // Delete history
1636   int deleted_count = 0;
1637   ASSERT_TRUE(backend->DeleteHistory(std::string(),
1638                                      std::vector<base::string16>(),
1639                                      &deleted_count));
1640   EXPECT_EQ(2, deleted_count);
1641   // The row2 was deleted.
1642   EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL));
1643   // Still find the row1.
1644   URLRow url_row;
1645   ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &url_row));
1646   // The visit_count was reset.
1647   EXPECT_EQ(0, url_row.visit_count());
1648   EXPECT_EQ(Time::UnixEpoch(), url_row.last_visit());
1649
1650   // Verify the row1 is still in bookmark model.
1651   content::RunAllPendingInMessageLoop();
1652   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1653   const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0);
1654   ASSERT_TRUE(child1);
1655   EXPECT_EQ(row1.title(), child1->GetTitle());
1656   EXPECT_EQ(row1.url(), child1->url());
1657
1658   // Verify notification
1659   ASSERT_TRUE(delegate_.deleted_details());
1660   ASSERT_EQ(2u, delegate_.deleted_details()->rows.size());
1661   EXPECT_EQ(row1.url(),
1662             delegate_.modified_details()->changed_urls[0].url());
1663   EXPECT_EQ(Time::UnixEpoch(),
1664             delegate_.modified_details()->changed_urls[0].last_visit());
1665   EXPECT_EQ(1u, delegate_.favicon_details()->urls.size());
1666 }
1667
1668 TEST_F(AndroidProviderBackendTest, TestMultipleNestingTransaction) {
1669   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1670   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1671   scoped_ptr<AndroidProviderBackend> backend(
1672       new AndroidProviderBackend(android_cache_db_name_,
1673                                  &history_db_,
1674                                  &thumbnail_db_,
1675                                  history_client_,
1676                                  &delegate_));
1677
1678   // Create the nested transactions.
1679   history_db_.BeginTransaction();
1680   history_db_.BeginTransaction();
1681   history_db_.BeginTransaction();
1682   thumbnail_db_.BeginTransaction();
1683   thumbnail_db_.BeginTransaction();
1684   int history_transaction = history_db_.transaction_nesting();
1685   int thumbnail_transaction = thumbnail_db_.transaction_nesting();
1686
1687   // Insert a row to verify the transaction number are not changed
1688   // after a transaction commit.
1689   HistoryAndBookmarkRow row1;
1690   row1.set_raw_url("cnn.com");
1691   row1.set_url(GURL("http://cnn.com"));
1692   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1693   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1694   row1.set_visit_count(10);
1695   row1.set_title(UTF8ToUTF16("cnn"));
1696   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1697   EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1698   EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1699
1700   // Insert the same URL, it should failed. The transaction are still same
1701   // after a rollback.
1702   ASSERT_FALSE(backend->InsertHistoryAndBookmark(row1));
1703   EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1704   EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1705
1706   // Insert another row to verify we are still fine after the previous
1707   // rollback.
1708   HistoryAndBookmarkRow row2;
1709   row2.set_raw_url("http://www.example.com");
1710   row2.set_url(GURL("http://www.example.com"));
1711   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1712   row2.set_is_bookmark(false);
1713   row2.set_title(UTF8ToUTF16("example"));
1714   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1715   EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1716   EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1717 }
1718
1719 TEST_F(AndroidProviderBackendTest, TestAndroidCTSComplianceForZeroVisitCount) {
1720   // This is to verify the last visit time and created time are same when visit
1721   // count is 0.
1722   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1723   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1724   scoped_ptr<AndroidProviderBackend> backend(
1725       new AndroidProviderBackend(android_cache_db_name_,
1726                                  &history_db_,
1727                                  &thumbnail_db_,
1728                                  history_client_,
1729                                  &delegate_));
1730   URLRow url_row(GURL("http://www.google.com"));
1731   url_row.set_last_visit(Time::Now());
1732   url_row.set_visit_count(0);
1733   history_db_.AddURL(url_row);
1734
1735   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1736
1737   projections.push_back(HistoryAndBookmarkRow::ID);
1738   projections.push_back(HistoryAndBookmarkRow::URL);
1739   projections.push_back(HistoryAndBookmarkRow::TITLE);
1740   projections.push_back(HistoryAndBookmarkRow::CREATED);
1741   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
1742   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
1743   projections.push_back(HistoryAndBookmarkRow::FAVICON);
1744   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
1745
1746   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1747       projections, std::string(), std::vector<base::string16>(),
1748       std::string("url ASC")));
1749
1750   ASSERT_TRUE(statement->statement()->Step());
1751   EXPECT_EQ(ToDatabaseTime(url_row.last_visit()),
1752             statement->statement()->ColumnInt64(3));
1753   EXPECT_EQ(ToDatabaseTime(url_row.last_visit()),
1754             statement->statement()->ColumnInt64(4));
1755   EXPECT_EQ(url_row.visit_count(), statement->statement()->ColumnInt(5));
1756 }
1757
1758 TEST_F(AndroidProviderBackendTest, AndroidCTSComplianceFolderColumnExists) {
1759   // This is test is used to verify the 'folder' column exists, all bookmarks
1760   // returned when folder is 0 and the non bookmark rows returned when folder
1761   // is 1.
1762   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1763   ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1764   scoped_ptr<AndroidProviderBackend> backend(
1765       new AndroidProviderBackend(android_cache_db_name_,
1766                                  &history_db_,
1767                                  &thumbnail_db_,
1768                                  history_client_,
1769                                  &delegate_));
1770   HistoryAndBookmarkRow row1;
1771   row1.set_raw_url("cnn.com");
1772   row1.set_url(GURL("http://cnn.com"));
1773   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1774   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1775   row1.set_visit_count(10);
1776   row1.set_is_bookmark(true);
1777   row1.set_title(UTF8ToUTF16("cnn"));
1778
1779   HistoryAndBookmarkRow row2;
1780   row2.set_raw_url("http://www.example.com");
1781   row2.set_url(GURL("http://www.example.com"));
1782   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1783   row2.set_is_bookmark(false);
1784   row2.set_title(UTF8ToUTF16("example"));
1785   std::vector<unsigned char> data;
1786   data.push_back('1');
1787   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1788
1789   AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1790   ASSERT_TRUE(id1);
1791   AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1792   ASSERT_TRUE(id2);
1793   content::RunAllPendingInMessageLoop();
1794
1795   // Query by folder=0, the row1 should returned.
1796   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1797
1798   projections.push_back(HistoryAndBookmarkRow::URL);
1799
1800   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1801       projections, std::string("folder=0"), std::vector<base::string16>(),
1802       std::string("url ASC")));
1803   ASSERT_TRUE(statement->statement()->Step());
1804   EXPECT_EQ(row1.raw_url(), statement->statement()->ColumnString(0));
1805   EXPECT_FALSE(statement->statement()->Step());
1806
1807   // Query by folder=1, the row2 should returned.
1808   statement.reset(backend->QueryHistoryAndBookmarks(
1809       projections, std::string("folder=1"), std::vector<base::string16>(),
1810       std::string("url ASC")));
1811   ASSERT_TRUE(statement->statement()->Step());
1812   EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(0)));
1813   EXPECT_FALSE(statement->statement()->Step());
1814 }
1815
1816 TEST_F(AndroidProviderBackendTest, QueryWithoutThumbnailDB) {
1817   GURL url1("http://www.cnn.com");
1818   URLID url_id1 = 0;
1819   const base::string16 title1(UTF8ToUTF16("cnn"));
1820   std::vector<VisitInfo> visits1;
1821   Time last_visited1 = Time::Now() - TimeDelta::FromDays(1);
1822   Time created1 = last_visited1 - TimeDelta::FromDays(20);
1823   visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK));
1824   visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
1825                               content::PAGE_TRANSITION_LINK));
1826   visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK));
1827
1828   GURL url2("http://www.example.com");
1829   URLID url_id2 = 0;
1830   std::vector<VisitInfo> visits2;
1831   const base::string16 title2(UTF8ToUTF16("example"));
1832   Time last_visited2 = Time::Now();
1833   Time created2 = last_visited2 - TimeDelta::FromDays(10);
1834   visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK));
1835   visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
1836                               content::PAGE_TRANSITION_LINK));
1837   visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK));
1838
1839   // Only use the HistoryBackend to generate the test data.
1840   // HistoryBackend will shutdown after that.
1841   {
1842   scoped_refptr<HistoryBackend> history_backend;
1843   history_backend = new HistoryBackend(
1844       temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
1845   history_backend->Init(std::string(), false);
1846   history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
1847   history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
1848   URLRow url_row;
1849
1850   ASSERT_TRUE(history_backend->GetURL(url1, &url_row));
1851   url_id1 = url_row.id();
1852   url_row.set_title(title1);
1853   ASSERT_TRUE(history_backend->UpdateURL(url_id1, url_row));
1854
1855   ASSERT_TRUE(history_backend->GetURL(url2, &url_row));
1856   url_id2 = url_row.id();
1857   url_row.set_title(title2);
1858   ASSERT_TRUE(history_backend->UpdateURL(url_id2, url_row));
1859
1860   // Set favicon to url2.
1861   std::vector<unsigned char> data;
1862   data.push_back('1');
1863   favicon_base::FaviconRawBitmapData bitmap_data_element;
1864   bitmap_data_element.bitmap_data = new base::RefCountedBytes(data);
1865   bitmap_data_element.pixel_size = gfx::Size();
1866   bitmap_data_element.icon_url = GURL();
1867   std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
1868   favicon_bitmap_data.push_back(bitmap_data_element);
1869
1870   history_backend->SetFavicons(
1871       url2, favicon_base::FAVICON, favicon_bitmap_data);
1872   history_backend->Closing();
1873   }
1874
1875   // The history_db_name and thumbnail_db_name files should be created by
1876   // HistoryBackend. We need to open the same database files.
1877   ASSERT_TRUE(base::PathExists(history_db_name_));
1878   ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
1879
1880   // Only creates the history database
1881   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1882
1883   // Set url1 as bookmark.
1884   AddBookmark(url1);
1885
1886   scoped_ptr<AndroidProviderBackend> backend(
1887       new AndroidProviderBackend(android_cache_db_name_,
1888                                  &history_db_,
1889                                  NULL,
1890                                  history_client_,
1891                                  &delegate_));
1892
1893   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1894
1895   projections.push_back(HistoryAndBookmarkRow::ID);
1896   projections.push_back(HistoryAndBookmarkRow::URL);
1897   projections.push_back(HistoryAndBookmarkRow::TITLE);
1898   projections.push_back(HistoryAndBookmarkRow::CREATED);
1899   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
1900   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
1901   projections.push_back(HistoryAndBookmarkRow::FAVICON);
1902   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
1903
1904   scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1905       projections, std::string(), std::vector<base::string16>(),
1906       std::string("url ASC")));
1907   ASSERT_TRUE(statement->statement()->Step());
1908   ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
1909   EXPECT_EQ(title1, statement->statement()->ColumnString16(2));
1910   EXPECT_EQ(ToDatabaseTime(created1),
1911             statement->statement()->ColumnInt64(3));
1912   EXPECT_EQ(ToDatabaseTime(last_visited1),
1913             statement->statement()->ColumnInt64(4));
1914   EXPECT_EQ(3, statement->statement()->ColumnInt(5));
1915   EXPECT_EQ(6, statement->favicon_index());
1916   // No favicon.
1917   EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
1918   EXPECT_TRUE(statement->statement()->ColumnBool(7));
1919
1920   ASSERT_TRUE(statement->statement()->Step());
1921   EXPECT_EQ(title2, statement->statement()->ColumnString16(2));
1922   ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
1923   EXPECT_EQ(ToDatabaseTime(created2),
1924             statement->statement()->ColumnInt64(3));
1925   EXPECT_EQ(ToDatabaseTime(last_visited2),
1926             statement->statement()->ColumnInt64(4));
1927   EXPECT_EQ(3, statement->statement()->ColumnInt(5));
1928   std::vector<unsigned char> favicon2;
1929   EXPECT_EQ(6, statement->favicon_index());
1930   // No favicon because thumbnail database wasn't initialized.
1931   EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
1932   EXPECT_FALSE(statement->statement()->ColumnBool(7));
1933
1934   // No more row.
1935   EXPECT_FALSE(statement->statement()->Step());
1936 }
1937
1938 TEST_F(AndroidProviderBackendTest, InsertWithoutThumbnailDB) {
1939   HistoryAndBookmarkRow row1;
1940   row1.set_raw_url("cnn.com");
1941   row1.set_url(GURL("http://cnn.com"));
1942   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1943   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1944   row1.set_visit_count(10);
1945   row1.set_is_bookmark(true);
1946   row1.set_title(UTF8ToUTF16("cnn"));
1947
1948   HistoryAndBookmarkRow row2;
1949   row2.set_raw_url("http://www.example.com");
1950   row2.set_url(GURL("http://www.example.com"));
1951   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1952   row2.set_is_bookmark(false);
1953   row2.set_title(UTF8ToUTF16("example"));
1954   std::vector<unsigned char> data;
1955   data.push_back('1');
1956   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1957
1958   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1959   scoped_ptr<AndroidProviderBackend> backend(
1960       new AndroidProviderBackend(android_cache_db_name_,
1961                                  &history_db_,
1962                                  NULL,
1963                                  history_client_,
1964                                  &delegate_));
1965
1966   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1967   EXPECT_FALSE(delegate_.deleted_details());
1968   ASSERT_TRUE(delegate_.modified_details());
1969   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1970   EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url());
1971   EXPECT_EQ(row1.last_visit_time(),
1972             delegate_.modified_details()->changed_urls[0].last_visit());
1973   EXPECT_EQ(row1.visit_count(),
1974             delegate_.modified_details()->changed_urls[0].visit_count());
1975   EXPECT_EQ(row1.title(),
1976             delegate_.modified_details()->changed_urls[0].title());
1977   EXPECT_FALSE(delegate_.favicon_details());
1978   content::RunAllPendingInMessageLoop();
1979   ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1980   const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
1981   ASSERT_TRUE(child);
1982   EXPECT_EQ(row1.title(), child->GetTitle());
1983   EXPECT_EQ(row1.url(), child->url());
1984
1985   delegate_.ResetDetails();
1986   ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1987   EXPECT_FALSE(delegate_.deleted_details());
1988   ASSERT_TRUE(delegate_.modified_details());
1989   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1990   EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url());
1991   EXPECT_EQ(row2.last_visit_time(),
1992             delegate_.modified_details()->changed_urls[0].last_visit());
1993   EXPECT_EQ(row2.title(),
1994             delegate_.modified_details()->changed_urls[0].title());
1995   // Favicon details is still false because thumbnail database wasn't
1996   // initialized, we ignore any changes of favicon.
1997   ASSERT_FALSE(delegate_.favicon_details());
1998 }
1999
2000 TEST_F(AndroidProviderBackendTest, DeleteWithoutThumbnailDB) {
2001   HistoryAndBookmarkRow row1;
2002   row1.set_raw_url("cnn.com");
2003   row1.set_url(GURL("http://cnn.com"));
2004   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
2005   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
2006   row1.set_visit_count(10);
2007   row1.set_is_bookmark(true);
2008   row1.set_title(UTF8ToUTF16("cnn"));
2009
2010   HistoryAndBookmarkRow row2;
2011   row2.set_raw_url("http://www.example.com");
2012   row2.set_url(GURL("http://www.example.com"));
2013   row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
2014   row2.set_is_bookmark(false);
2015   row2.set_title(UTF8ToUTF16("example"));
2016   std::vector<unsigned char> data;
2017   data.push_back('1');
2018   row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
2019
2020   {
2021     HistoryDatabase history_db;
2022     ThumbnailDatabase thumbnail_db;
2023     ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
2024     ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_));
2025
2026     scoped_ptr<AndroidProviderBackend> backend(
2027         new AndroidProviderBackend(android_cache_db_name_,
2028                                    &history_db,
2029                                    &thumbnail_db,
2030                                    history_client_,
2031                                    &delegate_));
2032
2033     ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
2034     ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
2035     // Verify the row1 has been added in bookmark model.
2036     content::RunAllPendingInMessageLoop();
2037     ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
2038     const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
2039     ASSERT_TRUE(child);
2040     EXPECT_EQ(row1.title(), child->GetTitle());
2041     EXPECT_EQ(row1.url(), child->url());
2042   }
2043   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2044   scoped_ptr<AndroidProviderBackend> backend(
2045       new AndroidProviderBackend(android_cache_db_name_,
2046                                  &history_db_,
2047                                  NULL,
2048                                  history_client_,
2049                                  &delegate_));
2050
2051   // Delete all rows.
2052   std::vector<base::string16> args;
2053   int deleted_count = 0;
2054   delegate_.ResetDetails();
2055   ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
2056                                                  &deleted_count));
2057   // All rows were deleted.
2058   EXPECT_EQ(2, deleted_count);
2059   // Verify the rows was removed from bookmark model.
2060   content::RunAllPendingInMessageLoop();
2061   ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count());
2062
2063   // Verify notifications
2064   ASSERT_TRUE(delegate_.deleted_details());
2065   EXPECT_FALSE(delegate_.modified_details());
2066   EXPECT_EQ(2u, delegate_.deleted_details()->rows.size());
2067   // No favicon has been deleted.
2068   EXPECT_FALSE(delegate_.favicon_details());
2069
2070   // No row exists.
2071   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
2072   projections.push_back(HistoryAndBookmarkRow::ID);
2073   projections.push_back(HistoryAndBookmarkRow::URL);
2074   projections.push_back(HistoryAndBookmarkRow::TITLE);
2075   projections.push_back(HistoryAndBookmarkRow::CREATED);
2076   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
2077   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
2078   projections.push_back(HistoryAndBookmarkRow::FAVICON);
2079   projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
2080
2081   scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks(
2082       projections, std::string(), std::vector<base::string16>(),
2083       std::string("url ASC")));
2084   ASSERT_FALSE(statement1->statement()->Step());
2085 }
2086
2087 TEST_F(AndroidProviderBackendTest, UpdateFaviconWithoutThumbnail) {
2088   HistoryAndBookmarkRow row1;
2089   row1.set_raw_url("cnn.com");
2090   row1.set_url(GURL("http://cnn.com"));
2091   row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
2092   row1.set_created(Time::Now() - TimeDelta::FromDays(20));
2093   row1.set_visit_count(10);
2094   row1.set_is_bookmark(true);
2095   row1.set_title(UTF8ToUTF16("cnn"));
2096
2097   {
2098     HistoryDatabase history_db;
2099     ThumbnailDatabase thumbnail_db;
2100     ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
2101     ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_));
2102     scoped_ptr<AndroidProviderBackend> backend(
2103         new AndroidProviderBackend(android_cache_db_name_,
2104                                    &history_db,
2105                                    &thumbnail_db,
2106                                    history_client_,
2107                                    &delegate_));
2108
2109     AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
2110     ASSERT_TRUE(id1);
2111   }
2112
2113   ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2114   scoped_ptr<AndroidProviderBackend> backend(
2115       new AndroidProviderBackend(android_cache_db_name_,
2116                                  &history_db_,
2117                                  NULL,
2118                                  history_client_,
2119                                  &delegate_));
2120
2121   int update_count;
2122   std::vector<base::string16> update_args;
2123   // Update the last visit time to a value greater than current one.
2124   HistoryAndBookmarkRow update_row1;
2125
2126   // Set visit count.
2127   update_row1.set_visit_count(5);
2128   // Set favicon.
2129   std::vector<unsigned char> data;
2130   data.push_back('1');
2131   update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data));
2132   update_args.push_back(UTF8ToUTF16(row1.raw_url()));
2133   delegate_.ResetDetails();
2134   ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
2135                                                  update_args, &update_count));
2136   // Verify notifications.
2137   EXPECT_FALSE(delegate_.deleted_details());
2138   ASSERT_TRUE(delegate_.modified_details());
2139   ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
2140   // No favicon will be updated as thumbnail database is missing.
2141   EXPECT_FALSE(delegate_.favicon_details());
2142 }
2143
2144 }  // namespace history