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 <windows.h> | |
8 | |
9 #include "base/files/file_enumerator.h" | |
10 #include "base/metrics/histogram_macros.h" | |
11 #include "base/threading/thread_restrictions.h" | |
12 | |
13 bool DeleteFiles(const base::FilePath& path, | |
14 const base::FilePath::StringType& pattern, | |
15 bool has_upper_limit, | |
16 FolderDeleteResult* delete_status) { | |
17 base::FileEnumerator traversal( | |
18 path, false, | |
19 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES, pattern); | |
20 int succees_count = 0; | |
21 int failure_count = 0; | |
22 for (base::FilePath current = traversal.Next(); !current.empty(); | |
23 current = traversal.Next()) { | |
24 // Try to clear the read-only bit if we find it. | |
25 base::FileEnumerator::FileInfo info = traversal.GetInfo(); | |
26 if (info.find_data().dwFileAttributes & FILE_ATTRIBUTE_READONLY) { | |
27 SetFileAttributes( | |
28 current.value().c_str(), | |
29 info.find_data().dwFileAttributes & ~FILE_ATTRIBUTE_READONLY); | |
30 } | |
31 | |
32 if (info.IsDirectory()) { | |
33 // JumpListIcons{,Old} directories shouldn't have sub-directories. | |
34 // If it does for unknown reasons, don't try to delete it. Instead, | |
35 // increment failure count if |has_upper_limit| is true and record this | |
36 // information in |delete_status|. | |
37 *delete_status = FAIL_SUBDIRECTORY_EXISTS; | |
38 if (!has_upper_limit) | |
39 return false; | |
40 failure_count++; | |
41 } else if (!::DeleteFile(current.value().c_str())) { | |
42 // If there is no upper limit, return false intermediately. Otherwise, | |
43 // increment |failure_count| until it hits the upper limit. | |
44 if (!has_upper_limit) | |
45 return false; | |
46 failure_count++; | |
47 } else { | |
48 succees_count++; | |
49 } | |
50 // If it successfully deletes |kMaxIconFilesDeletedPerUpdate| files without | |
grt (UTC plus 2)
2017/03/22 12:07:21
i think this is more clear with both limit checks
chengx
2017/03/22 21:16:36
Agreed and updated accordingly.
| |
51 // any failures, return true. If some files fail to be delete, record this | |
52 // information in |delete_status| and returns false. | |
53 if (has_upper_limit && succees_count >= kMaxIconFilesDeletedPerUpdate) { | |
54 if (failure_count > 0) { | |
55 *delete_status = FAIL_DELETE_MAX_FILE_PERFECTLY; | |
grt (UTC plus 2)
2017/03/22 12:07:22
this reads to me like "we failed because we perfec
chengx
2017/03/22 21:16:36
Done.
| |
56 } | |
57 return failure_count == 0; | |
58 } | |
59 // Return false when failing to delete |kMaxIconFilesDeletedPerUpdate| files | |
60 // comes before successfully deleting |kMaxIconFilesDeletedPerUpdate| files. | |
61 if (has_upper_limit && failure_count >= kMaxIconFilesDeletedPerUpdate) { | |
62 *delete_status = FAIL_DELETE_MAX_FILES_ANYWAY; | |
grt (UTC plus 2)
2017/03/22 12:07:21
FAIL_MAX_DELETE_FAILURES -> "we failed because we
chengx
2017/03/22 21:16:36
Sounds good.
| |
63 return false; | |
64 } | |
65 } | |
66 return true; | |
67 } | |
68 | |
69 bool DeleteDirectoryContent(const base::FilePath& path, | |
grt (UTC plus 2)
2017/03/22 12:07:21
return FolderDeleteResult rather than bool (which
chengx
2017/03/22 21:16:36
Done.
| |
70 bool has_upper_limit, | |
71 FolderDeleteResult* delete_status) { | |
72 base::ThreadRestrictions::AssertIOAllowed(); | |
grt (UTC plus 2)
2017/03/22 12:07:21
this function seems to assume that |delete_status|
chengx
2017/03/22 21:16:36
Changed to explicitly set it.
| |
73 | |
74 if (path.empty()) | |
75 return true; | |
76 | |
77 // For JumpListIcons{,Old} directories, since their names are shorter than | |
78 // MAX_PATH, hitting the code block below is unexpected. | |
79 if (path.value().length() >= MAX_PATH) { | |
80 *delete_status = FAIL_INVALID_FILE_PATH; | |
81 return false; | |
82 } | |
83 | |
84 DWORD attr = GetFileAttributes(path.value().c_str()); | |
85 // We're done if we can't find the path. | |
86 if (attr == INVALID_FILE_ATTRIBUTES) | |
87 return true; | |
88 // We may need to clear the read-only bit. | |
89 if ((attr & FILE_ATTRIBUTE_READONLY) && | |
90 !SetFileAttributes(path.value().c_str(), | |
91 attr & ~FILE_ATTRIBUTE_READONLY)) { | |
92 *delete_status = FAIL_READ_ONLY_DIRECTORY; | |
93 return false; | |
94 } | |
95 | |
96 // If |path| is a file, simply delete it. | |
97 // Since JumpListIcons{,Old} are directories, hitting the code block below is | |
98 // unexpected. | |
99 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { | |
100 bool delete_result = !!::DeleteFile(path.value().c_str()); | |
101 if (!delete_result) | |
102 *delete_status = FAIL_DELETE_SINGLE_FILE; | |
103 return delete_result; | |
104 } | |
105 | |
106 // If |path| is a directory, delete all its content but save the raw | |
107 // directory. | |
108 return DeleteFiles(path, L"*", has_upper_limit, delete_status); | |
109 } | |
110 | |
111 void DeleteDirectory(const base::FilePath& path, | |
grt (UTC plus 2)
2017/03/22 12:07:21
return FolderDeleteResult rather than void w/ out
chengx
2017/03/22 21:16:36
Done.
| |
112 bool has_upper_limit, | |
113 FolderDeleteResult* delete_status) { | |
114 base::ThreadRestrictions::AssertIOAllowed(); | |
115 | |
116 if (path.empty()) | |
117 return; | |
118 | |
119 // For JumpListIcons{,Old} directories, since their names are shorter than | |
120 // MAX_PATH, hitting the code block below is unexpected. | |
121 if (path.value().length() >= MAX_PATH) { | |
122 *delete_status = FAIL_INVALID_FILE_PATH; | |
123 return; | |
124 } | |
125 | |
126 DWORD attr = GetFileAttributes(path.value().c_str()); | |
127 // We're done if we can't find the path. | |
128 if (attr == INVALID_FILE_ATTRIBUTES) | |
129 return; | |
130 // We may need to clear the read-only bit. | |
131 if ((attr & FILE_ATTRIBUTE_READONLY) && | |
132 !SetFileAttributes(path.value().c_str(), | |
133 attr & ~FILE_ATTRIBUTE_READONLY)) { | |
134 *delete_status = FAIL_READ_ONLY_DIRECTORY; | |
135 return; | |
136 } | |
137 // If |path| is a file, delete it. | |
138 // Since JumpListIcons{,Old} are directories, hitting the code block below is | |
139 // unexpected. | |
140 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { | |
141 ::DeleteFile(path.value().c_str()); | |
142 *delete_status = FAIL_DELETE_SINGLE_FILE; | |
143 return; | |
144 } | |
145 // If |path| is a directory, delete its contents and if it succeeds, remove | |
146 // the raw directory. | |
147 if (DeleteFiles(path, L"*", has_upper_limit, delete_status)) | |
148 ::RemoveDirectory(path.value().c_str()); | |
149 return; | |
150 } | |
151 | |
152 void DeleteDirectoryAndLogResults(const base::FilePath& path, | |
153 bool has_upper_limit) { | |
154 FolderDeleteResult delete_status = SUCCEED; | |
155 DeleteDirectory(path, has_upper_limit, &delete_status); | |
156 UMA_HISTOGRAM_ENUMERATION("WinJumplist.DeleteStatusJumpListIconsOld", | |
157 static_cast<int>(delete_status), END); | |
grt (UTC plus 2)
2017/03/22 12:07:21
since FolderDeleteResult is an old-school enum and
chengx
2017/03/22 21:16:36
You are right. It is not needed.
| |
158 } | |
OLD | NEW |