blob: d76ea9dae796b3f96ababea6743071e75f57dff7 [file] [log] [blame]
// Copyright 2017 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 "components/ntp_snippets/remote/prefetched_pages_tracker_impl.h"
#include "base/bind.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/mock_callback.h"
#include "components/ntp_snippets/offline_pages/offline_pages_test_utils.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/stub_offline_page_model.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ntp_snippets::test::FakeOfflinePageModel;
using offline_pages::MultipleOfflinePageItemCallback;
using offline_pages::OfflinePageItem;
using testing::_;
using testing::Eq;
using testing::SaveArg;
using testing::StrictMock;
namespace ntp_snippets {
namespace {
const int64_t kSystemDownloadId = 0;
class MockOfflinePageModel : public offline_pages::StubOfflinePageModel {
public:
~MockOfflinePageModel() override = default;
MOCK_METHOD2(GetPagesByNamespace,
void(const std::string& name_space,
MultipleOfflinePageItemCallback callback));
};
OfflinePageItem CreateOfflinePageItem(const GURL& url,
const std::string& name_space) {
static int id = 0;
++id;
return OfflinePageItem(
url, id, offline_pages::ClientId(name_space, base::NumberToString(id)),
base::FilePath::FromUTF8Unsafe(
base::StringPrintf("some/folder/%d.mhtml", id)),
0, base::Time::Now());
}
} // namespace
class PrefetchedPagesTrackerImplTest : public ::testing::Test {
public:
PrefetchedPagesTrackerImplTest() = default;
FakeOfflinePageModel* fake_offline_page_model() {
return &fake_offline_page_model_;
}
MockOfflinePageModel* mock_offline_page_model() {
return &mock_offline_page_model_;
}
private:
FakeOfflinePageModel fake_offline_page_model_;
StrictMock<MockOfflinePageModel> mock_offline_page_model_;
DISALLOW_COPY_AND_ASSIGN(PrefetchedPagesTrackerImplTest);
};
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldRetrievePrefetchedEarlierSuggestionsOnInitialize) {
(*fake_offline_page_model()->mutable_items()) = {
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace)};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://not_added_url.com")));
EXPECT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldAddNewPrefetchedPagesWhenNotified) {
fake_offline_page_model()->mutable_items()->clear();
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageAdded(
fake_offline_page_model(),
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace));
EXPECT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldIgnoreOtherTypesOfOfflinePagesWhenNotified) {
fake_offline_page_model()->mutable_items()->clear();
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
tracker.OfflinePageAdded(
fake_offline_page_model(),
CreateOfflinePageItem(GURL("http://manually_downloaded.com"),
offline_pages::kNTPSuggestionsNamespace));
EXPECT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldIgnoreOtherTypesOfOfflinePagesOnStartup) {
(*fake_offline_page_model()->mutable_items()) = {
CreateOfflinePageItem(GURL("http://manually_downloaded.com"),
offline_pages::kNTPSuggestionsNamespace)};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
EXPECT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest, ShouldDeletePrefetchedURLWhenNotified) {
const OfflinePageItem item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
item.offline_id, kSystemDownloadId, item.client_id,
/*request_origin=*/"", item.original_url));
EXPECT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldIgnoreDeletionOfOtherTypeOfflinePagesWhenNotified) {
const OfflinePageItem prefetched_item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
// The URL is intentionally the same.
const OfflinePageItem manually_downloaded_item = CreateOfflinePageItem(
GURL("http://prefetched.com"), offline_pages::kNTPSuggestionsNamespace);
(*fake_offline_page_model()->mutable_items()) = {prefetched_item,
manually_downloaded_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
manually_downloaded_item.offline_id, kSystemDownloadId,
manually_downloaded_item.client_id,
/*request_origin=*/"", manually_downloaded_item.original_url));
EXPECT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldReportAsNotInitializedBeforeReceivedArticles) {
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _));
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
EXPECT_FALSE(tracker.IsInitialized());
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldReportAsInitializedAfterInitialization) {
MultipleOfflinePageItemCallback offline_pages_callback;
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce([&](const std::string& name_space,
MultipleOfflinePageItemCallback callback) {
offline_pages_callback = std::move(callback);
});
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.IsInitialized());
std::move(offline_pages_callback).Run(std::vector<OfflinePageItem>());
EXPECT_TRUE(tracker.IsInitialized());
}
TEST_F(PrefetchedPagesTrackerImplTest, ShouldCallCallbackAfterInitialization) {
MultipleOfflinePageItemCallback offline_pages_callback;
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce([&](const std::string& name_space,
MultipleOfflinePageItemCallback callback) {
offline_pages_callback = std::move(callback);
});
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
base::MockCallback<base::OnceCallback<void()>>
mock_initialization_completed_callback;
tracker.Initialize(mock_initialization_completed_callback.Get());
EXPECT_CALL(mock_initialization_completed_callback, Run());
std::move(offline_pages_callback).Run(std::vector<OfflinePageItem>());
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldCallMultipleCallbacksAfterInitialization) {
MultipleOfflinePageItemCallback offline_pages_callback;
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce([&](const std::string& name_space,
MultipleOfflinePageItemCallback callback) {
offline_pages_callback = std::move(callback);
});
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
base::MockCallback<base::OnceCallback<void()>>
first_mock_initialization_completed_callback,
second_mock_initialization_completed_callback;
tracker.Initialize(first_mock_initialization_completed_callback.Get());
tracker.Initialize(second_mock_initialization_completed_callback.Get());
EXPECT_CALL(first_mock_initialization_completed_callback, Run());
EXPECT_CALL(second_mock_initialization_completed_callback, Run());
std::move(offline_pages_callback).Run(std::vector<OfflinePageItem>());
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldCallCallbackImmediatelyIfAlreadyInitialiazed) {
MultipleOfflinePageItemCallback offline_pages_callback;
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce([&](const std::string& name_space,
MultipleOfflinePageItemCallback callback) {
offline_pages_callback = std::move(callback);
});
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
std::move(offline_pages_callback).Run(std::vector<OfflinePageItem>());
base::MockCallback<base::OnceCallback<void()>>
mock_initialization_completed_callback;
EXPECT_CALL(mock_initialization_completed_callback, Run());
tracker.Initialize(mock_initialization_completed_callback.Get());
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldKeepPrefetchedURLAfterDuplicatePageDeleted) {
const OfflinePageItem first_item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
const OfflinePageItem second_item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {first_item, second_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
first_item.offline_id, kSystemDownloadId, first_item.client_id,
/*request_origin=*/"", first_item.original_url));
// Only one offline page (out of two) has been removed, the remaining one
// should be reported here.
EXPECT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
ShouldDeletePrefetchedURLAfterAllItsPagesAreDeleted) {
const OfflinePageItem first_item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
const OfflinePageItem second_item =
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {first_item, second_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
first_item.offline_id, kSystemDownloadId, first_item.client_id,
/*request_origin=*/"", first_item.original_url));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
second_item.offline_id, kSystemDownloadId, second_item.client_id,
/*request_origin=*/"", second_item.original_url));
// All offline pages have been removed, their absence should be reported here.
EXPECT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
} // namespace ntp_snippets