| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.h" | 5 #include "components/offline_pages/offline_page_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 STORE_RELOAD_FAILED, | 36 STORE_RELOAD_FAILED, |
| 37 | 37 |
| 38 // NOTE: always keep this entry at the end. | 38 // NOTE: always keep this entry at the end. |
| 39 CLEAR_ALL_STATUS_COUNT | 39 CLEAR_ALL_STATUS_COUNT |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 // Threshold for how old offline copy of a page should be before we offer to | 42 // Threshold for how old offline copy of a page should be before we offer to |
| 43 // delete it to free up space. | 43 // delete it to free up space. |
| 44 const base::TimeDelta kPageCleanUpThreshold = base::TimeDelta::FromDays(30); | 44 const base::TimeDelta kPageCleanUpThreshold = base::TimeDelta::FromDays(30); |
| 45 | 45 |
| 46 // The delay for the final deletion to kick in after the page is marked for | |
| 47 // deletion. The value set here is a bit longer that the duration of the | |
| 48 // snackbar that offers undo. | |
| 49 const base::TimeDelta kFinalDeletionDelay = base::TimeDelta::FromSeconds(6); | |
| 50 | |
| 51 // The maximum histogram size for the metrics that measure time between views of | 46 // The maximum histogram size for the metrics that measure time between views of |
| 52 // a given page. | 47 // a given page. |
| 53 const base::TimeDelta kMaxOpenedPageHistogramBucket = | 48 const base::TimeDelta kMaxOpenedPageHistogramBucket = |
| 54 base::TimeDelta::FromDays(90); | 49 base::TimeDelta::FromDays(90); |
| 55 | 50 |
| 56 SavePageResult ToSavePageResult(ArchiverResult archiver_result) { | 51 SavePageResult ToSavePageResult(ArchiverResult archiver_result) { |
| 57 SavePageResult result; | 52 SavePageResult result; |
| 58 switch (archiver_result) { | 53 switch (archiver_result) { |
| 59 case ArchiverResult::SUCCESSFULLY_CREATED: | 54 case ArchiverResult::SUCCESSFULLY_CREATED: |
| 60 result = SavePageResult::SUCCESS; | 55 result = SavePageResult::SUCCESS; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 CHECK(base::CreateDirectory(archives_dir)); | 99 CHECK(base::CreateDirectory(archives_dir)); |
| 105 } | 100 } |
| 106 | 101 |
| 107 } // namespace | 102 } // namespace |
| 108 | 103 |
| 109 // static | 104 // static |
| 110 bool OfflinePageModel::CanSavePage(const GURL& url) { | 105 bool OfflinePageModel::CanSavePage(const GURL& url) { |
| 111 return url.SchemeIsHTTPOrHTTPS(); | 106 return url.SchemeIsHTTPOrHTTPS(); |
| 112 } | 107 } |
| 113 | 108 |
| 114 // static | |
| 115 base::TimeDelta OfflinePageModel::GetFinalDeletionDelayForTesting() { | |
| 116 return kFinalDeletionDelay; | |
| 117 } | |
| 118 | |
| 119 OfflinePageModel::OfflinePageModel( | 109 OfflinePageModel::OfflinePageModel( |
| 120 scoped_ptr<OfflinePageMetadataStore> store, | 110 scoped_ptr<OfflinePageMetadataStore> store, |
| 121 const base::FilePath& archives_dir, | 111 const base::FilePath& archives_dir, |
| 122 const scoped_refptr<base::SequencedTaskRunner>& task_runner) | 112 const scoped_refptr<base::SequencedTaskRunner>& task_runner) |
| 123 : store_(std::move(store)), | 113 : store_(std::move(store)), |
| 124 archives_dir_(archives_dir), | 114 archives_dir_(archives_dir), |
| 125 is_loaded_(false), | 115 is_loaded_(false), |
| 126 task_runner_(task_runner), | 116 task_runner_(task_runner), |
| 127 weak_ptr_factory_(this) { | 117 weak_ptr_factory_(this) { |
| 128 task_runner_->PostTaskAndReply( | 118 task_runner_->PostTaskAndReply( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 client_id, base::Time::Now(), callback)); | 157 client_id, base::Time::Now(), callback)); |
| 168 pending_archivers_.push_back(std::move(archiver)); | 158 pending_archivers_.push_back(std::move(archiver)); |
| 169 } | 159 } |
| 170 | 160 |
| 171 void OfflinePageModel::MarkPageAccessed(int64_t offline_id) { | 161 void OfflinePageModel::MarkPageAccessed(int64_t offline_id) { |
| 172 DCHECK(is_loaded_); | 162 DCHECK(is_loaded_); |
| 173 auto iter = offline_pages_.find(offline_id); | 163 auto iter = offline_pages_.find(offline_id); |
| 174 if (iter == offline_pages_.end()) | 164 if (iter == offline_pages_.end()) |
| 175 return; | 165 return; |
| 176 | 166 |
| 177 // MarkPageAccessed should not be called for a page that is being marked for | |
| 178 // deletion. | |
| 179 DCHECK(!iter->second.IsMarkedForDeletion()); | |
| 180 | |
| 181 // Make a copy of the cached item and update it. The cached item should only | 167 // Make a copy of the cached item and update it. The cached item should only |
| 182 // be updated upon the successful store operation. | 168 // be updated upon the successful store operation. |
| 183 OfflinePageItem offline_page_item = iter->second; | 169 OfflinePageItem offline_page_item = iter->second; |
| 184 | 170 |
| 185 base::Time now = base::Time::Now(); | 171 base::Time now = base::Time::Now(); |
| 186 base::TimeDelta time_since_last_accessed = | 172 base::TimeDelta time_since_last_accessed = |
| 187 now - offline_page_item.last_access_time; | 173 now - offline_page_item.last_access_time; |
| 188 | 174 |
| 189 // The last access time was set to same as creation time when the page was | 175 // The last access time was set to same as creation time when the page was |
| 190 // created. | 176 // created. |
| 191 if (offline_page_item.creation_time == offline_page_item.last_access_time) { | 177 if (offline_page_item.creation_time == offline_page_item.last_access_time) { |
| 192 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.FirstOpenSinceCreated", | 178 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.FirstOpenSinceCreated", |
| 193 time_since_last_accessed.InMinutes(), 1, | 179 time_since_last_accessed.InMinutes(), 1, |
| 194 kMaxOpenedPageHistogramBucket.InMinutes(), 50); | 180 kMaxOpenedPageHistogramBucket.InMinutes(), 50); |
| 195 } else { | 181 } else { |
| 196 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.OpenSinceLastOpen", | 182 UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.OpenSinceLastOpen", |
| 197 time_since_last_accessed.InMinutes(), 1, | 183 time_since_last_accessed.InMinutes(), 1, |
| 198 kMaxOpenedPageHistogramBucket.InMinutes(), 50); | 184 kMaxOpenedPageHistogramBucket.InMinutes(), 50); |
| 199 } | 185 } |
| 200 | 186 |
| 201 offline_page_item.last_access_time = now; | 187 offline_page_item.last_access_time = now; |
| 202 offline_page_item.access_count++; | 188 offline_page_item.access_count++; |
| 203 | 189 |
| 204 store_->AddOrUpdateOfflinePage( | 190 store_->AddOrUpdateOfflinePage( |
| 205 offline_page_item, | 191 offline_page_item, |
| 206 base::Bind(&OfflinePageModel::OnMarkPageAccesseDone, | 192 base::Bind(&OfflinePageModel::OnMarkPageAccesseDone, |
| 207 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); | 193 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); |
| 208 } | 194 } |
| 209 | 195 |
| 210 void OfflinePageModel::MarkPageForDeletion(int64_t offline_id, | |
| 211 const DeletePageCallback& callback) { | |
| 212 DCHECK(is_loaded_); | |
| 213 auto iter = offline_pages_.find(offline_id); | |
| 214 if (iter == offline_pages_.end()) { | |
| 215 InformDeletePageDone(callback, DeletePageResult::NOT_FOUND); | |
| 216 return; | |
| 217 } | |
| 218 | |
| 219 // Make a copy of the cached item and update it. The cached item should only | |
| 220 // be updated upon the successful store operation. | |
| 221 OfflinePageItem offline_page_item = iter->second; | |
| 222 offline_page_item.MarkForDeletion(); | |
| 223 store_->AddOrUpdateOfflinePage( | |
| 224 offline_page_item, | |
| 225 base::Bind(&OfflinePageModel::OnMarkPageForDeletionDone, | |
| 226 weak_ptr_factory_.GetWeakPtr(), offline_page_item, callback)); | |
| 227 } | |
| 228 | |
| 229 void OfflinePageModel::DeletePagesByOfflineId( | 196 void OfflinePageModel::DeletePagesByOfflineId( |
| 230 const std::vector<int64_t>& offline_ids, | 197 const std::vector<int64_t>& offline_ids, |
| 231 const DeletePageCallback& callback) { | 198 const DeletePageCallback& callback) { |
| 232 if (!is_loaded_) { | 199 if (!is_loaded_) { |
| 233 delayed_tasks_.push_back( | 200 delayed_tasks_.push_back( |
| 234 base::Bind(&OfflinePageModel::DoDeletePagesByOfflineId, | 201 base::Bind(&OfflinePageModel::DoDeletePagesByOfflineId, |
| 235 weak_ptr_factory_.GetWeakPtr(), offline_ids, callback)); | 202 weak_ptr_factory_.GetWeakPtr(), offline_ids, callback)); |
| 236 | 203 |
| 237 return; | 204 return; |
| 238 } | 205 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 DoDeletePagesByURLPredicate(predicate, callback); | 257 DoDeletePagesByURLPredicate(predicate, callback); |
| 291 } | 258 } |
| 292 | 259 |
| 293 void OfflinePageModel::DoDeletePagesByURLPredicate( | 260 void OfflinePageModel::DoDeletePagesByURLPredicate( |
| 294 const base::Callback<bool(const GURL&)>& predicate, | 261 const base::Callback<bool(const GURL&)>& predicate, |
| 295 const DeletePageCallback& callback) { | 262 const DeletePageCallback& callback) { |
| 296 DCHECK(is_loaded_); | 263 DCHECK(is_loaded_); |
| 297 | 264 |
| 298 std::vector<int64_t> offline_ids; | 265 std::vector<int64_t> offline_ids; |
| 299 for (const auto& id_page_pair : offline_pages_) { | 266 for (const auto& id_page_pair : offline_pages_) { |
| 300 if (!id_page_pair.second.IsMarkedForDeletion() && | 267 if (predicate.Run(id_page_pair.second.url)) |
| 301 predicate.Run(id_page_pair.second.url)) { | |
| 302 offline_ids.push_back(id_page_pair.first); | 268 offline_ids.push_back(id_page_pair.first); |
| 303 } | |
| 304 } | 269 } |
| 305 DoDeletePagesByOfflineId(offline_ids, callback); | 270 DoDeletePagesByOfflineId(offline_ids, callback); |
| 306 } | 271 } |
| 307 | 272 |
| 308 void OfflinePageModel::HasPages(const std::string& name_space, | 273 void OfflinePageModel::HasPages(const std::string& name_space, |
| 309 const HasPagesCallback& callback) { | 274 const HasPagesCallback& callback) { |
| 310 RunWhenLoaded(base::Bind(&OfflinePageModel::HasPagesAfterLoadDone, | 275 RunWhenLoaded(base::Bind(&OfflinePageModel::HasPagesAfterLoadDone, |
| 311 weak_ptr_factory_.GetWeakPtr(), name_space, | 276 weak_ptr_factory_.GetWeakPtr(), name_space, |
| 312 callback)); | 277 callback)); |
| 313 } | 278 } |
| 314 | 279 |
| 315 void OfflinePageModel::HasPagesAfterLoadDone( | 280 void OfflinePageModel::HasPagesAfterLoadDone( |
| 316 const std::string& name_space, | 281 const std::string& name_space, |
| 317 const HasPagesCallback& callback) const { | 282 const HasPagesCallback& callback) const { |
| 318 callback.Run(MaybeHasPages(name_space)); | 283 callback.Run(MaybeHasPages(name_space)); |
| 319 } | 284 } |
| 320 | 285 |
| 321 bool OfflinePageModel::MaybeHasPages(const std::string& name_space) const { | 286 bool OfflinePageModel::MaybeHasPages(const std::string& name_space) const { |
| 322 if (!is_loaded_) | 287 if (!is_loaded_) |
| 323 return false; | 288 return false; |
| 324 | 289 |
| 325 for (const auto& id_page_pair : offline_pages_) { | 290 for (const auto& id_page_pair : offline_pages_) { |
| 326 if (!id_page_pair.second.IsMarkedForDeletion() && | 291 if (id_page_pair.second.client_id.name_space == name_space) |
| 327 id_page_pair.second.client_id.name_space == name_space) { | |
| 328 return true; | 292 return true; |
| 329 } | |
| 330 } | 293 } |
| 331 | 294 |
| 332 return false; | 295 return false; |
| 333 } | 296 } |
| 334 | 297 |
| 335 void OfflinePageModel::GetAllPages(const GetAllPagesCallback& callback) { | 298 void OfflinePageModel::GetAllPages(const GetAllPagesCallback& callback) { |
| 336 if (!is_loaded_) { | 299 if (!is_loaded_) { |
| 337 delayed_tasks_.push_back( | 300 delayed_tasks_.push_back( |
| 338 base::Bind(&OfflinePageModel::GetAllPagesAfterLoadDone, | 301 base::Bind(&OfflinePageModel::GetAllPagesAfterLoadDone, |
| 339 weak_ptr_factory_.GetWeakPtr(), callback)); | 302 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 340 return; | 303 return; |
| 341 } | 304 } |
| 342 | 305 |
| 343 GetAllPagesAfterLoadDone(callback); | 306 GetAllPagesAfterLoadDone(callback); |
| 344 } | 307 } |
| 345 | 308 |
| 346 void OfflinePageModel::GetAllPagesAfterLoadDone( | 309 void OfflinePageModel::GetAllPagesAfterLoadDone( |
| 347 const GetAllPagesCallback& callback) { | 310 const GetAllPagesCallback& callback) { |
| 348 DCHECK(is_loaded_); | 311 DCHECK(is_loaded_); |
| 349 | 312 |
| 350 std::vector<OfflinePageItem> offline_pages; | 313 std::vector<OfflinePageItem> offline_pages; |
| 351 for (const auto& id_page_pair : offline_pages_) { | 314 for (const auto& id_page_pair : offline_pages_) |
| 352 if (id_page_pair.second.IsMarkedForDeletion()) | |
| 353 continue; | |
| 354 offline_pages.push_back(id_page_pair.second); | 315 offline_pages.push_back(id_page_pair.second); |
| 355 } | |
| 356 | 316 |
| 357 callback.Run(offline_pages); | 317 callback.Run(offline_pages); |
| 358 } | 318 } |
| 359 | 319 |
| 360 const std::vector<OfflinePageItem> OfflinePageModel::GetPagesToCleanUp() const { | 320 const std::vector<OfflinePageItem> OfflinePageModel::GetPagesToCleanUp() const { |
| 361 DCHECK(is_loaded_); | 321 DCHECK(is_loaded_); |
| 362 std::vector<OfflinePageItem> offline_pages; | 322 std::vector<OfflinePageItem> offline_pages; |
| 363 base::Time now = base::Time::Now(); | 323 base::Time now = base::Time::Now(); |
| 364 for (const auto& id_page_pair : offline_pages_) { | 324 for (const auto& id_page_pair : offline_pages_) { |
| 365 if (!id_page_pair.second.IsMarkedForDeletion() && | 325 if (now - id_page_pair.second.last_access_time > kPageCleanUpThreshold) |
| 366 now - id_page_pair.second.last_access_time > kPageCleanUpThreshold) { | |
| 367 offline_pages.push_back(id_page_pair.second); | 326 offline_pages.push_back(id_page_pair.second); |
| 368 } | |
| 369 } | 327 } |
| 370 return offline_pages; | 328 return offline_pages; |
| 371 } | 329 } |
| 372 | 330 |
| 331 // TODO(fgorski): Remove include_deleted, as it no longer makes sense. |
| 373 const std::vector<int64_t> OfflinePageModel::GetOfflineIdsForClientId( | 332 const std::vector<int64_t> OfflinePageModel::GetOfflineIdsForClientId( |
| 374 const ClientId& client_id, | 333 const ClientId& client_id, |
| 375 bool include_deleted) const { | 334 bool include_deleted) const { |
| 376 DCHECK(is_loaded_); | 335 DCHECK(is_loaded_); |
| 377 std::vector<int64_t> results; | 336 std::vector<int64_t> results; |
| 378 | 337 |
| 379 // We want only all pages, including those marked for deletion. | 338 // We want only all pages, including those marked for deletion. |
| 380 // TODO(bburns): actually use an index rather than linear scan. | 339 // TODO(bburns): actually use an index rather than linear scan. |
| 381 for (const auto& id_page_pair : offline_pages_) { | 340 for (const auto& id_page_pair : offline_pages_) { |
| 382 if (id_page_pair.second.client_id == client_id) { | 341 if (id_page_pair.second.client_id == client_id) |
| 383 if (include_deleted || !id_page_pair.second.IsMarkedForDeletion()) { | 342 results.push_back(id_page_pair.second.offline_id); |
| 384 results.push_back(id_page_pair.second.offline_id); | |
| 385 } | |
| 386 } | |
| 387 } | 343 } |
| 388 return results; | 344 return results; |
| 389 } | 345 } |
| 390 | 346 |
| 391 const OfflinePageItem* OfflinePageModel::GetPageByOfflineId( | 347 const OfflinePageItem* OfflinePageModel::GetPageByOfflineId( |
| 392 int64_t offline_id) const { | 348 int64_t offline_id) const { |
| 393 const auto iter = offline_pages_.find(offline_id); | 349 const auto iter = offline_pages_.find(offline_id); |
| 394 return iter != offline_pages_.end() && !iter->second.IsMarkedForDeletion() | 350 return iter != offline_pages_.end() ? &(iter->second) : nullptr; |
| 395 ? &(iter->second) | |
| 396 : nullptr; | |
| 397 } | 351 } |
| 398 | 352 |
| 399 const OfflinePageItem* OfflinePageModel::GetPageByOfflineURL( | 353 const OfflinePageItem* OfflinePageModel::GetPageByOfflineURL( |
| 400 const GURL& offline_url) const { | 354 const GURL& offline_url) const { |
| 401 for (auto iter = offline_pages_.begin(); | 355 for (const auto& id_page_pair : offline_pages_) { |
| 402 iter != offline_pages_.end(); | 356 if (id_page_pair.second.GetOfflineURL() == offline_url) |
| 403 ++iter) { | 357 return &(id_page_pair.second); |
| 404 if (iter->second.GetOfflineURL() == offline_url && | |
| 405 !iter->second.IsMarkedForDeletion()) { | |
| 406 return &(iter->second); | |
| 407 } | |
| 408 } | 358 } |
| 409 return nullptr; | 359 return nullptr; |
| 410 } | 360 } |
| 411 | 361 |
| 412 const OfflinePageItem* OfflinePageModel::GetPageByOnlineURL( | 362 const OfflinePageItem* OfflinePageModel::GetPageByOnlineURL( |
| 413 const GURL& online_url) const { | 363 const GURL& online_url) const { |
| 414 for (auto iter = offline_pages_.begin(); iter != offline_pages_.end(); | 364 for (const auto& id_page_pair : offline_pages_) { |
| 415 ++iter) { | 365 if (id_page_pair.second.url == online_url) |
| 416 if (iter->second.url == online_url && !iter->second.IsMarkedForDeletion()) | 366 return &(id_page_pair.second); |
| 417 return &(iter->second); | |
| 418 } | 367 } |
| 419 return nullptr; | 368 return nullptr; |
| 420 } | 369 } |
| 421 | 370 |
| 422 void OfflinePageModel::CheckForExternalFileDeletion() { | 371 void OfflinePageModel::CheckForExternalFileDeletion() { |
| 423 DCHECK(is_loaded_); | 372 DCHECK(is_loaded_); |
| 424 | 373 |
| 425 std::vector<std::pair<int64_t, base::FilePath>> id_path_pairs; | 374 std::vector<std::pair<int64_t, base::FilePath>> id_path_pairs; |
| 426 for (const auto& id_page_pair : offline_pages_) { | 375 for (const auto& id_page_pair : offline_pages_) { |
| 427 id_path_pairs.push_back( | 376 id_path_pairs.push_back( |
| 428 std::make_pair(id_page_pair.first, id_page_pair.second.file_path)); | 377 std::make_pair(id_page_pair.first, id_page_pair.second.file_path)); |
| 429 } | 378 } |
| 430 | 379 |
| 431 std::vector<int64_t>* ids_of_pages_missing_archive_file = | 380 std::vector<int64_t>* ids_of_pages_missing_archive_file = |
| 432 new std::vector<int64_t>(); | 381 new std::vector<int64_t>(); |
| 433 task_runner_->PostTaskAndReply( | 382 task_runner_->PostTaskAndReply( |
| 434 FROM_HERE, base::Bind(&FindPagesMissingArchiveFile, id_path_pairs, | 383 FROM_HERE, base::Bind(&FindPagesMissingArchiveFile, id_path_pairs, |
| 435 ids_of_pages_missing_archive_file), | 384 ids_of_pages_missing_archive_file), |
| 436 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile, | 385 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile, |
| 437 weak_ptr_factory_.GetWeakPtr(), | 386 weak_ptr_factory_.GetWeakPtr(), |
| 438 base::Owned(ids_of_pages_missing_archive_file))); | 387 base::Owned(ids_of_pages_missing_archive_file))); |
| 439 } | 388 } |
| 440 | 389 |
| 441 void OfflinePageModel::RecordStorageHistograms(int64_t total_space_bytes, | 390 void OfflinePageModel::RecordStorageHistograms(int64_t total_space_bytes, |
| 442 int64_t free_space_bytes, | 391 int64_t free_space_bytes, |
| 443 bool reporting_after_delete) { | 392 bool reporting_after_delete) { |
| 444 // Total space taken by offline pages. | 393 // Total space taken by offline pages. |
| 445 int64_t total_page_size = 0; | 394 int64_t total_page_size = 0; |
| 446 for (const auto& id_page_pair : offline_pages_) { | 395 for (const auto& id_page_pair : offline_pages_) { |
| 447 if (!id_page_pair.second.IsMarkedForDeletion()) | |
| 448 continue; | |
| 449 total_page_size += id_page_pair.second.file_size; | 396 total_page_size += id_page_pair.second.file_size; |
| 450 } | 397 } |
| 451 | 398 |
| 452 int total_page_size_mb = static_cast<int>(total_page_size / (1024 * 1024)); | 399 int total_page_size_mb = static_cast<int>(total_page_size / (1024 * 1024)); |
| 453 UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb); | 400 UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb); |
| 454 | 401 |
| 455 // How much of the total space the offline pages take. | 402 // How much of the total space the offline pages take. |
| 456 int total_page_size_percentage = | 403 int total_page_size_percentage = |
| 457 static_cast<int>(1.0 * total_page_size / total_space_bytes * 100); | 404 static_cast<int>(1.0 * total_page_size / total_space_bytes * 100); |
| 458 UMA_HISTOGRAM_PERCENTAGE("OfflinePages.TotalPageSizePercentage", | 405 UMA_HISTOGRAM_PERCENTAGE("OfflinePages.TotalPageSizePercentage", |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 void OfflinePageModel::OnMarkPageAccesseDone( | 481 void OfflinePageModel::OnMarkPageAccesseDone( |
| 535 const OfflinePageItem& offline_page_item, bool success) { | 482 const OfflinePageItem& offline_page_item, bool success) { |
| 536 // Update the item in the cache only upon success. | 483 // Update the item in the cache only upon success. |
| 537 if (success) | 484 if (success) |
| 538 offline_pages_[offline_page_item.offline_id] = offline_page_item; | 485 offline_pages_[offline_page_item.offline_id] = offline_page_item; |
| 539 | 486 |
| 540 // No need to fire OfflinePageModelChanged event since updating access info | 487 // No need to fire OfflinePageModelChanged event since updating access info |
| 541 // should not have any impact to the UI. | 488 // should not have any impact to the UI. |
| 542 } | 489 } |
| 543 | 490 |
| 544 void OfflinePageModel::OnMarkPageForDeletionDone( | |
| 545 const OfflinePageItem& offline_page_item, | |
| 546 const DeletePageCallback& callback, | |
| 547 bool success) { | |
| 548 // Update the item in the cache only upon success. | |
| 549 if (success) | |
| 550 offline_pages_[offline_page_item.offline_id] = offline_page_item; | |
| 551 | |
| 552 InformDeletePageDone(callback, success ? DeletePageResult::SUCCESS | |
| 553 : DeletePageResult::STORE_FAILURE); | |
| 554 | |
| 555 if (!success) | |
| 556 return; | |
| 557 | |
| 558 // Schedule to do the final deletion. | |
| 559 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 560 FROM_HERE, | |
| 561 base::Bind(&OfflinePageModel::FinalizePageDeletion, | |
| 562 weak_ptr_factory_.GetWeakPtr()), | |
| 563 kFinalDeletionDelay); | |
| 564 | |
| 565 FOR_EACH_OBSERVER(Observer, observers_, | |
| 566 OfflinePageDeleted(offline_page_item.offline_id, | |
| 567 offline_page_item.client_id)); | |
| 568 } | |
| 569 | |
| 570 void OfflinePageModel::OnUndoOfflinePageDone( | |
| 571 const OfflinePageItem& offline_page, bool success) { | |
| 572 if (!success) | |
| 573 return; | |
| 574 offline_pages_[offline_page.offline_id] = offline_page; | |
| 575 | |
| 576 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); | |
| 577 } | |
| 578 | |
| 579 void OfflinePageModel::FinalizePageDeletion() { | |
| 580 std::vector<int64_t> offline_ids_pending_deletion; | |
| 581 for (const auto& id_page_pair : offline_pages_) { | |
| 582 if (!id_page_pair.second.IsMarkedForDeletion()) | |
| 583 continue; | |
| 584 offline_ids_pending_deletion.push_back(id_page_pair.second.offline_id); | |
| 585 } | |
| 586 DeletePagesByOfflineId(offline_ids_pending_deletion, DeletePageCallback()); | |
| 587 } | |
| 588 | |
| 589 void OfflinePageModel::UndoPageDeletion(int64_t offline_id) { | |
| 590 auto iter = offline_pages_.find(offline_id); | |
| 591 if (iter == offline_pages_.end()) | |
| 592 return; | |
| 593 | |
| 594 // Make a copy of the cached item and update it. The cached item should only | |
| 595 // be updated upon the successful store operation. | |
| 596 OfflinePageItem offline_page_item = iter->second; | |
| 597 if (!offline_page_item.IsMarkedForDeletion()) | |
| 598 return; | |
| 599 | |
| 600 // Clear the flag to bring it back. | |
| 601 offline_page_item.ClearMarkForDeletion(); | |
| 602 store_->AddOrUpdateOfflinePage( | |
| 603 offline_page_item, | |
| 604 base::Bind(&OfflinePageModel::OnUndoOfflinePageDone, | |
| 605 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); | |
| 606 } | |
| 607 | |
| 608 void OfflinePageModel::OnEnsureArchivesDirCreatedDone() { | 491 void OfflinePageModel::OnEnsureArchivesDirCreatedDone() { |
| 609 store_->Load(base::Bind(&OfflinePageModel::OnLoadDone, | 492 store_->Load(base::Bind(&OfflinePageModel::OnLoadDone, |
| 610 weak_ptr_factory_.GetWeakPtr())); | 493 weak_ptr_factory_.GetWeakPtr())); |
| 611 } | 494 } |
| 612 | 495 |
| 613 void OfflinePageModel::OnLoadDone( | 496 void OfflinePageModel::OnLoadDone( |
| 614 OfflinePageMetadataStore::LoadStatus load_status, | 497 OfflinePageMetadataStore::LoadStatus load_status, |
| 615 const std::vector<OfflinePageItem>& offline_pages) { | 498 const std::vector<OfflinePageItem>& offline_pages) { |
| 616 DCHECK(!is_loaded_); | 499 DCHECK(!is_loaded_); |
| 617 is_loaded_ = true; | 500 is_loaded_ = true; |
| 618 | 501 |
| 619 // TODO(jianli): rebuild the store upon failure. | 502 // TODO(jianli): rebuild the store upon failure. |
| 620 | 503 |
| 621 if (load_status == OfflinePageMetadataStore::LOAD_SUCCEEDED) | 504 if (load_status == OfflinePageMetadataStore::LOAD_SUCCEEDED) |
| 622 CacheLoadedData(offline_pages); | 505 CacheLoadedData(offline_pages); |
| 623 | 506 |
| 624 // Run all the delayed tasks. | 507 // Run all the delayed tasks. |
| 625 for (const auto& delayed_task : delayed_tasks_) | 508 for (const auto& delayed_task : delayed_tasks_) |
| 626 delayed_task.Run(); | 509 delayed_task.Run(); |
| 627 delayed_tasks_.clear(); | 510 delayed_tasks_.clear(); |
| 628 | 511 |
| 629 // If there are pages that are marked for deletion, but not yet deleted and | |
| 630 // OfflinePageModel gets reloaded. Delete the pages now. | |
| 631 FinalizePageDeletion(); | |
| 632 | |
| 633 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this)); | 512 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this)); |
| 634 | 513 |
| 635 CheckForExternalFileDeletion(); | 514 CheckForExternalFileDeletion(); |
| 636 } | 515 } |
| 637 | 516 |
| 638 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback, | 517 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback, |
| 639 SavePageResult result, | 518 SavePageResult result, |
| 640 int64_t offline_id) { | 519 int64_t offline_id) { |
| 641 UMA_HISTOGRAM_ENUMERATION( | 520 UMA_HISTOGRAM_ENUMERATION( |
| 642 "OfflinePages.SavePageResult", | 521 "OfflinePages.SavePageResult", |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 "OfflinePages.DeletePage.LastOpenToCreated", | 575 "OfflinePages.DeletePage.LastOpenToCreated", |
| 697 (iter->second.last_access_time - iter->second.creation_time). | 576 (iter->second.last_access_time - iter->second.creation_time). |
| 698 InMinutes(), | 577 InMinutes(), |
| 699 1, | 578 1, |
| 700 base::TimeDelta::FromDays(365).InMinutes(), | 579 base::TimeDelta::FromDays(365).InMinutes(), |
| 701 100); | 580 100); |
| 702 UMA_HISTOGRAM_MEMORY_KB( | 581 UMA_HISTOGRAM_MEMORY_KB( |
| 703 "OfflinePages.DeletePage.PageSize", iter->second.file_size / 1024); | 582 "OfflinePages.DeletePage.PageSize", iter->second.file_size / 1024); |
| 704 UMA_HISTOGRAM_COUNTS( | 583 UMA_HISTOGRAM_COUNTS( |
| 705 "OfflinePages.DeletePage.AccessCount", iter->second.access_count); | 584 "OfflinePages.DeletePage.AccessCount", iter->second.access_count); |
| 706 // If the page is not marked for deletion at this point, the model has not | 585 FOR_EACH_OBSERVER( |
| 707 // yet informed the observer that the offline page is deleted. | 586 Observer, observers_, |
| 708 if (!iter->second.IsMarkedForDeletion()) { | 587 OfflinePageDeleted(iter->second.offline_id, iter->second.client_id)); |
| 709 FOR_EACH_OBSERVER( | |
| 710 Observer, observers_, | |
| 711 OfflinePageDeleted(iter->second.offline_id, iter->second.client_id)); | |
| 712 } | |
| 713 offline_pages_.erase(iter); | 588 offline_pages_.erase(iter); |
| 714 } | 589 } |
| 715 if (offline_ids.size() > 1) { | 590 if (offline_ids.size() > 1) { |
| 716 UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count", offline_ids.size()); | 591 UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count", offline_ids.size()); |
| 717 UMA_HISTOGRAM_MEMORY_KB( | 592 UMA_HISTOGRAM_MEMORY_KB( |
| 718 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); | 593 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); |
| 719 } | 594 } |
| 720 // Deleting multiple pages always succeeds when it gets to this point. | 595 // Deleting multiple pages always succeeds when it gets to this point. |
| 721 InformDeletePageDone(callback, (success || offline_ids.size() > 1) | 596 InformDeletePageDone(callback, (success || offline_ids.size() > 1) |
| 722 ? DeletePageResult::SUCCESS | 597 ? DeletePageResult::SUCCESS |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 const std::vector<OfflinePageItem>& offline_pages) { | 688 const std::vector<OfflinePageItem>& offline_pages) { |
| 814 offline_pages_.clear(); | 689 offline_pages_.clear(); |
| 815 for (const auto& offline_page : offline_pages) | 690 for (const auto& offline_page : offline_pages) |
| 816 offline_pages_[offline_page.offline_id] = offline_page; | 691 offline_pages_[offline_page.offline_id] = offline_page; |
| 817 } | 692 } |
| 818 | 693 |
| 819 int64_t OfflinePageModel::GenerateOfflineId() { | 694 int64_t OfflinePageModel::GenerateOfflineId() { |
| 820 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; | 695 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; |
| 821 } | 696 } |
| 822 | 697 |
| 823 void OfflinePageModel::MarkPagesForDeletion( | |
| 824 const std::vector<int64_t>& offline_ids, | |
| 825 const DeletePageCallback& callback) { | |
| 826 if (!is_loaded_) { | |
| 827 for (size_t i = 0; i < offline_ids.size(); i++) { | |
| 828 delayed_tasks_.push_back( | |
| 829 base::Bind(&OfflinePageModel::MarkPageForDeletion, | |
| 830 weak_ptr_factory_.GetWeakPtr(), offline_ids[i], callback)); | |
| 831 } | |
| 832 return; | |
| 833 } | |
| 834 for (const auto& id : offline_ids) { | |
| 835 MarkPageForDeletion(id, callback); | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 void OfflinePageModel::RunWhenLoaded(const base::Closure& task) { | 698 void OfflinePageModel::RunWhenLoaded(const base::Closure& task) { |
| 840 if (!is_loaded_) { | 699 if (!is_loaded_) { |
| 841 delayed_tasks_.push_back(task); | 700 delayed_tasks_.push_back(task); |
| 842 return; | 701 return; |
| 843 } | 702 } |
| 844 | 703 |
| 845 task_runner_->PostTask(FROM_HERE, task); | 704 task_runner_->PostTask(FROM_HERE, task); |
| 846 } | 705 } |
| 847 | 706 |
| 848 } // namespace offline_pages | 707 } // namespace offline_pages |
| OLD | NEW |