Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "chrome/browser/win/jumplist.h" | 5 #include "chrome/browser/win/jumplist.h" |
| 6 | 6 |
| 7 #include "base/base_paths.h" | 7 #include "base/base_paths.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 prefs::kIncognitoModeAvailability, | 243 prefs::kIncognitoModeAvailability, |
| 244 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, | 244 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, |
| 245 base::Unretained(this))); | 245 base::Unretained(this))); |
| 246 } | 246 } |
| 247 | 247 |
| 248 JumpList::~JumpList() { | 248 JumpList::~JumpList() { |
| 249 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 249 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 250 Terminate(); | 250 Terminate(); |
| 251 } | 251 } |
| 252 | 252 |
| 253 // static | 253 void JumpList::TopSitesLoaded(history::TopSites* top_sites) {} |
| 254 bool JumpList::Enabled() { | 254 |
| 255 return JumpListUpdater::IsEnabled(); | 255 void JumpList::TopSitesChanged(history::TopSites* top_sites, |
| 256 ChangeReason change_reason) { | |
| 257 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 258 | |
| 259 top_sites_has_pending_notification_ = true; | |
| 260 | |
| 261 // Postpone handling this notification until a pending update completes. | |
| 262 if (update_in_progress_) | |
| 263 return; | |
| 264 | |
| 265 // If we have a pending favicon request, cancel it here as it's out of date. | |
| 266 CancelPendingUpdate(); | |
| 267 | |
| 268 // Initialize the one-shot timer to update the JumpList in a while. | |
| 269 InitializeTimerForUpdate(); | |
| 256 } | 270 } |
| 257 | 271 |
| 258 void JumpList::CancelPendingUpdate() { | 272 void JumpList::TabRestoreServiceChanged(sessions::TabRestoreService* service) { |
| 259 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 273 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 260 | 274 |
| 261 // Cancel a pending most-visited URL fetch by invalidating the weak pointer. | 275 tab_restore_has_pending_notification_ = true; |
| 262 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 263 | 276 |
| 264 // Cancel a pending favicon loading by invalidating its task id. | 277 // Postpone handling this notification until a pending update completes. |
| 265 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { | 278 if (update_in_progress_) |
| 266 cancelable_task_tracker_.TryCancel(task_id_); | 279 return; |
| 267 task_id_ = base::CancelableTaskTracker::kBadTaskId; | 280 |
| 281 // if we have a pending favicon request, cancel it here as it's out of date. | |
| 282 CancelPendingUpdate(); | |
| 283 | |
| 284 // Initialize the one-shot timer to update the JumpList in a while. | |
| 285 InitializeTimerForUpdate(); | |
| 286 } | |
| 287 | |
| 288 void JumpList::TabRestoreServiceDestroyed( | |
| 289 sessions::TabRestoreService* service) {} | |
| 290 | |
| 291 void JumpList::InitializeTimerForUpdate() { | |
| 292 if (timer_.IsRunning()) { | |
| 293 timer_.Reset(); | |
| 294 } else { | |
| 295 // base::Unretained is safe since |this| is guaranteed to outlive timer_. | |
| 296 timer_.Start(FROM_HERE, kDelayForJumplistUpdate, | |
| 297 base::Bind(&JumpList::OnDelayTimer, base::Unretained(this))); | |
| 268 } | 298 } |
| 269 } | 299 } |
| 270 | 300 |
| 271 void JumpList::Terminate() { | 301 void JumpList::OnDelayTimer() { |
| 272 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 273 timer_.Stop(); | 303 |
| 274 CancelPendingUpdate(); | 304 if (updates_to_skip_ > 0) { |
| 275 update_in_progress_ = false; | 305 --updates_to_skip_; |
| 276 if (profile_) { | 306 return; |
| 277 sessions::TabRestoreService* tab_restore_service = | 307 } |
| 278 TabRestoreServiceFactory::GetForProfile(profile_); | 308 |
| 279 if (tab_restore_service) | 309 // Retrieve the recently closed URLs synchronously. |
| 280 tab_restore_service->RemoveObserver(this); | 310 if (tab_restore_has_pending_notification_) { |
| 311 tab_restore_has_pending_notification_ = false; | |
| 312 ProcessTabRestoreServiceNotification(); | |
| 313 } | |
| 314 | |
| 315 // If TopSites has updates, retrieve the URLs asynchronously, and on its | |
| 316 // completion, trigger favicon loading. | |
| 317 // Otherwise, call StartLoadingFavicon directly to start favicon loading. | |
| 318 if (top_sites_has_pending_notification_) | |
| 319 ProcessTopSitesNotification(); | |
| 320 else | |
| 321 StartLoadingFavicon(); | |
| 322 } | |
| 323 | |
| 324 void JumpList::ProcessTopSitesNotification() { | |
| 325 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 326 | |
| 327 // Opening the first tab in one session triggers a TopSite history sync. | |
| 328 // Delay this sync till the first tab is closed to allow the "recently closed" | |
| 329 // category from last session to stay longer. All previous pending | |
| 330 // notifications from TopSites are ignored. | |
| 331 if (!has_tab_closed_) { | |
| 332 top_sites_has_pending_notification_ = false; | |
| 333 return; | |
| 334 } | |
| 335 | |
| 336 scoped_refptr<history::TopSites> top_sites = | |
| 337 TopSitesFactory::GetForProfile(profile_); | |
| 338 if (top_sites) { | |
| 339 top_sites->GetMostVisitedURLs( | |
| 340 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | |
| 341 weak_ptr_factory_.GetWeakPtr()), | |
| 342 false); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void JumpList::ProcessTabRestoreServiceNotification() { | |
| 347 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 348 | |
| 349 // Create a list of ShellLinkItems from the "Recently Closed" pages. | |
| 350 // As noted above, we create a ShellLinkItem objects with the following | |
| 351 // parameters. | |
| 352 // * arguments | |
| 353 // The last URL of the tab object. | |
| 354 // * title | |
| 355 // The title of the last URL. | |
| 356 // * icon | |
| 357 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | |
| 358 | |
| 359 sessions::TabRestoreService* tab_restore_service = | |
| 360 TabRestoreServiceFactory::GetForProfile(profile_); | |
| 361 | |
| 362 recently_closed_pages_.clear(); | |
| 363 | |
| 364 for (const auto& entry : tab_restore_service->entries()) { | |
| 365 if (recently_closed_pages_.size() >= kRecentlyClosedItems) | |
| 366 break; | |
| 367 switch (entry->type) { | |
| 368 case sessions::TabRestoreService::TAB: | |
| 369 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), | |
| 370 kRecentlyClosedItems); | |
| 371 break; | |
| 372 case sessions::TabRestoreService::WINDOW: | |
| 373 AddWindow( | |
| 374 static_cast<const sessions::TabRestoreService::Window&>(*entry), | |
| 375 kRecentlyClosedItems); | |
| 376 break; | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 recently_closed_should_update_ = true; | |
| 381 | |
| 382 // Force a TopSite history sync when closing a first tab in one session. | |
| 383 if (!has_tab_closed_) { | |
| 384 has_tab_closed_ = true; | |
| 281 scoped_refptr<history::TopSites> top_sites = | 385 scoped_refptr<history::TopSites> top_sites = |
| 282 TopSitesFactory::GetForProfile(profile_); | 386 TopSitesFactory::GetForProfile(profile_); |
| 283 if (top_sites) | 387 if (top_sites) |
| 284 top_sites->RemoveObserver(this); | 388 top_sites->SyncWithHistory(); |
| 285 pref_change_registrar_.reset(); | |
| 286 } | 389 } |
| 287 profile_ = nullptr; | |
| 288 } | |
| 289 | |
| 290 void JumpList::Shutdown() { | |
| 291 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 292 Terminate(); | |
| 293 } | 390 } |
| 294 | 391 |
| 295 void JumpList::OnMostVisitedURLsAvailable( | 392 void JumpList::OnMostVisitedURLsAvailable( |
| 296 const history::MostVisitedURLList& urls) { | 393 const history::MostVisitedURLList& urls) { |
| 297 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 394 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 298 | 395 |
| 299 top_sites_has_pending_notification_ = false; | 396 top_sites_has_pending_notification_ = false; |
| 300 | 397 |
| 301 // There is no need to update the JumpList if the top most visited sites in | 398 // There is no need to update the JumpList if the top most visited sites in |
| 302 // display have not changed. | 399 // display have not changed. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 319 most_visited_pages_.push_back(link); | 416 most_visited_pages_.push_back(link); |
| 320 icon_urls_.emplace_back(std::move(url_string), std::move(link)); | 417 icon_urls_.emplace_back(std::move(url_string), std::move(link)); |
| 321 } | 418 } |
| 322 | 419 |
| 323 most_visited_should_update_ = true; | 420 most_visited_should_update_ = true; |
| 324 | 421 |
| 325 // Send a query that retrieves the first favicon. | 422 // Send a query that retrieves the first favicon. |
| 326 StartLoadingFavicon(); | 423 StartLoadingFavicon(); |
| 327 } | 424 } |
| 328 | 425 |
| 329 void JumpList::TabRestoreServiceChanged(sessions::TabRestoreService* service) { | |
| 330 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 331 | |
| 332 tab_restore_has_pending_notification_ = true; | |
| 333 | |
| 334 // Postpone handling this notification until a pending update completes. | |
| 335 if (update_in_progress_) | |
| 336 return; | |
| 337 | |
| 338 // if we have a pending favicon request, cancel it here as it's out of date. | |
| 339 CancelPendingUpdate(); | |
| 340 | |
| 341 // Initialize the one-shot timer to update the JumpList in a while. | |
| 342 InitializeTimerForUpdate(); | |
| 343 } | |
| 344 | |
| 345 void JumpList::TabRestoreServiceDestroyed( | |
| 346 sessions::TabRestoreService* service) {} | |
| 347 | |
| 348 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, | 426 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, |
| 349 size_t max_items) { | 427 size_t max_items) { |
| 350 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 428 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 351 | 429 |
| 352 // This code adds the URL and the title strings of the given tab to the | 430 // This code adds the URL and the title strings of the given tab to the |
| 353 // JumpList variables. | 431 // JumpList variables. |
| 354 if (recently_closed_pages_.size() >= max_items) | 432 if (recently_closed_pages_.size() >= max_items) |
| 355 return false; | 433 return false; |
| 356 | 434 |
| 357 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 435 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 local_most_visited_pages, local_recently_closed_pages, | 556 local_most_visited_pages, local_recently_closed_pages, |
| 479 most_visited_should_update, recently_closed_should_update, | 557 most_visited_should_update, recently_closed_should_update, |
| 480 incognito_availability, update_results.get()), | 558 incognito_availability, update_results.get()), |
| 481 base::Bind(&JumpList::OnRunUpdateCompletion, | 559 base::Bind(&JumpList::OnRunUpdateCompletion, |
| 482 weak_ptr_factory_.GetWeakPtr(), | 560 weak_ptr_factory_.GetWeakPtr(), |
| 483 base::Passed(std::move(update_results))))) { | 561 base::Passed(std::move(update_results))))) { |
| 484 OnRunUpdateCompletion(base::MakeUnique<UpdateResults>()); | 562 OnRunUpdateCompletion(base::MakeUnique<UpdateResults>()); |
| 485 } | 563 } |
| 486 } | 564 } |
| 487 | 565 |
| 488 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { | 566 void JumpList::OnRunUpdateCompletion( |
| 489 } | 567 std::unique_ptr<UpdateResults> update_results) { |
| 490 | |
| 491 void JumpList::TopSitesChanged(history::TopSites* top_sites, | |
| 492 ChangeReason change_reason) { | |
| 493 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 568 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 494 | 569 |
| 495 top_sites_has_pending_notification_ = true; | 570 // Update JumpList member variables based on the results from the update run |
| 571 // just finished. | |
| 572 if (update_results->update_timeout) | |
| 573 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; | |
| 496 | 574 |
| 497 // Postpone handling this notification until a pending update completes. | 575 if (update_results->update_success) { |
| 498 if (update_in_progress_) | 576 most_visited_icons_.swap(update_results->most_visited_icons_in_update); |
| 499 return; | 577 recently_closed_icons_.swap( |
| 578 update_results->recently_closed_icons_in_update); | |
| 579 most_visited_should_update_ = false; | |
| 580 recently_closed_should_update_ = false; | |
| 581 } | |
| 500 | 582 |
| 501 // If we have a pending favicon request, cancel it here as it's out of date. | 583 update_in_progress_ = false; |
| 502 CancelPendingUpdate(); | |
| 503 | 584 |
| 504 // Initialize the one-shot timer to update the JumpList in a while. | 585 // If there is any new notification during the update run just finished, start |
| 505 InitializeTimerForUpdate(); | 586 // another JumpList update. |
| 506 } | 587 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld |
| 588 // folders as they are no longer needed. Now we have the | |
| 589 // JumpListIcons{MostVisited, RecentClosed} folders instead. | |
| 590 if (top_sites_has_pending_notification_ || | |
| 591 tab_restore_has_pending_notification_) { | |
| 592 InitializeTimerForUpdate(); | |
| 593 } else { | |
| 594 base::FilePath profile_dir = profile_->GetPath(); | |
| 595 base::FilePath icon_dir = | |
| 596 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); | |
| 597 delete_jumplisticons_task_runner_->PostTask( | |
| 598 FROM_HERE, | |
| 599 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); | |
| 507 | 600 |
| 508 void JumpList::InitializeTimerForUpdate() { | 601 base::FilePath icon_dir_old = |
| 509 if (timer_.IsRunning()) { | 602 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("Old")); |
| 510 timer_.Reset(); | 603 delete_jumplisticons_task_runner_->PostTask( |
| 511 } else { | 604 FROM_HERE, base::Bind(&DeleteDirectory, std::move(icon_dir_old), |
| 512 // base::Unretained is safe since |this| is guaranteed to outlive timer_. | 605 kFileDeleteLimit)); |
| 513 timer_.Start(FROM_HERE, kDelayForJumplistUpdate, | |
| 514 base::Bind(&JumpList::OnDelayTimer, base::Unretained(this))); | |
| 515 } | 606 } |
| 516 } | 607 } |
| 517 | 608 |
| 518 void JumpList::OnDelayTimer() { | 609 void JumpList::CancelPendingUpdate() { |
| 519 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 610 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 520 | 611 |
| 521 if (updates_to_skip_ > 0) { | 612 // Cancel a pending most-visited URL fetch by invalidating the weak pointer. |
| 522 --updates_to_skip_; | 613 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 523 return; | |
| 524 } | |
| 525 | 614 |
| 526 // Retrieve the recently closed URLs synchronously. | 615 // Cancel a pending favicon loading by invalidating its task id. |
| 527 if (tab_restore_has_pending_notification_) { | 616 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { |
| 528 tab_restore_has_pending_notification_ = false; | 617 cancelable_task_tracker_.TryCancel(task_id_); |
| 529 ProcessTabRestoreServiceNotification(); | 618 task_id_ = base::CancelableTaskTracker::kBadTaskId; |
| 530 } | |
| 531 | |
| 532 // If TopSites has updates, retrieve the URLs asynchronously, and on its | |
| 533 // completion, trigger favicon loading. | |
| 534 // Otherwise, call StartLoadingFavicon directly to start favicon loading. | |
| 535 if (top_sites_has_pending_notification_) | |
| 536 ProcessTopSitesNotification(); | |
| 537 else | |
| 538 StartLoadingFavicon(); | |
| 539 } | |
| 540 | |
| 541 void JumpList::ProcessTopSitesNotification() { | |
| 542 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 543 | |
| 544 // Opening the first tab in one session triggers a TopSite history sync. | |
| 545 // Delay this sync till the first tab is closed to allow the "recently closed" | |
| 546 // category from last session to stay longer. All previous pending | |
| 547 // notifications from TopSites are ignored. | |
| 548 if (!has_tab_closed_) { | |
| 549 top_sites_has_pending_notification_ = false; | |
| 550 return; | |
| 551 } | |
| 552 | |
| 553 scoped_refptr<history::TopSites> top_sites = | |
| 554 TopSitesFactory::GetForProfile(profile_); | |
| 555 if (top_sites) { | |
| 556 top_sites->GetMostVisitedURLs( | |
| 557 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | |
| 558 weak_ptr_factory_.GetWeakPtr()), | |
| 559 false); | |
| 560 } | 619 } |
| 561 } | 620 } |
| 562 | 621 |
| 563 void JumpList::ProcessTabRestoreServiceNotification() { | 622 void JumpList::Terminate() { |
| 564 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 623 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 565 | 624 timer_.Stop(); |
| 566 // Create a list of ShellLinkItems from the "Recently Closed" pages. | 625 CancelPendingUpdate(); |
| 567 // As noted above, we create a ShellLinkItem objects with the following | 626 update_in_progress_ = false; |
| 568 // parameters. | 627 if (profile_) { |
| 569 // * arguments | 628 sessions::TabRestoreService* tab_restore_service = |
| 570 // The last URL of the tab object. | 629 TabRestoreServiceFactory::GetForProfile(profile_); |
| 571 // * title | 630 if (tab_restore_service) |
| 572 // The title of the last URL. | 631 tab_restore_service->RemoveObserver(this); |
| 573 // * icon | |
| 574 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | |
| 575 | |
| 576 sessions::TabRestoreService* tab_restore_service = | |
| 577 TabRestoreServiceFactory::GetForProfile(profile_); | |
| 578 | |
| 579 recently_closed_pages_.clear(); | |
| 580 | |
| 581 for (const auto& entry : tab_restore_service->entries()) { | |
| 582 if (recently_closed_pages_.size() >= kRecentlyClosedItems) | |
| 583 break; | |
| 584 switch (entry->type) { | |
| 585 case sessions::TabRestoreService::TAB: | |
| 586 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), | |
| 587 kRecentlyClosedItems); | |
| 588 break; | |
| 589 case sessions::TabRestoreService::WINDOW: | |
| 590 AddWindow( | |
| 591 static_cast<const sessions::TabRestoreService::Window&>(*entry), | |
| 592 kRecentlyClosedItems); | |
| 593 break; | |
| 594 } | |
| 595 } | |
| 596 | |
| 597 recently_closed_should_update_ = true; | |
| 598 | |
| 599 // Force a TopSite history sync when closing a first tab in one session. | |
| 600 if (!has_tab_closed_) { | |
| 601 has_tab_closed_ = true; | |
| 602 scoped_refptr<history::TopSites> top_sites = | 632 scoped_refptr<history::TopSites> top_sites = |
| 603 TopSitesFactory::GetForProfile(profile_); | 633 TopSitesFactory::GetForProfile(profile_); |
| 604 if (top_sites) | 634 if (top_sites) |
| 605 top_sites->SyncWithHistory(); | 635 top_sites->RemoveObserver(this); |
| 636 pref_change_registrar_.reset(); | |
| 606 } | 637 } |
| 638 profile_ = nullptr; | |
| 639 } | |
| 640 | |
| 641 void JumpList::Shutdown() { | |
|
grt (UTC plus 2)
2017/06/14 10:54:12
please put all methods here in the same order as t
chengx
2017/06/14 16:53:23
Done.
| |
| 642 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
| 643 Terminate(); | |
| 607 } | 644 } |
| 608 | 645 |
| 609 // static | 646 // static |
| 610 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, | 647 bool JumpList::Enabled() { |
| 611 URLIconCache* icon_cache) { | 648 return JumpListUpdater::IsEnabled(); |
| 612 // Put all cached icon file paths into a set. | |
| 613 base::flat_set<base::FilePath> cached_files; | |
| 614 cached_files.reserve(icon_cache->size()); | |
| 615 | |
| 616 for (const auto& url_path_pair : *icon_cache) | |
| 617 cached_files.insert(url_path_pair.second); | |
| 618 | |
| 619 DeleteNonCachedFiles(icon_dir, cached_files); | |
| 620 } | 649 } |
| 621 | 650 |
| 622 // static | 651 // static |
| 623 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, | |
| 624 const ShellLinkItemList& item_list, | |
| 625 size_t max_items, | |
| 626 URLIconCache* icon_cache) { | |
| 627 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 628 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | |
| 629 | |
| 630 int icons_created = 0; | |
| 631 | |
| 632 // Reuse icons for urls that already present in the current JumpList. | |
| 633 URLIconCache updated_map; | |
| 634 for (ShellLinkItemList::const_iterator iter = item_list.begin(); | |
| 635 iter != item_list.end() && max_items > 0; ++iter, --max_items) { | |
| 636 ShellLinkItem* item = iter->get(); | |
| 637 auto cache_iter = icon_cache->find(item->url()); | |
| 638 if (cache_iter != icon_cache->end()) { | |
| 639 item->set_icon(cache_iter->second.value(), 0); | |
| 640 updated_map[item->url()] = cache_iter->second; | |
| 641 } else { | |
| 642 base::FilePath icon_path; | |
| 643 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { | |
| 644 ++icons_created; | |
| 645 item->set_icon(icon_path.value(), 0); | |
| 646 updated_map[item->url()] = icon_path; | |
| 647 } | |
| 648 } | |
| 649 } | |
| 650 icon_cache->swap(updated_map); | |
| 651 | |
| 652 return icons_created; | |
| 653 } | |
| 654 | |
| 655 // static | |
| 656 int JumpList::UpdateIconFiles(const base::FilePath& icon_dir, | |
| 657 const ShellLinkItemList& page_list, | |
| 658 size_t slot_limit, | |
| 659 URLIconCache* icon_cache) { | |
| 660 int icons_created = 0; | |
| 661 | |
| 662 // Clear the JumpList icon folder at |icon_dir| and the cache when | |
| 663 // 1) |icon_cache| is empty. This happens when "Most visited" or "Recently | |
| 664 // closed" category updates for the 1st time after Chrome is launched. | |
| 665 // 2) The number of icons in |icon_dir| has exceeded the limit. | |
| 666 if (icon_cache->empty() || FilesExceedLimitInDir(icon_dir, slot_limit * 2)) { | |
| 667 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | |
| 668 icon_cache->clear(); | |
| 669 // Create new icons only when the directory exists and is empty. | |
| 670 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | |
| 671 icons_created += | |
| 672 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | |
| 673 } else if (base::CreateDirectory(icon_dir)) { | |
| 674 icons_created += | |
| 675 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | |
| 676 DeleteIconFiles(icon_dir, icon_cache); | |
| 677 } | |
| 678 | |
| 679 return icons_created; | |
| 680 } | |
| 681 | |
| 682 // static | |
| 683 void JumpList::RunUpdateJumpList( | 652 void JumpList::RunUpdateJumpList( |
| 684 const base::string16& app_id, | 653 const base::string16& app_id, |
| 685 const base::FilePath& profile_dir, | 654 const base::FilePath& profile_dir, |
| 686 const ShellLinkItemList& most_visited_pages, | 655 const ShellLinkItemList& most_visited_pages, |
| 687 const ShellLinkItemList& recently_closed_pages, | 656 const ShellLinkItemList& recently_closed_pages, |
| 688 bool most_visited_should_update, | 657 bool most_visited_should_update, |
| 689 bool recently_closed_should_update, | 658 bool recently_closed_should_update, |
| 690 IncognitoModePrefs::Availability incognito_availability, | 659 IncognitoModePrefs::Availability incognito_availability, |
| 691 UpdateResults* update_results) { | 660 UpdateResults* update_results) { |
| 692 if (!JumpListUpdater::IsEnabled()) | 661 if (!JumpListUpdater::IsEnabled()) |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 775 base::ElapsedTimer commit_update_timer; | 744 base::ElapsedTimer commit_update_timer; |
| 776 | 745 |
| 777 // Commit this transaction and send the updated JumpList to Windows. | 746 // Commit this transaction and send the updated JumpList to Windows. |
| 778 if (jumplist_updater.CommitUpdate()) | 747 if (jumplist_updater.CommitUpdate()) |
| 779 update_results->update_success = true; | 748 update_results->update_success = true; |
| 780 | 749 |
| 781 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) | 750 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) |
| 782 update_results->update_timeout = true; | 751 update_results->update_timeout = true; |
| 783 } | 752 } |
| 784 | 753 |
| 785 void JumpList::OnRunUpdateCompletion( | 754 // static |
| 786 std::unique_ptr<UpdateResults> update_results) { | 755 int JumpList::UpdateIconFiles(const base::FilePath& icon_dir, |
| 787 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 756 const ShellLinkItemList& page_list, |
| 757 size_t slot_limit, | |
| 758 URLIconCache* icon_cache) { | |
| 759 int icons_created = 0; | |
| 788 | 760 |
| 789 // Update JumpList member variables based on the results from the update run | 761 // Clear the JumpList icon folder at |icon_dir| and the cache when |
| 790 // just finished. | 762 // 1) |icon_cache| is empty. This happens when "Most visited" or "Recently |
| 791 if (update_results->update_timeout) | 763 // closed" category updates for the 1st time after Chrome is launched. |
| 792 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; | 764 // 2) The number of icons in |icon_dir| has exceeded the limit. |
| 793 | 765 if (icon_cache->empty() || FilesExceedLimitInDir(icon_dir, slot_limit * 2)) { |
| 794 if (update_results->update_success) { | 766 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); |
| 795 most_visited_icons_.swap(update_results->most_visited_icons_in_update); | 767 icon_cache->clear(); |
| 796 recently_closed_icons_.swap( | 768 // Create new icons only when the directory exists and is empty. |
| 797 update_results->recently_closed_icons_in_update); | 769 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) |
| 798 most_visited_should_update_ = false; | 770 icons_created += |
| 799 recently_closed_should_update_ = false; | 771 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); |
| 772 } else if (base::CreateDirectory(icon_dir)) { | |
| 773 icons_created += | |
| 774 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | |
| 775 DeleteIconFiles(icon_dir, icon_cache); | |
| 800 } | 776 } |
| 801 | 777 |
| 802 update_in_progress_ = false; | 778 return icons_created; |
| 779 } | |
| 803 | 780 |
| 804 // If there is any new notification during the update run just finished, start | 781 // static |
| 805 // another JumpList update. | 782 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, |
| 806 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld | 783 const ShellLinkItemList& item_list, |
| 807 // folders as they are no longer needed. Now we have the | 784 size_t max_items, |
| 808 // JumpListIcons{MostVisited, RecentClosed} folders instead. | 785 URLIconCache* icon_cache) { |
| 809 if (top_sites_has_pending_notification_ || | 786 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 810 tab_restore_has_pending_notification_) { | 787 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); |
| 811 InitializeTimerForUpdate(); | |
| 812 } else { | |
| 813 base::FilePath profile_dir = profile_->GetPath(); | |
| 814 base::FilePath icon_dir = | |
| 815 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); | |
| 816 delete_jumplisticons_task_runner_->PostTask( | |
| 817 FROM_HERE, | |
| 818 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); | |
| 819 | 788 |
| 820 base::FilePath icon_dir_old = | 789 int icons_created = 0; |
| 821 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("Old")); | 790 |
| 822 delete_jumplisticons_task_runner_->PostTask( | 791 // Reuse icons for urls that already present in the current JumpList. |
| 823 FROM_HERE, base::Bind(&DeleteDirectory, std::move(icon_dir_old), | 792 URLIconCache updated_map; |
| 824 kFileDeleteLimit)); | 793 for (ShellLinkItemList::const_iterator iter = item_list.begin(); |
| 794 iter != item_list.end() && max_items > 0; ++iter, --max_items) { | |
| 795 ShellLinkItem* item = iter->get(); | |
| 796 auto cache_iter = icon_cache->find(item->url()); | |
| 797 if (cache_iter != icon_cache->end()) { | |
| 798 item->set_icon(cache_iter->second.value(), 0); | |
| 799 updated_map[item->url()] = cache_iter->second; | |
| 800 } else { | |
| 801 base::FilePath icon_path; | |
| 802 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { | |
| 803 ++icons_created; | |
| 804 item->set_icon(icon_path.value(), 0); | |
| 805 updated_map[item->url()] = icon_path; | |
| 806 } | |
| 807 } | |
| 825 } | 808 } |
| 809 icon_cache->swap(updated_map); | |
| 810 | |
| 811 return icons_created; | |
| 826 } | 812 } |
| 813 | |
| 814 // static | |
| 815 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, | |
| 816 URLIconCache* icon_cache) { | |
| 817 // Put all cached icon file paths into a set. | |
| 818 base::flat_set<base::FilePath> cached_files; | |
| 819 cached_files.reserve(icon_cache->size()); | |
| 820 | |
| 821 for (const auto& url_path_pair : *icon_cache) | |
| 822 cached_files.insert(url_path_pair.second); | |
| 823 | |
| 824 DeleteNonCachedFiles(icon_dir, cached_files); | |
| 825 } | |
| OLD | NEW |