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