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 "chrome/browser/history/android/android_provider_backend.h" 6 7 #include <vector> 8 9 #include "base/file_util.h" 10 #include "base/files/file_path.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "chrome/browser/bookmarks/bookmark_model.h" 16 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 17 #include "chrome/browser/bookmarks/bookmark_service.h" 18 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/favicon/favicon_changed_details.h" 20 #include "chrome/browser/history/android/android_time.h" 21 #include "chrome/browser/history/history_backend.h" 22 #include "chrome/browser/profiles/profile_manager.h" 23 #include "chrome/common/chrome_constants.h" 24 #include "chrome/test/base/testing_browser_process.h" 25 #include "chrome/test/base/testing_profile.h" 26 #include "chrome/test/base/testing_profile_manager.h" 27 #include "chrome/test/base/ui_test_utils.h" 28 #include "content/public/browser/browser_thread.h" 29 #include "content/public/test/test_browser_thread.h" 30 #include "testing/gtest/include/gtest/gtest.h" 31 32 using base::Time; 33 using base::TimeDelta; 34 using content::BrowserThread; 35 36 namespace history { 37 38 namespace { 39 40 struct BookmarkCacheRow { 41 public: 42 BookmarkCacheRow() 43 : url_id_(0), 44 bookmark_(false), 45 favicon_id_(0) { 46 } 47 URLID url_id_; 48 Time create_time_; 49 Time last_visit_time_; 50 bool bookmark_; 51 chrome::FaviconID favicon_id_; 52 }; 53 54 } // namespace 55 56 class AndroidProviderBackendDelegate : public HistoryBackend::Delegate { 57 public: 58 AndroidProviderBackendDelegate() {} 59 60 virtual void NotifyProfileError(int backend_id, 61 sql::InitStatus init_status) OVERRIDE {} 62 virtual void SetInMemoryBackend(int backend_id, 63 InMemoryHistoryBackend* backend) OVERRIDE {} 64 virtual void BroadcastNotifications(int type, 65 HistoryDetails* details) OVERRIDE { 66 switch (type) { 67 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 68 deleted_details_.reset(static_cast<URLsDeletedDetails*>(details)); 69 break; 70 case chrome::NOTIFICATION_FAVICON_CHANGED: 71 favicon_details_.reset(static_cast<FaviconChangedDetails*>(details)); 72 break; 73 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: 74 modified_details_.reset(static_cast<URLsModifiedDetails*>(details)); 75 break; 76 } 77 } 78 virtual void DBLoaded(int backend_id) OVERRIDE {} 79 virtual void StartTopSitesMigration(int backend_id) OVERRIDE {} 80 virtual void NotifyVisitDBObserversOnAddVisit( 81 const history::BriefVisitInfo& info) OVERRIDE {} 82 83 URLsDeletedDetails* deleted_details() const { 84 return deleted_details_.get(); 85 } 86 87 URLsModifiedDetails* modified_details() const { 88 return modified_details_.get(); 89 } 90 91 FaviconChangedDetails* favicon_details() const { 92 return favicon_details_.get(); 93 } 94 95 void ResetDetails() { 96 deleted_details_.reset(); 97 modified_details_.reset(); 98 favicon_details_.reset(); 99 } 100 101 private: 102 scoped_ptr<URLsDeletedDetails> deleted_details_; 103 scoped_ptr<URLsModifiedDetails> modified_details_; 104 scoped_ptr<FaviconChangedDetails> favicon_details_; 105 106 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendDelegate); 107 }; 108 109 class AndroidProviderBackendTest : public testing::Test { 110 public: 111 AndroidProviderBackendTest() 112 : profile_manager_( 113 TestingBrowserProcess::GetGlobal()), 114 bookmark_model_(NULL), 115 ui_thread_(BrowserThread::UI, &message_loop_), 116 file_thread_(BrowserThread::FILE, &message_loop_) { 117 } 118 virtual ~AndroidProviderBackendTest() {} 119 120 protected: 121 virtual void SetUp() OVERRIDE { 122 // Setup the testing profile, so the bookmark_model_sql_handler could 123 // get the bookmark model from it. 124 ASSERT_TRUE(profile_manager_.SetUp()); 125 // It seems that the name has to be chrome::kInitialProfile, so it 126 // could be found by ProfileManager::GetLastUsedProfile(). 127 TestingProfile* testing_profile = profile_manager_.CreateTestingProfile( 128 chrome::kInitialProfile); 129 testing_profile->CreateBookmarkModel(true); 130 bookmark_model_ = BookmarkModelFactory::GetForProfile(testing_profile); 131 ui_test_utils::WaitForBookmarkModelToLoad(bookmark_model_); 132 ASSERT_TRUE(bookmark_model_); 133 134 // Get the BookmarkModel from LastUsedProfile, this is the same way that 135 // how the BookmarkModelSQLHandler gets the BookmarkModel. 136 Profile* profile = ProfileManager::GetLastUsedProfile(); 137 ASSERT_TRUE(profile); 138 139 // Setup the database directory and files. 140 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 141 142 history_db_name_ = temp_dir_.path().AppendASCII(chrome::kHistoryFilename); 143 thumbnail_db_name_ = temp_dir_.path().AppendASCII( 144 chrome::kFaviconsFilename); 145 android_cache_db_name_ = temp_dir_.path().AppendASCII( 146 "TestAndroidCache.db"); 147 } 148 149 void AddBookmark(const GURL& url) { 150 const BookmarkNode* mobile_node = bookmark_model_->mobile_node(); 151 ASSERT_TRUE(mobile_node); 152 ASSERT_TRUE(bookmark_model_->AddURL(mobile_node, 0, string16(), url)); 153 } 154 155 bool GetAndroidURLsRows(std::vector<AndroidURLRow>* rows, 156 AndroidProviderBackend* backend) { 157 sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE, 158 "SELECT id, raw_url, url_id FROM android_urls ORDER BY url_id ASC")); 159 160 while (statement.Step()) { 161 AndroidURLRow row; 162 row.id = statement.ColumnInt64(0); 163 row.raw_url = statement.ColumnString(1); 164 row.url_id = statement.ColumnInt64(2); 165 rows->push_back(row); 166 } 167 return true; 168 } 169 170 bool GetBookmarkCacheRows(std::vector<BookmarkCacheRow>* rows, 171 AndroidProviderBackend* backend) { 172 sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE, 173 "SELECT created_time, last_visit_time, url_id, bookmark, favicon_id " 174 "FROM android_cache_db.bookmark_cache ORDER BY url_id ASC")); 175 176 while (statement.Step()) { 177 BookmarkCacheRow row; 178 row.create_time_ = FromDatabaseTime(statement.ColumnInt64(0)); 179 row.last_visit_time_ = FromDatabaseTime(statement.ColumnInt64(1)); 180 row.url_id_ = statement.ColumnInt64(2); 181 row.bookmark_ = statement.ColumnBool(3); 182 row.favicon_id_ = statement.ColumnInt64(4); 183 rows->push_back(row); 184 } 185 return true; 186 } 187 188 AndroidProviderBackendDelegate delegate_; 189 scoped_refptr<HistoryBackend> history_backend_; 190 HistoryDatabase history_db_; 191 ThumbnailDatabase thumbnail_db_; 192 base::ScopedTempDir temp_dir_; 193 base::FilePath android_cache_db_name_; 194 base::FilePath history_db_name_; 195 base::FilePath thumbnail_db_name_; 196 197 TestingProfileManager profile_manager_; 198 BookmarkModel* bookmark_model_; 199 base::MessageLoopForUI message_loop_; 200 content::TestBrowserThread ui_thread_; 201 content::TestBrowserThread file_thread_; 202 203 204 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendTest); 205 }; 206 207 TEST_F(AndroidProviderBackendTest, UpdateTables) { 208 GURL url1("http://www.cnn.com"); 209 URLID url_id1 = 0; 210 std::vector<VisitInfo> visits1; 211 Time last_visited1 = Time::Now() - TimeDelta::FromDays(1); 212 Time created1 = last_visited1 - TimeDelta::FromDays(20); 213 visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK)); 214 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1), 215 content::PAGE_TRANSITION_LINK)); 216 visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK)); 217 218 GURL url2("http://www.example.com"); 219 URLID url_id2 = 0; 220 std::vector<VisitInfo> visits2; 221 Time last_visited2 = Time::Now(); 222 Time created2 = last_visited2 - TimeDelta::FromDays(10); 223 visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK)); 224 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5), 225 content::PAGE_TRANSITION_LINK)); 226 visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK)); 227 228 // Add a bookmark which is not in the history. 229 GURL url3("http://www.bookmark.com"); 230 string16 title3(UTF8ToUTF16("bookmark")); 231 ASSERT_TRUE(bookmark_model_->AddURL(bookmark_model_->bookmark_bar_node(), 0, 232 title3, url3)); 233 // Only use the HistoryBackend to generate the test data. 234 // HistoryBackend will shutdown after that. 235 { 236 scoped_refptr<HistoryBackend> history_backend; 237 history_backend = new HistoryBackend(temp_dir_.path(), 0, 238 new AndroidProviderBackendDelegate(), bookmark_model_); 239 history_backend->Init(std::string(), false); 240 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED); 241 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED); 242 URLRow url_row; 243 244 ASSERT_TRUE(history_backend->GetURL(url1, &url_row)); 245 url_id1 = url_row.id(); 246 ASSERT_TRUE(history_backend->GetURL(url2, &url_row)); 247 url_id2 = url_row.id(); 248 249 // Set favicon to url2. 250 std::vector<unsigned char> data; 251 data.push_back('1'); 252 chrome::FaviconBitmapData bitmap_data_element; 253 bitmap_data_element.bitmap_data = new base::RefCountedBytes(data); 254 bitmap_data_element.pixel_size = gfx::Size(); 255 bitmap_data_element.icon_url = GURL(); 256 std::vector<chrome::FaviconBitmapData> favicon_bitmap_data; 257 favicon_bitmap_data.push_back(bitmap_data_element); 258 259 history_backend->SetFavicons(url2, chrome::FAVICON, favicon_bitmap_data); 260 history_backend->Closing(); 261 } 262 263 // The history_db_name and thumbnail_db_name files should be created by 264 // HistoryBackend. We need to open the same database files. 265 ASSERT_TRUE(base::PathExists(history_db_name_)); 266 ASSERT_TRUE(base::PathExists(thumbnail_db_name_)); 267 268 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 269 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 270 &history_db_)); 271 // Set url1 as bookmark. 272 AddBookmark(url1); 273 scoped_ptr<AndroidProviderBackend> backend( 274 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 275 &thumbnail_db_, bookmark_model_, &delegate_)); 276 277 ASSERT_TRUE(backend->EnsureInitializedAndUpdated()); 278 279 // First verify that the bookmark which was not in the history has been added 280 // to history database. 281 URLRow url_row; 282 ASSERT_TRUE(history_db_.GetRowForURL(url3, &url_row)); 283 URLID url_id3 = url_row.id(); 284 ASSERT_EQ(url3, url_row.url()); 285 ASSERT_EQ(title3, url_row.title()); 286 287 std::vector<AndroidURLRow> android_url_rows; 288 ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get())); 289 ASSERT_EQ(3u, android_url_rows.size()); 290 std::vector<AndroidURLRow>::iterator i = android_url_rows.begin(); 291 EXPECT_EQ(url_id1, i->url_id); 292 EXPECT_EQ(url1.spec(), i->raw_url); 293 i++; 294 EXPECT_EQ(url_id2, i->url_id); 295 EXPECT_EQ(url2.spec(), i->raw_url); 296 i++; 297 EXPECT_EQ(url_id3, i->url_id); 298 EXPECT_EQ(url3.spec(), i->raw_url); 299 300 std::vector<BookmarkCacheRow> bookmark_cache_rows; 301 ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get())); 302 ASSERT_EQ(3u, bookmark_cache_rows.size()); 303 std::vector<BookmarkCacheRow>::const_iterator j = bookmark_cache_rows.begin(); 304 EXPECT_EQ(url_id1, j->url_id_); 305 EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_)); 306 EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_)); 307 EXPECT_EQ(0, j->favicon_id_); 308 EXPECT_TRUE(j->bookmark_); 309 j++; 310 EXPECT_EQ(url_id2, j->url_id_); 311 EXPECT_EQ(ToDatabaseTime(last_visited2), ToDatabaseTime(j->last_visit_time_)); 312 EXPECT_EQ(ToDatabaseTime(created2), ToDatabaseTime(j->create_time_)); 313 EXPECT_NE(0, j->favicon_id_); 314 EXPECT_FALSE(j->bookmark_); 315 316 // Delete url2 from database. 317 ASSERT_TRUE(history_db_.DeleteURLRow(url_id2)); 318 VisitVector visit_rows; 319 ASSERT_TRUE(history_db_.GetMostRecentVisitsForURL(url_id2, 10, 320 &visit_rows)); 321 ASSERT_EQ(3u, visit_rows.size()); 322 for (VisitVector::const_iterator v = visit_rows.begin(); 323 v != visit_rows.end(); v++) 324 history_db_.DeleteVisit(*v); 325 326 backend->UpdateTables(); 327 328 android_url_rows.clear(); 329 ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get())); 330 ASSERT_EQ(2u, android_url_rows.size()); 331 i = android_url_rows.begin(); 332 EXPECT_EQ(url_id1, i->url_id); 333 EXPECT_EQ(url1.spec(), i->raw_url); 334 ++i; 335 EXPECT_EQ(url_id3, i->url_id); 336 EXPECT_EQ(url3.spec(), i->raw_url); 337 338 bookmark_cache_rows.clear(); 339 ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get())); 340 ASSERT_EQ(2u, bookmark_cache_rows.size()); 341 j = bookmark_cache_rows.begin(); 342 EXPECT_EQ(url_id1, j->url_id_); 343 EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_)); 344 EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_)); 345 EXPECT_EQ(0, j->favicon_id_); 346 EXPECT_TRUE(j->bookmark_); 347 ++j; 348 EXPECT_EQ(url_id3, j->url_id_); 349 EXPECT_EQ(base::Time::UnixEpoch(), j->last_visit_time_); 350 EXPECT_EQ(base::Time::UnixEpoch(), j->create_time_); 351 EXPECT_EQ(0, j->favicon_id_); 352 EXPECT_TRUE(j->bookmark_); 353 } 354 355 TEST_F(AndroidProviderBackendTest, QueryHistoryAndBookmarks) { 356 GURL url1("http://www.cnn.com"); 357 URLID url_id1 = 0; 358 const string16 title1(UTF8ToUTF16("cnn")); 359 std::vector<VisitInfo> visits1; 360 Time last_visited1 = Time::Now() - TimeDelta::FromDays(1); 361 Time created1 = last_visited1 - TimeDelta::FromDays(20); 362 visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK)); 363 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1), 364 content::PAGE_TRANSITION_LINK)); 365 visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK)); 366 367 GURL url2("http://www.example.com"); 368 URLID url_id2 = 0; 369 std::vector<VisitInfo> visits2; 370 const string16 title2(UTF8ToUTF16("example")); 371 Time last_visited2 = Time::Now(); 372 Time created2 = last_visited2 - TimeDelta::FromDays(10); 373 visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK)); 374 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5), 375 content::PAGE_TRANSITION_LINK)); 376 visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK)); 377 378 // Only use the HistoryBackend to generate the test data. 379 // HistoryBackend will shutdown after that. 380 { 381 scoped_refptr<HistoryBackend> history_backend; 382 history_backend = new HistoryBackend(temp_dir_.path(), 0, 383 new AndroidProviderBackendDelegate(), bookmark_model_); 384 history_backend->Init(std::string(), false); 385 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED); 386 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED); 387 URLRow url_row; 388 389 ASSERT_TRUE(history_backend->GetURL(url1, &url_row)); 390 url_id1 = url_row.id(); 391 url_row.set_title(title1); 392 ASSERT_TRUE(history_backend->UpdateURL(url_id1, url_row)); 393 394 ASSERT_TRUE(history_backend->GetURL(url2, &url_row)); 395 url_id2 = url_row.id(); 396 url_row.set_title(title2); 397 ASSERT_TRUE(history_backend->UpdateURL(url_id2, url_row)); 398 399 // Set favicon to url2. 400 std::vector<unsigned char> data; 401 data.push_back('1'); 402 chrome::FaviconBitmapData bitmap_data_element; 403 bitmap_data_element.bitmap_data = new base::RefCountedBytes(data); 404 bitmap_data_element.pixel_size = gfx::Size(); 405 bitmap_data_element.icon_url = GURL(); 406 std::vector<chrome::FaviconBitmapData> favicon_bitmap_data; 407 favicon_bitmap_data.push_back(bitmap_data_element); 408 409 history_backend->SetFavicons(url2, chrome::FAVICON, favicon_bitmap_data); 410 history_backend->Closing(); 411 } 412 413 // The history_db_name and thumbnail_db_name files should be created by 414 // HistoryBackend. We need to open the same database files. 415 ASSERT_TRUE(base::PathExists(history_db_name_)); 416 ASSERT_TRUE(base::PathExists(thumbnail_db_name_)); 417 418 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 419 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 420 &history_db_)); 421 // Set url1 as bookmark. 422 AddBookmark(url1); 423 424 scoped_ptr<AndroidProviderBackend> backend( 425 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 426 &thumbnail_db_, bookmark_model_, &delegate_)); 427 428 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 429 430 projections.push_back(HistoryAndBookmarkRow::ID); 431 projections.push_back(HistoryAndBookmarkRow::URL); 432 projections.push_back(HistoryAndBookmarkRow::TITLE); 433 projections.push_back(HistoryAndBookmarkRow::CREATED); 434 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 435 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 436 projections.push_back(HistoryAndBookmarkRow::FAVICON); 437 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 438 439 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 440 projections, std::string(), std::vector<string16>(), 441 std::string("url ASC"))); 442 ASSERT_TRUE(statement->statement()->Step()); 443 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1))); 444 EXPECT_EQ(title1, statement->statement()->ColumnString16(2)); 445 EXPECT_EQ(ToDatabaseTime(created1), 446 statement->statement()->ColumnInt64(3)); 447 EXPECT_EQ(ToDatabaseTime(last_visited1), 448 statement->statement()->ColumnInt64(4)); 449 EXPECT_EQ(3, statement->statement()->ColumnInt(5)); 450 EXPECT_EQ(6, statement->favicon_index()); 451 // No favicon. 452 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6)); 453 EXPECT_TRUE(statement->statement()->ColumnBool(7)); 454 455 ASSERT_TRUE(statement->statement()->Step()); 456 EXPECT_EQ(title2, statement->statement()->ColumnString16(2)); 457 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1))); 458 EXPECT_EQ(ToDatabaseTime(created2), 459 statement->statement()->ColumnInt64(3)); 460 EXPECT_EQ(ToDatabaseTime(last_visited2), 461 statement->statement()->ColumnInt64(4)); 462 EXPECT_EQ(3, statement->statement()->ColumnInt(5)); 463 std::vector<unsigned char> favicon2; 464 EXPECT_EQ(6, statement->favicon_index()); 465 // Has favicon. 466 EXPECT_NE(0, statement->statement()->ColumnByteLength(6)); 467 EXPECT_FALSE(statement->statement()->ColumnBool(7)); 468 469 // No more row. 470 EXPECT_FALSE(statement->statement()->Step()); 471 472 // Query by bookmark 473 statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=1", 474 std::vector<string16>(), std::string("url ASC"))); 475 // Only URL1 is returned. 476 ASSERT_TRUE(statement->statement()->Step()); 477 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1))); 478 EXPECT_FALSE(statement->statement()->Step()); 479 480 statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=0", 481 std::vector<string16>(), std::string("url ASC"))); 482 // Only URL2 is returned. 483 ASSERT_TRUE(statement->statement()->Step()); 484 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1))); 485 EXPECT_FALSE(statement->statement()->Step()); 486 } 487 488 TEST_F(AndroidProviderBackendTest, InsertHistoryAndBookmark) { 489 HistoryAndBookmarkRow row1; 490 row1.set_raw_url("cnn.com"); 491 row1.set_url(GURL("http://cnn.com")); 492 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 493 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 494 row1.set_visit_count(10); 495 row1.set_is_bookmark(true); 496 row1.set_title(UTF8ToUTF16("cnn")); 497 498 HistoryAndBookmarkRow row2; 499 row2.set_raw_url("http://www.example.com"); 500 row2.set_url(GURL("http://www.example.com")); 501 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 502 row2.set_is_bookmark(false); 503 row2.set_title(UTF8ToUTF16("example")); 504 std::vector<unsigned char> data; 505 data.push_back('1'); 506 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 507 508 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 509 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 510 &history_db_)); 511 scoped_ptr<AndroidProviderBackend> backend( 512 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 513 &thumbnail_db_, bookmark_model_, &delegate_)); 514 515 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 516 EXPECT_FALSE(delegate_.deleted_details()); 517 ASSERT_TRUE(delegate_.modified_details()); 518 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 519 EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url()); 520 EXPECT_EQ(row1.last_visit_time(), 521 delegate_.modified_details()->changed_urls[0].last_visit()); 522 EXPECT_EQ(row1.visit_count(), 523 delegate_.modified_details()->changed_urls[0].visit_count()); 524 EXPECT_EQ(row1.title(), 525 delegate_.modified_details()->changed_urls[0].title()); 526 EXPECT_FALSE(delegate_.favicon_details()); 527 content::RunAllPendingInMessageLoop(); 528 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 529 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 530 ASSERT_TRUE(child); 531 EXPECT_EQ(row1.title(), child->GetTitle()); 532 EXPECT_EQ(row1.url(), child->url()); 533 534 delegate_.ResetDetails(); 535 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 536 EXPECT_FALSE(delegate_.deleted_details()); 537 ASSERT_TRUE(delegate_.modified_details()); 538 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 539 EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url()); 540 EXPECT_EQ(row2.last_visit_time(), 541 delegate_.modified_details()->changed_urls[0].last_visit()); 542 EXPECT_EQ(row2.title(), 543 delegate_.modified_details()->changed_urls[0].title()); 544 ASSERT_TRUE(delegate_.favicon_details()); 545 ASSERT_EQ(1u, delegate_.favicon_details()->urls.size()); 546 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 547 delegate_.favicon_details()->urls.find(row2.url())); 548 549 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 550 projections.push_back(HistoryAndBookmarkRow::ID); 551 projections.push_back(HistoryAndBookmarkRow::URL); 552 projections.push_back(HistoryAndBookmarkRow::TITLE); 553 projections.push_back(HistoryAndBookmarkRow::CREATED); 554 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 555 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 556 projections.push_back(HistoryAndBookmarkRow::FAVICON); 557 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 558 559 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 560 projections, std::string(), std::vector<string16>(), 561 std::string("url ASC"))); 562 ASSERT_TRUE(statement->statement()->Step()); 563 ASSERT_EQ(row1.raw_url(), statement->statement()->ColumnString(1)); 564 EXPECT_EQ(row1.title(), statement->statement()->ColumnString16(2)); 565 EXPECT_EQ(ToDatabaseTime(row1.created()), 566 statement->statement()->ColumnInt64(3)); 567 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 568 statement->statement()->ColumnInt64(4)); 569 EXPECT_EQ(row1.visit_count(), statement->statement()->ColumnInt(5)); 570 EXPECT_EQ(6, statement->favicon_index()); 571 // No favicon. 572 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6)); 573 574 // TODO: Find a way to test the bookmark was added in BookmarkModel. 575 // The bookmark was added in UI thread, there is no good way to test it. 576 EXPECT_TRUE(statement->statement()->ColumnBool(7)); 577 578 ASSERT_TRUE(statement->statement()->Step()); 579 EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2)); 580 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1))); 581 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()), 582 statement->statement()->ColumnInt64(3)); 583 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()), 584 statement->statement()->ColumnInt64(4)); 585 EXPECT_EQ(1, statement->statement()->ColumnInt(5)); 586 EXPECT_EQ(6, statement->favicon_index()); 587 // Has favicon. 588 EXPECT_NE(0, statement->statement()->ColumnByteLength(6)); 589 // TODO: Find a way to test the bookmark was added in BookmarkModel. 590 // The bookmark was added in UI thread, there is no good way to test it. 591 EXPECT_FALSE(statement->statement()->ColumnBool(7)); 592 593 // No more row. 594 EXPECT_FALSE(statement->statement()->Step()); 595 } 596 597 TEST_F(AndroidProviderBackendTest, DeleteHistoryAndBookmarks) { 598 HistoryAndBookmarkRow row1; 599 row1.set_raw_url("cnn.com"); 600 row1.set_url(GURL("http://cnn.com")); 601 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 602 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 603 row1.set_visit_count(10); 604 row1.set_is_bookmark(true); 605 row1.set_title(UTF8ToUTF16("cnn")); 606 607 HistoryAndBookmarkRow row2; 608 row2.set_raw_url("http://www.example.com"); 609 row2.set_url(GURL("http://www.example.com")); 610 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 611 row2.set_is_bookmark(false); 612 row2.set_title(UTF8ToUTF16("example")); 613 std::vector<unsigned char> data; 614 data.push_back('1'); 615 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 616 617 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 618 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 619 &history_db_)); 620 621 scoped_ptr<AndroidProviderBackend> backend( 622 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 623 &thumbnail_db_, bookmark_model_, &delegate_)); 624 625 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 626 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 627 // Verify the row1 has been added in bookmark model. 628 content::RunAllPendingInMessageLoop(); 629 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 630 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 631 ASSERT_TRUE(child); 632 EXPECT_EQ(row1.title(), child->GetTitle()); 633 EXPECT_EQ(row1.url(), child->url()); 634 635 // Delete the row1. 636 std::vector<string16> args; 637 int deleted_count = 0; 638 delegate_.ResetDetails(); 639 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args, 640 &deleted_count)); 641 EXPECT_EQ(1, deleted_count); 642 // Verify the row1 was removed from bookmark model. 643 content::RunAllPendingInMessageLoop(); 644 ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count()); 645 646 // Verify notifications 647 ASSERT_TRUE(delegate_.deleted_details()); 648 EXPECT_FALSE(delegate_.modified_details()); 649 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size()); 650 EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url()); 651 EXPECT_EQ(row1.last_visit_time(), 652 delegate_.deleted_details()->rows[0].last_visit()); 653 EXPECT_EQ(row1.title(), 654 delegate_.deleted_details()->rows[0].title()); 655 EXPECT_FALSE(delegate_.favicon_details()); 656 657 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 658 projections.push_back(HistoryAndBookmarkRow::ID); 659 projections.push_back(HistoryAndBookmarkRow::URL); 660 projections.push_back(HistoryAndBookmarkRow::TITLE); 661 projections.push_back(HistoryAndBookmarkRow::CREATED); 662 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 663 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 664 projections.push_back(HistoryAndBookmarkRow::FAVICON); 665 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 666 667 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 668 projections, std::string(), std::vector<string16>(), 669 std::string("url ASC"))); 670 ASSERT_TRUE(statement->statement()->Step()); 671 672 EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2)); 673 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1))); 674 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()), 675 statement->statement()->ColumnInt64(3)); 676 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()), 677 statement->statement()->ColumnInt64(4)); 678 EXPECT_EQ(1, statement->statement()->ColumnInt(5)); 679 EXPECT_EQ(6, statement->favicon_index()); 680 // Has favicon. 681 EXPECT_NE(0, statement->statement()->ColumnByteLength(6)); 682 // TODO: Find a way to test the bookmark was added in BookmarkModel. 683 // The bookmark was added in UI thread, there is no good way to test it. 684 EXPECT_FALSE(statement->statement()->ColumnBool(7)); 685 // No more row. 686 EXPECT_FALSE(statement->statement()->Step()); 687 688 deleted_count = 0; 689 // Delete row2. 690 delegate_.ResetDetails(); 691 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("bookmark = 0", 692 std::vector<string16>(), &deleted_count)); 693 // Verify notifications 694 ASSERT_TRUE(delegate_.deleted_details()); 695 EXPECT_FALSE(delegate_.modified_details()); 696 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size()); 697 EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url()); 698 EXPECT_EQ(row2.last_visit_time(), 699 delegate_.deleted_details()->rows[0].last_visit()); 700 EXPECT_EQ(row2.title(), 701 delegate_.deleted_details()->rows[0].title()); 702 ASSERT_TRUE(delegate_.favicon_details()); 703 ASSERT_EQ(1u, delegate_.favicon_details()->urls.size()); 704 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 705 delegate_.favicon_details()->urls.find(row2.url())); 706 707 ASSERT_EQ(1, deleted_count); 708 scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks( 709 projections, std::string(), std::vector<string16>(), 710 std::string("url ASC"))); 711 ASSERT_FALSE(statement1->statement()->Step()); 712 } 713 714 TEST_F(AndroidProviderBackendTest, IsValidHistoryAndBookmarkRow) { 715 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 716 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 717 &history_db_)); 718 scoped_ptr<AndroidProviderBackend> backend( 719 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 720 &thumbnail_db_, bookmark_model_, &delegate_)); 721 722 // The created time and last visit time are too close to have required visit 723 // count. 724 HistoryAndBookmarkRow row1; 725 row1.set_raw_url("cnn.com"); 726 row1.set_url(GURL("http://cnn.com")); 727 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 728 row1.set_created(Time::FromInternalValue( 729 row1.last_visit_time().ToInternalValue() - 1)); 730 row1.set_visit_count(10); 731 row1.set_is_bookmark(true); 732 row1.set_title(UTF8ToUTF16("cnn")); 733 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row1)); 734 735 // Have different created time and last visit time, but only have 1 visit 736 // count. 737 HistoryAndBookmarkRow row2; 738 row2.set_raw_url("http://www.example.com"); 739 row2.set_url(GURL("http://www.example.com")); 740 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 741 row2.set_created(Time::Now() - TimeDelta::FromDays(11)); 742 row2.set_visit_count(1); 743 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row2)); 744 745 // Have created time in the future. 746 HistoryAndBookmarkRow row3; 747 row3.set_raw_url("http://www.example.com"); 748 row3.set_url(GURL("http://www.example.com")); 749 row3.set_created(Time::Now() + TimeDelta::FromDays(11)); 750 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row3)); 751 752 // Have last vist time in the future. 753 HistoryAndBookmarkRow row4; 754 row4.set_raw_url("http://www.example.com"); 755 row4.set_url(GURL("http://www.example.com")); 756 row4.set_last_visit_time(Time::Now() + TimeDelta::FromDays(11)); 757 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row4)); 758 759 // Created time is larger than last visit time. 760 HistoryAndBookmarkRow row5; 761 row5.set_raw_url("http://www.example.com"); 762 row5.set_url(GURL("http://www.example.com")); 763 row5.set_last_visit_time(Time::Now()); 764 row5.set_created(Time::Now() + TimeDelta::FromDays(11)); 765 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row5)); 766 767 // Visit count is zero, and last visit time is not zero. 768 HistoryAndBookmarkRow row6; 769 row6.set_raw_url("http://www.example.com"); 770 row6.set_url(GURL("http://www.example.com")); 771 row6.set_visit_count(0); 772 row6.set_last_visit_time(Time::Now()); 773 row6.set_created(Time::Now() - TimeDelta::FromDays(1)); 774 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row6)); 775 776 // Visit count is zero, and create time is not zero. 777 HistoryAndBookmarkRow row7; 778 row7.set_raw_url("http://www.example.com"); 779 row7.set_url(GURL("http://www.example.com")); 780 row7.set_visit_count(0); 781 row7.set_last_visit_time(Time::Now()); 782 row7.set_created(Time::UnixEpoch()); 783 EXPECT_TRUE(backend->InsertHistoryAndBookmark(row7)); 784 } 785 786 TEST_F(AndroidProviderBackendTest, UpdateURL) { 787 HistoryAndBookmarkRow row1; 788 row1.set_raw_url("cnn.com"); 789 row1.set_url(GURL("http://cnn.com")); 790 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 791 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 792 row1.set_visit_count(10); 793 row1.set_is_bookmark(true); 794 row1.set_title(UTF8ToUTF16("cnn")); 795 796 HistoryAndBookmarkRow row2; 797 row2.set_raw_url("http://www.example.com"); 798 row2.set_url(GURL("http://www.example.com")); 799 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 800 row2.set_is_bookmark(false); 801 row2.set_title(UTF8ToUTF16("example")); 802 std::vector<unsigned char> data; 803 data.push_back('1'); 804 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 805 806 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 807 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 808 &history_db_)); 809 scoped_ptr<AndroidProviderBackend> backend( 810 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 811 &thumbnail_db_, bookmark_model_, &delegate_)); 812 813 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 814 ASSERT_TRUE(id1); 815 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2); 816 ASSERT_TRUE(id2); 817 818 // Verify the row1 has been added in bookmark model. 819 content::RunAllPendingInMessageLoop(); 820 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 821 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 822 ASSERT_TRUE(child); 823 EXPECT_EQ(row1.title(), child->GetTitle()); 824 EXPECT_EQ(row1.url(), child->url()); 825 826 // Make sure the url has correctly insertted. 827 URLID url_id1 = history_db_.GetRowForURL(row1.url(), NULL); 828 ASSERT_TRUE(url_id1); 829 URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL); 830 ASSERT_TRUE(url_id2); 831 832 // Make sure we have the correct visit rows in visit table. 833 VisitVector visits; 834 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits)); 835 ASSERT_EQ(10u, visits.size()); 836 visits.clear(); 837 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits)); 838 ASSERT_EQ(1u, visits.size()); 839 840 int update_count; 841 std::vector<string16> update_args; 842 // Try to update the mutiple rows with the same URL, this should failed. 843 HistoryAndBookmarkRow update_row1; 844 update_row1.set_raw_url("newwebiste.com"); 845 update_row1.set_url(GURL("http://newwebsite.com")); 846 update_args.clear(); 847 ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row1, std::string(), 848 update_args, &update_count)); 849 850 // Only update one URL. 851 update_args.clear(); 852 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 853 delegate_.ResetDetails(); 854 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 855 update_args, &update_count)); 856 // Verify notifications, Update involves insert and delete URLS. 857 ASSERT_TRUE(delegate_.deleted_details()); 858 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size()); 859 EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url()); 860 EXPECT_EQ(row1.last_visit_time(), 861 delegate_.deleted_details()->rows[0].last_visit()); 862 EXPECT_EQ(row1.title(), 863 delegate_.deleted_details()->rows[0].title()); 864 ASSERT_TRUE(delegate_.modified_details()); 865 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 866 EXPECT_EQ(update_row1.url(), 867 delegate_.modified_details()->changed_urls[0].url()); 868 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 869 ToDatabaseTime( 870 delegate_.modified_details()->changed_urls[0].last_visit())); 871 EXPECT_EQ(row1.title(), 872 delegate_.modified_details()->changed_urls[0].title()); 873 EXPECT_FALSE(delegate_.favicon_details()); 874 875 EXPECT_EQ(1, update_count); 876 // We shouldn't find orignal url anymore. 877 EXPECT_FALSE(history_db_.GetRowForURL(row1.url(), NULL)); 878 visits.clear(); 879 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits)); 880 EXPECT_EQ(0u, visits.size()); 881 // Verify new URL. 882 URLRow new_row; 883 EXPECT_TRUE(history_db_.GetRowForURL(update_row1.url(), &new_row)); 884 EXPECT_EQ(10, new_row.visit_count()); 885 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 886 ToDatabaseTime(new_row.last_visit())); 887 visits.clear(); 888 EXPECT_TRUE(history_db_.GetVisitsForURL(new_row.id(), &visits)); 889 EXPECT_EQ(10u, visits.size()); 890 AndroidURLRow android_url_row1; 891 ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row.id(), &android_url_row1)); 892 // Android URL ID shouldn't change. 893 EXPECT_EQ(id1, android_url_row1.id); 894 895 // Verify the bookmark model was updated. 896 content::RunAllPendingInMessageLoop(); 897 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 898 const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0); 899 ASSERT_TRUE(child1); 900 EXPECT_EQ(row1.title(), child1->GetTitle()); 901 EXPECT_EQ(update_row1.url(), child1->url()); 902 903 // Update the URL with visit count, created time, and last visit time. 904 HistoryAndBookmarkRow update_row2; 905 update_row2.set_raw_url("somethingelse.com"); 906 update_row2.set_url(GURL("http://somethingelse.com")); 907 update_row2.set_last_visit_time(Time::Now()); 908 update_row2.set_created(Time::Now() - TimeDelta::FromDays(20)); 909 update_row2.set_visit_count(10); 910 911 update_args.clear(); 912 update_args.push_back(UTF8ToUTF16(row2.raw_url())); 913 delegate_.ResetDetails(); 914 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?", 915 update_args, &update_count)); 916 // Verify notifications, Update involves insert and delete URLS. 917 ASSERT_TRUE(delegate_.deleted_details()); 918 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size()); 919 EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url()); 920 EXPECT_EQ(row2.last_visit_time(), 921 delegate_.deleted_details()->rows[0].last_visit()); 922 EXPECT_EQ(row2.title(), 923 delegate_.deleted_details()->rows[0].title()); 924 ASSERT_TRUE(delegate_.modified_details()); 925 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 926 EXPECT_EQ(update_row2.url(), 927 delegate_.modified_details()->changed_urls[0].url()); 928 EXPECT_EQ(ToDatabaseTime(update_row2.last_visit_time()), 929 ToDatabaseTime( 930 delegate_.modified_details()->changed_urls[0].last_visit())); 931 EXPECT_EQ(update_row2.visit_count(), 932 delegate_.modified_details()->changed_urls[0].visit_count()); 933 ASSERT_TRUE(delegate_.favicon_details()); 934 ASSERT_EQ(2u, delegate_.favicon_details()->urls.size()); 935 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 936 delegate_.favicon_details()->urls.find(row2.url())); 937 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 938 delegate_.favicon_details()->urls.find(update_row2.url())); 939 940 EXPECT_EQ(1, update_count); 941 // We shouldn't find orignal url anymore. 942 EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL)); 943 visits.clear(); 944 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits)); 945 EXPECT_EQ(0u, visits.size()); 946 947 // Verify new URL. 948 URLRow new_row2; 949 ASSERT_TRUE(history_db_.GetRowForURL(update_row2.url(), &new_row2)); 950 EXPECT_EQ(10, new_row2.visit_count()); 951 EXPECT_EQ(update_row2.last_visit_time(), new_row2.last_visit()); 952 visits.clear(); 953 EXPECT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits)); 954 EXPECT_EQ(10u, visits.size()); 955 AndroidURLRow android_url_row2; 956 ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row2.id(), &android_url_row2)); 957 // Android URL ID shouldn't change. 958 EXPECT_EQ(id2, android_url_row2.id); 959 960 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits)); 961 ASSERT_EQ(10u, visits.size()); 962 EXPECT_EQ(update_row2.created(), visits[0].visit_time); 963 EXPECT_EQ(update_row2.last_visit_time(), visits[9].visit_time); 964 } 965 966 TEST_F(AndroidProviderBackendTest, UpdateVisitCount) { 967 HistoryAndBookmarkRow row1; 968 row1.set_raw_url("cnn.com"); 969 row1.set_url(GURL("http://cnn.com")); 970 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 971 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 972 row1.set_visit_count(10); 973 row1.set_is_bookmark(true); 974 row1.set_title(UTF8ToUTF16("cnn")); 975 976 HistoryAndBookmarkRow row2; 977 row2.set_raw_url("http://www.example.com"); 978 row2.set_url(GURL("http://www.example.com")); 979 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 980 row2.set_is_bookmark(false); 981 row2.set_title(UTF8ToUTF16("example")); 982 std::vector<unsigned char> data; 983 data.push_back('1'); 984 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 985 986 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 987 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 988 &history_db_)); 989 scoped_ptr<AndroidProviderBackend> backend( 990 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 991 &thumbnail_db_, bookmark_model_, &delegate_)); 992 993 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 994 ASSERT_TRUE(id1); 995 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2); 996 ASSERT_TRUE(id2); 997 998 int update_count; 999 std::vector<string16> update_args; 1000 // Update the visit_count to a value less than current one. 1001 HistoryAndBookmarkRow update_row1; 1002 update_row1.set_visit_count(5); 1003 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 1004 delegate_.ResetDetails(); 1005 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 1006 update_args, &update_count)); 1007 // Verify notifications, Update involves modified URL. 1008 EXPECT_FALSE(delegate_.deleted_details()); 1009 ASSERT_TRUE(delegate_.modified_details()); 1010 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 1011 EXPECT_EQ(row1.url(), 1012 delegate_.modified_details()->changed_urls[0].url()); 1013 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 1014 ToDatabaseTime( 1015 delegate_.modified_details()->changed_urls[0].last_visit())); 1016 EXPECT_EQ(update_row1.visit_count(), 1017 delegate_.modified_details()->changed_urls[0].visit_count()); 1018 EXPECT_FALSE(delegate_.favicon_details()); 1019 1020 // All visits should be removed, and 5 new visit insertted. 1021 URLRow new_row1; 1022 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1)); 1023 EXPECT_EQ(5, new_row1.visit_count()); 1024 VisitVector visits; 1025 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits)); 1026 ASSERT_EQ(5u, visits.size()); 1027 EXPECT_EQ(row1.last_visit_time(), visits[4].visit_time); 1028 EXPECT_GT(row1.last_visit_time(), visits[0].visit_time); 1029 1030 // Update the visit_count to a value equal to current one. 1031 HistoryAndBookmarkRow update_row2; 1032 update_row2.set_visit_count(1); 1033 update_args.clear(); 1034 update_args.push_back(UTF8ToUTF16(row2.raw_url())); 1035 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?", 1036 update_args, &update_count)); 1037 // All shouldn't have any change. 1038 URLRow new_row2; 1039 ASSERT_TRUE(history_db_.GetRowForURL(row2.url(), &new_row2)); 1040 EXPECT_EQ(1, new_row2.visit_count()); 1041 1042 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits)); 1043 ASSERT_EQ(1u, visits.size()); 1044 EXPECT_EQ(row2.last_visit_time(), visits[0].visit_time); 1045 } 1046 1047 TEST_F(AndroidProviderBackendTest, UpdateLastVisitTime) { 1048 HistoryAndBookmarkRow row1; 1049 row1.set_raw_url("cnn.com"); 1050 row1.set_url(GURL("http://cnn.com")); 1051 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1052 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1053 row1.set_visit_count(10); 1054 row1.set_is_bookmark(true); 1055 row1.set_title(UTF8ToUTF16("cnn")); 1056 1057 HistoryAndBookmarkRow row2; 1058 row2.set_raw_url("http://www.example.com"); 1059 row2.set_url(GURL("http://www.example.com")); 1060 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1061 row2.set_is_bookmark(false); 1062 row2.set_title(UTF8ToUTF16("example")); 1063 std::vector<unsigned char> data; 1064 data.push_back('1'); 1065 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1066 1067 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1068 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1069 &history_db_)); 1070 scoped_ptr<AndroidProviderBackend> backend( 1071 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1072 &thumbnail_db_, bookmark_model_, &delegate_)); 1073 1074 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 1075 ASSERT_TRUE(id1); 1076 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2); 1077 ASSERT_TRUE(id2); 1078 1079 int update_count; 1080 std::vector<string16> update_args; 1081 // Update the last visit time to a value greater than current one. 1082 HistoryAndBookmarkRow update_row1; 1083 update_row1.set_last_visit_time(Time::Now()); 1084 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 1085 delegate_.ResetDetails(); 1086 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 1087 update_args, &update_count)); 1088 // Verify notifications, Update involves modified URL. 1089 EXPECT_FALSE(delegate_.deleted_details()); 1090 ASSERT_TRUE(delegate_.modified_details()); 1091 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 1092 EXPECT_EQ(row1.url(), 1093 delegate_.modified_details()->changed_urls[0].url()); 1094 EXPECT_EQ(ToDatabaseTime(update_row1.last_visit_time()), 1095 ToDatabaseTime( 1096 delegate_.modified_details()->changed_urls[0].last_visit())); 1097 EXPECT_FALSE(delegate_.favicon_details()); 1098 1099 URLRow new_row1; 1100 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1)); 1101 EXPECT_EQ(11, new_row1.visit_count()); 1102 EXPECT_EQ(update_row1.last_visit_time(), new_row1.last_visit()); 1103 VisitVector visits; 1104 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits)); 1105 // 1 new visit insertted. 1106 ASSERT_EQ(11u, visits.size()); 1107 EXPECT_EQ(update_row1.last_visit_time(), visits[10].visit_time); 1108 EXPECT_EQ(row1.last_visit_time(), visits[9].visit_time); 1109 1110 // Update the visit_tim to a value less than to current one. 1111 HistoryAndBookmarkRow update_row2; 1112 update_row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1113 update_args.clear(); 1114 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 1115 ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?", 1116 update_args, &update_count)); 1117 } 1118 1119 TEST_F(AndroidProviderBackendTest, UpdateFavicon) { 1120 HistoryAndBookmarkRow row1; 1121 row1.set_raw_url("cnn.com"); 1122 row1.set_url(GURL("http://cnn.com")); 1123 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1124 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1125 row1.set_visit_count(10); 1126 row1.set_is_bookmark(true); 1127 row1.set_title(UTF8ToUTF16("cnn")); 1128 1129 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1130 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1131 &history_db_)); 1132 scoped_ptr<AndroidProviderBackend> backend( 1133 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1134 &thumbnail_db_, bookmark_model_, &delegate_)); 1135 1136 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 1137 ASSERT_TRUE(id1); 1138 1139 int update_count; 1140 std::vector<string16> update_args; 1141 // Update the last visit time to a value greater than current one. 1142 HistoryAndBookmarkRow update_row1; 1143 1144 // Set favicon. 1145 std::vector<unsigned char> data; 1146 data.push_back('1'); 1147 update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1148 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 1149 delegate_.ResetDetails(); 1150 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 1151 update_args, &update_count)); 1152 // Verify notifications. 1153 EXPECT_FALSE(delegate_.deleted_details()); 1154 EXPECT_FALSE(delegate_.modified_details()); 1155 ASSERT_TRUE(delegate_.favicon_details()); 1156 ASSERT_EQ(1u, delegate_.favicon_details()->urls.size()); 1157 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 1158 delegate_.favicon_details()->urls.find(row1.url())); 1159 1160 std::vector<IconMapping> icon_mappings; 1161 EXPECT_TRUE(thumbnail_db_.GetIconMappingsForPageURL( 1162 row1.url(), chrome::FAVICON, &icon_mappings)); 1163 EXPECT_EQ(1u, icon_mappings.size()); 1164 std::vector<FaviconBitmap> favicon_bitmaps; 1165 EXPECT_TRUE(thumbnail_db_.GetFaviconBitmaps(icon_mappings[0].icon_id, 1166 &favicon_bitmaps)); 1167 EXPECT_EQ(1u, favicon_bitmaps.size()); 1168 EXPECT_TRUE(favicon_bitmaps[0].bitmap_data.get()); 1169 EXPECT_EQ(1u, favicon_bitmaps[0].bitmap_data->size()); 1170 EXPECT_EQ('1', *favicon_bitmaps[0].bitmap_data->front()); 1171 1172 // Remove favicon. 1173 HistoryAndBookmarkRow update_row2; 1174 1175 // Set favicon. 1176 update_row1.set_favicon(new base::RefCountedBytes()); 1177 update_args.clear(); 1178 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 1179 delegate_.ResetDetails(); 1180 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 1181 update_args, &update_count)); 1182 // Verify notifications. 1183 EXPECT_FALSE(delegate_.deleted_details()); 1184 EXPECT_FALSE(delegate_.modified_details()); 1185 ASSERT_TRUE(delegate_.favicon_details()); 1186 ASSERT_EQ(1u, delegate_.favicon_details()->urls.size()); 1187 ASSERT_TRUE(delegate_.favicon_details()->urls.end() != 1188 delegate_.favicon_details()->urls.find(row1.url())); 1189 1190 EXPECT_FALSE(thumbnail_db_.GetIconMappingsForPageURL( 1191 row1.url(), chrome::FAVICON, NULL)); 1192 } 1193 1194 TEST_F(AndroidProviderBackendTest, UpdateSearchTermTable) { 1195 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1196 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1197 &history_db_)); 1198 scoped_ptr<AndroidProviderBackend> backend( 1199 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1200 &thumbnail_db_, bookmark_model_, &delegate_)); 1201 // Insert a keyword search item to verify if the update succeeds. 1202 HistoryAndBookmarkRow row1; 1203 row1.set_raw_url("cnn.com"); 1204 row1.set_url(GURL("http://cnn.com")); 1205 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1206 row1.set_title(UTF8ToUTF16("cnn")); 1207 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1208 string16 term = UTF8ToUTF16("Search term 1"); 1209 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL); 1210 ASSERT_TRUE(url_id); 1211 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term)); 1212 ASSERT_TRUE(backend->UpdateSearchTermTable()); 1213 SearchTermRow keyword_cache; 1214 SearchTermID id = history_db_.GetSearchTerm(term, &keyword_cache); 1215 ASSERT_TRUE(id); 1216 EXPECT_EQ(term, keyword_cache.term); 1217 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 1218 ToDatabaseTime(keyword_cache.last_visit_time)); 1219 1220 // Add another row. 1221 HistoryAndBookmarkRow row2; 1222 row2.set_raw_url("google.com"); 1223 row2.set_url(GURL("http://google.com")); 1224 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(2)); 1225 row2.set_title(UTF8ToUTF16("cnn")); 1226 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 1227 url_id = history_db_.GetRowForURL(row2.url(), NULL); 1228 ASSERT_TRUE(url_id); 1229 string16 term2 = UTF8ToUTF16("Search term 2"); 1230 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term2)); 1231 ASSERT_TRUE(backend->UpdateSearchTermTable()); 1232 SearchTermID search_id1 = history_db_.GetSearchTerm(term, 1233 &keyword_cache); 1234 // The id shouldn't changed. 1235 ASSERT_EQ(id, search_id1); 1236 EXPECT_EQ(term, keyword_cache.term); 1237 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 1238 ToDatabaseTime(keyword_cache.last_visit_time)); 1239 // Verify the row just inserted. 1240 SearchTermID id2 = history_db_.GetSearchTerm(term2, &keyword_cache); 1241 ASSERT_TRUE(id2); 1242 EXPECT_EQ(term2, keyword_cache.term); 1243 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()), 1244 ToDatabaseTime(keyword_cache.last_visit_time)); 1245 1246 // Add 3rd row and associate it with term. 1247 HistoryAndBookmarkRow row3; 1248 row3.set_raw_url("search.com"); 1249 row3.set_url(GURL("http://search.com")); 1250 row3.set_last_visit_time(Time::Now()); 1251 row3.set_title(UTF8ToUTF16("search")); 1252 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row3)); 1253 url_id = history_db_.GetRowForURL(row3.url(), NULL); 1254 ASSERT_TRUE(url_id); 1255 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term)); 1256 ASSERT_TRUE(backend->UpdateSearchTermTable()); 1257 // Verify id not changed and last_visit_time updated. 1258 ASSERT_EQ(search_id1, history_db_.GetSearchTerm(term, &keyword_cache)); 1259 EXPECT_EQ(ToDatabaseTime(row3.last_visit_time()), 1260 ToDatabaseTime(keyword_cache.last_visit_time)); 1261 // The id of term2 wasn't changed. 1262 EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL)); 1263 1264 // Remove the term. 1265 ASSERT_TRUE(history_db_.DeleteKeywordSearchTerm(term)); 1266 ASSERT_TRUE(backend->UpdateSearchTermTable()); 1267 // The cache of term should removed. 1268 ASSERT_FALSE(history_db_.GetSearchTerm(term, NULL)); 1269 // The id of term2 wasn't changed. 1270 EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL)); 1271 } 1272 1273 TEST_F(AndroidProviderBackendTest, QuerySearchTerms) { 1274 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1275 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1276 &history_db_)); 1277 scoped_ptr<AndroidProviderBackend> backend( 1278 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1279 &thumbnail_db_, bookmark_model_, &delegate_)); 1280 // Insert a keyword search item to verify if we can find it. 1281 HistoryAndBookmarkRow row1; 1282 row1.set_raw_url("cnn.com"); 1283 row1.set_url(GURL("http://cnn.com")); 1284 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1285 row1.set_title(UTF8ToUTF16("cnn")); 1286 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1287 string16 term = UTF8ToUTF16("Search term 1"); 1288 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL); 1289 ASSERT_TRUE(url_id); 1290 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term)); 1291 1292 std::vector<SearchRow::ColumnID> projections; 1293 projections.push_back(SearchRow::ID); 1294 projections.push_back(SearchRow::SEARCH_TERM); 1295 projections.push_back(SearchRow::SEARCH_TIME); 1296 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms( 1297 projections, std::string(), std::vector<string16>(), std::string())); 1298 ASSERT_TRUE(statement.get()); 1299 ASSERT_TRUE(statement->statement()->Step()); 1300 EXPECT_TRUE(statement->statement()->ColumnInt64(0)); 1301 EXPECT_EQ(term, statement->statement()->ColumnString16(1)); 1302 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()), 1303 statement->statement()->ColumnInt64(2)); 1304 EXPECT_FALSE(statement->statement()->Step()); 1305 } 1306 1307 TEST_F(AndroidProviderBackendTest, UpdateSearchTerms) { 1308 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1309 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1310 &history_db_)); 1311 scoped_ptr<AndroidProviderBackend> backend( 1312 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1313 &thumbnail_db_, bookmark_model_, &delegate_)); 1314 // Insert a keyword. 1315 HistoryAndBookmarkRow row1; 1316 row1.set_raw_url("cnn.com"); 1317 row1.set_url(GURL("http://cnn.com")); 1318 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1319 row1.set_title(UTF8ToUTF16("cnn")); 1320 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1321 string16 term = UTF8ToUTF16("Search term 1"); 1322 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL); 1323 ASSERT_TRUE(url_id); 1324 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term)); 1325 1326 // Get the SearchTermID of the row we just inserted. 1327 std::vector<SearchRow::ColumnID> projections; 1328 projections.push_back(SearchRow::ID); 1329 projections.push_back(SearchRow::SEARCH_TIME); 1330 projections.push_back(SearchRow::SEARCH_TERM); 1331 std::vector<string16> args; 1332 args.push_back(term); 1333 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms( 1334 projections, "search = ?", args, std::string())); 1335 ASSERT_TRUE(statement.get()); 1336 ASSERT_TRUE(statement->statement()->Step()); 1337 SearchTermID id = statement->statement()->ColumnInt64(0); 1338 ASSERT_TRUE(id); 1339 EXPECT_FALSE(statement->statement()->Step()); 1340 1341 // Update the search term and time. 1342 string16 update_term = UTF8ToUTF16("Update search term"); 1343 args.clear(); 1344 args.push_back(term); 1345 SearchRow search_row; 1346 search_row.set_search_term(update_term); 1347 search_row.set_url(GURL("http://google.com")); 1348 search_row.set_template_url_id(1); 1349 search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1)); 1350 int update_count = 0; 1351 ASSERT_TRUE(backend->UpdateSearchTerms(search_row, "search = ?", args, 1352 &update_count)); 1353 EXPECT_EQ(1, update_count); 1354 1355 // Verify if the search term updated. 1356 // The origin term should be removed. 1357 std::vector<KeywordSearchTermRow> rows; 1358 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows)); 1359 EXPECT_TRUE(rows.empty()); 1360 // The new term should be inserted. 1361 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(update_term, &rows)); 1362 ASSERT_EQ(1u, rows.size()); 1363 // The history of urls shouldn't be removed. 1364 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), NULL)); 1365 // The new URL is inserted. 1366 ASSERT_TRUE(history_db_.GetRowForURL(search_row.url(), NULL)); 1367 1368 // Verfiy the AndoridSearchID isn't changed. 1369 args.clear(); 1370 args.push_back(update_term); 1371 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args, 1372 std::string())); 1373 ASSERT_TRUE(statement.get()); 1374 ASSERT_TRUE(statement->statement()->Step()); 1375 // The id didn't change. 1376 EXPECT_EQ(id, statement->statement()->ColumnInt64(0)); 1377 // The search time was updated. 1378 EXPECT_EQ(ToDatabaseTime(search_row.search_time()), 1379 statement->statement()->ColumnInt64(1)); 1380 // The search term was updated. 1381 EXPECT_EQ(update_term, statement->statement()->ColumnString16(2)); 1382 EXPECT_FALSE(statement->statement()->Step()); 1383 1384 // Only update the search time. 1385 SearchRow update_time; 1386 update_time.set_search_time(Time::Now()); 1387 // Update it by id. 1388 args.clear(); 1389 std::ostringstream oss; 1390 oss << id; 1391 args.push_back(UTF8ToUTF16(oss.str())); 1392 update_count = 0; 1393 ASSERT_TRUE(backend->UpdateSearchTerms(update_time, "_id = ?", args, 1394 &update_count)); 1395 EXPECT_EQ(1, update_count); 1396 1397 // Verify the update. 1398 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args, 1399 std::string())); 1400 ASSERT_TRUE(statement.get()); 1401 ASSERT_TRUE(statement->statement()->Step()); 1402 // The id didn't change. 1403 EXPECT_EQ(id, statement->statement()->ColumnInt64(0)); 1404 // The search time was updated. 1405 EXPECT_EQ(ToDatabaseTime(update_time.search_time()), 1406 statement->statement()->ColumnInt64(1)); 1407 // The search term didn't change. 1408 EXPECT_EQ(update_term, statement->statement()->ColumnString16(2)); 1409 EXPECT_FALSE(statement->statement()->Step()); 1410 } 1411 1412 TEST_F(AndroidProviderBackendTest, DeleteSearchTerms) { 1413 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1414 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1415 &history_db_)); 1416 scoped_ptr<AndroidProviderBackend> backend( 1417 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1418 &thumbnail_db_, bookmark_model_, &delegate_)); 1419 // Insert a keyword. 1420 HistoryAndBookmarkRow row1; 1421 row1.set_raw_url("cnn.com"); 1422 row1.set_url(GURL("http://cnn.com")); 1423 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1424 row1.set_title(UTF8ToUTF16("cnn")); 1425 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1426 string16 term = UTF8ToUTF16("Search term 1"); 1427 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL); 1428 ASSERT_TRUE(url_id); 1429 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term)); 1430 1431 // Get the SearchTermID of the row we just inserted. 1432 std::vector<SearchRow::ColumnID> projections; 1433 projections.push_back(SearchRow::ID); 1434 projections.push_back(SearchRow::SEARCH_TIME); 1435 projections.push_back(SearchRow::SEARCH_TERM); 1436 std::vector<string16> args; 1437 args.push_back(term); 1438 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms( 1439 projections, "search = ?", args, std::string())); 1440 ASSERT_TRUE(statement.get()); 1441 ASSERT_TRUE(statement->statement()->Step()); 1442 SearchTermID id1 = statement->statement()->ColumnInt64(0); 1443 ASSERT_TRUE(id1); 1444 EXPECT_FALSE(statement->statement()->Step()); 1445 1446 // Insert a keyword. 1447 HistoryAndBookmarkRow row2; 1448 row2.set_raw_url("google.com"); 1449 row2.set_url(GURL("http://google.com")); 1450 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1451 row2.set_title(UTF8ToUTF16("google")); 1452 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 1453 string16 term2 = UTF8ToUTF16("Search term 2"); 1454 URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL); 1455 ASSERT_TRUE(url_id2); 1456 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id2, 1, term2)); 1457 1458 // Get the SearchTermID of the row we just inserted. 1459 projections.clear(); 1460 projections.push_back(SearchRow::ID); 1461 projections.push_back(SearchRow::SEARCH_TIME); 1462 projections.push_back(SearchRow::SEARCH_TERM); 1463 args.clear(); 1464 args.push_back(term2); 1465 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args, 1466 std::string())); 1467 ASSERT_TRUE(statement.get()); 1468 ASSERT_TRUE(statement->statement()->Step()); 1469 SearchTermID id2 = statement->statement()->ColumnInt64(0); 1470 ASSERT_TRUE(id2); 1471 EXPECT_FALSE(statement->statement()->Step()); 1472 1473 // Delete the first one. 1474 args.clear(); 1475 args.push_back(term); 1476 int deleted_count = 0; 1477 ASSERT_TRUE(backend->DeleteSearchTerms("search = ?", args, &deleted_count)); 1478 EXPECT_EQ(1, deleted_count); 1479 std::vector<KeywordSearchTermRow> rows; 1480 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows)); 1481 EXPECT_TRUE(rows.empty()); 1482 // Verify we can't get the first term. 1483 args.clear(); 1484 std::ostringstream oss; 1485 oss << id1; 1486 args.push_back(UTF8ToUTF16(oss.str())); 1487 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args, 1488 std::string())); 1489 ASSERT_TRUE(statement.get()); 1490 EXPECT_FALSE(statement->statement()->Step()); 1491 1492 // The second one is still there. 1493 args.clear(); 1494 std::ostringstream oss1; 1495 oss1 << id2; 1496 args.push_back(UTF8ToUTF16(oss1.str())); 1497 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args, 1498 std::string())); 1499 ASSERT_TRUE(statement.get()); 1500 EXPECT_TRUE(statement->statement()->Step()); 1501 EXPECT_EQ(id2, statement->statement()->ColumnInt64(0)); 1502 EXPECT_FALSE(statement->statement()->Step()); 1503 1504 // Remove all search terms in no condition. 1505 deleted_count = 0; 1506 args.clear(); 1507 ASSERT_TRUE(backend->DeleteSearchTerms(std::string(), args, &deleted_count)); 1508 EXPECT_EQ(1, deleted_count); 1509 1510 // Verify the second one was removed. 1511 args.clear(); 1512 args.push_back(UTF8ToUTF16(oss1.str())); 1513 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args, 1514 std::string())); 1515 ASSERT_TRUE(statement.get()); 1516 EXPECT_FALSE(statement->statement()->Step()); 1517 } 1518 1519 TEST_F(AndroidProviderBackendTest, InsertSearchTerm) { 1520 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1521 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1522 &history_db_)); 1523 scoped_ptr<AndroidProviderBackend> backend( 1524 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1525 &thumbnail_db_, bookmark_model_, &delegate_)); 1526 SearchRow search_row; 1527 search_row.set_search_term(UTF8ToUTF16("google")); 1528 search_row.set_url(GURL("http://google.com")); 1529 search_row.set_template_url_id(1); 1530 search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1)); 1531 1532 SearchTermID id = backend->InsertSearchTerm(search_row); 1533 ASSERT_TRUE(id); 1534 1535 std::vector<SearchRow::ColumnID> projections; 1536 projections.push_back(SearchRow::ID); 1537 projections.push_back(SearchRow::SEARCH_TIME); 1538 projections.push_back(SearchRow::SEARCH_TERM); 1539 std::vector<string16> args; 1540 std::ostringstream oss; 1541 oss << id; 1542 args.push_back(UTF8ToUTF16(oss.str())); 1543 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms( 1544 projections, "_id = ?", args, std::string())); 1545 ASSERT_TRUE(statement.get()); 1546 ASSERT_TRUE(statement->statement()->Step()); 1547 EXPECT_EQ(id, statement->statement()->ColumnInt64(0)); 1548 EXPECT_EQ(ToDatabaseTime(search_row.search_time()), 1549 statement->statement()->ColumnInt64(1)); 1550 EXPECT_EQ(search_row.search_term(), 1551 statement->statement()->ColumnString16(2)); 1552 EXPECT_FALSE(statement->statement()->Step()); 1553 } 1554 1555 TEST_F(AndroidProviderBackendTest, DeleteHistory) { 1556 HistoryAndBookmarkRow row1; 1557 row1.set_raw_url("cnn.com"); 1558 row1.set_url(GURL("http://cnn.com")); 1559 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1560 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1561 row1.set_visit_count(10); 1562 row1.set_is_bookmark(true); 1563 row1.set_title(UTF8ToUTF16("cnn")); 1564 1565 HistoryAndBookmarkRow row2; 1566 row2.set_raw_url("http://www.example.com"); 1567 row2.set_url(GURL("http://www.example.com")); 1568 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1569 row2.set_is_bookmark(false); 1570 row2.set_title(UTF8ToUTF16("example")); 1571 std::vector<unsigned char> data; 1572 data.push_back('1'); 1573 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1574 1575 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1576 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1577 &history_db_)); 1578 scoped_ptr<AndroidProviderBackend> backend( 1579 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1580 &thumbnail_db_, bookmark_model_, &delegate_)); 1581 1582 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 1583 ASSERT_TRUE(id1); 1584 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2); 1585 ASSERT_TRUE(id2); 1586 1587 // Verify the row1 has been added in bookmark model. 1588 content::RunAllPendingInMessageLoop(); 1589 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 1590 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 1591 ASSERT_TRUE(child); 1592 EXPECT_EQ(row1.title(), child->GetTitle()); 1593 EXPECT_EQ(row1.url(), child->url()); 1594 1595 // Delete history 1596 int deleted_count = 0; 1597 ASSERT_TRUE(backend->DeleteHistory(std::string(), std::vector<string16>(), 1598 &deleted_count)); 1599 EXPECT_EQ(2, deleted_count); 1600 // The row2 was deleted. 1601 EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL)); 1602 // Still find the row1. 1603 URLRow url_row; 1604 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &url_row)); 1605 // The visit_count was reset. 1606 EXPECT_EQ(0, url_row.visit_count()); 1607 EXPECT_EQ(Time::UnixEpoch(), url_row.last_visit()); 1608 1609 // Verify the row1 is still in bookmark model. 1610 content::RunAllPendingInMessageLoop(); 1611 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 1612 const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0); 1613 ASSERT_TRUE(child1); 1614 EXPECT_EQ(row1.title(), child1->GetTitle()); 1615 EXPECT_EQ(row1.url(), child1->url()); 1616 1617 // Verify notification 1618 ASSERT_TRUE(delegate_.deleted_details()); 1619 ASSERT_EQ(2u, delegate_.deleted_details()->rows.size()); 1620 EXPECT_EQ(row1.url(), 1621 delegate_.modified_details()->changed_urls[0].url()); 1622 EXPECT_EQ(Time::UnixEpoch(), 1623 delegate_.modified_details()->changed_urls[0].last_visit()); 1624 EXPECT_EQ(1u, delegate_.favicon_details()->urls.size()); 1625 } 1626 1627 TEST_F(AndroidProviderBackendTest, TestMultipleNestingTransaction) { 1628 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1629 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1630 &history_db_)); 1631 scoped_ptr<AndroidProviderBackend> backend( 1632 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1633 &thumbnail_db_, bookmark_model_, &delegate_)); 1634 1635 // Create the nested transactions. 1636 history_db_.BeginTransaction(); 1637 history_db_.BeginTransaction(); 1638 history_db_.BeginTransaction(); 1639 thumbnail_db_.BeginTransaction(); 1640 thumbnail_db_.BeginTransaction(); 1641 int history_transaction = history_db_.transaction_nesting(); 1642 int thumbnail_transaction = thumbnail_db_.transaction_nesting(); 1643 1644 // Insert a row to verify the transaction number are not changed 1645 // after a transaction commit. 1646 HistoryAndBookmarkRow row1; 1647 row1.set_raw_url("cnn.com"); 1648 row1.set_url(GURL("http://cnn.com")); 1649 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1650 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1651 row1.set_visit_count(10); 1652 row1.set_title(UTF8ToUTF16("cnn")); 1653 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1654 EXPECT_EQ(history_transaction, history_db_.transaction_nesting()); 1655 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting()); 1656 1657 // Insert the same URL, it should failed. The transaction are still same 1658 // after a rollback. 1659 ASSERT_FALSE(backend->InsertHistoryAndBookmark(row1)); 1660 EXPECT_EQ(history_transaction, history_db_.transaction_nesting()); 1661 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting()); 1662 1663 // Insert another row to verify we are still fine after the previous 1664 // rollback. 1665 HistoryAndBookmarkRow row2; 1666 row2.set_raw_url("http://www.example.com"); 1667 row2.set_url(GURL("http://www.example.com")); 1668 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1669 row2.set_is_bookmark(false); 1670 row2.set_title(UTF8ToUTF16("example")); 1671 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 1672 EXPECT_EQ(history_transaction, history_db_.transaction_nesting()); 1673 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting()); 1674 } 1675 1676 TEST_F(AndroidProviderBackendTest, TestAndroidCTSComplianceForZeroVisitCount) { 1677 // This is to verify the last visit time and created time are same when visit 1678 // count is 0. 1679 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1680 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1681 &history_db_)); 1682 scoped_ptr<AndroidProviderBackend> backend( 1683 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1684 &thumbnail_db_, bookmark_model_, &delegate_)); 1685 URLRow url_row(GURL("http://www.google.com")); 1686 url_row.set_last_visit(Time::Now()); 1687 url_row.set_visit_count(0); 1688 history_db_.AddURL(url_row); 1689 1690 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 1691 1692 projections.push_back(HistoryAndBookmarkRow::ID); 1693 projections.push_back(HistoryAndBookmarkRow::URL); 1694 projections.push_back(HistoryAndBookmarkRow::TITLE); 1695 projections.push_back(HistoryAndBookmarkRow::CREATED); 1696 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 1697 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 1698 projections.push_back(HistoryAndBookmarkRow::FAVICON); 1699 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 1700 1701 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 1702 projections, std::string(), std::vector<string16>(), 1703 std::string("url ASC"))); 1704 1705 ASSERT_TRUE(statement->statement()->Step()); 1706 EXPECT_EQ(ToDatabaseTime(url_row.last_visit()), 1707 statement->statement()->ColumnInt64(3)); 1708 EXPECT_EQ(ToDatabaseTime(url_row.last_visit()), 1709 statement->statement()->ColumnInt64(4)); 1710 EXPECT_EQ(url_row.visit_count(), statement->statement()->ColumnInt(5)); 1711 } 1712 1713 TEST_F(AndroidProviderBackendTest, AndroidCTSComplianceFolderColumnExists) { 1714 // This is test is used to verify the 'folder' column exists, all bookmarks 1715 // returned when folder is 0 and the non bookmark rows returned when folder 1716 // is 1. 1717 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1718 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL, 1719 &history_db_)); 1720 scoped_ptr<AndroidProviderBackend> backend( 1721 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1722 &thumbnail_db_, bookmark_model_, &delegate_)); 1723 HistoryAndBookmarkRow row1; 1724 row1.set_raw_url("cnn.com"); 1725 row1.set_url(GURL("http://cnn.com")); 1726 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1727 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1728 row1.set_visit_count(10); 1729 row1.set_is_bookmark(true); 1730 row1.set_title(UTF8ToUTF16("cnn")); 1731 1732 HistoryAndBookmarkRow row2; 1733 row2.set_raw_url("http://www.example.com"); 1734 row2.set_url(GURL("http://www.example.com")); 1735 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1736 row2.set_is_bookmark(false); 1737 row2.set_title(UTF8ToUTF16("example")); 1738 std::vector<unsigned char> data; 1739 data.push_back('1'); 1740 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1741 1742 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 1743 ASSERT_TRUE(id1); 1744 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2); 1745 ASSERT_TRUE(id2); 1746 content::RunAllPendingInMessageLoop(); 1747 1748 // Query by folder=0, the row1 should returned. 1749 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 1750 1751 projections.push_back(HistoryAndBookmarkRow::URL); 1752 1753 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 1754 projections, std::string("folder=0"), std::vector<string16>(), 1755 std::string("url ASC"))); 1756 ASSERT_TRUE(statement->statement()->Step()); 1757 EXPECT_EQ(row1.raw_url(), statement->statement()->ColumnString(0)); 1758 EXPECT_FALSE(statement->statement()->Step()); 1759 1760 // Query by folder=1, the row2 should returned. 1761 statement.reset(backend->QueryHistoryAndBookmarks( 1762 projections, std::string("folder=1"), std::vector<string16>(), 1763 std::string("url ASC"))); 1764 ASSERT_TRUE(statement->statement()->Step()); 1765 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(0))); 1766 EXPECT_FALSE(statement->statement()->Step()); 1767 } 1768 1769 TEST_F(AndroidProviderBackendTest, QueryWithoutThumbnailDB) { 1770 GURL url1("http://www.cnn.com"); 1771 URLID url_id1 = 0; 1772 const string16 title1(UTF8ToUTF16("cnn")); 1773 std::vector<VisitInfo> visits1; 1774 Time last_visited1 = Time::Now() - TimeDelta::FromDays(1); 1775 Time created1 = last_visited1 - TimeDelta::FromDays(20); 1776 visits1.push_back(VisitInfo(created1, content::PAGE_TRANSITION_LINK)); 1777 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1), 1778 content::PAGE_TRANSITION_LINK)); 1779 visits1.push_back(VisitInfo(last_visited1, content::PAGE_TRANSITION_LINK)); 1780 1781 GURL url2("http://www.example.com"); 1782 URLID url_id2 = 0; 1783 std::vector<VisitInfo> visits2; 1784 const string16 title2(UTF8ToUTF16("example")); 1785 Time last_visited2 = Time::Now(); 1786 Time created2 = last_visited2 - TimeDelta::FromDays(10); 1787 visits2.push_back(VisitInfo(created2, content::PAGE_TRANSITION_LINK)); 1788 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5), 1789 content::PAGE_TRANSITION_LINK)); 1790 visits2.push_back(VisitInfo(last_visited2, content::PAGE_TRANSITION_LINK)); 1791 1792 // Only use the HistoryBackend to generate the test data. 1793 // HistoryBackend will shutdown after that. 1794 { 1795 scoped_refptr<HistoryBackend> history_backend; 1796 history_backend = new HistoryBackend(temp_dir_.path(), 0, 1797 new AndroidProviderBackendDelegate(), bookmark_model_); 1798 history_backend->Init(std::string(), false); 1799 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED); 1800 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED); 1801 URLRow url_row; 1802 1803 ASSERT_TRUE(history_backend->GetURL(url1, &url_row)); 1804 url_id1 = url_row.id(); 1805 url_row.set_title(title1); 1806 ASSERT_TRUE(history_backend->UpdateURL(url_id1, url_row)); 1807 1808 ASSERT_TRUE(history_backend->GetURL(url2, &url_row)); 1809 url_id2 = url_row.id(); 1810 url_row.set_title(title2); 1811 ASSERT_TRUE(history_backend->UpdateURL(url_id2, url_row)); 1812 1813 // Set favicon to url2. 1814 std::vector<unsigned char> data; 1815 data.push_back('1'); 1816 chrome::FaviconBitmapData bitmap_data_element; 1817 bitmap_data_element.bitmap_data = new base::RefCountedBytes(data); 1818 bitmap_data_element.pixel_size = gfx::Size(); 1819 bitmap_data_element.icon_url = GURL(); 1820 std::vector<chrome::FaviconBitmapData> favicon_bitmap_data; 1821 favicon_bitmap_data.push_back(bitmap_data_element); 1822 1823 history_backend->SetFavicons(url2, chrome::FAVICON, favicon_bitmap_data); 1824 history_backend->Closing(); 1825 } 1826 1827 // The history_db_name and thumbnail_db_name files should be created by 1828 // HistoryBackend. We need to open the same database files. 1829 ASSERT_TRUE(base::PathExists(history_db_name_)); 1830 ASSERT_TRUE(base::PathExists(thumbnail_db_name_)); 1831 1832 // Only creates the history database 1833 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1834 1835 // Set url1 as bookmark. 1836 AddBookmark(url1); 1837 1838 scoped_ptr<AndroidProviderBackend> backend( 1839 new AndroidProviderBackend(android_cache_db_name_, &history_db_, NULL, 1840 bookmark_model_, &delegate_)); 1841 1842 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 1843 1844 projections.push_back(HistoryAndBookmarkRow::ID); 1845 projections.push_back(HistoryAndBookmarkRow::URL); 1846 projections.push_back(HistoryAndBookmarkRow::TITLE); 1847 projections.push_back(HistoryAndBookmarkRow::CREATED); 1848 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 1849 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 1850 projections.push_back(HistoryAndBookmarkRow::FAVICON); 1851 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 1852 1853 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks( 1854 projections, std::string(), std::vector<string16>(), 1855 std::string("url ASC"))); 1856 ASSERT_TRUE(statement->statement()->Step()); 1857 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1))); 1858 EXPECT_EQ(title1, statement->statement()->ColumnString16(2)); 1859 EXPECT_EQ(ToDatabaseTime(created1), 1860 statement->statement()->ColumnInt64(3)); 1861 EXPECT_EQ(ToDatabaseTime(last_visited1), 1862 statement->statement()->ColumnInt64(4)); 1863 EXPECT_EQ(3, statement->statement()->ColumnInt(5)); 1864 EXPECT_EQ(6, statement->favicon_index()); 1865 // No favicon. 1866 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6)); 1867 EXPECT_TRUE(statement->statement()->ColumnBool(7)); 1868 1869 ASSERT_TRUE(statement->statement()->Step()); 1870 EXPECT_EQ(title2, statement->statement()->ColumnString16(2)); 1871 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1))); 1872 EXPECT_EQ(ToDatabaseTime(created2), 1873 statement->statement()->ColumnInt64(3)); 1874 EXPECT_EQ(ToDatabaseTime(last_visited2), 1875 statement->statement()->ColumnInt64(4)); 1876 EXPECT_EQ(3, statement->statement()->ColumnInt(5)); 1877 std::vector<unsigned char> favicon2; 1878 EXPECT_EQ(6, statement->favicon_index()); 1879 // No favicon because thumbnail database wasn't initialized. 1880 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6)); 1881 EXPECT_FALSE(statement->statement()->ColumnBool(7)); 1882 1883 // No more row. 1884 EXPECT_FALSE(statement->statement()->Step()); 1885 } 1886 1887 TEST_F(AndroidProviderBackendTest, InsertWithoutThumbnailDB) { 1888 HistoryAndBookmarkRow row1; 1889 row1.set_raw_url("cnn.com"); 1890 row1.set_url(GURL("http://cnn.com")); 1891 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1892 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1893 row1.set_visit_count(10); 1894 row1.set_is_bookmark(true); 1895 row1.set_title(UTF8ToUTF16("cnn")); 1896 1897 HistoryAndBookmarkRow row2; 1898 row2.set_raw_url("http://www.example.com"); 1899 row2.set_url(GURL("http://www.example.com")); 1900 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1901 row2.set_is_bookmark(false); 1902 row2.set_title(UTF8ToUTF16("example")); 1903 std::vector<unsigned char> data; 1904 data.push_back('1'); 1905 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1906 1907 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1908 scoped_ptr<AndroidProviderBackend> backend( 1909 new AndroidProviderBackend(android_cache_db_name_, &history_db_, NULL, 1910 bookmark_model_, &delegate_)); 1911 1912 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1913 EXPECT_FALSE(delegate_.deleted_details()); 1914 ASSERT_TRUE(delegate_.modified_details()); 1915 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 1916 EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url()); 1917 EXPECT_EQ(row1.last_visit_time(), 1918 delegate_.modified_details()->changed_urls[0].last_visit()); 1919 EXPECT_EQ(row1.visit_count(), 1920 delegate_.modified_details()->changed_urls[0].visit_count()); 1921 EXPECT_EQ(row1.title(), 1922 delegate_.modified_details()->changed_urls[0].title()); 1923 EXPECT_FALSE(delegate_.favicon_details()); 1924 content::RunAllPendingInMessageLoop(); 1925 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 1926 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 1927 ASSERT_TRUE(child); 1928 EXPECT_EQ(row1.title(), child->GetTitle()); 1929 EXPECT_EQ(row1.url(), child->url()); 1930 1931 delegate_.ResetDetails(); 1932 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 1933 EXPECT_FALSE(delegate_.deleted_details()); 1934 ASSERT_TRUE(delegate_.modified_details()); 1935 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 1936 EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url()); 1937 EXPECT_EQ(row2.last_visit_time(), 1938 delegate_.modified_details()->changed_urls[0].last_visit()); 1939 EXPECT_EQ(row2.title(), 1940 delegate_.modified_details()->changed_urls[0].title()); 1941 // Favicon details is still false because thumbnail database wasn't 1942 // initialized, we ignore any changes of favicon. 1943 ASSERT_FALSE(delegate_.favicon_details()); 1944 } 1945 1946 TEST_F(AndroidProviderBackendTest, DeleteWithoutThumbnailDB) { 1947 HistoryAndBookmarkRow row1; 1948 row1.set_raw_url("cnn.com"); 1949 row1.set_url(GURL("http://cnn.com")); 1950 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 1951 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 1952 row1.set_visit_count(10); 1953 row1.set_is_bookmark(true); 1954 row1.set_title(UTF8ToUTF16("cnn")); 1955 1956 HistoryAndBookmarkRow row2; 1957 row2.set_raw_url("http://www.example.com"); 1958 row2.set_url(GURL("http://www.example.com")); 1959 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10)); 1960 row2.set_is_bookmark(false); 1961 row2.set_title(UTF8ToUTF16("example")); 1962 std::vector<unsigned char> data; 1963 data.push_back('1'); 1964 row2.set_favicon(base::RefCountedBytes::TakeVector(&data)); 1965 1966 { 1967 HistoryDatabase history_db; 1968 ThumbnailDatabase thumbnail_db; 1969 ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_)); 1970 ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, NULL, 1971 &history_db)); 1972 1973 scoped_ptr<AndroidProviderBackend> backend( 1974 new AndroidProviderBackend(android_cache_db_name_, &history_db, 1975 &thumbnail_db, bookmark_model_, &delegate_)); 1976 1977 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1)); 1978 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2)); 1979 // Verify the row1 has been added in bookmark model. 1980 content::RunAllPendingInMessageLoop(); 1981 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count()); 1982 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0); 1983 ASSERT_TRUE(child); 1984 EXPECT_EQ(row1.title(), child->GetTitle()); 1985 EXPECT_EQ(row1.url(), child->url()); 1986 } 1987 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 1988 scoped_ptr<AndroidProviderBackend> backend( 1989 new AndroidProviderBackend(android_cache_db_name_, &history_db_, 1990 NULL, bookmark_model_, &delegate_)); 1991 1992 // Delete all rows. 1993 std::vector<string16> args; 1994 int deleted_count = 0; 1995 delegate_.ResetDetails(); 1996 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args, 1997 &deleted_count)); 1998 // All rows were deleted. 1999 EXPECT_EQ(2, deleted_count); 2000 // Verify the rows was removed from bookmark model. 2001 content::RunAllPendingInMessageLoop(); 2002 ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count()); 2003 2004 // Verify notifications 2005 ASSERT_TRUE(delegate_.deleted_details()); 2006 EXPECT_FALSE(delegate_.modified_details()); 2007 EXPECT_EQ(2u, delegate_.deleted_details()->rows.size()); 2008 // No favicon has been deleted. 2009 EXPECT_FALSE(delegate_.favicon_details()); 2010 2011 // No row exists. 2012 std::vector<HistoryAndBookmarkRow::ColumnID> projections; 2013 projections.push_back(HistoryAndBookmarkRow::ID); 2014 projections.push_back(HistoryAndBookmarkRow::URL); 2015 projections.push_back(HistoryAndBookmarkRow::TITLE); 2016 projections.push_back(HistoryAndBookmarkRow::CREATED); 2017 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); 2018 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); 2019 projections.push_back(HistoryAndBookmarkRow::FAVICON); 2020 projections.push_back(HistoryAndBookmarkRow::BOOKMARK); 2021 2022 scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks( 2023 projections, std::string(), std::vector<string16>(), 2024 std::string("url ASC"))); 2025 ASSERT_FALSE(statement1->statement()->Step()); 2026 } 2027 2028 TEST_F(AndroidProviderBackendTest, UpdateFaviconWithoutThumbnail) { 2029 HistoryAndBookmarkRow row1; 2030 row1.set_raw_url("cnn.com"); 2031 row1.set_url(GURL("http://cnn.com")); 2032 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1)); 2033 row1.set_created(Time::Now() - TimeDelta::FromDays(20)); 2034 row1.set_visit_count(10); 2035 row1.set_is_bookmark(true); 2036 row1.set_title(UTF8ToUTF16("cnn")); 2037 2038 { 2039 HistoryDatabase history_db; 2040 ThumbnailDatabase thumbnail_db; 2041 ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_)); 2042 ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, NULL, 2043 &history_db)); 2044 scoped_ptr<AndroidProviderBackend> backend( 2045 new AndroidProviderBackend(android_cache_db_name_, &history_db, 2046 &thumbnail_db, bookmark_model_, &delegate_)); 2047 2048 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1); 2049 ASSERT_TRUE(id1); 2050 } 2051 2052 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_)); 2053 scoped_ptr<AndroidProviderBackend> backend( 2054 new AndroidProviderBackend(android_cache_db_name_, &history_db_, NULL, 2055 bookmark_model_, &delegate_)); 2056 2057 int update_count; 2058 std::vector<string16> update_args; 2059 // Update the last visit time to a value greater than current one. 2060 HistoryAndBookmarkRow update_row1; 2061 2062 // Set visit count. 2063 update_row1.set_visit_count(5); 2064 // Set favicon. 2065 std::vector<unsigned char> data; 2066 data.push_back('1'); 2067 update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data)); 2068 update_args.push_back(UTF8ToUTF16(row1.raw_url())); 2069 delegate_.ResetDetails(); 2070 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?", 2071 update_args, &update_count)); 2072 // Verify notifications. 2073 EXPECT_FALSE(delegate_.deleted_details()); 2074 ASSERT_TRUE(delegate_.modified_details()); 2075 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size()); 2076 // No favicon will be updated as thumbnail database is missing. 2077 EXPECT_FALSE(delegate_.favicon_details()); 2078 } 2079 2080 } // namespace history 2081