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