• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ThumbnailDatabaseTest()53   ThumbnailDatabaseTest() {
54   }
~ThumbnailDatabaseTest()55   ~ThumbnailDatabaseTest() {
56   }
57 
58  protected:
SetUp()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:
IconMappingMigrationTest()80   IconMappingMigrationTest() {
81   }
~IconMappingMigrationTest()82   ~IconMappingMigrationTest() {
83   }
84 
85  protected:
SetUp()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 
TEST_F(ThumbnailDatabaseTest,GetFaviconAfterMigrationToTopSites)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 
TEST_F(ThumbnailDatabaseTest,AddIconMapping)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 
TEST_F(ThumbnailDatabaseTest,UpdateIconMapping)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 
TEST_F(ThumbnailDatabaseTest,DeleteIconMappings)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 
TEST_F(ThumbnailDatabaseTest,GetIconMappingsForPageURL)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 
TEST_F(ThumbnailDatabaseTest,UpgradeToVersion4)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 
TEST_F(ThumbnailDatabaseTest,TemporayIconMapping)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 
TEST_F(ThumbnailDatabaseTest,GetIconMappingsForPageURLForReturnOrder)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 
TEST_F(ThumbnailDatabaseTest,HasMappingFor)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 
TEST_F(IconMappingMigrationTest,TestIconMappingMigration)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