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