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