blob: 61a567d1dc5bd15c2c745e3769ed4bbeb208c9e6 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/importer/profile_writer.h"
#include <stddef.h>
#include <string>
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/importer/importer_unittest_utils.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/test/base/testing_profile.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_utils.h"
#include "components/bookmarks/browser/titled_url_match.h"
#include "components/bookmarks/browser/url_and_title.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_types.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
using bookmarks::BookmarkModel;
using bookmarks::TitledUrlMatch;
using bookmarks::UrlAndTitle;
class TestProfileWriter : public ProfileWriter {
public:
explicit TestProfileWriter(Profile* profile) : ProfileWriter(profile) {}
protected:
~TestProfileWriter() override {}
};
class ProfileWriterTest : public testing::Test {
public:
ProfileWriterTest() {}
~ProfileWriterTest() override {}
void SetUp() override {
DCHECK(profile_dir_.CreateUniqueTempDir());
TestingProfile::Builder profile_builder;
profile_builder.SetPath(profile_dir_.GetPath());
profile_builder.AddTestingFactory(
BookmarkModelFactory::GetInstance(),
BookmarkModelFactory::GetDefaultFactory());
profile_builder.AddTestingFactory(
HistoryServiceFactory::GetInstance(),
HistoryServiceFactory::GetDefaultFactory());
profile_ = profile_builder.Build();
DCHECK(second_profile_dir_.CreateUniqueTempDir());
TestingProfile::Builder second_profile_builder;
second_profile_builder.SetPath(second_profile_dir_.GetPath());
second_profile_builder.AddTestingFactory(
BookmarkModelFactory::GetInstance(),
BookmarkModelFactory::GetDefaultFactory());
second_profile_builder.AddTestingFactory(
HistoryServiceFactory::GetInstance(),
HistoryServiceFactory::GetDefaultFactory());
second_profile_ = second_profile_builder.Build();
}
TestingProfile* profile() { return profile_.get(); }
TestingProfile* second_profile() { return second_profile_.get(); }
// Create test bookmark entries to be added to ProfileWriter to
// simulate bookmark importing.
void CreateImportedBookmarksEntries() {
AddImportedBookmarkEntry(GURL("http://www.google.com"),
base::ASCIIToUTF16("Google"));
AddImportedBookmarkEntry(GURL("http://www.yahoo.com"),
base::ASCIIToUTF16("Yahoo"));
}
// Helper function to create history entries.
history::URLRow MakeURLRow(const char* url,
base::string16 title,
int visit_count,
int days_since_last_visit,
int typed_count) {
history::URLRow row(GURL(url), 0);
row.set_title(title);
row.set_visit_count(visit_count);
row.set_typed_count(typed_count);
row.set_last_visit(base::Time::NowFromSystemTime() -
base::TimeDelta::FromDays(days_since_last_visit));
return row;
}
// Create test history entries to be added to ProfileWriter to
// simulate history importing.
void CreateHistoryPageEntries() {
history::URLRow row1(
MakeURLRow("http://www.google.com", base::ASCIIToUTF16("Google"),
3, 10, 1));
history::URLRow row2(
MakeURLRow("http://www.yahoo.com", base::ASCIIToUTF16("Yahoo"),
3, 30, 10));
pages_.push_back(row1);
pages_.push_back(row2);
}
void VerifyBookmarksCount(const std::vector<UrlAndTitle>& bookmarks_record,
BookmarkModel* bookmark_model,
size_t expected) {
std::vector<TitledUrlMatch> matches;
for (size_t i = 0; i < bookmarks_record.size(); ++i) {
bookmark_model->GetBookmarksMatching(
bookmarks_record[i].title, 10, &matches);
EXPECT_EQ(expected, matches.size());
matches.clear();
}
}
void VerifyHistoryCount(Profile* profile) {
history::HistoryService* history_service =
HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS);
history::QueryOptions options;
base::CancelableTaskTracker history_task_tracker;
base::RunLoop loop;
history_service->QueryHistory(
base::string16(), options,
base::BindLambdaForTesting([&](history::QueryResults results) {
history_count_ = results.size();
loop.Quit();
}),
&history_task_tracker);
loop.Run();
}
// Creates a TemplateURL from the provided data.
std::unique_ptr<TemplateURL> CreateTemplateURL(const std::string& keyword,
const std::string& url,
const std::string& short_name);
protected:
std::vector<ImportedBookmarkEntry> bookmarks_;
history::URLRows pages_;
size_t history_count_;
private:
void AddImportedBookmarkEntry(const GURL& url, const base::string16& title) {
base::Time date;
ImportedBookmarkEntry entry;
entry.creation_time = date;
entry.url = url;
entry.title = title;
entry.in_toolbar = true;
entry.is_folder = false;
bookmarks_.push_back(entry);
}
// Profile directories that outlive |task_environment_| are needed because
// CreateHistoryService/CreateBookmarkModel use the directory to host
// databases. See https://crbug.com/546640 for more details.
base::ScopedTempDir profile_dir_;
base::ScopedTempDir second_profile_dir_;
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<TestingProfile> second_profile_;
DISALLOW_COPY_AND_ASSIGN(ProfileWriterTest);
};
// Add bookmarks via ProfileWriter to profile1 when profile2 also exists.
TEST_F(ProfileWriterTest, CheckBookmarksWithMultiProfile) {
BookmarkModel* bookmark_model2 =
BookmarkModelFactory::GetForBrowserContext(second_profile());
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model2);
bookmarks::AddIfNotBookmarked(
bookmark_model2, GURL("http://www.bing.com"), base::ASCIIToUTF16("Bing"));
CreateImportedBookmarksEntries();
BookmarkModel* bookmark_model1 =
BookmarkModelFactory::GetForBrowserContext(profile());
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model1);
scoped_refptr<TestProfileWriter> profile_writer(
new TestProfileWriter(profile()));
profile_writer->AddBookmarks(bookmarks_,
base::ASCIIToUTF16("Imported from Firefox"));
std::vector<UrlAndTitle> url_record1;
bookmark_model1->GetBookmarks(&url_record1);
EXPECT_EQ(2u, url_record1.size());
std::vector<UrlAndTitle> url_record2;
bookmark_model2->GetBookmarks(&url_record2);
EXPECT_EQ(1u, url_record2.size());
}
// Verify that bookmarks are duplicated when added twice.
TEST_F(ProfileWriterTest, CheckBookmarksAfterWritingDataTwice) {
CreateImportedBookmarksEntries();
BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile());
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
scoped_refptr<TestProfileWriter> profile_writer(
new TestProfileWriter(profile()));
profile_writer->AddBookmarks(bookmarks_,
base::ASCIIToUTF16("Imported from Firefox"));
std::vector<UrlAndTitle> bookmarks_record;
bookmark_model->GetBookmarks(&bookmarks_record);
EXPECT_EQ(2u, bookmarks_record.size());
VerifyBookmarksCount(bookmarks_record, bookmark_model, 1);
profile_writer->AddBookmarks(bookmarks_,
base::ASCIIToUTF16("Imported from Firefox"));
// Verify that duplicate bookmarks exist.
VerifyBookmarksCount(bookmarks_record, bookmark_model, 2);
}
std::unique_ptr<TemplateURL> ProfileWriterTest::CreateTemplateURL(
const std::string& keyword,
const std::string& url,
const std::string& short_name) {
TemplateURLData data;
data.SetKeyword(base::ASCIIToUTF16(keyword));
data.SetShortName(base::ASCIIToUTF16(short_name));
data.SetURL(TemplateURLRef::DisplayURLToURLRef(base::ASCIIToUTF16(url)));
return std::make_unique<TemplateURL>(data);
}
// Verify that history entires are not duplicated when added twice.
TEST_F(ProfileWriterTest, CheckHistoryAfterWritingDataTwice) {
profile()->BlockUntilHistoryProcessesPendingRequests();
CreateHistoryPageEntries();
scoped_refptr<TestProfileWriter> profile_writer(
new TestProfileWriter(profile()));
profile_writer->AddHistoryPage(pages_, history::SOURCE_FIREFOX_IMPORTED);
VerifyHistoryCount(profile());
size_t original_history_count = history_count_;
history_count_ = 0;
profile_writer->AddHistoryPage(pages_, history::SOURCE_FIREFOX_IMPORTED);
VerifyHistoryCount(profile());
EXPECT_EQ(original_history_count, history_count_);
}
TEST_F(ProfileWriterTest, AddKeywords) {
TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile(),
base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor));
TemplateURLService::OwnedTemplateURLVector keywords;
keywords.push_back(CreateTemplateURL("key1", "http://key1.com", "n1"));
// This entry will not be added since it has the same key as an existing
// keyword.
keywords.push_back(CreateTemplateURL("key1", "http://key1_1.com", "n1_1"));
keywords.push_back(CreateTemplateURL("key2", "http://key2.com", "n2"));
// This entry will not be added since the keyword contains spaces.
keywords.push_back(CreateTemplateURL("key 3", "http://key3.com", "n3"));
auto profile_writer = base::MakeRefCounted<TestProfileWriter>(profile());
profile_writer->AddKeywords(std::move(keywords), false);
TemplateURLService* turl_model =
TemplateURLServiceFactory::GetForProfile(profile());
auto turls = turl_model->GetTemplateURLs();
EXPECT_EQ(turls.size(), 2u);
EXPECT_EQ(turls[0]->keyword(), base::ASCIIToUTF16("key1"));
EXPECT_EQ(turls[0]->url(), "http://key1.com");
EXPECT_EQ(turls[0]->short_name(), base::ASCIIToUTF16("n1"));
EXPECT_EQ(turls[1]->keyword(), base::ASCIIToUTF16("key2"));
EXPECT_EQ(turls[1]->url(), "http://key2.com");
EXPECT_EQ(turls[1]->short_name(), base::ASCIIToUTF16("n2"));
}