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