| // Copyright 2015 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/offline_pages/offline_page_model_impl.h" |
| |
| #include <stdint.h> |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/feature_list.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/metrics/statistics_recorder.h" |
| #include "base/run_loop.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/test_mock_time_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.h" |
| #include "components/offline_pages/client_namespace_constants.h" |
| #include "components/offline_pages/client_policy_controller.h" |
| #include "components/offline_pages/offline_page_client_policy.h" |
| #include "components/offline_pages/offline_page_feature.h" |
| #include "components/offline_pages/offline_page_item.h" |
| #include "components/offline_pages/offline_page_storage_manager.h" |
| #include "components/offline_pages/offline_page_test_archiver.h" |
| #include "components/offline_pages/offline_page_test_store.h" |
| #include "components/offline_pages/offline_page_types.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace offline_pages { |
| |
| namespace { |
| const char kTestClientNamespace[] = "CLIENT_NAMESPACE"; |
| const char kUserRequestedNamespace[] = "download"; |
| const GURL kTestUrl("http://example.com"); |
| const GURL kTestUrl2("http://other.page.com"); |
| const GURL kTestUrl3("http://test.xyz"); |
| const GURL kTestUrl4("http://page.net"); |
| const GURL kFileUrl("file:///foo"); |
| const ClientId kTestClientId1(kTestClientNamespace, "1234"); |
| const ClientId kTestClientId2(kTestClientNamespace, "5678"); |
| const ClientId kTestClientId3(kTestClientNamespace, "42"); |
| const ClientId kTestUserRequestedClientId(kUserRequestedNamespace, "714"); |
| const int64_t kTestFileSize = 876543LL; |
| const base::string16 kTestTitle = base::UTF8ToUTF16("a title"); |
| |
| bool URLSpecContains(std::string contains_value, const GURL& url) { |
| std::string spec = url.spec(); |
| return spec.find(contains_value) != std::string::npos; |
| } |
| |
| } // namespace |
| |
| class OfflinePageModelImplTest |
| : public testing::Test, |
| public OfflinePageModel::Observer, |
| public OfflinePageTestArchiver::Observer, |
| public base::SupportsWeakPtr<OfflinePageModelImplTest> { |
| public: |
| OfflinePageModelImplTest(); |
| ~OfflinePageModelImplTest() override; |
| |
| void SetUp() override; |
| void TearDown() override; |
| |
| // OfflinePageModel::Observer implementation. |
| void OfflinePageModelLoaded(OfflinePageModel* model) override; |
| void OfflinePageModelChanged(OfflinePageModel* model) override; |
| void OfflinePageDeleted(int64_t offline_id, |
| const ClientId& client_id) override; |
| |
| // OfflinePageTestArchiver::Observer implementation. |
| void SetLastPathCreatedByArchiver(const base::FilePath& file_path) override; |
| |
| // OfflinePageModel callbacks. |
| void OnSavePageDone(SavePageResult result, int64_t offline_id); |
| void OnDeletePageDone(DeletePageResult result); |
| void OnCheckPagesExistOfflineDone(const CheckPagesExistOfflineResult& result); |
| void OnGetOfflineIdsForClientIdDone(MultipleOfflineIdResult* storage, |
| const MultipleOfflineIdResult& result); |
| void OnGetSingleOfflinePageItemResult(const OfflinePageItem** storage, |
| const OfflinePageItem* result); |
| void OnGetMultipleOfflinePageItemsResult( |
| MultipleOfflinePageItemResult* storage, |
| const MultipleOfflinePageItemResult& result); |
| void OnPagesExpired(bool result); |
| |
| // OfflinePageMetadataStore callbacks. |
| void OnStoreUpdateDone(bool /* success */); |
| |
| std::unique_ptr<OfflinePageTestArchiver> BuildArchiver( |
| const GURL& url, |
| OfflinePageArchiver::ArchiverResult result); |
| std::unique_ptr<OfflinePageMetadataStore> BuildStore(); |
| std::unique_ptr<OfflinePageModelImpl> BuildModel( |
| std::unique_ptr<OfflinePageMetadataStore> store); |
| void ResetModel(); |
| |
| // Utility methods. |
| // Runs until all of the tasks that are not delayed are gone from the task |
| // queue. |
| void PumpLoop(); |
| // Fast-forwards virtual time by |delta|, causing tasks with a remaining |
| // delay less than or equal to |delta| to be executed. |
| void FastForwardBy(base::TimeDelta delta); |
| void ResetResults(); |
| |
| OfflinePageTestStore* GetStore(); |
| |
| MultipleOfflinePageItemResult GetAllPages(); |
| |
| // Returns the offline ID of the saved page. |
| std::pair<SavePageResult, int64_t> SavePage(const GURL& url, |
| ClientId client_id); |
| |
| void SavePageWithArchiverResult(const GURL& url, |
| ClientId client_id, |
| OfflinePageArchiver::ArchiverResult result); |
| |
| void DeletePage(int64_t offline_id, const DeletePageCallback& callback) { |
| std::vector<int64_t> offline_ids; |
| offline_ids.push_back(offline_id); |
| model()->DeletePagesByOfflineId(offline_ids, callback); |
| } |
| |
| bool HasPages(std::string name_space); |
| |
| CheckPagesExistOfflineResult CheckPagesExistOffline(std::set<GURL>); |
| |
| MultipleOfflineIdResult GetOfflineIdsForClientId(const ClientId& client_id); |
| |
| const OfflinePageItem* GetPageByOfflineId(int64_t offline_id); |
| |
| MultipleOfflinePageItemResult GetPagesByOnlineURL(const GURL& offline_url); |
| |
| const OfflinePageItem* GetPageByOfflineURL(const GURL& offline_url); |
| |
| OfflinePageModelImpl* model() { return model_.get(); } |
| |
| int64_t last_save_offline_id() const { return last_save_offline_id_; } |
| |
| SavePageResult last_save_result() const { return last_save_result_; } |
| |
| DeletePageResult last_delete_result() const { return last_delete_result_; } |
| |
| int64_t last_deleted_offline_id() const { return last_deleted_offline_id_; } |
| |
| ClientId last_deleted_client_id() const { return last_deleted_client_id_; } |
| |
| const base::FilePath& last_archiver_path() { return last_archiver_path_; } |
| |
| int last_cleared_pages_count() const { return last_cleared_pages_count_; } |
| |
| DeletePageResult last_clear_page_result() const { |
| return last_clear_page_result_; |
| } |
| |
| bool last_expire_page_result() const { return last_expire_page_result_; } |
| |
| const base::HistogramTester& histograms() const { return histogram_tester_; } |
| |
| private: |
| scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; |
| base::ThreadTaskRunnerHandle task_runner_handle_; |
| base::ScopedTempDir temp_dir_; |
| |
| std::unique_ptr<OfflinePageModelImpl> model_; |
| SavePageResult last_save_result_; |
| int64_t last_save_offline_id_; |
| DeletePageResult last_delete_result_; |
| base::FilePath last_archiver_path_; |
| int64_t last_deleted_offline_id_; |
| ClientId last_deleted_client_id_; |
| CheckPagesExistOfflineResult last_pages_exist_result_; |
| int last_cleared_pages_count_; |
| DeletePageResult last_clear_page_result_; |
| bool last_expire_page_result_; |
| |
| base::HistogramTester histogram_tester_; |
| }; |
| |
| OfflinePageModelImplTest::OfflinePageModelImplTest() |
| : task_runner_(new base::TestMockTimeTaskRunner), |
| task_runner_handle_(task_runner_), |
| last_save_result_(SavePageResult::CANCELLED), |
| last_save_offline_id_(-1), |
| last_delete_result_(DeletePageResult::CANCELLED), |
| last_deleted_offline_id_(-1) {} |
| |
| OfflinePageModelImplTest::~OfflinePageModelImplTest() {} |
| |
| void OfflinePageModelImplTest::SetUp() { |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| model_ = BuildModel(BuildStore()); |
| model_->AddObserver(this); |
| PumpLoop(); |
| } |
| |
| void OfflinePageModelImplTest::TearDown() { |
| model_->RemoveObserver(this); |
| model_.reset(); |
| PumpLoop(); |
| } |
| |
| void OfflinePageModelImplTest::OfflinePageModelLoaded(OfflinePageModel* model) { |
| ASSERT_EQ(model_.get(), model); |
| } |
| |
| void OfflinePageModelImplTest::OfflinePageModelChanged( |
| OfflinePageModel* model) { |
| ASSERT_EQ(model_.get(), model); |
| } |
| |
| void OfflinePageModelImplTest::OfflinePageDeleted(int64_t offline_id, |
| const ClientId& client_id) { |
| last_deleted_offline_id_ = offline_id; |
| last_deleted_client_id_ = client_id; |
| } |
| |
| void OfflinePageModelImplTest::SetLastPathCreatedByArchiver( |
| const base::FilePath& file_path) { |
| last_archiver_path_ = file_path; |
| } |
| |
| void OfflinePageModelImplTest::OnSavePageDone(SavePageResult result, |
| int64_t offline_id) { |
| last_save_result_ = result; |
| last_save_offline_id_ = offline_id; |
| } |
| |
| void OfflinePageModelImplTest::OnDeletePageDone(DeletePageResult result) { |
| last_delete_result_ = result; |
| } |
| |
| void OfflinePageModelImplTest::OnCheckPagesExistOfflineDone( |
| const CheckPagesExistOfflineResult& result) { |
| last_pages_exist_result_ = result; |
| } |
| |
| void OfflinePageModelImplTest::OnStoreUpdateDone(bool /* success - ignored */) { |
| } |
| |
| std::unique_ptr<OfflinePageTestArchiver> |
| OfflinePageModelImplTest::BuildArchiver( |
| const GURL& url, |
| OfflinePageArchiver::ArchiverResult result) { |
| return std::unique_ptr<OfflinePageTestArchiver>( |
| new OfflinePageTestArchiver(this, url, result, kTestTitle, kTestFileSize, |
| base::ThreadTaskRunnerHandle::Get())); |
| } |
| |
| std::unique_ptr<OfflinePageMetadataStore> |
| OfflinePageModelImplTest::BuildStore() { |
| return std::unique_ptr<OfflinePageMetadataStore>( |
| new OfflinePageTestStore(base::ThreadTaskRunnerHandle::Get())); |
| } |
| |
| std::unique_ptr<OfflinePageModelImpl> OfflinePageModelImplTest::BuildModel( |
| std::unique_ptr<OfflinePageMetadataStore> store) { |
| return std::unique_ptr<OfflinePageModelImpl>( |
| new OfflinePageModelImpl(std::move(store), temp_dir_.GetPath(), |
| base::ThreadTaskRunnerHandle::Get())); |
| } |
| |
| void OfflinePageModelImplTest::ResetModel() { |
| model_->RemoveObserver(this); |
| OfflinePageTestStore* old_store = GetStore(); |
| std::unique_ptr<OfflinePageMetadataStore> new_store( |
| new OfflinePageTestStore(*old_store)); |
| model_ = BuildModel(std::move(new_store)); |
| model_->AddObserver(this); |
| PumpLoop(); |
| } |
| |
| void OfflinePageModelImplTest::PumpLoop() { |
| task_runner_->RunUntilIdle(); |
| } |
| |
| void OfflinePageModelImplTest::FastForwardBy(base::TimeDelta delta) { |
| task_runner_->FastForwardBy(delta); |
| } |
| |
| void OfflinePageModelImplTest::ResetResults() { |
| last_save_result_ = SavePageResult::CANCELLED; |
| last_delete_result_ = DeletePageResult::CANCELLED; |
| last_archiver_path_.clear(); |
| last_pages_exist_result_.clear(); |
| last_cleared_pages_count_ = 0; |
| } |
| |
| OfflinePageTestStore* OfflinePageModelImplTest::GetStore() { |
| return static_cast<OfflinePageTestStore*>(model()->GetStoreForTesting()); |
| } |
| |
| std::pair<SavePageResult, int64_t> OfflinePageModelImplTest::SavePage( |
| const GURL& url, |
| ClientId client_id) { |
| SavePageWithArchiverResult( |
| url, client_id, |
| OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED); |
| return std::make_pair(last_save_result_, last_save_offline_id_); |
| } |
| |
| void OfflinePageModelImplTest::SavePageWithArchiverResult( |
| const GURL& url, |
| ClientId client_id, |
| OfflinePageArchiver::ArchiverResult result) { |
| std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(url, result)); |
| model()->SavePage( |
| url, client_id, 0l, std::move(archiver), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| } |
| |
| MultipleOfflinePageItemResult OfflinePageModelImplTest::GetAllPages() { |
| MultipleOfflinePageItemResult result; |
| model()->GetAllPages( |
| base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult, |
| AsWeakPtr(), base::Unretained(&result))); |
| PumpLoop(); |
| return result; |
| } |
| |
| CheckPagesExistOfflineResult OfflinePageModelImplTest::CheckPagesExistOffline( |
| std::set<GURL> pages) { |
| model()->CheckPagesExistOffline( |
| pages, base::Bind(&OfflinePageModelImplTest::OnCheckPagesExistOfflineDone, |
| AsWeakPtr())); |
| PumpLoop(); |
| return last_pages_exist_result_; |
| } |
| |
| MultipleOfflineIdResult OfflinePageModelImplTest::GetOfflineIdsForClientId( |
| const ClientId& client_id) { |
| MultipleOfflineIdResult result; |
| model()->GetOfflineIdsForClientId( |
| client_id, |
| base::Bind(&OfflinePageModelImplTest::OnGetOfflineIdsForClientIdDone, |
| AsWeakPtr(), base::Unretained(&result))); |
| PumpLoop(); |
| return result; |
| } |
| |
| void OfflinePageModelImplTest::OnGetOfflineIdsForClientIdDone( |
| MultipleOfflineIdResult* storage, |
| const MultipleOfflineIdResult& result) { |
| *storage = result; |
| } |
| |
| const OfflinePageItem* OfflinePageModelImplTest::GetPageByOfflineId( |
| int64_t offline_id) { |
| const OfflinePageItem* result = nullptr; |
| model()->GetPageByOfflineId( |
| offline_id, |
| base::Bind(&OfflinePageModelImplTest::OnGetSingleOfflinePageItemResult, |
| AsWeakPtr(), base::Unretained(&result))); |
| PumpLoop(); |
| return result; |
| } |
| |
| const OfflinePageItem* OfflinePageModelImplTest::GetPageByOfflineURL( |
| const GURL& offline_url) { |
| const OfflinePageItem* result = nullptr; |
| model()->GetPageByOfflineURL( |
| offline_url, |
| base::Bind(&OfflinePageModelImplTest::OnGetSingleOfflinePageItemResult, |
| AsWeakPtr(), base::Unretained(&result))); |
| PumpLoop(); |
| return result; |
| } |
| |
| void OfflinePageModelImplTest::OnGetSingleOfflinePageItemResult( |
| const OfflinePageItem** storage, |
| const OfflinePageItem* result) { |
| *storage = result; |
| } |
| |
| void OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult( |
| MultipleOfflinePageItemResult* storage, |
| const MultipleOfflinePageItemResult& result) { |
| *storage = result; |
| } |
| |
| void OfflinePageModelImplTest::OnPagesExpired(bool result) { |
| last_expire_page_result_ = result; |
| } |
| |
| MultipleOfflinePageItemResult OfflinePageModelImplTest::GetPagesByOnlineURL( |
| const GURL& online_url) { |
| MultipleOfflinePageItemResult result; |
| model()->GetPagesByOnlineURL( |
| online_url, |
| base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult, |
| AsWeakPtr(), base::Unretained(&result))); |
| PumpLoop(); |
| return result; |
| } |
| |
| bool OfflinePageModelImplTest::HasPages(std::string name_space) { |
| MultipleOfflinePageItemResult all_pages = GetAllPages(); |
| for (const auto& page : all_pages) { |
| if (page.client_id.name_space == name_space) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageSuccessful) { |
| EXPECT_FALSE(HasPages(kTestClientNamespace)); |
| SavePage(kTestUrl, kTestClientId1); |
| EXPECT_TRUE(HasPages(kTestClientNamespace)); |
| |
| OfflinePageTestStore* store = GetStore(); |
| EXPECT_EQ(kTestUrl, store->last_saved_page().url); |
| EXPECT_EQ(kTestClientId1.id, store->last_saved_page().client_id.id); |
| EXPECT_EQ(kTestClientId1.name_space, |
| store->last_saved_page().client_id.name_space); |
| // Save last_archiver_path since it will be referred to later. |
| base::FilePath archiver_path = last_archiver_path(); |
| EXPECT_EQ(archiver_path, store->last_saved_page().file_path); |
| EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| ResetResults(); |
| |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| |
| EXPECT_EQ(1UL, offline_pages.size()); |
| EXPECT_EQ(kTestUrl, offline_pages[0].url); |
| EXPECT_EQ(kTestClientId1.id, offline_pages[0].client_id.id); |
| EXPECT_EQ(kTestClientId1.name_space, offline_pages[0].client_id.name_space); |
| EXPECT_EQ(archiver_path, offline_pages[0].file_path); |
| EXPECT_EQ(kTestFileSize, offline_pages[0].file_size); |
| EXPECT_EQ(0, offline_pages[0].access_count); |
| EXPECT_EQ(0, offline_pages[0].flags); |
| EXPECT_EQ(kTestTitle, offline_pages[0].title); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverCancelled) { |
| SavePageWithArchiverResult( |
| kTestUrl, kTestClientId1, |
| OfflinePageArchiver::ArchiverResult::ERROR_CANCELED); |
| EXPECT_EQ(SavePageResult::CANCELLED, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverDeviceFull) { |
| SavePageWithArchiverResult( |
| kTestUrl, kTestClientId1, |
| OfflinePageArchiver::ArchiverResult::ERROR_DEVICE_FULL); |
| EXPECT_EQ(SavePageResult::DEVICE_FULL, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverContentUnavailable) { |
| SavePageWithArchiverResult( |
| kTestUrl, kTestClientId1, |
| OfflinePageArchiver::ArchiverResult::ERROR_CONTENT_UNAVAILABLE); |
| EXPECT_EQ(SavePageResult::CONTENT_UNAVAILABLE, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineCreationFailed) { |
| SavePageWithArchiverResult( |
| kTestUrl, kTestClientId1, |
| OfflinePageArchiver::ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED); |
| EXPECT_EQ(SavePageResult::ARCHIVE_CREATION_FAILED, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverReturnedWrongUrl) { |
| std::unique_ptr<OfflinePageTestArchiver> archiver( |
| BuildArchiver(GURL("http://other.random.url.com"), |
| OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)); |
| model()->SavePage( |
| kTestUrl, kTestClientId1, 0l, std::move(archiver), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| EXPECT_EQ(SavePageResult::ARCHIVE_CREATION_FAILED, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineCreationStoreWriteFailure) { |
| GetStore()->set_test_scenario( |
| OfflinePageTestStore::TestScenario::WRITE_FAILED); |
| SavePage(kTestUrl, kTestClientId1); |
| EXPECT_EQ(SavePageResult::STORE_FAILURE, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageLocalFileFailed) { |
| // Don't create archiver since it will not be needed for pages that are not |
| // going to be saved. |
| model()->SavePage( |
| kFileUrl, kTestClientId1, 0l, std::unique_ptr<OfflinePageTestArchiver>(), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| EXPECT_EQ(SavePageResult::SKIPPED, last_save_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverTwoPages) { |
| std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver( |
| kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)); |
| // archiver_ptr will be valid until after first PumpLoop() call after |
| // CompleteCreateArchive() is called. |
| OfflinePageTestArchiver* archiver_ptr = archiver.get(); |
| archiver_ptr->set_delayed(true); |
| model()->SavePage( |
| kTestUrl, kTestClientId1, 0l, std::move(archiver), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| EXPECT_TRUE(archiver_ptr->create_archive_called()); |
| |
| // Request to save another page. |
| SavePage(kTestUrl2, kTestClientId2); |
| |
| OfflinePageTestStore* store = GetStore(); |
| |
| EXPECT_EQ(kTestUrl2, store->last_saved_page().url); |
| EXPECT_EQ(kTestClientId2, store->last_saved_page().client_id); |
| base::FilePath archiver_path2 = last_archiver_path(); |
| EXPECT_EQ(archiver_path2, store->last_saved_page().file_path); |
| EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| |
| ResetResults(); |
| |
| archiver_ptr->CompleteCreateArchive(); |
| // After this pump loop archiver_ptr is invalid. |
| PumpLoop(); |
| |
| EXPECT_EQ(kTestUrl, store->last_saved_page().url); |
| EXPECT_EQ(kTestClientId1, store->last_saved_page().client_id); |
| base::FilePath archiver_path = last_archiver_path(); |
| EXPECT_EQ(archiver_path, store->last_saved_page().file_path); |
| EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| |
| ResetResults(); |
| |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| |
| EXPECT_EQ(2UL, offline_pages.size()); |
| // Offline IDs are random, so the order of the pages is also random |
| // So load in the right page for the validation below. |
| const OfflinePageItem* page1 = nullptr; |
| const OfflinePageItem* page2 = nullptr; |
| if (offline_pages[0].client_id == kTestClientId1) { |
| page1 = &offline_pages[0]; |
| page2 = &offline_pages[1]; |
| } else { |
| page1 = &offline_pages[1]; |
| page2 = &offline_pages[0]; |
| } |
| |
| EXPECT_EQ(kTestUrl, page1->url); |
| EXPECT_EQ(kTestClientId1, page1->client_id); |
| EXPECT_EQ(archiver_path, page1->file_path); |
| EXPECT_EQ(kTestFileSize, page1->file_size); |
| EXPECT_EQ(0, page1->access_count); |
| EXPECT_EQ(0, page1->flags); |
| EXPECT_EQ(kTestUrl2, page2->url); |
| EXPECT_EQ(kTestClientId2, page2->client_id); |
| EXPECT_EQ(archiver_path2, page2->file_path); |
| EXPECT_EQ(kTestFileSize, page2->file_size); |
| EXPECT_EQ(0, page2->access_count); |
| EXPECT_EQ(0, page2->flags); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, MarkPageAccessed) { |
| SavePage(kTestUrl, kTestClientId1); |
| |
| // This will increase access_count by one. |
| model()->MarkPageAccessed(last_save_offline_id()); |
| PumpLoop(); |
| |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| |
| EXPECT_EQ(1UL, offline_pages.size()); |
| EXPECT_EQ(kTestUrl, offline_pages[0].url); |
| EXPECT_EQ(kTestClientId1, offline_pages[0].client_id); |
| EXPECT_EQ(kTestFileSize, offline_pages[0].file_size); |
| EXPECT_EQ(1, offline_pages[0].access_count); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetAllPagesStoreEmpty) { |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| |
| EXPECT_EQ(0UL, offline_pages.size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetAllPagesStoreFailure) { |
| GetStore()->set_test_scenario( |
| OfflinePageTestStore::TestScenario::LOAD_FAILED); |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| |
| EXPECT_EQ(0UL, offline_pages.size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeletePageSuccessful) { |
| OfflinePageTestStore* store = GetStore(); |
| |
| // Save one page. |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(1u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Save another page. |
| SavePage(kTestUrl2, kTestClientId2); |
| int64_t offline2 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(2u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Delete one page. |
| DeletePage(offline1, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| |
| PumpLoop(); |
| |
| EXPECT_EQ(last_deleted_offline_id(), offline1); |
| EXPECT_EQ(last_deleted_client_id(), kTestClientId1); |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| ASSERT_EQ(1u, store->GetAllPages().size()); |
| EXPECT_EQ(kTestUrl2, store->GetAllPages()[0].url); |
| |
| // Delete another page. |
| DeletePage(offline2, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| |
| ResetResults(); |
| |
| PumpLoop(); |
| |
| EXPECT_EQ(last_deleted_offline_id(), offline2); |
| EXPECT_EQ(last_deleted_client_id(), kTestClientId2); |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| EXPECT_EQ(0u, store->GetAllPages().size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeleteCachedPageByPredicateUserRequested) { |
| OfflinePageTestStore* store = GetStore(); |
| |
| // Save one page. |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(1u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Save an user-requested page in same domain. |
| SavePage(kTestUrl, kTestUserRequestedClientId); |
| int64_t offline2 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(2u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Delete the second page. |
| model()->DeleteCachedPagesByURLPredicate( |
| base::Bind(&URLSpecContains, "example.com"), |
| base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr())); |
| |
| PumpLoop(); |
| |
| EXPECT_EQ(last_deleted_offline_id(), offline1); |
| EXPECT_EQ(last_deleted_client_id(), kTestClientId1); |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| ASSERT_EQ(1u, store->GetAllPages().size()); |
| EXPECT_EQ(kTestUrl, store->GetAllPages()[0].url); |
| EXPECT_EQ(offline2, store->GetAllPages()[0].offline_id); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeleteCachedPageByPredicate) { |
| OfflinePageTestStore* store = GetStore(); |
| |
| // Save one page. |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(1u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Save another page. |
| SavePage(kTestUrl2, kTestClientId2); |
| int64_t offline2 = last_save_offline_id(); |
| EXPECT_EQ(SavePageResult::SUCCESS, last_save_result()); |
| EXPECT_EQ(2u, store->GetAllPages().size()); |
| |
| ResetResults(); |
| |
| // Delete the second page. |
| model()->DeleteCachedPagesByURLPredicate( |
| base::Bind(&URLSpecContains, "page.com"), |
| base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr())); |
| |
| PumpLoop(); |
| |
| EXPECT_EQ(last_deleted_offline_id(), offline2); |
| EXPECT_EQ(last_deleted_client_id(), kTestClientId2); |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| ASSERT_EQ(1u, store->GetAllPages().size()); |
| EXPECT_EQ(kTestUrl, store->GetAllPages()[0].url); |
| |
| ResetResults(); |
| |
| // Delete the first page. |
| model()->DeleteCachedPagesByURLPredicate( |
| base::Bind(&URLSpecContains, "example.com"), |
| base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr())); |
| |
| PumpLoop(); |
| |
| EXPECT_EQ(last_deleted_offline_id(), offline1); |
| EXPECT_EQ(last_deleted_client_id(), kTestClientId1); |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| EXPECT_EQ(0u, store->GetAllPages().size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeletePageNotFound) { |
| DeletePage(1234LL, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| PumpLoop(); |
| |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| |
| ResetResults(); |
| |
| model()->DeleteCachedPagesByURLPredicate( |
| base::Bind(&URLSpecContains, "page.com"), |
| base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr())); |
| PumpLoop(); |
| |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeletePageStoreFailureOnRemove) { |
| // Save a page. |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline_id = last_save_offline_id(); |
| ResetResults(); |
| |
| // Try to delete this page. |
| GetStore()->set_test_scenario( |
| OfflinePageTestStore::TestScenario::REMOVE_FAILED); |
| DeletePage(offline_id, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| PumpLoop(); |
| EXPECT_EQ(DeletePageResult::STORE_FAILURE, last_delete_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DetectThatOfflineCopyIsMissing) { |
| // Save a page. |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline_id = last_save_offline_id(); |
| |
| ResetResults(); |
| |
| const OfflinePageItem* page = GetPageByOfflineId(offline_id); |
| |
| // Delete the offline copy of the page. |
| base::DeleteFile(page->file_path, false); |
| |
| // Resetting the model will cause a consistency check. |
| ResetModel(); |
| |
| PumpLoop(); |
| |
| // Check if the page has been expired. |
| EXPECT_EQ(0UL, GetAllPages().size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DetectThatOfflineCopyIsMissingAfterLoad) { |
| // Save a page. |
| SavePage(kTestUrl, kTestClientId1); |
| PumpLoop(); |
| int64_t offline_id = last_save_offline_id(); |
| |
| ResetResults(); |
| |
| const OfflinePageItem* page = GetPageByOfflineId(offline_id); |
| // Delete the offline copy of the page and check the metadata. |
| base::DeleteFile(page->file_path, false); |
| // Reseting the model should trigger the metadata consistency check as well. |
| ResetModel(); |
| PumpLoop(); |
| |
| // Check if the page has been expired. |
| EXPECT_EQ(0UL, GetAllPages().size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DetectThatHeadlessPageIsDeleted) { |
| // Save a page. |
| SavePage(kTestUrl, kTestClientId1); |
| PumpLoop(); |
| int64_t offline_id = last_save_offline_id(); |
| |
| ResetResults(); |
| const OfflinePageItem* page = GetPageByOfflineId(offline_id); |
| base::FilePath path = page->file_path; |
| EXPECT_TRUE(base::PathExists(path)); |
| GetStore()->ClearAllPages(); |
| |
| EXPECT_TRUE(base::PathExists(path)); |
| // Since we've manually changed the store, we have to reload the model to |
| // actually refresh the in-memory copy in model. Otherwise GetAllPages() would |
| // still have the page we saved above. |
| ResetModel(); |
| PumpLoop(); |
| |
| EXPECT_EQ(0UL, GetAllPages().size()); |
| EXPECT_FALSE(base::PathExists(path)); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DeleteMultiplePages) { |
| OfflinePageTestStore* store = GetStore(); |
| |
| // Save 3 pages. |
| std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver( |
| kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)); |
| model()->SavePage( |
| kTestUrl, kTestClientId1, 0l, std::move(archiver), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| int64_t offline1 = last_save_offline_id(); |
| |
| std::unique_ptr<OfflinePageTestArchiver> archiver2(BuildArchiver( |
| kTestUrl2, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)); |
| model()->SavePage( |
| kTestUrl2, kTestClientId2, 0l, std::move(archiver2), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| int64_t offline2 = last_save_offline_id(); |
| |
| std::unique_ptr<OfflinePageTestArchiver> archiver3(BuildArchiver( |
| kTestUrl3, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)); |
| model()->SavePage( |
| kTestUrl3, kTestClientId3, 0l, std::move(archiver3), |
| base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr())); |
| PumpLoop(); |
| |
| EXPECT_EQ(3u, store->GetAllPages().size()); |
| |
| // Delete multiple pages. |
| std::vector<int64_t> ids_to_delete; |
| ids_to_delete.push_back(offline2); |
| ids_to_delete.push_back(offline1); |
| ids_to_delete.push_back(23434LL); // Non-existent ID. |
| model()->DeletePagesByOfflineId( |
| ids_to_delete, |
| base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr())); |
| PumpLoop(); |
| |
| // Success is expected if at least one page is deleted successfully. |
| EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); |
| EXPECT_EQ(1u, store->GetAllPages().size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetPageByOfflineId) { |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| SavePage(kTestUrl2, kTestClientId2); |
| int64_t offline2 = last_save_offline_id(); |
| |
| const OfflinePageItem* page = GetPageByOfflineId(offline1); |
| EXPECT_TRUE(page); |
| EXPECT_EQ(kTestUrl, page->url); |
| EXPECT_EQ(kTestClientId1, page->client_id); |
| EXPECT_EQ(kTestFileSize, page->file_size); |
| |
| page = GetPageByOfflineId(offline2); |
| EXPECT_TRUE(page); |
| EXPECT_EQ(kTestUrl2, page->url); |
| EXPECT_EQ(kTestClientId2, page->client_id); |
| EXPECT_EQ(kTestFileSize, page->file_size); |
| |
| page = GetPageByOfflineId(-42); |
| EXPECT_FALSE(page); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetPageByOfflineURL) { |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| |
| OfflinePageTestStore* store = GetStore(); |
| GURL offline_url = store->last_saved_page().GetOfflineURL(); |
| |
| SavePage(kTestUrl2, kTestClientId2); |
| |
| GURL offline_url2 = store->last_saved_page().GetOfflineURL(); |
| int64_t offline2 = last_save_offline_id(); |
| |
| const OfflinePageItem* page = GetPageByOfflineURL(offline_url2); |
| EXPECT_TRUE(page); |
| EXPECT_EQ(kTestUrl2, page->url); |
| EXPECT_EQ(kTestClientId2, page->client_id); |
| EXPECT_EQ(offline2, page->offline_id); |
| |
| page = GetPageByOfflineURL(offline_url); |
| EXPECT_TRUE(page); |
| EXPECT_EQ(kTestUrl, page->url); |
| EXPECT_EQ(kTestClientId1, page->client_id); |
| EXPECT_EQ(offline1, page->offline_id); |
| |
| page = GetPageByOfflineURL(GURL("http://foo")); |
| EXPECT_FALSE(page); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetPagesByOnlineURL) { |
| SavePage(kTestUrl, kTestClientId1); |
| SavePage(kTestUrl2, kTestClientId2); |
| |
| MultipleOfflinePageItemResult pages = GetPagesByOnlineURL(kTestUrl2); |
| EXPECT_EQ(1U, pages.size()); |
| EXPECT_EQ(kTestUrl2, pages[0].url); |
| EXPECT_EQ(kTestClientId2, pages[0].client_id); |
| |
| pages = GetPagesByOnlineURL(kTestUrl); |
| EXPECT_EQ(1U, pages.size()); |
| EXPECT_EQ(kTestUrl, pages[0].url); |
| EXPECT_EQ(kTestClientId1, pages[0].client_id); |
| |
| pages = GetPagesByOnlineURL(GURL("http://foo")); |
| EXPECT_EQ(0U, pages.size()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, CheckPagesExistOffline) { |
| SavePage(kTestUrl, kTestClientId1); |
| SavePage(kTestUrl2, kTestClientId2); |
| |
| // TODO(dewittj): Remove the "Last N" restriction in favor of a better query |
| // interface. See https://crbug.com/622763 for information. |
| const ClientId last_n_client_id(kLastNNamespace, "1234"); |
| SavePage(kTestUrl3, last_n_client_id); |
| |
| std::set<GURL> input; |
| input.insert(kTestUrl); |
| input.insert(kTestUrl2); |
| input.insert(kTestUrl3); |
| input.insert(kTestUrl4); |
| |
| CheckPagesExistOfflineResult existing_pages = CheckPagesExistOffline(input); |
| EXPECT_EQ(2U, existing_pages.size()); |
| EXPECT_NE(existing_pages.end(), existing_pages.find(kTestUrl)); |
| EXPECT_NE(existing_pages.end(), existing_pages.find(kTestUrl2)); |
| EXPECT_EQ(existing_pages.end(), existing_pages.find(kTestUrl3)); |
| EXPECT_EQ(existing_pages.end(), existing_pages.find(kTestUrl4)); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, CanSaveURL) { |
| EXPECT_TRUE(OfflinePageModel::CanSaveURL(GURL("http://foo"))); |
| EXPECT_TRUE(OfflinePageModel::CanSaveURL(GURL("https://foo"))); |
| EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("file:///foo"))); |
| EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("data:image/png;base64,ab"))); |
| EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("chrome://version"))); |
| EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("chrome-native://newtab/"))); |
| EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("/invalid/url.mhtml"))); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SaveRetrieveMultipleClientIds) { |
| EXPECT_FALSE(HasPages(kTestClientNamespace)); |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| EXPECT_TRUE(HasPages(kTestClientNamespace)); |
| |
| SavePage(kTestUrl2, kTestClientId1); |
| int64_t offline2 = last_save_offline_id(); |
| |
| EXPECT_NE(offline1, offline2); |
| |
| const std::vector<int64_t> ids = GetOfflineIdsForClientId(kTestClientId1); |
| |
| EXPECT_EQ(2UL, ids.size()); |
| |
| std::set<int64_t> id_set; |
| for (size_t i = 0; i < ids.size(); i++) { |
| id_set.insert(ids[i]); |
| } |
| |
| EXPECT_TRUE(id_set.find(offline1) != id_set.end()); |
| EXPECT_TRUE(id_set.find(offline2) != id_set.end()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, SaveMultiplePagesWithSameURLBySameClientId) { |
| EXPECT_FALSE(HasPages(kTestClientNamespace)); |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline1 = last_save_offline_id(); |
| EXPECT_TRUE(HasPages(kTestClientNamespace)); |
| |
| SavePage(kTestUrl, kTestClientId1); |
| int64_t offline2 = last_save_offline_id(); |
| |
| EXPECT_NE(offline1, offline2); |
| |
| const std::vector<int64_t> ids = GetOfflineIdsForClientId(kTestClientId1); |
| |
| EXPECT_EQ(1UL, ids.size()); |
| |
| std::set<int64_t> id_set; |
| for (size_t i = 0; i < ids.size(); i++) { |
| id_set.insert(ids[i]); |
| } |
| |
| EXPECT_TRUE(id_set.find(offline2) != id_set.end()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DownloadMetrics) { |
| EXPECT_FALSE(HasPages(kUserRequestedNamespace)); |
| SavePage(kTestUrl, kTestUserRequestedClientId); |
| histograms().ExpectUniqueSample( |
| "OfflinePages.DownloadSavedPageDuplicateCount", 1, 1); |
| FastForwardBy(base::TimeDelta::FromMinutes(1)); |
| histograms().ExpectTotalCount( |
| "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved", 0); |
| SavePage(kTestUrl, kTestUserRequestedClientId); |
| histograms().ExpectTotalCount("OfflinePages.DownloadSavedPageDuplicateCount", |
| 2); |
| histograms().ExpectBucketCount("OfflinePages.DownloadSavedPageDuplicateCount", |
| 2, 1); |
| histograms().ExpectBucketCount("OfflinePages.DownloadSavedPageDuplicateCount", |
| 1, 1); |
| histograms().ExpectTotalCount( |
| "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved", 1); |
| histograms().ExpectTotalCount( |
| "OfflinePages.DownloadDeletedPageDuplicateCount", 0); |
| |
| // void DeletePage(int64_t offline_id, const DeletePageCallback& callback) { |
| const std::vector<int64_t> ids = |
| GetOfflineIdsForClientId(kTestUserRequestedClientId); |
| ASSERT_EQ(2U, ids.size()); |
| |
| DeletePage(ids[0], base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| PumpLoop(); |
| histograms().ExpectUniqueSample( |
| "OfflinePages.DownloadDeletedPageDuplicateCount", 2, 1); |
| DeletePage(ids[1], base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, |
| AsWeakPtr())); |
| PumpLoop(); |
| // No change when we delete the last page. |
| histograms().ExpectTotalCount( |
| "OfflinePages.DownloadDeletedPageDuplicateCount", 2); |
| histograms().ExpectBucketCount( |
| "OfflinePages.DownloadDeletedPageDuplicateCount", 1, 1); |
| histograms().ExpectBucketCount( |
| "OfflinePages.DownloadDeletedPageDuplicateCount", 2, 1); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, GetBestPage) { |
| // We will save 3 pages - two for the same URL, and one for a different URL. |
| // Correct behavior will pick the most recently saved page for the correct |
| // URL. |
| std::pair<SavePageResult, int64_t> saved_pages[3]; |
| saved_pages[0] = SavePage(kTestUrl, kTestClientId1); |
| saved_pages[1] = SavePage(kTestUrl, kTestClientId1); |
| saved_pages[2] = SavePage(kTestUrl2, kTestClientId2); |
| |
| for (const auto& save_result : saved_pages) { |
| ASSERT_EQ(OfflinePageModel::SavePageResult::SUCCESS, |
| std::get<0>(save_result)); |
| } |
| |
| const OfflinePageItem* offline_page = |
| model()->MaybeGetBestPageForOnlineURL(kTestUrl); |
| ASSERT_TRUE(nullptr != offline_page); |
| |
| EXPECT_EQ(std::get<1>(saved_pages[1]), offline_page->offline_id); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, ExpirePages) { |
| // We will save 3 pages and then expire 2 of them. |
| std::pair<SavePageResult, int64_t> saved_pages[3]; |
| saved_pages[0] = SavePage(kTestUrl, kTestClientId1); |
| saved_pages[1] = SavePage(kTestUrl2, kTestClientId2); |
| saved_pages[2] = SavePage(kTestUrl3, kTestClientId3); |
| |
| for (const auto& save_result : saved_pages) { |
| ASSERT_EQ(OfflinePageModel::SavePageResult::SUCCESS, |
| std::get<0>(save_result)); |
| } |
| |
| // First two pages will be expired. |
| std::vector<int64_t> pages_to_expire = {std::get<1>(saved_pages[0]), |
| std::get<1>(saved_pages[1])}; |
| // Pages are marked as expired if they have an expiration_time set. |
| base::Time expiration_time = |
| base::Time::Now() + base::TimeDelta::FromMinutes(5); |
| |
| model()->ExpirePages( |
| pages_to_expire, expiration_time, |
| base::Bind(&OfflinePageModelImplTest::OnPagesExpired, AsWeakPtr())); |
| PumpLoop(); |
| |
| const std::vector<OfflinePageItem>& offline_pages = GetAllPages(); |
| for (const auto& offline_page : offline_pages) { |
| if (std::find(pages_to_expire.begin(), pages_to_expire.end(), |
| offline_page.offline_id) != pages_to_expire.end()) { |
| EXPECT_EQ(expiration_time, offline_page.expiration_time); |
| EXPECT_TRUE(offline_page.IsExpired()); |
| } else { |
| EXPECT_EQ(base::Time(), offline_page.expiration_time); |
| EXPECT_FALSE(offline_page.IsExpired()); |
| } |
| } |
| EXPECT_TRUE(last_expire_page_result()); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, CustomTabsNamespace) { |
| SavePage(kTestUrl, ClientId(kCCTNamespace, "123")); |
| std::string histogram_name = "OfflinePages.SavePageResult."; |
| histogram_name += kCCTNamespace; |
| |
| histograms().ExpectUniqueSample(histogram_name, |
| static_cast<int>(SavePageResult::SUCCESS), 1); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, DownloadNamespace) { |
| SavePage(kTestUrl, ClientId(kDownloadNamespace, "123")); |
| std::string histogram_name = "OfflinePages.SavePageResult."; |
| histogram_name += kDownloadNamespace; |
| |
| histograms().ExpectUniqueSample(histogram_name, |
| static_cast<int>(SavePageResult::SUCCESS), 1); |
| } |
| |
| TEST_F(OfflinePageModelImplTest, NewTabPageNamespace) { |
| SavePage(kTestUrl, ClientId(kNTPSuggestionsNamespace, "123")); |
| std::string histogram_name = "OfflinePages.SavePageResult."; |
| histogram_name += kNTPSuggestionsNamespace; |
| |
| histograms().ExpectUniqueSample(histogram_name, |
| static_cast<int>(SavePageResult::SUCCESS), 1); |
| } |
| |
| TEST(CommandLineFlagsTest, OfflineBookmarks) { |
| // Disabled by default. |
| EXPECT_FALSE(offline_pages::IsOfflineBookmarksEnabled()); |
| |
| // Check if feature is correctly enabled by command-line flag. |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitAndEnableFeature(kOfflineBookmarksFeature); |
| EXPECT_TRUE(offline_pages::IsOfflineBookmarksEnabled()); |
| } |
| |
| TEST(CommandLineFlagsTest, OffliningRecentPages) { |
| // Enable offline bookmarks feature first. |
| // TODO(dimich): once offline pages are enabled by default, remove this. |
| std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list( |
| new base::test::ScopedFeatureList); |
| scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature); |
| |
| // This feature is still disabled by default. |
| EXPECT_FALSE(offline_pages::IsOffliningRecentPagesEnabled()); |
| |
| // Check if feature is correctly enabled by command-line flag. |
| scoped_feature_list.reset(new base::test::ScopedFeatureList); |
| scoped_feature_list->InitFromCommandLine( |
| std::string(kOfflineBookmarksFeature.name) + "," + |
| kOffliningRecentPagesFeature.name, |
| ""); |
| EXPECT_TRUE(offline_pages::IsOffliningRecentPagesEnabled()); |
| } |
| |
| TEST(CommandLineFlagsTest, OfflinePagesBackgroundLoading) { |
| // Enable offline bookmarks feature first. |
| // TODO(dimich): once offline pages are enabled by default, remove this. |
| std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list( |
| new base::test::ScopedFeatureList); |
| scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature); |
| |
| // This feature is still disabled by default. |
| EXPECT_FALSE(offline_pages::IsOfflinePagesBackgroundLoadingEnabled()); |
| |
| // Check if feature is correctly enabled by command-line flag. |
| scoped_feature_list.reset(new base::test::ScopedFeatureList); |
| scoped_feature_list->InitFromCommandLine( |
| std::string(kOfflineBookmarksFeature.name) + "," + |
| kOfflinePagesBackgroundLoadingFeature.name, |
| ""); |
| EXPECT_TRUE(offline_pages::IsOfflinePagesBackgroundLoadingEnabled()); |
| } |
| |
| TEST(CommandLineFlagsTest, OfflinePagesSharing) { |
| // Enable offline bookmarks feature first. |
| // TODO(dimich): once offline pages are enabled by default, remove this. |
| std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list( |
| new base::test::ScopedFeatureList); |
| scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature); |
| |
| // This feature is still disabled by default. |
| EXPECT_FALSE(offline_pages::IsOfflinePagesSharingEnabled()); |
| |
| // Check if feature is correctly enabled by command-line flag. |
| scoped_feature_list.reset(new base::test::ScopedFeatureList); |
| scoped_feature_list->InitFromCommandLine( |
| std::string(kOfflineBookmarksFeature.name) + "," + |
| kOfflinePagesSharingFeature.name, |
| ""); |
| EXPECT_TRUE(offline_pages::IsOfflinePagesSharingEnabled()); |
| } |
| |
| } // namespace offline_pages |