OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/win/jumplist_file_util.h" | |
6 | |
7 #include <Shlwapi.h> | |
8 #include <windows.h> | |
9 | |
10 #include "base/files/file_enumerator.h" | |
11 #include "base/metrics/histogram_macros.h" | |
12 #include "base/threading/thread_restrictions.h" | |
13 | |
14 FolderDeleteResult DeleteFiles(const base::FilePath& path, | |
15 const base::FilePath::StringType& pattern, | |
16 const int max_file_deleted) { | |
17 int success_count = 0; | |
18 int failure_count = 0; | |
19 FolderDeleteResult delete_status = SUCCEED; | |
20 | |
21 base::FileEnumerator traversal( | |
22 path, false, | |
23 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES, pattern); | |
24 for (base::FilePath current = traversal.Next(); !current.empty(); | |
25 current = traversal.Next()) { | |
26 // Try to clear the read-only bit if we find it. | |
27 base::FileEnumerator::FileInfo info = traversal.GetInfo(); | |
28 if (info.find_data().dwFileAttributes & FILE_ATTRIBUTE_READONLY) { | |
29 SetFileAttributes( | |
30 current.value().c_str(), | |
31 info.find_data().dwFileAttributes & ~FILE_ATTRIBUTE_READONLY); | |
32 } | |
33 | |
34 if (info.IsDirectory()) { | |
35 // JumpListIcons{,Old} directories shouldn't have sub-directories. | |
36 // If any of them does for unknown reasons, don't delete them. Instead, | |
37 // increment the failure count and record this information. | |
38 delete_status = FAIL_SUBDIRECTORY_EXISTS; | |
39 failure_count++; | |
40 } else if (!::DeleteFile(current.value().c_str())) { | |
41 failure_count++; | |
42 } else { | |
43 success_count++; | |
44 } | |
45 // If it deletes max_file_deleted files with any attempt failures, record | |
46 // this information in |delete_status|. | |
47 if (success_count >= max_file_deleted) { | |
48 // The desired max number of files have been deleted. | |
49 if (failure_count) | |
grt (UTC plus 2)
2017/03/23 11:24:58
return failure_count ? FAIL_DELETE_MAX_FILES_WITH_
chengx
2017/03/23 21:16:11
Done.
| |
50 delete_status = FAIL_DELETE_MAX_FILES_WITH_ERRORS; | |
51 return delete_status; | |
52 } | |
53 if (failure_count >= max_file_deleted) { | |
54 // The desired max number of failures have been hit. | |
55 return FAIL_MAX_DELETE_FAILURES; | |
56 } | |
57 } | |
58 return delete_status; | |
59 } | |
60 | |
61 FolderDeleteResult DeleteDirectoryContent(const base::FilePath& path, | |
62 const int max_file_deleted) { | |
63 base::ThreadRestrictions::AssertIOAllowed(); | |
64 | |
65 if (path.empty()) | |
66 return SUCCEED; | |
67 | |
68 // For JumpListIcons{,Old} directories, since their names are shorter than | |
69 // MAX_PATH, hitting the code in the if-block below is unexpected. | |
70 if (path.value().length() >= MAX_PATH) { | |
grt (UTC plus 2)
2017/03/23 11:24:57
nit: omit braces
chengx
2017/03/23 21:16:12
Done.
| |
71 return FAIL_INVALID_FILE_PATH; | |
72 } | |
73 | |
74 DWORD attr = GetFileAttributes(path.value().c_str()); | |
75 // We're done if we can't find the path. | |
76 if (attr == INVALID_FILE_ATTRIBUTES) | |
77 return SUCCEED; | |
78 // Try to clear the read-only bit if we find it. | |
79 if ((attr & FILE_ATTRIBUTE_READONLY) && | |
80 !SetFileAttributes(path.value().c_str(), | |
81 attr & ~FILE_ATTRIBUTE_READONLY)) { | |
82 return FAIL_READ_ONLY_DIRECTORY; | |
83 } | |
84 | |
85 // If |path| is a file, simply delete it. However, since JumpListIcons{,Old} | |
86 // are directories, hitting the code inside the if-block below is unexpected. | |
87 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { | |
88 ::DeleteFile(path.value().c_str()); | |
89 return FAIL_DELETE_SINGLE_FILE; | |
90 } | |
91 | |
92 // If |path| is a directory, delete at most |max_file_deleted| files in it. | |
93 return DeleteFiles(path, L"*", max_file_deleted); | |
94 } | |
95 | |
96 FolderDeleteResult DeleteDirectory(const base::FilePath& path, | |
97 const int max_file_deleted) { | |
98 base::ThreadRestrictions::AssertIOAllowed(); | |
99 // Delete at most |max_file_deleted| files in |path|. | |
100 FolderDeleteResult delete_status = | |
101 DeleteDirectoryContent(path, max_file_deleted); | |
102 // Since DeleteDirectoryContent() can only delete at most |max_file_deleted| | |
103 // files, its return value cannot indicate if |path| is empty or not. | |
104 // Instead, use PathIsDirectoryEmpty to check if |path| is empty and remove it | |
105 // if it is. | |
106 if (::PathIsDirectoryEmpty(path.value().c_str()) && | |
107 !::RemoveDirectory(path.value().c_str())) | |
108 delete_status = FAIL_REMOVE_RAW_DIRECTORY; | |
grt (UTC plus 2)
2017/03/23 11:24:58
nit: braces around this due to multi-line conditio
chengx
2017/03/23 21:16:12
Done.
| |
109 return delete_status; | |
110 } | |
111 | |
112 void DeleteDirectoryAndLogResults(const base::FilePath& path, | |
113 const int max_file_deleted) { | |
114 FolderDeleteResult delete_status = DeleteDirectory(path, max_file_deleted); | |
115 UMA_HISTOGRAM_ENUMERATION("WinJumplist.DeleteStatusJumpListIconsOld", | |
116 delete_status, END); | |
117 } | |
OLD | NEW |