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