Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: chrome/browser/win/jumplist.cc

Issue 2865133003: Defer syncing TopSites with history until the first tab closure (Closed)
Patch Set: Git pull and fix merge conflicts Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/win/jumplist.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include "ui/gfx/image/image_family.h" 49 #include "ui/gfx/image/image_family.h"
50 #include "ui/gfx/image/image_skia.h" 50 #include "ui/gfx/image/image_skia.h"
51 #include "ui/gfx/image/image_skia_rep.h" 51 #include "ui/gfx/image/image_skia_rep.h"
52 #include "url/gurl.h" 52 #include "url/gurl.h"
53 53
54 using content::BrowserThread; 54 using content::BrowserThread;
55 using JumpListData = JumpList::JumpListData; 55 using JumpListData = JumpList::JumpListData;
56 56
57 namespace { 57 namespace {
58 58
59 // The default maximum number of items to display in JumpList is 10.
60 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx
61 // The "Most visited" and "Recently closed" category titles always take 2 slots.
62 // For the remaining 8 slots, we allocate 5 slots to "most-visited" items and 3
63 // slots to"recently-closed" items, respectively.
64 constexpr size_t kMostVisitedItems = 5;
65 constexpr size_t kRecentlyClosedItems = 3;
66
59 // The number of updates to skip to alleviate the machine when a previous update 67 // The number of updates to skip to alleviate the machine when a previous update
60 // was too slow. 68 // was too slow.
61 constexpr int kUpdatesToSkipUnderHeavyLoad = 10; 69 constexpr int kUpdatesToSkipUnderHeavyLoad = 10;
62 70
63 // The delay before updating the JumpList to prevent update storms. 71 // The delay before updating the JumpList to prevent update storms.
64 constexpr base::TimeDelta kDelayForJumplistUpdate = 72 constexpr base::TimeDelta kDelayForJumplistUpdate =
65 base::TimeDelta::FromMilliseconds(3500); 73 base::TimeDelta::FromMilliseconds(3500);
66 74
67 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking 75 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking
68 // longer than this are discarded to prevent bogging down slow machines. 76 // longer than this are discarded to prevent bogging down slow machines.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 TabRestoreServiceFactory::GetForProfile(profile_); 223 TabRestoreServiceFactory::GetForProfile(profile_);
216 if (!tab_restore_service) 224 if (!tab_restore_service)
217 return; 225 return;
218 226
219 app_id_ = 227 app_id_ =
220 shell_integration::win::GetChromiumModelIdForProfile(profile_->GetPath()); 228 shell_integration::win::GetChromiumModelIdForProfile(profile_->GetPath());
221 229
222 scoped_refptr<history::TopSites> top_sites = 230 scoped_refptr<history::TopSites> top_sites =
223 TopSitesFactory::GetForProfile(profile_); 231 TopSitesFactory::GetForProfile(profile_);
224 if (top_sites) { 232 if (top_sites) {
225 // TopSites updates itself after a delay. This is especially noticable when
226 // your profile is empty. Ask TopSites to update itself when jumplist is
227 // initialized.
228 top_sites->SyncWithHistory();
229 // Register as TopSitesObserver so that we can update ourselves when the 233 // Register as TopSitesObserver so that we can update ourselves when the
230 // TopSites changes. 234 // TopSites changes. TopSites updates itself after a delay. This is
235 // especially noticable when your profile is empty.
231 top_sites->AddObserver(this); 236 top_sites->AddObserver(this);
232 } 237 }
233 tab_restore_service->AddObserver(this); 238 tab_restore_service->AddObserver(this);
234 pref_change_registrar_.reset(new PrefChangeRegistrar); 239 pref_change_registrar_.reset(new PrefChangeRegistrar);
235 pref_change_registrar_->Init(profile_->GetPrefs()); 240 pref_change_registrar_->Init(profile_->GetPrefs());
236 pref_change_registrar_->Add( 241 pref_change_registrar_->Add(
237 prefs::kIncognitoModeAvailability, 242 prefs::kIncognitoModeAvailability,
238 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this)); 243 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this));
239 } 244 }
240 245
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 282
278 void JumpList::ShutdownOnUIThread() { 283 void JumpList::ShutdownOnUIThread() {
279 DCHECK(CalledOnValidThread()); 284 DCHECK(CalledOnValidThread());
280 Terminate(); 285 Terminate();
281 } 286 }
282 287
283 void JumpList::OnMostVisitedURLsAvailable( 288 void JumpList::OnMostVisitedURLsAvailable(
284 const history::MostVisitedURLList& urls) { 289 const history::MostVisitedURLList& urls) {
285 DCHECK(CalledOnValidThread()); 290 DCHECK(CalledOnValidThread());
286 291
287 // At most 9 JumpList items can be displayed for the "Most Visited"
288 // category.
289 const int kMostVistedCount = 9;
290 { 292 {
291 JumpListData* data = &jumplist_data_->data; 293 JumpListData* data = &jumplist_data_->data;
292 base::AutoLock auto_lock(data->list_lock_); 294 base::AutoLock auto_lock(data->list_lock_);
293 data->most_visited_pages_.clear(); 295 data->most_visited_pages_.clear();
294 296
295 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { 297 for (size_t i = 0; i < urls.size() && i < kMostVisitedItems; i++) {
296 const history::MostVisitedURL& url = urls[i]; 298 const history::MostVisitedURL& url = urls[i];
297 scoped_refptr<ShellLinkItem> link = CreateShellLink(); 299 scoped_refptr<ShellLinkItem> link = CreateShellLink();
298 std::string url_string = url.url.spec(); 300 std::string url_string = url.url.spec();
299 base::string16 url_string_wide = base::UTF8ToUTF16(url_string); 301 base::string16 url_string_wide = base::UTF8ToUTF16(url_string);
300 link->GetCommandLine()->AppendArgNative(url_string_wide); 302 link->GetCommandLine()->AppendArgNative(url_string_wide);
301 link->GetCommandLine()->AppendSwitchASCII( 303 link->GetCommandLine()->AppendSwitchASCII(
302 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); 304 switches::kWinJumplistAction, jumplist::kMostVisitedCategory);
303 link->set_title(!url.title.empty() ? url.title : url_string_wide); 305 link->set_title(!url.title.empty() ? url.title : url_string_wide);
304 link->set_url(url_string); 306 link->set_url(url_string);
305 data->most_visited_pages_.push_back(link); 307 data->most_visited_pages_.push_back(link);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 if (timer_most_visited_.IsRunning()) { 525 if (timer_most_visited_.IsRunning()) {
524 timer_most_visited_.Reset(); 526 timer_most_visited_.Reset();
525 } else { 527 } else {
526 timer_most_visited_.Start( 528 timer_most_visited_.Start(
527 FROM_HERE, kDelayForJumplistUpdate, 529 FROM_HERE, kDelayForJumplistUpdate,
528 base::Bind(&JumpList::DeferredTopSitesChanged, base::Unretained(this))); 530 base::Bind(&JumpList::DeferredTopSitesChanged, base::Unretained(this)));
529 } 531 }
530 } 532 }
531 533
532 void JumpList::DeferredTopSitesChanged() { 534 void JumpList::DeferredTopSitesChanged() {
535 DCHECK(CalledOnValidThread());
536
533 if (updates_to_skip_ > 0) { 537 if (updates_to_skip_ > 0) {
534 --updates_to_skip_; 538 --updates_to_skip_;
535 return; 539 return;
536 } 540 }
537 541
542 // Opening the first tab in one session triggers a TopSite history sync.
543 // Delay this sync till the first tab is closed to allow the "recently closed"
544 // category from last session to stay longer.
545 if (!has_tab_closed_)
546 return;
547
538 scoped_refptr<history::TopSites> top_sites = 548 scoped_refptr<history::TopSites> top_sites =
539 TopSitesFactory::GetForProfile(profile_); 549 TopSitesFactory::GetForProfile(profile_);
540 if (top_sites) { 550 if (top_sites) {
541 top_sites->GetMostVisitedURLs( 551 top_sites->GetMostVisitedURLs(
542 base::Bind(&JumpList::OnMostVisitedURLsAvailable, 552 base::Bind(&JumpList::OnMostVisitedURLsAvailable,
543 weak_ptr_factory_.GetWeakPtr()), 553 weak_ptr_factory_.GetWeakPtr()),
544 false); 554 false);
545 } 555 }
546 } 556 }
547 557
548 void JumpList::DeferredTabRestoreServiceChanged() { 558 void JumpList::DeferredTabRestoreServiceChanged() {
559 DCHECK(CalledOnValidThread());
560
549 if (updates_to_skip_ > 0) { 561 if (updates_to_skip_ > 0) {
550 --updates_to_skip_; 562 --updates_to_skip_;
551 return; 563 return;
552 } 564 }
553 565
566 // Force a TopSite history sync when closing a first tab in one session.
567 if (!has_tab_closed_) {
568 has_tab_closed_ = true;
569 scoped_refptr<history::TopSites> top_sites =
570 TopSitesFactory::GetForProfile(profile_);
571 if (top_sites)
572 top_sites->SyncWithHistory();
573 }
574
554 // Create a list of ShellLinkItems from the "Recently Closed" pages. 575 // Create a list of ShellLinkItems from the "Recently Closed" pages.
555 // As noted above, we create a ShellLinkItem objects with the following 576 // As noted above, we create a ShellLinkItem objects with the following
556 // parameters. 577 // parameters.
557 // * arguments 578 // * arguments
558 // The last URL of the tab object. 579 // The last URL of the tab object.
559 // * title 580 // * title
560 // The title of the last URL. 581 // The title of the last URL.
561 // * icon 582 // * icon
562 // An empty string. This value is to be updated in OnFaviconDataAvailable(). 583 // An empty string. This value is to be updated in OnFaviconDataAvailable().
563 const int kRecentlyClosedCount = 3; 584
564 sessions::TabRestoreService* tab_restore_service = 585 sessions::TabRestoreService* tab_restore_service =
565 TabRestoreServiceFactory::GetForProfile(profile_); 586 TabRestoreServiceFactory::GetForProfile(profile_);
566 587
567 { 588 {
568 JumpListData* data = &jumplist_data_->data; 589 JumpListData* data = &jumplist_data_->data;
569 base::AutoLock auto_lock(data->list_lock_); 590 base::AutoLock auto_lock(data->list_lock_);
570 data->recently_closed_pages_.clear(); 591 data->recently_closed_pages_.clear();
571 592
572 for (const auto& entry : tab_restore_service->entries()) { 593 for (const auto& entry : tab_restore_service->entries()) {
573 if (data->recently_closed_pages_.size() >= kRecentlyClosedCount) 594 if (data->recently_closed_pages_.size() >= kRecentlyClosedItems)
574 break; 595 break;
575 switch (entry->type) { 596 switch (entry->type) {
576 case sessions::TabRestoreService::TAB: 597 case sessions::TabRestoreService::TAB:
577 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), 598 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry),
578 kRecentlyClosedCount, data); 599 kRecentlyClosedItems, data);
579 break; 600 break;
580 case sessions::TabRestoreService::WINDOW: 601 case sessions::TabRestoreService::WINDOW:
581 AddWindow( 602 AddWindow(
582 static_cast<const sessions::TabRestoreService::Window&>(*entry), 603 static_cast<const sessions::TabRestoreService::Window&>(*entry),
583 kRecentlyClosedCount, data); 604 kRecentlyClosedItems, data);
584 break; 605 break;
585 } 606 }
586 } 607 }
587 608
588 data->recently_closed_pages_have_updates_ = true; 609 data->recently_closed_pages_have_updates_ = true;
589 } 610 }
590 611
591 // Send a query that retrieves the first favicon. 612 // Send a query that retrieves the first favicon.
592 StartLoadingFavicon(); 613 StartLoadingFavicon();
593 } 614 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 725
705 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer 726 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer
706 // than the maximum allowed time, as it's very likely the following update 727 // than the maximum allowed time, as it's very likely the following update
707 // steps will also take a long time. As we've not updated the icons on the 728 // steps will also take a long time. As we've not updated the icons on the
708 // disk, discarding this update wont't affect the current JumpList used by OS. 729 // disk, discarding this update wont't affect the current JumpList used by OS.
709 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) { 730 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) {
710 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; 731 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad;
711 return false; 732 return false;
712 } 733 }
713 734
714 // The default maximum number of items to display in JumpList is 10.
715 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx
716 // The "Most visited" category title always takes 1 of the JumpList slots if
717 // |most_visited_pages| isn't empty.
718 // The "Recently closed" category title will also take 1 if
719 // |recently_closed_pages| isn't empty.
720 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories
721 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories
722 // present) to "recently-closed" items, respectively.
723 // Nevertheless, if there are not so many items in |recently_closed_pages|,
724 // we give the remaining slots to "most-visited" items.
725
726 const int kMostVisited = 50;
727 const int kRecentlyClosed = 30;
728 const int kTotal = kMostVisited + kRecentlyClosed;
729
730 // Adjust the available jumplist slots to account for the category titles.
731 size_t user_max_items_adjusted = jumplist_updater.user_max_items();
732 if (!most_visited_pages.empty())
733 --user_max_items_adjusted;
734 if (!recently_closed_pages.empty())
735 --user_max_items_adjusted;
736
737 size_t most_visited_items =
738 MulDiv(user_max_items_adjusted, kMostVisited, kTotal);
739 size_t recently_closed_items = user_max_items_adjusted - most_visited_items;
740 if (recently_closed_pages.size() < recently_closed_items) {
741 most_visited_items += recently_closed_items - recently_closed_pages.size();
742 recently_closed_items = recently_closed_pages.size();
743 }
744
745 // Record the desired number of icons to create in this JumpList update. 735 // Record the desired number of icons to create in this JumpList update.
746 int icons_to_create = 0; 736 int icons_to_create = 0;
747 737
748 // Update the icons for "Most Visisted" category of the JumpList if needed. 738 // Update the icons for "Most Visisted" category of the JumpList if needed.
749 if (most_visited_pages_have_updates) { 739 if (most_visited_pages_have_updates) {
750 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( 740 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName(
751 profile_dir, FILE_PATH_LITERAL("MostVisited")); 741 profile_dir, FILE_PATH_LITERAL("MostVisited"));
752 742
753 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, 743 UpdateIconFiles(icon_dir_most_visited, most_visited_pages,
754 most_visited_items, JumpListCategory::kMostVisited); 744 kMostVisitedItems, JumpListCategory::kMostVisited);
755 745
756 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); 746 icons_to_create += std::min(most_visited_pages.size(), kMostVisitedItems);
757 } 747 }
758 748
759 // Update the icons for "Recently Closed" category of the JumpList if needed. 749 // Update the icons for "Recently Closed" category of the JumpList if needed.
760 if (recently_closed_pages_have_updates) { 750 if (recently_closed_pages_have_updates) {
761 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( 751 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName(
762 profile_dir, FILE_PATH_LITERAL("RecentClosed")); 752 profile_dir, FILE_PATH_LITERAL("RecentClosed"));
763 753
764 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, 754 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages,
765 recently_closed_items, JumpListCategory::kRecentlyClosed); 755 kRecentlyClosedItems, JumpListCategory::kRecentlyClosed);
766 756
767 icons_to_create += 757 icons_to_create +=
768 std::min(recently_closed_pages.size(), recently_closed_items); 758 std::min(recently_closed_pages.size(), kRecentlyClosedItems);
769 } 759 }
770 760
771 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. 761 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407.
772 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); 762 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create);
773 763
774 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. 764 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407.
775 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); 765 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration");
776 766
777 base::ElapsedTimer add_custom_category_timer; 767 base::ElapsedTimer add_custom_category_timer;
778 768
779 // Update the "Most Visited" category of the JumpList if it exists. 769 // Update the "Most Visited" category of the JumpList if it exists.
780 // This update request is applied into the JumpList when we commit this 770 // This update request is applied into the JumpList when we commit this
781 // transaction. 771 // transaction.
782 if (!jumplist_updater.AddCustomCategory( 772 if (!jumplist_updater.AddCustomCategory(
783 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), 773 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED),
784 most_visited_pages, most_visited_items)) { 774 most_visited_pages, kMostVisitedItems)) {
785 return false; 775 return false;
786 } 776 }
787 777
788 // Update the "Recently Closed" category of the JumpList. 778 // Update the "Recently Closed" category of the JumpList.
789 if (!jumplist_updater.AddCustomCategory( 779 if (!jumplist_updater.AddCustomCategory(
790 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, 780 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages,
791 recently_closed_items)) { 781 kRecentlyClosedItems)) {
792 return false; 782 return false;
793 } 783 }
794 784
795 // If JumpListUpdater::AddCustomCategory or JumpListUpdater::CommitUpdate 785 // If JumpListUpdater::AddCustomCategory or JumpListUpdater::CommitUpdate
796 // takes longer than the maximum allowed time, skip the next 786 // takes longer than the maximum allowed time, skip the next
797 // |kUpdatesToSkipUnderHeavyLoad| updates. This update should be finished 787 // |kUpdatesToSkipUnderHeavyLoad| updates. This update should be finished
798 // because we've already updated the icons on the disk. If discarding this 788 // because we've already updated the icons on the disk. If discarding this
799 // update from here, some items in the current JumpList may not have icons 789 // update from here, some items in the current JumpList may not have icons
800 // as they've been delete from the disk. In this case, the background color of 790 // as they've been delete from the disk. In this case, the background color of
801 // the JumpList panel is used instead, which doesn't look nice. 791 // the JumpList panel is used instead, which doesn't look nice.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 app_id, profile_dir, local_most_visited_pages, 849 app_id, profile_dir, local_most_visited_pages,
860 local_recently_closed_pages, most_visited_pages_have_updates, 850 local_recently_closed_pages, most_visited_pages_have_updates,
861 recently_closed_pages_have_updates, incognito_availability)) { 851 recently_closed_pages_have_updates, incognito_availability)) {
862 base::AutoLock auto_lock(data->list_lock_); 852 base::AutoLock auto_lock(data->list_lock_);
863 if (most_visited_pages_have_updates) 853 if (most_visited_pages_have_updates)
864 data->most_visited_pages_have_updates_ = true; 854 data->most_visited_pages_have_updates_ = true;
865 if (recently_closed_pages_have_updates) 855 if (recently_closed_pages_have_updates)
866 data->recently_closed_pages_have_updates_ = true; 856 data->recently_closed_pages_have_updates_ = true;
867 } 857 }
868 } 858 }
OLDNEW
« no previous file with comments | « chrome/browser/win/jumplist.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698