Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(545)

Unified Diff: components/offline_pages/offline_page_model_impl.cc

Issue 2489443002: Move all components/offline_pages/ files into component/offline_pages/core (Closed)
Patch Set: more rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/offline_pages/offline_page_model_impl.cc
diff --git a/components/offline_pages/offline_page_model_impl.cc b/components/offline_pages/offline_page_model_impl.cc
deleted file mode 100644
index 627f7f8c48cf6c0ca42fdb91f640601ac4298a7e..0000000000000000000000000000000000000000
--- a/components/offline_pages/offline_page_model_impl.cc
+++ /dev/null
@@ -1,1153 +0,0 @@
-// Copyright 2016 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 <algorithm>
-#include <limits>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/clock.h"
-#include "base/time/time.h"
-#include "components/offline_pages/archive_manager.h"
-#include "components/offline_pages/client_namespace_constants.h"
-#include "components/offline_pages/client_policy_controller.h"
-#include "components/offline_pages/offline_page_item.h"
-#include "components/offline_pages/offline_page_model_query.h"
-#include "components/offline_pages/offline_page_storage_manager.h"
-#include "url/gurl.h"
-
-using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult;
-using ClearStorageCallback =
- offline_pages::OfflinePageStorageManager::ClearStorageCallback;
-using ClearStorageResult =
- offline_pages::OfflinePageStorageManager::ClearStorageResult;
-
-namespace offline_pages {
-
-namespace {
-
-// The delay used to schedule the first clear storage request for storage
-// manager after the model is loaded.
-const base::TimeDelta kStorageManagerStartingDelay =
- base::TimeDelta::FromSeconds(20);
-
-int64_t GenerateOfflineId() {
- return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1;
-}
-
-// The maximum histogram size for the metrics that measure time between views of
-// a given page.
-const base::TimeDelta kMaxOpenedPageHistogramBucket =
- base::TimeDelta::FromDays(90);
-
-SavePageResult ToSavePageResult(ArchiverResult archiver_result) {
- SavePageResult result;
- switch (archiver_result) {
- case ArchiverResult::SUCCESSFULLY_CREATED:
- result = SavePageResult::SUCCESS;
- break;
- case ArchiverResult::ERROR_DEVICE_FULL:
- result = SavePageResult::DEVICE_FULL;
- break;
- case ArchiverResult::ERROR_CONTENT_UNAVAILABLE:
- result = SavePageResult::CONTENT_UNAVAILABLE;
- break;
- case ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED:
- result = SavePageResult::ARCHIVE_CREATION_FAILED;
- break;
- case ArchiverResult::ERROR_CANCELED:
- result = SavePageResult::CANCELLED;
- break;
- case ArchiverResult::ERROR_SECURITY_CERTIFICATE:
- result = SavePageResult::SECURITY_CERTIFICATE_ERROR;
- break;
- default:
- NOTREACHED();
- result = SavePageResult::CONTENT_UNAVAILABLE;
- }
- return result;
-}
-
-std::string AddHistogramSuffix(const ClientId& client_id,
- const char* histogram_name) {
- if (client_id.name_space.empty()) {
- NOTREACHED();
- return histogram_name;
- }
- std::string adjusted_histogram_name(histogram_name);
- adjusted_histogram_name += ".";
- adjusted_histogram_name += client_id.name_space;
- return adjusted_histogram_name;
-}
-
-void ReportStorageHistogramsAfterSave(
- const ArchiveManager::StorageStats& storage_stats) {
- const int kMB = 1024 * 1024;
- int free_disk_space_mb =
- static_cast<int>(storage_stats.free_disk_space / kMB);
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.SavePage.FreeSpaceMB",
- free_disk_space_mb, 1, 500000, 50);
-
- int total_page_size_mb =
- static_cast<int>(storage_stats.total_archives_size / kMB);
- UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb);
-}
-
-void ReportStorageHistogramsAfterDelete(
- const ArchiveManager::StorageStats& storage_stats) {
- const int kMB = 1024 * 1024;
- int free_disk_space_mb =
- static_cast<int>(storage_stats.free_disk_space / kMB);
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DeletePage.FreeSpaceMB",
- free_disk_space_mb, 1, 500000, 50);
-
- int total_page_size_mb =
- static_cast<int>(storage_stats.total_archives_size / kMB);
- UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb);
-
- if (storage_stats.free_disk_space > 0) {
- int percentage_of_free = static_cast<int>(
- 1.0 * storage_stats.total_archives_size /
- (storage_stats.total_archives_size + storage_stats.free_disk_space) *
- 100);
- UMA_HISTOGRAM_PERCENTAGE(
- "OfflinePages.DeletePage.TotalPageSizeAsPercentageOfFreeSpace",
- percentage_of_free);
- }
-}
-
-void ReportSavePageResultHistogramAfterSave(const ClientId& client_id,
- SavePageResult result) {
- // The histogram below is an expansion of the UMA_HISTOGRAM_ENUMERATION
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.SavePageResult"),
- 1,
- static_cast<int>(SavePageResult::RESULT_COUNT),
- static_cast<int>(SavePageResult::RESULT_COUNT) + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(static_cast<int>(result));
-}
-
-// Goes through the list of offline pages, compiling the following two metrics:
-// - a count of the pages with the same URL
-// - The difference between the |created_before| time and the creation time of
-// the page with the closest creation time before |created_before|.
-// Returns true if there was a page that was saved before |created_before| with
-// a matching URL.
-bool GetMatchingURLCountAndMostRecentCreationTime(
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- std::string name_space,
- const GURL& url,
- base::Time created_before,
- int* matching_url_count,
- base::TimeDelta* most_recent_creation_time) {
- int count = 0;
-
- // Create a time that is very old, so that any valid time will be newer than
- // it.
- base::Time latest_time;
- bool matching_page = false;
-
- for (auto& id_page_pair : offline_pages) {
- if (id_page_pair.second.client_id.name_space == name_space &&
- url == id_page_pair.second.url) {
- count++;
- base::Time page_creation_time = id_page_pair.second.creation_time;
- if (page_creation_time < created_before &&
- page_creation_time > latest_time) {
- latest_time = page_creation_time;
- matching_page = true;
- }
- }
- }
-
- if (matching_url_count != nullptr)
- *matching_url_count = count;
- if (most_recent_creation_time != nullptr && latest_time != base::Time())
- *most_recent_creation_time = created_before - latest_time;
-
- return matching_page;
-}
-
-void ReportPageHistogramAfterSave(
- ClientPolicyController* policy_controller_,
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- const OfflinePageItem& offline_page,
- const base::Time& save_time) {
- DCHECK(policy_controller_);
- // The histogram below is an expansion of the UMA_HISTOGRAM_TIMES
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
- AddHistogramSuffix(offline_page.client_id, "OfflinePages.SavePageTime"),
- base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(10),
- 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->AddTime(save_time - offline_page.creation_time);
-
- // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- // Reported as Kb between 1Kb and 10Mb.
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(offline_page.client_id, "OfflinePages.PageSize"),
- 1, 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(offline_page.file_size / 1024);
-
- if (policy_controller_->IsSupportedByDownload(
- offline_page.client_id.name_space)) {
- int matching_url_count;
- base::TimeDelta time_since_most_recent_duplicate;
- if (GetMatchingURLCountAndMostRecentCreationTime(
- offline_pages, offline_page.client_id.name_space, offline_page.url,
- offline_page.creation_time, &matching_url_count,
- &time_since_most_recent_duplicate)) {
- // Using CUSTOM_COUNTS instead of time-oriented histogram to record
- // samples in seconds rather than milliseconds.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved",
- time_since_most_recent_duplicate.InSeconds(),
- base::TimeDelta::FromSeconds(1).InSeconds(),
- base::TimeDelta::FromDays(7).InSeconds(), 50);
- }
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DownloadSavedPageDuplicateCount",
- matching_url_count, 1, 20, 10);
- }
-}
-
-void ReportPageHistogramsAfterDelete(
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- const std::vector<OfflinePageItem>& deleted_pages,
- const base::Time& delete_time) {
- const int max_minutes = base::TimeDelta::FromDays(365).InMinutes();
- int64_t total_size = 0;
-
- for (const auto& page : deleted_pages) {
- total_size += page.file_size;
- ClientId client_id = page.client_id;
-
- if (client_id.name_space == kDownloadNamespace) {
- int remaining_pages_with_url;
- GetMatchingURLCountAndMostRecentCreationTime(
- offline_pages, page.client_id.name_space, page.url, base::Time::Max(),
- &remaining_pages_with_url, nullptr);
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "OfflinePages.DownloadDeletedPageDuplicateCount",
- remaining_pages_with_url, 1, 20, 10);
- }
-
- // The histograms below are an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.PageLifetime"),
- 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((delete_time - page.creation_time).InMinutes());
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(
- client_id, "OfflinePages.DeletePage.TimeSinceLastOpen"),
- 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((delete_time - page.last_access_time).InMinutes());
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(
- client_id, "OfflinePages.DeletePage.LastOpenToCreated"),
- 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((page.last_access_time - page.creation_time).InMinutes());
-
- // Reported as Kb between 1Kb and 10Mb.
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.DeletePage.PageSize"),
- 1, 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(page.file_size / 1024);
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.DeletePage.AccessCount"),
- 1, 1000000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(page.access_count);
- }
-
- if (deleted_pages.size() > 1) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count",
- static_cast<int32_t>(deleted_pages.size()));
- UMA_HISTOGRAM_MEMORY_KB(
- "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024);
- }
-}
-
-void ReportPageHistogramsAfterAccess(const OfflinePageItem& offline_page_item,
- const base::Time& access_time) {
- // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(
- offline_page_item.client_id,
- offline_page_item.access_count == 0 ?
- "OfflinePages.FirstOpenSinceCreated" :
- "OfflinePages.OpenSinceLastOpen"),
- 1, kMaxOpenedPageHistogramBucket.InMinutes(), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(
- (access_time - offline_page_item.last_access_time).InMinutes());
-}
-
-} // namespace
-
-// protected
-OfflinePageModelImpl::OfflinePageModelImpl()
- : OfflinePageModel(), is_loaded_(false), weak_ptr_factory_(this) {}
-
-OfflinePageModelImpl::OfflinePageModelImpl(
- std::unique_ptr<OfflinePageMetadataStore> store,
- const base::FilePath& archives_dir,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : store_(std::move(store)),
- archives_dir_(archives_dir),
- is_loaded_(false),
- policy_controller_(new ClientPolicyController()),
- archive_manager_(new ArchiveManager(archives_dir, task_runner)),
- testing_clock_(nullptr),
- weak_ptr_factory_(this) {
- archive_manager_->EnsureArchivesDirCreated(
- base::Bind(&OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone,
- weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()));
-}
-
-OfflinePageModelImpl::~OfflinePageModelImpl() {}
-
-void OfflinePageModelImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void OfflinePageModelImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void OfflinePageModelImpl::SavePage(
- const SavePageParams& save_page_params,
- std::unique_ptr<OfflinePageArchiver> archiver,
- const SavePageCallback& callback) {
- DCHECK(is_loaded_);
-
- // Skip saving the page that is not intended to be saved, like local file
- // page.
- if (!OfflinePageModel::CanSaveURL(save_page_params.url)) {
- InformSavePageDone(callback, SavePageResult::SKIPPED,
- save_page_params.client_id, kInvalidOfflineId);
- return;
- }
-
- // The web contents is not available if archiver is not created and passed.
- if (!archiver.get()) {
- InformSavePageDone(callback, SavePageResult::CONTENT_UNAVAILABLE,
- save_page_params.client_id, kInvalidOfflineId);
- return;
- }
-
- // If we already have an offline id, use it. If not, generate one.
- int64_t offline_id = save_page_params.proposed_offline_id;
- if (offline_id == kInvalidOfflineId)
- offline_id = GenerateOfflineId();
-
- archiver->CreateArchive(
- archives_dir_, offline_id,
- base::Bind(&OfflinePageModelImpl::OnCreateArchiveDone,
- weak_ptr_factory_.GetWeakPtr(), save_page_params, offline_id,
- GetCurrentTime(), callback));
- pending_archivers_.push_back(std::move(archiver));
-}
-
-void OfflinePageModelImpl::MarkPageAccessed(int64_t offline_id) {
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::MarkPageAccessedWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), offline_id));
-}
-
-void OfflinePageModelImpl::MarkPageAccessedWhenLoadDone(int64_t offline_id) {
- DCHECK(is_loaded_);
-
- auto iter = offline_pages_.find(offline_id);
- if (iter == offline_pages_.end() || iter->second.IsExpired())
- return;
-
- // Make a copy of the cached item and update it. The cached item should only
- // be updated upon the successful store operation.
- OfflinePageItem offline_page_item = iter->second;
-
- ReportPageHistogramsAfterAccess(offline_page_item, GetCurrentTime());
-
- offline_page_item.last_access_time = GetCurrentTime();
- offline_page_item.access_count++;
-
- std::vector<OfflinePageItem> items = { offline_page_item };
- store_->UpdateOfflinePages(
- items, base::Bind(&OfflinePageModelImpl::OnMarkPageAccesseDone,
- weak_ptr_factory_.GetWeakPtr(), offline_page_item));
-}
-
-void OfflinePageModelImpl::DeletePagesByOfflineId(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) {
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::DoDeletePagesByOfflineId,
- weak_ptr_factory_.GetWeakPtr(), offline_ids,
- callback));
-}
-
-void OfflinePageModelImpl::DoDeletePagesByOfflineId(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) {
- DCHECK(is_loaded_);
-
- std::vector<base::FilePath> paths_to_delete;
- for (const auto& offline_id : offline_ids) {
- auto iter = offline_pages_.find(offline_id);
- if (iter != offline_pages_.end() && !iter->second.IsExpired()) {
- paths_to_delete.push_back(iter->second.file_path);
- }
- }
-
- // If there're no pages to delete, return early.
- if (paths_to_delete.empty()) {
- InformDeletePageDone(callback, DeletePageResult::SUCCESS);
- return;
- }
-
- archive_manager_->DeleteMultipleArchives(
- paths_to_delete,
- base::Bind(&OfflinePageModelImpl::OnDeleteArchiveFilesDone,
- weak_ptr_factory_.GetWeakPtr(), offline_ids, callback));
-}
-
-void OfflinePageModelImpl::DeletePagesByClientIds(
- const std::vector<ClientId>& client_ids,
- const DeletePageCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder
- .SetClientIds(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- client_ids)
- .AllowExpiredPages(true);
- auto delete_pages = base::Bind(&OfflinePageModelImpl::DeletePages,
- weak_ptr_factory_.GetWeakPtr(), callback);
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- delete_pages));
-}
-
-void OfflinePageModelImpl::DeletePages(
- const DeletePageCallback& callback,
- const MultipleOfflinePageItemResult& pages) {
- DCHECK(is_loaded_);
-
- std::vector<int64_t> offline_ids;
- for (auto& page : pages)
- offline_ids.emplace_back(page.offline_id);
-
- DoDeletePagesByOfflineId(offline_ids, callback);
-}
-
-void OfflinePageModelImpl::GetPagesByClientIds(
- const std::vector<ClientId>& client_ids,
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.SetClientIds(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- client_ids);
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- callback));
-}
-
-void OfflinePageModelImpl::DeleteCachedPagesByURLPredicate(
- const UrlPredicate& predicate,
- const DeletePageCallback& callback) {
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::DoDeleteCachedPagesByURLPredicate,
- weak_ptr_factory_.GetWeakPtr(), predicate, callback));
-}
-
-void OfflinePageModelImpl::DoDeleteCachedPagesByURLPredicate(
- const UrlPredicate& predicate,
- const DeletePageCallback& callback) {
- DCHECK(is_loaded_);
-
- std::vector<int64_t> offline_ids;
- for (const auto& id_page_pair : offline_pages_) {
- if (IsRemovedOnCacheReset(id_page_pair.second) &&
- predicate.Run(id_page_pair.second.url)) {
- offline_ids.push_back(id_page_pair.first);
- }
- }
- DoDeletePagesByOfflineId(offline_ids, callback);
-}
-
-void OfflinePageModelImpl::CheckPagesExistOffline(
- const std::set<GURL>& urls,
- const CheckPagesExistOfflineCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder
- .SetUrls(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- std::vector<GURL>(urls.begin(), urls.end()))
- .RequireRestrictedToOriginalTab(
- OfflinePageModelQueryBuilder::Requirement::EXCLUDE_MATCHING);
- auto pages_to_urls = base::Bind(
- [](const CheckPagesExistOfflineCallback& callback,
- const MultipleOfflinePageItemResult& pages) {
- CheckPagesExistOfflineResult result;
- for (auto& page : pages)
- result.insert(page.url);
- callback.Run(result);
- },
- callback);
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- pages_to_urls));
-}
-
-void OfflinePageModelImpl::GetPagesMatchingQuery(
- std::unique_ptr<OfflinePageModelQuery> query,
- const MultipleOfflinePageItemCallback& callback) {
- DCHECK(query);
-
- MultipleOfflinePageItemResult offline_pages_result;
-
- for (const auto& id_page_pair : offline_pages_) {
- if (query->Matches(id_page_pair.second))
- offline_pages_result.emplace_back(id_page_pair.second);
- }
-
- callback.Run(offline_pages_result);
-}
-
-void OfflinePageModelImpl::GetAllPages(
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- callback));
-}
-
-void OfflinePageModelImpl::GetAllPagesWithExpired(
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.AllowExpiredPages(true);
-
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- callback));
-}
-
-void OfflinePageModelImpl::GetOfflineIdsForClientId(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) {
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetOfflineIdsForClientIdWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), client_id, callback));
-}
-
-void OfflinePageModelImpl::GetOfflineIdsForClientIdWhenLoadDone(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) const {
- callback.Run(MaybeGetOfflineIdsForClientId(client_id));
-}
-
-const std::vector<int64_t> OfflinePageModelImpl::MaybeGetOfflineIdsForClientId(
- const ClientId& client_id) const {
- DCHECK(is_loaded_);
- std::vector<int64_t> results;
-
- // We want only all pages, including those marked for deletion.
- // TODO(fgorski): actually use an index rather than linear scan.
- for (const auto& id_page_pair : offline_pages_) {
- if (id_page_pair.second.client_id == client_id &&
- !id_page_pair.second.IsExpired()) {
- results.push_back(id_page_pair.second.offline_id);
- }
- }
- return results;
-}
-
-void OfflinePageModelImpl::GetPageByOfflineId(
- int64_t offline_id,
- const SingleOfflinePageItemCallback& callback) {
- std::vector<int64_t> query_ids;
- query_ids.emplace_back(offline_id);
-
- OfflinePageModelQueryBuilder builder;
- builder.SetOfflinePageIds(
- OfflinePageModelQuery::Requirement::INCLUDE_MATCHING, query_ids);
-
- auto multiple_callback = base::Bind(
- [](const SingleOfflinePageItemCallback& callback,
- const MultipleOfflinePageItemResult& result) {
- DCHECK_LE(result.size(), 1U);
- if (result.empty()) {
- callback.Run(nullptr);
- } else {
- callback.Run(&result[0]);
- }
- },
- callback);
-
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetPagesMatchingQuery,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())),
- multiple_callback));
-}
-
-void OfflinePageModelImpl::GetPagesByURL(
- const GURL& url,
- URLSearchMode url_search_mode,
- const MultipleOfflinePageItemCallback& callback) {
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesByURLWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), url,
- url_search_mode, callback));
-}
-
-void OfflinePageModelImpl::GetPagesByURLWhenLoadDone(
- const GURL& url,
- URLSearchMode url_search_mode,
- const MultipleOfflinePageItemCallback& callback) const {
- std::vector<OfflinePageItem> result;
-
- GURL::Replacements remove_params;
- remove_params.ClearRef();
-
- GURL url_without_fragment =
- url.ReplaceComponents(remove_params);
-
- for (const auto& id_page_pair : offline_pages_) {
- if (id_page_pair.second.IsExpired())
- continue;
- // First, search by last committed URL with fragment stripped.
- if (url_without_fragment ==
- id_page_pair.second.url.ReplaceComponents(remove_params)) {
- result.push_back(id_page_pair.second);
- continue;
- }
- // Then, search by original request URL if |url_search_mode| wants it.
- // Note that we want to do the exact match with fragment included. This is
- // because original URL is used for redirect purpose and it is always safer
- // to support the exact redirect.
- if (url_search_mode == URLSearchMode::SEARCH_BY_ALL_URLS &&
- url == id_page_pair.second.original_url) {
- result.push_back(id_page_pair.second);
- }
- }
-
- callback.Run(result);
-}
-
-void OfflinePageModelImpl::CheckMetadataConsistency() {
- archive_manager_->GetAllArchives(
- base::Bind(&OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void OfflinePageModelImpl::ExpirePages(
- const std::vector<int64_t>& offline_ids,
- const base::Time& expiration_time,
- const base::Callback<void(bool)>& callback) {
- std::vector<base::FilePath> paths_to_delete;
- std::vector<OfflinePageItem> items_to_update;
- for (int64_t offline_id : offline_ids) {
- auto iter = offline_pages_.find(offline_id);
- if (iter == offline_pages_.end())
- continue;
-
- OfflinePageItem offline_page = iter->second;
- paths_to_delete.push_back(offline_page.file_path);
- offline_page.expiration_time = expiration_time;
-
- items_to_update.push_back(offline_page);
- }
-
- store_->UpdateOfflinePages(
- items_to_update,
- base::Bind(&OfflinePageModelImpl::OnExpirePageDone,
- weak_ptr_factory_.GetWeakPtr(), expiration_time));
-
- if (paths_to_delete.empty()) {
- callback.Run(true);
- return;
- }
- archive_manager_->DeleteMultipleArchives(paths_to_delete, callback);
-}
-
-void OfflinePageModelImpl::OnExpirePageDone(
- const base::Time& expiration_time,
- std::unique_ptr<OfflinePagesUpdateResult> result) {
- UMA_HISTOGRAM_BOOLEAN("OfflinePages.ExpirePage.StoreUpdateResult",
- result->updated_items.size() > 0);
- for (const auto& expired_page : result->updated_items) {
- const auto& iter = offline_pages_.find(expired_page.offline_id);
- if (iter == offline_pages_.end())
- continue;
-
- iter->second.expiration_time = expiration_time;
- ClientId client_id = iter->second.client_id;
- offline_event_logger_.RecordPageExpired(
- std::to_string(expired_page.offline_id));
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.ExpirePage.PageLifetime"),
- 1, base::TimeDelta::FromDays(30).InMinutes(), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((expiration_time - iter->second.creation_time).InMinutes());
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id,
- "OfflinePages.ExpirePage.TimeSinceLastAccess"),
- 1, base::TimeDelta::FromDays(30).InMinutes(), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(
- (expiration_time - iter->second.last_access_time).InMinutes());
- }
-}
-
-ClientPolicyController* OfflinePageModelImpl::GetPolicyController() {
- return policy_controller_.get();
-}
-
-OfflinePageMetadataStore* OfflinePageModelImpl::GetStoreForTesting() {
- return store_.get();
-}
-
-OfflinePageStorageManager* OfflinePageModelImpl::GetStorageManager() {
- return storage_manager_.get();
-}
-
-bool OfflinePageModelImpl::is_loaded() const {
- return is_loaded_;
-}
-
-OfflineEventLogger* OfflinePageModelImpl::GetLogger() {
- return &offline_event_logger_;
-}
-
-void OfflinePageModelImpl::OnCreateArchiveDone(
- const SavePageParams& save_page_params,
- int64_t offline_id,
- const base::Time& start_time,
- const SavePageCallback& callback,
- OfflinePageArchiver* archiver,
- ArchiverResult archiver_result,
- const GURL& url,
- const base::FilePath& file_path,
- const base::string16& title,
- int64_t file_size) {
- if (save_page_params.url != url) {
- DVLOG(1) << "Saved URL does not match requested URL.";
- // TODO(fgorski): We have created an archive for a wrong URL. It should be
- // deleted from here, once archiver has the right functionality.
- InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED,
- save_page_params.client_id, offline_id);
- DeletePendingArchiver(archiver);
- return;
- }
-
- if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) {
- SavePageResult result = ToSavePageResult(archiver_result);
- InformSavePageDone(
- callback, result, save_page_params.client_id, offline_id);
- DeletePendingArchiver(archiver);
- return;
- }
- OfflinePageItem offline_page_item(url, offline_id, save_page_params.client_id,
- file_path, file_size, start_time);
- offline_page_item.title = title;
- offline_page_item.original_url = save_page_params.original_url;
- store_->AddOfflinePage(offline_page_item,
- base::Bind(&OfflinePageModelImpl::OnAddOfflinePageDone,
- weak_ptr_factory_.GetWeakPtr(), archiver,
- callback, offline_page_item));
-}
-
-void OfflinePageModelImpl::OnAddOfflinePageDone(
- OfflinePageArchiver* archiver,
- const SavePageCallback& callback,
- const OfflinePageItem& offline_page,
- ItemActionStatus status) {
- SavePageResult result;
- if (status == ItemActionStatus::SUCCESS) {
- offline_pages_[offline_page.offline_id] = offline_page;
- result = SavePageResult::SUCCESS;
- ReportPageHistogramAfterSave(policy_controller_.get(), offline_pages_,
- offline_page, GetCurrentTime());
- offline_event_logger_.RecordPageSaved(
- offline_page.client_id.name_space, offline_page.url.spec(),
- std::to_string(offline_page.offline_id));
- } else if (status == ItemActionStatus::ALREADY_EXISTS) {
- result = SavePageResult::ALREADY_EXISTS;
- } else {
- result = SavePageResult::STORE_FAILURE;
- }
- InformSavePageDone(callback, result, offline_page.client_id,
- offline_page.offline_id);
- if (result == SavePageResult::SUCCESS) {
- DeleteExistingPagesWithSameURL(offline_page);
- } else {
- PostClearStorageIfNeededTask(false /* delayed */);
- }
-
- DeletePendingArchiver(archiver);
- for (Observer& observer : observers_)
- observer.OfflinePageModelChanged(this);
-}
-
-void OfflinePageModelImpl::OnMarkPageAccesseDone(
- const OfflinePageItem& offline_page_item,
- std::unique_ptr<OfflinePagesUpdateResult> result) {
- // Update the item in the cache only upon success.
- if (result->updated_items.size() > 0)
- offline_pages_[offline_page_item.offline_id] = offline_page_item;
-
- // No need to fire OfflinePageModelChanged event since updating access info
- // should not have any impact to the UI.
-}
-
-void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone(
- const base::TimeTicks& start_time) {
- UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime",
- base::TimeTicks::Now() - start_time);
-
- const int kResetAttemptsLeft = 1;
- store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
- weak_ptr_factory_.GetWeakPtr(), start_time,
- kResetAttemptsLeft));
-}
-
-void OfflinePageModelImpl::OnStoreInitialized(const base::TimeTicks& start_time,
- int reset_attempts_left,
- bool success) {
- if (success) {
- DCHECK_EQ(store_->state(), StoreState::LOADED);
- store_->GetOfflinePages(
- base::Bind(&OfflinePageModelImpl::OnInitialGetOfflinePagesDone,
- weak_ptr_factory_.GetWeakPtr(), start_time));
- return;
- }
-
- DCHECK_EQ(store_->state(), StoreState::FAILED_LOADING);
- // If there are no more reset attempts left, stop here.
- if (reset_attempts_left == 0) {
- FinalizeModelLoad();
- return;
- }
-
- // Otherwise reduce the remaining attempts counter and reset store.
- store_->Reset(base::Bind(&OfflinePageModelImpl::OnStoreResetDone,
- weak_ptr_factory_.GetWeakPtr(), start_time,
- reset_attempts_left - 1));
-}
-
-void OfflinePageModelImpl::OnStoreResetDone(const base::TimeTicks& start_time,
- int reset_attempts_left,
- bool success) {
- if (success) {
- DCHECK_EQ(store_->state(), StoreState::NOT_LOADED);
- store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
- weak_ptr_factory_.GetWeakPtr(), start_time,
- reset_attempts_left));
- return;
- }
-
- DCHECK_EQ(store_->state(), StoreState::FAILED_RESET);
- FinalizeModelLoad();
-}
-
-void OfflinePageModelImpl::OnInitialGetOfflinePagesDone(
- const base::TimeTicks& start_time,
- const std::vector<OfflinePageItem>& offline_pages) {
- DCHECK(!is_loaded_);
-
- UMA_HISTOGRAM_TIMES("OfflinePages.Model.ConstructionToLoadedEventTime",
- base::TimeTicks::Now() - start_time);
-
- CacheLoadedData(offline_pages);
- FinalizeModelLoad();
-
- // Ensure necessary cleanup operations are started.
- CheckMetadataConsistency();
-}
-
-void OfflinePageModelImpl::FinalizeModelLoad() {
- is_loaded_ = true;
-
- // All actions below are meant to be taken regardless of successful load of
- // the store.
-
- // Inform observers the load is done.
- for (Observer& observer : observers_)
- observer.OfflinePageModelLoaded(this);
-
- // Run all the delayed tasks.
- for (const auto& delayed_task : delayed_tasks_)
- delayed_task.Run();
- delayed_tasks_.clear();
-
- // Clear storage.
- PostClearStorageIfNeededTask(true /* delayed */);
-}
-
-void OfflinePageModelImpl::InformSavePageDone(const SavePageCallback& callback,
- SavePageResult result,
- const ClientId& client_id,
- int64_t offline_id) {
- ReportSavePageResultHistogramAfterSave(client_id, result);
- archive_manager_->GetStorageStats(
- base::Bind(&ReportStorageHistogramsAfterSave));
- callback.Run(result, offline_id);
-}
-
-void OfflinePageModelImpl::DeleteExistingPagesWithSameURL(
- const OfflinePageItem& offline_page) {
- // Remove existing pages generated by the same policy and with same url.
- size_t pages_allowed =
- policy_controller_->GetPolicy(offline_page.client_id.name_space)
- .pages_allowed_per_url;
- if (pages_allowed == kUnlimitedPages)
- return;
- GetPagesByURL(
- offline_page.url,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY,
- base::Bind(&OfflinePageModelImpl::OnPagesFoundWithSameURL,
- weak_ptr_factory_.GetWeakPtr(), offline_page, pages_allowed));
-}
-
-void OfflinePageModelImpl::OnPagesFoundWithSameURL(
- const OfflinePageItem& offline_page,
- size_t pages_allowed,
- const MultipleOfflinePageItemResult& items) {
- std::vector<OfflinePageItem> pages_to_delete;
- for (const auto& item : items) {
- if (item.offline_id != offline_page.offline_id &&
- item.client_id.name_space == offline_page.client_id.name_space) {
- pages_to_delete.push_back(item);
- }
- }
- // Only keep |pages_allowed|-1 of most fresh pages and delete others, by
- // sorting pages with the oldest ones first and resize the vector.
- if (pages_to_delete.size() >= pages_allowed) {
- sort(pages_to_delete.begin(), pages_to_delete.end(),
- [](const OfflinePageItem& a, const OfflinePageItem& b) -> bool {
- return a.last_access_time < b.last_access_time;
- });
- pages_to_delete.resize(pages_to_delete.size() - pages_allowed + 1);
- }
- std::vector<int64_t> page_ids_to_delete;
- for (const auto& item : pages_to_delete)
- page_ids_to_delete.push_back(item.offline_id);
- DeletePagesByOfflineId(
- page_ids_to_delete,
- base::Bind(&OfflinePageModelImpl::OnDeleteOldPagesWithSameURL,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void OfflinePageModelImpl::OnDeleteOldPagesWithSameURL(
- DeletePageResult result) {
- // TODO(romax) Add UMAs for failure cases.
- PostClearStorageIfNeededTask(false /* delayed */);
-}
-
-void OfflinePageModelImpl::DeletePendingArchiver(
- OfflinePageArchiver* archiver) {
- pending_archivers_.erase(std::find(pending_archivers_.begin(),
- pending_archivers_.end(), archiver));
-}
-
-void OfflinePageModelImpl::OnDeleteArchiveFilesDone(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback,
- bool success) {
- if (!success) {
- InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE);
- return;
- }
-
- store_->RemoveOfflinePages(
- offline_ids, base::Bind(&OfflinePageModelImpl::OnRemoveOfflinePagesDone,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void OfflinePageModelImpl::OnRemoveOfflinePagesDone(
- const DeletePageCallback& callback,
- std::unique_ptr<OfflinePagesUpdateResult> result) {
- ReportPageHistogramsAfterDelete(offline_pages_, result->updated_items,
- GetCurrentTime());
-
- // This part of the loop is explicitly broken out, as it should be gone in
- // fully asynchronous code.
- for (const auto& page : result->updated_items) {
- int64_t offline_id = page.offline_id;
- offline_event_logger_.RecordPageDeleted(std::to_string(offline_id));
- auto iter = offline_pages_.find(offline_id);
- if (iter == offline_pages_.end())
- continue;
- offline_pages_.erase(iter);
- }
-
- for (const auto& page : result->updated_items) {
- for (Observer& observer : observers_)
- observer.OfflinePageDeleted(page.offline_id, page.client_id);
- }
-
- // TODO(fgorski): React the FAILED_INITIALIZATION, FAILED_RESET here.
- // TODO(fgorski): We need a better callback interface for the Remove action on
- // the this class. Currently removing an item that does not exist is
- // considered a success, but not called out as such to the caller.
- DeletePageResult delete_result;
- if (result->store_state == StoreState::LOADED)
- delete_result = DeletePageResult::SUCCESS;
- else
- delete_result = DeletePageResult::STORE_FAILURE;
-
- InformDeletePageDone(callback, delete_result);
-}
-
-void OfflinePageModelImpl::InformDeletePageDone(
- const DeletePageCallback& callback,
- DeletePageResult result) {
- UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult",
- static_cast<int>(result),
- static_cast<int>(DeletePageResult::RESULT_COUNT));
- archive_manager_->GetStorageStats(
- base::Bind(&ReportStorageHistogramsAfterDelete));
- if (!callback.is_null())
- callback.Run(result);
-}
-
-void OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths(
- const std::set<base::FilePath>& archive_paths) {
- ExpirePagesMissingArchiveFile(archive_paths);
- DeleteOrphanedArchives(archive_paths);
-}
-
-void OfflinePageModelImpl::ExpirePagesMissingArchiveFile(
- const std::set<base::FilePath>& archive_paths) {
- std::vector<int64_t> ids_of_pages_missing_archive_file;
- for (const auto& id_page_pair : offline_pages_) {
- if (archive_paths.count(id_page_pair.second.file_path) == 0UL)
- ids_of_pages_missing_archive_file.push_back(id_page_pair.first);
- }
-
- if (ids_of_pages_missing_archive_file.empty())
- return;
-
- ExpirePages(
- ids_of_pages_missing_archive_file, GetCurrentTime(),
- base::Bind(&OfflinePageModelImpl::OnExpirePagesMissingArchiveFileDone,
- weak_ptr_factory_.GetWeakPtr(),
- ids_of_pages_missing_archive_file));
-}
-
-void OfflinePageModelImpl::OnExpirePagesMissingArchiveFileDone(
- const std::vector<int64_t>& offline_ids,
- bool success) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.Consistency.PagesMissingArchiveFileCount",
- static_cast<int32_t>(offline_ids.size()));
- UMA_HISTOGRAM_BOOLEAN(
- "OfflinePages.Consistency.ExpirePagesMissingArchiveFileResult", success);
-}
-
-void OfflinePageModelImpl::DeleteOrphanedArchives(
- const std::set<base::FilePath>& archive_paths) {
- // Archives are considered orphaned unless they are pointed to by some pages.
- std::set<base::FilePath> orphaned_archive_set(archive_paths);
- for (const auto& id_page_pair : offline_pages_)
- orphaned_archive_set.erase(id_page_pair.second.file_path);
-
- if (orphaned_archive_set.empty())
- return;
-
- std::vector<base::FilePath> orphaned_archives(orphaned_archive_set.begin(),
- orphaned_archive_set.end());
- archive_manager_->DeleteMultipleArchives(
- orphaned_archives,
- base::Bind(&OfflinePageModelImpl::OnDeleteOrphanedArchivesDone,
- weak_ptr_factory_.GetWeakPtr(), orphaned_archives));
-}
-
-void OfflinePageModelImpl::OnDeleteOrphanedArchivesDone(
- const std::vector<base::FilePath>& archives,
- bool success) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.Consistency.OrphanedArchivesCount",
- static_cast<int32_t>(archives.size()));
- UMA_HISTOGRAM_BOOLEAN("OfflinePages.Consistency.DeleteOrphanedArchivesResult",
- success);
-}
-
-void OfflinePageModelImpl::CacheLoadedData(
- const std::vector<OfflinePageItem>& offline_pages) {
- offline_pages_.clear();
- for (const auto& offline_page : offline_pages)
- offline_pages_[offline_page.offline_id] = offline_page;
-}
-
-void OfflinePageModelImpl::ClearStorageIfNeeded(
- const ClearStorageCallback& callback) {
- // Create Storage Manager if necessary.
- if (!storage_manager_) {
- storage_manager_.reset(new OfflinePageStorageManager(
- this, GetPolicyController(), archive_manager_.get()));
- }
- storage_manager_->ClearPagesIfNeeded(callback);
-}
-
-void OfflinePageModelImpl::OnStorageCleared(size_t expired_page_count,
- ClearStorageResult result) {
- UMA_HISTOGRAM_ENUMERATION("OfflinePages.ClearStorageResult",
- static_cast<int>(result),
- static_cast<int>(ClearStorageResult::RESULT_COUNT));
- if (expired_page_count > 0) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.ExpirePage.BatchSize",
- static_cast<int32_t>(expired_page_count));
- }
-}
-
-void OfflinePageModelImpl::PostClearStorageIfNeededTask(bool delayed) {
- base::TimeDelta delay =
- delayed ? kStorageManagerStartingDelay : base::TimeDelta();
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&OfflinePageModelImpl::ClearStorageIfNeeded,
- weak_ptr_factory_.GetWeakPtr(),
- base::Bind(&OfflinePageModelImpl::OnStorageCleared,
- weak_ptr_factory_.GetWeakPtr())),
- delay);
-}
-
-bool OfflinePageModelImpl::IsRemovedOnCacheReset(
- const OfflinePageItem& offline_page) const {
- return policy_controller_->IsRemovedOnCacheReset(
- offline_page.client_id.name_space);
-}
-
-void OfflinePageModelImpl::RunWhenLoaded(const base::Closure& task) {
- if (!is_loaded_) {
- delayed_tasks_.push_back(task);
- return;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
-}
-
-base::Time OfflinePageModelImpl::GetCurrentTime() const {
- return testing_clock_ ? testing_clock_->Now() : base::Time::Now();
-}
-
-} // namespace offline_pages

Powered by Google App Engine
This is Rietveld 408576698