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 <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 |