Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: chrome/browser/win/jumplist.cc

Issue 2859193005: Cache JumpList icons to avoid unnecessary creation and deletion (Closed)
Patch Set: Address comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698