1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 7 #include "base/message_loop/message_loop.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/bookmarks/bookmark_model.h" 10 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 11 #include "chrome/browser/bookmarks/bookmark_title_match.h" 12 #include "chrome/browser/bookmarks/bookmark_utils.h" 13 #include "chrome/browser/history/history_service_factory.h" 14 #include "chrome/browser/history/history_types.h" 15 #include "chrome/browser/importer/importer_unittest_utils.h" 16 #include "chrome/browser/importer/profile_writer.h" 17 #include "chrome/common/importer/imported_bookmark_entry.h" 18 #include "chrome/test/base/testing_profile.h" 19 #include "chrome/test/base/ui_test_utils.h" 20 #include "content/public/test/test_browser_thread.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 using content::BrowserThread; 24 25 class TestProfileWriter : public ProfileWriter { 26 public: 27 explicit TestProfileWriter(Profile* profile) : ProfileWriter(profile) {} 28 protected: 29 virtual ~TestProfileWriter() {} 30 }; 31 32 class ProfileWriterTest : public testing::Test { 33 public: 34 ProfileWriterTest() 35 : loop_(base::MessageLoop::TYPE_DEFAULT), 36 ui_thread_(BrowserThread::UI, &loop_), 37 file_thread_(BrowserThread::FILE, &loop_) { 38 } 39 virtual ~ProfileWriterTest() {} 40 41 // Create test bookmark entries to be added to ProfileWriter to 42 // simulate bookmark importing. 43 void CreateImportedBookmarksEntries() { 44 AddImportedBookmarkEntry(GURL("http://www.google.com"), 45 ASCIIToUTF16("Google")); 46 AddImportedBookmarkEntry(GURL("http://www.yahoo.com"), 47 ASCIIToUTF16("Yahoo")); 48 } 49 50 // Helper function to create history entries. 51 history::URLRow MakeURLRow(const char* url, 52 string16 title, 53 int visit_count, 54 int days_since_last_visit, 55 int typed_count) { 56 history::URLRow row(GURL(url), 0); 57 row.set_title(title); 58 row.set_visit_count(visit_count); 59 row.set_typed_count(typed_count); 60 row.set_last_visit(base::Time::NowFromSystemTime() - 61 base::TimeDelta::FromDays(days_since_last_visit)); 62 return row; 63 } 64 65 // Create test history entries to be added to ProfileWriter to 66 // simulate history importing. 67 void CreateHistoryPageEntries() { 68 history::URLRow row1( 69 MakeURLRow("http://www.google.com", ASCIIToUTF16("Google"), 3, 10, 1)); 70 history::URLRow row2( 71 MakeURLRow("http://www.yahoo.com", ASCIIToUTF16("Yahoo"), 3, 30, 10)); 72 pages_.push_back(row1); 73 pages_.push_back(row2); 74 } 75 76 void VerifyBookmarksCount( 77 const std::vector<BookmarkService::URLAndTitle>& bookmarks_record, 78 BookmarkModel* bookmark_model, 79 size_t expected) { 80 std::vector<BookmarkTitleMatch> matches; 81 for (size_t i = 0; i < bookmarks_record.size(); ++i) { 82 bookmark_model->GetBookmarksWithTitlesMatching(bookmarks_record[i].title, 83 10, 84 &matches); 85 EXPECT_EQ(expected, matches.size()); 86 matches.clear(); 87 } 88 } 89 90 void VerifyHistoryCount(Profile* profile) { 91 HistoryService* history_service = 92 HistoryServiceFactory::GetForProfile(profile, 93 Profile::EXPLICIT_ACCESS); 94 history::QueryOptions options; 95 CancelableRequestConsumer history_request_consumer; 96 history_service->QueryHistory( 97 string16(), 98 options, 99 &history_request_consumer, 100 base::Bind(&ProfileWriterTest::HistoryQueryComplete, 101 base::Unretained(this))); 102 base::MessageLoop::current()->Run(); 103 } 104 105 void HistoryQueryComplete(HistoryService::Handle handle, 106 history::QueryResults* results) { 107 base::MessageLoop::current()->Quit(); 108 history_count_ = results->size(); 109 } 110 111 protected: 112 std::vector<ImportedBookmarkEntry> bookmarks_; 113 history::URLRows pages_; 114 size_t history_count_; 115 116 private: 117 void AddImportedBookmarkEntry(const GURL& url, const string16& title) { 118 base::Time date; 119 ImportedBookmarkEntry entry; 120 entry.creation_time = date; 121 entry.url = url; 122 entry.title = title; 123 entry.in_toolbar = true; 124 entry.is_folder = false; 125 bookmarks_.push_back(entry); 126 } 127 128 base::MessageLoop loop_; 129 content::TestBrowserThread ui_thread_; 130 content::TestBrowserThread file_thread_; 131 132 DISALLOW_COPY_AND_ASSIGN(ProfileWriterTest); 133 }; 134 135 // Add bookmarks via ProfileWriter to profile1 when profile2 also exists. 136 TEST_F(ProfileWriterTest, CheckBookmarksWithMultiProfile) { 137 TestingProfile profile2; 138 profile2.CreateBookmarkModel(true); 139 140 BookmarkModel* bookmark_model2 = 141 BookmarkModelFactory::GetForProfile(&profile2); 142 ui_test_utils::WaitForBookmarkModelToLoad(bookmark_model2); 143 bookmark_utils::AddIfNotBookmarked(bookmark_model2, 144 GURL("http://www.bing.com"), 145 ASCIIToUTF16("Bing")); 146 TestingProfile profile1; 147 profile1.CreateBookmarkModel(true); 148 149 CreateImportedBookmarksEntries(); 150 BookmarkModel* bookmark_model1 = 151 BookmarkModelFactory::GetForProfile(&profile1); 152 ui_test_utils::WaitForBookmarkModelToLoad(bookmark_model1); 153 154 scoped_refptr<TestProfileWriter> profile_writer( 155 new TestProfileWriter(&profile1)); 156 profile_writer->AddBookmarks(bookmarks_, 157 ASCIIToUTF16("Imported from Firefox")); 158 159 std::vector<BookmarkService::URLAndTitle> url_record1; 160 bookmark_model1->GetBookmarks(&url_record1); 161 EXPECT_EQ(2u, url_record1.size()); 162 163 std::vector<BookmarkService::URLAndTitle> url_record2; 164 bookmark_model2->GetBookmarks(&url_record2); 165 EXPECT_EQ(1u, url_record2.size()); 166 } 167 168 // Verify that bookmarks are duplicated when added twice. 169 TEST_F(ProfileWriterTest, CheckBookmarksAfterWritingDataTwice) { 170 TestingProfile profile; 171 profile.CreateBookmarkModel(true); 172 173 CreateImportedBookmarksEntries(); 174 BookmarkModel* bookmark_model = 175 BookmarkModelFactory::GetForProfile(&profile); 176 ui_test_utils::WaitForBookmarkModelToLoad(bookmark_model); 177 178 scoped_refptr<TestProfileWriter> profile_writer( 179 new TestProfileWriter(&profile)); 180 profile_writer->AddBookmarks(bookmarks_, 181 ASCIIToUTF16("Imported from Firefox")); 182 std::vector<BookmarkService::URLAndTitle> bookmarks_record; 183 bookmark_model->GetBookmarks(&bookmarks_record); 184 EXPECT_EQ(2u, bookmarks_record.size()); 185 186 VerifyBookmarksCount(bookmarks_record, bookmark_model, 1); 187 188 profile_writer->AddBookmarks(bookmarks_, 189 ASCIIToUTF16("Imported from Firefox")); 190 // Verify that duplicate bookmarks exist. 191 VerifyBookmarksCount(bookmarks_record, bookmark_model, 2); 192 } 193 194 // Verify that history entires are not duplicated when added twice. 195 TEST_F(ProfileWriterTest, CheckHistoryAfterWritingDataTwice) { 196 TestingProfile profile; 197 ASSERT_TRUE(profile.CreateHistoryService(true, false)); 198 profile.BlockUntilHistoryProcessesPendingRequests(); 199 200 CreateHistoryPageEntries(); 201 scoped_refptr<TestProfileWriter> profile_writer( 202 new TestProfileWriter(&profile)); 203 profile_writer->AddHistoryPage(pages_, history::SOURCE_FIREFOX_IMPORTED); 204 VerifyHistoryCount(&profile); 205 size_t original_history_count = history_count_; 206 history_count_ = 0; 207 208 profile_writer->AddHistoryPage(pages_, history::SOURCE_FIREFOX_IMPORTED); 209 VerifyHistoryCount(&profile); 210 EXPECT_EQ(original_history_count, history_count_); 211 } 212