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

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

Issue 2752063002: Remove JumpListIconsOld directory and set upper limit for delete attempts (Closed)
Patch Set: Merge branch 'master' of https://chromium.googlesource.com/chromium/src into jumplistdeletesetupperā€¦ Created 3 years, 9 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
« no previous file with comments | « chrome/browser/win/jumplist.h ('k') | chrome/browser/win/jumplist_file_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <Shlwapi.h> 7 #include <Shlwapi.h>
8 #include <windows.h>
9 8
10 #include "base/bind.h" 9 #include "base/bind.h"
11 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h" 11 #include "base/command_line.h"
14 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
15 #include "base/macros.h" 13 #include "base/macros.h"
16 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
17 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/sequenced_task_runner.h"
18 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
19 #include "base/task_scheduler/post_task.h"
20 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
21 #include "base/threading/thread_restrictions.h" 21 #include "base/threading/thread_restrictions.h"
22 #include "base/trace_event/trace_event.h" 22 #include "base/trace_event/trace_event.h"
23 #include "chrome/browser/chrome_notification_types.h" 23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/favicon/favicon_service_factory.h" 24 #include "chrome/browser/favicon/favicon_service_factory.h"
25 #include "chrome/browser/history/top_sites_factory.h" 25 #include "chrome/browser/history/top_sites_factory.h"
26 #include "chrome/browser/metrics/jumplist_metrics_win.h" 26 #include "chrome/browser/metrics/jumplist_metrics_win.h"
27 #include "chrome/browser/profiles/profile.h" 27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/sessions/tab_restore_service_factory.h" 28 #include "chrome/browser/sessions/tab_restore_service_factory.h"
29 #include "chrome/browser/shell_integration_win.h" 29 #include "chrome/browser/shell_integration_win.h"
30 #include "chrome/browser/win/jumplist_file_util.h"
30 #include "chrome/common/chrome_constants.h" 31 #include "chrome/common/chrome_constants.h"
31 #include "chrome/common/chrome_icon_resources_win.h" 32 #include "chrome/common/chrome_icon_resources_win.h"
32 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/pref_names.h" 34 #include "chrome/common/pref_names.h"
34 #include "chrome/common/url_constants.h" 35 #include "chrome/common/url_constants.h"
35 #include "chrome/grit/generated_resources.h" 36 #include "chrome/grit/generated_resources.h"
36 #include "chrome/installer/util/browser_distribution.h" 37 #include "chrome/installer/util/browser_distribution.h"
37 #include "components/favicon/core/favicon_service.h" 38 #include "components/favicon/core/favicon_service.h"
38 #include "components/favicon_base/favicon_types.h" 39 #include "components/favicon_base/favicon_types.h"
39 #include "components/history/core/browser/history_service.h" 40 #include "components/history/core/browser/history_service.h"
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) 223 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability))
223 return false; 224 return false;
224 225
225 // Commit this transaction and send the updated JumpList to Windows. 226 // Commit this transaction and send the updated JumpList to Windows.
226 if (!jumplist_updater.CommitUpdate()) 227 if (!jumplist_updater.CommitUpdate())
227 return false; 228 return false;
228 229
229 return true; 230 return true;
230 } 231 }
231 232
232 // Renames the directory |from_dir| to |to_path|. This method fails if any
233 // process has a handle open in |from_dir| or if |to_path| exists. Base::Move()
234 // tries to rename a file and if this fails, it tries copy-n-delete; This
235 // RenameDirectory method only does the rename part.
236 bool RenameDirectory(const base::FilePath& from_path,
237 const base::FilePath& to_path) {
238 base::ThreadRestrictions::AssertIOAllowed();
239 if (from_path.ReferencesParent() || to_path.ReferencesParent())
240 return false;
241 if (from_path.value().length() >= MAX_PATH ||
242 to_path.value().length() >= MAX_PATH) {
243 return false;
244 }
245 return MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), 0) != 0;
246 }
247
248 // Updates the jumplist, once all the data has been fetched. 233 // Updates the jumplist, once all the data has been fetched.
249 void RunUpdateOnFileThread( 234 void RunUpdateOnFileThread(
250 IncognitoModePrefs::Availability incognito_availability, 235 IncognitoModePrefs::Availability incognito_availability,
251 const std::wstring& app_id, 236 const std::wstring& app_id,
252 const base::FilePath& icon_dir, 237 const base::FilePath& icon_dir,
253 base::RefCountedData<JumpListData>* ref_counted_data) { 238 base::RefCountedData<JumpListData>* ref_counted_data,
239 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner) {
254 JumpListData* data = &ref_counted_data->data; 240 JumpListData* data = &ref_counted_data->data;
255 ShellLinkItemList local_most_visited_pages; 241 ShellLinkItemList local_most_visited_pages;
256 ShellLinkItemList local_recently_closed_pages; 242 ShellLinkItemList local_recently_closed_pages;
257 243
258 { 244 {
259 base::AutoLock auto_lock(data->list_lock_); 245 base::AutoLock auto_lock(data->list_lock_);
260 // Make sure we are not out of date: if icon_urls_ is not empty, then 246 // Make sure we are not out of date: if icon_urls_ is not empty, then
261 // another notification has been received since we processed this one 247 // another notification has been received since we processed this one
262 if (!data->icon_urls_.empty()) 248 if (!data->icon_urls_.empty())
263 return; 249 return;
264 250
265 // Make local copies of lists so we can release the lock. 251 // Make local copies of lists so we can release the lock.
266 local_most_visited_pages = data->most_visited_pages_; 252 local_most_visited_pages = data->most_visited_pages_;
267 local_recently_closed_pages = data->recently_closed_pages_; 253 local_recently_closed_pages = data->recently_closed_pages_;
268 } 254 }
269 255
270 // Delete the directory which contains old icon files, rename the current 256 // Delete the contents in JumpListIcons directory and log the delete status
271 // icon directory, and create a new directory which contains new JumpList 257 // to UMA.
272 // icon files. 258 FolderDeleteResult delete_status =
273 base::FilePath icon_dir_old = icon_dir.DirName().Append( 259 DeleteDirectoryContent(icon_dir, kFileDeleteLimit);
274 icon_dir.BaseName().value() + FILE_PATH_LITERAL("Old"));
275 260
276 enum FolderOperationResult { 261 UMA_HISTOGRAM_ENUMERATION("WinJumplist.DeleteStatusJumpListIcons",
277 SUCCESS = 0, 262 delete_status, END);
278 DELETE_DEST_FAILED = 1 << 0,
279 RENAME_FAILED = 1 << 1,
280 DELETE_SRC_CONTENT_FAILED = 1 << 2,
281 DELETE_SRC_DIR_FAILED = 1 << 3,
282 CREATE_SRC_FAILED = 1 << 4,
283 // This value is beyond the sum of all bit fields above and
284 // should remain last (shifted by one more than the last value)
285 END = 1 << 5
286 };
287 263
288 // This variable records the status of three folder operations. 264 // If JumpListIcons directory is not empty, skip jumplist update and return
289 uint32_t folder_operation_status = FolderOperationResult::SUCCESS; 265 // early. If the directory doesn't exist which shouldn't though, try to create
290 266 // a new JumpListIcons directory. If the creation fails, return early.
291 base::ScopedClosureRunner log_operation_status_when_done(base::Bind( 267 if (base::DirectoryExists(icon_dir)) {
292 [](uint32_t* folder_operation_status_ptr) { 268 DirectoryEmptyStatus empty_status =
293 UMA_HISTOGRAM_ENUMERATION( 269 ::PathIsDirectoryEmpty(icon_dir.value().c_str()) ? EMPTY : NON_EMPTY;
294 "WinJumplist.DetailedFolderResultsDeleteUpdated", 270 UMA_HISTOGRAM_ENUMERATION("WinJumplist.EmptyStatusJumpListIcons",
295 *folder_operation_status_ptr, FolderOperationResult::END); 271 empty_status, EMPTY_STATUS_END);
296 }, 272 if (empty_status == NON_EMPTY)
297 base::Unretained(&folder_operation_status))); 273 return;
298 274 } else if (!base::CreateDirectory(icon_dir)) {
299 // If deletion of |icon_dir_old| fails, do not rename |icon_dir| to
300 // |icon_dir_old|, instead, delete |icon_dir| directly to avoid bloating
301 // |icon_dir_old| by moving more things to it.
302 if (!base::DeleteFile(icon_dir_old, true)) {
303 folder_operation_status |= FolderOperationResult::DELETE_DEST_FAILED;
304 // If deletion of any item in |icon_dir| fails, exit early. If deletion of
305 // all the items succeeds while only deletion of the dir fails, it is okay
306 // to proceed. This skips creating the same directory and updating jumplist
307 // icons to avoid bloating the JumplistIcons folder.
308 if (!base::DeleteFile(icon_dir, true)) {
309 if (!::PathIsDirectoryEmpty(icon_dir.value().c_str())) {
310 folder_operation_status |=
311 FolderOperationResult::DELETE_SRC_CONTENT_FAILED;
312 return;
313 }
314 folder_operation_status |= FolderOperationResult::DELETE_SRC_DIR_FAILED;
315 }
316 } else if (!RenameDirectory(icon_dir, icon_dir_old)) {
317 // If RenameDirectory() fails, delete |icon_dir| to avoid file accumulation
318 // in this directory, which can eventually lead the folder to be huge.
319 folder_operation_status |= FolderOperationResult::RENAME_FAILED;
320 // If deletion of any item in |icon_dir| fails, exit early. If deletion of
321 // all the items succeeds while only deletion of the dir fails, it is okay
322 // to proceed. This skips creating the same directory and updating jumplist
323 // icons to avoid bloating the JumplistIcons folder.
324 if (!base::DeleteFile(icon_dir, true)) {
325 if (!::PathIsDirectoryEmpty(icon_dir.value().c_str())) {
326 folder_operation_status |=
327 FolderOperationResult::DELETE_SRC_CONTENT_FAILED;
328 return;
329 }
330 folder_operation_status |= FolderOperationResult::DELETE_SRC_DIR_FAILED;
331 }
332 }
333
334 // If CreateDirectory() fails, exit early.
335 if (!base::CreateDirectory(icon_dir)) {
336 folder_operation_status |= FolderOperationResult::CREATE_SRC_FAILED;
337 return; 275 return;
338 } 276 }
339 277
340 // Create temporary icon files for shortcuts in the "Most Visited" category. 278 // Create temporary icon files for shortcuts in the "Most Visited" category.
341 CreateIconFiles(icon_dir, local_most_visited_pages); 279 CreateIconFiles(icon_dir, local_most_visited_pages);
342 280
343 // Create temporary icon files for shortcuts in the "Recently Closed" 281 // Create temporary icon files for shortcuts in the "Recently Closed"
344 // category. 282 // category.
345 CreateIconFiles(icon_dir, local_recently_closed_pages); 283 CreateIconFiles(icon_dir, local_recently_closed_pages);
346 284
347 // We finished collecting all resources needed for updating an application 285 // We finished collecting all resources needed for updating an application
348 // JumpList. So, create a new JumpList and replace the current JumpList 286 // JumpList. So, create a new JumpList and replace the current JumpList
349 // with it. 287 // with it.
350 UpdateJumpList(app_id.c_str(), local_most_visited_pages, 288 UpdateJumpList(app_id.c_str(), local_most_visited_pages,
351 local_recently_closed_pages, incognito_availability); 289 local_recently_closed_pages, incognito_availability);
290
291 // Post a background task to delete JumpListIconsOld folder if it exists and
292 // log the delete results to UMA.
293 base::FilePath icon_dir_old = icon_dir.DirName().Append(
294 icon_dir.BaseName().value() + FILE_PATH_LITERAL("Old"));
295
296 if (base::DirectoryExists(icon_dir_old)) {
297 sequenced_task_runner->PostTask(
298 FROM_HERE, base::Bind(&DeleteDirectoryAndLogResults, icon_dir_old,
299 kFileDeleteLimit));
300 }
352 } 301 }
353 302
354 } // namespace 303 } // namespace
355 304
356 JumpList::JumpListData::JumpListData() {} 305 JumpList::JumpListData::JumpListData() {}
357 306
358 JumpList::JumpListData::~JumpListData() {} 307 JumpList::JumpListData::~JumpListData() {}
359 308
360 JumpList::JumpList(Profile* profile) 309 JumpList::JumpList(Profile* profile)
361 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( 310 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread(
362 content::BrowserThread::UI)), 311 content::BrowserThread::UI)),
363 profile_(profile), 312 profile_(profile),
364 jumplist_data_(new base::RefCountedData<JumpListData>), 313 jumplist_data_(new base::RefCountedData<JumpListData>),
365 task_id_(base::CancelableTaskTracker::kBadTaskId), 314 task_id_(base::CancelableTaskTracker::kBadTaskId),
315 sequenced_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
316 base::TaskTraits()
317 .WithPriority(base::TaskPriority::BACKGROUND)
318 .WithShutdownBehavior(
319 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
320 .MayBlock())),
366 weak_ptr_factory_(this) { 321 weak_ptr_factory_(this) {
367 DCHECK(Enabled()); 322 DCHECK(Enabled());
368 // To update JumpList when a tab is added or removed, we add this object to 323 // To update JumpList when a tab is added or removed, we add this object to
369 // the observer list of the TabRestoreService class. 324 // the observer list of the TabRestoreService class.
370 // When we add this object to the observer list, we save the pointer to this 325 // When we add this object to the observer list, we save the pointer to this
371 // TabRestoreService object. This pointer is used when we remove this object 326 // TabRestoreService object. This pointer is used when we remove this object
372 // from the observer list. 327 // from the observer list.
373 sessions::TabRestoreService* tab_restore_service = 328 sessions::TabRestoreService* tab_restore_service =
374 TabRestoreServiceFactory::GetForProfile(profile_); 329 TabRestoreServiceFactory::GetForProfile(profile_);
375 if (!tab_restore_service) 330 if (!tab_restore_service)
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 DCHECK(CalledOnValidThread()); 609 DCHECK(CalledOnValidThread());
655 610
656 TRACE_EVENT0("browser", "JumpList::DeferredRunUpdate"); 611 TRACE_EVENT0("browser", "JumpList::DeferredRunUpdate");
657 // Check if incognito windows (or normal windows) are disabled by policy. 612 // Check if incognito windows (or normal windows) are disabled by policy.
658 IncognitoModePrefs::Availability incognito_availability = 613 IncognitoModePrefs::Availability incognito_availability =
659 profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) 614 profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs())
660 : IncognitoModePrefs::ENABLED; 615 : IncognitoModePrefs::ENABLED;
661 616
662 BrowserThread::PostTask( 617 BrowserThread::PostTask(
663 BrowserThread::FILE, FROM_HERE, 618 BrowserThread::FILE, FROM_HERE,
664 base::Bind(&RunUpdateOnFileThread, 619 base::Bind(&RunUpdateOnFileThread, incognito_availability, app_id_,
665 incognito_availability, 620 icon_dir_, base::RetainedRef(jumplist_data_),
666 app_id_, 621 sequenced_task_runner_));
667 icon_dir_,
668 base::RetainedRef(jumplist_data_)));
669 } 622 }
670 623
671 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { 624 void JumpList::TopSitesLoaded(history::TopSites* top_sites) {
672 } 625 }
673 626
674 void JumpList::TopSitesChanged(history::TopSites* top_sites, 627 void JumpList::TopSitesChanged(history::TopSites* top_sites,
675 ChangeReason change_reason) { 628 ChangeReason change_reason) {
676 top_sites->GetMostVisitedURLs( 629 top_sites->GetMostVisitedURLs(
677 base::Bind(&JumpList::OnMostVisitedURLsAvailable, 630 base::Bind(&JumpList::OnMostVisitedURLsAvailable,
678 weak_ptr_factory_.GetWeakPtr()), 631 weak_ptr_factory_.GetWeakPtr()),
679 false); 632 false);
680 } 633 }
OLDNEW
« no previous file with comments | « chrome/browser/win/jumplist.h ('k') | chrome/browser/win/jumplist_file_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698