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 <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 void JumpList::CancelPendingUpdate() { | 437 void JumpList::CancelPendingUpdate() { |
438 DCHECK(CalledOnValidThread()); | 438 DCHECK(CalledOnValidThread()); |
439 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { | 439 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { |
440 cancelable_task_tracker_.TryCancel(task_id_); | 440 cancelable_task_tracker_.TryCancel(task_id_); |
441 task_id_ = base::CancelableTaskTracker::kBadTaskId; | 441 task_id_ = base::CancelableTaskTracker::kBadTaskId; |
442 } | 442 } |
443 } | 443 } |
444 | 444 |
445 void JumpList::Terminate() { | 445 void JumpList::Terminate() { |
446 DCHECK(CalledOnValidThread()); | 446 DCHECK(CalledOnValidThread()); |
| 447 timer_most_visited_.Stop(); |
| 448 timer_recently_closed_.Stop(); |
447 CancelPendingUpdate(); | 449 CancelPendingUpdate(); |
448 if (profile_) { | 450 if (profile_) { |
449 sessions::TabRestoreService* tab_restore_service = | 451 sessions::TabRestoreService* tab_restore_service = |
450 TabRestoreServiceFactory::GetForProfile(profile_); | 452 TabRestoreServiceFactory::GetForProfile(profile_); |
451 if (tab_restore_service) | 453 if (tab_restore_service) |
452 tab_restore_service->RemoveObserver(this); | 454 tab_restore_service->RemoveObserver(this); |
453 scoped_refptr<history::TopSites> top_sites = | 455 scoped_refptr<history::TopSites> top_sites = |
454 TopSitesFactory::GetForProfile(profile_); | 456 TopSitesFactory::GetForProfile(profile_); |
455 if (top_sites) | 457 if (top_sites) |
456 top_sites->RemoveObserver(this); | 458 top_sites->RemoveObserver(this); |
457 pref_change_registrar_.reset(); | 459 pref_change_registrar_.reset(); |
458 } | 460 } |
459 profile_ = NULL; | 461 profile_ = NULL; |
460 } | 462 } |
461 | 463 |
462 void JumpList::ShutdownOnUIThread() { | 464 void JumpList::ShutdownOnUIThread() { |
463 DCHECK(CalledOnValidThread()); | 465 DCHECK(CalledOnValidThread()); |
464 Terminate(); | 466 Terminate(); |
465 } | 467 } |
466 | 468 |
467 void JumpList::OnMostVisitedURLsAvailable( | 469 void JumpList::OnMostVisitedURLsAvailable( |
468 const history::MostVisitedURLList& urls) { | 470 const history::MostVisitedURLList& urls) { |
469 DCHECK(CalledOnValidThread()); | 471 DCHECK(CalledOnValidThread()); |
470 // If we have a pending favicon request, cancel it here (it is out of date). | |
471 CancelPendingUpdate(); | |
472 | 472 |
| 473 // At most 9 JumpList items can be displayed for the "Most Visited" |
| 474 // category. |
| 475 const int kMostVistedCount = 9; |
473 { | 476 { |
474 JumpListData* data = &jumplist_data_->data; | 477 JumpListData* data = &jumplist_data_->data; |
475 base::AutoLock auto_lock(data->list_lock_); | 478 base::AutoLock auto_lock(data->list_lock_); |
476 data->most_visited_pages_.clear(); | 479 data->most_visited_pages_.clear(); |
477 for (size_t i = 0; i < urls.size(); i++) { | 480 |
| 481 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { |
478 const history::MostVisitedURL& url = urls[i]; | 482 const history::MostVisitedURL& url = urls[i]; |
479 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 483 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
480 std::string url_string = url.url.spec(); | 484 std::string url_string = url.url.spec(); |
481 std::wstring url_string_wide = base::UTF8ToWide(url_string); | 485 std::wstring url_string_wide = base::UTF8ToWide(url_string); |
482 link->GetCommandLine()->AppendArgNative(url_string_wide); | 486 link->GetCommandLine()->AppendArgNative(url_string_wide); |
483 link->GetCommandLine()->AppendSwitchASCII( | 487 link->GetCommandLine()->AppendSwitchASCII( |
484 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); | 488 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); |
485 link->set_title(!url.title.empty() ? url.title : url_string_wide); | 489 link->set_title(!url.title.empty() ? url.title : url_string_wide); |
486 data->most_visited_pages_.push_back(link); | 490 data->most_visited_pages_.push_back(link); |
487 data->icon_urls_.push_back(std::make_pair(url_string, link)); | 491 data->icon_urls_.push_back(std::make_pair(url_string, link)); |
488 } | 492 } |
489 data->most_visited_pages_have_updates_ = true; | 493 data->most_visited_pages_have_updates_ = true; |
490 } | 494 } |
491 | 495 |
492 // Send a query that retrieves the first favicon. | 496 // Send a query that retrieves the first favicon. |
493 StartLoadingFavicon(); | 497 StartLoadingFavicon(); |
494 } | 498 } |
495 | 499 |
496 void JumpList::TabRestoreServiceChanged(sessions::TabRestoreService* service) { | 500 void JumpList::TabRestoreServiceChanged(sessions::TabRestoreService* service) { |
497 DCHECK(CalledOnValidThread()); | 501 DCHECK(CalledOnValidThread()); |
| 502 |
498 // if we have a pending favicon request, cancel it here (it is out of date). | 503 // if we have a pending favicon request, cancel it here (it is out of date). |
499 CancelPendingUpdate(); | 504 CancelPendingUpdate(); |
500 | 505 |
501 // Create a list of ShellLinkItems from the "Recently Closed" pages. | 506 // Initialize the one-shot timer to update the the "Recently Closed" category |
502 // As noted above, we create a ShellLinkItem objects with the following | 507 // in a while. If there is already a request queued then cancel it and post |
503 // parameters. | 508 // the new request. This ensures that JumpList update of the "Recently Closed" |
504 // * arguments | 509 // category won't happen until there has been a brief quiet period, thus |
505 // The last URL of the tab object. | 510 // avoiding update storms. |
506 // * title | 511 if (timer_recently_closed_.IsRunning()) { |
507 // The title of the last URL. | 512 timer_recently_closed_.Reset(); |
508 // * icon | 513 } else { |
509 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | 514 timer_recently_closed_.Start( |
510 const int kRecentlyClosedCount = 3; | 515 FROM_HERE, kDelayForJumplistUpdate, |
511 sessions::TabRestoreService* tab_restore_service = | 516 base::Bind(&JumpList::DeferredTabRestoreServiceChanged, |
512 TabRestoreServiceFactory::GetForProfile(profile_); | 517 base::Unretained(this))); |
513 | |
514 { | |
515 JumpListData* data = &jumplist_data_->data; | |
516 base::AutoLock auto_lock(data->list_lock_); | |
517 data->recently_closed_pages_.clear(); | |
518 | |
519 for (const auto& entry : tab_restore_service->entries()) { | |
520 switch (entry->type) { | |
521 case sessions::TabRestoreService::TAB: | |
522 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), | |
523 kRecentlyClosedCount, data); | |
524 break; | |
525 case sessions::TabRestoreService::WINDOW: | |
526 AddWindow( | |
527 static_cast<const sessions::TabRestoreService::Window&>(*entry), | |
528 kRecentlyClosedCount, data); | |
529 break; | |
530 } | |
531 } | |
532 | |
533 data->recently_closed_pages_have_updates_ = true; | |
534 } | 518 } |
535 | |
536 // Send a query that retrieves the first favicon. | |
537 StartLoadingFavicon(); | |
538 } | 519 } |
539 | 520 |
540 void JumpList::TabRestoreServiceDestroyed( | 521 void JumpList::TabRestoreServiceDestroyed( |
541 sessions::TabRestoreService* service) {} | 522 sessions::TabRestoreService* service) {} |
542 | 523 |
543 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, | 524 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, |
544 size_t max_items, | 525 size_t max_items, |
545 JumpListData* data) { | 526 JumpListData* data) { |
546 DCHECK(CalledOnValidThread()); | 527 DCHECK(CalledOnValidThread()); |
547 data->list_lock_.AssertAcquired(); | 528 data->list_lock_.AssertAcquired(); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 // category changes, mark the flags so that icon files for those categories | 649 // category changes, mark the flags so that icon files for those categories |
669 // won't be updated later on. | 650 // won't be updated later on. |
670 if (!waiting_for_icons) | 651 if (!waiting_for_icons) |
671 PostRunUpdate(); | 652 PostRunUpdate(); |
672 } | 653 } |
673 | 654 |
674 void JumpList::PostRunUpdate() { | 655 void JumpList::PostRunUpdate() { |
675 DCHECK(CalledOnValidThread()); | 656 DCHECK(CalledOnValidThread()); |
676 | 657 |
677 TRACE_EVENT0("browser", "JumpList::PostRunUpdate"); | 658 TRACE_EVENT0("browser", "JumpList::PostRunUpdate"); |
678 // Initialize the one-shot timer to update the jumplists in a while. | |
679 // If there is already a request queued then cancel it and post the new | |
680 // request. This ensures that JumpListUpdates won't happen until there has | |
681 // been a brief quiet period, thus avoiding update storms. | |
682 if (timer_.IsRunning()) { | |
683 timer_.Reset(); | |
684 } else { | |
685 timer_.Start(FROM_HERE, kDelayForJumplistUpdate, this, | |
686 &JumpList::DeferredRunUpdate); | |
687 } | |
688 } | |
689 | |
690 void JumpList::DeferredRunUpdate() { | |
691 DCHECK(CalledOnValidThread()); | |
692 | |
693 TRACE_EVENT0("browser", "JumpList::DeferredRunUpdate"); | |
694 if (!profile_) | 659 if (!profile_) |
695 return; | 660 return; |
696 | 661 |
697 base::FilePath profile_dir = profile_->GetPath(); | 662 base::FilePath profile_dir = profile_->GetPath(); |
698 | 663 |
699 // Check if incognito windows (or normal windows) are disabled by policy. | 664 // Check if incognito windows (or normal windows) are disabled by policy. |
700 IncognitoModePrefs::Availability incognito_availability = | 665 IncognitoModePrefs::Availability incognito_availability = |
701 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 666 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); |
702 | 667 |
703 // Post a task to update the JumpList, which consists of 1) delete old icons, | 668 // Post a task to update the JumpList, which consists of 1) delete old icons, |
(...skipping 19 matching lines...) Expand all Loading... |
723 delete_jumplisticons_task_runner_->PostTask( | 688 delete_jumplisticons_task_runner_->PostTask( |
724 FROM_HERE, | 689 FROM_HERE, |
725 base::Bind(&DeleteDirectory, std::move(icon_dir_old), kFileDeleteLimit)); | 690 base::Bind(&DeleteDirectory, std::move(icon_dir_old), kFileDeleteLimit)); |
726 } | 691 } |
727 | 692 |
728 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { | 693 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { |
729 } | 694 } |
730 | 695 |
731 void JumpList::TopSitesChanged(history::TopSites* top_sites, | 696 void JumpList::TopSitesChanged(history::TopSites* top_sites, |
732 ChangeReason change_reason) { | 697 ChangeReason change_reason) { |
733 top_sites->GetMostVisitedURLs( | 698 // If we have a pending favicon request, cancel it here (it is out of date). |
734 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | 699 CancelPendingUpdate(); |
735 weak_ptr_factory_.GetWeakPtr()), | 700 |
736 false); | 701 // Initialize the one-shot timer to update the the "Most visited" category in |
| 702 // a while. If there is already a request queued then cancel it and post the |
| 703 // new request. This ensures that JumpList update of the "Most visited" |
| 704 // category won't happen until there has been a brief quiet period, thus |
| 705 // avoiding update storms. |
| 706 if (timer_most_visited_.IsRunning()) { |
| 707 timer_most_visited_.Reset(); |
| 708 } else { |
| 709 timer_most_visited_.Start( |
| 710 FROM_HERE, kDelayForJumplistUpdate, |
| 711 base::Bind(&JumpList::DeferredTopSitesChanged, base::Unretained(this))); |
| 712 } |
737 } | 713 } |
| 714 |
| 715 void JumpList::DeferredTopSitesChanged() { |
| 716 scoped_refptr<history::TopSites> top_sites = |
| 717 TopSitesFactory::GetForProfile(profile_); |
| 718 if (top_sites) { |
| 719 top_sites->GetMostVisitedURLs( |
| 720 base::Bind(&JumpList::OnMostVisitedURLsAvailable, |
| 721 weak_ptr_factory_.GetWeakPtr()), |
| 722 false); |
| 723 } |
| 724 } |
| 725 |
| 726 void JumpList::DeferredTabRestoreServiceChanged() { |
| 727 // Create a list of ShellLinkItems from the "Recently Closed" pages. |
| 728 // As noted above, we create a ShellLinkItem objects with the following |
| 729 // parameters. |
| 730 // * arguments |
| 731 // The last URL of the tab object. |
| 732 // * title |
| 733 // The title of the last URL. |
| 734 // * icon |
| 735 // An empty string. This value is to be updated in OnFaviconDataAvailable(). |
| 736 const int kRecentlyClosedCount = 3; |
| 737 sessions::TabRestoreService* tab_restore_service = |
| 738 TabRestoreServiceFactory::GetForProfile(profile_); |
| 739 |
| 740 { |
| 741 JumpListData* data = &jumplist_data_->data; |
| 742 base::AutoLock auto_lock(data->list_lock_); |
| 743 data->recently_closed_pages_.clear(); |
| 744 |
| 745 for (const auto& entry : tab_restore_service->entries()) { |
| 746 if (data->recently_closed_pages_.size() >= kRecentlyClosedCount) |
| 747 break; |
| 748 switch (entry->type) { |
| 749 case sessions::TabRestoreService::TAB: |
| 750 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), |
| 751 kRecentlyClosedCount, data); |
| 752 break; |
| 753 case sessions::TabRestoreService::WINDOW: |
| 754 AddWindow( |
| 755 static_cast<const sessions::TabRestoreService::Window&>(*entry), |
| 756 kRecentlyClosedCount, data); |
| 757 break; |
| 758 } |
| 759 } |
| 760 |
| 761 data->recently_closed_pages_have_updates_ = true; |
| 762 } |
| 763 |
| 764 // Send a query that retrieves the first favicon. |
| 765 StartLoadingFavicon(); |
| 766 } |
OLD | NEW |