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 "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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 #include "url/gurl.h" | 54 #include "url/gurl.h" |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| 57 | 57 |
| 58 // The default maximum number of items to display in JumpList is 10. | 58 // The default maximum number of items to display in JumpList is 10. |
| 59 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx | 59 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx |
| 60 // The "Most visited" and "Recently closed" category titles always take 2 slots. | 60 // The "Most visited" and "Recently closed" category titles always take 2 slots. |
| 61 // For the remaining 8 slots, we allocate 5 slots to "most-visited" items and 3 | 61 // For the remaining 8 slots, we allocate 5 slots to "most-visited" items and 3 |
| 62 // slots to "recently-closed" items, respectively. | 62 // slots to "recently-closed" items, respectively. |
| 63 constexpr size_t kMostVisitedItems = 5; | 63 constexpr size_t kMostVisitedItems = 5; |
| 64 constexpr size_t kRecentlyClosedItems = 3; | 64 constexpr size_t kRecentClosedItems = 3; |
| 65 | 65 |
| 66 // The number of updates to skip to alleviate the machine when a previous update | 66 // The number of updates to skip to alleviate the machine when a previous update |
| 67 // was too slow. | 67 // was too slow. |
| 68 constexpr int kUpdatesToSkipUnderHeavyLoad = 10; | 68 constexpr int kUpdatesToSkipUnderHeavyLoad = 10; |
| 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 kTimeOutForBeginUpdate = |
| 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 both "most visited" and "recently |
| 80 // closed" categories via JumpListUpdater::AddCustomCategory. | 80 // closed" categories via JumpListUpdater::AddCustomCategory. |
| 81 constexpr base::TimeDelta kTimeOutForAddCustomCategory = | 81 constexpr base::TimeDelta kTimeOutForAddCategory = |
| 82 base::TimeDelta::FromMilliseconds(500); | 82 base::TimeDelta::FromMilliseconds(500); |
| 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 kTimeOutForCommitUpdate = |
| 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(); |
| 93 shell_link->GetCommandLine()->CopySwitchesFrom(command_line, | 93 shell_link->GetCommandLine()->CopySwitchesFrom(command_line, |
| 94 kSwitchNames, | 94 kSwitchNames, |
| 95 arraysize(kSwitchNames)); | 95 arraysize(kSwitchNames)); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 // * arguments | 369 // * arguments |
| 370 // The last URL of the tab object. | 370 // The last URL of the tab object. |
| 371 // * title | 371 // * title |
| 372 // The title of the last URL. | 372 // The title of the last URL. |
| 373 // * icon | 373 // * icon |
| 374 // An empty string. This value is to be updated in OnFaviconDataAvailable(). | 374 // An empty string. This value is to be updated in OnFaviconDataAvailable(). |
| 375 | 375 |
| 376 sessions::TabRestoreService* tab_restore_service = | 376 sessions::TabRestoreService* tab_restore_service = |
| 377 TabRestoreServiceFactory::GetForProfile(profile_); | 377 TabRestoreServiceFactory::GetForProfile(profile_); |
| 378 | 378 |
| 379 recently_closed_pages_.clear(); | 379 recent_closed_pages_.clear(); |
| 380 | 380 |
| 381 for (const auto& entry : tab_restore_service->entries()) { | 381 for (const auto& entry : tab_restore_service->entries()) { |
| 382 if (recently_closed_pages_.size() >= kRecentlyClosedItems) | 382 if (recent_closed_pages_.size() >= kRecentClosedItems) |
| 383 break; | 383 break; |
| 384 switch (entry->type) { | 384 switch (entry->type) { |
| 385 case sessions::TabRestoreService::TAB: | 385 case sessions::TabRestoreService::TAB: |
| 386 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), | 386 AddTab(static_cast<const sessions::TabRestoreService::Tab&>(*entry), |
| 387 kRecentlyClosedItems); | 387 kRecentClosedItems); |
| 388 break; | 388 break; |
| 389 case sessions::TabRestoreService::WINDOW: | 389 case sessions::TabRestoreService::WINDOW: |
| 390 AddWindow( | 390 AddWindow( |
| 391 static_cast<const sessions::TabRestoreService::Window&>(*entry), | 391 static_cast<const sessions::TabRestoreService::Window&>(*entry), |
| 392 kRecentlyClosedItems); | 392 kRecentClosedItems); |
| 393 break; | 393 break; |
| 394 } | 394 } |
| 395 } | 395 } |
| 396 | 396 |
| 397 recently_closed_should_update_ = true; | 397 recent_closed_should_update_ = true; |
| 398 | 398 |
| 399 // Force a TopSite history sync when closing a first tab in one session. | 399 // Force a TopSite history sync when closing a first tab in one session. |
| 400 if (!has_tab_closed_) { | 400 if (!has_tab_closed_) { |
| 401 has_tab_closed_ = true; | 401 has_tab_closed_ = true; |
| 402 scoped_refptr<history::TopSites> top_sites = | 402 scoped_refptr<history::TopSites> top_sites = |
| 403 TopSitesFactory::GetForProfile(profile_); | 403 TopSitesFactory::GetForProfile(profile_); |
| 404 if (top_sites) | 404 if (top_sites) |
| 405 top_sites->SyncWithHistory(); | 405 top_sites->SyncWithHistory(); |
| 406 } | 406 } |
| 407 } | 407 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 // Send a query that retrieves the first favicon. | 440 // Send a query that retrieves the first favicon. |
| 441 StartLoadingFavicon(); | 441 StartLoadingFavicon(); |
| 442 } | 442 } |
| 443 | 443 |
| 444 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, | 444 bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab, |
| 445 size_t max_items) { | 445 size_t max_items) { |
| 446 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 446 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 447 | 447 |
| 448 // This code adds the URL and the title strings of the given tab to the | 448 // This code adds the URL and the title strings of the given tab to the |
| 449 // JumpList variables. | 449 // JumpList variables. |
| 450 if (recently_closed_pages_.size() >= max_items) | 450 if (recent_closed_pages_.size() >= max_items) |
| 451 return false; | 451 return false; |
| 452 | 452 |
| 453 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 453 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
| 454 const sessions::SerializedNavigationEntry& current_navigation = | 454 const sessions::SerializedNavigationEntry& current_navigation = |
| 455 tab.navigations.at(tab.current_navigation_index); | 455 tab.navigations.at(tab.current_navigation_index); |
| 456 std::string url = current_navigation.virtual_url().spec(); | 456 std::string url = current_navigation.virtual_url().spec(); |
| 457 link->GetCommandLine()->AppendArgNative(base::UTF8ToUTF16(url)); | 457 link->GetCommandLine()->AppendArgNative(base::UTF8ToUTF16(url)); |
| 458 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, | 458 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, |
| 459 jumplist::kRecentlyClosedCategory); | 459 jumplist::kRecentlyClosedCategory); |
| 460 link->set_title(current_navigation.title()); | 460 link->set_title(current_navigation.title()); |
| 461 link->set_url(url); | 461 link->set_url(url); |
| 462 recently_closed_pages_.push_back(link); | 462 recent_closed_pages_.push_back(link); |
| 463 if (recently_closed_icons_.find(url) == recently_closed_icons_.end()) | 463 if (recent_closed_icons_.find(url) == recent_closed_icons_.end()) |
| 464 icon_urls_.emplace_back(std::move(url), std::move(link)); | 464 icon_urls_.emplace_back(std::move(url), std::move(link)); |
| 465 | 465 |
| 466 return true; | 466 return true; |
| 467 } | 467 } |
| 468 | 468 |
| 469 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, | 469 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, |
| 470 size_t max_items) { | 470 size_t max_items) { |
| 471 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 471 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 472 DCHECK(!window.tabs.empty()); | 472 DCHECK(!window.tabs.empty()); |
| 473 | 473 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 544 update_in_progress_ = true; | 544 update_in_progress_ = true; |
| 545 | 545 |
| 546 base::FilePath profile_dir = profile_->GetPath(); | 546 base::FilePath profile_dir = profile_->GetPath(); |
| 547 | 547 |
| 548 // Check if incognito windows (or normal windows) are disabled by policy. | 548 // Check if incognito windows (or normal windows) are disabled by policy. |
| 549 IncognitoModePrefs::Availability incognito_availability = | 549 IncognitoModePrefs::Availability incognito_availability = |
| 550 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 550 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); |
| 551 | 551 |
| 552 // Make local copies of JumpList member variables and use them for an update. | 552 // Make local copies of JumpList member variables and use them for an update. |
| 553 ShellLinkItemList local_most_visited_pages = most_visited_pages_; | 553 ShellLinkItemList local_most_visited_pages = most_visited_pages_; |
| 554 ShellLinkItemList local_recently_closed_pages = recently_closed_pages_; | 554 ShellLinkItemList local_recent_closed_pages = recent_closed_pages_; |
| 555 | |
| 556 bool most_visited_should_update = most_visited_should_update_; | |
| 557 bool recently_closed_should_update = recently_closed_should_update_; | |
| 558 | 555 |
| 559 auto update_results = base::MakeUnique<UpdateResults>(); | 556 auto update_results = base::MakeUnique<UpdateResults>(); |
|
grt (UTC plus 2)
2017/06/20 10:29:18
meta comment: this object does more than just carr
chengx
2017/06/20 19:33:59
The two lists above, i.e., *_pages_, are not updat
grt (UTC plus 2)
2017/06/21 10:57:29
So they're in-out params, yes? I can see how they
chengx
2017/06/22 22:45:06
Yes, they're in-out params. I've renamed the enum
| |
| 560 update_results->most_visited_icons_in_update = most_visited_icons_; | 557 update_results->most_visited_icons = most_visited_icons_; |
| 561 update_results->recently_closed_icons_in_update = recently_closed_icons_; | 558 update_results->recent_closed_icons = recent_closed_icons_; |
| 559 update_results->most_visited_icon_assoc = most_visited_icon_assoc_; | |
| 560 update_results->recent_closed_icon_assoc = recent_closed_icon_assoc_; | |
| 561 update_results->most_visited_should_update = most_visited_should_update_; | |
| 562 update_results->recent_closed_should_update = recent_closed_should_update_; | |
| 562 | 563 |
| 563 // Parameter evaluation order is unspecified in C++. Ensure the pointer value | 564 // Parameter evaluation order is unspecified in C++. Ensure the pointer value |
| 564 // is obtained before base::Passed() is called. | 565 // is obtained before base::Passed() is called. |
| 565 auto* update_results_raw = update_results.get(); | 566 auto* update_results_raw = update_results.get(); |
| 566 | 567 |
| 567 // Post a task to update the JumpList, which consists of 1) create new icons, | 568 // Post a task to update the JumpList, which consists of 1) create new icons, |
| 568 // 2) delete old icons, 3) notify the OS. | 569 // 2) notify the OS, 3) delete old icons. |
| 569 if (!update_jumplist_task_runner_->PostTaskAndReply( | 570 if (!update_jumplist_task_runner_->PostTaskAndReply( |
| 570 FROM_HERE, | 571 FROM_HERE, |
| 571 base::Bind(&JumpList::RunUpdateJumpList, app_id_, profile_dir, | 572 base::Bind(&JumpList::RunUpdateJumpList, app_id_, profile_dir, |
| 572 local_most_visited_pages, local_recently_closed_pages, | 573 local_most_visited_pages, local_recent_closed_pages, |
| 573 most_visited_should_update, recently_closed_should_update, | |
| 574 incognito_availability, update_results_raw), | 574 incognito_availability, update_results_raw), |
| 575 base::Bind(&JumpList::OnRunUpdateCompletion, | 575 base::Bind(&JumpList::OnRunUpdateCompletion, |
| 576 weak_ptr_factory_.GetWeakPtr(), | 576 weak_ptr_factory_.GetWeakPtr(), |
| 577 base::Passed(std::move(update_results))))) { | 577 base::Passed(std::move(update_results))))) { |
| 578 OnRunUpdateCompletion(base::MakeUnique<UpdateResults>()); | 578 OnRunUpdateCompletion(base::MakeUnique<UpdateResults>()); |
| 579 } | 579 } |
| 580 } | 580 } |
| 581 | 581 |
| 582 void JumpList::OnRunUpdateCompletion( | 582 void JumpList::OnRunUpdateCompletion( |
| 583 std::unique_ptr<UpdateResults> update_results) { | 583 std::unique_ptr<UpdateResults> update_results) { |
| 584 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 584 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 585 | 585 |
| 586 // Update JumpList member variables based on the results from the update run | 586 // Update JumpList member variables based on the results from the update run |
| 587 // just finished. | 587 // just finished. |
| 588 if (update_results->update_timeout) | 588 if (update_results->update_timeout) |
| 589 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; | 589 updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad; |
| 590 | 590 |
| 591 if (update_results->update_success) { | 591 if (update_results->update_success) { |
| 592 most_visited_icons_.swap(update_results->most_visited_icons_in_update); | 592 if (update_results->most_visited_should_update) { |
| 593 recently_closed_icons_.swap( | 593 most_visited_icons_.swap(update_results->most_visited_icons); |
| 594 update_results->recently_closed_icons_in_update); | 594 most_visited_icon_assoc_.swap(update_results->most_visited_icon_assoc); |
| 595 most_visited_should_update_ = false; | 595 most_visited_should_update_ = false; |
| 596 recently_closed_should_update_ = false; | 596 } |
| 597 if (update_results->recent_closed_should_update) { | |
| 598 recent_closed_icons_.swap(update_results->recent_closed_icons); | |
| 599 recent_closed_icon_assoc_.swap(update_results->recent_closed_icon_assoc); | |
| 600 recent_closed_should_update_ = false; | |
| 601 } | |
| 597 } | 602 } |
| 598 | 603 |
| 599 update_in_progress_ = false; | 604 update_in_progress_ = false; |
| 600 | 605 |
| 601 // If there is any new notification during the update run just finished, start | 606 // If there is any new notification during the update run just finished, start |
| 602 // another JumpList update. | 607 // another JumpList update. |
| 603 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld | 608 // Otherwise, post tasks to delete the JumpListIcons and JumpListIconsOld |
| 604 // folders as they are no longer needed. Now we have the | 609 // folders as they are no longer needed. Now we have the |
| 605 // JumpListIcons{MostVisited, RecentClosed} folders instead. | 610 // JumpListIcons{MostVisited, RecentClosed} folders instead. |
| 606 if (top_sites_has_pending_notification_ || | 611 if (top_sites_has_pending_notification_ || |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 652 pref_change_registrar_.reset(); | 657 pref_change_registrar_.reset(); |
| 653 } | 658 } |
| 654 profile_ = nullptr; | 659 profile_ = nullptr; |
| 655 } | 660 } |
| 656 | 661 |
| 657 // static | 662 // static |
| 658 void JumpList::RunUpdateJumpList( | 663 void JumpList::RunUpdateJumpList( |
| 659 const base::string16& app_id, | 664 const base::string16& app_id, |
| 660 const base::FilePath& profile_dir, | 665 const base::FilePath& profile_dir, |
| 661 const ShellLinkItemList& most_visited_pages, | 666 const ShellLinkItemList& most_visited_pages, |
| 662 const ShellLinkItemList& recently_closed_pages, | 667 const ShellLinkItemList& recent_closed_pages, |
| 663 bool most_visited_should_update, | |
| 664 bool recently_closed_should_update, | |
| 665 IncognitoModePrefs::Availability incognito_availability, | 668 IncognitoModePrefs::Availability incognito_availability, |
| 666 UpdateResults* update_results) { | 669 UpdateResults* update_results) { |
| 667 if (!JumpListUpdater::IsEnabled()) | 670 if (!JumpListUpdater::IsEnabled()) |
| 668 return; | 671 return; |
| 669 | 672 |
| 670 DCHECK(update_results); | 673 DCHECK(update_results); |
| 671 | 674 |
| 672 JumpListUpdater jumplist_updater(app_id); | 675 JumpListUpdater jumplist_updater(app_id); |
| 673 | 676 |
| 674 base::ElapsedTimer begin_update_timer; | 677 base::ElapsedTimer begin_update_timer; |
| 675 | 678 |
| 676 if (!jumplist_updater.BeginUpdate()) | 679 if (!jumplist_updater.BeginUpdate()) |
| 677 return; | 680 return; |
| 678 | 681 |
| 679 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer | 682 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer |
| 680 // than the maximum allowed time, as it's very likely the following update | 683 // 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 | 684 // steps will also take a long time. As we've not updated the icons on the |
| 682 // disk, discarding this update wont't affect the current JumpList used by OS. | 685 // disk, discarding this update wont't affect the current JumpList used by OS. |
| 683 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) { | 686 if (begin_update_timer.Elapsed() >= kTimeOutForBeginUpdate) { |
| 684 update_results->update_timeout = true; | 687 update_results->update_timeout = true; |
| 685 return; | 688 return; |
| 686 } | 689 } |
| 687 | 690 |
| 688 // Record the desired number of icons created in this JumpList update. | 691 // Record the desired number of icons created in this JumpList update. |
| 689 int icons_created = 0; | 692 int icons_created = 0; |
| 690 | 693 |
| 694 URLIconCache most_visited_icons_next; | |
| 695 URLIconCache recent_closed_icons_next; | |
| 696 | |
| 697 base::FilePath most_visited_icon_dir = GenerateJumplistIconDirName( | |
| 698 profile_dir, FILE_PATH_LITERAL("MostVisited")); | |
| 699 base::FilePath recent_closed_icon_dir = GenerateJumplistIconDirName( | |
| 700 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | |
| 701 | |
| 691 // Update the icons for "Most Visisted" category of the JumpList if needed. | 702 // Update the icons for "Most Visisted" category of the JumpList if needed. |
| 692 if (most_visited_should_update) { | 703 if (update_results->most_visited_should_update) { |
| 693 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( | 704 icons_created += SafeCreateIconFiles( |
| 694 profile_dir, FILE_PATH_LITERAL("MostVisited")); | 705 most_visited_icon_dir, most_visited_pages, kMostVisitedItems, |
| 695 | 706 &update_results->most_visited_icon_assoc, |
| 696 icons_created += UpdateIconFiles( | 707 &update_results->most_visited_icons, &most_visited_icons_next); |
| 697 icon_dir_most_visited, most_visited_pages, kMostVisitedItems, | |
| 698 &update_results->most_visited_icons_in_update); | |
| 699 } | 708 } |
| 700 | 709 |
| 701 // Update the icons for "Recently Closed" category of the JumpList if needed. | 710 // Update the icons for "Recently Closed" category of the JumpList if needed. |
| 702 if (recently_closed_should_update) { | 711 if (update_results->recent_closed_should_update) { |
| 703 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( | 712 icons_created += SafeCreateIconFiles( |
| 704 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | 713 recent_closed_icon_dir, recent_closed_pages, kRecentClosedItems, |
| 705 | 714 &update_results->recent_closed_icon_assoc, |
| 706 icons_created += UpdateIconFiles( | 715 &update_results->recent_closed_icons, &recent_closed_icons_next); |
| 707 icon_dir_recent_closed, recently_closed_pages, kRecentlyClosedItems, | |
| 708 &update_results->recently_closed_icons_in_update); | |
| 709 } | 716 } |
| 710 | 717 |
| 711 // 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. |
| 712 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_created); | 719 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_created); |
| 713 | 720 |
| 714 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 721 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 715 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | 722 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); |
| 716 | 723 |
| 717 base::ElapsedTimer add_custom_category_timer; | 724 base::ElapsedTimer add_custom_category_timer; |
| 718 | 725 |
| 719 // Update the "Most Visited" category of the JumpList if it exists. | 726 // Update the JumpList categories. This update request is applied into the |
| 720 // This update request is applied into the JumpList when we commit this | 727 // JumpList when we commit this transaction. |
| 721 // transaction. | 728 bool add_category_success = |
| 722 if (!jumplist_updater.AddCustomCategory( | 729 jumplist_updater.AddCustomCategory( |
| 723 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | 730 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), |
| 724 most_visited_pages, kMostVisitedItems)) { | 731 most_visited_pages, kMostVisitedItems) && |
| 732 jumplist_updater.AddCustomCategory( | |
| 733 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recent_closed_pages, | |
| 734 kRecentClosedItems); | |
| 735 | |
| 736 // If AddCustomCategory call takes longer than the maximum allowed time, abort | |
| 737 // the current update and skip the next |kUpdatesToSkipUnderHeavyLoad| | |
| 738 // updates. | |
| 739 bool timeout = add_custom_category_timer.Elapsed() >= kTimeOutForAddCategory; | |
| 740 if (timeout) | |
| 741 update_results->update_timeout = true; | |
| 742 | |
| 743 if (!add_category_success || timeout) { | |
| 744 DeleteIconFilesUnified(most_visited_icon_dir, recent_closed_icon_dir, | |
| 745 update_results, JumpListVersion::kNext); | |
| 725 return; | 746 return; |
| 726 } | 747 } |
| 727 | 748 |
| 728 // Update the "Recently Closed" category of the JumpList. | 749 // Update the "Tasks" category of the JumpList. |
| 729 if (!jumplist_updater.AddCustomCategory( | 750 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) { |
| 730 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, | 751 DeleteIconFilesUnified(most_visited_icon_dir, recent_closed_icon_dir, |
| 731 kRecentlyClosedItems)) { | 752 update_results, JumpListVersion::kNext); |
| 732 return; | 753 return; |
| 733 } | 754 } |
| 734 | 755 |
| 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. | |
| 747 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | |
| 748 return; | |
| 749 | |
| 750 base::ElapsedTimer commit_update_timer; | 756 base::ElapsedTimer commit_update_timer; |
| 751 | 757 |
| 752 // Commit this transaction and send the updated JumpList to Windows. | 758 // Commit this transaction and send the updated JumpList to Windows. |
| 753 if (jumplist_updater.CommitUpdate()) | 759 bool commit_success = jumplist_updater.CommitUpdate(); |
| 760 | |
| 761 // If CommitUpdate call takes longer than the maximum allowed time, abort the | |
| 762 // current update and skip the next |kUpdatesToSkipUnderHeavyLoad| updates. | |
| 763 if (commit_update_timer.Elapsed() >= kTimeOutForCommitUpdate) | |
| 764 update_results->update_timeout = true; | |
| 765 | |
| 766 if (commit_success) { | |
| 754 update_results->update_success = true; | 767 update_results->update_success = true; |
| 768 if (update_results->most_visited_should_update) | |
| 769 update_results->most_visited_icons.swap(most_visited_icons_next); | |
| 770 if (update_results->recent_closed_should_update) | |
| 771 update_results->recent_closed_icons.swap(recent_closed_icons_next); | |
| 772 } | |
| 755 | 773 |
| 756 if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate) | 774 // Delete the set of icons based on commit status. |
| 757 update_results->update_timeout = true; | 775 JumpListVersion version = |
| 776 commit_success ? JumpListVersion::kCurrent : JumpListVersion::kNext; | |
| 777 | |
| 778 DeleteIconFilesUnified(most_visited_icon_dir, recent_closed_icon_dir, | |
| 779 update_results, version); | |
| 758 } | 780 } |
| 759 | 781 |
| 760 // static | 782 // static |
| 761 int JumpList::UpdateIconFiles(const base::FilePath& icon_dir, | 783 int JumpList::SafeCreateIconFiles(const base::FilePath& icon_dir, |
| 762 const ShellLinkItemList& page_list, | 784 const ShellLinkItemList& page_list, |
| 763 size_t slot_limit, | 785 size_t slot_limit, |
| 764 URLIconCache* icon_cache) { | 786 IconAssociation* icon_assoc, |
| 787 URLIconCache* icon_cur, | |
| 788 URLIconCache* icon_next) { | |
| 789 DCHECK(icon_assoc); | |
| 790 DCHECK(icon_cur); | |
| 791 DCHECK(icon_next); | |
| 792 | |
| 765 int icons_created = 0; | 793 int icons_created = 0; |
| 766 | 794 |
| 767 // Clear the JumpList icon folder at |icon_dir| and the cache when | 795 // Clear the JumpList icon folder at |icon_dir| and the caches when |
| 768 // 1) |icon_cache| is empty. This happens when "Most visited" or "Recently | 796 // 1) |icon_cur| is empty. This happens when "Most visited" or "Recently |
| 769 // closed" category updates for the 1st time after Chrome is launched. | 797 // closed" category updates for the 1st time after Chrome is launched. |
| 770 // 2) The number of icons in |icon_dir| has exceeded the limit. | 798 // 2) The number of icons in |icon_dir| has exceeded the limit. |
| 771 if (icon_cache->empty() || FilesExceedLimitInDir(icon_dir, slot_limit * 2)) { | 799 if (icon_cur->empty() || FilesExceedLimitInDir(icon_dir, slot_limit * 2)) { |
| 772 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | 800 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); |
| 773 icon_cache->clear(); | 801 icon_assoc->clear(); |
| 802 icon_cur->clear(); | |
| 803 icon_next->clear(); | |
| 804 | |
| 774 // Create new icons only when the directory exists and is empty. | 805 // Create new icons only when the directory exists and is empty. |
| 775 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | 806 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) { |
| 776 icons_created += | 807 icons_created += CreateIconFiles(icon_dir, page_list, slot_limit, |
| 777 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | 808 icon_assoc, icon_cur, icon_next); |
| 809 } | |
| 778 } else if (base::CreateDirectory(icon_dir)) { | 810 } else if (base::CreateDirectory(icon_dir)) { |
| 779 icons_created += | 811 icons_created += CreateIconFiles(icon_dir, page_list, slot_limit, |
| 780 CreateIconFiles(icon_dir, page_list, slot_limit, icon_cache); | 812 icon_assoc, icon_cur, icon_next); |
| 781 DeleteIconFiles(icon_dir, icon_cache); | |
| 782 } | 813 } |
| 783 | 814 |
| 784 return icons_created; | 815 return icons_created; |
| 785 } | 816 } |
| 786 | 817 |
| 787 // static | 818 // static |
| 788 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, | 819 int JumpList::CreateIconFiles(const base::FilePath& icon_dir, |
| 789 const ShellLinkItemList& item_list, | 820 const ShellLinkItemList& item_list, |
| 790 size_t max_items, | 821 size_t max_items, |
| 791 URLIconCache* icon_cache) { | 822 IconAssociation* icon_assoc, |
| 823 URLIconCache* icon_cur, | |
| 824 URLIconCache* icon_next) { | |
| 825 DCHECK(icon_assoc); | |
| 826 DCHECK(icon_cur); | |
| 827 DCHECK(icon_next); | |
| 828 | |
| 792 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 829 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 793 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | 830 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); |
| 794 | 831 |
| 795 int icons_created = 0; | 832 int icons_created = 0; |
| 796 | 833 |
| 834 // Mark all the icons kCurrent as they are used by the current JumpList. | |
| 835 for (auto iter = icon_assoc->begin(); iter != icon_assoc->end(); ++iter) | |
| 836 iter->second = JumpListVersion::kCurrent; | |
| 837 | |
| 797 // Reuse icons for urls that already present in the current JumpList. | 838 // Reuse icons for urls that already present in the current JumpList. |
| 798 URLIconCache updated_map; | |
| 799 for (ShellLinkItemList::const_iterator iter = item_list.begin(); | 839 for (ShellLinkItemList::const_iterator iter = item_list.begin(); |
| 800 iter != item_list.end() && max_items > 0; ++iter, --max_items) { | 840 iter != item_list.end() && max_items > 0; ++iter, --max_items) { |
| 801 ShellLinkItem* item = iter->get(); | 841 ShellLinkItem* item = iter->get(); |
| 802 auto cache_iter = icon_cache->find(item->url()); | 842 auto cache_iter = icon_cur->find(item->url()); |
| 803 if (cache_iter != icon_cache->end()) { | 843 if (cache_iter != icon_cur->end()) { |
| 804 item->set_icon(cache_iter->second.value(), 0); | 844 item->set_icon(cache_iter->second.value(), 0); |
| 805 updated_map[item->url()] = cache_iter->second; | 845 (*icon_next)[item->url()] = cache_iter->second; |
| 846 (*icon_assoc)[cache_iter->second] = JumpListVersion::kShared; | |
| 806 } else { | 847 } else { |
| 807 base::FilePath icon_path; | 848 base::FilePath icon_path; |
| 808 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { | 849 if (CreateIconFile(item->icon_image(), icon_dir, &icon_path)) { |
| 809 ++icons_created; | 850 ++icons_created; |
| 810 item->set_icon(icon_path.value(), 0); | 851 item->set_icon(icon_path.value(), 0); |
| 811 updated_map[item->url()] = icon_path; | 852 (*icon_next)[item->url()] = icon_path; |
| 853 (*icon_assoc)[icon_path] = JumpListVersion::kNext; | |
| 812 } | 854 } |
| 813 } | 855 } |
| 814 } | 856 } |
| 815 icon_cache->swap(updated_map); | |
| 816 | 857 |
| 817 return icons_created; | 858 return icons_created; |
| 818 } | 859 } |
| 819 | 860 |
| 820 // static | 861 // static |
| 862 void JumpList::DeleteIconFilesUnified( | |
| 863 const base::FilePath& most_visited_icon_dir, | |
| 864 const base::FilePath& recent_closed_icon_dir, | |
| 865 UpdateResults* update_results, | |
| 866 JumpListVersion version) { | |
| 867 DCHECK(update_results); | |
| 868 | |
| 869 if (update_results->most_visited_should_update) { | |
| 870 DeleteIconFiles(most_visited_icon_dir, | |
| 871 &update_results->most_visited_icon_assoc, version); | |
| 872 } | |
| 873 if (update_results->recent_closed_should_update) { | |
| 874 DeleteIconFiles(recent_closed_icon_dir, | |
| 875 &update_results->recent_closed_icon_assoc, version); | |
| 876 } | |
| 877 } | |
| 878 | |
| 879 // static | |
| 821 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, | 880 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, |
| 822 URLIconCache* icon_cache) { | 881 IconAssociation* icon_assoc, |
| 823 // Put all cached icon file paths into a set. | 882 JumpListVersion version) { |
| 883 DCHECK(icon_assoc); | |
| 884 | |
| 885 IconAssociation icon_assoc_updated; | |
| 886 | |
| 887 // Put paths of icon files to keep into a set. | |
| 824 base::flat_set<base::FilePath> cached_files; | 888 base::flat_set<base::FilePath> cached_files; |
| 825 cached_files.reserve(icon_cache->size()); | 889 cached_files.reserve(icon_assoc->size()); |
| 826 | 890 for (const auto& path_version_pair : *icon_assoc) { |
| 827 for (const auto& url_path_pair : *icon_cache) | 891 if (path_version_pair.second != version) { |
| 828 cached_files.insert(url_path_pair.second); | 892 cached_files.insert(path_version_pair.first); |
| 893 icon_assoc_updated[path_version_pair.first] = path_version_pair.second; | |
| 894 } | |
| 895 } | |
| 829 | 896 |
| 830 DeleteNonCachedFiles(icon_dir, cached_files); | 897 DeleteNonCachedFiles(icon_dir, cached_files); |
| 898 | |
| 899 // Keep icon_assoc up-to-date after deleting obsolete icons. | |
| 900 icon_assoc->swap(icon_assoc_updated); | |
| 831 } | 901 } |
| OLD | NEW |