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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 | 69 |
70 // The delay before updating the JumpList to prevent update storms. | 70 // The delay before updating the JumpList to prevent update storms. |
71 constexpr base::TimeDelta kDelayForJumplistUpdate = | 71 constexpr base::TimeDelta kDelayForJumplistUpdate = |
72 base::TimeDelta::FromMilliseconds(3500); | 72 base::TimeDelta::FromMilliseconds(3500); |
73 | 73 |
74 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking | 74 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking |
75 // longer than this are discarded to prevent bogging down slow machines. | 75 // longer than this are discarded to prevent bogging down slow machines. |
76 constexpr base::TimeDelta kTimeOutForJumplistBeginUpdate = | 76 constexpr base::TimeDelta kTimeOutForJumplistBeginUpdate = |
77 base::TimeDelta::FromMilliseconds(500); | 77 base::TimeDelta::FromMilliseconds(500); |
78 | 78 |
79 // The maximum allowed time for updating both "most visited" and "recently | 79 // The maximum allowed time for updating the "most visited" category via |
80 // closed" categories via JumpListUpdater::AddCustomCategory. | 80 // JumpListUpdater::AddCustomCategory. |
81 constexpr base::TimeDelta kTimeOutForAddCustomCategory = | 81 constexpr base::TimeDelta kTimeOutForAddCustomCategory = |
82 base::TimeDelta::FromMilliseconds(500); | 82 base::TimeDelta::FromMilliseconds(300); |
grt (UTC plus 2)
2017/06/24 20:40:28
is this change worth mentioning in the CL descript
chengx
2017/06/25 02:32:09
Originally we were monitoring the total runtime of
| |
83 | 83 |
84 // The maximum allowed time for JumpListUpdater::CommitUpdate. | 84 // The maximum allowed time for JumpListUpdater::CommitUpdate. |
85 constexpr base::TimeDelta kTimeOutForJumplistCommitUpdate = | 85 constexpr base::TimeDelta kTimeOutForJumplistCommitUpdate = |
86 base::TimeDelta::FromMilliseconds(1000); | 86 base::TimeDelta::FromMilliseconds(1000); |
87 | 87 |
88 // Appends the common switches to each shell link. | 88 // Appends the common switches to each shell link. |
89 void AppendCommonSwitches(ShellLinkItem* shell_link) { | 89 void AppendCommonSwitches(ShellLinkItem* shell_link) { |
90 const char* kSwitchNames[] = { switches::kUserDataDir }; | 90 const char* kSwitchNames[] = { switches::kUserDataDir }; |
91 const base::CommandLine& command_line = | 91 const base::CommandLine& command_line = |
92 *base::CommandLine::ForCurrentProcess(); | 92 *base::CommandLine::ForCurrentProcess(); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 base::FilePath GenerateJumplistIconDirName( | 187 base::FilePath GenerateJumplistIconDirName( |
188 const base::FilePath& profile_dir, | 188 const base::FilePath& profile_dir, |
189 const base::FilePath::StringPieceType& suffix) { | 189 const base::FilePath::StringPieceType& suffix) { |
190 base::FilePath::StringType dir_name(chrome::kJumpListIconDirname); | 190 base::FilePath::StringType dir_name(chrome::kJumpListIconDirname); |
191 suffix.AppendToString(&dir_name); | 191 suffix.AppendToString(&dir_name); |
192 return profile_dir.Append(dir_name); | 192 return profile_dir.Append(dir_name); |
193 } | 193 } |
194 | 194 |
195 } // namespace | 195 } // namespace |
196 | 196 |
197 JumpList::UpdateResults::UpdateResults() {} | 197 JumpList::UpdateTransaction::UpdateTransaction() {} |
198 | 198 |
199 JumpList::UpdateResults::~UpdateResults() {} | 199 JumpList::UpdateTransaction::~UpdateTransaction() {} |
200 | 200 |
201 // static | 201 // static |
202 bool JumpList::Enabled() { | 202 bool JumpList::Enabled() { |
203 return JumpListUpdater::IsEnabled(); | 203 return JumpListUpdater::IsEnabled(); |
204 } | 204 } |
205 | 205 |
206 void JumpList::Shutdown() { | 206 void JumpList::Shutdown() { |
207 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 207 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
208 Terminate(); | 208 Terminate(); |
209 } | 209 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 sessions::TabRestoreService* service) {} | 299 sessions::TabRestoreService* service) {} |
300 | 300 |
301 void JumpList::OnIncognitoAvailabilityChanged() { | 301 void JumpList::OnIncognitoAvailabilityChanged() { |
302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
303 | 303 |
304 if (icon_urls_.empty()) | 304 if (icon_urls_.empty()) |
305 PostRunUpdate(); | 305 PostRunUpdate(); |
306 } | 306 } |
307 | 307 |
308 void JumpList::InitializeTimerForUpdate() { | 308 void JumpList::InitializeTimerForUpdate() { |
309 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
310 | |
309 if (timer_.IsRunning()) { | 311 if (timer_.IsRunning()) { |
310 timer_.Reset(); | 312 timer_.Reset(); |
311 } else { | 313 } else { |
312 // base::Unretained is safe since |this| is guaranteed to outlive timer_. | 314 // base::Unretained is safe since |this| is guaranteed to outlive timer_. |
313 timer_.Start(FROM_HERE, kDelayForJumplistUpdate, | 315 timer_.Start(FROM_HERE, kDelayForJumplistUpdate, |
314 base::Bind(&JumpList::OnDelayTimer, base::Unretained(this))); | 316 base::Bind(&JumpList::OnDelayTimer, base::Unretained(this))); |
315 } | 317 } |
316 } | 318 } |
317 | 319 |
318 void JumpList::OnDelayTimer() { | 320 void JumpList::OnDelayTimer() { |
319 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 321 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
322 DCHECK(!update_in_progress_); | |
320 | 323 |
321 if (updates_to_skip_ > 0) { | 324 if (updates_to_skip_ > 0) { |
322 --updates_to_skip_; | 325 --updates_to_skip_; |
323 return; | 326 return; |
324 } | 327 } |
325 | 328 |
326 // Retrieve the recently closed URLs synchronously. | 329 // Retrieve the recently closed URLs synchronously. |
327 if (tab_restore_has_pending_notification_) { | 330 if (tab_restore_has_pending_notification_) { |
328 tab_restore_has_pending_notification_ = false; | 331 tab_restore_has_pending_notification_ = false; |
329 ProcessTabRestoreServiceNotification(); | 332 ProcessTabRestoreServiceNotification(); |
330 } | 333 } |
331 | 334 |
332 // If TopSites has updates, retrieve the URLs asynchronously, and on its | 335 // If TopSites has updates, retrieve the URLs asynchronously, and on its |
333 // completion, trigger favicon loading. | 336 // completion, trigger favicon loading. |
334 // Otherwise, call StartLoadingFavicon directly to start favicon loading. | 337 // Otherwise, call StartLoadingFavicon directly to start favicon loading. |
335 if (top_sites_has_pending_notification_) | 338 if (top_sites_has_pending_notification_) |
336 ProcessTopSitesNotification(); | 339 ProcessTopSitesNotification(); |
337 else | 340 else |
338 StartLoadingFavicon(); | 341 StartLoadingFavicon(); |
339 } | 342 } |
340 | 343 |
341 void JumpList::ProcessTopSitesNotification() { | 344 void JumpList::ProcessTopSitesNotification() { |
342 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 345 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
346 DCHECK(!update_in_progress_); | |
343 | 347 |
344 // Opening the first tab in one session triggers a TopSite history sync. | 348 // Opening the first tab in one session triggers a TopSite history sync. |
345 // Delay this sync till the first tab is closed to allow the "recently closed" | 349 // Delay this sync till the first tab is closed to allow the "recently closed" |
346 // category from last session to stay longer. All previous pending | 350 // category from last session to stay longer. All previous pending |
347 // notifications from TopSites are ignored. | 351 // notifications from TopSites are ignored. |
348 if (!has_tab_closed_) { | 352 if (!has_tab_closed_) { |
349 top_sites_has_pending_notification_ = false; | 353 top_sites_has_pending_notification_ = false; |
350 return; | 354 return; |
351 } | 355 } |
352 | 356 |
353 scoped_refptr<history::TopSites> top_sites = | 357 scoped_refptr<history::TopSites> top_sites = |
354 TopSitesFactory::GetForProfile(profile_); | 358 TopSitesFactory::GetForProfile(profile_); |
355 if (top_sites) { | 359 if (top_sites) { |
356 top_sites->GetMostVisitedURLs( | 360 top_sites->GetMostVisitedURLs( |
357 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | 361 base::Bind(&JumpList::OnMostVisitedURLsAvailable, |
358 weak_ptr_factory_.GetWeakPtr()), | 362 weak_ptr_factory_.GetWeakPtr()), |
359 false); | 363 false); |
360 } | 364 } |
361 } | 365 } |
362 | 366 |
363 void JumpList::ProcessTabRestoreServiceNotification() { | 367 void JumpList::ProcessTabRestoreServiceNotification() { |
364 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 368 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
369 DCHECK(!update_in_progress_); | |
365 | 370 |
366 // Create a list of ShellLinkItems from the "Recently Closed" pages. | 371 // Create a list of ShellLinkItems from the "Recently Closed" pages. |
367 // As noted above, we create a ShellLinkItem objects with the following | 372 // As noted above, we create a ShellLinkItem objects with the following |
368 // parameters. | 373 // parameters. |
369 // * arguments | 374 // * arguments |
370 // The last URL of the tab object. | 375 // The last URL of the tab object. |
371 // * title | 376 // * title |
372 // The title of the last URL. | 377 // The title of the last URL. |
373 // * icon | 378 // * icon |
374 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | 379 // An empty string. This value is to be updated in OnFaviconDataAvailable(). |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
545 | 550 |
546 base::FilePath profile_dir = profile_->GetPath(); | 551 base::FilePath profile_dir = profile_->GetPath(); |
547 | 552 |
548 // Check if incognito windows (or normal windows) are disabled by policy. | 553 // Check if incognito windows (or normal windows) are disabled by policy. |
549 IncognitoModePrefs::Availability incognito_availability = | 554 IncognitoModePrefs::Availability incognito_availability = |
550 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 555 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); |
551 | 556 |
552 // Make local copies of JumpList member variables and use them for an update. | 557 // Make local copies of JumpList member variables and use them for an update. |
553 ShellLinkItemList local_most_visited_pages = most_visited_pages_; | 558 ShellLinkItemList local_most_visited_pages = most_visited_pages_; |
554 ShellLinkItemList local_recently_closed_pages = recently_closed_pages_; | 559 ShellLinkItemList local_recently_closed_pages = recently_closed_pages_; |
555 | |
556 bool most_visited_should_update = most_visited_should_update_; | 560 bool most_visited_should_update = most_visited_should_update_; |
557 bool recently_closed_should_update = recently_closed_should_update_; | 561 bool recently_closed_should_update = recently_closed_should_update_; |
558 | 562 |
559 auto update_results = base::MakeUnique<UpdateResults>(); | 563 auto update_transaction = base::MakeUnique<UpdateTransaction>(); |
560 update_results->most_visited_icons_in_update = most_visited_icons_; | 564 update_transaction->most_visited_icons = most_visited_icons_; |
561 update_results->recently_closed_icons_in_update = recently_closed_icons_; | 565 update_transaction->recently_closed_icons = recently_closed_icons_; |
562 | 566 |
563 // Parameter evaluation order is unspecified in C++. Ensure the pointer value | 567 // Parameter evaluation order is unspecified in C++. Do the first bind and |
564 // is obtained before base::Passed() is called. | 568 // then move it into PostTaskAndReply to ensure the pointer value is obtained |
565 auto* update_results_raw = update_results.get(); | 569 // before base::Passed() is called. |
570 auto run_update = | |
571 base::Bind(&JumpList::RunUpdateJumpList, app_id_, profile_dir, | |
572 local_most_visited_pages, local_recently_closed_pages, | |
573 most_visited_should_update, recently_closed_should_update, | |
574 incognito_availability, update_transaction.get()); | |
566 | 575 |
567 // Post a task to update the JumpList, which consists of 1) create new icons, | 576 // Post a task to update the JumpList, which consists of 1) create new icons, |
568 // 2) delete old icons, 3) notify the OS. | 577 // 2) notify the OS, 3) delete old icons. |
569 if (!update_jumplist_task_runner_->PostTaskAndReply( | 578 if (!update_jumplist_task_runner_->PostTaskAndReply( |
570 FROM_HERE, | 579 FROM_HERE, std::move(run_update), |
571 base::Bind(&JumpList::RunUpdateJumpList, app_id_, profile_dir, | |
572 local_most_visited_pages, local_recently_closed_pages, | |
573 most_visited_should_update, recently_closed_should_update, | |
574 incognito_availability, update_results_raw), | |
575 base::Bind(&JumpList::OnRunUpdateCompletion, | 580 base::Bind(&JumpList::OnRunUpdateCompletion, |
576 weak_ptr_factory_.GetWeakPtr(), | 581 weak_ptr_factory_.GetWeakPtr(), |
577 base::Passed(std::move(update_results))))) { | 582 base::Passed(std::move(update_transaction))))) { |
578 OnRunUpdateCompletion(base::MakeUnique<UpdateResults>()); | 583 OnRunUpdateCompletion(base::MakeUnique<UpdateTransaction>()); |
579 } | 584 } |
580 } | 585 } |
581 | 586 |
582 void JumpList::OnRunUpdateCompletion( | 587 void JumpList::OnRunUpdateCompletion( |
583 std::unique_ptr<UpdateResults> update_results) { | 588 std::unique_ptr<UpdateTransaction> update_transaction) { |
584 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 589 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
585 | 590 |
586 // Update JumpList member variables based on the results from the update run | 591 // Update JumpList member variables based on the results from the update run |
587 // just finished. | 592 // just finished. |
588 if (update_results->update_timeout) | 593 if (update_transaction->update_timeout) |
589 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; | 594 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; |
590 | 595 |
591 if (update_results->update_success) { | 596 if (update_transaction->update_success) { |
592 most_visited_icons_.swap(update_results->most_visited_icons_in_update); | 597 if (most_visited_should_update_) { |
593 recently_closed_icons_.swap( | 598 most_visited_icons_ = std::move(update_transaction->most_visited_icons); |
594 update_results->recently_closed_icons_in_update); | 599 most_visited_should_update_ = false; |
595 most_visited_should_update_ = false; | 600 } |
596 recently_closed_should_update_ = false; | 601 if (recently_closed_should_update_) { |
602 recently_closed_icons_ = | |
603 std::move(update_transaction->recently_closed_icons); | |
604 recently_closed_should_update_ = false; | |
605 } | |
597 } | 606 } |
598 | 607 |
599 update_in_progress_ = false; | 608 update_in_progress_ = false; |
600 | 609 |
601 // If there is any new notification during the update run just finished, start | 610 // If there is any new notification during the update run just finished, start |
602 // another JumpList update. | 611 // another JumpList update. |
603 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld | 612 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld |
604 // folders as they are no longer needed. Now we have the | 613 // folders as they are no longer needed. Now we have the |
605 // JumpListIcons{MostVisited, RecentClosed} folders instead. | 614 // JumpListIcons{MostVisited, RecentClosed} folders instead. |
606 if (top_sites_has_pending_notification_ || | 615 if (top_sites_has_pending_notification_ || |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
656 | 665 |
657 // static | 666 // static |
658 void JumpList::RunUpdateJumpList( | 667 void JumpList::RunUpdateJumpList( |
659 const base::string16& app_id, | 668 const base::string16& app_id, |
660 const base::FilePath& profile_dir, | 669 const base::FilePath& profile_dir, |
661 const ShellLinkItemList& most_visited_pages, | 670 const ShellLinkItemList& most_visited_pages, |
662 const ShellLinkItemList& recently_closed_pages, | 671 const ShellLinkItemList& recently_closed_pages, |
663 bool most_visited_should_update, | 672 bool most_visited_should_update, |
664 bool recently_closed_should_update, | 673 bool recently_closed_should_update, |
665 IncognitoModePrefs::Availability incognito_availability, | 674 IncognitoModePrefs::Availability incognito_availability, |
666 UpdateResults* update_results) { | 675 UpdateTransaction* update_transaction) { |
667 if (!JumpListUpdater::IsEnabled()) | 676 if (!JumpListUpdater::IsEnabled()) |
668 return; | 677 return; |
669 | 678 |
670 DCHECK(update_results); | 679 DCHECK(update_transaction); |
680 | |
681 base::FilePath most_visited_icon_dir = GenerateJumplistIconDirName( | |
682 profile_dir, FILE_PATH_LITERAL("MostVisited")); | |
683 base::FilePath recently_closed_icon_dir = GenerateJumplistIconDirName( | |
684 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | |
685 | |
686 CreateNewJumpListAndNotifyOS( | |
687 app_id, most_visited_icon_dir, recently_closed_icon_dir, | |
688 most_visited_pages, recently_closed_pages, most_visited_should_update, | |
689 recently_closed_should_update, incognito_availability, | |
690 update_transaction); | |
691 | |
692 // Delete any obsolete icon files. | |
693 if (most_visited_should_update) { | |
694 DeleteIconFiles(most_visited_icon_dir, | |
695 update_transaction->most_visited_icons); | |
696 } | |
697 if (recently_closed_should_update) { | |
698 DeleteIconFiles(recently_closed_icon_dir, | |
699 update_transaction->recently_closed_icons); | |
700 } | |
701 } | |
702 | |
703 // static | |
704 void JumpList::CreateNewJumpListAndNotifyOS( | |
705 const base::string16& app_id, | |
706 const base::FilePath& most_visited_icon_dir, | |
707 const base::FilePath& recently_closed_icon_dir, | |
708 const ShellLinkItemList& most_visited_pages, | |
709 const ShellLinkItemList& recently_closed_pages, | |
710 bool most_visited_should_update, | |
711 bool recently_closed_should_update, | |
712 IncognitoModePrefs::Availability incognito_availability, | |
713 UpdateTransaction* update_transaction) { | |
714 DCHECK(update_transaction); | |
671 | 715 |
672 JumpListUpdater jumplist_updater(app_id); | 716 JumpListUpdater jumplist_updater(app_id); |
673 | 717 |
674 base::ElapsedTimer begin_update_timer; | 718 base::ElapsedTimer begin_update_timer; |
675 | 719 |
676 if (!jumplist_updater.BeginUpdate()) | 720 bool begin_success = jumplist_updater.BeginUpdate(); |
677 return; | |
678 | 721 |
679 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer | 722 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer |
680 // than the maximum allowed time, as it's very likely the following update | 723 // than the maximum allowed time, as it's very likely the following update |
681 // steps will also take a long time. As we've not updated the icons on the | 724 // steps will also take a long time. |
682 // disk, discarding this update wont't affect the current JumpList used by OS. | |
683 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) { | 725 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) { |
684 update_results->update_timeout = true; | 726 update_transaction->update_timeout = true; |
685 return; | 727 return; |
686 } | 728 } |
687 | 729 |
730 if (!begin_success) | |
731 return; | |
732 | |
688 // Record the desired number of icons created in this JumpList update. | 733 // Record the desired number of icons created in this JumpList update. |
689 int icons_created = 0; | 734 int icons_created = 0; |
690 | 735 |
736 URLIconCache most_visited_icons_next; | |
737 URLIconCache recently_closed_icons_next; | |
738 | |
691 // Update the icons for "Most Visisted" category of the JumpList if needed. | 739 // Update the icons for "Most Visisted" category of the JumpList if needed. |
692 if (most_visited_should_update) { | 740 if (most_visited_should_update) { |
693 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( | |
694 profile_dir, FILE_PATH_LITERAL("MostVisited")); | |
695 | |
696 icons_created += UpdateIconFiles( | 741 icons_created += UpdateIconFiles( |
697 icon_dir_most_visited, most_visited_pages, kMostVisitedItems, | 742 most_visited_icon_dir, most_visited_pages, kMostVisitedItems, |
698 &update_results->most_visited_icons_in_update); | 743 &update_transaction->most_visited_icons, &most_visited_icons_next); |
699 } | 744 } |
700 | 745 |
701 // Update the icons for "Recently Closed" category of the JumpList if needed. | 746 // Update the icons for "Recently Closed" category of the JumpList if needed. |
702 if (recently_closed_should_update) { | 747 if (recently_closed_should_update) { |
703 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( | |
704 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | |
705 | |
706 icons_created += UpdateIconFiles( | 748 icons_created += UpdateIconFiles( |
707 icon_dir_recent_closed, recently_closed_pages, kRecentlyClosedItems, | 749 recently_closed_icon_dir, recently_closed_pages, kRecentlyClosedItems, |
708 &update_results->recently_closed_icons_in_update); | 750 &update_transaction->recently_closed_icons, |
751 &recently_closed_icons_next); | |
709 } | 752 } |
710 | 753 |
711 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 754 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
712 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_created); | 755 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_created); |
713 | 756 |
714 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 757 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
715 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | 758 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); |
716 | 759 |
717 base::ElapsedTimer add_custom_category_timer; | 760 base::ElapsedTimer add_custom_category_timer; |
718 | 761 |
719 // Update the "Most Visited" category of the JumpList if it exists. | 762 // Update the "Most Visited" category of the JumpList if it exists. |
720 // This update request is applied into the JumpList when we commit this | 763 // This update request is applied into the JumpList when we commit this |
721 // transaction. | 764 // transaction. |
722 if (!jumplist_updater.AddCustomCategory( | 765 bool add_category_success = jumplist_updater.AddCustomCategory( |
723 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | 766 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), most_visited_pages, |
724 most_visited_pages, kMostVisitedItems)) { | 767 kMostVisitedItems); |
768 | |
769 // If AddCustomCategory takes longer than the maximum allowed time, abort the | |
770 // current update and skip the next |kUpdatesToSkipUnderHeavyLoad| updates. | |
771 if (add_custom_category_timer.Elapsed() >= kTimeOutForAddCustomCategory) { | |
772 update_transaction->update_timeout = true; | |
725 return; | 773 return; |
726 } | 774 } |
727 | 775 |
776 if (!add_category_success) | |
777 return; | |
778 | |
728 // Update the "Recently Closed" category of the JumpList. | 779 // Update the "Recently Closed" category of the JumpList. |
780 // This update request is applied into the JumpList when we commit this | |
781 // transaction. We don't need to monitor the runtime of this AddCustomCategory | |
782 // call as it should be very similar to the previous one. | |
729 if (!jumplist_updater.AddCustomCategory( | 783 if (!jumplist_updater.AddCustomCategory( |
730 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, | 784 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, |
731 kRecentlyClosedItems)) { | 785 kRecentlyClosedItems)) { |
732 return; | 786 return; |
733 } | 787 } |
734 | 788 |
735 // If JumpListUpdater::AddCustomCategory or JumpListUpdater::CommitUpdate | |
736 // takes longer than the maximum allowed time, skip the next | |
737 // |kUpdatesToSkipUnderHeavyLoad| updates. This update should be finished | |
738 // because we've already updated the icons on the disk. If discarding this | |
739 // update from here, some items in the current JumpList may not have icons | |
740 // as they've been delete from the disk. In this case, the background color of | |
741 // the JumpList panel is used instead, which doesn't look nice. | |
742 | |
743 if (add_custom_category_timer.Elapsed() >= kTimeOutForAddCustomCategory) | |
744 update_results->update_timeout = true; | |
745 | |
746 // Update the "Tasks" category of the JumpList. | 789 // Update the "Tasks" category of the JumpList. |
747 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | 790 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) |
748 return; | 791 return; |
749 | 792 |
750 base::ElapsedTimer commit_update_timer; | 793 base::ElapsedTimer commit_update_timer; |
751 | 794 |
752 // Commit this transaction and send the updated JumpList to Windows. | 795 // Commit this transaction and send the updated JumpList to Windows. |
753 if (jumplist_updater.CommitUpdate()) | 796 bool commit_success = jumplist_updater.CommitUpdate(); |
754 update_results->update_success = true; | |
755 | 797 |
798 // If CommitUpdate call takes longer than the maximum allowed time, skip the | |
799 // next |kUpdatesToSkipUnderHeavyLoad| updates. | |
756 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) | 800 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) |
757 update_results->update_timeout = true; | 801 update_transaction->update_timeout = true; |
802 | |
803 if (commit_success) { | |
804 update_transaction->update_success = true; | |
805 | |
806 // The move assignments below ensure update_transaction always has the icons | |
807 // to keep. | |
808 if (most_visited_should_update) { | |
809 update_transaction->most_visited_icons = | |
810 std::move(most_visited_icons_next); | |
811 } | |
812 if (recently_closed_should_update) { | |
813 update_transaction->recently_closed_icons = | |
814 std::move(recently_closed_icons_next); | |
815 } | |
816 } | |
758 } | 817 } |
759 | 818 |
760 // static | 819 // static |
761 int JumpList::UpdateIconFiles(const base::FilePath& icon_dir, | 820 int JumpList::UpdateIconFiles(const base::FilePath& icon_dir, |
762 const ShellLinkItemList& page_list, | 821 const ShellLinkItemList& item_list, |
763 size_t slot_limit, | 822 size_t max_items, |
764 URLIconCache* icon_cache) { | 823 URLIconCache* icon_cur, |
824 URLIconCache* icon_next) { | |
825 DCHECK(icon_cur); | |
826 DCHECK(icon_next); | |
827 | |
828 // Clear the JumpList icon folder at |icon_dir| and the caches when | |
829 // 1) |icon_cur| is empty. This happens when "Most visited" or "Recently | |
830 // closed" category updates for the 1st time after Chrome is launched. | |
831 // 2) The number of icons in |icon_dir| has exceeded the limit. | |
832 if (icon_cur->empty() || FilesExceedLimitInDir(icon_dir, max_items * 2)) { | |
833 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | |
834 icon_cur->clear(); | |
835 icon_next->clear(); | |
836 // Create new icons only when the directory exists and is empty. | |
837 if (!base::CreateDirectory(icon_dir) || !base::IsDirectoryEmpty(icon_dir)) | |
838 return 0; | |
839 } else if (!base::CreateDirectory(icon_dir)) { | |
840 return 0; | |
841 } | |
842 | |
843 return CreateIconFiles(icon_dir, item_list, max_items, *icon_cur, icon_next); | |
844 } | |
845 | |
846 // static | |
847 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, | |
848 const ShellLinkItemList& item_list, | |
849 size_t max_items, | |
850 const URLIconCache& icon_cur, | |
851 URLIconCache* icon_next) { | |
852 DCHECK(icon_next); | |
853 | |
854 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
855 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | |
856 | |
765 int icons_created = 0; | 857 int icons_created = 0; |
766 | 858 |
767 // Clear the JumpList icon folder at |icon_dir| and the cache when | 859 // Reuse icons for urls that already present in the current JumpList. |
768 // 1) |icon_cache| is empty. This happens when "Most visited" or "Recently | 860 for (ShellLinkItemList::const_iterator iter = item_list.begin(); |
769 // closed" category updates for the 1st time after Chrome is launched. | 861 iter != item_list.end() && max_items > 0; ++iter, --max_items) { |
770 // 2) The number of icons in |icon_dir| has exceeded the limit. | 862 ShellLinkItem* item = iter->get(); |
771 if (icon_cache->empty() || FilesExceedLimitInDir(icon_dir, slot_limit * 2)) { | 863 auto cache_iter = icon_cur.find(item->url()); |
772 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | 864 if (cache_iter != icon_cur.end()) { |
773 icon_cache->clear(); | 865 item->set_icon(cache_iter->second.value(), 0); |
774 // Create new icons only when the directory exists and is empty. | 866 (*icon_next)[item->url()] = cache_iter->second; |
775 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | 867 } else { |
776 icons_created += | 868 base::FilePath icon_path; |
777 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | 869 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { |
778 } else if (base::CreateDirectory(icon_dir)) { | 870 ++icons_created; |
779 icons_created += | 871 item->set_icon(icon_path.value(), 0); |
780 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | 872 (*icon_next)[item->url()] = icon_path; |
781 DeleteIconFiles(icon_dir, icon_cache); | 873 } |
874 } | |
782 } | 875 } |
783 | 876 |
784 return icons_created; | 877 return icons_created; |
785 } | 878 } |
786 | 879 |
787 // static | 880 // static |
788 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, | |
789 const ShellLinkItemList& item_list, | |
790 size_t max_items, | |
791 URLIconCache* icon_cache) { | |
792 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
793 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | |
794 | |
795 int icons_created = 0; | |
796 | |
797 // Reuse icons for urls that already present in the current JumpList. | |
798 URLIconCache updated_map; | |
799 for (ShellLinkItemList::const_iterator iter = item_list.begin(); | |
800 iter != item_list.end() && max_items > 0; ++iter, --max_items) { | |
801 ShellLinkItem* item = iter->get(); | |
802 auto cache_iter = icon_cache->find(item->url()); | |
803 if (cache_iter != icon_cache->end()) { | |
804 item->set_icon(cache_iter->second.value(), 0); | |
805 updated_map[item->url()] = cache_iter->second; | |
806 } else { | |
807 base::FilePath icon_path; | |
808 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { | |
809 ++icons_created; | |
810 item->set_icon(icon_path.value(), 0); | |
811 updated_map[item->url()] = icon_path; | |
812 } | |
813 } | |
814 } | |
815 icon_cache->swap(updated_map); | |
816 | |
817 return icons_created; | |
818 } | |
819 | |
820 // static | |
821 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, | 881 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, |
822 URLIconCache* icon_cache) { | 882 const URLIconCache& icons_cache) { |
823 // Put all cached icon file paths into a set. | 883 // Put all cached icon file paths into a set. |
824 base::flat_set<base::FilePath> cached_files; | 884 base::flat_set<base::FilePath> cached_files; |
825 cached_files.reserve(icon_cache->size()); | 885 cached_files.reserve(icons_cache.size()); |
826 | 886 |
827 for (const auto& url_path_pair : *icon_cache) | 887 for (const auto& url_path_pair : icons_cache) |
828 cached_files.insert(url_path_pair.second); | 888 cached_files.insert(url_path_pair.second); |
829 | 889 |
830 DeleteNonCachedFiles(icon_dir, cached_files); | 890 DeleteNonCachedFiles(icon_dir, cached_files); |
831 } | 891 } |
OLD | NEW |