| Index: chrome/browser/win/jumplist.cc
|
| diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
|
| index 680db16a6a490256bf10dd17a699b6806db5152a..2773e1c34dd349eb5f5ec18303951672b4e47238 100644
|
| --- a/chrome/browser/win/jumplist.cc
|
| +++ b/chrome/browser/win/jumplist.cc
|
| @@ -5,11 +5,9 @@
|
| #include "chrome/browser/win/jumplist.h"
|
|
|
| #include <Shlwapi.h>
|
| -#include <windows.h>
|
|
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| -#include "base/callback_helpers.h"
|
| #include "base/command_line.h"
|
| #include "base/files/file_util.h"
|
| #include "base/macros.h"
|
| @@ -27,6 +25,7 @@
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/sessions/tab_restore_service_factory.h"
|
| #include "chrome/browser/shell_integration_win.h"
|
| +#include "chrome/browser/win/jumplist_file_util.h"
|
| #include "chrome/common/chrome_constants.h"
|
| #include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/pref_names.h"
|
| @@ -229,28 +228,13 @@ bool UpdateJumpList(const wchar_t* app_id,
|
| return true;
|
| }
|
|
|
| -// Renames the directory |from_dir| to |to_path|. This method fails if any
|
| -// process has a handle open in |from_dir| or if |to_path| exists. Base::Move()
|
| -// tries to rename a file and if this fails, it tries copy-n-delete; This
|
| -// RenameDirectory method only does the rename part.
|
| -bool RenameDirectory(const base::FilePath& from_path,
|
| - const base::FilePath& to_path) {
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| - if (from_path.ReferencesParent() || to_path.ReferencesParent())
|
| - return false;
|
| - if (from_path.value().length() >= MAX_PATH ||
|
| - to_path.value().length() >= MAX_PATH) {
|
| - return false;
|
| - }
|
| - return MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), 0) != 0;
|
| -}
|
| -
|
| // Updates the jumplist, once all the data has been fetched.
|
| void RunUpdateOnFileThread(
|
| IncognitoModePrefs::Availability incognito_availability,
|
| const std::wstring& app_id,
|
| const base::FilePath& icon_dir,
|
| - base::RefCountedData<JumpListData>* ref_counted_data) {
|
| + base::RefCountedData<JumpListData>* ref_counted_data,
|
| + const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner) {
|
| JumpListData* data = &ref_counted_data->data;
|
| ShellLinkItemList local_most_visited_pages;
|
| ShellLinkItemList local_recently_closed_pages;
|
| @@ -267,73 +251,21 @@ void RunUpdateOnFileThread(
|
| local_recently_closed_pages = data->recently_closed_pages_;
|
| }
|
|
|
| - // Delete the directory which contains old icon files, rename the current
|
| - // icon directory, and create a new directory which contains new JumpList
|
| - // icon files.
|
| - base::FilePath icon_dir_old = icon_dir.DirName().Append(
|
| - icon_dir.BaseName().value() + FILE_PATH_LITERAL("Old"));
|
| + // Delete the contents in JumpListIcons directory and log the delete status
|
| + // to UMA.
|
| + FolderDeleteResult delete_status =
|
| + DeleteDirectoryContent(icon_dir, kMaxFilesDeleted);
|
|
|
| - enum FolderOperationResult {
|
| - SUCCESS = 0,
|
| - DELETE_DEST_FAILED = 1 << 0,
|
| - RENAME_FAILED = 1 << 1,
|
| - DELETE_SRC_CONTENT_FAILED = 1 << 2,
|
| - DELETE_SRC_DIR_FAILED = 1 << 3,
|
| - CREATE_SRC_FAILED = 1 << 4,
|
| - // This value is beyond the sum of all bit fields above and
|
| - // should remain last (shifted by one more than the last value)
|
| - END = 1 << 5
|
| - };
|
| -
|
| - // This variable records the status of three folder operations.
|
| - uint32_t folder_operation_status = FolderOperationResult::SUCCESS;
|
| -
|
| - base::ScopedClosureRunner log_operation_status_when_done(base::Bind(
|
| - [](uint32_t* folder_operation_status_ptr) {
|
| - UMA_HISTOGRAM_ENUMERATION(
|
| - "WinJumplist.DetailedFolderResultsDeleteUpdated",
|
| - *folder_operation_status_ptr, FolderOperationResult::END);
|
| - },
|
| - base::Unretained(&folder_operation_status)));
|
| -
|
| - // If deletion of |icon_dir_old| fails, do not rename |icon_dir| to
|
| - // |icon_dir_old|, instead, delete |icon_dir| directly to avoid bloating
|
| - // |icon_dir_old| by moving more things to it.
|
| - if (!base::DeleteFile(icon_dir_old, true)) {
|
| - folder_operation_status |= FolderOperationResult::DELETE_DEST_FAILED;
|
| - // If deletion of any item in |icon_dir| fails, exit early. If deletion of
|
| - // all the items succeeds while only deletion of the dir fails, it is okay
|
| - // to proceed. This skips creating the same directory and updating jumplist
|
| - // icons to avoid bloating the JumplistIcons folder.
|
| - if (!base::DeleteFile(icon_dir, true)) {
|
| - if (!::PathIsDirectoryEmpty(icon_dir.value().c_str())) {
|
| - folder_operation_status |=
|
| - FolderOperationResult::DELETE_SRC_CONTENT_FAILED;
|
| - return;
|
| - }
|
| - folder_operation_status |= FolderOperationResult::DELETE_SRC_DIR_FAILED;
|
| - }
|
| - } else if (!RenameDirectory(icon_dir, icon_dir_old)) {
|
| - // If RenameDirectory() fails, delete |icon_dir| to avoid file accumulation
|
| - // in this directory, which can eventually lead the folder to be huge.
|
| - folder_operation_status |= FolderOperationResult::RENAME_FAILED;
|
| - // If deletion of any item in |icon_dir| fails, exit early. If deletion of
|
| - // all the items succeeds while only deletion of the dir fails, it is okay
|
| - // to proceed. This skips creating the same directory and updating jumplist
|
| - // icons to avoid bloating the JumplistIcons folder.
|
| - if (!base::DeleteFile(icon_dir, true)) {
|
| - if (!::PathIsDirectoryEmpty(icon_dir.value().c_str())) {
|
| - folder_operation_status |=
|
| - FolderOperationResult::DELETE_SRC_CONTENT_FAILED;
|
| - return;
|
| - }
|
| - folder_operation_status |= FolderOperationResult::DELETE_SRC_DIR_FAILED;
|
| - }
|
| - }
|
| + UMA_HISTOGRAM_ENUMERATION("WinJumplist.DeleteStatusJumpListIcons",
|
| + delete_status, END);
|
|
|
| - // If CreateDirectory() fails, exit early.
|
| - if (!base::CreateDirectory(icon_dir)) {
|
| - folder_operation_status |= FolderOperationResult::CREATE_SRC_FAILED;
|
| + // If JumpListIcons directory is not empty, skip jumplist update and return
|
| + // early. If the directory doesn't exist which shouldn't though, try to create
|
| + // a new JumpListIcons directory. If the creation fails, return early.
|
| + if (base::DirectoryExists(icon_dir)) {
|
| + if (!::PathIsDirectoryEmpty(icon_dir.value().c_str()))
|
| + return;
|
| + } else if (!base::CreateDirectory(icon_dir)) {
|
| return;
|
| }
|
|
|
| @@ -349,6 +281,17 @@ void RunUpdateOnFileThread(
|
| // with it.
|
| UpdateJumpList(app_id.c_str(), local_most_visited_pages,
|
| local_recently_closed_pages, incognito_availability);
|
| +
|
| + // Post a background task to delete JumpListIconsOld folder if it exists and
|
| + // log the delete results to UMA.
|
| + base::FilePath icon_dir_old = icon_dir.DirName().Append(
|
| + icon_dir.BaseName().value() + FILE_PATH_LITERAL("Old"));
|
| +
|
| + if (base::DirectoryExists(icon_dir_old)) {
|
| + sequenced_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(&DeleteDirectoryAndLogResults, icon_dir_old,
|
| + kMaxFilesDeleted));
|
| + }
|
| }
|
|
|
| } // namespace
|
| @@ -363,6 +306,12 @@ JumpList::JumpList(Profile* profile)
|
| profile_(profile),
|
| jumplist_data_(new base::RefCountedData<JumpListData>),
|
| task_id_(base::CancelableTaskTracker::kBadTaskId),
|
| + sequenced_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
|
| + base::TaskTraits()
|
| + .WithPriority(base::TaskPriority::BACKGROUND)
|
| + .WithShutdownBehavior(
|
| + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
|
| + .MayBlock())),
|
| weak_ptr_factory_(this) {
|
| DCHECK(Enabled());
|
| // To update JumpList when a tab is added or removed, we add this object to
|
| @@ -661,11 +610,9 @@ void JumpList::DeferredRunUpdate() {
|
|
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&RunUpdateOnFileThread,
|
| - incognito_availability,
|
| - app_id_,
|
| - icon_dir_,
|
| - base::RetainedRef(jumplist_data_)));
|
| + base::Bind(&RunUpdateOnFileThread, incognito_availability, app_id_,
|
| + icon_dir_, base::RetainedRef(jumplist_data_),
|
| + sequenced_task_runner_));
|
| }
|
|
|
| void JumpList::TopSitesLoaded(history::TopSites* top_sites) {
|
|
|