blob: 648eeb314a1c19236916f785232e14758173b4b3 [file] [log] [blame]
// Copyright 2019 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/content_index/content_index_provider_impl.h"
#include <memory>
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/time/time.h"
#include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/engagement/site_engagement_service_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/test/test_history_database.h"
#include "components/offline_items_collection/core/offline_content_provider.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_index_provider.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_storage_partition.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace {
using offline_items_collection::ContentId;
using offline_items_collection::OfflineContentAggregator;
using offline_items_collection::OfflineContentProvider;
using offline_items_collection::OfflineItem;
using offline_items_collection::OfflineItemVisuals;
using offline_items_collection::UpdateDelta;
using testing::_;
constexpr int64_t kServiceWorkerRegistrationId = 42;
constexpr double kEngagementScore = 42.0;
// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
// function.
GURL LaunchURL() {
return GURL("https://example.com/foo");
}
url::Origin Origin() {
return url::Origin::Create(LaunchURL().GetOrigin());
}
// Hosts the test profile. Global to be accessible from
// |BuildTestHistoryService|.
base::FilePath profile_path;
std::unique_ptr<KeyedService> BuildTestHistoryService(
content::BrowserContext* context) {
std::unique_ptr<history::HistoryService> service(
std::make_unique<history::HistoryService>());
service->Init(history::TestHistoryDatabaseParamsForPath(profile_path));
return std::move(service);
}
std::unique_ptr<KeyedService> BuildTestSiteEngagementService(
content::BrowserContext* context) {
Profile* profile = static_cast<Profile*>(context);
std::unique_ptr<SiteEngagementService> service(
std::make_unique<SiteEngagementService>(profile));
service->ResetBaseScoreForURL(Origin().GetURL(), kEngagementScore);
return std::move(service);
}
} // namespace
class ContentIndexProviderImplTest : public testing::Test,
public OfflineContentProvider::Observer {
public:
void SetUp() override {
TestingProfile::Builder builder;
builder.AddTestingFactory(HistoryServiceFactory::GetInstance(),
base::BindRepeating(&BuildTestHistoryService));
builder.AddTestingFactory(
SiteEngagementServiceFactory::GetInstance(),
base::BindRepeating(&BuildTestSiteEngagementService));
ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
profile_path = profile_dir_.GetPath();
builder.SetPath(profile_dir_.GetPath());
profile_ = builder.Build();
provider_ = std::make_unique<ContentIndexProviderImpl>(profile_.get());
provider_->AddObserver(this);
}
void TearDown() override { provider_->RemoveObserver(this); }
// OfflineContentProvider::Observer implementation.
MOCK_METHOD1(OnItemsAdded,
void(const OfflineContentProvider::OfflineItemList& items));
MOCK_METHOD1(OnItemRemoved, void(const ContentId& id));
void OnItemUpdated(const OfflineItem& item,
const base::Optional<UpdateDelta>& update_delta) override {
NOTREACHED();
}
content::ContentIndexEntry CreateEntry(const std::string& id) {
auto description = blink::mojom::ContentDescription::New(
id, "title", "description", blink::mojom::ContentCategory::ARTICLE,
std::vector<blink::mojom::ContentIconDefinitionPtr>(), "launch_url");
return content::ContentIndexEntry(kServiceWorkerRegistrationId,
std::move(description), LaunchURL(),
base::Time::Now());
}
protected:
base::ScopedTempDir profile_dir_;
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<ContentIndexProviderImpl> provider_;
};
TEST_F(ContentIndexProviderImplTest, OfflineItemCreation) {
std::vector<OfflineItem> items;
{
EXPECT_CALL(*this, OnItemsAdded(_)).WillOnce(testing::SaveArg<0>(&items));
provider_->OnContentAdded(CreateEntry("id"));
}
ASSERT_EQ(items.size(), 1u);
const auto& item = items[0];
EXPECT_FALSE(item.id.name_space.empty());
EXPECT_FALSE(item.id.id.empty());
EXPECT_FALSE(item.title.empty());
EXPECT_FALSE(item.description.empty());
EXPECT_FALSE(item.is_transient);
EXPECT_TRUE(item.is_suggested);
EXPECT_TRUE(item.is_openable);
EXPECT_EQ(item.page_url, LaunchURL());
EXPECT_EQ(item.content_quality_score, kEngagementScore / 100.0);
}
TEST_F(ContentIndexProviderImplTest, ObserverUpdates) {
{
EXPECT_CALL(*this, OnItemsAdded(_));
provider_->OnContentAdded(CreateEntry("id"));
}
// Adding an already existing ID should call update.
{
EXPECT_CALL(*this, OnItemRemoved(_)).Times(1);
EXPECT_CALL(*this, OnItemsAdded(_)).Times(1);
provider_->OnContentAdded(CreateEntry("id"));
}
{
EXPECT_CALL(*this, OnItemRemoved(_));
provider_->OnContentDeleted(kServiceWorkerRegistrationId, Origin(), "id");
}
}