Chromium Code Reviews| 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" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/rand_util.h" | |
| 15 #include "base/sequenced_task_runner.h" | 16 #include "base/sequenced_task_runner.h" |
| 17 #include "base/strings/string_number_conversions.h" | |
| 16 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| 17 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 18 #include "components/bookmarks/browser/bookmark_model.h" | 20 #include "components/bookmarks/browser/bookmark_model.h" |
| 19 #include "components/bookmarks/browser/bookmark_node.h" | 21 #include "components/bookmarks/browser/bookmark_node.h" |
| 20 #include "components/offline_pages/offline_page_item.h" | 22 #include "components/offline_pages/offline_page_item.h" |
| 23 #include "components/offline_pages/proto/offline_pages.pb.h" | |
| 21 #include "url/gurl.h" | 24 #include "url/gurl.h" |
| 22 | 25 |
| 23 using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult; | 26 using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult; |
| 24 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult; | 27 using SavePageResult = offline_pages::OfflinePageModel::SavePageResult; |
| 25 | 28 |
| 26 namespace offline_pages { | 29 namespace offline_pages { |
| 27 | 30 |
| 28 namespace { | 31 namespace { |
| 29 | 32 |
| 30 // This enum is used in an UMA histogram. Hence the entries here shouldn't | 33 // This enum is used in an UMA histogram. Hence the entries here shouldn't |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 | 150 |
| 148 void OfflinePageModel::AddObserver(Observer* observer) { | 151 void OfflinePageModel::AddObserver(Observer* observer) { |
| 149 observers_.AddObserver(observer); | 152 observers_.AddObserver(observer); |
| 150 } | 153 } |
| 151 | 154 |
| 152 void OfflinePageModel::RemoveObserver(Observer* observer) { | 155 void OfflinePageModel::RemoveObserver(Observer* observer) { |
| 153 observers_.RemoveObserver(observer); | 156 observers_.RemoveObserver(observer); |
| 154 } | 157 } |
| 155 | 158 |
| 156 void OfflinePageModel::SavePage(const GURL& url, | 159 void OfflinePageModel::SavePage(const GURL& url, |
| 157 int64_t bookmark_id, | 160 const ClientId& client_id, |
| 158 scoped_ptr<OfflinePageArchiver> archiver, | 161 scoped_ptr<OfflinePageArchiver> archiver, |
| 159 const SavePageCallback& callback) { | 162 const SavePageCallback& callback) { |
| 160 DCHECK(is_loaded_); | 163 DCHECK(is_loaded_); |
| 161 | 164 |
| 162 // Skip saving the page that is not intended to be saved, like local file | 165 // Skip saving the page that is not intended to be saved, like local file |
| 163 // page. | 166 // page. |
| 164 if (!CanSavePage(url)) { | 167 if (!CanSavePage(url)) { |
| 165 InformSavePageDone(callback, SavePageResult::SKIPPED); | 168 InformSavePageDone(callback, SavePageResult::SKIPPED, INVALID_OFFLINE_ID); |
| 166 return; | 169 return; |
| 167 } | 170 } |
| 168 | 171 |
| 169 DCHECK(archiver.get()); | 172 DCHECK(archiver.get()); |
| 170 archiver->CreateArchive(archives_dir_, | 173 |
| 171 base::Bind(&OfflinePageModel::OnCreateArchiveDone, | 174 int64_t offline_id = GenerateOfflineId(); |
| 172 weak_ptr_factory_.GetWeakPtr(), url, | 175 |
| 173 bookmark_id, base::Time::Now(), callback)); | 176 archiver->CreateArchive( |
| 177 archives_dir_, base::Bind(&OfflinePageModel::OnCreateArchiveDone, | |
| 178 weak_ptr_factory_.GetWeakPtr(), url, offline_id, | |
| 179 client_id, base::Time::Now(), callback)); | |
| 174 pending_archivers_.push_back(std::move(archiver)); | 180 pending_archivers_.push_back(std::move(archiver)); |
| 175 } | 181 } |
| 176 | 182 |
| 177 void OfflinePageModel::MarkPageAccessed(int64_t bookmark_id) { | 183 void OfflinePageModel::MarkPageAccessed(int64_t offline_id) { |
| 178 DCHECK(is_loaded_); | 184 DCHECK(is_loaded_); |
| 179 auto iter = offline_pages_.find(bookmark_id); | 185 auto iter = offline_pages_.find(offline_id); |
| 180 if (iter == offline_pages_.end()) | 186 if (iter == offline_pages_.end()) |
| 181 return; | 187 return; |
| 182 | 188 |
| 183 // MarkPageAccessed should not be called for a page that is being marked for | 189 // MarkPageAccessed should not be called for a page that is being marked for |
| 184 // deletion. | 190 // deletion. |
| 185 DCHECK(!iter->second.IsMarkedForDeletion()); | 191 DCHECK(!iter->second.IsMarkedForDeletion()); |
| 186 | 192 |
| 187 // Make a copy of the cached item and update it. The cached item should only | 193 // Make a copy of the cached item and update it. The cached item should only |
| 188 // be updated upon the successful store operation. | 194 // be updated upon the successful store operation. |
| 189 OfflinePageItem offline_page_item = iter->second; | 195 OfflinePageItem offline_page_item = iter->second; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 206 | 212 |
| 207 offline_page_item.last_access_time = now; | 213 offline_page_item.last_access_time = now; |
| 208 offline_page_item.access_count++; | 214 offline_page_item.access_count++; |
| 209 | 215 |
| 210 store_->AddOrUpdateOfflinePage( | 216 store_->AddOrUpdateOfflinePage( |
| 211 offline_page_item, | 217 offline_page_item, |
| 212 base::Bind(&OfflinePageModel::OnMarkPageAccesseDone, | 218 base::Bind(&OfflinePageModel::OnMarkPageAccesseDone, |
| 213 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); | 219 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); |
| 214 } | 220 } |
| 215 | 221 |
| 216 void OfflinePageModel::MarkPageForDeletion(int64_t bookmark_id, | 222 void OfflinePageModel::MarkPageForDeletion(int64_t offline_id, |
| 217 const DeletePageCallback& callback) { | 223 const DeletePageCallback& callback) { |
| 218 DCHECK(is_loaded_); | 224 DCHECK(is_loaded_); |
| 219 auto iter = offline_pages_.find(bookmark_id); | 225 auto iter = offline_pages_.find(offline_id); |
| 220 if (iter == offline_pages_.end()) { | 226 if (iter == offline_pages_.end()) { |
| 221 InformDeletePageDone(callback, DeletePageResult::NOT_FOUND); | 227 InformDeletePageDone(callback, DeletePageResult::NOT_FOUND); |
| 222 return; | 228 return; |
| 223 } | 229 } |
| 224 | 230 |
| 225 // Make a copy of the cached item and update it. The cached item should only | 231 // Make a copy of the cached item and update it. The cached item should only |
| 226 // be updated upon the successful store operation. | 232 // be updated upon the successful store operation. |
| 227 OfflinePageItem offline_page_item = iter->second; | 233 OfflinePageItem offline_page_item = iter->second; |
| 228 offline_page_item.MarkForDeletion(); | 234 offline_page_item.MarkForDeletion(); |
| 229 store_->AddOrUpdateOfflinePage( | 235 store_->AddOrUpdateOfflinePage( |
| 230 offline_page_item, | 236 offline_page_item, |
| 231 base::Bind(&OfflinePageModel::OnMarkPageForDeletionDone, | 237 base::Bind(&OfflinePageModel::OnMarkPageForDeletionDone, |
| 232 weak_ptr_factory_.GetWeakPtr(), offline_page_item, callback)); | 238 weak_ptr_factory_.GetWeakPtr(), offline_page_item, callback)); |
| 233 } | 239 } |
| 234 | 240 |
| 235 void OfflinePageModel::DeletePageByBookmarkId( | 241 void OfflinePageModel::DeletePageByOfflineId( |
| 236 int64_t bookmark_id, | 242 int64_t offline_id, |
| 237 const DeletePageCallback& callback) { | 243 const DeletePageCallback& callback) { |
| 238 DCHECK(is_loaded_); | 244 DCHECK(is_loaded_); |
| 239 std::vector<int64_t> bookmark_ids_to_delete; | 245 std::vector<int64_t> offline_ids_to_delete; |
| 240 bookmark_ids_to_delete.push_back(bookmark_id); | 246 offline_ids_to_delete.push_back(offline_id); |
| 241 DeletePagesByBookmarkId(bookmark_ids_to_delete, callback); | 247 DeletePagesByOfflineId(offline_ids_to_delete, callback); |
| 242 } | 248 } |
| 243 | 249 |
| 244 void OfflinePageModel::DeletePagesByBookmarkId( | 250 void OfflinePageModel::DeletePagesByOfflineId( |
| 245 const std::vector<int64_t>& bookmark_ids, | 251 const std::vector<int64_t>& offline_ids, |
| 246 const DeletePageCallback& callback) { | 252 const DeletePageCallback& callback) { |
| 247 DCHECK(is_loaded_); | 253 DCHECK(is_loaded_); |
| 248 | 254 |
| 249 std::vector<base::FilePath> paths_to_delete; | 255 std::vector<base::FilePath> paths_to_delete; |
| 250 for (const auto& bookmark_id : bookmark_ids) { | 256 for (const auto& offline_id : offline_ids) { |
| 251 auto iter = offline_pages_.find(bookmark_id); | 257 auto iter = offline_pages_.find(offline_id); |
| 252 if (iter != offline_pages_.end()) { | 258 if (iter != offline_pages_.end()) { |
| 253 paths_to_delete.push_back(iter->second.file_path); | 259 paths_to_delete.push_back(iter->second.file_path); |
| 254 } | 260 } |
| 255 } | 261 } |
| 256 | 262 |
| 257 if (paths_to_delete.empty()) { | 263 if (paths_to_delete.empty()) { |
| 258 InformDeletePageDone(callback, DeletePageResult::NOT_FOUND); | 264 InformDeletePageDone(callback, DeletePageResult::NOT_FOUND); |
| 259 return; | 265 return; |
| 260 } | 266 } |
| 261 | 267 |
| 262 bool* success = new bool(false); | 268 bool* success = new bool(false); |
| 263 task_runner_->PostTaskAndReply( | 269 task_runner_->PostTaskAndReply( |
| 264 FROM_HERE, | 270 FROM_HERE, base::Bind(&DeleteArchiveFiles, paths_to_delete, success), |
| 265 base::Bind(&DeleteArchiveFiles, paths_to_delete, success), | |
| 266 base::Bind(&OfflinePageModel::OnDeleteArchiveFilesDone, | 271 base::Bind(&OfflinePageModel::OnDeleteArchiveFilesDone, |
| 267 weak_ptr_factory_.GetWeakPtr(), | 272 weak_ptr_factory_.GetWeakPtr(), offline_ids, callback, |
| 268 bookmark_ids, | |
| 269 callback, | |
| 270 base::Owned(success))); | 273 base::Owned(success))); |
| 271 } | 274 } |
| 272 | 275 |
| 273 void OfflinePageModel::ClearAll(const base::Closure& callback) { | 276 void OfflinePageModel::ClearAll(const base::Closure& callback) { |
| 274 DCHECK(is_loaded_); | 277 DCHECK(is_loaded_); |
| 275 | 278 |
| 276 std::vector<int64_t> bookmark_ids; | 279 std::vector<int64_t> offline_ids; |
| 277 for (const auto& id_page_pair : offline_pages_) | 280 for (const auto& id_page_pair : offline_pages_) |
| 278 bookmark_ids.push_back(id_page_pair.first); | 281 offline_ids.push_back(id_page_pair.first); |
| 279 DeletePagesByBookmarkId( | 282 DeletePagesByOfflineId( |
| 280 bookmark_ids, | 283 offline_ids, |
| 281 base::Bind(&OfflinePageModel::OnRemoveAllFilesDoneForClearAll, | 284 base::Bind(&OfflinePageModel::OnRemoveAllFilesDoneForClearAll, |
| 282 weak_ptr_factory_.GetWeakPtr(), | 285 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 283 callback)); | |
| 284 } | 286 } |
| 285 | 287 |
| 286 bool OfflinePageModel::HasOfflinePages() const { | 288 bool OfflinePageModel::HasOfflinePages() const { |
| 287 DCHECK(is_loaded_); | 289 DCHECK(is_loaded_); |
| 288 // Check that at least one page is not marked for deletion. Because we have | 290 // Check that at least one page is not marked for deletion. Because we have |
| 289 // pages marked for deletion, we cannot simply invert result of |empty()|. | 291 // pages marked for deletion, we cannot simply invert result of |empty()|. |
| 290 for (const auto& id_page_pair : offline_pages_) { | 292 for (const auto& id_page_pair : offline_pages_) { |
| 291 if (!id_page_pair.second.IsMarkedForDeletion()) | 293 if (!id_page_pair.second.IsMarkedForDeletion()) |
| 292 return true; | 294 return true; |
| 293 } | 295 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 311 base::Time now = base::Time::Now(); | 313 base::Time now = base::Time::Now(); |
| 312 for (const auto& id_page_pair : offline_pages_) { | 314 for (const auto& id_page_pair : offline_pages_) { |
| 313 if (!id_page_pair.second.IsMarkedForDeletion() && | 315 if (!id_page_pair.second.IsMarkedForDeletion() && |
| 314 now - id_page_pair.second.last_access_time > kPageCleanUpThreshold) { | 316 now - id_page_pair.second.last_access_time > kPageCleanUpThreshold) { |
| 315 offline_pages.push_back(id_page_pair.second); | 317 offline_pages.push_back(id_page_pair.second); |
| 316 } | 318 } |
| 317 } | 319 } |
| 318 return offline_pages; | 320 return offline_pages; |
| 319 } | 321 } |
| 320 | 322 |
| 321 const OfflinePageItem* OfflinePageModel::GetPageByBookmarkId( | 323 const std::vector<int64_t> OfflinePageModel::GetOfflineIdsForClientId( |
| 322 int64_t bookmark_id) const { | 324 const ClientId& cid) const { |
| 323 const auto iter = offline_pages_.find(bookmark_id); | 325 std::vector<int64_t> results; |
| 326 | |
| 327 // TODO(bburns): actually use an index rather than linear scan. | |
| 328 const std::vector<OfflinePageItem> offline_pages = GetAllPages(); | |
| 329 | |
| 330 for (size_t i = 0; i < offline_pages.size(); i++) { | |
| 331 if (offline_pages[i].client_id.name_space == cid.name_space && | |
|
fgorski
2016/02/26 19:29:22
Use client_id equals operator defined here:
https:
bburns
2016/02/27 00:48:19
Done.
| |
| 332 offline_pages[i].client_id.id == cid.id) { | |
| 333 results.push_back(offline_pages[i].offline_id); | |
| 334 } | |
| 335 } | |
| 336 return results; | |
| 337 } | |
| 338 | |
| 339 const OfflinePageItem* OfflinePageModel::GetPageByOfflineId( | |
| 340 int64_t offline_id) const { | |
| 341 const auto iter = offline_pages_.find(offline_id); | |
| 324 return iter != offline_pages_.end() && !iter->second.IsMarkedForDeletion() | 342 return iter != offline_pages_.end() && !iter->second.IsMarkedForDeletion() |
| 325 ? &(iter->second) | 343 ? &(iter->second) |
| 326 : nullptr; | 344 : nullptr; |
| 327 } | 345 } |
| 328 | 346 |
| 329 const OfflinePageItem* OfflinePageModel::GetPageByOfflineURL( | 347 const OfflinePageItem* OfflinePageModel::GetPageByOfflineURL( |
| 330 const GURL& offline_url) const { | 348 const GURL& offline_url) const { |
| 331 for (auto iter = offline_pages_.begin(); | 349 for (auto iter = offline_pages_.begin(); |
| 332 iter != offline_pages_.end(); | 350 iter != offline_pages_.end(); |
| 333 ++iter) { | 351 ++iter) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile, | 384 base::Bind(&OfflinePageModel::OnFindPagesMissingArchiveFile, |
| 367 weak_ptr_factory_.GetWeakPtr(), | 385 weak_ptr_factory_.GetWeakPtr(), |
| 368 base::Owned(ids_of_pages_missing_archive_file))); | 386 base::Owned(ids_of_pages_missing_archive_file))); |
| 369 } | 387 } |
| 370 | 388 |
| 371 OfflinePageMetadataStore* OfflinePageModel::GetStoreForTesting() { | 389 OfflinePageMetadataStore* OfflinePageModel::GetStoreForTesting() { |
| 372 return store_.get(); | 390 return store_.get(); |
| 373 } | 391 } |
| 374 | 392 |
| 375 void OfflinePageModel::OnCreateArchiveDone(const GURL& requested_url, | 393 void OfflinePageModel::OnCreateArchiveDone(const GURL& requested_url, |
| 376 int64_t bookmark_id, | 394 int64_t offline_id, |
| 395 const ClientId& client_id, | |
| 377 const base::Time& start_time, | 396 const base::Time& start_time, |
| 378 const SavePageCallback& callback, | 397 const SavePageCallback& callback, |
| 379 OfflinePageArchiver* archiver, | 398 OfflinePageArchiver* archiver, |
| 380 ArchiverResult archiver_result, | 399 ArchiverResult archiver_result, |
| 381 const GURL& url, | 400 const GURL& url, |
| 382 const base::FilePath& file_path, | 401 const base::FilePath& file_path, |
| 383 int64_t file_size) { | 402 int64_t file_size) { |
| 384 if (requested_url != url) { | 403 if (requested_url != url) { |
| 385 DVLOG(1) << "Saved URL does not match requested URL."; | 404 DVLOG(1) << "Saved URL does not match requested URL."; |
| 386 // TODO(fgorski): We have created an archive for a wrong URL. It should be | 405 // TODO(fgorski): We have created an archive for a wrong URL. It should be |
| 387 // deleted from here, once archiver has the right functionality. | 406 // deleted from here, once archiver has the right functionality. |
| 388 InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED); | 407 InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED, |
| 408 offline_id); | |
| 389 DeletePendingArchiver(archiver); | 409 DeletePendingArchiver(archiver); |
| 390 return; | 410 return; |
| 391 } | 411 } |
| 392 | 412 |
| 393 if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) { | 413 if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) { |
| 394 SavePageResult result = ToSavePageResult(archiver_result); | 414 SavePageResult result = ToSavePageResult(archiver_result); |
| 395 InformSavePageDone(callback, result); | 415 InformSavePageDone(callback, result, offline_id); |
| 396 DeletePendingArchiver(archiver); | 416 DeletePendingArchiver(archiver); |
| 397 return; | 417 return; |
| 398 } | 418 } |
| 399 | 419 OfflinePageItem offline_page_item(url, offline_id, client_id, file_path, |
| 400 OfflinePageItem offline_page_item(url, bookmark_id, file_path, file_size, | 420 file_size, start_time); |
| 401 start_time); | |
| 402 store_->AddOrUpdateOfflinePage( | 421 store_->AddOrUpdateOfflinePage( |
| 403 offline_page_item, | 422 offline_page_item, |
| 404 base::Bind(&OfflinePageModel::OnAddOfflinePageDone, | 423 base::Bind(&OfflinePageModel::OnAddOfflinePageDone, |
| 405 weak_ptr_factory_.GetWeakPtr(), archiver, callback, | 424 weak_ptr_factory_.GetWeakPtr(), archiver, callback, |
| 406 offline_page_item)); | 425 offline_page_item)); |
| 407 } | 426 } |
| 408 | 427 |
| 409 void OfflinePageModel::OnAddOfflinePageDone(OfflinePageArchiver* archiver, | 428 void OfflinePageModel::OnAddOfflinePageDone(OfflinePageArchiver* archiver, |
| 410 const SavePageCallback& callback, | 429 const SavePageCallback& callback, |
| 411 const OfflinePageItem& offline_page, | 430 const OfflinePageItem& offline_page, |
| 412 bool success) { | 431 bool success) { |
| 413 SavePageResult result; | 432 SavePageResult result; |
| 414 if (success) { | 433 if (success) { |
| 415 offline_pages_[offline_page.bookmark_id] = offline_page; | 434 offline_pages_[offline_page.offline_id] = offline_page; |
| 416 result = SavePageResult::SUCCESS; | 435 result = SavePageResult::SUCCESS; |
| 417 UMA_HISTOGRAM_TIMES( | 436 UMA_HISTOGRAM_TIMES( |
| 418 "OfflinePages.SavePageTime", | 437 "OfflinePages.SavePageTime", |
| 419 base::Time::Now() - offline_page.creation_time); | 438 base::Time::Now() - offline_page.creation_time); |
| 420 UMA_HISTOGRAM_MEMORY_KB( | 439 UMA_HISTOGRAM_MEMORY_KB( |
| 421 "OfflinePages.PageSize", offline_page.file_size / 1024); | 440 "OfflinePages.PageSize", offline_page.file_size / 1024); |
| 422 } else { | 441 } else { |
| 423 result = SavePageResult::STORE_FAILURE; | 442 result = SavePageResult::STORE_FAILURE; |
| 424 } | 443 } |
| 425 InformSavePageDone(callback, result); | 444 InformSavePageDone(callback, result, offline_page.offline_id); |
| 426 DeletePendingArchiver(archiver); | 445 DeletePendingArchiver(archiver); |
| 427 | 446 |
| 428 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); | 447 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); |
| 429 } | 448 } |
| 430 | 449 |
| 431 void OfflinePageModel::OnMarkPageAccesseDone( | 450 void OfflinePageModel::OnMarkPageAccesseDone( |
| 432 const OfflinePageItem& offline_page_item, bool success) { | 451 const OfflinePageItem& offline_page_item, bool success) { |
| 433 // Update the item in the cache only upon success. | 452 // Update the item in the cache only upon success. |
| 434 if (success) | 453 if (success) |
| 435 offline_pages_[offline_page_item.bookmark_id] = offline_page_item; | 454 offline_pages_[offline_page_item.offline_id] = offline_page_item; |
| 436 | 455 |
| 437 // No need to fire OfflinePageModelChanged event since updating access info | 456 // No need to fire OfflinePageModelChanged event since updating access info |
| 438 // should not have any impact to the UI. | 457 // should not have any impact to the UI. |
| 439 } | 458 } |
| 440 | 459 |
| 441 void OfflinePageModel::OnMarkPageForDeletionDone( | 460 void OfflinePageModel::OnMarkPageForDeletionDone( |
| 442 const OfflinePageItem& offline_page_item, | 461 const OfflinePageItem& offline_page_item, |
| 443 const DeletePageCallback& callback, | 462 const DeletePageCallback& callback, |
| 444 bool success) { | 463 bool success) { |
| 445 // Update the item in the cache only upon success. | 464 // Update the item in the cache only upon success. |
| 446 if (success) | 465 if (success) |
| 447 offline_pages_[offline_page_item.bookmark_id] = offline_page_item; | 466 offline_pages_[offline_page_item.offline_id] = offline_page_item; |
| 448 | 467 |
| 449 InformDeletePageDone(callback, success ? DeletePageResult::SUCCESS | 468 InformDeletePageDone(callback, success ? DeletePageResult::SUCCESS |
| 450 : DeletePageResult::STORE_FAILURE); | 469 : DeletePageResult::STORE_FAILURE); |
| 451 | 470 |
| 452 if (!success) | 471 if (!success) |
| 453 return; | 472 return; |
| 454 | 473 |
| 455 // Schedule to do the final deletion. | 474 // Schedule to do the final deletion. |
| 456 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 475 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 457 FROM_HERE, | 476 FROM_HERE, |
| 458 base::Bind(&OfflinePageModel::FinalizePageDeletion, | 477 base::Bind(&OfflinePageModel::FinalizePageDeletion, |
| 459 weak_ptr_factory_.GetWeakPtr()), | 478 weak_ptr_factory_.GetWeakPtr()), |
| 460 kFinalDeletionDelay); | 479 kFinalDeletionDelay); |
| 461 | 480 |
| 462 FOR_EACH_OBSERVER( | 481 FOR_EACH_OBSERVER(Observer, observers_, |
| 463 Observer, observers_, OfflinePageDeleted(offline_page_item.bookmark_id)); | 482 OfflinePageDeleted(offline_page_item.offline_id)); |
| 464 } | 483 } |
| 465 | 484 |
| 466 void OfflinePageModel::OnUndoOfflinePageDone( | 485 void OfflinePageModel::OnUndoOfflinePageDone( |
| 467 const OfflinePageItem& offline_page, bool success) { | 486 const OfflinePageItem& offline_page, bool success) { |
| 468 if (!success) | 487 if (!success) |
| 469 return; | 488 return; |
| 470 offline_pages_[offline_page.bookmark_id] = offline_page; | 489 offline_pages_[offline_page.offline_id] = offline_page; |
| 471 | 490 |
| 472 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); | 491 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); |
| 473 } | 492 } |
| 474 | 493 |
| 475 void OfflinePageModel::FinalizePageDeletion() { | 494 void OfflinePageModel::FinalizePageDeletion() { |
| 476 std::vector<int64_t> bookmark_ids_pending_deletion; | 495 std::vector<int64_t> offline_ids_pending_deletion; |
| 477 for (const auto& id_page_pair : offline_pages_) { | 496 for (const auto& id_page_pair : offline_pages_) { |
| 478 if (!id_page_pair.second.IsMarkedForDeletion()) | 497 if (!id_page_pair.second.IsMarkedForDeletion()) |
| 479 continue; | 498 continue; |
| 480 bookmark_ids_pending_deletion.push_back(id_page_pair.second.bookmark_id); | 499 offline_ids_pending_deletion.push_back(id_page_pair.second.offline_id); |
| 481 } | 500 } |
| 482 DeletePagesByBookmarkId(bookmark_ids_pending_deletion, DeletePageCallback()); | 501 DeletePagesByOfflineId(offline_ids_pending_deletion, DeletePageCallback()); |
| 483 } | 502 } |
| 484 | 503 |
| 485 void OfflinePageModel::UndoPageDeletion(int64_t bookmark_id) { | 504 void OfflinePageModel::UndoPageDeletion(int64_t offline_id) { |
| 486 auto iter = offline_pages_.find(bookmark_id); | 505 auto iter = offline_pages_.find(offline_id); |
| 487 if (iter == offline_pages_.end()) | 506 if (iter == offline_pages_.end()) |
| 488 return; | 507 return; |
| 489 | 508 |
| 490 // Make a copy of the cached item and update it. The cached item should only | 509 // Make a copy of the cached item and update it. The cached item should only |
| 491 // be updated upon the successful store operation. | 510 // be updated upon the successful store operation. |
| 492 OfflinePageItem offline_page_item = iter->second; | 511 OfflinePageItem offline_page_item = iter->second; |
| 493 if (!offline_page_item.IsMarkedForDeletion()) | 512 if (!offline_page_item.IsMarkedForDeletion()) |
| 494 return; | 513 return; |
| 495 | 514 |
| 496 // Clear the flag to bring it back. | 515 // Clear the flag to bring it back. |
| 497 offline_page_item.ClearMarkForDeletion(); | 516 offline_page_item.ClearMarkForDeletion(); |
| 498 store_->AddOrUpdateOfflinePage( | 517 store_->AddOrUpdateOfflinePage( |
| 499 offline_page_item, | 518 offline_page_item, |
| 500 base::Bind(&OfflinePageModel::OnUndoOfflinePageDone, | 519 base::Bind(&OfflinePageModel::OnUndoOfflinePageDone, |
| 501 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); | 520 weak_ptr_factory_.GetWeakPtr(), offline_page_item)); |
| 502 } | 521 } |
| 503 | 522 |
| 504 void OfflinePageModel::BookmarkModelChanged() { | 523 void OfflinePageModel::BookmarkModelChanged() { |
| 505 } | 524 } |
| 506 | 525 |
| 507 void OfflinePageModel::BookmarkNodeAdded(bookmarks::BookmarkModel* model, | 526 void OfflinePageModel::BookmarkNodeAdded(bookmarks::BookmarkModel* model, |
| 508 const bookmarks::BookmarkNode* parent, | 527 const bookmarks::BookmarkNode* parent, |
| 509 int index) { | 528 int index) { |
| 510 const bookmarks::BookmarkNode* node = parent->GetChild(index); | 529 const bookmarks::BookmarkNode* node = parent->GetChild(index); |
| 511 DCHECK(node); | 530 DCHECK(node); |
| 512 UndoPageDeletion(node->id()); | 531 ClientId cid; |
| 532 cid.name_space = BOOKMARK_NAMESPACE; | |
| 533 cid.id = base::Int64ToString(node->id()); | |
| 534 std::vector<int64_t> ids = GetOfflineIdsForClientId(cid); | |
| 535 for (size_t i = 0; i < ids.size(); i++) { | |
| 536 UndoPageDeletion(ids[i]); | |
| 537 } | |
| 513 } | 538 } |
| 514 | 539 |
| 515 void OfflinePageModel::BookmarkNodeRemoved( | 540 void OfflinePageModel::BookmarkNodeRemoved( |
| 516 bookmarks::BookmarkModel* model, | 541 bookmarks::BookmarkModel* model, |
| 517 const bookmarks::BookmarkNode* parent, | 542 const bookmarks::BookmarkNode* parent, |
| 518 int old_index, | 543 int old_index, |
| 519 const bookmarks::BookmarkNode* node, | 544 const bookmarks::BookmarkNode* node, |
| 520 const std::set<GURL>& removed_urls) { | 545 const std::set<GURL>& removed_urls) { |
| 546 ClientId cid; | |
| 547 cid.name_space = BOOKMARK_NAMESPACE; | |
| 548 cid.id = base::Int64ToString(node->id()); | |
| 549 std::vector<int64_t> ids = GetOfflineIdsForClientId(cid); | |
| 521 if (!is_loaded_) { | 550 if (!is_loaded_) { |
| 522 delayed_tasks_.push_back( | 551 for (size_t i = 0; i < ids.size(); i++) { |
| 523 base::Bind(&OfflinePageModel::MarkPageForDeletion, | 552 delayed_tasks_.push_back( |
| 524 weak_ptr_factory_.GetWeakPtr(), | 553 base::Bind(&OfflinePageModel::MarkPageForDeletion, |
| 525 node->id(), | 554 weak_ptr_factory_.GetWeakPtr(), ids[i], |
| 526 base::Bind(&EmptyDeleteCallback))); | 555 base::Bind(&EmptyDeleteCallback))); |
| 556 } | |
| 527 return; | 557 return; |
| 528 } | 558 } |
| 529 MarkPageForDeletion(node->id(), base::Bind(&EmptyDeleteCallback)); | 559 for (size_t i = 0; i < ids.size(); i++) { |
| 560 MarkPageForDeletion(ids[i], base::Bind(&EmptyDeleteCallback)); | |
| 561 } | |
| 530 } | 562 } |
| 531 | 563 |
| 532 void OfflinePageModel::BookmarkNodeChanged( | 564 void OfflinePageModel::BookmarkNodeChanged( |
| 533 bookmarks::BookmarkModel* model, | 565 bookmarks::BookmarkModel* model, |
| 534 const bookmarks::BookmarkNode* node) { | 566 const bookmarks::BookmarkNode* node) { |
| 535 // BookmarkNodeChanged could be triggered if title or URL gets changed. If | 567 // BookmarkNodeChanged could be triggered if title or URL gets changed. If |
| 536 // the latter, we need to invalidate the offline copy. | 568 // the latter, we need to invalidate the offline copy. |
| 537 auto iter = offline_pages_.find(node->id()); | 569 ClientId cid; |
| 538 if (iter != offline_pages_.end() && iter->second.url != node->url()) | 570 cid.name_space = BOOKMARK_NAMESPACE; |
| 539 DeletePageByBookmarkId(node->id(), DeletePageCallback()); | 571 cid.id = base::Int64ToString(node->id()); |
| 572 std::vector<int64_t> ids = GetOfflineIdsForClientId(cid); | |
| 573 for (size_t i = 0; i < ids.size(); i++) { | |
| 574 auto iter = offline_pages_.find(ids[i]); | |
| 575 if (iter != offline_pages_.end() && iter->second.url != node->url()) | |
| 576 DeletePageByOfflineId(ids[i], DeletePageCallback()); | |
| 577 } | |
| 540 } | 578 } |
| 541 | 579 |
| 542 void OfflinePageModel::OnEnsureArchivesDirCreatedDone() { | 580 void OfflinePageModel::OnEnsureArchivesDirCreatedDone() { |
| 543 store_->Load(base::Bind(&OfflinePageModel::OnLoadDone, | 581 store_->Load(base::Bind(&OfflinePageModel::OnLoadDone, |
| 544 weak_ptr_factory_.GetWeakPtr())); | 582 weak_ptr_factory_.GetWeakPtr())); |
| 545 } | 583 } |
| 546 | 584 |
| 547 void OfflinePageModel::OnLoadDone( | 585 void OfflinePageModel::OnLoadDone( |
| 548 OfflinePageMetadataStore::LoadStatus load_status, | 586 OfflinePageMetadataStore::LoadStatus load_status, |
| 549 const std::vector<OfflinePageItem>& offline_pages) { | 587 const std::vector<OfflinePageItem>& offline_pages) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 563 // If there are pages that are marked for deletion, but not yet deleted and | 601 // If there are pages that are marked for deletion, but not yet deleted and |
| 564 // OfflinePageModel gets reloaded. Delete the pages now. | 602 // OfflinePageModel gets reloaded. Delete the pages now. |
| 565 FinalizePageDeletion(); | 603 FinalizePageDeletion(); |
| 566 | 604 |
| 567 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this)); | 605 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelLoaded(this)); |
| 568 | 606 |
| 569 CheckForExternalFileDeletion(); | 607 CheckForExternalFileDeletion(); |
| 570 } | 608 } |
| 571 | 609 |
| 572 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback, | 610 void OfflinePageModel::InformSavePageDone(const SavePageCallback& callback, |
| 573 SavePageResult result) { | 611 SavePageResult result, |
| 612 int64_t offline_id) { | |
| 574 UMA_HISTOGRAM_ENUMERATION( | 613 UMA_HISTOGRAM_ENUMERATION( |
| 575 "OfflinePages.SavePageResult", | 614 "OfflinePages.SavePageResult", |
| 576 static_cast<int>(result), | 615 static_cast<int>(result), |
| 577 static_cast<int>(SavePageResult::RESULT_COUNT)); | 616 static_cast<int>(SavePageResult::RESULT_COUNT)); |
| 578 callback.Run(result); | 617 callback.Run(result, offline_id); |
| 579 } | 618 } |
| 580 | 619 |
| 581 void OfflinePageModel::DeletePendingArchiver(OfflinePageArchiver* archiver) { | 620 void OfflinePageModel::DeletePendingArchiver(OfflinePageArchiver* archiver) { |
| 582 pending_archivers_.erase(std::find( | 621 pending_archivers_.erase(std::find( |
| 583 pending_archivers_.begin(), pending_archivers_.end(), archiver)); | 622 pending_archivers_.begin(), pending_archivers_.end(), archiver)); |
| 584 } | 623 } |
| 585 | 624 |
| 586 void OfflinePageModel::OnDeleteArchiveFilesDone( | 625 void OfflinePageModel::OnDeleteArchiveFilesDone( |
| 587 const std::vector<int64_t>& bookmark_ids, | 626 const std::vector<int64_t>& offline_ids, |
| 588 const DeletePageCallback& callback, | 627 const DeletePageCallback& callback, |
| 589 const bool* success) { | 628 const bool* success) { |
| 590 DCHECK(success); | 629 DCHECK(success); |
| 591 | 630 |
| 592 if (!*success) { | 631 if (!*success) { |
| 593 InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE); | 632 InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE); |
| 594 return; | 633 return; |
| 595 } | 634 } |
| 596 | 635 |
| 597 store_->RemoveOfflinePages( | 636 store_->RemoveOfflinePages( |
| 598 bookmark_ids, | 637 offline_ids, |
| 599 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone, | 638 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone, |
| 600 weak_ptr_factory_.GetWeakPtr(), bookmark_ids, callback)); | 639 weak_ptr_factory_.GetWeakPtr(), offline_ids, callback)); |
| 601 } | 640 } |
| 602 | 641 |
| 603 void OfflinePageModel::OnRemoveOfflinePagesDone( | 642 void OfflinePageModel::OnRemoveOfflinePagesDone( |
| 604 const std::vector<int64_t>& bookmark_ids, | 643 const std::vector<int64_t>& offline_ids, |
| 605 const DeletePageCallback& callback, | 644 const DeletePageCallback& callback, |
| 606 bool success) { | 645 bool success) { |
| 607 // Delete the offline page from the in memory cache regardless of success in | 646 // Delete the offline page from the in memory cache regardless of success in |
| 608 // store. | 647 // store. |
| 609 base::Time now = base::Time::Now(); | 648 base::Time now = base::Time::Now(); |
| 610 int64_t total_size = 0; | 649 int64_t total_size = 0; |
| 611 for (int64_t bookmark_id : bookmark_ids) { | 650 for (int64_t offline_id : offline_ids) { |
| 612 auto iter = offline_pages_.find(bookmark_id); | 651 auto iter = offline_pages_.find(offline_id); |
| 613 if (iter == offline_pages_.end()) | 652 if (iter == offline_pages_.end()) |
| 614 continue; | 653 continue; |
| 615 total_size += iter->second.file_size; | 654 total_size += iter->second.file_size; |
| 616 UMA_HISTOGRAM_CUSTOM_COUNTS( | 655 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 617 "OfflinePages.PageLifetime", | 656 "OfflinePages.PageLifetime", |
| 618 (now - iter->second.creation_time).InMinutes(), | 657 (now - iter->second.creation_time).InMinutes(), |
| 619 1, | 658 1, |
| 620 base::TimeDelta::FromDays(365).InMinutes(), | 659 base::TimeDelta::FromDays(365).InMinutes(), |
| 621 100); | 660 100); |
| 622 UMA_HISTOGRAM_CUSTOM_COUNTS( | 661 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 633 base::TimeDelta::FromDays(365).InMinutes(), | 672 base::TimeDelta::FromDays(365).InMinutes(), |
| 634 100); | 673 100); |
| 635 UMA_HISTOGRAM_MEMORY_KB( | 674 UMA_HISTOGRAM_MEMORY_KB( |
| 636 "OfflinePages.DeletePage.PageSize", iter->second.file_size / 1024); | 675 "OfflinePages.DeletePage.PageSize", iter->second.file_size / 1024); |
| 637 UMA_HISTOGRAM_COUNTS( | 676 UMA_HISTOGRAM_COUNTS( |
| 638 "OfflinePages.DeletePage.AccessCount", iter->second.access_count); | 677 "OfflinePages.DeletePage.AccessCount", iter->second.access_count); |
| 639 // If the page is not marked for deletion at this point, the model has not | 678 // If the page is not marked for deletion at this point, the model has not |
| 640 // yet informed the observer that the offline page is deleted. | 679 // yet informed the observer that the offline page is deleted. |
| 641 if (!iter->second.IsMarkedForDeletion()) { | 680 if (!iter->second.IsMarkedForDeletion()) { |
| 642 FOR_EACH_OBSERVER(Observer, observers_, | 681 FOR_EACH_OBSERVER(Observer, observers_, |
| 643 OfflinePageDeleted(iter->second.bookmark_id)); | 682 OfflinePageDeleted(iter->second.offline_id)); |
| 644 } | 683 } |
| 645 offline_pages_.erase(iter); | 684 offline_pages_.erase(iter); |
| 646 } | 685 } |
| 647 if (bookmark_ids.size() > 1) { | 686 if (offline_ids.size() > 1) { |
| 648 UMA_HISTOGRAM_COUNTS( | 687 UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count", offline_ids.size()); |
| 649 "OfflinePages.BatchDelete.Count", bookmark_ids.size()); | |
| 650 UMA_HISTOGRAM_MEMORY_KB( | 688 UMA_HISTOGRAM_MEMORY_KB( |
| 651 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); | 689 "OfflinePages.BatchDelete.TotalPageSize", total_size / 1024); |
| 652 } | 690 } |
| 653 // Deleting multiple pages always succeeds when it gets to this point. | 691 // Deleting multiple pages always succeeds when it gets to this point. |
| 654 InformDeletePageDone( | 692 InformDeletePageDone(callback, (success || offline_ids.size() > 1) |
| 655 callback, | 693 ? DeletePageResult::SUCCESS |
| 656 (success || bookmark_ids.size() > 1) ? DeletePageResult::SUCCESS | 694 : DeletePageResult::STORE_FAILURE); |
| 657 : DeletePageResult::STORE_FAILURE); | |
| 658 } | 695 } |
| 659 | 696 |
| 660 void OfflinePageModel::InformDeletePageDone(const DeletePageCallback& callback, | 697 void OfflinePageModel::InformDeletePageDone(const DeletePageCallback& callback, |
| 661 DeletePageResult result) { | 698 DeletePageResult result) { |
| 662 UMA_HISTOGRAM_ENUMERATION( | 699 UMA_HISTOGRAM_ENUMERATION( |
| 663 "OfflinePages.DeletePageResult", | 700 "OfflinePages.DeletePageResult", |
| 664 static_cast<int>(result), | 701 static_cast<int>(result), |
| 665 static_cast<int>(DeletePageResult::RESULT_COUNT)); | 702 static_cast<int>(DeletePageResult::RESULT_COUNT)); |
| 666 if (!callback.is_null()) | 703 if (!callback.is_null()) |
| 667 callback.Run(result); | 704 callback.Run(result); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 680 | 717 |
| 681 store_->RemoveOfflinePages( | 718 store_->RemoveOfflinePages( |
| 682 *ids_of_pages_missing_archive_file, | 719 *ids_of_pages_missing_archive_file, |
| 683 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone, | 720 base::Bind(&OfflinePageModel::OnRemoveOfflinePagesDone, |
| 684 weak_ptr_factory_.GetWeakPtr(), | 721 weak_ptr_factory_.GetWeakPtr(), |
| 685 *ids_of_pages_missing_archive_file, | 722 *ids_of_pages_missing_archive_file, |
| 686 done_callback)); | 723 done_callback)); |
| 687 } | 724 } |
| 688 | 725 |
| 689 void OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone( | 726 void OfflinePageModel::OnRemoveOfflinePagesMissingArchiveFileDone( |
| 690 const std::vector<int64_t>& bookmark_ids, | 727 const std::vector<int64_t>& offline_ids, |
| 691 OfflinePageModel::DeletePageResult /* result */) { | 728 OfflinePageModel::DeletePageResult /* result */) { |
| 692 for (int64_t bookmark_id : bookmark_ids) { | 729 for (int64_t offline_id : offline_ids) { |
| 693 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageDeleted(bookmark_id)); | 730 FOR_EACH_OBSERVER(Observer, observers_, OfflinePageDeleted(offline_id)); |
| 694 } | 731 } |
| 695 } | 732 } |
| 696 | 733 |
| 697 void OfflinePageModel::OnRemoveAllFilesDoneForClearAll( | 734 void OfflinePageModel::OnRemoveAllFilesDoneForClearAll( |
| 698 const base::Closure& callback, | 735 const base::Closure& callback, |
| 699 DeletePageResult result) { | 736 DeletePageResult result) { |
| 700 store_->Reset(base::Bind(&OfflinePageModel::OnResetStoreDoneForClearAll, | 737 store_->Reset(base::Bind(&OfflinePageModel::OnResetStoreDoneForClearAll, |
| 701 weak_ptr_factory_.GetWeakPtr(), | 738 weak_ptr_factory_.GetWeakPtr(), |
| 702 callback)); | 739 callback)); |
| 703 } | 740 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 727 CLEAR_ALL_STATUS_COUNT); | 764 CLEAR_ALL_STATUS_COUNT); |
| 728 | 765 |
| 729 CacheLoadedData(offline_pages); | 766 CacheLoadedData(offline_pages); |
| 730 callback.Run(); | 767 callback.Run(); |
| 731 } | 768 } |
| 732 | 769 |
| 733 void OfflinePageModel::CacheLoadedData( | 770 void OfflinePageModel::CacheLoadedData( |
| 734 const std::vector<OfflinePageItem>& offline_pages) { | 771 const std::vector<OfflinePageItem>& offline_pages) { |
| 735 offline_pages_.clear(); | 772 offline_pages_.clear(); |
| 736 for (const auto& offline_page : offline_pages) | 773 for (const auto& offline_page : offline_pages) |
| 737 offline_pages_[offline_page.bookmark_id] = offline_page; | 774 offline_pages_[offline_page.offline_id] = offline_page; |
| 775 } | |
| 776 | |
| 777 int64_t OfflinePageModel::GenerateOfflineId() { | |
| 778 int64_t result = base::RandUint64(); | |
|
dewittj
2016/02/26 18:42:56
I think this can result in a negative |result| sin
fgorski
2016/02/26 19:29:22
base::RandGenerator(std::numeric_limits<int64_t>::
dewittj
2016/02/26 19:39:25
No, RandGenerator generates numbers from [0, range
bburns
2016/02/27 00:48:19
Done.
| |
| 779 while (result == INVALID_OFFLINE_ID) { | |
| 780 result = base::RandUint64(); | |
| 781 } | |
| 782 return result; | |
| 738 } | 783 } |
| 739 | 784 |
| 740 } // namespace offline_pages | 785 } // namespace offline_pages |
| OLD | NEW |