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/files/file_path.h"
10 #include "base/files/file_util.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/history/android/android_time.h"
18 #include "chrome/browser/history/chrome_history_client.h"
19 #include "chrome/browser/history/chrome_history_client_factory.h"
20 #include "chrome/browser/history/history_backend.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/common/chrome_constants.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "components/bookmarks/browser/bookmark_model.h"
27 #include "components/bookmarks/test/bookmark_test_helpers.h"
28 #include "components/history/core/browser/keyword_search_term.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "content/public/test/test_utils.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/skia/include/core/SkBitmap.h"
36 using base::TimeDelta;
37 using base::UTF8ToUTF16;
38 using content::BrowserThread;
44 struct BookmarkCacheRow {
53 Time last_visit_time_;
55 favicon_base::FaviconID favicon_id_;
58 // Creates a 16x16 bitmap.
59 SkBitmap CreateBitmap() {
61 bitmap.allocN32Pixels(16, 16);
62 bitmap.eraseColor(SK_ColorBLUE);
68 class AndroidProviderBackendDelegate : public HistoryBackend::Delegate {
70 AndroidProviderBackendDelegate() {}
72 virtual void NotifyProfileError(sql::InitStatus init_status) override {}
73 virtual void SetInMemoryBackend(
74 scoped_ptr<InMemoryHistoryBackend> backend) override {}
75 virtual void NotifyAddVisit(const history::BriefVisitInfo& info) override {}
76 virtual void NotifyFaviconChanged(const std::set<GURL>& url) override {
77 favicon_changed_.reset(new std::set<GURL>(url.begin(), url.end()));
79 virtual void NotifyURLVisited(ui::PageTransition,
80 const history::URLRow& row,
81 const history::RedirectList& redirects,
82 base::Time visit_time) override {}
83 virtual void BroadcastNotifications(
85 scoped_ptr<HistoryDetails> details) override {
87 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
88 deleted_details_.reset(
89 static_cast<URLsDeletedDetails*>(details.release()));
91 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
92 modified_details_.reset(
93 static_cast<URLsModifiedDetails*>(details.release()));
97 virtual void DBLoaded() override {}
99 URLsDeletedDetails* deleted_details() const {
100 return deleted_details_.get();
103 URLsModifiedDetails* modified_details() const {
104 return modified_details_.get();
107 std::set<GURL>* favicon_changed() const { return favicon_changed_.get(); }
109 void ResetDetails() {
110 deleted_details_.reset();
111 modified_details_.reset();
112 favicon_changed_.reset();
116 scoped_ptr<URLsDeletedDetails> deleted_details_;
117 scoped_ptr<URLsModifiedDetails> modified_details_;
118 scoped_ptr<std::set<GURL> > favicon_changed_;
120 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendDelegate);
123 class AndroidProviderBackendTest : public testing::Test {
125 AndroidProviderBackendTest()
126 : thumbnail_db_(NULL),
128 TestingBrowserProcess::GetGlobal()),
129 bookmark_model_(NULL),
130 ui_thread_(BrowserThread::UI, &message_loop_),
131 file_thread_(BrowserThread::FILE, &message_loop_) {
133 virtual ~AndroidProviderBackendTest() {}
136 virtual void SetUp() override {
137 // Setup the testing profile, so the bookmark_model_sql_handler could
138 // get the bookmark model from it.
139 ASSERT_TRUE(profile_manager_.SetUp());
140 // It seems that the name has to be chrome::kInitialProfile, so it
141 // could be found by ProfileManager::GetLastUsedProfile().
142 TestingProfile* testing_profile = profile_manager_.CreateTestingProfile(
143 chrome::kInitialProfile);
144 testing_profile->CreateBookmarkModel(true);
145 bookmark_model_ = BookmarkModelFactory::GetForProfile(testing_profile);
147 ChromeHistoryClientFactory::GetForProfile(testing_profile);
148 bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_);
149 ASSERT_TRUE(bookmark_model_);
151 // Get the BookmarkModel from LastUsedProfile, this is the same way that
152 // how the BookmarkModelSQLHandler gets the BookmarkModel.
153 Profile* profile = ProfileManager::GetLastUsedProfile();
154 ASSERT_TRUE(profile);
156 // Setup the database directory and files.
157 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
159 history_db_name_ = temp_dir_.path().AppendASCII(chrome::kHistoryFilename);
160 thumbnail_db_name_ = temp_dir_.path().AppendASCII(
161 chrome::kFaviconsFilename);
162 android_cache_db_name_ = temp_dir_.path().AppendASCII(
163 "TestAndroidCache.db");
166 void AddBookmark(const GURL& url) {
167 const BookmarkNode* mobile_node = bookmark_model_->mobile_node();
168 ASSERT_TRUE(mobile_node);
169 ASSERT_TRUE(bookmark_model_->AddURL(mobile_node, 0, base::string16(), url));
172 bool GetAndroidURLsRows(std::vector<AndroidURLRow>* rows,
173 AndroidProviderBackend* backend) {
174 sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE,
175 "SELECT id, raw_url, url_id FROM android_urls ORDER BY url_id ASC"));
177 while (statement.Step()) {
179 row.id = statement.ColumnInt64(0);
180 row.raw_url = statement.ColumnString(1);
181 row.url_id = statement.ColumnInt64(2);
182 rows->push_back(row);
187 bool GetBookmarkCacheRows(std::vector<BookmarkCacheRow>* rows,
188 AndroidProviderBackend* backend) {
189 sql::Statement statement(backend->db_->GetCachedStatement(SQL_FROM_HERE,
190 "SELECT created_time, last_visit_time, url_id, bookmark, favicon_id "
191 "FROM android_cache_db.bookmark_cache ORDER BY url_id ASC"));
193 while (statement.Step()) {
194 BookmarkCacheRow row;
195 row.create_time_ = FromDatabaseTime(statement.ColumnInt64(0));
196 row.last_visit_time_ = FromDatabaseTime(statement.ColumnInt64(1));
197 row.url_id_ = statement.ColumnInt64(2);
198 row.bookmark_ = statement.ColumnBool(3);
199 row.favicon_id_ = statement.ColumnInt64(4);
200 rows->push_back(row);
205 AndroidProviderBackendDelegate delegate_;
206 scoped_refptr<HistoryBackend> history_backend_;
207 HistoryDatabase history_db_;
208 ThumbnailDatabase thumbnail_db_;
209 base::ScopedTempDir temp_dir_;
210 base::FilePath android_cache_db_name_;
211 base::FilePath history_db_name_;
212 base::FilePath thumbnail_db_name_;
214 TestingProfileManager profile_manager_;
215 BookmarkModel* bookmark_model_;
216 base::MessageLoopForUI message_loop_;
217 content::TestBrowserThread ui_thread_;
218 content::TestBrowserThread file_thread_;
219 ChromeHistoryClient* history_client_;
221 DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackendTest);
224 TEST_F(AndroidProviderBackendTest, UpdateTables) {
225 GURL url1("http://www.cnn.com");
227 std::vector<VisitInfo> visits1;
228 Time last_visited1 = Time::Now() - TimeDelta::FromDays(1);
229 Time created1 = last_visited1 - TimeDelta::FromDays(20);
230 visits1.push_back(VisitInfo(created1, ui::PAGE_TRANSITION_LINK));
231 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
232 ui::PAGE_TRANSITION_LINK));
233 visits1.push_back(VisitInfo(last_visited1, ui::PAGE_TRANSITION_LINK));
235 GURL url2("http://www.example.com");
237 std::vector<VisitInfo> visits2;
238 Time last_visited2 = Time::Now();
239 Time created2 = last_visited2 - TimeDelta::FromDays(10);
240 visits2.push_back(VisitInfo(created2, ui::PAGE_TRANSITION_LINK));
241 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
242 ui::PAGE_TRANSITION_LINK));
243 visits2.push_back(VisitInfo(last_visited2, ui::PAGE_TRANSITION_LINK));
245 // Add a bookmark which is not in the history.
246 GURL url3("http://www.bookmark.com");
247 base::string16 title3(UTF8ToUTF16("bookmark"));
248 ASSERT_TRUE(bookmark_model_->AddURL(bookmark_model_->bookmark_bar_node(), 0,
250 // Only use the HistoryBackend to generate the test data.
251 // HistoryBackend will shutdown after that.
253 scoped_refptr<HistoryBackend> history_backend;
254 history_backend = new HistoryBackend(
255 temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
256 history_backend->Init(std::string(), false);
257 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
258 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
261 ASSERT_TRUE(history_backend->GetURL(url1, &url_row));
262 url_id1 = url_row.id();
263 ASSERT_TRUE(history_backend->GetURL(url2, &url_row));
264 url_id2 = url_row.id();
266 // Set favicon to url2.
267 std::vector<SkBitmap> bitmaps(1u, CreateBitmap());
268 history_backend->SetFavicons(url2, favicon_base::FAVICON, GURL(), bitmaps);
269 history_backend->Closing();
272 // The history_db_name and thumbnail_db_name files should be created by
273 // HistoryBackend. We need to open the same database files.
274 ASSERT_TRUE(base::PathExists(history_db_name_));
275 ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
277 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
278 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
279 // Set url1 as bookmark.
281 scoped_ptr<AndroidProviderBackend> backend(
282 new AndroidProviderBackend(android_cache_db_name_,
288 ASSERT_TRUE(backend->EnsureInitializedAndUpdated());
290 // First verify that the bookmark which was not in the history has been added
291 // to history database.
293 ASSERT_TRUE(history_db_.GetRowForURL(url3, &url_row));
294 URLID url_id3 = url_row.id();
295 ASSERT_EQ(url3, url_row.url());
296 ASSERT_EQ(title3, url_row.title());
298 std::vector<AndroidURLRow> android_url_rows;
299 ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get()));
300 ASSERT_EQ(3u, android_url_rows.size());
301 std::vector<AndroidURLRow>::iterator i = android_url_rows.begin();
302 EXPECT_EQ(url_id1, i->url_id);
303 EXPECT_EQ(url1.spec(), i->raw_url);
305 EXPECT_EQ(url_id2, i->url_id);
306 EXPECT_EQ(url2.spec(), i->raw_url);
308 EXPECT_EQ(url_id3, i->url_id);
309 EXPECT_EQ(url3.spec(), i->raw_url);
311 std::vector<BookmarkCacheRow> bookmark_cache_rows;
312 ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get()));
313 ASSERT_EQ(3u, bookmark_cache_rows.size());
314 std::vector<BookmarkCacheRow>::const_iterator j = bookmark_cache_rows.begin();
315 EXPECT_EQ(url_id1, j->url_id_);
316 EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_));
317 EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_));
318 EXPECT_EQ(0, j->favicon_id_);
319 EXPECT_TRUE(j->bookmark_);
321 EXPECT_EQ(url_id2, j->url_id_);
322 EXPECT_EQ(ToDatabaseTime(last_visited2), ToDatabaseTime(j->last_visit_time_));
323 EXPECT_EQ(ToDatabaseTime(created2), ToDatabaseTime(j->create_time_));
324 EXPECT_NE(0, j->favicon_id_);
325 EXPECT_FALSE(j->bookmark_);
327 // Delete url2 from database.
328 ASSERT_TRUE(history_db_.DeleteURLRow(url_id2));
329 VisitVector visit_rows;
330 ASSERT_TRUE(history_db_.GetMostRecentVisitsForURL(url_id2, 10,
332 ASSERT_EQ(3u, visit_rows.size());
333 for (VisitVector::const_iterator v = visit_rows.begin();
334 v != visit_rows.end(); v++)
335 history_db_.DeleteVisit(*v);
337 backend->UpdateTables();
339 android_url_rows.clear();
340 ASSERT_TRUE(GetAndroidURLsRows(&android_url_rows, backend.get()));
341 ASSERT_EQ(2u, android_url_rows.size());
342 i = android_url_rows.begin();
343 EXPECT_EQ(url_id1, i->url_id);
344 EXPECT_EQ(url1.spec(), i->raw_url);
346 EXPECT_EQ(url_id3, i->url_id);
347 EXPECT_EQ(url3.spec(), i->raw_url);
349 bookmark_cache_rows.clear();
350 ASSERT_TRUE(GetBookmarkCacheRows(&bookmark_cache_rows, backend.get()));
351 ASSERT_EQ(2u, bookmark_cache_rows.size());
352 j = bookmark_cache_rows.begin();
353 EXPECT_EQ(url_id1, j->url_id_);
354 EXPECT_EQ(ToDatabaseTime(last_visited1), ToDatabaseTime(j->last_visit_time_));
355 EXPECT_EQ(ToDatabaseTime(created1), ToDatabaseTime(j->create_time_));
356 EXPECT_EQ(0, j->favicon_id_);
357 EXPECT_TRUE(j->bookmark_);
359 EXPECT_EQ(url_id3, j->url_id_);
360 EXPECT_EQ(base::Time::UnixEpoch(), j->last_visit_time_);
361 EXPECT_EQ(base::Time::UnixEpoch(), j->create_time_);
362 EXPECT_EQ(0, j->favicon_id_);
363 EXPECT_TRUE(j->bookmark_);
366 TEST_F(AndroidProviderBackendTest, QueryHistoryAndBookmarks) {
367 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, ui::PAGE_TRANSITION_LINK));
373 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
374 ui::PAGE_TRANSITION_LINK));
375 visits1.push_back(VisitInfo(last_visited1, ui::PAGE_TRANSITION_LINK));
377 GURL url2("http://www.example.com");
378 std::vector<VisitInfo> visits2;
379 const base::string16 title2(UTF8ToUTF16("example"));
380 Time last_visited2 = Time::Now();
381 Time created2 = last_visited2 - TimeDelta::FromDays(10);
382 visits2.push_back(VisitInfo(created2, ui::PAGE_TRANSITION_LINK));
383 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
384 ui::PAGE_TRANSITION_LINK));
385 visits2.push_back(VisitInfo(last_visited2, ui::PAGE_TRANSITION_LINK));
387 // Only use the HistoryBackend to generate the test data.
388 // HistoryBackend will shutdown after that.
390 scoped_refptr<HistoryBackend> history_backend;
391 history_backend = new HistoryBackend(
392 temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
393 history_backend->Init(std::string(), false);
394 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
395 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
397 history::URLRows url_rows(2u);
398 ASSERT_TRUE(history_backend->GetURL(url1, &url_rows[0]));
399 ASSERT_TRUE(history_backend->GetURL(url2, &url_rows[1]));
400 url_rows[0].set_title(title1);
401 url_rows[1].set_title(title2);
402 ASSERT_EQ(2u, history_backend->UpdateURLs(url_rows));
404 // Set favicon to url2.
405 std::vector<SkBitmap> bitmaps(1u, CreateBitmap());
406 history_backend->SetFavicons(url2, favicon_base::FAVICON, GURL(), bitmaps);
407 history_backend->Closing();
410 // The history_db_name and thumbnail_db_name files should be created by
411 // HistoryBackend. We need to open the same database files.
412 ASSERT_TRUE(base::PathExists(history_db_name_));
413 ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
415 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
416 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
417 // Set url1 as bookmark.
420 scoped_ptr<AndroidProviderBackend> backend(
421 new AndroidProviderBackend(android_cache_db_name_,
427 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
429 projections.push_back(HistoryAndBookmarkRow::ID);
430 projections.push_back(HistoryAndBookmarkRow::URL);
431 projections.push_back(HistoryAndBookmarkRow::TITLE);
432 projections.push_back(HistoryAndBookmarkRow::CREATED);
433 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
434 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
435 projections.push_back(HistoryAndBookmarkRow::FAVICON);
436 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
438 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
439 projections, std::string(), std::vector<base::string16>(),
440 std::string("url ASC")));
441 ASSERT_TRUE(statement->statement()->Step());
442 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
443 EXPECT_EQ(title1, statement->statement()->ColumnString16(2));
444 EXPECT_EQ(ToDatabaseTime(created1),
445 statement->statement()->ColumnInt64(3));
446 EXPECT_EQ(ToDatabaseTime(last_visited1),
447 statement->statement()->ColumnInt64(4));
448 EXPECT_EQ(3, statement->statement()->ColumnInt(5));
449 EXPECT_EQ(6, statement->favicon_index());
451 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
452 EXPECT_TRUE(statement->statement()->ColumnBool(7));
454 ASSERT_TRUE(statement->statement()->Step());
455 EXPECT_EQ(title2, statement->statement()->ColumnString16(2));
456 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
457 EXPECT_EQ(ToDatabaseTime(created2),
458 statement->statement()->ColumnInt64(3));
459 EXPECT_EQ(ToDatabaseTime(last_visited2),
460 statement->statement()->ColumnInt64(4));
461 EXPECT_EQ(3, statement->statement()->ColumnInt(5));
462 std::vector<unsigned char> favicon2;
463 EXPECT_EQ(6, statement->favicon_index());
465 EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
466 EXPECT_FALSE(statement->statement()->ColumnBool(7));
469 EXPECT_FALSE(statement->statement()->Step());
472 statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=1",
473 std::vector<base::string16>(), std::string("url ASC")));
474 // Only URL1 is returned.
475 ASSERT_TRUE(statement->statement()->Step());
476 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
477 EXPECT_FALSE(statement->statement()->Step());
479 statement.reset(backend->QueryHistoryAndBookmarks(projections, "bookmark=0",
480 std::vector<base::string16>(), std::string("url ASC")));
481 // Only URL2 is returned.
482 ASSERT_TRUE(statement->statement()->Step());
483 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
484 EXPECT_FALSE(statement->statement()->Step());
487 TEST_F(AndroidProviderBackendTest, InsertHistoryAndBookmark) {
488 HistoryAndBookmarkRow row1;
489 row1.set_raw_url("cnn.com");
490 row1.set_url(GURL("http://cnn.com"));
491 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
492 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
493 row1.set_visit_count(10);
494 row1.set_is_bookmark(true);
495 row1.set_title(UTF8ToUTF16("cnn"));
497 HistoryAndBookmarkRow row2;
498 row2.set_raw_url("http://www.example.com");
499 row2.set_url(GURL("http://www.example.com"));
500 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
501 row2.set_is_bookmark(false);
502 row2.set_title(UTF8ToUTF16("example"));
503 std::vector<unsigned char> data;
505 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
507 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
508 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
509 scoped_ptr<AndroidProviderBackend> backend(
510 new AndroidProviderBackend(android_cache_db_name_,
516 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
517 EXPECT_FALSE(delegate_.deleted_details());
518 ASSERT_TRUE(delegate_.modified_details());
519 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
520 EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url());
521 EXPECT_EQ(row1.last_visit_time(),
522 delegate_.modified_details()->changed_urls[0].last_visit());
523 EXPECT_EQ(row1.visit_count(),
524 delegate_.modified_details()->changed_urls[0].visit_count());
525 EXPECT_EQ(row1.title(),
526 delegate_.modified_details()->changed_urls[0].title());
527 EXPECT_FALSE(delegate_.favicon_changed());
528 content::RunAllPendingInMessageLoop();
529 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
530 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
532 EXPECT_EQ(row1.title(), child->GetTitle());
533 EXPECT_EQ(row1.url(), child->url());
535 delegate_.ResetDetails();
536 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
537 EXPECT_FALSE(delegate_.deleted_details());
538 ASSERT_TRUE(delegate_.modified_details());
539 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
540 EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url());
541 EXPECT_EQ(row2.last_visit_time(),
542 delegate_.modified_details()->changed_urls[0].last_visit());
543 EXPECT_EQ(row2.title(),
544 delegate_.modified_details()->changed_urls[0].title());
545 ASSERT_TRUE(delegate_.favicon_changed());
546 ASSERT_EQ(1u, delegate_.favicon_changed()->size());
547 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
548 delegate_.favicon_changed()->find(row2.url()));
550 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
551 projections.push_back(HistoryAndBookmarkRow::ID);
552 projections.push_back(HistoryAndBookmarkRow::URL);
553 projections.push_back(HistoryAndBookmarkRow::TITLE);
554 projections.push_back(HistoryAndBookmarkRow::CREATED);
555 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
556 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
557 projections.push_back(HistoryAndBookmarkRow::FAVICON);
558 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
560 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
561 projections, std::string(), std::vector<base::string16>(),
562 std::string("url ASC")));
563 ASSERT_TRUE(statement->statement()->Step());
564 ASSERT_EQ(row1.raw_url(), statement->statement()->ColumnString(1));
565 EXPECT_EQ(row1.title(), statement->statement()->ColumnString16(2));
566 EXPECT_EQ(ToDatabaseTime(row1.created()),
567 statement->statement()->ColumnInt64(3));
568 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
569 statement->statement()->ColumnInt64(4));
570 EXPECT_EQ(row1.visit_count(), statement->statement()->ColumnInt(5));
571 EXPECT_EQ(6, statement->favicon_index());
573 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
575 // TODO: Find a way to test the bookmark was added in BookmarkModel.
576 // The bookmark was added in UI thread, there is no good way to test it.
577 EXPECT_TRUE(statement->statement()->ColumnBool(7));
579 ASSERT_TRUE(statement->statement()->Step());
580 EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2));
581 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1)));
582 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
583 statement->statement()->ColumnInt64(3));
584 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
585 statement->statement()->ColumnInt64(4));
586 EXPECT_EQ(1, statement->statement()->ColumnInt(5));
587 EXPECT_EQ(6, statement->favicon_index());
589 EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
590 // TODO: Find a way to test the bookmark was added in BookmarkModel.
591 // The bookmark was added in UI thread, there is no good way to test it.
592 EXPECT_FALSE(statement->statement()->ColumnBool(7));
595 EXPECT_FALSE(statement->statement()->Step());
598 TEST_F(AndroidProviderBackendTest, DeleteHistoryAndBookmarks) {
599 HistoryAndBookmarkRow row1;
600 row1.set_raw_url("cnn.com");
601 row1.set_url(GURL("http://cnn.com"));
602 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
603 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
604 row1.set_visit_count(10);
605 row1.set_is_bookmark(true);
606 row1.set_title(UTF8ToUTF16("cnn"));
608 HistoryAndBookmarkRow row2;
609 row2.set_raw_url("http://www.example.com");
610 row2.set_url(GURL("http://www.example.com"));
611 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
612 row2.set_is_bookmark(false);
613 row2.set_title(UTF8ToUTF16("example"));
614 std::vector<unsigned char> data;
616 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
618 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
619 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
621 scoped_ptr<AndroidProviderBackend> backend(
622 new AndroidProviderBackend(android_cache_db_name_,
628 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
629 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
630 // Verify the row1 has been added in bookmark model.
631 content::RunAllPendingInMessageLoop();
632 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
633 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
635 EXPECT_EQ(row1.title(), child->GetTitle());
636 EXPECT_EQ(row1.url(), child->url());
639 std::vector<base::string16> args;
640 int deleted_count = 0;
641 delegate_.ResetDetails();
642 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
644 EXPECT_EQ(1, deleted_count);
645 // Verify the row1 was removed from bookmark model.
646 content::RunAllPendingInMessageLoop();
647 ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count());
649 // Verify notifications
650 ASSERT_TRUE(delegate_.deleted_details());
651 EXPECT_FALSE(delegate_.modified_details());
652 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
653 EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url());
654 EXPECT_EQ(row1.last_visit_time(),
655 delegate_.deleted_details()->rows[0].last_visit());
656 EXPECT_EQ(row1.title(),
657 delegate_.deleted_details()->rows[0].title());
658 EXPECT_FALSE(delegate_.favicon_changed());
660 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
661 projections.push_back(HistoryAndBookmarkRow::ID);
662 projections.push_back(HistoryAndBookmarkRow::URL);
663 projections.push_back(HistoryAndBookmarkRow::TITLE);
664 projections.push_back(HistoryAndBookmarkRow::CREATED);
665 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
666 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
667 projections.push_back(HistoryAndBookmarkRow::FAVICON);
668 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
670 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
671 projections, std::string(), std::vector<base::string16>(),
672 std::string("url ASC")));
673 ASSERT_TRUE(statement->statement()->Step());
675 EXPECT_EQ(row2.title(), statement->statement()->ColumnString16(2));
676 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(1)));
677 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
678 statement->statement()->ColumnInt64(3));
679 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
680 statement->statement()->ColumnInt64(4));
681 EXPECT_EQ(1, statement->statement()->ColumnInt(5));
682 EXPECT_EQ(6, statement->favicon_index());
684 EXPECT_NE(0, statement->statement()->ColumnByteLength(6));
685 // TODO: Find a way to test the bookmark was added in BookmarkModel.
686 // The bookmark was added in UI thread, there is no good way to test it.
687 EXPECT_FALSE(statement->statement()->ColumnBool(7));
689 EXPECT_FALSE(statement->statement()->Step());
693 delegate_.ResetDetails();
694 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("bookmark = 0",
695 std::vector<base::string16>(), &deleted_count));
696 // Verify notifications
697 ASSERT_TRUE(delegate_.deleted_details());
698 EXPECT_FALSE(delegate_.modified_details());
699 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
700 EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url());
701 EXPECT_EQ(row2.last_visit_time(),
702 delegate_.deleted_details()->rows[0].last_visit());
703 EXPECT_EQ(row2.title(),
704 delegate_.deleted_details()->rows[0].title());
705 ASSERT_TRUE(delegate_.favicon_changed());
706 ASSERT_EQ(1u, delegate_.favicon_changed()->size());
707 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
708 delegate_.favicon_changed()->find(row2.url()));
710 ASSERT_EQ(1, deleted_count);
711 scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks(
712 projections, std::string(), std::vector<base::string16>(),
713 std::string("url ASC")));
714 ASSERT_FALSE(statement1->statement()->Step());
717 TEST_F(AndroidProviderBackendTest, IsValidHistoryAndBookmarkRow) {
718 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
719 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
720 scoped_ptr<AndroidProviderBackend> backend(
721 new AndroidProviderBackend(android_cache_db_name_,
727 // The created time and last visit time are too close to have required visit
729 HistoryAndBookmarkRow row1;
730 row1.set_raw_url("cnn.com");
731 row1.set_url(GURL("http://cnn.com"));
732 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
733 row1.set_created(Time::FromInternalValue(
734 row1.last_visit_time().ToInternalValue() - 1));
735 row1.set_visit_count(10);
736 row1.set_is_bookmark(true);
737 row1.set_title(UTF8ToUTF16("cnn"));
738 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row1));
740 // Have different created time and last visit time, but only have 1 visit
742 HistoryAndBookmarkRow row2;
743 row2.set_raw_url("http://www.example.com");
744 row2.set_url(GURL("http://www.example.com"));
745 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
746 row2.set_created(Time::Now() - TimeDelta::FromDays(11));
747 row2.set_visit_count(1);
748 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row2));
750 // Have created time in the future.
751 HistoryAndBookmarkRow row3;
752 row3.set_raw_url("http://www.example.com");
753 row3.set_url(GURL("http://www.example.com"));
754 row3.set_created(Time::Now() + TimeDelta::FromDays(11));
755 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row3));
757 // Have last vist time in the future.
758 HistoryAndBookmarkRow row4;
759 row4.set_raw_url("http://www.example.com");
760 row4.set_url(GURL("http://www.example.com"));
761 row4.set_last_visit_time(Time::Now() + TimeDelta::FromDays(11));
762 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row4));
764 // Created time is larger than last visit time.
765 HistoryAndBookmarkRow row5;
766 row5.set_raw_url("http://www.example.com");
767 row5.set_url(GURL("http://www.example.com"));
768 row5.set_last_visit_time(Time::Now());
769 row5.set_created(Time::Now() + TimeDelta::FromDays(11));
770 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row5));
772 // Visit count is zero, and last visit time is not zero.
773 HistoryAndBookmarkRow row6;
774 row6.set_raw_url("http://www.example.com");
775 row6.set_url(GURL("http://www.example.com"));
776 row6.set_visit_count(0);
777 row6.set_last_visit_time(Time::Now());
778 row6.set_created(Time::Now() - TimeDelta::FromDays(1));
779 EXPECT_FALSE(backend->InsertHistoryAndBookmark(row6));
781 // Visit count is zero, and create time is not zero.
782 HistoryAndBookmarkRow row7;
783 row7.set_raw_url("http://www.example.com");
784 row7.set_url(GURL("http://www.example.com"));
785 row7.set_visit_count(0);
786 row7.set_last_visit_time(Time::Now());
787 row7.set_created(Time::UnixEpoch());
788 EXPECT_TRUE(backend->InsertHistoryAndBookmark(row7));
791 TEST_F(AndroidProviderBackendTest, UpdateURL) {
792 HistoryAndBookmarkRow row1;
793 row1.set_raw_url("cnn.com");
794 row1.set_url(GURL("http://cnn.com"));
795 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
796 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
797 row1.set_visit_count(10);
798 row1.set_is_bookmark(true);
799 row1.set_title(UTF8ToUTF16("cnn"));
801 HistoryAndBookmarkRow row2;
802 row2.set_raw_url("http://www.example.com");
803 row2.set_url(GURL("http://www.example.com"));
804 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
805 row2.set_is_bookmark(false);
806 row2.set_title(UTF8ToUTF16("example"));
807 std::vector<unsigned char> data;
809 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
811 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
812 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
813 scoped_ptr<AndroidProviderBackend> backend(
814 new AndroidProviderBackend(android_cache_db_name_,
820 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
822 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
825 // Verify the row1 has been added in bookmark model.
826 content::RunAllPendingInMessageLoop();
827 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
828 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
830 EXPECT_EQ(row1.title(), child->GetTitle());
831 EXPECT_EQ(row1.url(), child->url());
833 // Make sure the url has correctly insertted.
834 URLID url_id1 = history_db_.GetRowForURL(row1.url(), NULL);
835 ASSERT_TRUE(url_id1);
836 URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL);
837 ASSERT_TRUE(url_id2);
839 // Make sure we have the correct visit rows in visit table.
841 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
842 ASSERT_EQ(10u, visits.size());
844 ASSERT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
845 ASSERT_EQ(1u, visits.size());
848 std::vector<base::string16> update_args;
849 // Try to update the mutiple rows with the same URL, this should failed.
850 HistoryAndBookmarkRow update_row1;
851 update_row1.set_raw_url("newwebiste.com");
852 update_row1.set_url(GURL("http://newwebsite.com"));
854 ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row1, std::string(),
855 update_args, &update_count));
857 // Only update one URL.
859 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
860 delegate_.ResetDetails();
861 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
862 update_args, &update_count));
863 // Verify notifications, Update involves insert and delete URLS.
864 ASSERT_TRUE(delegate_.deleted_details());
865 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
866 EXPECT_EQ(row1.url(), delegate_.deleted_details()->rows[0].url());
867 EXPECT_EQ(row1.last_visit_time(),
868 delegate_.deleted_details()->rows[0].last_visit());
869 EXPECT_EQ(row1.title(),
870 delegate_.deleted_details()->rows[0].title());
871 ASSERT_TRUE(delegate_.modified_details());
872 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
873 EXPECT_EQ(update_row1.url(),
874 delegate_.modified_details()->changed_urls[0].url());
875 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
877 delegate_.modified_details()->changed_urls[0].last_visit()));
878 EXPECT_EQ(row1.title(),
879 delegate_.modified_details()->changed_urls[0].title());
880 EXPECT_FALSE(delegate_.favicon_changed());
882 EXPECT_EQ(1, update_count);
883 // We shouldn't find orignal url anymore.
884 EXPECT_FALSE(history_db_.GetRowForURL(row1.url(), NULL));
886 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id1, &visits));
887 EXPECT_EQ(0u, visits.size());
890 EXPECT_TRUE(history_db_.GetRowForURL(update_row1.url(), &new_row));
891 EXPECT_EQ(10, new_row.visit_count());
892 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
893 ToDatabaseTime(new_row.last_visit()));
895 EXPECT_TRUE(history_db_.GetVisitsForURL(new_row.id(), &visits));
896 EXPECT_EQ(10u, visits.size());
897 AndroidURLRow android_url_row1;
898 ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row.id(), &android_url_row1));
899 // Android URL ID shouldn't change.
900 EXPECT_EQ(id1, android_url_row1.id);
902 // Verify the bookmark model was updated.
903 content::RunAllPendingInMessageLoop();
904 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
905 const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0);
907 EXPECT_EQ(row1.title(), child1->GetTitle());
908 EXPECT_EQ(update_row1.url(), child1->url());
910 // Update the URL with visit count, created time, and last visit time.
911 HistoryAndBookmarkRow update_row2;
912 update_row2.set_raw_url("somethingelse.com");
913 update_row2.set_url(GURL("http://somethingelse.com"));
914 update_row2.set_last_visit_time(Time::Now());
915 update_row2.set_created(Time::Now() - TimeDelta::FromDays(20));
916 update_row2.set_visit_count(10);
919 update_args.push_back(UTF8ToUTF16(row2.raw_url()));
920 delegate_.ResetDetails();
921 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
922 update_args, &update_count));
923 // Verify notifications, Update involves insert and delete URLS.
924 ASSERT_TRUE(delegate_.deleted_details());
925 EXPECT_EQ(1u, delegate_.deleted_details()->rows.size());
926 EXPECT_EQ(row2.url(), delegate_.deleted_details()->rows[0].url());
927 EXPECT_EQ(row2.last_visit_time(),
928 delegate_.deleted_details()->rows[0].last_visit());
929 EXPECT_EQ(row2.title(),
930 delegate_.deleted_details()->rows[0].title());
931 ASSERT_TRUE(delegate_.modified_details());
932 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
933 EXPECT_EQ(update_row2.url(),
934 delegate_.modified_details()->changed_urls[0].url());
935 EXPECT_EQ(ToDatabaseTime(update_row2.last_visit_time()),
937 delegate_.modified_details()->changed_urls[0].last_visit()));
938 EXPECT_EQ(update_row2.visit_count(),
939 delegate_.modified_details()->changed_urls[0].visit_count());
940 ASSERT_TRUE(delegate_.favicon_changed());
941 ASSERT_EQ(2u, delegate_.favicon_changed()->size());
942 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
943 delegate_.favicon_changed()->find(row2.url()));
944 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
945 delegate_.favicon_changed()->find(update_row2.url()));
947 EXPECT_EQ(1, update_count);
948 // We shouldn't find orignal url anymore.
949 EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL));
951 EXPECT_TRUE(history_db_.GetVisitsForURL(url_id2, &visits));
952 EXPECT_EQ(0u, visits.size());
956 ASSERT_TRUE(history_db_.GetRowForURL(update_row2.url(), &new_row2));
957 EXPECT_EQ(10, new_row2.visit_count());
958 EXPECT_EQ(update_row2.last_visit_time(), new_row2.last_visit());
960 EXPECT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
961 EXPECT_EQ(10u, visits.size());
962 AndroidURLRow android_url_row2;
963 ASSERT_TRUE(history_db_.GetAndroidURLRow(new_row2.id(), &android_url_row2));
964 // Android URL ID shouldn't change.
965 EXPECT_EQ(id2, android_url_row2.id);
967 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
968 ASSERT_EQ(10u, visits.size());
969 EXPECT_EQ(update_row2.created(), visits[0].visit_time);
970 EXPECT_EQ(update_row2.last_visit_time(), visits[9].visit_time);
973 TEST_F(AndroidProviderBackendTest, UpdateVisitCount) {
974 HistoryAndBookmarkRow row1;
975 row1.set_raw_url("cnn.com");
976 row1.set_url(GURL("http://cnn.com"));
977 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
978 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
979 row1.set_visit_count(10);
980 row1.set_is_bookmark(true);
981 row1.set_title(UTF8ToUTF16("cnn"));
983 HistoryAndBookmarkRow row2;
984 row2.set_raw_url("http://www.example.com");
985 row2.set_url(GURL("http://www.example.com"));
986 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
987 row2.set_is_bookmark(false);
988 row2.set_title(UTF8ToUTF16("example"));
989 std::vector<unsigned char> data;
991 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
993 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
994 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
995 scoped_ptr<AndroidProviderBackend> backend(
996 new AndroidProviderBackend(android_cache_db_name_,
1002 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1004 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1008 std::vector<base::string16> update_args;
1009 // Update the visit_count to a value less than current one.
1010 HistoryAndBookmarkRow update_row1;
1011 update_row1.set_visit_count(5);
1012 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1013 delegate_.ResetDetails();
1014 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1015 update_args, &update_count));
1016 // Verify notifications, Update involves modified URL.
1017 EXPECT_FALSE(delegate_.deleted_details());
1018 ASSERT_TRUE(delegate_.modified_details());
1019 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1020 EXPECT_EQ(row1.url(),
1021 delegate_.modified_details()->changed_urls[0].url());
1022 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1024 delegate_.modified_details()->changed_urls[0].last_visit()));
1025 EXPECT_EQ(update_row1.visit_count(),
1026 delegate_.modified_details()->changed_urls[0].visit_count());
1027 EXPECT_FALSE(delegate_.favicon_changed());
1029 // All visits should be removed, and 5 new visit insertted.
1031 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1));
1032 EXPECT_EQ(5, new_row1.visit_count());
1034 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits));
1035 ASSERT_EQ(5u, visits.size());
1036 EXPECT_EQ(row1.last_visit_time(), visits[4].visit_time);
1037 EXPECT_GT(row1.last_visit_time(), visits[0].visit_time);
1039 // Update the visit_count to a value equal to current one.
1040 HistoryAndBookmarkRow update_row2;
1041 update_row2.set_visit_count(1);
1042 update_args.clear();
1043 update_args.push_back(UTF8ToUTF16(row2.raw_url()));
1044 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
1045 update_args, &update_count));
1046 // All shouldn't have any change.
1048 ASSERT_TRUE(history_db_.GetRowForURL(row2.url(), &new_row2));
1049 EXPECT_EQ(1, new_row2.visit_count());
1051 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row2.id(), &visits));
1052 ASSERT_EQ(1u, visits.size());
1053 EXPECT_EQ(row2.last_visit_time(), visits[0].visit_time);
1056 TEST_F(AndroidProviderBackendTest, UpdateLastVisitTime) {
1057 HistoryAndBookmarkRow row1;
1058 row1.set_raw_url("cnn.com");
1059 row1.set_url(GURL("http://cnn.com"));
1060 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1061 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1062 row1.set_visit_count(10);
1063 row1.set_is_bookmark(true);
1064 row1.set_title(UTF8ToUTF16("cnn"));
1066 HistoryAndBookmarkRow row2;
1067 row2.set_raw_url("http://www.example.com");
1068 row2.set_url(GURL("http://www.example.com"));
1069 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1070 row2.set_is_bookmark(false);
1071 row2.set_title(UTF8ToUTF16("example"));
1072 std::vector<unsigned char> data;
1073 data.push_back('1');
1074 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1076 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1077 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1078 scoped_ptr<AndroidProviderBackend> backend(
1079 new AndroidProviderBackend(android_cache_db_name_,
1085 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1087 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1091 std::vector<base::string16> update_args;
1092 // Update the last visit time to a value greater than current one.
1093 HistoryAndBookmarkRow update_row1;
1094 update_row1.set_last_visit_time(Time::Now());
1095 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1096 delegate_.ResetDetails();
1097 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1098 update_args, &update_count));
1099 // Verify notifications, Update involves modified URL.
1100 EXPECT_FALSE(delegate_.deleted_details());
1101 ASSERT_TRUE(delegate_.modified_details());
1102 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1103 EXPECT_EQ(row1.url(),
1104 delegate_.modified_details()->changed_urls[0].url());
1105 EXPECT_EQ(ToDatabaseTime(update_row1.last_visit_time()),
1107 delegate_.modified_details()->changed_urls[0].last_visit()));
1108 EXPECT_FALSE(delegate_.favicon_changed());
1111 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &new_row1));
1112 EXPECT_EQ(11, new_row1.visit_count());
1113 EXPECT_EQ(update_row1.last_visit_time(), new_row1.last_visit());
1115 ASSERT_TRUE(history_db_.GetVisitsForURL(new_row1.id(), &visits));
1116 // 1 new visit insertted.
1117 ASSERT_EQ(11u, visits.size());
1118 EXPECT_EQ(update_row1.last_visit_time(), visits[10].visit_time);
1119 EXPECT_EQ(row1.last_visit_time(), visits[9].visit_time);
1121 // Update the visit_tim to a value less than to current one.
1122 HistoryAndBookmarkRow update_row2;
1123 update_row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1124 update_args.clear();
1125 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1126 ASSERT_FALSE(backend->UpdateHistoryAndBookmarks(update_row2, "url = ?",
1127 update_args, &update_count));
1130 TEST_F(AndroidProviderBackendTest, UpdateFavicon) {
1131 HistoryAndBookmarkRow row1;
1132 row1.set_raw_url("cnn.com");
1133 row1.set_url(GURL("http://cnn.com"));
1134 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1135 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1136 row1.set_visit_count(10);
1137 row1.set_is_bookmark(true);
1138 row1.set_title(UTF8ToUTF16("cnn"));
1140 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1141 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1142 scoped_ptr<AndroidProviderBackend> backend(
1143 new AndroidProviderBackend(android_cache_db_name_,
1149 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1153 std::vector<base::string16> update_args;
1154 // Update the last visit time to a value greater than current one.
1155 HistoryAndBookmarkRow update_row1;
1158 std::vector<unsigned char> data;
1159 data.push_back('1');
1160 update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data));
1161 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1162 delegate_.ResetDetails();
1163 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1164 update_args, &update_count));
1165 // Verify notifications.
1166 EXPECT_FALSE(delegate_.deleted_details());
1167 EXPECT_FALSE(delegate_.modified_details());
1168 ASSERT_TRUE(delegate_.favicon_changed());
1169 ASSERT_EQ(1u, delegate_.favicon_changed()->size());
1170 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
1171 delegate_.favicon_changed()->find(row1.url()));
1173 std::vector<IconMapping> icon_mappings;
1174 EXPECT_TRUE(thumbnail_db_.GetIconMappingsForPageURL(
1175 row1.url(), favicon_base::FAVICON, &icon_mappings));
1176 EXPECT_EQ(1u, icon_mappings.size());
1177 std::vector<FaviconBitmap> favicon_bitmaps;
1178 EXPECT_TRUE(thumbnail_db_.GetFaviconBitmaps(icon_mappings[0].icon_id,
1180 EXPECT_EQ(1u, favicon_bitmaps.size());
1181 EXPECT_TRUE(favicon_bitmaps[0].bitmap_data.get());
1182 EXPECT_EQ(1u, favicon_bitmaps[0].bitmap_data->size());
1183 EXPECT_EQ('1', *favicon_bitmaps[0].bitmap_data->front());
1186 HistoryAndBookmarkRow update_row2;
1189 update_row1.set_favicon(new base::RefCountedBytes());
1190 update_args.clear();
1191 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
1192 delegate_.ResetDetails();
1193 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
1194 update_args, &update_count));
1195 // Verify notifications.
1196 EXPECT_FALSE(delegate_.deleted_details());
1197 EXPECT_FALSE(delegate_.modified_details());
1198 ASSERT_TRUE(delegate_.favicon_changed());
1199 ASSERT_EQ(1u, delegate_.favicon_changed()->size());
1200 ASSERT_TRUE(delegate_.favicon_changed()->end() !=
1201 delegate_.favicon_changed()->find(row1.url()));
1203 EXPECT_FALSE(thumbnail_db_.GetIconMappingsForPageURL(
1204 row1.url(), favicon_base::FAVICON, NULL));
1207 TEST_F(AndroidProviderBackendTest, UpdateSearchTermTable) {
1208 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1209 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1210 scoped_ptr<AndroidProviderBackend> backend(
1211 new AndroidProviderBackend(android_cache_db_name_,
1216 // Insert a keyword search item to verify if the update succeeds.
1217 HistoryAndBookmarkRow row1;
1218 row1.set_raw_url("cnn.com");
1219 row1.set_url(GURL("http://cnn.com"));
1220 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1221 row1.set_title(UTF8ToUTF16("cnn"));
1222 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1223 base::string16 term = UTF8ToUTF16("Search term 1");
1224 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1225 ASSERT_TRUE(url_id);
1226 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1227 ASSERT_TRUE(backend->UpdateSearchTermTable());
1228 SearchTermRow keyword_cache;
1229 SearchTermID id = history_db_.GetSearchTerm(term, &keyword_cache);
1231 EXPECT_EQ(term, keyword_cache.term);
1232 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1233 ToDatabaseTime(keyword_cache.last_visit_time));
1236 HistoryAndBookmarkRow row2;
1237 row2.set_raw_url("google.com");
1238 row2.set_url(GURL("http://google.com"));
1239 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(2));
1240 row2.set_title(UTF8ToUTF16("cnn"));
1241 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1242 url_id = history_db_.GetRowForURL(row2.url(), NULL);
1243 ASSERT_TRUE(url_id);
1244 base::string16 term2 = UTF8ToUTF16("Search term 2");
1245 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term2));
1246 ASSERT_TRUE(backend->UpdateSearchTermTable());
1247 SearchTermID search_id1 = history_db_.GetSearchTerm(term,
1249 // The id shouldn't changed.
1250 ASSERT_EQ(id, search_id1);
1251 EXPECT_EQ(term, keyword_cache.term);
1252 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1253 ToDatabaseTime(keyword_cache.last_visit_time));
1254 // Verify the row just inserted.
1255 SearchTermID id2 = history_db_.GetSearchTerm(term2, &keyword_cache);
1257 EXPECT_EQ(term2, keyword_cache.term);
1258 EXPECT_EQ(ToDatabaseTime(row2.last_visit_time()),
1259 ToDatabaseTime(keyword_cache.last_visit_time));
1261 // Add 3rd row and associate it with term.
1262 HistoryAndBookmarkRow row3;
1263 row3.set_raw_url("search.com");
1264 row3.set_url(GURL("http://search.com"));
1265 row3.set_last_visit_time(Time::Now());
1266 row3.set_title(UTF8ToUTF16("search"));
1267 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row3));
1268 url_id = history_db_.GetRowForURL(row3.url(), NULL);
1269 ASSERT_TRUE(url_id);
1270 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1271 ASSERT_TRUE(backend->UpdateSearchTermTable());
1272 // Verify id not changed and last_visit_time updated.
1273 ASSERT_EQ(search_id1, history_db_.GetSearchTerm(term, &keyword_cache));
1274 EXPECT_EQ(ToDatabaseTime(row3.last_visit_time()),
1275 ToDatabaseTime(keyword_cache.last_visit_time));
1276 // The id of term2 wasn't changed.
1277 EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL));
1280 ASSERT_TRUE(history_db_.DeleteKeywordSearchTerm(term));
1281 ASSERT_TRUE(backend->UpdateSearchTermTable());
1282 // The cache of term should removed.
1283 ASSERT_FALSE(history_db_.GetSearchTerm(term, NULL));
1284 // The id of term2 wasn't changed.
1285 EXPECT_EQ(id2, history_db_.GetSearchTerm(term2, NULL));
1288 TEST_F(AndroidProviderBackendTest, QuerySearchTerms) {
1289 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1290 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1291 scoped_ptr<AndroidProviderBackend> backend(
1292 new AndroidProviderBackend(android_cache_db_name_,
1297 // Insert a keyword search item to verify if we can find it.
1298 HistoryAndBookmarkRow row1;
1299 row1.set_raw_url("cnn.com");
1300 row1.set_url(GURL("http://cnn.com"));
1301 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1302 row1.set_title(UTF8ToUTF16("cnn"));
1303 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1304 base::string16 term = UTF8ToUTF16("Search term 1");
1305 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1306 ASSERT_TRUE(url_id);
1307 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1309 std::vector<SearchRow::ColumnID> projections;
1310 projections.push_back(SearchRow::ID);
1311 projections.push_back(SearchRow::SEARCH_TERM);
1312 projections.push_back(SearchRow::SEARCH_TIME);
1313 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1314 projections, std::string(), std::vector<base::string16>(),
1316 ASSERT_TRUE(statement.get());
1317 ASSERT_TRUE(statement->statement()->Step());
1318 EXPECT_TRUE(statement->statement()->ColumnInt64(0));
1319 EXPECT_EQ(term, statement->statement()->ColumnString16(1));
1320 EXPECT_EQ(ToDatabaseTime(row1.last_visit_time()),
1321 statement->statement()->ColumnInt64(2));
1322 EXPECT_FALSE(statement->statement()->Step());
1325 TEST_F(AndroidProviderBackendTest, UpdateSearchTerms) {
1326 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1327 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1328 scoped_ptr<AndroidProviderBackend> backend(
1329 new AndroidProviderBackend(android_cache_db_name_,
1334 // Insert a keyword.
1335 HistoryAndBookmarkRow row1;
1336 row1.set_raw_url("cnn.com");
1337 row1.set_url(GURL("http://cnn.com"));
1338 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1339 row1.set_title(UTF8ToUTF16("cnn"));
1340 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1341 base::string16 term = UTF8ToUTF16("Search term 1");
1342 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1343 ASSERT_TRUE(url_id);
1344 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1346 // Get the SearchTermID of the row we just inserted.
1347 std::vector<SearchRow::ColumnID> projections;
1348 projections.push_back(SearchRow::ID);
1349 projections.push_back(SearchRow::SEARCH_TIME);
1350 projections.push_back(SearchRow::SEARCH_TERM);
1351 std::vector<base::string16> args;
1352 args.push_back(term);
1353 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1354 projections, "search = ?", args, std::string()));
1355 ASSERT_TRUE(statement.get());
1356 ASSERT_TRUE(statement->statement()->Step());
1357 SearchTermID id = statement->statement()->ColumnInt64(0);
1359 EXPECT_FALSE(statement->statement()->Step());
1361 // Update the search term and time.
1362 base::string16 update_term = UTF8ToUTF16("Update search term");
1364 args.push_back(term);
1365 SearchRow search_row;
1366 search_row.set_search_term(update_term);
1367 search_row.set_url(GURL("http://google.com"));
1368 search_row.set_keyword_id(1);
1369 search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1));
1370 int update_count = 0;
1371 ASSERT_TRUE(backend->UpdateSearchTerms(search_row, "search = ?", args,
1373 EXPECT_EQ(1, update_count);
1375 // Verify if the search term updated.
1376 // The origin term should be removed.
1377 std::vector<KeywordSearchTermRow> rows;
1378 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows));
1379 EXPECT_TRUE(rows.empty());
1380 // The new term should be inserted.
1381 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(update_term, &rows));
1382 ASSERT_EQ(1u, rows.size());
1383 // The history of urls shouldn't be removed.
1384 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), NULL));
1385 // The new URL is inserted.
1386 ASSERT_TRUE(history_db_.GetRowForURL(search_row.url(), NULL));
1388 // Verfiy the AndoridSearchID isn't changed.
1390 args.push_back(update_term);
1391 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
1393 ASSERT_TRUE(statement.get());
1394 ASSERT_TRUE(statement->statement()->Step());
1395 // The id didn't change.
1396 EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1397 // The search time was updated.
1398 EXPECT_EQ(ToDatabaseTime(search_row.search_time()),
1399 statement->statement()->ColumnInt64(1));
1400 // The search term was updated.
1401 EXPECT_EQ(update_term, statement->statement()->ColumnString16(2));
1402 EXPECT_FALSE(statement->statement()->Step());
1404 // Only update the search time.
1405 SearchRow update_time;
1406 update_time.set_search_time(Time::Now());
1409 std::ostringstream oss;
1411 args.push_back(UTF8ToUTF16(oss.str()));
1413 ASSERT_TRUE(backend->UpdateSearchTerms(update_time, "_id = ?", args,
1415 EXPECT_EQ(1, update_count);
1417 // Verify the update.
1418 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1420 ASSERT_TRUE(statement.get());
1421 ASSERT_TRUE(statement->statement()->Step());
1422 // The id didn't change.
1423 EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1424 // The search time was updated.
1425 EXPECT_EQ(ToDatabaseTime(update_time.search_time()),
1426 statement->statement()->ColumnInt64(1));
1427 // The search term didn't change.
1428 EXPECT_EQ(update_term, statement->statement()->ColumnString16(2));
1429 EXPECT_FALSE(statement->statement()->Step());
1432 TEST_F(AndroidProviderBackendTest, DeleteSearchTerms) {
1433 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1434 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1435 scoped_ptr<AndroidProviderBackend> backend(
1436 new AndroidProviderBackend(android_cache_db_name_,
1441 // Insert a keyword.
1442 HistoryAndBookmarkRow row1;
1443 row1.set_raw_url("cnn.com");
1444 row1.set_url(GURL("http://cnn.com"));
1445 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1446 row1.set_title(UTF8ToUTF16("cnn"));
1447 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1448 base::string16 term = UTF8ToUTF16("Search term 1");
1449 URLID url_id = history_db_.GetRowForURL(row1.url(), NULL);
1450 ASSERT_TRUE(url_id);
1451 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id, 1, term));
1453 // Get the SearchTermID of the row we just inserted.
1454 std::vector<SearchRow::ColumnID> projections;
1455 projections.push_back(SearchRow::ID);
1456 projections.push_back(SearchRow::SEARCH_TIME);
1457 projections.push_back(SearchRow::SEARCH_TERM);
1458 std::vector<base::string16> args;
1459 args.push_back(term);
1460 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1461 projections, "search = ?", args, std::string()));
1462 ASSERT_TRUE(statement.get());
1463 ASSERT_TRUE(statement->statement()->Step());
1464 SearchTermID id1 = statement->statement()->ColumnInt64(0);
1466 EXPECT_FALSE(statement->statement()->Step());
1468 // Insert a keyword.
1469 HistoryAndBookmarkRow row2;
1470 row2.set_raw_url("google.com");
1471 row2.set_url(GURL("http://google.com"));
1472 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1473 row2.set_title(UTF8ToUTF16("google"));
1474 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1475 base::string16 term2 = UTF8ToUTF16("Search term 2");
1476 URLID url_id2 = history_db_.GetRowForURL(row2.url(), NULL);
1477 ASSERT_TRUE(url_id2);
1478 ASSERT_TRUE(history_db_.SetKeywordSearchTermsForURL(url_id2, 1, term2));
1480 // Get the SearchTermID of the row we just inserted.
1481 projections.clear();
1482 projections.push_back(SearchRow::ID);
1483 projections.push_back(SearchRow::SEARCH_TIME);
1484 projections.push_back(SearchRow::SEARCH_TERM);
1486 args.push_back(term2);
1487 statement.reset(backend->QuerySearchTerms(projections, "search = ?", args,
1489 ASSERT_TRUE(statement.get());
1490 ASSERT_TRUE(statement->statement()->Step());
1491 SearchTermID id2 = statement->statement()->ColumnInt64(0);
1493 EXPECT_FALSE(statement->statement()->Step());
1495 // Delete the first one.
1497 args.push_back(term);
1498 int deleted_count = 0;
1499 ASSERT_TRUE(backend->DeleteSearchTerms("search = ?", args, &deleted_count));
1500 EXPECT_EQ(1, deleted_count);
1501 std::vector<KeywordSearchTermRow> rows;
1502 ASSERT_TRUE(history_db_.GetKeywordSearchTermRows(term, &rows));
1503 EXPECT_TRUE(rows.empty());
1504 // Verify we can't get the first term.
1506 std::ostringstream oss;
1508 args.push_back(UTF8ToUTF16(oss.str()));
1509 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1511 ASSERT_TRUE(statement.get());
1512 EXPECT_FALSE(statement->statement()->Step());
1514 // The second one is still there.
1516 std::ostringstream oss1;
1518 args.push_back(UTF8ToUTF16(oss1.str()));
1519 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1521 ASSERT_TRUE(statement.get());
1522 EXPECT_TRUE(statement->statement()->Step());
1523 EXPECT_EQ(id2, statement->statement()->ColumnInt64(0));
1524 EXPECT_FALSE(statement->statement()->Step());
1526 // Remove all search terms in no condition.
1529 ASSERT_TRUE(backend->DeleteSearchTerms(std::string(), args, &deleted_count));
1530 EXPECT_EQ(1, deleted_count);
1532 // Verify the second one was removed.
1534 args.push_back(UTF8ToUTF16(oss1.str()));
1535 statement.reset(backend->QuerySearchTerms(projections, "_id = ?", args,
1537 ASSERT_TRUE(statement.get());
1538 EXPECT_FALSE(statement->statement()->Step());
1541 TEST_F(AndroidProviderBackendTest, InsertSearchTerm) {
1542 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1543 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1544 scoped_ptr<AndroidProviderBackend> backend(
1545 new AndroidProviderBackend(android_cache_db_name_,
1550 SearchRow search_row;
1551 search_row.set_search_term(UTF8ToUTF16("google"));
1552 search_row.set_url(GURL("http://google.com"));
1553 search_row.set_keyword_id(1);
1554 search_row.set_search_time(Time::Now() - TimeDelta::FromHours(1));
1556 SearchTermID id = backend->InsertSearchTerm(search_row);
1559 std::vector<SearchRow::ColumnID> projections;
1560 projections.push_back(SearchRow::ID);
1561 projections.push_back(SearchRow::SEARCH_TIME);
1562 projections.push_back(SearchRow::SEARCH_TERM);
1563 std::vector<base::string16> args;
1564 std::ostringstream oss;
1566 args.push_back(UTF8ToUTF16(oss.str()));
1567 scoped_ptr<AndroidStatement> statement(backend->QuerySearchTerms(
1568 projections, "_id = ?", args, std::string()));
1569 ASSERT_TRUE(statement.get());
1570 ASSERT_TRUE(statement->statement()->Step());
1571 EXPECT_EQ(id, statement->statement()->ColumnInt64(0));
1572 EXPECT_EQ(ToDatabaseTime(search_row.search_time()),
1573 statement->statement()->ColumnInt64(1));
1574 EXPECT_EQ(search_row.search_term(),
1575 statement->statement()->ColumnString16(2));
1576 EXPECT_FALSE(statement->statement()->Step());
1579 TEST_F(AndroidProviderBackendTest, DeleteHistory) {
1580 HistoryAndBookmarkRow row1;
1581 row1.set_raw_url("cnn.com");
1582 row1.set_url(GURL("http://cnn.com"));
1583 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1584 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1585 row1.set_visit_count(10);
1586 row1.set_is_bookmark(true);
1587 row1.set_title(UTF8ToUTF16("cnn"));
1589 HistoryAndBookmarkRow row2;
1590 row2.set_raw_url("http://www.example.com");
1591 row2.set_url(GURL("http://www.example.com"));
1592 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1593 row2.set_is_bookmark(false);
1594 row2.set_title(UTF8ToUTF16("example"));
1595 std::vector<unsigned char> data;
1596 data.push_back('1');
1597 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1599 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1600 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1601 scoped_ptr<AndroidProviderBackend> backend(
1602 new AndroidProviderBackend(android_cache_db_name_,
1608 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1610 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1613 // Verify the row1 has been added in bookmark model.
1614 content::RunAllPendingInMessageLoop();
1615 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1616 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
1618 EXPECT_EQ(row1.title(), child->GetTitle());
1619 EXPECT_EQ(row1.url(), child->url());
1622 int deleted_count = 0;
1623 ASSERT_TRUE(backend->DeleteHistory(std::string(),
1624 std::vector<base::string16>(),
1626 EXPECT_EQ(2, deleted_count);
1627 // The row2 was deleted.
1628 EXPECT_FALSE(history_db_.GetRowForURL(row2.url(), NULL));
1629 // Still find the row1.
1631 ASSERT_TRUE(history_db_.GetRowForURL(row1.url(), &url_row));
1632 // The visit_count was reset.
1633 EXPECT_EQ(0, url_row.visit_count());
1634 EXPECT_EQ(Time::UnixEpoch(), url_row.last_visit());
1636 // Verify the row1 is still in bookmark model.
1637 content::RunAllPendingInMessageLoop();
1638 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1639 const BookmarkNode* child1 = bookmark_model_->mobile_node()->GetChild(0);
1640 ASSERT_TRUE(child1);
1641 EXPECT_EQ(row1.title(), child1->GetTitle());
1642 EXPECT_EQ(row1.url(), child1->url());
1644 // Verify notification
1645 ASSERT_TRUE(delegate_.deleted_details());
1646 ASSERT_EQ(2u, delegate_.deleted_details()->rows.size());
1647 EXPECT_EQ(row1.url(),
1648 delegate_.modified_details()->changed_urls[0].url());
1649 EXPECT_EQ(Time::UnixEpoch(),
1650 delegate_.modified_details()->changed_urls[0].last_visit());
1651 EXPECT_EQ(1u, delegate_.favicon_changed()->size());
1654 TEST_F(AndroidProviderBackendTest, TestMultipleNestingTransaction) {
1655 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1656 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1657 scoped_ptr<AndroidProviderBackend> backend(
1658 new AndroidProviderBackend(android_cache_db_name_,
1664 // Create the nested transactions.
1665 history_db_.BeginTransaction();
1666 history_db_.BeginTransaction();
1667 history_db_.BeginTransaction();
1668 thumbnail_db_.BeginTransaction();
1669 thumbnail_db_.BeginTransaction();
1670 int history_transaction = history_db_.transaction_nesting();
1671 int thumbnail_transaction = thumbnail_db_.transaction_nesting();
1673 // Insert a row to verify the transaction number are not changed
1674 // after a transaction commit.
1675 HistoryAndBookmarkRow row1;
1676 row1.set_raw_url("cnn.com");
1677 row1.set_url(GURL("http://cnn.com"));
1678 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1679 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1680 row1.set_visit_count(10);
1681 row1.set_title(UTF8ToUTF16("cnn"));
1682 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1683 EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1684 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1686 // Insert the same URL, it should failed. The transaction are still same
1687 // after a rollback.
1688 ASSERT_FALSE(backend->InsertHistoryAndBookmark(row1));
1689 EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1690 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1692 // Insert another row to verify we are still fine after the previous
1694 HistoryAndBookmarkRow row2;
1695 row2.set_raw_url("http://www.example.com");
1696 row2.set_url(GURL("http://www.example.com"));
1697 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1698 row2.set_is_bookmark(false);
1699 row2.set_title(UTF8ToUTF16("example"));
1700 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1701 EXPECT_EQ(history_transaction, history_db_.transaction_nesting());
1702 EXPECT_EQ(thumbnail_transaction, thumbnail_db_.transaction_nesting());
1705 TEST_F(AndroidProviderBackendTest, TestAndroidCTSComplianceForZeroVisitCount) {
1706 // This is to verify the last visit time and created time are same when visit
1708 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1709 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1710 scoped_ptr<AndroidProviderBackend> backend(
1711 new AndroidProviderBackend(android_cache_db_name_,
1716 URLRow url_row(GURL("http://www.google.com"));
1717 url_row.set_last_visit(Time::Now());
1718 url_row.set_visit_count(0);
1719 history_db_.AddURL(url_row);
1721 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1723 projections.push_back(HistoryAndBookmarkRow::ID);
1724 projections.push_back(HistoryAndBookmarkRow::URL);
1725 projections.push_back(HistoryAndBookmarkRow::TITLE);
1726 projections.push_back(HistoryAndBookmarkRow::CREATED);
1727 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
1728 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
1729 projections.push_back(HistoryAndBookmarkRow::FAVICON);
1730 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
1732 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1733 projections, std::string(), std::vector<base::string16>(),
1734 std::string("url ASC")));
1736 ASSERT_TRUE(statement->statement()->Step());
1737 EXPECT_EQ(ToDatabaseTime(url_row.last_visit()),
1738 statement->statement()->ColumnInt64(3));
1739 EXPECT_EQ(ToDatabaseTime(url_row.last_visit()),
1740 statement->statement()->ColumnInt64(4));
1741 EXPECT_EQ(url_row.visit_count(), statement->statement()->ColumnInt(5));
1744 TEST_F(AndroidProviderBackendTest, AndroidCTSComplianceFolderColumnExists) {
1745 // This is test is used to verify the 'folder' column exists, all bookmarks
1746 // returned when folder is 0 and the non bookmark rows returned when folder
1748 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1749 ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_));
1750 scoped_ptr<AndroidProviderBackend> backend(
1751 new AndroidProviderBackend(android_cache_db_name_,
1756 HistoryAndBookmarkRow row1;
1757 row1.set_raw_url("cnn.com");
1758 row1.set_url(GURL("http://cnn.com"));
1759 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1760 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1761 row1.set_visit_count(10);
1762 row1.set_is_bookmark(true);
1763 row1.set_title(UTF8ToUTF16("cnn"));
1765 HistoryAndBookmarkRow row2;
1766 row2.set_raw_url("http://www.example.com");
1767 row2.set_url(GURL("http://www.example.com"));
1768 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1769 row2.set_is_bookmark(false);
1770 row2.set_title(UTF8ToUTF16("example"));
1771 std::vector<unsigned char> data;
1772 data.push_back('1');
1773 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1775 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
1777 AndroidURLID id2 = backend->InsertHistoryAndBookmark(row2);
1779 content::RunAllPendingInMessageLoop();
1781 // Query by folder=0, the row1 should returned.
1782 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1784 projections.push_back(HistoryAndBookmarkRow::URL);
1786 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1787 projections, std::string("folder=0"), std::vector<base::string16>(),
1788 std::string("url ASC")));
1789 ASSERT_TRUE(statement->statement()->Step());
1790 EXPECT_EQ(row1.raw_url(), statement->statement()->ColumnString(0));
1791 EXPECT_FALSE(statement->statement()->Step());
1793 // Query by folder=1, the row2 should returned.
1794 statement.reset(backend->QueryHistoryAndBookmarks(
1795 projections, std::string("folder=1"), std::vector<base::string16>(),
1796 std::string("url ASC")));
1797 ASSERT_TRUE(statement->statement()->Step());
1798 EXPECT_EQ(row2.url(), GURL(statement->statement()->ColumnString(0)));
1799 EXPECT_FALSE(statement->statement()->Step());
1802 TEST_F(AndroidProviderBackendTest, QueryWithoutThumbnailDB) {
1803 GURL url1("http://www.cnn.com");
1804 const base::string16 title1(UTF8ToUTF16("cnn"));
1805 std::vector<VisitInfo> visits1;
1806 Time last_visited1 = Time::Now() - TimeDelta::FromDays(1);
1807 Time created1 = last_visited1 - TimeDelta::FromDays(20);
1808 visits1.push_back(VisitInfo(created1, ui::PAGE_TRANSITION_LINK));
1809 visits1.push_back(VisitInfo(last_visited1 - TimeDelta::FromDays(1),
1810 ui::PAGE_TRANSITION_LINK));
1811 visits1.push_back(VisitInfo(last_visited1, ui::PAGE_TRANSITION_LINK));
1813 GURL url2("http://www.example.com");
1814 std::vector<VisitInfo> visits2;
1815 const base::string16 title2(UTF8ToUTF16("example"));
1816 Time last_visited2 = Time::Now();
1817 Time created2 = last_visited2 - TimeDelta::FromDays(10);
1818 visits2.push_back(VisitInfo(created2, ui::PAGE_TRANSITION_LINK));
1819 visits2.push_back(VisitInfo(last_visited2 - TimeDelta::FromDays(5),
1820 ui::PAGE_TRANSITION_LINK));
1821 visits2.push_back(VisitInfo(last_visited2, ui::PAGE_TRANSITION_LINK));
1823 // Only use the HistoryBackend to generate the test data.
1824 // HistoryBackend will shutdown after that.
1826 scoped_refptr<HistoryBackend> history_backend;
1827 history_backend = new HistoryBackend(
1828 temp_dir_.path(), new AndroidProviderBackendDelegate(), history_client_);
1829 history_backend->Init(std::string(), false);
1830 history_backend->AddVisits(url1, visits1, history::SOURCE_SYNCED);
1831 history_backend->AddVisits(url2, visits2, history::SOURCE_SYNCED);
1834 history::URLRows url_rows(2u);
1835 ASSERT_TRUE(history_backend->GetURL(url1, &url_rows[0]));
1836 ASSERT_TRUE(history_backend->GetURL(url2, &url_rows[1]));
1837 url_rows[0].set_title(title1);
1838 url_rows[1].set_title(title2);
1839 ASSERT_EQ(2u, history_backend->UpdateURLs(url_rows));
1841 // Set favicon to url2.
1842 std::vector<SkBitmap> bitmaps(1u, CreateBitmap());
1843 history_backend->SetFavicons(url2, favicon_base::FAVICON, GURL(), bitmaps);
1844 history_backend->Closing();
1847 // The history_db_name and thumbnail_db_name files should be created by
1848 // HistoryBackend. We need to open the same database files.
1849 ASSERT_TRUE(base::PathExists(history_db_name_));
1850 ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
1852 // Only creates the history database
1853 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1855 // Set url1 as bookmark.
1858 scoped_ptr<AndroidProviderBackend> backend(
1859 new AndroidProviderBackend(android_cache_db_name_,
1865 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
1867 projections.push_back(HistoryAndBookmarkRow::ID);
1868 projections.push_back(HistoryAndBookmarkRow::URL);
1869 projections.push_back(HistoryAndBookmarkRow::TITLE);
1870 projections.push_back(HistoryAndBookmarkRow::CREATED);
1871 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
1872 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
1873 projections.push_back(HistoryAndBookmarkRow::FAVICON);
1874 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
1876 scoped_ptr<AndroidStatement> statement(backend->QueryHistoryAndBookmarks(
1877 projections, std::string(), std::vector<base::string16>(),
1878 std::string("url ASC")));
1879 ASSERT_TRUE(statement->statement()->Step());
1880 ASSERT_EQ(url1, GURL(statement->statement()->ColumnString(1)));
1881 EXPECT_EQ(title1, statement->statement()->ColumnString16(2));
1882 EXPECT_EQ(ToDatabaseTime(created1),
1883 statement->statement()->ColumnInt64(3));
1884 EXPECT_EQ(ToDatabaseTime(last_visited1),
1885 statement->statement()->ColumnInt64(4));
1886 EXPECT_EQ(3, statement->statement()->ColumnInt(5));
1887 EXPECT_EQ(6, statement->favicon_index());
1889 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
1890 EXPECT_TRUE(statement->statement()->ColumnBool(7));
1892 ASSERT_TRUE(statement->statement()->Step());
1893 EXPECT_EQ(title2, statement->statement()->ColumnString16(2));
1894 ASSERT_EQ(url2, GURL(statement->statement()->ColumnString(1)));
1895 EXPECT_EQ(ToDatabaseTime(created2),
1896 statement->statement()->ColumnInt64(3));
1897 EXPECT_EQ(ToDatabaseTime(last_visited2),
1898 statement->statement()->ColumnInt64(4));
1899 EXPECT_EQ(3, statement->statement()->ColumnInt(5));
1900 std::vector<unsigned char> favicon2;
1901 EXPECT_EQ(6, statement->favicon_index());
1902 // No favicon because thumbnail database wasn't initialized.
1903 EXPECT_EQ(0, statement->statement()->ColumnByteLength(6));
1904 EXPECT_FALSE(statement->statement()->ColumnBool(7));
1907 EXPECT_FALSE(statement->statement()->Step());
1910 TEST_F(AndroidProviderBackendTest, InsertWithoutThumbnailDB) {
1911 HistoryAndBookmarkRow row1;
1912 row1.set_raw_url("cnn.com");
1913 row1.set_url(GURL("http://cnn.com"));
1914 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1915 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1916 row1.set_visit_count(10);
1917 row1.set_is_bookmark(true);
1918 row1.set_title(UTF8ToUTF16("cnn"));
1920 HistoryAndBookmarkRow row2;
1921 row2.set_raw_url("http://www.example.com");
1922 row2.set_url(GURL("http://www.example.com"));
1923 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1924 row2.set_is_bookmark(false);
1925 row2.set_title(UTF8ToUTF16("example"));
1926 std::vector<unsigned char> data;
1927 data.push_back('1');
1928 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1930 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
1931 scoped_ptr<AndroidProviderBackend> backend(
1932 new AndroidProviderBackend(android_cache_db_name_,
1938 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
1939 EXPECT_FALSE(delegate_.deleted_details());
1940 ASSERT_TRUE(delegate_.modified_details());
1941 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1942 EXPECT_EQ(row1.url(), delegate_.modified_details()->changed_urls[0].url());
1943 EXPECT_EQ(row1.last_visit_time(),
1944 delegate_.modified_details()->changed_urls[0].last_visit());
1945 EXPECT_EQ(row1.visit_count(),
1946 delegate_.modified_details()->changed_urls[0].visit_count());
1947 EXPECT_EQ(row1.title(),
1948 delegate_.modified_details()->changed_urls[0].title());
1949 EXPECT_FALSE(delegate_.favicon_changed());
1950 content::RunAllPendingInMessageLoop();
1951 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
1952 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
1954 EXPECT_EQ(row1.title(), child->GetTitle());
1955 EXPECT_EQ(row1.url(), child->url());
1957 delegate_.ResetDetails();
1958 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
1959 EXPECT_FALSE(delegate_.deleted_details());
1960 ASSERT_TRUE(delegate_.modified_details());
1961 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
1962 EXPECT_EQ(row2.url(), delegate_.modified_details()->changed_urls[0].url());
1963 EXPECT_EQ(row2.last_visit_time(),
1964 delegate_.modified_details()->changed_urls[0].last_visit());
1965 EXPECT_EQ(row2.title(),
1966 delegate_.modified_details()->changed_urls[0].title());
1967 // Favicon details is still false because thumbnail database wasn't
1968 // initialized, we ignore any changes of favicon.
1969 ASSERT_FALSE(delegate_.favicon_changed());
1972 TEST_F(AndroidProviderBackendTest, DeleteWithoutThumbnailDB) {
1973 HistoryAndBookmarkRow row1;
1974 row1.set_raw_url("cnn.com");
1975 row1.set_url(GURL("http://cnn.com"));
1976 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
1977 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
1978 row1.set_visit_count(10);
1979 row1.set_is_bookmark(true);
1980 row1.set_title(UTF8ToUTF16("cnn"));
1982 HistoryAndBookmarkRow row2;
1983 row2.set_raw_url("http://www.example.com");
1984 row2.set_url(GURL("http://www.example.com"));
1985 row2.set_last_visit_time(Time::Now() - TimeDelta::FromDays(10));
1986 row2.set_is_bookmark(false);
1987 row2.set_title(UTF8ToUTF16("example"));
1988 std::vector<unsigned char> data;
1989 data.push_back('1');
1990 row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
1993 HistoryDatabase history_db;
1994 ThumbnailDatabase thumbnail_db(NULL);
1995 ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
1996 ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_));
1998 scoped_ptr<AndroidProviderBackend> backend(
1999 new AndroidProviderBackend(android_cache_db_name_,
2005 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row1));
2006 ASSERT_TRUE(backend->InsertHistoryAndBookmark(row2));
2007 // Verify the row1 has been added in bookmark model.
2008 content::RunAllPendingInMessageLoop();
2009 ASSERT_EQ(1, bookmark_model_->mobile_node()->child_count());
2010 const BookmarkNode* child = bookmark_model_->mobile_node()->GetChild(0);
2012 EXPECT_EQ(row1.title(), child->GetTitle());
2013 EXPECT_EQ(row1.url(), child->url());
2015 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2016 scoped_ptr<AndroidProviderBackend> backend(
2017 new AndroidProviderBackend(android_cache_db_name_,
2024 std::vector<base::string16> args;
2025 int deleted_count = 0;
2026 delegate_.ResetDetails();
2027 ASSERT_TRUE(backend->DeleteHistoryAndBookmarks("Favicon IS NULL", args,
2029 // All rows were deleted.
2030 EXPECT_EQ(2, deleted_count);
2031 // Verify the rows was removed from bookmark model.
2032 content::RunAllPendingInMessageLoop();
2033 ASSERT_EQ(0, bookmark_model_->mobile_node()->child_count());
2035 // Verify notifications
2036 ASSERT_TRUE(delegate_.deleted_details());
2037 EXPECT_FALSE(delegate_.modified_details());
2038 EXPECT_EQ(2u, delegate_.deleted_details()->rows.size());
2039 // No favicon has been deleted.
2040 EXPECT_FALSE(delegate_.favicon_changed());
2043 std::vector<HistoryAndBookmarkRow::ColumnID> projections;
2044 projections.push_back(HistoryAndBookmarkRow::ID);
2045 projections.push_back(HistoryAndBookmarkRow::URL);
2046 projections.push_back(HistoryAndBookmarkRow::TITLE);
2047 projections.push_back(HistoryAndBookmarkRow::CREATED);
2048 projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
2049 projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
2050 projections.push_back(HistoryAndBookmarkRow::FAVICON);
2051 projections.push_back(HistoryAndBookmarkRow::BOOKMARK);
2053 scoped_ptr<AndroidStatement> statement1(backend->QueryHistoryAndBookmarks(
2054 projections, std::string(), std::vector<base::string16>(),
2055 std::string("url ASC")));
2056 ASSERT_FALSE(statement1->statement()->Step());
2059 TEST_F(AndroidProviderBackendTest, UpdateFaviconWithoutThumbnail) {
2060 HistoryAndBookmarkRow row1;
2061 row1.set_raw_url("cnn.com");
2062 row1.set_url(GURL("http://cnn.com"));
2063 row1.set_last_visit_time(Time::Now() - TimeDelta::FromDays(1));
2064 row1.set_created(Time::Now() - TimeDelta::FromDays(20));
2065 row1.set_visit_count(10);
2066 row1.set_is_bookmark(true);
2067 row1.set_title(UTF8ToUTF16("cnn"));
2070 HistoryDatabase history_db;
2071 ThumbnailDatabase thumbnail_db(NULL);
2072 ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
2073 ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_));
2074 scoped_ptr<AndroidProviderBackend> backend(
2075 new AndroidProviderBackend(android_cache_db_name_,
2081 AndroidURLID id1 = backend->InsertHistoryAndBookmark(row1);
2085 ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
2086 scoped_ptr<AndroidProviderBackend> backend(
2087 new AndroidProviderBackend(android_cache_db_name_,
2094 std::vector<base::string16> update_args;
2095 // Update the last visit time to a value greater than current one.
2096 HistoryAndBookmarkRow update_row1;
2099 update_row1.set_visit_count(5);
2101 std::vector<unsigned char> data;
2102 data.push_back('1');
2103 update_row1.set_favicon(base::RefCountedBytes::TakeVector(&data));
2104 update_args.push_back(UTF8ToUTF16(row1.raw_url()));
2105 delegate_.ResetDetails();
2106 ASSERT_TRUE(backend->UpdateHistoryAndBookmarks(update_row1, "url = ?",
2107 update_args, &update_count));
2108 // Verify notifications.
2109 EXPECT_FALSE(delegate_.deleted_details());
2110 ASSERT_TRUE(delegate_.modified_details());
2111 ASSERT_EQ(1u, delegate_.modified_details()->changed_urls.size());
2112 // No favicon will be updated as thumbnail database is missing.
2113 EXPECT_FALSE(delegate_.favicon_changed());
2116 } // namespace history