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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/win/jumplist.cc
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index 24ac405c820d75e2c19b92784cc03fe21829bc8d..d79dae180d7feb40036c2dbca98197baa16dc06f 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/containers/flat_set.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
@@ -287,6 +288,7 @@ void JumpList::OnMostVisitedURLsAvailable(
link->GetCommandLine()->AppendSwitchASCII(
switches::kWinJumplistAction, jumplist::kMostVisitedCategory);
link->set_title(!url.title.empty() ? url.title : url_string_wide);
+ link->set_url(url_string);
data->most_visited_pages_.push_back(link);
data->icon_urls_.push_back(std::make_pair(url_string, link));
}
@@ -339,6 +341,7 @@ bool JumpList::AddTab(const sessions::TabRestoreService::Tab& tab,
link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction,
jumplist::kRecentlyClosedCategory);
link->set_title(current_navigation.title());
+ link->set_url(url);
data->recently_closed_pages_.push_back(link);
data->icon_urls_.push_back(std::make_pair(std::move(url), std::move(link)));
@@ -566,28 +569,102 @@ void JumpList::DeferredTabRestoreServiceChanged() {
StartLoadingFavicon();
}
+void JumpList::DeleteIconFiles(const base::FilePath& icon_dir,
+ JumpListCategory category) {
+ base::flat_map<std::string, base::FilePath>* source_map = nullptr;
+ switch (category) {
+ case JumpListCategory::kMostVisited:
+ source_map = &most_visited_map_;
+ break;
+ case JumpListCategory::kRecentlyClosed:
+ source_map = &recently_closed_map_;
+ break;
+ }
+
+ 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.
+ return;
+
+ // Put all cached icon file paths into a set.
+ base::flat_set<base::FilePath> cached_files;
+ cached_files.reserve(source_map->size());
+
+ for (const auto& url_path_pair : *source_map)
+ 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
+
+ DeleteNonCachedFiles(icon_dir, cached_files);
+}
+
void JumpList::CreateIconFiles(const base::FilePath& icon_dir,
const ShellLinkItemList& item_list,
- size_t max_items) {
+ size_t max_items,
+ JumpListCategory category) {
// TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407.
SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration");
+ // 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.
+ // URL, then we simply re-use the icon. Otherwise, we need to create a new
+ // icon for this URL.
+
+ base::flat_map<std::string, base::FilePath>* source_map = nullptr;
+ switch (category) {
+ case JumpListCategory::kMostVisited:
+ source_map = &most_visited_map_;
+ break;
+ case JumpListCategory::kRecentlyClosed:
+ source_map = &recently_closed_map_;
+ break;
+ }
+
+ if (!source_map)
grt (UTC plus 2) 2017/05/15 11:28:19 remove as above
chengx 2017/05/17 21:59:36 Done.
+ return;
+
+ base::flat_map<std::string, base::FilePath> updated_map;
+
for (ShellLinkItemList::const_iterator item = item_list.begin();
item != item_list.end() && max_items > 0; ++item, --max_items) {
- base::FilePath icon_path;
- if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path))
- (*item)->set_icon(icon_path.value(), 0);
+ 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.
+ 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.
+ (*item)->set_icon((*source_map)[(*item)->url()].value(), 0);
+ updated_map[(*item)->url()] = path;
+ } else {
+ base::FilePath icon_path;
+ 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
+ (*item)->set_icon(icon_path.value(), 0);
+ updated_map[(*item)->url()] = icon_path;
+ }
+ }
}
+ source_map->swap(updated_map);
}
void JumpList::UpdateIconFiles(const base::FilePath& icon_dir,
const ShellLinkItemList& page_list,
- size_t slot_limit) {
- DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit);
-
- // Create new icons only when the directory exists and is empty.
- if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir))
- CreateIconFiles(icon_dir, page_list, slot_limit);
+ size_t slot_limit,
+ JumpListCategory category) {
+ // Maximum number of icon files that each JumpList icon folder allows to hold.
+ size_t icon_limit = (category == JumpListCategory::kMostVisited) ? 12 : 6;
+
+ // Clear the JumpList icon folder at |icon_dir| and the cache when
+ // 1) "Most visited" category updates for the 1st time after Chrome is
+ // launched. This actually happens right after Chrome is launched.
+ // 2) "Recently closed" category updates for the 1st time after Chrome is
+ // launched.
+ // 3) The number of icons in |icon_dir| has exceeded the limit.
+ if ((category == JumpListCategory::kMostVisited &&
+ most_visited_map_.empty()) ||
+ (category == JumpListCategory::kRecentlyClosed &&
+ recently_closed_map_.empty()) ||
+ FilesExceedLimitInDir(icon_dir, icon_limit)) {
+ DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit);
+ most_visited_map_.clear();
+ recently_closed_map_.clear();
+ // Create new icons only when the directory exists and is empty.
+ if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir))
+ CreateIconFiles(icon_dir, page_list, slot_limit, category);
+ } else if (base::CreateDirectory(icon_dir)) {
+ 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
+ DeleteIconFiles(icon_dir, category);
+ }
}
bool JumpList::UpdateJumpList(
@@ -654,7 +731,7 @@ bool JumpList::UpdateJumpList(
profile_dir, FILE_PATH_LITERAL("MostVisited"));
UpdateIconFiles(icon_dir_most_visited, most_visited_pages,
- most_visited_items);
+ most_visited_items, JumpListCategory::kMostVisited);
icons_to_create += std::min(most_visited_pages.size(), most_visited_items);
}
@@ -665,7 +742,7 @@ bool JumpList::UpdateJumpList(
profile_dir, FILE_PATH_LITERAL("RecentClosed"));
UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages,
- recently_closed_items);
+ recently_closed_items, JumpListCategory::kRecentlyClosed);
icons_to_create +=
std::min(recently_closed_pages.size(), recently_closed_items);

Powered by Google App Engine
This is Rietveld 408576698