Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2011 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/file_path.h"
     11 #include "base/file_util.h"
     12 #include "base/memory/ref_counted_memory.h"
     13 #include "base/memory/scoped_temp_dir.h"
     14 #include "base/path_service.h"
     15 #include "chrome/browser/history/history_database.h"
     16 #include "chrome/browser/history/history_unittest_base.h"
     17 #include "chrome/browser/history/thumbnail_database.h"
     18 #include "chrome/common/chrome_constants.h"
     19 #include "chrome/common/chrome_paths.h"
     20 #include "chrome/common/thumbnail_score.h"
     21 #include "chrome/test/testing_profile.h"
     22 #include "chrome/tools/profiles/thumbnail-inl.h"
     23 #include "googleurl/src/gurl.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "third_party/skia/include/core/SkBitmap.h"
     26 #include "ui/gfx/codec/jpeg_codec.h"
     27 
     28 using base::Time;
     29 using base::TimeDelta;
     30 
     31 namespace history {
     32 
     33 namespace {
     34 
     35 // data we'll put into the thumbnail database
     36 static const unsigned char blob1[] =
     37     "12346102356120394751634516591348710478123649165419234519234512349134";
     38 static const unsigned char blob2[] =
     39     "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef";
     40 static const unsigned char blob3[] =
     41     "3716871354098370776510470746794707624107647054607467847164027";
     42 const double kBoringness = 0.25;
     43 const double kWorseBoringness = 0.50;
     44 const double kBetterBoringness = 0.10;
     45 const double kTotallyBoring = 1.0;
     46 
     47 const int64 kPage1 = 1234;
     48 
     49 }  // namespace
     50 
     51 class ThumbnailDatabaseTest : public testing::Test {
     52  public:
     53   ThumbnailDatabaseTest() {
     54   }
     55   ~ThumbnailDatabaseTest() {
     56   }
     57 
     58  protected:
     59   virtual void SetUp() {
     60     // Get a temporary directory for the test DB files.
     61     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     62 
     63     file_name_ = temp_dir_.path().AppendASCII("TestThumbnails.db");
     64     new_file_name_ = temp_dir_.path().AppendASCII("TestFavicons.db");
     65     history_db_name_ = temp_dir_.path().AppendASCII("TestHistory.db");
     66     google_bitmap_.reset(
     67         gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
     68   }
     69 
     70   scoped_ptr<SkBitmap> google_bitmap_;
     71 
     72   ScopedTempDir temp_dir_;
     73   FilePath file_name_;
     74   FilePath new_file_name_;
     75   FilePath history_db_name_;
     76 };
     77 
     78 class IconMappingMigrationTest : public HistoryUnitTestBase {
     79  public:
     80   IconMappingMigrationTest() {
     81   }
     82   ~IconMappingMigrationTest() {
     83   }
     84 
     85  protected:
     86   virtual void SetUp() {
     87     profile_.reset(new TestingProfile);
     88 
     89     FilePath data_path;
     90     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
     91     data_path = data_path.AppendASCII("History");
     92 
     93     history_db_name_ = profile_->GetPath().Append(chrome::kHistoryFilename);
     94     // Set up history and thumbnails as they would be before migration.
     95     ASSERT_NO_FATAL_FAILURE(
     96         ExecuteSQLScript(data_path.AppendASCII("history.20.sql"),
     97                          history_db_name_));
     98     thumbnail_db_name_ =
     99         profile_->GetPath().Append(chrome::kThumbnailsFilename);
    100     ASSERT_NO_FATAL_FAILURE(
    101         ExecuteSQLScript(data_path.AppendASCII("thumbnails.3.sql"),
    102                          thumbnail_db_name_));
    103   }
    104 
    105  protected:
    106   FilePath history_db_name_;
    107   FilePath thumbnail_db_name_;
    108 
    109  private:
    110   scoped_ptr<TestingProfile> profile_;
    111 };
    112 
    113 TEST_F(ThumbnailDatabaseTest, GetFaviconAfterMigrationToTopSites) {
    114   ThumbnailDatabase db;
    115   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    116   db.BeginTransaction();
    117 
    118   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    119   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    120 
    121   GURL url("http://google.com");
    122   FaviconID id = db.AddFavicon(url, FAVICON);
    123   base::Time time = base::Time::Now();
    124   db.SetFavicon(id, favicon, time);
    125   EXPECT_TRUE(db.RenameAndDropThumbnails(file_name_, new_file_name_));
    126 
    127   base::Time time_out;
    128   std::vector<unsigned char> favicon_out;
    129   GURL url_out;
    130   EXPECT_TRUE(db.GetFavicon(id, &time_out, &favicon_out, &url_out));
    131   EXPECT_EQ(url, url_out);
    132   EXPECT_EQ(time.ToTimeT(), time_out.ToTimeT());
    133   ASSERT_EQ(data.size(), favicon_out.size());
    134   EXPECT_TRUE(std::equal(data.begin(),
    135                          data.end(),
    136                          favicon_out.begin()));
    137 }
    138 
    139 TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
    140   ThumbnailDatabase db;
    141   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    142   db.BeginTransaction();
    143 
    144   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    145   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    146 
    147   GURL url("http://google.com");
    148   FaviconID id = db.AddFavicon(url, TOUCH_ICON);
    149   EXPECT_NE(0, id);
    150   base::Time time = base::Time::Now();
    151   db.SetFavicon(id, favicon, time);
    152 
    153   EXPECT_NE(0, db.AddIconMapping(url, id));
    154   std::vector<IconMapping> icon_mapping;
    155   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    156   EXPECT_EQ(1u, icon_mapping.size());
    157   EXPECT_EQ(url, icon_mapping.front().page_url);
    158   EXPECT_EQ(id, icon_mapping.front().icon_id);
    159 }
    160 
    161 TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) {
    162   ThumbnailDatabase db;
    163   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    164   db.BeginTransaction();
    165 
    166   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    167   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    168 
    169   GURL url("http://google.com");
    170   FaviconID id = db.AddFavicon(url, TOUCH_ICON);
    171   base::Time time = base::Time::Now();
    172   db.SetFavicon(id, favicon, time);
    173 
    174   EXPECT_TRUE(0 < db.AddIconMapping(url, id));
    175   std::vector<IconMapping> icon_mapping;
    176   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    177   ASSERT_EQ(1u, icon_mapping.size());
    178   EXPECT_EQ(url, icon_mapping.front().page_url);
    179   EXPECT_EQ(id, icon_mapping.front().icon_id);
    180 
    181   GURL url1("http://www.google.com/");
    182   FaviconID new_id = db.AddFavicon(url1, TOUCH_ICON);
    183   EXPECT_TRUE(db.UpdateIconMapping(icon_mapping.front().mapping_id, new_id));
    184 
    185   icon_mapping.clear();
    186   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    187   ASSERT_EQ(1u, icon_mapping.size());
    188   EXPECT_EQ(url, icon_mapping.front().page_url);
    189   EXPECT_EQ(new_id, icon_mapping.front().icon_id);
    190   EXPECT_NE(id, icon_mapping.front().icon_id);
    191 }
    192 
    193 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) {
    194   ThumbnailDatabase db;
    195   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    196   db.BeginTransaction();
    197 
    198   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    199   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    200 
    201   GURL url("http://google.com");
    202   FaviconID id = db.AddFavicon(url, TOUCH_ICON);
    203   base::Time time = base::Time::Now();
    204   db.SetFavicon(id, favicon, time);
    205   EXPECT_TRUE(0 < db.AddIconMapping(url, id));
    206 
    207   FaviconID id2 = db.AddFavicon(url, FAVICON);
    208   db.SetFavicon(id2, favicon, time);
    209   EXPECT_TRUE(0 < db.AddIconMapping(url, id2));
    210   ASSERT_NE(id, id2);
    211 
    212   std::vector<IconMapping> icon_mapping;
    213   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    214   ASSERT_EQ(2u, icon_mapping.size());
    215   EXPECT_EQ(icon_mapping.front().icon_type, TOUCH_ICON);
    216   EXPECT_TRUE(db.GetIconMappingForPageURL(url, FAVICON, NULL));
    217 
    218   db.DeleteIconMappings(url);
    219 
    220   EXPECT_FALSE(db.GetIconMappingsForPageURL(url, NULL));
    221   EXPECT_FALSE(db.GetIconMappingForPageURL(url, FAVICON, NULL));
    222 }
    223 
    224 TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
    225   ThumbnailDatabase db;
    226   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    227   db.BeginTransaction();
    228 
    229   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    230   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    231 
    232   GURL url("http://google.com");
    233 
    234   FaviconID id1 = db.AddFavicon(url, TOUCH_ICON);
    235   base::Time time = base::Time::Now();
    236   db.SetFavicon(id1, favicon, time);
    237   EXPECT_TRUE(0 < db.AddIconMapping(url, id1));
    238 
    239   FaviconID id2 = db.AddFavicon(url, FAVICON);
    240   EXPECT_NE(id1, id2);
    241   db.SetFavicon(id2, favicon, time);
    242   EXPECT_TRUE(0 < db.AddIconMapping(url, id2));
    243 
    244   std::vector<IconMapping> icon_mapping;
    245   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    246   ASSERT_EQ(2u, icon_mapping.size());
    247   EXPECT_NE(icon_mapping[0].icon_id, icon_mapping[1].icon_id);
    248   EXPECT_TRUE(icon_mapping[0].icon_id == id1 && icon_mapping[1].icon_id == id2);
    249 }
    250 
    251 TEST_F(ThumbnailDatabaseTest, UpgradeToVersion4) {
    252   ThumbnailDatabase db;
    253   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    254   db.BeginTransaction();
    255 
    256   const char* name = "favicons";
    257   std::string sql;
    258   sql.append("DROP TABLE IF EXISTS ");
    259   sql.append(name);
    260   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    261 
    262   sql.resize(0);
    263   sql.append("CREATE TABLE ");
    264   sql.append(name);
    265   sql.append("("
    266              "id INTEGER PRIMARY KEY,"
    267              "url LONGVARCHAR NOT NULL,"
    268              "last_updated INTEGER DEFAULT 0,"
    269              "image_data BLOB)");
    270   EXPECT_TRUE(db.db_.Execute(sql.c_str()));
    271 
    272   EXPECT_TRUE(db.UpgradeToVersion4());
    273 
    274   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    275   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    276 
    277   GURL url("http://google.com");
    278   FaviconID id = db.AddFavicon(url, TOUCH_ICON);
    279   base::Time time = base::Time::Now();
    280   db.SetFavicon(id, favicon, time);
    281 
    282   EXPECT_TRUE(0 < db.AddIconMapping(url, id));
    283   IconMapping icon_mapping;
    284   EXPECT_TRUE(db.GetIconMappingForPageURL(url, TOUCH_ICON, &icon_mapping));
    285   EXPECT_EQ(url, icon_mapping.page_url);
    286   EXPECT_EQ(id, icon_mapping.icon_id);
    287 }
    288 
    289 TEST_F(ThumbnailDatabaseTest, TemporayIconMapping) {
    290   ThumbnailDatabase db;
    291 
    292   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    293 
    294   db.BeginTransaction();
    295 
    296   EXPECT_TRUE(db.InitTemporaryIconMappingTable());
    297 
    298   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    299   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    300 
    301   GURL url("http://google.com");
    302   FaviconID id = db.AddFavicon(url, FAVICON);
    303   base::Time time = base::Time::Now();
    304   db.SetFavicon(id, favicon, time);
    305 
    306   db.AddToTemporaryIconMappingTable(url, id);
    307   db.CommitTemporaryIconMappingTable();
    308   IconMapping icon_mapping;
    309   EXPECT_TRUE(db.GetIconMappingForPageURL(url, FAVICON, &icon_mapping));
    310   EXPECT_EQ(id, icon_mapping.icon_id);
    311   EXPECT_EQ(url, icon_mapping.page_url);
    312 }
    313 
    314 TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
    315   ThumbnailDatabase db;
    316   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    317   db.BeginTransaction();
    318 
    319   // Add a favicon
    320   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    321   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    322 
    323   GURL url("http://google.com");
    324   FaviconID id = db.AddFavicon(url, FAVICON);
    325   base::Time time = base::Time::Now();
    326   db.SetFavicon(id, favicon, time);
    327 
    328   EXPECT_NE(0, db.AddIconMapping(url, id));
    329   std::vector<IconMapping> icon_mapping;
    330   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    331 
    332   EXPECT_EQ(url, icon_mapping.front().page_url);
    333   EXPECT_EQ(id, icon_mapping.front().icon_id);
    334   EXPECT_EQ(FAVICON, icon_mapping.front().icon_type);
    335 
    336   // Add a touch icon
    337   std::vector<unsigned char> data2(blob2, blob2 + sizeof(blob2));
    338   scoped_refptr<RefCountedBytes> favicon2(new RefCountedBytes(data));
    339 
    340   FaviconID id2 = db.AddFavicon(url, TOUCH_ICON);
    341   db.SetFavicon(id2, favicon2, time);
    342   EXPECT_NE(0, db.AddIconMapping(url, id2));
    343 
    344   icon_mapping.clear();
    345   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    346 
    347   EXPECT_EQ(url, icon_mapping.front().page_url);
    348   EXPECT_EQ(id2, icon_mapping.front().icon_id);
    349   EXPECT_EQ(TOUCH_ICON, icon_mapping.front().icon_type);
    350 
    351   // Add a touch precomposed icon
    352   scoped_refptr<RefCountedBytes> favicon3(new RefCountedBytes(data2));
    353 
    354   FaviconID id3 = db.AddFavicon(url, TOUCH_PRECOMPOSED_ICON);
    355   db.SetFavicon(id3, favicon3, time);
    356   EXPECT_NE(0, db.AddIconMapping(url, id3));
    357 
    358   icon_mapping.clear();
    359   EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping));
    360 
    361   EXPECT_EQ(url, icon_mapping.front().page_url);
    362   EXPECT_EQ(id3, icon_mapping.front().icon_id);
    363   EXPECT_EQ(TOUCH_PRECOMPOSED_ICON, icon_mapping.front().icon_type);
    364 }
    365 
    366 TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
    367   ThumbnailDatabase db;
    368   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
    369   db.BeginTransaction();
    370 
    371   std::vector<unsigned char> data(blob1, blob1 + sizeof(blob1));
    372   scoped_refptr<RefCountedBytes> favicon(new RefCountedBytes(data));
    373 
    374   // Add a favicon which will have icon_mappings
    375   FaviconID id1 = db.AddFavicon(GURL("http://google.com"), FAVICON);
    376   EXPECT_NE(id1, 0);
    377   base::Time time = base::Time::Now();
    378   db.SetFavicon(id1, favicon, time);
    379 
    380   // Add another type of favicon
    381   FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"), TOUCH_ICON);
    382   EXPECT_NE(id2, 0);
    383   time = base::Time::Now();
    384   db.SetFavicon(id2, favicon, time);
    385 
    386   // Add 3rd favicon
    387   FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"), TOUCH_ICON);
    388   EXPECT_NE(id3, 0);
    389   time = base::Time::Now();
    390   db.SetFavicon(id3, favicon, time);
    391 
    392   // Add 2 icon mapping
    393   GURL page_url("http://www.google.com");
    394   EXPECT_TRUE(db.AddIconMapping(page_url, id1));
    395   EXPECT_TRUE(db.AddIconMapping(page_url, id2));
    396 
    397   EXPECT_TRUE(db.HasMappingFor(id1));
    398   EXPECT_TRUE(db.HasMappingFor(id2));
    399   EXPECT_FALSE(db.HasMappingFor(id3));
    400 
    401   // Remove all mappings
    402   db.DeleteIconMappings(page_url);
    403   EXPECT_FALSE(db.HasMappingFor(id1));
    404   EXPECT_FALSE(db.HasMappingFor(id2));
    405   EXPECT_FALSE(db.HasMappingFor(id3));
    406 }
    407 
    408 TEST_F(IconMappingMigrationTest, TestIconMappingMigration) {
    409   HistoryDatabase history_db;
    410   ASSERT_TRUE(history_db.db_.Open(history_db_name_));
    411   history_db.BeginTransaction();
    412 
    413   const GURL icon1 = GURL("http://www.google.com/favicon.ico");
    414   const GURL icon2 = GURL("http://www.yahoo.com/favicon.ico");
    415 
    416   ThumbnailDatabase db;
    417   ASSERT_EQ(sql::INIT_OK, db.Init(thumbnail_db_name_, NULL, &history_db));
    418   db.BeginTransaction();
    419 
    420   // Migration should be done.
    421   // Test one icon_mapping.
    422   GURL page_url1 = GURL("http://google.com/");
    423   std::vector<IconMapping> icon_mappings;
    424   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
    425   ASSERT_EQ(1u, icon_mappings.size());
    426   EXPECT_EQ(FAVICON, icon_mappings[0].icon_type);
    427   EXPECT_EQ(page_url1, icon_mappings[0].page_url);
    428   EXPECT_EQ(1, icon_mappings[0].icon_id);
    429   base::Time time;
    430   std::vector<unsigned char> out_data;
    431   GURL out_icon_url;
    432   ASSERT_TRUE(db.GetFavicon(
    433       icon_mappings[0].icon_id, &time, &out_data, &out_icon_url));
    434   EXPECT_EQ(icon1, out_icon_url);
    435 
    436   // Test a page which has the same icon.
    437   GURL page_url3 = GURL("http://www.google.com/");
    438   icon_mappings.clear();
    439   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url3, &icon_mappings));
    440   ASSERT_EQ(1u, icon_mappings.size());
    441   EXPECT_EQ(FAVICON, icon_mappings[0].icon_type);
    442   EXPECT_EQ(page_url3, icon_mappings[0].page_url);
    443   EXPECT_EQ(1, icon_mappings[0].icon_id);
    444 
    445   // Test a icon_mapping with different IconID.
    446   GURL page_url2 = GURL("http://yahoo.com/");
    447   icon_mappings.clear();
    448   EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
    449   ASSERT_EQ(1u, icon_mappings.size());
    450   EXPECT_EQ(FAVICON, icon_mappings[0].icon_type);
    451   EXPECT_EQ(page_url2, icon_mappings[0].page_url);
    452   EXPECT_EQ(2, icon_mappings[0].icon_id);
    453   ASSERT_TRUE(db.GetFavicon(
    454       icon_mappings[0].icon_id, &time, &out_data, &out_icon_url));
    455   EXPECT_EQ(icon2, out_icon_url);
    456 
    457   // Test a page without icon
    458   GURL page_url4 = GURL("http://www.google.com/blank.html");
    459   EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url4, NULL));
    460 }
    461 
    462 }  // namespace history
    463