Home | History | Annotate | Download | only in history
      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 <algorithm>
      6 #include <vector>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/command_line.h"
     10 #include "base/files/file_path.h"
     11 #include "base/files/scoped_temp_dir.h"
     12 #include "base/memory/ref_counted_memory.h"
     13 #include "base/path_service.h"
     14 #include "chrome/browser/history/history_database.h"
     15 #include "chrome/browser/history/history_unittest_base.h"
     16 #include "chrome/browser/history/thumbnail_database.h"
     17 #include "chrome/common/chrome_constants.h"
     18 #include "chrome/common/chrome_paths.h"
     19 #include "chrome/common/thumbnail_score.h"
     20 #include "chrome/test/base/testing_profile.h"
     21 #include "chrome/tools/profiles/thumbnail-inl.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "third_party/skia/include/core/SkBitmap.h"
     24 #include "ui/gfx/codec/jpeg_codec.h"
     25 #include "url/gurl.h"
     26 
     27 using base::Time;
     28 using base::TimeDelta;
     29 
     30 namespace history {
     31 
     32 namespace {
     33 
     34 // data we'll put into the thumbnail database
     35 static const unsigned char blob1[] =
     36     "12346102356120394751634516591348710478123649165419234519234512349134";
     37 static const unsigned char blob2[] =
     38     "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef";
     39 static const unsigned char blob3[] =
     40     "3716871354098370776510470746794707624107647054607467847164027";
     41 const double kBoringness = 0.25;
     42 const double kWorseBoringness = 0.50;
     43 const double kBetterBoringness = 0.10;
     44 const double kTotallyBoring = 1.0;
     45 
     46 const int64 kPage1 = 1234;
     47 
     48 const gfx::Size kSmallSize = gfx::Size(16, 16);
     49 const gfx::Size kLargeSize = gfx::Size(32, 32);
     50 
     51 }  // namespace
     52 
     53 class ThumbnailDatabaseTest : public testing::Test {
     54  public:
     55   ThumbnailDatabaseTest() {
     56   }
     57   virtual ~ThumbnailDatabaseTest() {
     58   }
     59 
     60  protected:
     61   virtual void SetUp() {
     62     // Get a temporary directory for the test DB files.
     63     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     64 
     65     file_name_ = temp_dir_.path().AppendASCII("TestThumbnails.db");
     66     new_file_name_ = temp_dir_.path().AppendASCII("TestFavicons.db");
     67     history_db_name_ = temp_dir_.path().AppendASCII("TestHistory.db");
     68     google_bitmap_.reset(
     69         gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
     70   }
     71 
     72   scoped_ptr<SkBitmap> google_bitmap_;
     73 
     74   base::ScopedTempDir temp_dir_;
     75   base::FilePath file_name_;
     76   base::FilePath new_file_name_;
     77   base::FilePath history_db_name_;
     78 };
     79 
     80 class IconMappingMigrationTest : public HistoryUnitTestBase {
     81  public:
     82   IconMappingMigrationTest() {
     83   }
     84   virtual ~IconMappingMigrationTest() {
     85   }
     86 
     87  protected:
     88   virtual void SetUp() {
     89     profile_.reset(new TestingProfile);
     90 
     91     base::FilePath data_path;
     92     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
     93     data_path = data_path.AppendASCII("History");
     94 
     95     history_db_name_ = profile_->GetPath().Append(chrome::kHistoryFilename);
     96     // Set up history and thumbnails as they would be before migration.
     97     ASSERT_NO_FATAL_FAILURE(
     98         ExecuteSQLScript(data_path.AppendASCII("history.20.sql"),
     99                          history_db_name_));
    100     thumbnail_db_name_ =
    101         profile_->GetPath().Append(chrome::kThumbnailsFilename);
    102     ASSERT_NO_FATAL_FAILURE(
    103         ExecuteSQLScript(data_path.AppendASCII("thumbnails.3.sql"),
    104                          thumbnail_db_name_));
    105   }
    106 
    107  protected:
    108   base::FilePath history_db_name_;
    109   base::FilePath thumbnail_db_name_;
    110 
    111  private:
    112   scoped_ptr<TestingProfile> profile_;
    113 };
    114 
    115 TEST_F(ThumbnailDatabaseTest, GetFaviconAfterMigrationToTopSites) {
    116   ThumbnailDatabase db;
    117   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    118   db.BeginTransaction();
    119 
    120   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    121   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    122 
    123   GURL url("http://google.com");
    124   chrome::FaviconID icon_id = db.AddFavicon(url, chrome::FAVICON);
    125   base::Time time = base::Time::Now();
    126   FaviconBitmapID bitmap1_id = db.AddFaviconBitmap(icon_id, favicon, time,
    127                                                    kSmallSize);
    128   FaviconBitmapID bitmap2_id = db.AddFaviconBitmap(icon_id, favicon, time,
    129                                                    kLargeSize);
    130   EXPECT_TRUE(db.RenameAndDropThumbnails(file_name_, new_file_name_));
    131   EXPECT_TRUE(db.IsLatestVersion());
    132 
    133   GURL url_out;
    134   chrome::IconType icon_type_out;
    135   EXPECT_TRUE(db.GetFaviconHeader(icon_id, &url_out, &icon_type_out));
    136 
    137   EXPECT_EQ(url, url_out);
    138   EXPECT_EQ(chrome::FAVICON, icon_type_out);
    139 
    140   std::vector<FaviconBitmap> favicon_bitmaps_out;
    141   EXPECT_TRUE(db.GetFaviconBitmaps(icon_id, &favicon_bitmaps_out));
    142   EXPECT_EQ(2u, favicon_bitmaps_out.size());
    143 
    144   FaviconBitmap favicon_bitmap1 = favicon_bitmaps_out[0];
    145   FaviconBitmap favicon_bitmap2 = favicon_bitmaps_out[1];
    146 
    147   // Favicon bitmaps do not need to be in particular order.
    148   if (favicon_bitmap1.bitmap_id == bitmap2_id) {
    149     FaviconBitmap tmp_favicon_bitmap = favicon_bitmap1;
    150     favicon_bitmap1 = favicon_bitmap2;
    151     favicon_bitmap2 = tmp_favicon_bitmap;
    152   }
    153 
    154   EXPECT_EQ(bitmap1_id, favicon_bitmap1.bitmap_id);
    155   EXPECT_EQ(icon_id, favicon_bitmap1.icon_id);
    156   EXPECT_EQ(time.ToInternalValue(),
    157             favicon_bitmap1.last_updated.ToInternalValue());
    158   EXPECT_EQ(data.size(), favicon_bitmap1.bitmap_data->size());
    159   EXPECT_TRUE(std::equal(data.begin(),
    160                          data.end(),
    161                          favicon_bitmap1.bitmap_data->front()));
    162   EXPECT_EQ(kSmallSize, favicon_bitmap1.pixel_size);
    163 
    164   EXPECT_EQ(bitmap2_id, favicon_bitmap2.bitmap_id);
    165   EXPECT_EQ(icon_id, favicon_bitmap2.icon_id);
    166   EXPECT_EQ(time.ToInternalValue(),
    167             favicon_bitmap2.last_updated.ToInternalValue());
    168   EXPECT_EQ(data.size(), favicon_bitmap2.bitmap_data->size());
    169   EXPECT_TRUE(std::equal(data.begin(),
    170                          data.end(),
    171                          favicon_bitmap2.bitmap_data->front()));
    172   EXPECT_EQ(kLargeSize, favicon_bitmap2.pixel_size);
    173 }
    174 
    175 TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
    176   ThumbnailDatabase db;
    177   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    178   db.BeginTransaction();
    179 
    180   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    181   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    182 
    183   GURL url("http://google.com");
    184   base::Time time = base::Time::Now();
    185   chrome::FaviconID id = db.AddFavicon(url,
    186                                        chrome::TOUCH_ICON,
    187                                        favicon,
    188                                        time,
    189                                        gfx::Size());
    190   EXPECT_NE(0, id);
    191 
    192   EXPECT_NE(0, db.AddIconMapping(url, id));
    193   std::vector<IconMapping> icon_mappings;
    194   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings));
    195   EXPECT_EQ(1u, icon_mappings.size());
    196   EXPECT_EQ(url, icon_mappings.front().page_url);
    197   EXPECT_EQ(id, icon_mappings.front().icon_id);
    198 }
    199 
    200 TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) {
    201   ThumbnailDatabase db;
    202   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    203   db.BeginTransaction();
    204 
    205   GURL url("http://google.com");
    206   chrome::FaviconID id =
    207       db.AddFavicon(url, chrome::TOUCH_ICON);
    208 
    209   EXPECT_LT(0, db.AddIconMapping(url, id));
    210   std::vector<IconMapping> icon_mapping;
    211   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    212   ASSERT_EQ(1u, icon_mapping.size());
    213   EXPECT_EQ(url, icon_mapping.front().page_url);
    214   EXPECT_EQ(id, icon_mapping.front().icon_id);
    215 
    216   GURL url1("http://www.google.com/");
    217   chrome::FaviconID new_id =
    218       db.AddFavicon(url1, chrome::TOUCH_ICON);
    219   EXPECT_TRUE(db.UpdateIconMapping(icon_mapping.front().mapping_id, new_id));
    220 
    221   icon_mapping.clear();
    222   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    223   ASSERT_EQ(1u, icon_mapping.size());
    224   EXPECT_EQ(url, icon_mapping.front().page_url);
    225   EXPECT_EQ(new_id, icon_mapping.front().icon_id);
    226   EXPECT_NE(id, icon_mapping.front().icon_id);
    227 }
    228 
    229 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) {
    230   ThumbnailDatabase db;
    231   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    232   db.BeginTransaction();
    233 
    234   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    235   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    236 
    237   GURL url("http://google.com");
    238   chrome::FaviconID id =
    239       db.AddFavicon(url, chrome::TOUCH_ICON);
    240   base::Time time = base::Time::Now();
    241   db.AddFaviconBitmap(id, favicon, time, gfx::Size());
    242   EXPECT_LT(0, db.AddIconMapping(url, id));
    243 
    244   chrome::FaviconID id2 =
    245       db.AddFavicon(url, chrome::FAVICON);
    246   EXPECT_LT(0, db.AddIconMapping(url, id2));
    247   ASSERT_NE(id, id2);
    248 
    249   std::vector<IconMapping> icon_mapping;
    250   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    251   ASSERT_EQ(2u, icon_mapping.size());
    252   EXPECT_EQ(icon_mapping.front().icon_type, chrome::TOUCH_ICON);
    253   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, chrome::FAVICON, NULL));
    254 
    255   db.DeleteIconMappings(url);
    256 
    257   EXPECT_FALSE(db.GetIconMappingsForPageURL(url, NULL));
    258   EXPECT_FALSE(db.GetIconMappingsForPageURL(url, chrome::FAVICON, NULL));
    259 }
    260 
    261 TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
    262   ThumbnailDatabase db;
    263   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    264   db.BeginTransaction();
    265 
    266   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    267   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    268 
    269   GURL url("http://google.com");
    270 
    271   chrome::FaviconID id1 = db.AddFavicon(url, chrome::TOUCH_ICON);
    272   base::Time time = base::Time::Now();
    273   db.AddFaviconBitmap(id1, favicon, time, kSmallSize);
    274   db.AddFaviconBitmap(id1, favicon, time, kLargeSize);
    275   EXPECT_LT(0, db.AddIconMapping(url, id1));
    276 
    277   chrome::FaviconID id2 = db.AddFavicon(url, chrome::FAVICON);
    278   EXPECT_NE(id1, id2);
    279   db.AddFaviconBitmap(id2, favicon, time, kSmallSize);
    280   EXPECT_LT(0, db.AddIconMapping(url, id2));
    281 
    282   std::vector<IconMapping> icon_mappings;
    283   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings));
    284   ASSERT_EQ(2u, icon_mappings.size());
    285   EXPECT_EQ(id1, icon_mappings[0].icon_id);
    286   EXPECT_EQ(id2, icon_mappings[1].icon_id);
    287 }
    288 
    289 // Test upgrading database to version 4.
    290 TEST_F(ThumbnailDatabaseTest, UpgradeToVersion4) {
    291   ThumbnailDatabase db;
    292   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    293   db.BeginTransaction();
    294 
    295   const char* name = "favicons";
    296   std::string sql;
    297   sql.append("DROP TABLE IF EXISTS ");
    298   sql.append(name);
    299   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    300 
    301   sql.resize(0);
    302   sql.append("CREATE TABLE ");
    303   sql.append(name);
    304   sql.append("("
    305              "id INTEGER PRIMARY KEY,"
    306              "url LONGVARCHAR NOT NULL,"
    307              "last_updated INTEGER DEFAULT 0,"
    308              "image_data BLOB)");
    309   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    310 
    311   EXPECT_TRUE(db.UpgradeToVersion4());
    312 
    313   GURL url("http://google.com");
    314 
    315   sql::Statement statement;
    316   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    317       "INSERT INTO favicons (url, icon_type) VALUES (?, ?)"));
    318   statement.BindString(0, URLDatabase::GURLToDatabaseURL(url));
    319   statement.BindInt(1, chrome::TOUCH_ICON);
    320   EXPECT_TRUE(statement.Run());
    321 
    322   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    323       "SELECT icon_type FROM favicons"));
    324   EXPECT_TRUE(statement.Step());
    325 
    326   EXPECT_EQ(chrome::TOUCH_ICON,
    327             static_cast<chrome::IconType>(statement.ColumnInt(0)));
    328 }
    329 
    330 // Test upgrading database to version 5.
    331 TEST_F(ThumbnailDatabaseTest, UpgradeToVersion5) {
    332   ThumbnailDatabase db;
    333   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    334   db.BeginTransaction();
    335 
    336   const char* name = "favicons";
    337   std::string sql;
    338   sql.append("DROP TABLE IF EXISTS ");
    339   sql.append(name);
    340   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    341 
    342   sql.resize(0);
    343   sql.append("CREATE TABLE ");
    344   sql.append(name);
    345   sql.append("("
    346              "id INTEGER PRIMARY KEY,"
    347              "url LONGVARCHAR NOT NULL,"
    348              "last_updated INTEGER DEFAULT 0,"
    349              "image_data BLOB,"
    350              "icon_type INTEGER DEFAULT 1)");
    351   ASSERT_TRUE(db.db_.Execute(sql.c_str()));
    352 
    353   ASSERT_TRUE(db.UpgradeToVersion5());
    354 
    355   sql = "SELECT sizes FROM favicons";
    356   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    357 }
    358 
    359 // Test upgrading database to version 6.
    360 TEST_F(ThumbnailDatabaseTest, UpgradeToVersion6) {
    361   ThumbnailDatabase db;
    362   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    363   db.BeginTransaction();
    364 
    365   const char* name = "favicons";
    366   std::string sql;
    367   sql.append("DROP TABLE IF EXISTS ");
    368   sql.append(name);
    369   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    370 
    371   sql.clear();
    372   sql.append("CREATE TABLE ");
    373   sql.append(name);
    374   sql.append("("
    375              "id INTEGER PRIMARY KEY,"
    376              "url LONGVARCHAR NOT NULL,"
    377              "last_updated INTEGER DEFAULT 0,"
    378              "image_data BLOB,"
    379              "icon_type INTEGER DEFAULT 1,"
    380              "sizes LONGVARCHAR)");
    381   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    382 
    383   int favicon_id = 1;
    384   GURL url("http://google.com");
    385   int64 last_updated = Time::Now().ToInternalValue();
    386   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    387   scoped_refptr<base::RefCountedBytes> bitmap_data(
    388       new base::RefCountedBytes(data));
    389 
    390   sql::Statement statement;
    391   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    392       "INSERT INTO favicons (id, url, last_updated, image_data, icon_type, "
    393       "sizes) VALUES (?, ?, ?, ?, ?, ?)"));
    394   statement.BindInt(0, favicon_id);
    395   statement.BindString(1, URLDatabase::GURLToDatabaseURL(url));
    396   statement.BindInt64(2, last_updated);
    397   statement.BindBlob(3, bitmap_data->front(),
    398                      static_cast<int>(bitmap_data->size()));
    399   statement.BindInt(4, chrome::TOUCH_ICON);
    400   statement.BindCString(5, "Data which happened to be there");
    401   EXPECT_TRUE(statement.Run());
    402 
    403   EXPECT_TRUE(db.UpgradeToVersion6());
    404 
    405   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    406       "SELECT id, url, icon_type, sizes FROM favicons"));
    407   EXPECT_TRUE(statement.Step());
    408   EXPECT_EQ(favicon_id, statement.ColumnInt(0));
    409   EXPECT_EQ(url, GURL(statement.ColumnString(1)));
    410   EXPECT_EQ(chrome::TOUCH_ICON, statement.ColumnInt(2));
    411   // Any previous data in sizes should be cleared.
    412   EXPECT_EQ(std::string(), statement.ColumnString(3));
    413 
    414   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    415       "SELECT icon_id, last_updated, image_data, width, height "
    416       "FROM favicon_bitmaps"));
    417   EXPECT_TRUE(statement.Step());
    418   EXPECT_EQ(favicon_id, statement.ColumnInt(0));
    419   EXPECT_EQ(last_updated, statement.ColumnInt64(1));
    420   EXPECT_EQ(static_cast<int>(bitmap_data->size()),
    421             statement.ColumnByteLength(2));
    422   EXPECT_EQ(0, statement.ColumnInt(3));
    423   EXPECT_EQ(0, statement.ColumnInt(4));
    424 }
    425 
    426 // Test upgrading database to version 7.
    427 TEST_F(ThumbnailDatabaseTest, UpgradeToVersion7) {
    428   ThumbnailDatabase db;
    429   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    430   db.BeginTransaction();
    431 
    432   const char* name = "favicons";
    433   std::string sql;
    434   sql.append("DROP TABLE IF EXISTS ");
    435   sql.append(name);
    436   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    437 
    438   sql.clear();
    439   sql.append("CREATE TABLE ");
    440   sql.append(name);
    441   sql.append("("
    442              "id INTEGER PRIMARY KEY,"
    443              "url LONGVARCHAR NOT NULL,"
    444              "icon_type INTEGER DEFAULT 1,"
    445              "sizes LONGVARCHAR)");
    446   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    447 
    448   int favicon_id = 1;
    449   GURL url("http://google.com");
    450 
    451   sql::Statement statement;
    452   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    453       "INSERT INTO favicons (id, url, icon_type, sizes) "
    454       "VALUES (?, ?, ?, ?)"));
    455   statement.BindInt(0, favicon_id);
    456   statement.BindString(1, URLDatabase::GURLToDatabaseURL(url));
    457   statement.BindInt(2, chrome::TOUCH_ICON);
    458   statement.BindCString(3, "Data which happened to be there");
    459   EXPECT_TRUE(statement.Run());
    460 
    461   EXPECT_TRUE(db.UpgradeToVersion7());
    462 
    463   EXPECT_FALSE(db.db_.DoesColumnExist("favicons", "sizes"));
    464 
    465   statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
    466       "SELECT id, url, icon_type FROM favicons"));
    467   EXPECT_TRUE(statement.Step());
    468   EXPECT_EQ(favicon_id, statement.ColumnInt(0));
    469   EXPECT_EQ(url, GURL(statement.ColumnString(1)));
    470   EXPECT_EQ(chrome::TOUCH_ICON, statement.ColumnInt(2));
    471 }
    472 
    473 // Test that only data moved to a temporary table is left in the main table
    474 // once the temporary table is committed.
    475 TEST_F(ThumbnailDatabaseTest, TemporaryTables) {
    476   ThumbnailDatabase db;
    477 
    478   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    479 
    480   db.BeginTransaction();
    481 
    482   EXPECT_TRUE(db.InitTemporaryTables());
    483 
    484   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    485   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    486 
    487   GURL unkept_url("http://google.com/favicon2.ico");
    488   chrome::FaviconID unkept_id = db.AddFavicon(unkept_url, chrome::FAVICON);
    489   db.AddFaviconBitmap(unkept_id, favicon, base::Time::Now(), kSmallSize);
    490 
    491   GURL kept_url("http://google.com/favicon.ico");
    492   chrome::FaviconID kept_id = db.AddFavicon(kept_url, chrome::FAVICON);
    493   db.AddFaviconBitmap(kept_id, favicon, base::Time::Now(), kLargeSize);
    494 
    495   GURL page_url("http://google.com");
    496   db.AddIconMapping(page_url, unkept_id);
    497   db.AddIconMapping(page_url, kept_id);
    498 
    499   chrome::FaviconID new_favicon_id =
    500       db.CopyFaviconAndFaviconBitmapsToTemporaryTables(kept_id);
    501   EXPECT_NE(0, new_favicon_id);
    502   EXPECT_TRUE(db.AddToTemporaryIconMappingTable(page_url, new_favicon_id));
    503 
    504   EXPECT_TRUE(db.CommitTemporaryTables());
    505 
    506   // Only copied data should be left.
    507   std::vector<IconMapping> icon_mappings;
    508   EXPECT_TRUE(
    509       db.GetIconMappingsForPageURL(page_url, chrome::FAVICON, &icon_mappings));
    510   EXPECT_EQ(1u, icon_mappings.size());
    511   EXPECT_EQ(new_favicon_id, icon_mappings[0].icon_id);
    512   EXPECT_EQ(page_url, icon_mappings[0].page_url);
    513 
    514   std::vector<FaviconBitmap> favicon_bitmaps;
    515   EXPECT_TRUE(db.GetFaviconBitmaps(icon_mappings[0].icon_id, &favicon_bitmaps));
    516   EXPECT_EQ(1u, favicon_bitmaps.size());
    517   EXPECT_EQ(kLargeSize, favicon_bitmaps[0].pixel_size);
    518 
    519   EXPECT_FALSE(db.GetFaviconIDForFaviconURL(unkept_url, false, NULL));
    520 }
    521 
    522 // Tests that deleting a favicon deletes the favicon row and favicon bitmap
    523 // rows from the database.
    524 TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
    525   ThumbnailDatabase db;
    526   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    527   db.BeginTransaction();
    528 
    529   std::vector<unsigned char> data1(blob1, blob1 + sizeof(blob1));
    530   scoped_refptr<base::RefCountedBytes> favicon1(
    531       new base::RefCountedBytes(data1));
    532   std::vector<unsigned char> data2(blob2, blob2 + sizeof(blob2));
    533   scoped_refptr<base::RefCountedBytes> favicon2(
    534       new base::RefCountedBytes(data2));
    535 
    536   GURL url("http://google.com");
    537   chrome::FaviconID id = db.AddFavicon(url, chrome::FAVICON);
    538   base::Time last_updated = base::Time::Now();
    539   db.AddFaviconBitmap(id, favicon1, last_updated, kSmallSize);
    540   db.AddFaviconBitmap(id, favicon2, last_updated, kLargeSize);
    541 
    542   EXPECT_TRUE(db.GetFaviconBitmaps(id, NULL));
    543 
    544   EXPECT_TRUE(db.DeleteFavicon(id));
    545   EXPECT_FALSE(db.GetFaviconBitmaps(id, NULL));
    546 }
    547 
    548 TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
    549   ThumbnailDatabase db;
    550   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    551   db.BeginTransaction();
    552 
    553   // Add a favicon
    554   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    555   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    556 
    557   GURL page_url("http://google.com");
    558   GURL icon_url("http://google.com/favicon.ico");
    559   base::Time time = base::Time::Now();
    560 
    561   chrome::FaviconID id = db.AddFavicon(icon_url,
    562                                        chrome::FAVICON,
    563                                        favicon,
    564                                        time,
    565                                        gfx::Size());
    566   EXPECT_NE(0, db.AddIconMapping(page_url, id));
    567   std::vector<IconMapping> icon_mappings;
    568   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
    569 
    570   EXPECT_EQ(page_url, icon_mappings.front().page_url);
    571   EXPECT_EQ(id, icon_mappings.front().icon_id);
    572   EXPECT_EQ(chrome::FAVICON, icon_mappings.front().icon_type);
    573   EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
    574 
    575   // Add a touch icon
    576   std::vector<unsigned char> data2(blob2, blob2 + sizeof(blob2));
    577   scoped_refptr<base::RefCountedBytes> favicon2 =
    578       new base::RefCountedBytes(data);
    579 
    580   chrome::FaviconID id2 = db.AddFavicon(icon_url,
    581                                         chrome::TOUCH_ICON,
    582                                         favicon2,
    583                                         time,
    584                                         gfx::Size());
    585   EXPECT_NE(0, db.AddIconMapping(page_url, id2));
    586 
    587   icon_mappings.clear();
    588   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
    589 
    590   EXPECT_EQ(page_url, icon_mappings.front().page_url);
    591   EXPECT_EQ(id2, icon_mappings.front().icon_id);
    592   EXPECT_EQ(chrome::TOUCH_ICON, icon_mappings.front().icon_type);
    593   EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
    594 
    595   // Add a touch precomposed icon
    596   scoped_refptr<base::RefCountedBytes> favicon3 =
    597       new base::RefCountedBytes(data2);
    598 
    599   chrome::FaviconID id3 = db.AddFavicon(icon_url,
    600                                         chrome::TOUCH_PRECOMPOSED_ICON,
    601                                         favicon3,
    602                                         time,
    603                                         gfx::Size());
    604   EXPECT_NE(0, db.AddIconMapping(page_url, id3));
    605 
    606   icon_mappings.clear();
    607   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings));
    608 
    609   EXPECT_EQ(page_url, icon_mappings.front().page_url);
    610   EXPECT_EQ(id3, icon_mappings.front().icon_id);
    611   EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON, icon_mappings.front().icon_type);
    612   EXPECT_EQ(icon_url, icon_mappings.front().icon_url);
    613 }
    614 
    615 // Test result of GetIconMappingsForPageURL when an icon type is passed in.
    616 TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLWithIconType) {
    617   ThumbnailDatabase db;
    618   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    619   db.BeginTransaction();
    620 
    621   GURL url("http://google.com");
    622   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    623   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    624   base::Time time = base::Time::Now();
    625 
    626   chrome::FaviconID id1 = db.AddFavicon(url,
    627                                         chrome::FAVICON,
    628                                         favicon,
    629                                         time,
    630                                         gfx::Size());
    631   EXPECT_NE(0, db.AddIconMapping(url, id1));
    632 
    633   chrome::FaviconID id2 = db.AddFavicon(url,
    634                                         chrome::TOUCH_ICON,
    635                                         favicon,
    636                                         time,
    637                                         gfx::Size());
    638   EXPECT_NE(0, db.AddIconMapping(url, id2));
    639 
    640   chrome::FaviconID id3 = db.AddFavicon(url,
    641                                         chrome::TOUCH_ICON,
    642                                         favicon,
    643                                         time,
    644                                         gfx::Size());
    645   EXPECT_NE(0, db.AddIconMapping(url, id3));
    646 
    647   // Only the mappings for favicons of type TOUCH_ICON should be returned as
    648   // TOUCH_ICON is a larger icon type than FAVICON.
    649   std::vector<IconMapping> icon_mappings;
    650   EXPECT_TRUE(db.GetIconMappingsForPageURL(
    651       url,
    652       chrome::FAVICON | chrome::TOUCH_ICON | chrome::TOUCH_PRECOMPOSED_ICON,
    653       &icon_mappings));
    654 
    655   EXPECT_EQ(2u, icon_mappings.size());
    656   if (id2 == icon_mappings[0].icon_id) {
    657     EXPECT_EQ(id3, icon_mappings[1].icon_id);
    658   } else {
    659     EXPECT_EQ(id3, icon_mappings[0].icon_id);
    660     EXPECT_EQ(id2, icon_mappings[1].icon_id);
    661   }
    662 
    663   icon_mappings.clear();
    664   EXPECT_TRUE(
    665       db.GetIconMappingsForPageURL(url, chrome::TOUCH_ICON, &icon_mappings));
    666   if (id2 == icon_mappings[0].icon_id) {
    667     EXPECT_EQ(id3, icon_mappings[1].icon_id);
    668   } else {
    669     EXPECT_EQ(id3, icon_mappings[0].icon_id);
    670     EXPECT_EQ(id2, icon_mappings[1].icon_id);
    671   }
    672 
    673   icon_mappings.clear();
    674   EXPECT_TRUE(
    675       db.GetIconMappingsForPageURL(url, chrome::FAVICON, &icon_mappings));
    676   EXPECT_EQ(1u, icon_mappings.size());
    677   EXPECT_EQ(id1, icon_mappings[0].icon_id);
    678 }
    679 
    680 TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
    681   ThumbnailDatabase db;
    682   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    683   db.BeginTransaction();
    684 
    685   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    686   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    687 
    688   // Add a favicon which will have icon_mappings
    689   base::Time time = base::Time::Now();
    690   chrome::FaviconID id1 = db.AddFavicon(GURL("http://google.com"),
    691                                         chrome::FAVICON,
    692                                         favicon,
    693                                         time,
    694                                         gfx::Size());
    695   EXPECT_NE(id1, 0);
    696 
    697   // Add another type of favicon
    698   time = base::Time::Now();
    699   chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
    700                                         chrome::TOUCH_ICON,
    701                                         favicon,
    702                                         time,
    703                                         gfx::Size());
    704   EXPECT_NE(id2, 0);
    705 
    706   // Add 3rd favicon
    707   time = base::Time::Now();
    708   chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
    709                                         chrome::TOUCH_ICON,
    710                                         favicon,
    711                                         time,
    712                                         gfx::Size());
    713   EXPECT_NE(id3, 0);
    714 
    715   // Add 2 icon mapping
    716   GURL page_url("http://www.google.com");
    717   EXPECT_TRUE(db.AddIconMapping(page_url, id1));
    718   EXPECT_TRUE(db.AddIconMapping(page_url, id2));
    719 
    720   EXPECT_TRUE(db.HasMappingFor(id1));
    721   EXPECT_TRUE(db.HasMappingFor(id2));
    722   EXPECT_FALSE(db.HasMappingFor(id3));
    723 
    724   // Remove all mappings
    725   db.DeleteIconMappings(page_url);
    726   EXPECT_FALSE(db.HasMappingFor(id1));
    727   EXPECT_FALSE(db.HasMappingFor(id2));
    728   EXPECT_FALSE(db.HasMappingFor(id3));
    729 }
    730 
    731 TEST_F(ThumbnailDatabaseTest, CloneIconMappings) {
    732   ThumbnailDatabase db;
    733   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    734   db.BeginTransaction();
    735 
    736   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    737   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    738 
    739   // Add a favicon which will have icon_mappings
    740   chrome::FaviconID id1 = db.AddFavicon(
    741       GURL("http://google.com"), chrome::FAVICON);
    742   EXPECT_NE(0, id1);
    743   base::Time time = base::Time::Now();
    744   db.AddFaviconBitmap(id1, favicon, time, gfx::Size());
    745 
    746   // Add another type of favicon
    747   chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
    748                                         chrome::TOUCH_ICON);
    749   EXPECT_NE(0, id2);
    750   time = base::Time::Now();
    751   db.AddFaviconBitmap(id2, favicon, time, gfx::Size());
    752 
    753   // Add 3rd favicon
    754   chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
    755                                         chrome::TOUCH_ICON);
    756   EXPECT_NE(0, id3);
    757   time = base::Time::Now();
    758   db.AddFaviconBitmap(id3, favicon, time, gfx::Size());
    759 
    760   GURL page1_url("http://page1.com");
    761   EXPECT_TRUE(db.AddIconMapping(page1_url, id1));
    762   EXPECT_TRUE(db.AddIconMapping(page1_url, id2));
    763 
    764   GURL page2_url("http://page2.com");
    765   EXPECT_TRUE(db.AddIconMapping(page2_url, id3));
    766 
    767   // Test we do nothing with existing mappings.
    768   std::vector<IconMapping> icon_mapping;
    769   EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping));
    770   ASSERT_EQ(1U, icon_mapping.size());
    771 
    772   EXPECT_TRUE(db.CloneIconMappings(page1_url, page2_url));
    773 
    774   icon_mapping.clear();
    775   EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping));
    776   ASSERT_EQ(1U, icon_mapping.size());
    777   EXPECT_EQ(page2_url, icon_mapping[0].page_url);
    778   EXPECT_EQ(id3, icon_mapping[0].icon_id);
    779 
    780   // Test we clone if the new page has no mappings.
    781   GURL page3_url("http://page3.com");
    782   EXPECT_TRUE(db.CloneIconMappings(page1_url, page3_url));
    783 
    784   icon_mapping.clear();
    785   EXPECT_TRUE(db.GetIconMappingsForPageURL(page3_url, &icon_mapping));
    786 
    787   ASSERT_EQ(2U, icon_mapping.size());
    788   if (icon_mapping[0].icon_id == id2)
    789     std::swap(icon_mapping[0], icon_mapping[1]);
    790   EXPECT_EQ(page3_url, icon_mapping[0].page_url);
    791   EXPECT_EQ(id1, icon_mapping[0].icon_id);
    792   EXPECT_EQ(page3_url, icon_mapping[1].page_url);
    793   EXPECT_EQ(id2, icon_mapping[1].icon_id);
    794 }
    795 
    796 TEST_F(IconMappingMigrationTest, TestIconMappingMigration) {
    797   HistoryDatabase history_db;
    798   ASSERT_TRUE(history_db.db_.Open(history_db_name_));
    799   history_db.BeginTransaction();
    800 
    801   const GURL icon1 = GURL("http://www.google.com/favicon.ico");
    802   const GURL icon2 = GURL("http://www.yahoo.com/favicon.ico");
    803 
    804   ThumbnailDatabase db;
    805   ASSERT_EQ(sql::INIT_OK, db.Init(thumbnail_db_name_, NULL, &history_db));
    806   db.BeginTransaction();
    807 
    808   // Migration should be done.
    809   // Test one icon_mapping.
    810   GURL page_url1 = GURL("http://google.com/");
    811   std::vector<IconMapping> icon_mappings;
    812   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
    813   ASSERT_EQ(1u, icon_mappings.size());
    814   EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
    815   EXPECT_EQ(page_url1, icon_mappings[0].page_url);
    816   EXPECT_EQ(1, icon_mappings[0].icon_id);
    817   EXPECT_EQ(icon1, icon_mappings[0].icon_url);
    818 
    819   // Test a page which has the same icon.
    820   GURL page_url3 = GURL("http://www.google.com/");
    821   icon_mappings.clear();
    822   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url3, &icon_mappings));
    823   ASSERT_EQ(1u, icon_mappings.size());
    824   EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
    825   EXPECT_EQ(page_url3, icon_mappings[0].page_url);
    826   EXPECT_EQ(1, icon_mappings[0].icon_id);
    827   EXPECT_EQ(icon1, icon_mappings[0].icon_url);
    828 
    829   // Test a icon_mapping with different IconID.
    830   GURL page_url2 = GURL("http://yahoo.com/");
    831   icon_mappings.clear();
    832   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
    833   ASSERT_EQ(1u, icon_mappings.size());
    834   EXPECT_EQ(chrome::FAVICON, icon_mappings[0].icon_type);
    835   EXPECT_EQ(page_url2, icon_mappings[0].page_url);
    836   EXPECT_EQ(2, icon_mappings[0].icon_id);
    837   EXPECT_EQ(icon2, icon_mappings[0].icon_url);
    838 
    839   // Test a page without icon
    840   GURL page_url4 = GURL("http://www.google.com/blank.html");
    841   EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url4, NULL));
    842 }
    843 
    844 TEST_F(ThumbnailDatabaseTest, IconMappingEnumerator) {
    845   ThumbnailDatabase db;
    846   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    847   db.BeginTransaction();
    848 
    849   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    850   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
    851 
    852   GURL url("http://google.com");
    853   GURL icon_url1("http://google.com/favicon.ico");
    854   chrome::FaviconID touch_icon_id1 = db.AddFavicon(icon_url1,
    855                                                    chrome::TOUCH_ICON,
    856                                                    favicon,
    857                                                    base::Time::Now(),
    858                                                    gfx::Size());
    859   ASSERT_NE(0, touch_icon_id1);
    860   IconMappingID touch_mapping_id1 = db.AddIconMapping(url, touch_icon_id1);
    861   ASSERT_NE(0, touch_mapping_id1);
    862 
    863   chrome::FaviconID favicon_id1 = db.AddFavicon(icon_url1,
    864                                                 chrome::FAVICON,
    865                                                 favicon,
    866                                                 base::Time::Now(),
    867                                                 gfx::Size());
    868   ASSERT_NE(0, favicon_id1);
    869   IconMappingID favicon_mapping_id1 = db.AddIconMapping(url, favicon_id1);
    870   ASSERT_NE(0, favicon_mapping_id1);
    871 
    872   GURL url2("http://chromium.org");
    873   GURL icon_url2("http://chromium.org/favicon.ico");
    874   chrome::FaviconID favicon_id2 = db.AddFavicon(icon_url2,
    875                                                 chrome::FAVICON,
    876                                                 favicon,
    877                                                 base::Time::Now(),
    878                                                 gfx::Size());
    879   ASSERT_NE(0, favicon_id2);
    880   IconMappingID favicon_mapping_id2 = db.AddIconMapping(url2, favicon_id2);
    881   ASSERT_NE(0, favicon_mapping_id2);
    882 
    883   IconMapping icon_mapping;
    884   ThumbnailDatabase::IconMappingEnumerator enumerator1;
    885   ASSERT_TRUE(db.InitIconMappingEnumerator(chrome::FAVICON, &enumerator1));
    886   // There are 2 favicon mappings.
    887   bool has_favicon_mapping1 = false;
    888   bool has_favicon_mapping2 = false;
    889   int mapping_count = 0;
    890   while (enumerator1.GetNextIconMapping(&icon_mapping)) {
    891     mapping_count++;
    892     if (favicon_mapping_id1 == icon_mapping.mapping_id) {
    893       has_favicon_mapping1 = true;
    894       EXPECT_EQ(url, icon_mapping.page_url);
    895       EXPECT_EQ(favicon_id1, icon_mapping.icon_id);
    896       EXPECT_EQ(icon_url1, icon_mapping.icon_url);
    897       EXPECT_EQ(chrome::FAVICON, icon_mapping.icon_type);
    898     } else if (favicon_mapping_id2 == icon_mapping.mapping_id) {
    899       has_favicon_mapping2 = true;
    900       EXPECT_EQ(url2, icon_mapping.page_url);
    901       EXPECT_EQ(favicon_id2, icon_mapping.icon_id);
    902       EXPECT_EQ(icon_url2, icon_mapping.icon_url);
    903       EXPECT_EQ(chrome::FAVICON, icon_mapping.icon_type);
    904     }
    905   }
    906   EXPECT_EQ(2, mapping_count);
    907   EXPECT_TRUE(has_favicon_mapping1);
    908   EXPECT_TRUE(has_favicon_mapping2);
    909 
    910   ThumbnailDatabase::IconMappingEnumerator enumerator2;
    911   ASSERT_TRUE(db.InitIconMappingEnumerator(chrome::TOUCH_ICON, &enumerator2));
    912   ASSERT_TRUE(enumerator2.GetNextIconMapping(&icon_mapping));
    913   EXPECT_EQ(touch_mapping_id1, icon_mapping.mapping_id);
    914   EXPECT_EQ(url, icon_mapping.page_url);
    915   EXPECT_EQ(touch_icon_id1, icon_mapping.icon_id);
    916   EXPECT_EQ(icon_url1, icon_mapping.icon_url);
    917   EXPECT_EQ(chrome::TOUCH_ICON, icon_mapping.icon_type);
    918 
    919   EXPECT_FALSE(enumerator2.GetNextIconMapping(&icon_mapping));
    920 }
    921 
    922 }  // namespace history
    923