Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/offline_pages/offline_page_model_impl.h" | 5 #include "components/offline_pages/offline_page_model_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 base::TimeDelta::FromSeconds(1).InSeconds(), | 229 base::TimeDelta::FromSeconds(1).InSeconds(), |
| 230 base::TimeDelta::FromDays(7).InSeconds(), 50); | 230 base::TimeDelta::FromDays(7).InSeconds(), 50); |
| 231 } | 231 } |
| 232 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DownloadSavedPageDuplicateCount", | 232 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DownloadSavedPageDuplicateCount", |
| 233 matching_url_count, 1, 20, 10); | 233 matching_url_count, 1, 20, 10); |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 | 236 |
| 237 void ReportPageHistogramsAfterDelete( | 237 void ReportPageHistogramsAfterDelete( |
| 238 const std::map<int64_t, OfflinePageItem>& offline_pages, | 238 const std::map<int64_t, OfflinePageItem>& offline_pages, |
| 239 const std::vector<int64_t>& deleted_offline_ids, | 239 const std::vector<OfflinePageItem>& deleted_pages, |
| 240 const base::Time& delete_time) { | 240 const base::Time& delete_time) { |
| 241 const int max_minutes = base::TimeDelta::FromDays(365).InMinutes(); | 241 const int max_minutes = base::TimeDelta::FromDays(365).InMinutes(); |
| 242 int64_t total_size = 0; | 242 int64_t total_size = 0; |
| 243 for (int64_t offline_id : deleted_offline_ids) { | |
| 244 auto iter = offline_pages.find(offline_id); | |
| 245 if (iter == offline_pages.end()) | |
| 246 continue; | |
| 247 | 243 |
| 248 total_size += iter->second.file_size; | 244 for (const auto& page : deleted_pages) { |
| 249 ClientId client_id = iter->second.client_id; | 245 total_size += page.file_size; |
| 246 ClientId client_id = page.client_id; | |
| 250 | 247 |
| 251 if (client_id.name_space == kDownloadNamespace) { | 248 if (client_id.name_space == kDownloadNamespace) { |
| 252 int remaining_pages_with_url; | 249 int remaining_pages_with_url; |
| 253 GetMatchingURLCountAndMostRecentCreationTime( | 250 GetMatchingURLCountAndMostRecentCreationTime( |
| 254 offline_pages, iter->second.client_id.name_space, iter->second.url, | 251 offline_pages, page.client_id.name_space, page.url, base::Time::Max(), |
| 255 base::Time::Max(), &remaining_pages_with_url, nullptr); | 252 &remaining_pages_with_url, nullptr); |
| 256 UMA_HISTOGRAM_CUSTOM_COUNTS( | 253 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 257 "OfflinePages.DownloadDeletedPageDuplicateCount", | 254 "OfflinePages.DownloadDeletedPageDuplicateCount", |
| 258 remaining_pages_with_url, 1, 20, 10); | 255 remaining_pages_with_url, 1, 20, 10); |
| 259 } | 256 } |
| 260 | 257 |
| 261 // The histograms below are an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS | 258 // The histograms below are an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS |
| 262 // macro adapted to allow for a dynamically suffixed histogram name. | 259 // macro adapted to allow for a dynamically suffixed histogram name. |
| 263 // Note: The factory creates and owns the histogram. | 260 // Note: The factory creates and owns the histogram. |
| 264 base::HistogramBase* histogram = base::Histogram::FactoryGet( | 261 base::HistogramBase* histogram = base::Histogram::FactoryGet( |
| 265 AddHistogramSuffix(client_id, "OfflinePages.PageLifetime"), | 262 AddHistogramSuffix(client_id, "OfflinePages.PageLifetime"), |
| 266 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); | 263 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 267 histogram->Add((delete_time - iter->second.creation_time).InMinutes()); | 264 histogram->Add((delete_time - page.creation_time).InMinutes()); |
| 268 | 265 |
| 269 histogram = base::Histogram::FactoryGet( | 266 histogram = base::Histogram::FactoryGet( |
| 270 AddHistogramSuffix( | 267 AddHistogramSuffix( |
| 271 client_id, "OfflinePages.DeletePage.TimeSinceLastOpen"), | 268 client_id, "OfflinePages.DeletePage.TimeSinceLastOpen"), |
| 272 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); | 269 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 273 histogram->Add((delete_time - iter->second.last_access_time).InMinutes()); | 270 histogram->Add((delete_time - page.last_access_time).InMinutes()); |
| 274 | 271 |
| 275 histogram = base::Histogram::FactoryGet( | 272 histogram = base::Histogram::FactoryGet( |
| 276 AddHistogramSuffix( | 273 AddHistogramSuffix( |
| 277 client_id, "OfflinePages.DeletePage.LastOpenToCreated"), | 274 client_id, "OfflinePages.DeletePage.LastOpenToCreated"), |
| 278 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); | 275 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 279 histogram->Add( | 276 histogram->Add((page.last_access_time - page.creation_time).InMinutes()); |
| 280 (iter->second.last_access_time - iter->second.creation_time). | |
| 281 InMinutes()); | |
| 282 | 277 |
| 283 // Reported as Kb between 1Kb and 10Mb. | 278 // Reported as Kb between 1Kb and 10Mb. |
| 284 histogram = base::Histogram::FactoryGet( | 279 histogram = base::Histogram::FactoryGet( |
| 285 AddHistogramSuffix(client_id, "OfflinePages.DeletePage.PageSize"), | 280 AddHistogramSuffix(client_id, "OfflinePages.DeletePage.PageSize"), |
| 286 1, 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag); | 281 1, 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 287 histogram->Add(iter->second.file_size / 1024); | 282 histogram->Add(page.file_size / 1024); |
| 288 | 283 |
| 289 histogram = base::Histogram::FactoryGet( | 284 histogram = base::Histogram::FactoryGet( |
| 290 AddHistogramSuffix(client_id, "OfflinePages.DeletePage.AccessCount"), | 285 AddHistogramSuffix(client_id, "OfflinePages.DeletePage.AccessCount"), |
| 291 1, 1000000, 50, base::HistogramBase::kUmaTargetedHistogramFlag); | 286 1, 1000000, 50, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 292 histogram->Add(iter->second.access_count); | 287 histogram->Add(page.access_count); |
| 293 } | 288 } |
| 294 | 289 |
| 295 if (deleted_offline_ids.size() > 1) { | 290 if (deleted_pages.size() > 1) { |
| 296 UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count", | 291 UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count", |
| 297 static_cast<int32_t>(deleted_offline_ids.size())); | 292 static_cast<int32_t>(deleted_pages.size())); |
| 298 UMA_HISTOGRAM_MEMORY_KB( | 293 UMA_HISTOGRAM_MEMORY_KB( |
| 299 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); | 294 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); |
| 300 } | 295 } |
| 301 } | 296 } |
| 302 | 297 |
| 303 void ReportPageHistogramsAfterAccess(const OfflinePageItem& offline_page_item, | 298 void ReportPageHistogramsAfterAccess(const OfflinePageItem& offline_page_item, |
| 304 const base::Time& access_time) { | 299 const base::Time& access_time) { |
| 305 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS | 300 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS |
| 306 // macro adapted to allow for a dynamically suffixed histogram name. | 301 // macro adapted to allow for a dynamically suffixed histogram name. |
| 307 // Note: The factory creates and owns the histogram. | 302 // Note: The factory creates and owns the histogram. |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 682 if (iter == offline_pages_.end()) | 677 if (iter == offline_pages_.end()) |
| 683 continue; | 678 continue; |
| 684 | 679 |
| 685 OfflinePageItem offline_page = iter->second; | 680 OfflinePageItem offline_page = iter->second; |
| 686 paths_to_delete.push_back(offline_page.file_path); | 681 paths_to_delete.push_back(offline_page.file_path); |
| 687 offline_page.expiration_time = expiration_time; | 682 offline_page.expiration_time = expiration_time; |
| 688 | 683 |
| 689 items_to_update.push_back(offline_page); | 684 items_to_update.push_back(offline_page); |
| 690 } | 685 } |
| 691 | 686 |
| 692 store_->UpdateOfflinePages(items_to_update, | 687 store_->UpdateOfflinePages( |
| 693 base::Bind(&OfflinePageModelImpl::OnExpirePageDone, | 688 items_to_update, |
| 694 weak_ptr_factory_.GetWeakPtr(), | 689 base::Bind(&OfflinePageModelImpl::OnExpirePageDone, |
| 695 items_to_update, expiration_time)); | 690 weak_ptr_factory_.GetWeakPtr(), expiration_time)); |
| 696 | 691 |
| 697 if (paths_to_delete.empty()) { | 692 if (paths_to_delete.empty()) { |
| 698 callback.Run(true); | 693 callback.Run(true); |
| 699 return; | 694 return; |
| 700 } | 695 } |
| 701 archive_manager_->DeleteMultipleArchives(paths_to_delete, callback); | 696 archive_manager_->DeleteMultipleArchives(paths_to_delete, callback); |
| 702 } | 697 } |
| 703 | 698 |
| 704 void OfflinePageModelImpl::OnExpirePageDone( | 699 void OfflinePageModelImpl::OnExpirePageDone( |
| 705 const std::vector<OfflinePageItem>& expired_pages, | |
| 706 const base::Time& expiration_time, | 700 const base::Time& expiration_time, |
| 707 bool success) { | 701 std::unique_ptr<StoreUpdateResult> result) { |
| 708 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ExpirePage.StoreUpdateResult", success); | 702 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ExpirePage.StoreUpdateResult", |
| 709 if (!success) | 703 result->updated_items.size() > 0); |
| 710 return; | 704 for (const auto& expired_page : result->updated_items) { |
| 711 for (auto& expired_page : expired_pages) { | |
| 712 const auto& iter = offline_pages_.find(expired_page.offline_id); | 705 const auto& iter = offline_pages_.find(expired_page.offline_id); |
| 713 if (iter == offline_pages_.end()) | 706 if (iter == offline_pages_.end()) |
| 714 continue; | 707 continue; |
| 715 | 708 |
| 716 iter->second.expiration_time = expiration_time; | 709 iter->second.expiration_time = expiration_time; |
| 717 ClientId client_id = iter->second.client_id; | 710 ClientId client_id = iter->second.client_id; |
| 718 offline_event_logger_.RecordPageExpired( | 711 offline_event_logger_.RecordPageExpired( |
| 719 std::to_string(expired_page.offline_id)); | 712 std::to_string(expired_page.offline_id)); |
| 720 base::HistogramBase* histogram = base::Histogram::FactoryGet( | 713 base::HistogramBase* histogram = base::Histogram::FactoryGet( |
| 721 AddHistogramSuffix(client_id, "OfflinePages.ExpirePage.PageLifetime"), | 714 AddHistogramSuffix(client_id, "OfflinePages.ExpirePage.PageLifetime"), |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 store_->AddOfflinePage(offline_page_item, | 778 store_->AddOfflinePage(offline_page_item, |
| 786 base::Bind(&OfflinePageModelImpl::OnAddOfflinePageDone, | 779 base::Bind(&OfflinePageModelImpl::OnAddOfflinePageDone, |
| 787 weak_ptr_factory_.GetWeakPtr(), archiver, | 780 weak_ptr_factory_.GetWeakPtr(), archiver, |
| 788 callback, offline_page_item)); | 781 callback, offline_page_item)); |
| 789 } | 782 } |
| 790 | 783 |
| 791 void OfflinePageModelImpl::OnAddOfflinePageDone( | 784 void OfflinePageModelImpl::OnAddOfflinePageDone( |
| 792 OfflinePageArchiver* archiver, | 785 OfflinePageArchiver* archiver, |
| 793 const SavePageCallback& callback, | 786 const SavePageCallback& callback, |
| 794 const OfflinePageItem& offline_page, | 787 const OfflinePageItem& offline_page, |
| 795 OfflinePageMetadataStore::ItemActionStatus status) { | 788 ItemActionStatus status) { |
| 796 SavePageResult result; | 789 SavePageResult result; |
| 797 if (status == OfflinePageMetadataStore::SUCCESS) { | 790 if (status == ItemActionStatus::SUCCESS) { |
| 798 offline_pages_[offline_page.offline_id] = offline_page; | 791 offline_pages_[offline_page.offline_id] = offline_page; |
| 799 result = SavePageResult::SUCCESS; | 792 result = SavePageResult::SUCCESS; |
| 800 ReportPageHistogramAfterSave(offline_pages_, offline_page, | 793 ReportPageHistogramAfterSave(offline_pages_, offline_page, |
| 801 GetCurrentTime()); | 794 GetCurrentTime()); |
| 802 offline_event_logger_.RecordPageSaved( | 795 offline_event_logger_.RecordPageSaved( |
| 803 offline_page.client_id.name_space, offline_page.url.spec(), | 796 offline_page.client_id.name_space, offline_page.url.spec(), |
| 804 std::to_string(offline_page.offline_id)); | 797 std::to_string(offline_page.offline_id)); |
| 805 } else if (status == OfflinePageMetadataStore::ALREADY_EXISTS) { | 798 } else if (status == ItemActionStatus::ALREADY_EXISTS) { |
| 806 result = SavePageResult::ALREADY_EXISTS; | 799 result = SavePageResult::ALREADY_EXISTS; |
| 807 } else { | 800 } else { |
| 808 result = SavePageResult::STORE_FAILURE; | 801 result = SavePageResult::STORE_FAILURE; |
| 809 } | 802 } |
| 810 InformSavePageDone(callback, result, offline_page.client_id, | 803 InformSavePageDone(callback, result, offline_page.client_id, |
| 811 offline_page.offline_id); | 804 offline_page.offline_id); |
| 812 if (result == SavePageResult::SUCCESS) { | 805 if (result == SavePageResult::SUCCESS) { |
| 813 DeleteExistingPagesWithSameURL(offline_page); | 806 DeleteExistingPagesWithSameURL(offline_page); |
| 814 } else { | 807 } else { |
| 815 PostClearStorageIfNeededTask(); | 808 PostClearStorageIfNeededTask(); |
| 816 } | 809 } |
| 817 | 810 |
| 818 DeletePendingArchiver(archiver); | 811 DeletePendingArchiver(archiver); |
| 819 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); | 812 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); |
| 820 } | 813 } |
| 821 | 814 |
| 822 void OfflinePageModelImpl::OnMarkPageAccesseDone( | 815 void OfflinePageModelImpl::OnMarkPageAccesseDone( |
| 823 const OfflinePageItem& offline_page_item, | 816 const OfflinePageItem& offline_page_item, |
| 824 bool success) { | 817 std::unique_ptr<StoreUpdateResult> result) { |
| 825 // Update the item in the cache only upon success. | 818 // Update the item in the cache only upon success. |
| 826 if (success) | 819 if (result->updated_items.size() > 0) |
| 827 offline_pages_[offline_page_item.offline_id] = offline_page_item; | 820 offline_pages_[offline_page_item.offline_id] = offline_page_item; |
| 828 | 821 |
| 829 // No need to fire OfflinePageModelChanged event since updating access info | 822 // No need to fire OfflinePageModelChanged event since updating access info |
| 830 // should not have any impact to the UI. | 823 // should not have any impact to the UI. |
| 831 } | 824 } |
| 832 | 825 |
| 833 void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone( | 826 void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone( |
| 834 const base::TimeTicks& start_time) { | 827 const base::TimeTicks& start_time) { |
| 835 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime", | 828 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime", |
| 836 base::TimeTicks::Now() - start_time); | 829 base::TimeTicks::Now() - start_time); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 void OfflinePageModelImpl::OnDeleteArchiveFilesDone( | 937 void OfflinePageModelImpl::OnDeleteArchiveFilesDone( |
| 945 const std::vector<int64_t>& offline_ids, | 938 const std::vector<int64_t>& offline_ids, |
| 946 const DeletePageCallback& callback, | 939 const DeletePageCallback& callback, |
| 947 bool success) { | 940 bool success) { |
| 948 if (!success) { | 941 if (!success) { |
| 949 InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE); | 942 InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE); |
| 950 return; | 943 return; |
| 951 } | 944 } |
| 952 | 945 |
| 953 store_->RemoveOfflinePages( | 946 store_->RemoveOfflinePages( |
| 954 offline_ids, | 947 offline_ids, base::Bind(&OfflinePageModelImpl::OnRemoveOfflinePagesDone, |
| 955 base::Bind(&OfflinePageModelImpl::OnRemoveOfflinePagesDone, | 948 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 956 weak_ptr_factory_.GetWeakPtr(), offline_ids, callback)); | |
| 957 } | 949 } |
| 958 | 950 |
| 959 void OfflinePageModelImpl::OnRemoveOfflinePagesDone( | 951 void OfflinePageModelImpl::OnRemoveOfflinePagesDone( |
| 960 const std::vector<int64_t>& offline_ids, | |
| 961 const DeletePageCallback& callback, | 952 const DeletePageCallback& callback, |
| 962 bool success) { | 953 std::unique_ptr<StoreUpdateResult> result) { |
| 963 ReportPageHistogramsAfterDelete( | 954 ReportPageHistogramsAfterDelete(offline_pages_, result->updated_items, |
| 964 offline_pages_, offline_ids, GetCurrentTime()); | 955 GetCurrentTime()); |
| 965 | 956 |
| 966 for (int64_t offline_id : offline_ids) { | 957 // This pat of the loop is explicitly broken out, as it should be gone in |
| 958 // fully asynchronous code. | |
| 959 for (const auto& page : result->updated_items) { | |
| 960 int64_t offline_id = page.offline_id; | |
| 967 offline_event_logger_.RecordPageDeleted(std::to_string(offline_id)); | 961 offline_event_logger_.RecordPageDeleted(std::to_string(offline_id)); |
| 968 auto iter = offline_pages_.find(offline_id); | 962 auto iter = offline_pages_.find(offline_id); |
| 969 if (iter == offline_pages_.end()) | 963 if (iter == offline_pages_.end()) |
| 970 continue; | 964 continue; |
| 971 FOR_EACH_OBSERVER( | |
| 972 Observer, observers_, | |
| 973 OfflinePageDeleted(iter->second.offline_id, iter->second.client_id)); | |
| 974 offline_pages_.erase(iter); | 965 offline_pages_.erase(iter); |
| 975 } | 966 } |
| 976 | 967 |
| 977 // Deleting multiple pages always succeeds when it gets to this point. | 968 for (const auto& page : result->updated_items) { |
| 978 InformDeletePageDone(callback, (success || offline_ids.size() > 1) | 969 FOR_EACH_OBSERVER(Observer, observers_, |
| 979 ? DeletePageResult::SUCCESS | 970 OfflinePageDeleted(page.offline_id, page.client_id)); |
| 980 : DeletePageResult::STORE_FAILURE); | 971 } |
| 972 | |
| 973 // TODO(fgorski): React the FAILED_INITIALIZATION, FAILED_RESET here. | |
| 974 DeletePageResult delete_result = DeletePageResult::SUCCESS; | |
| 975 // TODO(fgorski): Update this code to check if there was a store error. | |
| 976 if (result->updated_items.size() == 0 && result->item_statuses.size() > 0 && | |
|
dougarnett
2016/09/19 16:37:29
It we had 'failures' rather than 'item_statuses' f
fgorski
2016/09/19 23:24:30
I meant to update the code. We have a pretty simpl
| |
| 977 result->item_statuses.begin()->second == ItemActionStatus::STORE_ERROR) { | |
| 978 delete_result = DeletePageResult::STORE_FAILURE; | |
| 979 } | |
| 980 InformDeletePageDone(callback, delete_result); | |
| 981 } | 981 } |
| 982 | 982 |
| 983 void OfflinePageModelImpl::InformDeletePageDone( | 983 void OfflinePageModelImpl::InformDeletePageDone( |
| 984 const DeletePageCallback& callback, | 984 const DeletePageCallback& callback, |
| 985 DeletePageResult result) { | 985 DeletePageResult result) { |
| 986 UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult", | 986 UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult", |
| 987 static_cast<int>(result), | 987 static_cast<int>(result), |
| 988 static_cast<int>(DeletePageResult::RESULT_COUNT)); | 988 static_cast<int>(DeletePageResult::RESULT_COUNT)); |
| 989 archive_manager_->GetStorageStats( | 989 archive_manager_->GetStorageStats( |
| 990 base::Bind(&ReportStorageHistogramsAfterDelete)); | 990 base::Bind(&ReportStorageHistogramsAfterDelete)); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); | 1143 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); |
| 1144 } | 1144 } |
| 1145 | 1145 |
| 1146 base::Time OfflinePageModelImpl::GetCurrentTime() const { | 1146 base::Time OfflinePageModelImpl::GetCurrentTime() const { |
| 1147 return testing_clock_ ? testing_clock_->Now() : base::Time::Now(); | 1147 return testing_clock_ ? testing_clock_->Now() : base::Time::Now(); |
| 1148 } | 1148 } |
| 1149 | 1149 |
| 1150 } // namespace offline_pages | 1150 } // namespace offline_pages |
| OLD | NEW |