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" |
| 11 #include "base/containers/flat_set.h" | |
| 11 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 14 #include "base/sequenced_task_runner.h" | 15 #include "base/sequenced_task_runner.h" |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_piece.h" | 17 #include "base/strings/string_piece.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/task_scheduler/post_task.h" | 20 #include "base/task_scheduler/post_task.h" |
| 20 #include "base/task_scheduler/task_traits.h" | 21 #include "base/task_scheduler/task_traits.h" |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 | 281 |
| 281 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { | 282 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { |
| 282 const history::MostVisitedURL& url = urls[i]; | 283 const history::MostVisitedURL& url = urls[i]; |
| 283 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 284 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
| 284 std::string url_string = url.url.spec(); | 285 std::string url_string = url.url.spec(); |
| 285 base::string16 url_string_wide = base::UTF8ToUTF16(url_string); | 286 base::string16 url_string_wide = base::UTF8ToUTF16(url_string); |
| 286 link->GetCommandLine()->AppendArgNative(url_string_wide); | 287 link->GetCommandLine()->AppendArgNative(url_string_wide); |
| 287 link->GetCommandLine()->AppendSwitchASCII( | 288 link->GetCommandLine()->AppendSwitchASCII( |
| 288 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); | 289 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); |
| 289 link->set_title(!url.title.empty() ? url.title : url_string_wide); | 290 link->set_title(!url.title.empty() ? url.title : url_string_wide); |
| 291 link->set_url(url_string); | |
| 290 data->most_visited_pages_.push_back(link); | 292 data->most_visited_pages_.push_back(link); |
| 291 data->icon_urls_.push_back(std::make_pair(url_string, link)); | 293 data->icon_urls_.push_back(std::make_pair(url_string, link)); |
| 292 } | 294 } |
| 293 data->most_visited_pages_have_updates_ = true; | 295 data->most_visited_pages_have_updates_ = true; |
| 294 } | 296 } |
| 295 | 297 |
| 296 // Send a query that retrieves the first favicon. | 298 // Send a query that retrieves the first favicon. |
| 297 StartLoadingFavicon(); | 299 StartLoadingFavicon(); |
| 298 } | 300 } |
| 299 | 301 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 return false; | 334 return false; |
| 333 | 335 |
| 334 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 336 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
| 335 const sessions::SerializedNavigationEntry& current_navigation = | 337 const sessions::SerializedNavigationEntry& current_navigation = |
| 336 tab.navigations.at(tab.current_navigation_index); | 338 tab.navigations.at(tab.current_navigation_index); |
| 337 std::string url = current_navigation.virtual_url().spec(); | 339 std::string url = current_navigation.virtual_url().spec(); |
| 338 link->GetCommandLine()->AppendArgNative(base::UTF8ToUTF16(url)); | 340 link->GetCommandLine()->AppendArgNative(base::UTF8ToUTF16(url)); |
| 339 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, | 341 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, |
| 340 jumplist::kRecentlyClosedCategory); | 342 jumplist::kRecentlyClosedCategory); |
| 341 link->set_title(current_navigation.title()); | 343 link->set_title(current_navigation.title()); |
| 344 link->set_url(url); | |
| 342 data->recently_closed_pages_.push_back(link); | 345 data->recently_closed_pages_.push_back(link); |
| 343 data->icon_urls_.push_back(std::make_pair(std::move(url), std::move(link))); | 346 data->icon_urls_.push_back(std::make_pair(std::move(url), std::move(link))); |
| 344 | 347 |
| 345 return true; | 348 return true; |
| 346 } | 349 } |
| 347 | 350 |
| 348 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, | 351 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, |
| 349 size_t max_items, | 352 size_t max_items, |
| 350 JumpListData* data) { | 353 JumpListData* data) { |
| 351 DCHECK(CalledOnValidThread()); | 354 DCHECK(CalledOnValidThread()); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 } | 562 } |
| 560 } | 563 } |
| 561 | 564 |
| 562 data->recently_closed_pages_have_updates_ = true; | 565 data->recently_closed_pages_have_updates_ = true; |
| 563 } | 566 } |
| 564 | 567 |
| 565 // Send a query that retrieves the first favicon. | 568 // Send a query that retrieves the first favicon. |
| 566 StartLoadingFavicon(); | 569 StartLoadingFavicon(); |
| 567 } | 570 } |
| 568 | 571 |
| 572 void JumpList::DeleteIconFiles(const base::FilePath& icon_dir, | |
| 573 JumpListCategory category) { | |
| 574 base::flat_map<std::string, base::FilePath>* source_map = nullptr; | |
| 575 switch (category) { | |
| 576 case JumpListCategory::kMostVisited: | |
| 577 source_map = &most_visited_map_; | |
| 578 break; | |
| 579 case JumpListCategory::kRecentlyClosed: | |
| 580 source_map = &recently_closed_map_; | |
| 581 break; | |
| 582 } | |
| 583 | |
| 584 if (!source_map) | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
remove this check -- it can't be hit under normal
chengx
2017/05/17 21:59:36
Done.
| |
| 585 return; | |
| 586 | |
| 587 // Put all cached icon file paths into a set. | |
| 588 base::flat_set<base::FilePath> cached_files; | |
| 589 cached_files.reserve(source_map->size()); | |
| 590 | |
| 591 for (const auto& url_path_pair : *source_map) | |
| 592 cached_files.insert(cached_files.end(), url_path_pair.second); | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
oops, i was wrong about this being O(N) -- that wo
chengx
2017/05/17 21:59:36
I would go with the latter one too, as the size of
| |
| 593 | |
| 594 DeleteNonCachedFiles(icon_dir, cached_files); | |
| 595 } | |
| 596 | |
| 569 void JumpList::CreateIconFiles(const base::FilePath& icon_dir, | 597 void JumpList::CreateIconFiles(const base::FilePath& icon_dir, |
| 570 const ShellLinkItemList& item_list, | 598 const ShellLinkItemList& item_list, |
| 571 size_t max_items) { | 599 size_t max_items, |
| 600 JumpListCategory category) { | |
| 572 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 601 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 573 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | 602 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); |
| 574 | 603 |
| 604 // If the current URL is cached which means there's already an icon for this | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
maybe this can be simplified by removing the idea
chengx
2017/05/17 21:59:36
Done.
| |
| 605 // URL, then we simply re-use the icon. Otherwise, we need to create a new | |
| 606 // icon for this URL. | |
| 607 | |
| 608 base::flat_map<std::string, base::FilePath>* source_map = nullptr; | |
| 609 switch (category) { | |
| 610 case JumpListCategory::kMostVisited: | |
| 611 source_map = &most_visited_map_; | |
| 612 break; | |
| 613 case JumpListCategory::kRecentlyClosed: | |
| 614 source_map = &recently_closed_map_; | |
| 615 break; | |
| 616 } | |
| 617 | |
| 618 if (!source_map) | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
remove as above
chengx
2017/05/17 21:59:36
Done.
| |
| 619 return; | |
| 620 | |
| 621 base::flat_map<std::string, base::FilePath> updated_map; | |
| 622 | |
| 575 for (ShellLinkItemList::const_iterator item = item_list.begin(); | 623 for (ShellLinkItemList::const_iterator item = item_list.begin(); |
| 576 item != item_list.end() && max_items > 0; ++item, --max_items) { | 624 item != item_list.end() && max_items > 0; ++item, --max_items) { |
| 577 base::FilePath icon_path; | 625 if (source_map->find((*item)->url()) != source_map->end()) { |
|
grt (UTC plus 2)
2017/05/15 11:28:19
nit: (*item)-> everywhere is a bit ugly. how about
chengx
2017/05/17 21:59:36
Done.
| |
| 578 if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path)) | 626 base::FilePath path = (*source_map)[(*item)->url()]; |
|
grt (UTC plus 2)
2017/05/15 11:28:19
rather than indexing into the map a second time, c
chengx
2017/05/17 21:59:36
Done.
| |
| 579 (*item)->set_icon(icon_path.value(), 0); | 627 (*item)->set_icon((*source_map)[(*item)->url()].value(), 0); |
| 628 updated_map[(*item)->url()] = path; | |
| 629 } else { | |
| 630 base::FilePath icon_path; | |
| 631 if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path)) { | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
rather than creating new icons as you go here and
chengx
2017/05/17 21:59:36
I understand what you suggest here, but IMHO it do
| |
| 632 (*item)->set_icon(icon_path.value(), 0); | |
| 633 updated_map[(*item)->url()] = icon_path; | |
| 634 } | |
| 635 } | |
| 580 } | 636 } |
| 637 source_map->swap(updated_map); | |
| 581 } | 638 } |
| 582 | 639 |
| 583 void JumpList::UpdateIconFiles(const base::FilePath& icon_dir, | 640 void JumpList::UpdateIconFiles(const base::FilePath& icon_dir, |
| 584 const ShellLinkItemList& page_list, | 641 const ShellLinkItemList& page_list, |
| 585 size_t slot_limit) { | 642 size_t slot_limit, |
| 586 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | 643 JumpListCategory category) { |
| 644 // Maximum number of icon files that each JumpList icon folder allows to hold. | |
| 645 size_t icon_limit = (category == JumpListCategory::kMostVisited) ? 12 : 6; | |
| 587 | 646 |
| 588 // Create new icons only when the directory exists and is empty. | 647 // Clear the JumpList icon folder at |icon_dir| and the cache when |
| 589 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | 648 // 1) "Most visited" category updates for the 1st time after Chrome is |
| 590 CreateIconFiles(icon_dir, page_list, slot_limit); | 649 // launched. This actually happens right after Chrome is launched. |
| 650 // 2) "Recently closed" category updates for the 1st time after Chrome is | |
| 651 // launched. | |
| 652 // 3) The number of icons in |icon_dir| has exceeded the limit. | |
| 653 if ((category == JumpListCategory::kMostVisited && | |
| 654 most_visited_map_.empty()) || | |
| 655 (category == JumpListCategory::kRecentlyClosed && | |
| 656 recently_closed_map_.empty()) || | |
| 657 FilesExceedLimitInDir(icon_dir, icon_limit)) { | |
| 658 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | |
| 659 most_visited_map_.clear(); | |
| 660 recently_closed_map_.clear(); | |
| 661 // Create new icons only when the directory exists and is empty. | |
| 662 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | |
| 663 CreateIconFiles(icon_dir, page_list, slot_limit, category); | |
| 664 } else if (base::CreateDirectory(icon_dir)) { | |
| 665 CreateIconFiles(icon_dir, page_list, slot_limit, category); | |
|
grt (UTC plus 2)
2017/05/15 11:28:19
should this check that the max # of files isn't be
chengx
2017/05/17 21:59:36
No, this won't cause the dir-with-too-many-files p
| |
| 666 DeleteIconFiles(icon_dir, category); | |
| 667 } | |
| 591 } | 668 } |
| 592 | 669 |
| 593 bool JumpList::UpdateJumpList( | 670 bool JumpList::UpdateJumpList( |
| 594 const base::string16& app_id, | 671 const base::string16& app_id, |
| 595 const base::FilePath& profile_dir, | 672 const base::FilePath& profile_dir, |
| 596 const ShellLinkItemList& most_visited_pages, | 673 const ShellLinkItemList& most_visited_pages, |
| 597 const ShellLinkItemList& recently_closed_pages, | 674 const ShellLinkItemList& recently_closed_pages, |
| 598 bool most_visited_pages_have_updates, | 675 bool most_visited_pages_have_updates, |
| 599 bool recently_closed_pages_have_updates, | 676 bool recently_closed_pages_have_updates, |
| 600 IncognitoModePrefs::Availability incognito_availability) { | 677 IncognitoModePrefs::Availability incognito_availability) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 | 724 |
| 648 // Record the desired number of icons to create in this JumpList update. | 725 // Record the desired number of icons to create in this JumpList update. |
| 649 int icons_to_create = 0; | 726 int icons_to_create = 0; |
| 650 | 727 |
| 651 // Update the icons for "Most Visisted" category of the JumpList if needed. | 728 // Update the icons for "Most Visisted" category of the JumpList if needed. |
| 652 if (most_visited_pages_have_updates) { | 729 if (most_visited_pages_have_updates) { |
| 653 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( | 730 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( |
| 654 profile_dir, FILE_PATH_LITERAL("MostVisited")); | 731 profile_dir, FILE_PATH_LITERAL("MostVisited")); |
| 655 | 732 |
| 656 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, | 733 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, |
| 657 most_visited_items); | 734 most_visited_items, JumpListCategory::kMostVisited); |
| 658 | 735 |
| 659 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); | 736 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); |
| 660 } | 737 } |
| 661 | 738 |
| 662 // Update the icons for "Recently Closed" category of the JumpList if needed. | 739 // Update the icons for "Recently Closed" category of the JumpList if needed. |
| 663 if (recently_closed_pages_have_updates) { | 740 if (recently_closed_pages_have_updates) { |
| 664 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( | 741 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( |
| 665 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | 742 profile_dir, FILE_PATH_LITERAL("RecentClosed")); |
| 666 | 743 |
| 667 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, | 744 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, |
| 668 recently_closed_items); | 745 recently_closed_items, JumpListCategory::kRecentlyClosed); |
| 669 | 746 |
| 670 icons_to_create += | 747 icons_to_create += |
| 671 std::min(recently_closed_pages.size(), recently_closed_items); | 748 std::min(recently_closed_pages.size(), recently_closed_items); |
| 672 } | 749 } |
| 673 | 750 |
| 674 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | 751 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 675 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); | 752 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); |
| 676 | 753 |
| 677 // 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. |
| 678 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | 755 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 app_id, profile_dir, local_most_visited_pages, | 819 app_id, profile_dir, local_most_visited_pages, |
| 743 local_recently_closed_pages, most_visited_pages_have_updates, | 820 local_recently_closed_pages, most_visited_pages_have_updates, |
| 744 recently_closed_pages_have_updates, incognito_availability)) { | 821 recently_closed_pages_have_updates, incognito_availability)) { |
| 745 base::AutoLock auto_lock(data->list_lock_); | 822 base::AutoLock auto_lock(data->list_lock_); |
| 746 if (most_visited_pages_have_updates) | 823 if (most_visited_pages_have_updates) |
| 747 data->most_visited_pages_have_updates_ = true; | 824 data->most_visited_pages_have_updates_ = true; |
| 748 if (recently_closed_pages_have_updates) | 825 if (recently_closed_pages_have_updates) |
| 749 data->recently_closed_pages_have_updates_ = true; | 826 data->recently_closed_pages_have_updates_ = true; |
| 750 } | 827 } |
| 751 } | 828 } |
| OLD | NEW |