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.
5 #include "chrome/browser/history/android/android_provider_backend.h"
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"
35 using base::TimeDelta;
36 using base::UTF8ToUTF16;
37 using content::BrowserThread;
43 struct BookmarkCacheRow {
52 Time last_visit_time_;
54 favicon_base::FaviconID favicon_id_;
59 class AndroidProviderBackendDelegate : public HistoryBackend::Delegate {
61 AndroidProviderBackendDelegate() {}
63 virtual void NotifyProfileError(sql::InitStatus init_status) OVERRIDE {}
64 virtual void SetInMemoryBackend(
65 scoped_ptr<InMemoryHistoryBackend> backend) OVERRIDE {}
66 virtual void BroadcastNotifications(
68 scoped_ptr<HistoryDetails> details) OVERRIDE {
70 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
71 deleted_details_.reset(
72 static_cast<URLsDeletedDetails*>(details.release()));
74 case chrome::NOTIFICATION_FAVICON_CHANGED:
75 favicon_details_.reset(
76 static_cast<FaviconChangedDetails*>(details.release()));
78 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
79 modified_details_.reset(
80 static_cast<URLsModifiedDetails*>(details.release()));
84 virtual void DBLoaded() OVERRIDE {}
85 virtual void NotifyVisitDBObserversOnAddVisit(
86 const history::BriefVisitInfo& info) OVERRIDE {}
88 URLsDeletedDetails* deleted_details() const {
89 return deleted_details_.get();
92 URLsModifiedDetails* modified_details() const {
93 return modified_details_.get();
96 FaviconChangedDetails* favicon_details() const {
97 return favicon_details_.get();
100 void ResetDetails() {
101 deleted_details_.reset();
102 modified_details_.reset();
103 favicon_details_.reset();
107 scoped_ptr<URLsDeletedDetails> deleted_details_;
108 scoped_ptr<URLsModifiedDetails> modified_details_;
109 scoped_ptr<FaviconChangedDetails> favicon_details_;
111 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendDelegate);
114 class AndroidProviderBackendTest : public testing::Test {
116 AndroidProviderBackendTest()
118 TestingBrowserProcess::GetGlobal()),
119 bookmark_model_(NULL),
120 ui_thread_(BrowserThread::UI, &message_loop_),
121 file_thread_(BrowserThread::FILE, &message_loop_) {
123 virtual ~AndroidProviderBackendTest() {}
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);
137 ChromeHistoryClientFactory::GetForProfile(testing_profile);
138 test::WaitForBookmarkModelToLoad(bookmark_model_);
139 ASSERT_TRUE(bookmark_model_);
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);
146 // Setup the database directory and files.
147 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
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");
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));
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"));
167 while (statement.Step()) {
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);
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"));
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);
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_;
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_;
211 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendTest);
214 TEST_F(AndroidProviderBackendTest, UpdateTables) {
215 GURL url1("http://www.cnn.com");
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));
225 GURL url2("http://www.example.com");
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));
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,
240 // Only use the HistoryBackend to generate the test data.
241 // HistoryBackend will shutdown after that.
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);
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();
256 // Set favicon to url2.
257 std::vector<unsigned char> data;
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);
266 history_backend->SetFavicons(
267 url2, favicon_base::FAVICON, favicon_bitmap_data);
268 history_backend->Closing();
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_));
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.
280 scoped_ptr<AndroidProviderBackend> backend(
281 new AndroidProviderBackend(android_cache_db_name_,
287 ASSERT_TRUE(backend->EnsureInitializedAndUpdated());
289 // First verify that the bookmark which was not in the history has been added
290 // to history database.
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());
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);
304 EXPECT_EQ(url_id2, i->url_id);
305 EXPECT_EQ(url2.spec(), i->raw_url);
307 EXPECT_EQ(url_id3, i->url_id);
308 EXPECT_EQ(url3.spec(), i->raw_url);
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_);
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_);
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,
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);
336 backend->UpdateTables();
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);
345 EXPECT_EQ(url_id3, i->url_id);
346 EXPECT_EQ(url3.spec(), i->raw_url);
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_);
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_);
365 TEST_F(AndroidProviderBackendTest, QueryHistoryAndBookmarks) {
366 GURL url1("http://www.cnn.com");
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));
377 GURL url2("http://www.example.com");
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));
388 // Only use the HistoryBackend to generate the test data.
389 // HistoryBackend will shutdown after that.
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);
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));
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));
409 // Set favicon to url2.
410 std::vector<unsigned char> data;
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);
419 history_backend->SetFavicons(
420 url2, favicon_base::FAVICON, favicon_bitmap_data);
421 history_backend->Closing();
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_));
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.
434 scoped_ptr<AndroidProviderBackend> backend(
435 new AndroidProviderBackend(android_cache_db_name_,
441 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
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);
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());
465 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
466 EXPECT_TRUE(statement->statement()->ColumnBool(7));
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());
479 EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
480 EXPECT_FALSE(statement->statement()->ColumnBool(7));
483 EXPECT_FALSE(statement->statement()->Step());
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());
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());
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"));
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;
519 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
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_,
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);
546 EXPECT_EQ(row1.title(), child->GetTitle());
547 EXPECT_EQ(row1.url(), child->url());
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()));
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);
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());
587 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
589 // TODO: Find a way to test the bookmark was added in BookmarkModel.
590 // The bookmark was added in UI thread, there is no good way to test it.
591 EXPECT_TRUE(statement->statement()->ColumnBool(7));
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());
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));
609 EXPECT_FALSE(statement->statement()->Step());
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"));
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;
630 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
632 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
633 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
635 scoped_ptr<AndroidProviderBackend> backend(
636 new AndroidProviderBackend(android_cache_db_name_,
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);
649 EXPECT_EQ(row1.title(), child->GetTitle());
650 EXPECT_EQ(row1.url(), child->url());
653 std::vector<base::string16> args;
654 int deleted_count = 0;
655 delegate_.ResetDetails();
656 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
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());
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());
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);
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());
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());
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));
703 EXPECT_FALSE(statement->statement()->Step());
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()));
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());
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_,
741 // The created time and last visit time are too close to have required visit
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));
754 // Have different created time and last visit time, but only have 1 visit
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));
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));
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));
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));
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));
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));
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"));
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;
823 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
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_,
834 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
836 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
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);
844 EXPECT_EQ(row1.title(), child->GetTitle());
845 EXPECT_EQ(row1.url(), child->url());
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);
853 // Make sure we have the correct visit rows in visit table.
855 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
856 ASSERT_EQ(10u, visits.size());
858 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
859 ASSERT_EQ(1u, visits.size());
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"));
868 ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row1, std::string(),
869 update_args, &update_count));
871 // Only update one URL.
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()),
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());
896 EXPECT_EQ(1, update_count);
897 // We shouldn't find orignal url anymore.
898 EXPECT_FALSE(history_db_.GetRowForURL(row1.url(), NULL));
900 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
901 EXPECT_EQ(0u, visits.size());
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()));
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);
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);
921 EXPECT_EQ(row1.title(), child1->GetTitle());
922 EXPECT_EQ(update_row1.url(), child1->url());
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);
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()),
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()));
961 EXPECT_EQ(1, update_count);
962 // We shouldn't find orignal url anymore.
963 EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL));
965 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
966 EXPECT_EQ(0u, visits.size());
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());
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);
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);
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"));
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));
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_,
1016 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1018 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
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()),
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());
1043 // All visits should be removed, and 5 new visit insertted.
1045 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1));
1046 EXPECT_EQ(5, new_row1.visit_count());
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);
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.
1062 ASSERT_TRUE(history_db_.GetRowForURL(row2.url(), &new_row2));
1063 EXPECT_EQ(1, new_row2.visit_count());
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);
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"));
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));
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_,
1099 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1101 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
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()),
1121 delegate_.modified_details()->changed_urls[0].last_visit()));
1122 EXPECT_FALSE(delegate_.favicon_details());
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());
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);
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));
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"));
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_,
1163 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1167 std::vector<base::string16> update_args;
1168 // Update the last visit time to a value greater than current one.
1169 HistoryAndBookmarkRow update_row1;
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()));
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,
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());
1200 HistoryAndBookmarkRow update_row2;
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()));
1217 EXPECT_FALSE(thumbnail_db_.GetIconMappingsForPageURL(
1218 row1.url(), favicon_base::FAVICON, NULL));
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_,
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);
1245 EXPECT_EQ(term, keyword_cache.term);
1246 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1247 ToDatabaseTime(keyword_cache.last_visit_time));
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,
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);
1271 EXPECT_EQ(term2, keyword_cache.term);
1272 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
1273 ToDatabaseTime(keyword_cache.last_visit_time));
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));
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));
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_,
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));
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>(),
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());
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_,
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));
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);
1373 EXPECT_FALSE(statement->statement()->Step());
1375 // Update the search term and time.
1376 base::string16 update_term = UTF8ToUTF16("Update search term");
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,
1387 EXPECT_EQ(1, update_count);
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));
1402 // Verfiy the AndoridSearchID isn't changed.
1404 args.push_back(update_term);
1405 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
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());
1418 // Only update the search time.
1419 SearchRow update_time;
1420 update_time.set_search_time(Time::Now());
1423 std::ostringstream oss;
1425 args.push_back(UTF8ToUTF16(oss.str()));
1427 ASSERT_TRUE(backend->UpdateSearchTerms(update_time, "_id = ?", args,
1429 EXPECT_EQ(1, update_count);
1431 // Verify the update.
1432 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
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());
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_,
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));
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);
1480 EXPECT_FALSE(statement->statement()->Step());
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));
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);
1500 args.push_back(term2);
1501 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
1503 ASSERT_TRUE(statement.get());
1504 ASSERT_TRUE(statement->statement()->Step());
1505 SearchTermID id2 = statement->statement()->ColumnInt64(0);
1507 EXPECT_FALSE(statement->statement()->Step());
1509 // Delete the first one.
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.
1520 std::ostringstream oss;
1522 args.push_back(UTF8ToUTF16(oss.str()));
1523 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1525 ASSERT_TRUE(statement.get());
1526 EXPECT_FALSE(statement->statement()->Step());
1528 // The second one is still there.
1530 std::ostringstream oss1;
1532 args.push_back(UTF8ToUTF16(oss1.str()));
1533 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
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());
1540 // Remove all search terms in no condition.
1543 ASSERT_TRUE(backend->DeleteSearchTerms(std::string(), args, &deleted_count));
1544 EXPECT_EQ(1, deleted_count);
1546 // Verify the second one was removed.
1548 args.push_back(UTF8ToUTF16(oss1.str()));
1549 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1551 ASSERT_TRUE(statement.get());
1552 EXPECT_FALSE(statement->statement()->Step());
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_,
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));
1570 SearchTermID id = backend->InsertSearchTerm(search_row);
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;
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());
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"));
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));
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_,
1622 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1624 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
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);
1632 EXPECT_EQ(row1.title(), child->GetTitle());
1633 EXPECT_EQ(row1.url(), child->url());
1636 int deleted_count = 0;
1637 ASSERT_TRUE(backend->DeleteHistory(std::string(),
1638 std::vector<base::string16>(),
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.
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());
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());
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());
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_,
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();
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());
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());
1706 // Insert another row to verify we are still fine after the previous
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());
1719 TEST_F(AndroidProviderBackendTest, TestAndroidCTSComplianceForZeroVisitCount) {
1720 // This is to verify the last visit time and created time are same when visit
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_,
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);
1735 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
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);
1746 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1747 projections, std::string(), std::vector<base::string16>(),
1748 std::string("url ASC")));
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));
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
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_,
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"));
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));
1789 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1791 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1793 content::RunAllPendingInMessageLoop();
1795 // Query by folder=0, the row1 should returned.
1796 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1798 projections.push_back(HistoryAndBookmarkRow::URL);
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());
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());
1816 TEST_F(AndroidProviderBackendTest, QueryWithoutThumbnailDB) {
1817 GURL url1("http://www.cnn.com");
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));
1828 GURL url2("http://www.example.com");
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));
1839 // Only use the HistoryBackend to generate the test data.
1840 // HistoryBackend will shutdown after that.
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);
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));
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));
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);
1870 history_backend->SetFavicons(
1871 url2, favicon_base::FAVICON, favicon_bitmap_data);
1872 history_backend->Closing();
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_));
1880 // Only creates the history database
1881 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1883 // Set url1 as bookmark.
1886 scoped_ptr<AndroidProviderBackend> backend(
1887 new AndroidProviderBackend(android_cache_db_name_,
1893 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
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);
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());
1917 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
1918 EXPECT_TRUE(statement->statement()->ColumnBool(7));
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));
1935 EXPECT_FALSE(statement->statement()->Step());
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"));
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));
1958 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1959 scoped_ptr<AndroidProviderBackend> backend(
1960 new AndroidProviderBackend(android_cache_db_name_,
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);
1982 EXPECT_EQ(row1.title(), child->GetTitle());
1983 EXPECT_EQ(row1.url(), child->url());
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());
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"));
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));
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_));
2026 scoped_ptr<AndroidProviderBackend> backend(
2027 new AndroidProviderBackend(android_cache_db_name_,
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);
2040 EXPECT_EQ(row1.title(), child->GetTitle());
2041 EXPECT_EQ(row1.url(), child->url());
2043 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2044 scoped_ptr<AndroidProviderBackend> backend(
2045 new AndroidProviderBackend(android_cache_db_name_,
2052 std::vector<base::string16> args;
2053 int deleted_count = 0;
2054 delegate_.ResetDetails();
2055 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
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());
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());
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);
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());
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"));
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_,
2109 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
2113 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2114 scoped_ptr<AndroidProviderBackend> backend(
2115 new AndroidProviderBackend(android_cache_db_name_,
2122 std::vector<base::string16> update_args;
2123 // Update the last visit time to a value greater than current one.
2124 HistoryAndBookmarkRow update_row1;
2127 update_row1.set_visit_count(5);
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());
2144 } // namespace history