OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
13 #include "base/memory/ref_counted_memory.h" | 13 #include "base/memory/ref_counted_memory.h" |
14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "components/history/core/browser/history_backend_client.h" |
15 #include "components/history/core/browser/thumbnail_database.h" | 16 #include "components/history/core/browser/thumbnail_database.h" |
16 #include "components/history/core/test/database_test_utils.h" | 17 #include "components/history/core/test/database_test_utils.h" |
17 #include "sql/connection.h" | 18 #include "sql/connection.h" |
18 #include "sql/recovery.h" | 19 #include "sql/recovery.h" |
19 #include "sql/test/scoped_error_expecter.h" | 20 #include "sql/test/scoped_error_expecter.h" |
20 #include "sql/test/test_helpers.h" | 21 #include "sql/test/test_helpers.h" |
| 22 #include "testing/gmock/include/gmock/gmock.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
22 #include "third_party/sqlite/sqlite3.h" | 24 #include "third_party/sqlite/sqlite3.h" |
23 #include "url/gurl.h" | 25 #include "url/gurl.h" |
24 | 26 |
| 27 using testing::StrictMock; |
| 28 using testing::Return; |
| 29 |
25 namespace history { | 30 namespace history { |
26 | 31 |
27 namespace { | 32 namespace { |
28 | 33 |
29 // Blobs for the bitmap tests. These aren't real bitmaps. Golden | 34 // Blobs for the bitmap tests. These aren't real bitmaps. Golden |
30 // database files store the same blobs (see VersionN tests). | 35 // database files store the same blobs (see VersionN tests). |
31 const unsigned char kBlob1[] = | 36 const unsigned char kBlob1[] = |
32 "12346102356120394751634516591348710478123649165419234519234512349134"; | 37 "12346102356120394751634516591348710478123649165419234519234512349134"; |
33 const unsigned char kBlob2[] = | 38 const unsigned char kBlob2[] = |
34 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; | 39 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 } | 145 } |
141 | 146 |
142 if (memcmp(favicon_bitmaps[0].bitmap_data->front(), | 147 if (memcmp(favicon_bitmaps[0].bitmap_data->front(), |
143 expected_icon_contents, expected_icon_contents_size)) { | 148 expected_icon_contents, expected_icon_contents_size)) { |
144 ADD_FAILURE() << "failed to match |expected_icon_contents|"; | 149 ADD_FAILURE() << "failed to match |expected_icon_contents|"; |
145 return false; | 150 return false; |
146 } | 151 } |
147 return true; | 152 return true; |
148 } | 153 } |
149 | 154 |
| 155 class MockHistoryBackendClient : public HistoryBackendClient { |
| 156 public: |
| 157 // MOCK_METHOD0(~HistoryBackendClient, void()); |
| 158 MOCK_METHOD1(IsBookmarked, bool(const GURL& url)); |
| 159 MOCK_METHOD1(GetBookmarks, void(std::vector<URLAndTitle>* bookmarks)); |
| 160 MOCK_METHOD0(ShouldReportDatabaseError, bool()); |
| 161 MOCK_METHOD1(IsWebSafe, bool(const GURL& url)); |
| 162 |
| 163 #if defined(OS_ANDROID) |
| 164 MOCK_METHOD4(OnHistoryBackendInitialized, |
| 165 void(HistoryBackend* history_backend, |
| 166 HistoryDatabase* history_database, |
| 167 ThumbnailDatabase* thumbnail_database, |
| 168 const base::FilePath& history_dir)); |
| 169 MOCK_METHOD2(OnHistoryBackendDestroyed, |
| 170 void(HistoryBackend* history_backend, |
| 171 const base::FilePath& history_dir)); |
| 172 #endif // defined(OS_ANDROID) |
| 173 }; |
| 174 |
150 } // namespace | 175 } // namespace |
151 | 176 |
152 class ThumbnailDatabaseTest : public testing::Test { | 177 class ThumbnailDatabaseTest : public testing::Test { |
153 public: | 178 public: |
154 ThumbnailDatabaseTest() {} | 179 ThumbnailDatabaseTest() {} |
155 ~ThumbnailDatabaseTest() override {} | 180 ~ThumbnailDatabaseTest() override {} |
156 | 181 |
157 // Initialize a thumbnail database instance from the SQL file at | 182 // Initialize a thumbnail database instance from the SQL file at |
158 // |golden_path| in the "History/" subdirectory of test data. | 183 // |golden_path| in the "History/" subdirectory of test data. |
159 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { | 184 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 EXPECT_NE(0, id); | 221 EXPECT_NE(0, id); |
197 | 222 |
198 EXPECT_NE(0, db.AddIconMapping(url, id)); | 223 EXPECT_NE(0, db.AddIconMapping(url, id)); |
199 std::vector<IconMapping> icon_mappings; | 224 std::vector<IconMapping> icon_mappings; |
200 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings)); | 225 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings)); |
201 EXPECT_EQ(1u, icon_mappings.size()); | 226 EXPECT_EQ(1u, icon_mappings.size()); |
202 EXPECT_EQ(url, icon_mappings.front().page_url); | 227 EXPECT_EQ(url, icon_mappings.front().page_url); |
203 EXPECT_EQ(id, icon_mappings.front().icon_id); | 228 EXPECT_EQ(id, icon_mappings.front().icon_id); |
204 } | 229 } |
205 | 230 |
206 TEST_F(ThumbnailDatabaseTest, LastRequestedTime) { | 231 TEST_F(ThumbnailDatabaseTest, CleanUnusedFavicons) { |
| 232 StrictMock<MockHistoryBackendClient> mock_client; |
| 233 ThumbnailDatabase db(&mock_client); |
| 234 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 235 db.BeginTransaction(); |
| 236 |
| 237 base::Time start; |
| 238 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 239 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 240 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 241 |
| 242 // Icon 1: recently used case. |
| 243 GURL url1("http://google.com"); |
| 244 favicon_base::FaviconID icon1 = db.AddFavicon(url1, favicon_base::FAVICON); |
| 245 EXPECT_NE(0, icon1); |
| 246 FaviconBitmapID bitmap1 = |
| 247 db.AddFaviconBitmap(icon1, favicon, start, gfx::Size()); |
| 248 EXPECT_NE(0, bitmap1); |
| 249 EXPECT_NE(0, db.AddIconMapping(url1, icon1)); |
| 250 |
| 251 // Icon 2: not recently used case (not bookmarked). |
| 252 GURL url2("http://youtube.com"); |
| 253 EXPECT_CALL(mock_client, IsBookmarked(url2)).WillOnce(Return(false)); |
| 254 favicon_base::FaviconID icon2 = db.AddFavicon(url2, favicon_base::FAVICON); |
| 255 EXPECT_NE(0, icon2); |
| 256 EXPECT_NE(0, db.AddFaviconBitmap(icon2, favicon, start, gfx::Size())); |
| 257 EXPECT_NE(0, db.AddIconMapping(url2, icon2)); |
| 258 |
| 259 // Icon 3: not recently used case (bookmarked). |
| 260 GURL url3("http://photos.google.com"); |
| 261 EXPECT_CALL(mock_client, IsBookmarked(url3)).WillOnce(Return(true)); |
| 262 favicon_base::FaviconID icon3 = db.AddFavicon(url3, favicon_base::FAVICON); |
| 263 EXPECT_NE(0, icon3); |
| 264 EXPECT_NE(0, db.AddFaviconBitmap(icon3, favicon, start, gfx::Size())); |
| 265 EXPECT_NE(0, db.AddIconMapping(url3, icon3)); |
| 266 |
| 267 // Update the last_requested info for the first icon 3 weeks later. |
| 268 scoped_refptr<base::RefCountedMemory> bitmap_data_out; |
| 269 gfx::Size pixel_size_out; |
| 270 EXPECT_TRUE(db.GetFaviconBitmap(bitmap1, |
| 271 start + base::TimeDelta::FromDays(21), |
| 272 nullptr, &bitmap_data_out, &pixel_size_out)); |
| 273 |
| 274 db.CleanUnusedFavicons(start + base::TimeDelta::FromDays(14)); |
| 275 |
| 276 // The first icon is not deleted. |
| 277 EXPECT_TRUE(db.GetFaviconHeader(icon1, nullptr, nullptr)); |
| 278 std::vector<FaviconBitmap> favicon_bitmaps1; |
| 279 EXPECT_TRUE(db.GetFaviconBitmaps(icon1, &favicon_bitmaps1)); |
| 280 ASSERT_EQ(1u, favicon_bitmaps1.size()); |
| 281 std::vector<IconMapping> icon_mapping1; |
| 282 EXPECT_TRUE(db.GetIconMappingsForPageURL(url1, &icon_mapping1)); |
| 283 ASSERT_EQ(1u, icon_mapping1.size()); |
| 284 EXPECT_EQ(icon1, icon_mapping1[0].icon_id); |
| 285 |
| 286 // The second icon gets deleted with all details. |
| 287 EXPECT_FALSE(db.GetIconMappingsForPageURL(url2, nullptr)); |
| 288 EXPECT_FALSE(db.GetFaviconHeader(icon2, nullptr, nullptr)); |
| 289 EXPECT_FALSE(db.GetFaviconBitmaps(icon2, nullptr)); |
| 290 |
| 291 // The third icon is not deleted because the page URL is bookmarked. |
| 292 EXPECT_TRUE(db.GetFaviconHeader(icon3, nullptr, nullptr)); |
| 293 std::vector<FaviconBitmap> favicon_bitmaps3; |
| 294 EXPECT_TRUE(db.GetFaviconBitmaps(icon3, &favicon_bitmaps3)); |
| 295 ASSERT_EQ(1u, favicon_bitmaps3.size()); |
| 296 std::vector<IconMapping> icon_mapping3; |
| 297 EXPECT_TRUE(db.GetIconMappingsForPageURL(url3, &icon_mapping3)); |
| 298 ASSERT_EQ(1u, icon_mapping3.size()); |
| 299 EXPECT_EQ(icon3, icon_mapping3[0].icon_id); |
| 300 } |
| 301 |
| 302 TEST_F(ThumbnailDatabaseTest, DoNotUpdateLastRequestedTimeIfZero) { |
207 ThumbnailDatabase db(NULL); | 303 ThumbnailDatabase db(NULL); |
208 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 304 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
209 db.BeginTransaction(); | 305 db.BeginTransaction(); |
210 | 306 |
| 307 base::Time start; |
| 308 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
211 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | 309 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
212 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | 310 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
213 | 311 |
214 GURL url("http://google.com"); | 312 GURL url("http://google.com"); |
215 base::Time now = base::Time::Now(); | 313 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
216 favicon_base::FaviconID id = | 314 EXPECT_NE(0, icon); |
217 db.AddFavicon(url, favicon_base::TOUCH_ICON, favicon, now, gfx::Size()); | 315 FaviconBitmapID bitmap = |
218 ASSERT_NE(0, id); | 316 db.AddFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 317 EXPECT_NE(0, bitmap); |
| 318 EXPECT_NE(0, db.AddIconMapping(url, icon)); |
219 | 319 |
220 // Fetching the last requested time of a non-existent bitmap should fail. | 320 // Access the icon 3 weeks later with zero time - this happens e.g. from an |
221 base::Time last_requested = base::Time::UnixEpoch(); | 321 // incognito profile. |
222 EXPECT_FALSE(db.GetFaviconBitmap(id + 1, NULL, &last_requested, NULL, NULL)); | 322 scoped_refptr<base::RefCountedMemory> bitmap_data_out; |
223 EXPECT_EQ(last_requested, base::Time::UnixEpoch()); // Remains unchanged. | 323 gfx::Size pixel_size_out; |
| 324 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, base::Time(), nullptr, |
| 325 &bitmap_data_out, &pixel_size_out)); |
224 | 326 |
225 // Fetching the last requested time of a bitmap that has no last request | 327 db.CleanUnusedFavicons(start + base::TimeDelta::FromDays(14)); |
226 // should return a null timestamp. | |
227 last_requested = base::Time::UnixEpoch(); | |
228 EXPECT_TRUE(db.GetFaviconBitmap(id, NULL, &last_requested, NULL, NULL)); | |
229 EXPECT_TRUE(last_requested.is_null()); | |
230 | 328 |
231 // Setting the last requested time of an existing bitmap should succeed, and | 329 // The icon gets deleted with all details because the (incognito) visit with |
232 // the set time should be returned by the corresponding "Get". | 330 // zero time did not count. |
233 last_requested = base::Time::UnixEpoch(); | 331 EXPECT_FALSE(db.GetIconMappingsForPageURL(url, nullptr)); |
234 EXPECT_TRUE(db.SetFaviconBitmapLastRequestedTime(id, now)); | 332 EXPECT_FALSE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
235 EXPECT_TRUE(db.GetFaviconBitmap(id, NULL, &last_requested, NULL, NULL)); | 333 EXPECT_FALSE(db.GetFaviconBitmaps(icon, nullptr)); |
236 EXPECT_EQ(last_requested, now); | |
237 } | 334 } |
238 | 335 |
239 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { | 336 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { |
240 ThumbnailDatabase db(NULL); | 337 ThumbnailDatabase db(NULL); |
241 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 338 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
242 db.BeginTransaction(); | 339 db.BeginTransaction(); |
243 | 340 |
244 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | 341 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
245 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | 342 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
246 | 343 |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 ThumbnailDatabase db(NULL); | 1177 ThumbnailDatabase db(NULL); |
1081 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); | 1178 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); |
1082 | 1179 |
1083 // Verify that the resulting schema is correct, whether it | 1180 // Verify that the resulting schema is correct, whether it |
1084 // involved razing the file or fixing things in place. | 1181 // involved razing the file or fixing things in place. |
1085 VerifyTablesAndColumns(&db.db_); | 1182 VerifyTablesAndColumns(&db.db_); |
1086 } | 1183 } |
1087 } | 1184 } |
1088 | 1185 |
1089 } // namespace history | 1186 } // namespace history |
OLD | NEW |