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

Side by Side Diff: chrome/browser/media_galleries/media_folder_finder.cc

Issue 173853007: Media Galleries: Prune uninteresting folders when scanning. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: add tests, fix bugs Created 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/media_galleries/media_folder_finder.h" 5 #include "chrome/browser/media_galleries/media_folder_finder.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/sequence_checker.h" 12 #include "base/sequence_checker.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/sequenced_worker_pool.h"
17 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
17 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 18 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
18 #include "components/storage_monitor/storage_monitor.h" 19 #include "components/storage_monitor/storage_monitor.h"
19 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
20 21
21 #if defined(OS_CHROMEOS) 22 #if defined(OS_CHROMEOS)
22 #include "chrome/common/chrome_paths.h" 23 #include "chrome/common/chrome_paths.h"
23 #include "chromeos/dbus/cros_disks_client.h" 24 #include "chromeos/dbus/cros_disks_client.h"
24 #endif 25 #endif
25 26
26 typedef base::Callback<void(const std::vector<base::FilePath>& /*roots*/)> 27 typedef base::Callback<void(const std::vector<base::FilePath>& /*roots*/)>
27 DefaultScanRootsCallback; 28 DefaultScanRootsCallback;
28 using content::BrowserThread; 29 using content::BrowserThread;
29 30
30 namespace { 31 namespace {
31 32
32 const int64 kMinimumImageSize = 200 * 1024; // 200 KB 33 const int64 kMinimumImageSize = 200 * 1024; // 200 KB
33 const int64 kMinimumAudioSize = 500 * 1024; // 500 KB 34 const int64 kMinimumAudioSize = 500 * 1024; // 500 KB
34 const int64 kMinimumVideoSize = 1024 * 1024; // 1 MB 35 const int64 kMinimumVideoSize = 1024 * 1024; // 1 MB
35 36
37 const int kPrunedPaths[] = {
38 base::DIR_CACHE,
39 base::DIR_TEMP,
40 #if defined(OS_WIN)
41 base::DIR_IE_INTERNET_CACHE,
42 base::DIR_PROGRAM_FILES,
43 base::DIR_PROGRAM_FILESX86,
44 base::DIR_WINDOWS,
45 #endif
46 #if defined(OS_MACOSX) && !defined(OS_IOS)
47 DIR_USER_LIBRARY,
48 #endif
49 };
50
36 bool IsValidScanPath(const base::FilePath& path) { 51 bool IsValidScanPath(const base::FilePath& path) {
37 return !path.empty() && path.IsAbsolute(); 52 return !path.empty() && path.IsAbsolute();
38 } 53 }
39 54
40 void CountScanResult(MediaGalleryScanFileType type, 55 void CountScanResult(MediaGalleryScanFileType type,
41 MediaGalleryScanResult* scan_result) { 56 MediaGalleryScanResult* scan_result) {
42 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE) 57 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE)
43 scan_result->image_count += 1; 58 scan_result->image_count += 1;
44 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO) 59 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO)
45 scan_result->audio_count += 1; 60 scan_result->audio_count += 1;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 } // namespace 154 } // namespace
140 155
141 MediaFolderFinder::WorkerReply::WorkerReply() {} 156 MediaFolderFinder::WorkerReply::WorkerReply() {}
142 157
143 MediaFolderFinder::WorkerReply::~WorkerReply() {} 158 MediaFolderFinder::WorkerReply::~WorkerReply() {}
144 159
145 // The Worker is created on the UI thread, but does all its work on a blocking 160 // The Worker is created on the UI thread, but does all its work on a blocking
146 // SequencedTaskRunner. 161 // SequencedTaskRunner.
147 class MediaFolderFinder::Worker { 162 class MediaFolderFinder::Worker {
148 public: 163 public:
149 Worker(); 164 explicit Worker(const std::vector<base::FilePath>& graylisted_folders);
150 ~Worker(); 165 ~Worker();
151 166
152 // Scans |path| and return the results. 167 // Scans |path| and return the results.
153 WorkerReply ScanFolder(const base::FilePath& path); 168 WorkerReply ScanFolder(const base::FilePath& path);
154 169
155 private: 170 private:
171 const std::vector<base::FilePath> graylisted_folders_;
172 std::vector<base::FilePath> pruned_folders_;
173
156 scoped_ptr<MediaPathFilter> filter_; 174 scoped_ptr<MediaPathFilter> filter_;
157 175
158 base::SequenceChecker sequence_checker_; 176 base::SequenceChecker sequence_checker_;
159 177
160 DISALLOW_COPY_AND_ASSIGN(Worker); 178 DISALLOW_COPY_AND_ASSIGN(Worker);
161 }; 179 };
162 180
163 MediaFolderFinder::Worker::Worker() { 181 MediaFolderFinder::Worker::Worker(
182 const std::vector<base::FilePath>& graylisted_folders)
183 : graylisted_folders_(graylisted_folders),
184 filter_(new MediaPathFilter) {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
165 filter_.reset(new MediaPathFilter); 186
187 for (size_t i = 0; i < arraysize(kPrunedPaths); ++i) {
188 base::FilePath path;
189 if (PathService::Get(kPrunedPaths[i], &path))
190 pruned_folders_.push_back(path);
191 }
192
166 sequence_checker_.DetachFromSequence(); 193 sequence_checker_.DetachFromSequence();
167 } 194 }
168 195
169 MediaFolderFinder::Worker::~Worker() { 196 MediaFolderFinder::Worker::~Worker() {
170 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 197 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
171 } 198 }
172 199
173 MediaFolderFinder::WorkerReply MediaFolderFinder::Worker::ScanFolder( 200 MediaFolderFinder::WorkerReply MediaFolderFinder::Worker::ScanFolder(
174 const base::FilePath& path) { 201 const base::FilePath& path) {
175 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 202 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
176 CHECK(IsValidScanPath(path)); 203 CHECK(IsValidScanPath(path));
177 204
178 WorkerReply reply; 205 WorkerReply reply;
179 bool folder_meets_size_requirement = false; 206 bool folder_meets_size_requirement = false;
207 bool is_graylisted_folder = false;
208 for (size_t i = 0; i < graylisted_folders_.size(); ++i) {
209 if (path == graylisted_folders_[i] ||
210 path.IsParent(graylisted_folders_[i])) {
211 is_graylisted_folder = true;
212 break;
213 }
214 }
215
180 base::FileEnumerator enumerator( 216 base::FileEnumerator enumerator(
181 path, 217 path,
182 false, /* recursive? */ 218 false, /* recursive? */
183 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES 219 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES
184 #if defined(OS_POSIX) 220 #if defined(OS_POSIX)
185 | base::FileEnumerator::SHOW_SYM_LINKS // show symlinks, not follow. 221 | base::FileEnumerator::SHOW_SYM_LINKS // show symlinks, not follow.
186 #endif 222 #endif
187 ); 223 ); // NOLINT
188 while (!enumerator.Next().empty()) { 224 while (!enumerator.Next().empty()) {
189 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 225 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
190 base::FilePath full_path = path.Append(file_info.GetName()); 226 base::FilePath full_path = path.Append(file_info.GetName());
191 if (MediaPathFilter::ShouldSkip(full_path)) 227 if (MediaPathFilter::ShouldSkip(full_path))
192 continue; 228 continue;
193 229
230 // Enumerating a directory.
194 if (file_info.IsDirectory()) { 231 if (file_info.IsDirectory()) {
195 reply.new_folders.push_back(full_path); 232 bool is_pruned_folder = false;
233 for (size_t i = 0; i < pruned_folders_.size(); ++i) {
234 if (full_path == pruned_folders_[i]) {
235 is_pruned_folder = true;
236 break;
237 }
238 }
239
240 if (!is_pruned_folder)
241 reply.new_folders.push_back(full_path);
196 continue; 242 continue;
197 } 243 }
244
245 // Enumerating a file.
246 //
247 // Do not include scan results for graylisted folders.
248 if (is_graylisted_folder)
249 continue;
250
198 MediaGalleryScanFileType type = filter_->GetType(full_path); 251 MediaGalleryScanFileType type = filter_->GetType(full_path);
199 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN) 252 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN)
200 continue; 253 continue;
201 254
202 CountScanResult(type, &reply.scan_result); 255 CountScanResult(type, &reply.scan_result);
203 if (!folder_meets_size_requirement) { 256 if (!folder_meets_size_requirement) {
204 folder_meets_size_requirement = 257 folder_meets_size_requirement =
205 FileMeetsSizeRequirement(type, file_info.GetSize()); 258 FileMeetsSizeRequirement(type, file_info.GetSize());
206 } 259 }
207 } 260 }
208 // Make sure there is at least 1 file above a size threshold. 261 // Make sure there is at least 1 file above a size threshold.
209 if (!folder_meets_size_requirement) 262 if (!folder_meets_size_requirement)
210 reply.scan_result = MediaGalleryScanResult(); 263 reply.scan_result = MediaGalleryScanResult();
211 return reply; 264 return reply;
212 } 265 }
213 266
214 MediaFolderFinder::MediaFolderFinder( 267 MediaFolderFinder::MediaFolderFinder(
215 const MediaFolderFinderResultsCallback& callback) 268 const MediaFolderFinderResultsCallback& callback)
216 : results_callback_(callback), 269 : results_callback_(callback),
270 graylisted_folders_(
271 extensions::file_system_api::GetGrayListedDirectories()),
217 scan_state_(SCAN_STATE_NOT_STARTED), 272 scan_state_(SCAN_STATE_NOT_STARTED),
218 worker_(new Worker()), 273 worker_(new Worker(graylisted_folders_)),
219 has_roots_for_testing_(false), 274 has_roots_for_testing_(false),
220 weak_factory_(this) { 275 weak_factory_(this) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
222 277
223 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 278 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
224 worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 279 worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
225 } 280 }
226 281
227 MediaFolderFinder::~MediaFolderFinder() { 282 MediaFolderFinder::~MediaFolderFinder() {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 13 matching lines...) Expand all
242 if (scan_state_ != SCAN_STATE_NOT_STARTED) 297 if (scan_state_ != SCAN_STATE_NOT_STARTED)
243 return; 298 return;
244 299
245 scan_state_ = SCAN_STATE_STARTED; 300 scan_state_ = SCAN_STATE_STARTED;
246 GetDefaultScanRoots( 301 GetDefaultScanRoots(
247 base::Bind(&MediaFolderFinder::OnInitialized, weak_factory_.GetWeakPtr()), 302 base::Bind(&MediaFolderFinder::OnInitialized, weak_factory_.GetWeakPtr()),
248 has_roots_for_testing_, 303 has_roots_for_testing_,
249 roots_for_testing_); 304 roots_for_testing_);
250 } 305 }
251 306
307 const std::vector<base::FilePath>&
308 MediaFolderFinder::graylisted_folders() const {
309 return graylisted_folders_;
310 }
311
252 void MediaFolderFinder::SetRootsForTesting( 312 void MediaFolderFinder::SetRootsForTesting(
253 const std::vector<base::FilePath>& roots) { 313 const std::vector<base::FilePath>& roots) {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255 DCHECK_EQ(SCAN_STATE_NOT_STARTED, scan_state_); 315 DCHECK_EQ(SCAN_STATE_NOT_STARTED, scan_state_);
256 316
257 has_roots_for_testing_ = true; 317 has_roots_for_testing_ = true;
258 roots_for_testing_ = roots; 318 roots_for_testing_ = roots;
259 } 319 }
260 320
261 void MediaFolderFinder::OnInitialized( 321 void MediaFolderFinder::OnInitialized(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 389
330 if (!IsEmptyScanResult(reply.scan_result)) 390 if (!IsEmptyScanResult(reply.scan_result))
331 results_[path] = reply.scan_result; 391 results_[path] = reply.scan_result;
332 392
333 // Push new folders to the |folders_to_scan_| in reverse order. 393 // Push new folders to the |folders_to_scan_| in reverse order.
334 std::copy(reply.new_folders.rbegin(), reply.new_folders.rend(), 394 std::copy(reply.new_folders.rbegin(), reply.new_folders.rend(),
335 std::back_inserter(folders_to_scan_)); 395 std::back_inserter(folders_to_scan_));
336 396
337 ScanFolder(); 397 ScanFolder();
338 } 398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698