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