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

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: Created 6 years, 10 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,
vandebo (ex-Chrome) 2014/02/20 23:00:23 It's not clear that we want to prune the temp dir.
Lei Zhang 2014/02/20 23:04:52 On Windows, it's buried and not easily accessible
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.
vandebo (ex-Chrome) 2014/02/20 23:00:23 nit: remove *
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.
vandebo (ex-Chrome) 2014/02/20 23:00:23 ditto
246 // Do not include scan results for graylisted folders.
247 if (is_graylisted_folder)
248 continue;
249
198 MediaGalleryScanFileType type = filter_->GetType(full_path); 250 MediaGalleryScanFileType type = filter_->GetType(full_path);
199 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN) 251 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN)
200 continue; 252 continue;
201 253
202 CountScanResult(type, &reply.scan_result); 254 CountScanResult(type, &reply.scan_result);
203 if (!folder_meets_size_requirement) { 255 if (!folder_meets_size_requirement) {
204 folder_meets_size_requirement = 256 folder_meets_size_requirement =
205 FileMeetsSizeRequirement(type, file_info.GetSize()); 257 FileMeetsSizeRequirement(type, file_info.GetSize());
206 } 258 }
207 } 259 }
208 // Make sure there is at least 1 file above a size threshold. 260 // Make sure there is at least 1 file above a size threshold.
209 if (!folder_meets_size_requirement) 261 if (!folder_meets_size_requirement)
210 reply.scan_result = MediaGalleryScanResult(); 262 reply.scan_result = MediaGalleryScanResult();
211 return reply; 263 return reply;
212 } 264 }
213 265
214 MediaFolderFinder::MediaFolderFinder( 266 MediaFolderFinder::MediaFolderFinder(
215 const MediaFolderFinderResultsCallback& callback) 267 const MediaFolderFinderResultsCallback& callback)
216 : results_callback_(callback), 268 : results_callback_(callback),
269 graylisted_folders_(
270 extensions::file_system_api::GetGrayListedDirectories()),
217 scan_state_(SCAN_STATE_NOT_STARTED), 271 scan_state_(SCAN_STATE_NOT_STARTED),
218 worker_(new Worker()), 272 worker_(new Worker(graylisted_folders_)),
219 has_roots_for_testing_(false), 273 has_roots_for_testing_(false),
220 weak_factory_(this) { 274 weak_factory_(this) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
222 276
223 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 277 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
224 worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 278 worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
225 } 279 }
226 280
227 MediaFolderFinder::~MediaFolderFinder() { 281 MediaFolderFinder::~MediaFolderFinder() {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 283
230 worker_task_runner_->DeleteSoon(FROM_HERE, worker_); 284 worker_task_runner_->DeleteSoon(FROM_HERE, worker_);
231 285
232 if (scan_state_ == SCAN_STATE_FINISHED) 286 if (scan_state_ == SCAN_STATE_FINISHED)
233 return; 287 return;
234 288
235 MediaFolderFinderResults empty_results; 289 MediaFolderFinderResults empty_results;
236 results_callback_.Run(false /* success? */, empty_results); 290 std::vector<base::FilePath> empty_sensitive_locations;
291 results_callback_.Run(false /* success? */,
292 empty_results,
293 empty_sensitive_locations);
237 } 294 }
238 295
239 void MediaFolderFinder::StartScan() { 296 void MediaFolderFinder::StartScan() {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241 298
242 if (scan_state_ != SCAN_STATE_NOT_STARTED) 299 if (scan_state_ != SCAN_STATE_NOT_STARTED)
243 return; 300 return;
244 301
245 scan_state_ = SCAN_STATE_STARTED; 302 scan_state_ = SCAN_STATE_STARTED;
246 GetDefaultScanRoots( 303 GetDefaultScanRoots(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 std::back_inserter(folders_to_scan_)); 354 std::back_inserter(folders_to_scan_));
298 ScanFolder(); 355 ScanFolder();
299 } 356 }
300 357
301 void MediaFolderFinder::ScanFolder() { 358 void MediaFolderFinder::ScanFolder() {
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
303 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 360 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_);
304 361
305 if (folders_to_scan_.empty()) { 362 if (folders_to_scan_.empty()) {
306 scan_state_ = SCAN_STATE_FINISHED; 363 scan_state_ = SCAN_STATE_FINISHED;
307 results_callback_.Run(true /* success? */, results_); 364 results_callback_.Run(true /* success? */, results_, graylisted_folders_);
308 return; 365 return;
309 } 366 }
310 367
311 base::FilePath folder_to_scan = folders_to_scan_.back(); 368 base::FilePath folder_to_scan = folders_to_scan_.back();
312 folders_to_scan_.pop_back(); 369 folders_to_scan_.pop_back();
313 base::PostTaskAndReplyWithResult( 370 base::PostTaskAndReplyWithResult(
314 worker_task_runner_, FROM_HERE, 371 worker_task_runner_, FROM_HERE,
315 base::Bind(&Worker::ScanFolder, 372 base::Bind(&Worker::ScanFolder,
316 base::Unretained(worker_), 373 base::Unretained(worker_),
317 folder_to_scan), 374 folder_to_scan),
(...skipping 11 matching lines...) Expand all
329 386
330 if (!IsEmptyScanResult(reply.scan_result)) 387 if (!IsEmptyScanResult(reply.scan_result))
331 results_[path] = reply.scan_result; 388 results_[path] = reply.scan_result;
332 389
333 // Push new folders to the |folders_to_scan_| in reverse order. 390 // Push new folders to the |folders_to_scan_| in reverse order.
334 std::copy(reply.new_folders.rbegin(), reply.new_folders.rend(), 391 std::copy(reply.new_folders.rbegin(), reply.new_folders.rend(),
335 std::back_inserter(folders_to_scan_)); 392 std::back_inserter(folders_to_scan_));
336 393
337 ScanFolder(); 394 ScanFolder();
338 } 395 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698