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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 #include "ui/gfx/image/image_family.h" | 57 #include "ui/gfx/image/image_family.h" |
58 #include "ui/gfx/image/image_skia.h" | 58 #include "ui/gfx/image/image_skia.h" |
59 #include "ui/gfx/image/image_skia_rep.h" | 59 #include "ui/gfx/image/image_skia_rep.h" |
60 #include "url/gurl.h" | 60 #include "url/gurl.h" |
61 | 61 |
62 using content::BrowserThread; | 62 using content::BrowserThread; |
63 using JumpListData = JumpList::JumpListData; | 63 using JumpListData = JumpList::JumpListData; |
64 | 64 |
65 namespace { | 65 namespace { |
66 | 66 |
67 // The maximum allowed number of updates that can be cancelled intentionally due | |
68 // to one jumplist updater timeout. | |
69 constexpr int kCancelledUpdates = 10; | |
gab
2017/05/11 14:48:24
Feels like we should delay for a period of time, e
chengx
2017/05/11 16:41:43
I did think about delaying for a period of time. B
| |
70 | |
67 // The delay before updating the JumpList to prevent update storms. | 71 // The delay before updating the JumpList to prevent update storms. |
68 constexpr base::TimeDelta kDelayForJumplistUpdate = | 72 constexpr base::TimeDelta kDelayForJumplistUpdate = |
69 base::TimeDelta::FromMilliseconds(3500); | 73 base::TimeDelta::FromMilliseconds(3500); |
70 | 74 |
71 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking | 75 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking |
72 // longer than this are discarded to prevent bogging down slow machines. | 76 // longer than this are discarded to prevent bogging down slow machines. |
73 constexpr base::TimeDelta kTimeOutForJumplistUpdate = | 77 constexpr base::TimeDelta kTimeOutForJumplistBeginUpdate = |
74 base::TimeDelta::FromMilliseconds(500); | 78 base::TimeDelta::FromMilliseconds(500); |
75 | 79 |
80 // The maximum allowed time for updating both "most visited" and "recently | |
81 // closed" categories via JumpListUpdater::AddCustomCategory. | |
82 constexpr base::TimeDelta kTimeOutForAddCustomCategory = | |
83 base::TimeDelta::FromMilliseconds(500); | |
84 | |
85 // The maximum allowed time for JumpListUpdater::CommitUpdate. | |
86 constexpr base::TimeDelta kTimeOutForJumplistCommitUpdate = | |
87 base::TimeDelta::FromMilliseconds(1000); | |
88 | |
76 // Appends the common switches to each shell link. | 89 // Appends the common switches to each shell link. |
77 void AppendCommonSwitches(ShellLinkItem* shell_link) { | 90 void AppendCommonSwitches(ShellLinkItem* shell_link) { |
78 const char* kSwitchNames[] = { switches::kUserDataDir }; | 91 const char* kSwitchNames[] = { switches::kUserDataDir }; |
79 const base::CommandLine& command_line = | 92 const base::CommandLine& command_line = |
80 *base::CommandLine::ForCurrentProcess(); | 93 *base::CommandLine::ForCurrentProcess(); |
81 shell_link->GetCommandLine()->CopySwitchesFrom(command_line, | 94 shell_link->GetCommandLine()->CopySwitchesFrom(command_line, |
82 kSwitchNames, | 95 kSwitchNames, |
83 arraysize(kSwitchNames)); | 96 arraysize(kSwitchNames)); |
84 } | 97 } |
85 | 98 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 } // namespace | 196 } // namespace |
184 | 197 |
185 JumpList::JumpListData::JumpListData() {} | 198 JumpList::JumpListData::JumpListData() {} |
186 | 199 |
187 JumpList::JumpListData::~JumpListData() {} | 200 JumpList::JumpListData::~JumpListData() {} |
188 | 201 |
189 JumpList::JumpList(Profile* profile) | 202 JumpList::JumpList(Profile* profile) |
190 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( | 203 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( |
191 content::BrowserThread::UI)), | 204 content::BrowserThread::UI)), |
192 profile_(profile), | 205 profile_(profile), |
206 cancelled_update_count_(0), | |
207 jumplist_updater_timeout_(false), | |
193 jumplist_data_(new base::RefCountedData<JumpListData>), | 208 jumplist_data_(new base::RefCountedData<JumpListData>), |
194 task_id_(base::CancelableTaskTracker::kBadTaskId), | 209 task_id_(base::CancelableTaskTracker::kBadTaskId), |
195 update_jumplist_task_runner_(base::CreateCOMSTATaskRunnerWithTraits( | 210 update_jumplist_task_runner_(base::CreateCOMSTATaskRunnerWithTraits( |
196 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, | 211 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, |
197 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), | 212 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), |
198 delete_jumplisticons_task_runner_( | 213 delete_jumplisticons_task_runner_( |
199 base::CreateSequencedTaskRunnerWithTraits( | 214 base::CreateSequencedTaskRunnerWithTraits( |
200 {base::MayBlock(), base::TaskPriority::BACKGROUND, | 215 {base::MayBlock(), base::TaskPriority::BACKGROUND, |
201 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), | 216 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), |
202 weak_ptr_factory_(this) { | 217 weak_ptr_factory_(this) { |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 // avoiding update storms. | 530 // avoiding update storms. |
516 if (timer_most_visited_.IsRunning()) { | 531 if (timer_most_visited_.IsRunning()) { |
517 timer_most_visited_.Reset(); | 532 timer_most_visited_.Reset(); |
518 } else { | 533 } else { |
519 timer_most_visited_.Start( | 534 timer_most_visited_.Start( |
520 FROM_HERE, kDelayForJumplistUpdate, | 535 FROM_HERE, kDelayForJumplistUpdate, |
521 base::Bind(&JumpList::DeferredTopSitesChanged, base::Unretained(this))); | 536 base::Bind(&JumpList::DeferredTopSitesChanged, base::Unretained(this))); |
522 } | 537 } |
523 } | 538 } |
524 | 539 |
540 bool JumpList::CheckAndUpdateTimeoutInfo() { | |
541 if (jumplist_updater_timeout_ && | |
542 ++cancelled_update_count_ > kCancelledUpdates) { | |
543 jumplist_updater_timeout_ = false; | |
544 cancelled_update_count_ = 0; | |
545 } | |
546 return jumplist_updater_timeout_; | |
547 } | |
548 | |
525 void JumpList::DeferredTopSitesChanged() { | 549 void JumpList::DeferredTopSitesChanged() { |
550 if (CheckAndUpdateTimeoutInfo()) | |
551 return; | |
552 | |
526 scoped_refptr<history::TopSites> top_sites = | 553 scoped_refptr<history::TopSites> top_sites = |
527 TopSitesFactory::GetForProfile(profile_); | 554 TopSitesFactory::GetForProfile(profile_); |
528 if (top_sites) { | 555 if (top_sites) { |
529 top_sites->GetMostVisitedURLs( | 556 top_sites->GetMostVisitedURLs( |
530 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | 557 base::Bind(&JumpList::OnMostVisitedURLsAvailable, |
531 weak_ptr_factory_.GetWeakPtr()), | 558 weak_ptr_factory_.GetWeakPtr()), |
532 false); | 559 false); |
533 } | 560 } |
534 } | 561 } |
535 | 562 |
536 void JumpList::DeferredTabRestoreServiceChanged() { | 563 void JumpList::DeferredTabRestoreServiceChanged() { |
564 if (CheckAndUpdateTimeoutInfo()) | |
565 return; | |
566 | |
537 // Create a list of ShellLinkItems from the "Recently Closed" pages. | 567 // Create a list of ShellLinkItems from the "Recently Closed" pages. |
538 // As noted above, we create a ShellLinkItem objects with the following | 568 // As noted above, we create a ShellLinkItem objects with the following |
539 // parameters. | 569 // parameters. |
540 // * arguments | 570 // * arguments |
541 // The last URL of the tab object. | 571 // The last URL of the tab object. |
542 // * title | 572 // * title |
543 // The title of the last URL. | 573 // The title of the last URL. |
544 // * icon | 574 // * icon |
545 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | 575 // An empty string. This value is to be updated in OnFaviconDataAvailable(). |
546 const int kRecentlyClosedCount = 3; | 576 const int kRecentlyClosedCount = 3; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 JumpListUpdater jumplist_updater(app_id); | 643 JumpListUpdater jumplist_updater(app_id); |
614 | 644 |
615 base::ElapsedTimer begin_update_timer; | 645 base::ElapsedTimer begin_update_timer; |
616 | 646 |
617 if (!jumplist_updater.BeginUpdate()) | 647 if (!jumplist_updater.BeginUpdate()) |
618 return false; | 648 return false; |
619 | 649 |
620 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer | 650 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer |
621 // than the maximum allowed time, as it's very likely the following update | 651 // than the maximum allowed time, as it's very likely the following update |
622 // steps will also take a long time. | 652 // steps will also take a long time. |
623 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistUpdate) | 653 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) { |
654 jumplist_updater_timeout_ = true; | |
624 return false; | 655 return false; |
656 } | |
625 | 657 |
626 // The default maximum number of items to display in JumpList is 10. | 658 // The default maximum number of items to display in JumpList is 10. |
627 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx | 659 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx |
628 // The "Most visited" category title always takes 1 of the JumpList slots if | 660 // The "Most visited" category title always takes 1 of the JumpList slots if |
629 // |most_visited_pages| isn't empty. | 661 // |most_visited_pages| isn't empty. |
630 // The "Recently closed" category title will also take 1 if | 662 // The "Recently closed" category title will also take 1 if |
631 // |recently_closed_pages| isn't empty. | 663 // |recently_closed_pages| isn't empty. |
632 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories | 664 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories |
633 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories | 665 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories |
634 // present) to "recently-closed" items, respectively. | 666 // present) to "recently-closed" items, respectively. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
679 icons_to_create += | 711 icons_to_create += |
680 std::min(recently_closed_pages.size(), recently_closed_items); | 712 std::min(recently_closed_pages.size(), recently_closed_items); |
681 } | 713 } |
682 | 714 |
683 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 715 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
684 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); | 716 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); |
685 | 717 |
686 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 718 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
687 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | 719 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); |
688 | 720 |
721 base::ElapsedTimer add_custom_category_timer; | |
722 | |
689 // Update the "Most Visited" category of the JumpList if it exists. | 723 // Update the "Most Visited" category of the JumpList if it exists. |
690 // This update request is applied into the JumpList when we commit this | 724 // This update request is applied into the JumpList when we commit this |
691 // transaction. | 725 // transaction. |
692 if (!jumplist_updater.AddCustomCategory( | 726 if (!jumplist_updater.AddCustomCategory( |
693 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | 727 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), |
694 most_visited_pages, most_visited_items)) { | 728 most_visited_pages, most_visited_items)) { |
695 return false; | 729 return false; |
696 } | 730 } |
697 | 731 |
698 // Update the "Recently Closed" category of the JumpList. | 732 // Update the "Recently Closed" category of the JumpList. |
699 if (!jumplist_updater.AddCustomCategory( | 733 if (!jumplist_updater.AddCustomCategory( |
700 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, | 734 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, |
701 recently_closed_items)) { | 735 recently_closed_items)) { |
702 return false; | 736 return false; |
703 } | 737 } |
704 | 738 |
739 // If JumpListUpdater::AddCustomCategory takes longer than the maximum allowed | |
740 // time, mark the flag but continue with this update. | |
741 if (add_custom_category_timer.Elapsed() >= kTimeOutForAddCustomCategory) | |
742 jumplist_updater_timeout_ = true; | |
743 | |
705 // Update the "Tasks" category of the JumpList. | 744 // Update the "Tasks" category of the JumpList. |
706 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | 745 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) |
707 return false; | 746 return false; |
708 | 747 |
748 base::ElapsedTimer commit_update_timer; | |
749 | |
709 // Commit this transaction and send the updated JumpList to Windows. | 750 // Commit this transaction and send the updated JumpList to Windows. |
710 return jumplist_updater.CommitUpdate(); | 751 bool commit_result = jumplist_updater.CommitUpdate(); |
752 | |
753 // If JumpListUpdater::CommitUpdate takes longer than the maximum allowed | |
754 // time, mark the flag but continue with this update. | |
755 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) | |
756 jumplist_updater_timeout_ = true; | |
757 | |
758 return commit_result; | |
711 } | 759 } |
712 | 760 |
713 void JumpList::RunUpdateJumpList( | 761 void JumpList::RunUpdateJumpList( |
714 IncognitoModePrefs::Availability incognito_availability, | 762 IncognitoModePrefs::Availability incognito_availability, |
715 const base::string16& app_id, | 763 const base::string16& app_id, |
716 const base::FilePath& profile_dir, | 764 const base::FilePath& profile_dir, |
717 base::RefCountedData<JumpListData>* ref_counted_data) { | 765 base::RefCountedData<JumpListData>* ref_counted_data) { |
718 JumpListData* data = &ref_counted_data->data; | 766 JumpListData* data = &ref_counted_data->data; |
719 ShellLinkItemList local_most_visited_pages; | 767 ShellLinkItemList local_most_visited_pages; |
720 ShellLinkItemList local_recently_closed_pages; | 768 ShellLinkItemList local_recently_closed_pages; |
(...skipping 30 matching lines...) Expand all Loading... | |
751 app_id, profile_dir, local_most_visited_pages, | 799 app_id, profile_dir, local_most_visited_pages, |
752 local_recently_closed_pages, most_visited_pages_have_updates, | 800 local_recently_closed_pages, most_visited_pages_have_updates, |
753 recently_closed_pages_have_updates, incognito_availability)) { | 801 recently_closed_pages_have_updates, incognito_availability)) { |
754 base::AutoLock auto_lock(data->list_lock_); | 802 base::AutoLock auto_lock(data->list_lock_); |
755 if (most_visited_pages_have_updates) | 803 if (most_visited_pages_have_updates) |
756 data->most_visited_pages_have_updates_ = true; | 804 data->most_visited_pages_have_updates_ = true; |
757 if (recently_closed_pages_have_updates) | 805 if (recently_closed_pages_have_updates) |
758 data->recently_closed_pages_have_updates_ = true; | 806 data->recently_closed_pages_have_updates_ = true; |
759 } | 807 } |
760 } | 808 } |
OLD | NEW |