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

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

Issue 166353002: Media Galleries: Refactor media scan worker function into a worker class. (Closed) Base URL: svn://svn.chromium.org/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/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
14 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
15 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
16 #include "chrome/browser/storage_monitor/storage_monitor.h" 17 #include "chrome/browser/storage_monitor/storage_monitor.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 19
19 #if defined(OS_CHROMEOS) 20 #if defined(OS_CHROMEOS)
20 #include "chrome/common/chrome_paths.h" 21 #include "chrome/common/chrome_paths.h"
21 #include "chromeos/dbus/cros_disks_client.h" 22 #include "chromeos/dbus/cros_disks_client.h"
22 #endif 23 #endif
23 24
24 typedef base::Callback<void(const std::vector<base::FilePath>& /*roots*/)> 25 typedef base::Callback<void(const std::vector<base::FilePath>& /*roots*/)>
25 DefaultScanRootsCallback; 26 DefaultScanRootsCallback;
26 using content::BrowserThread; 27 using content::BrowserThread;
27 28
28 namespace { 29 namespace {
29 30
30 const int64 kMinimumImageSize = 200 * 1024; // 200 KB 31 const int64 kMinimumImageSize = 200 * 1024; // 200 KB
31 const int64 kMinimumAudioSize = 500 * 1024; // 500 KB 32 const int64 kMinimumAudioSize = 500 * 1024; // 500 KB
32 const int64 kMinimumVideoSize = 1024 * 1024; // 1 MB 33 const int64 kMinimumVideoSize = 1024 * 1024; // 1 MB
33 34
34 bool IsValidScanPath(const base::FilePath& path) { 35 bool IsValidScanPath(const base::FilePath& path) {
35 return !path.empty() && path.IsAbsolute(); 36 return !path.empty() && path.IsAbsolute();
36 } 37 }
37 38
38 MediaGalleryScanFileType FilterPath(MediaPathFilter* filter, 39 void CountScanResult(MediaGalleryScanFileType type,
39 const base::FilePath& path) { 40 MediaGalleryScanResult* scan_result) {
40 DCHECK(IsValidScanPath(path)); 41 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE)
41 return filter->GetType(path); 42 scan_result->image_count += 1;
43 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO)
44 scan_result->audio_count += 1;
45 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO)
46 scan_result->video_count += 1;
42 } 47 }
43 48
44 bool FileMeetsSizeRequirement(bool requirement_met, 49 bool FileMeetsSizeRequirement(MediaGalleryScanFileType type, int64 size) {
45 MediaGalleryScanFileType type,
46 int64 size) {
47 if (requirement_met)
48 return true;
49
50 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE) 50 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE)
51 if (size >= kMinimumImageSize) 51 if (size >= kMinimumImageSize)
52 return true; 52 return true;
53 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO) 53 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO)
54 if (size >= kMinimumAudioSize) 54 if (size >= kMinimumAudioSize)
55 return true; 55 return true;
56 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO) 56 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO)
57 if (size >= kMinimumVideoSize) 57 if (size >= kMinimumVideoSize)
58 return true; 58 return true;
59 return false; 59 return false;
60 } 60 }
61 61
62 void ScanFolderOnBlockingPool(
63 const base::FilePath& path,
64 const MediaFolderFinder::FilterCallback& filter_callback_,
65 MediaGalleryScanResult* scan_result,
66 std::vector<base::FilePath>* new_folders) {
67 CHECK(IsValidScanPath(path));
68 DCHECK(scan_result);
69 DCHECK(new_folders);
70 DCHECK(IsEmptyScanResult(*scan_result));
71
72 bool folder_meets_size_requirement = false;
73 base::FileEnumerator enumerator(
74 path,
75 false, /* recursive? */
76 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES
77 #if defined(OS_POSIX)
78 | base::FileEnumerator::SHOW_SYM_LINKS // show symlinks, not follow.
79 #endif
80 );
81 while (!enumerator.Next().empty()) {
82 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
83 base::FilePath full_path = path.Append(file_info.GetName());
84 if (MediaPathFilter::ShouldSkip(full_path))
85 continue;
86
87 if (file_info.IsDirectory()) {
88 new_folders->push_back(full_path);
89 continue;
90 }
91 MediaGalleryScanFileType type = filter_callback_.Run(full_path);
92 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN)
93 continue;
94
95 // Make sure there is at least 1 file above a size threshold.
96 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE)
97 scan_result->image_count += 1;
98 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO)
99 scan_result->audio_count += 1;
100 if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO)
101 scan_result->video_count += 1;
102 folder_meets_size_requirement =
103 FileMeetsSizeRequirement(folder_meets_size_requirement,
104 type,
105 file_info.GetSize());
106 }
107 if (!folder_meets_size_requirement) {
108 scan_result->image_count = 0;
109 scan_result->audio_count = 0;
110 scan_result->video_count = 0;
111 }
112 }
113
114 // Return true if |path| should not be considered as the starting point for a 62 // Return true if |path| should not be considered as the starting point for a
115 // media scan. 63 // media scan.
116 bool ShouldIgnoreScanRoot(const base::FilePath& path) { 64 bool ShouldIgnoreScanRoot(const base::FilePath& path) {
117 #if defined(OS_MACOSX) 65 #if defined(OS_MACOSX)
118 // Scanning root is of little value. 66 // Scanning root is of little value.
119 return (path.value() == "/"); 67 return (path.value() == "/");
120 #elif defined(OS_CHROMEOS) 68 #elif defined(OS_CHROMEOS)
121 // Sanity check to make sure mount points are where they should be. 69 // Sanity check to make sure mount points are where they should be.
122 base::FilePath mount_point = 70 base::FilePath mount_point =
123 chromeos::CrosDisksClient::GetRemovableDiskMountPoint(); 71 chromeos::CrosDisksClient::GetRemovableDiskMountPoint();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 } 130 }
183 131
184 base::FilePath platform_root = GetPlatformSpecificDefaultScanRoot(); 132 base::FilePath platform_root = GetPlatformSpecificDefaultScanRoot();
185 if (!platform_root.empty()) 133 if (!platform_root.empty())
186 roots.push_back(platform_root); 134 roots.push_back(platform_root);
187 callback.Run(roots); 135 callback.Run(roots);
188 } 136 }
189 137
190 } // namespace 138 } // namespace
191 139
140 // The Worker is created on the UI thread, but does all its work on a blocking
141 // SequencedTaskRunner.
142 class MediaFolderFinder::Worker {
143 public:
144 Worker();
145 ~Worker();
146
147 // Scans |path| and return the results.
148 WorkerReply ScanFolder(const base::FilePath& path);
149
150 private:
151 scoped_ptr<MediaPathFilter> filter_;
152
153 base::SequenceChecker sequence_checker_;
154
155 DISALLOW_COPY_AND_ASSIGN(Worker);
156 };
157
158 MediaFolderFinder::Worker::Worker() {
159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
160 filter_.reset(new MediaPathFilter);
161 sequence_checker_.DetachFromSequence();
162 }
163
164 MediaFolderFinder::Worker::~Worker() {
165 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
166 }
167
168 MediaFolderFinder::WorkerReply MediaFolderFinder::Worker::ScanFolder(
169 const base::FilePath& path) {
170 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
171 CHECK(IsValidScanPath(path));
172
173 WorkerReply reply;
174 MediaGalleryScanResult& scan_result = reply.first;
175 std::vector<base::FilePath>& new_folders = reply.second;
176 bool folder_meets_size_requirement = false;
177 base::FileEnumerator enumerator(
178 path,
179 false, /* recursive? */
180 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES
181 #if defined(OS_POSIX)
182 | base::FileEnumerator::SHOW_SYM_LINKS // show symlinks, not follow.
183 #endif
184 );
185 while (!enumerator.Next().empty()) {
186 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
187 base::FilePath full_path = path.Append(file_info.GetName());
188 if (MediaPathFilter::ShouldSkip(full_path))
189 continue;
190
191 if (file_info.IsDirectory()) {
192 new_folders.push_back(full_path);
193 continue;
194 }
195 MediaGalleryScanFileType type = filter_->GetType(full_path);
196 if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN)
197 continue;
198
199 CountScanResult(type, &scan_result);
200 if (!folder_meets_size_requirement) {
201 folder_meets_size_requirement =
202 FileMeetsSizeRequirement(type, file_info.GetSize());
203 }
204 }
205 // Make sure there is at least 1 file above a size threshold.
206 if (!folder_meets_size_requirement)
207 scan_result = MediaGalleryScanResult();
208 return reply;
209 }
210
192 MediaFolderFinder::MediaFolderFinder( 211 MediaFolderFinder::MediaFolderFinder(
193 const MediaFolderFinderResultsCallback& callback) 212 const MediaFolderFinderResultsCallback& callback)
194 : results_callback_(callback), 213 : results_callback_(callback),
195 scan_state_(SCAN_STATE_NOT_STARTED), 214 scan_state_(SCAN_STATE_NOT_STARTED),
215 worker_(new Worker()),
196 has_roots_for_testing_(false), 216 has_roots_for_testing_(false),
197 weak_factory_(this) { 217 weak_factory_(this) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
219
220 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
221 worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
199 } 222 }
200 223
201 MediaFolderFinder::~MediaFolderFinder() { 224 MediaFolderFinder::~MediaFolderFinder() {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226
227 worker_task_runner_->DeleteSoon(FROM_HERE, worker_);
228
203 if (scan_state_ == SCAN_STATE_FINISHED) 229 if (scan_state_ == SCAN_STATE_FINISHED)
204 return; 230 return;
205 231
206 MediaFolderFinderResults empty_results; 232 MediaFolderFinderResults empty_results;
207 results_callback_.Run(false /* success? */, empty_results); 233 results_callback_.Run(false /* success? */, empty_results);
208 } 234 }
209 235
210 void MediaFolderFinder::StartScan() { 236 void MediaFolderFinder::StartScan() {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
212 238
(...skipping 12 matching lines...) Expand all
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226 DCHECK_EQ(SCAN_STATE_NOT_STARTED, scan_state_); 252 DCHECK_EQ(SCAN_STATE_NOT_STARTED, scan_state_);
227 253
228 has_roots_for_testing_ = true; 254 has_roots_for_testing_ = true;
229 roots_for_testing_ = roots; 255 roots_for_testing_ = roots;
230 } 256 }
231 257
232 void MediaFolderFinder::OnInitialized( 258 void MediaFolderFinder::OnInitialized(
233 const std::vector<base::FilePath>& roots) { 259 const std::vector<base::FilePath>& roots) {
234 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 260 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_);
235 DCHECK(!token_.IsValid());
236 DCHECK(filter_callback_.is_null());
237 261
238 std::set<base::FilePath> valid_roots; 262 std::set<base::FilePath> valid_roots;
239 for (size_t i = 0; i < roots.size(); ++i) { 263 for (size_t i = 0; i < roots.size(); ++i) {
240 // Skip if |path| is invalid or redundant. 264 // Skip if |path| is invalid or redundant.
241 const base::FilePath& path = roots[i]; 265 const base::FilePath& path = roots[i];
242 if (!IsValidScanPath(path)) 266 if (!IsValidScanPath(path))
243 continue; 267 continue;
244 if (ContainsKey(valid_roots, path)) 268 if (ContainsKey(valid_roots, path))
245 continue; 269 continue;
246 270
(...skipping 14 matching lines...) Expand all
261 continue; 285 continue;
262 // Remove anything |path| overlaps from |valid_roots|. 286 // Remove anything |path| overlaps from |valid_roots|.
263 for (size_t i = 0; i < overlapping_paths_to_remove.size(); ++i) 287 for (size_t i = 0; i < overlapping_paths_to_remove.size(); ++i)
264 valid_roots.erase(overlapping_paths_to_remove[i]); 288 valid_roots.erase(overlapping_paths_to_remove[i]);
265 289
266 valid_roots.insert(path); 290 valid_roots.insert(path);
267 } 291 }
268 292
269 std::copy(valid_roots.begin(), valid_roots.end(), 293 std::copy(valid_roots.begin(), valid_roots.end(),
270 std::back_inserter(folders_to_scan_)); 294 std::back_inserter(folders_to_scan_));
271 token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
272 filter_callback_ = base::Bind(&FilterPath,
273 base::Owned(new MediaPathFilter()));
274 ScanFolder(); 295 ScanFolder();
275 } 296 }
276 297
277 void MediaFolderFinder::ScanFolder() { 298 void MediaFolderFinder::ScanFolder() {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 300 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_);
280 301
281 if (folders_to_scan_.empty()) { 302 if (folders_to_scan_.empty()) {
282 scan_state_ = SCAN_STATE_FINISHED; 303 scan_state_ = SCAN_STATE_FINISHED;
283 results_callback_.Run(true /* success? */, results_); 304 results_callback_.Run(true /* success? */, results_);
284 return; 305 return;
285 } 306 }
286 307
287 DCHECK(token_.IsValid());
288 DCHECK(!filter_callback_.is_null());
289
290 base::FilePath folder_to_scan = folders_to_scan_.back(); 308 base::FilePath folder_to_scan = folders_to_scan_.back();
291 folders_to_scan_.pop_back(); 309 folders_to_scan_.pop_back();
292 MediaGalleryScanResult* scan_result = new MediaGalleryScanResult(); 310 base::PostTaskAndReplyWithResult(
293 std::vector<base::FilePath>* new_folders = new std::vector<base::FilePath>(); 311 worker_task_runner_, FROM_HERE,
294 scoped_refptr<base::SequencedTaskRunner> task_runner = 312 base::Bind(&Worker::ScanFolder,
295 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(token_); 313 base::Unretained(worker_),
296 task_runner->PostTaskAndReply( 314 folder_to_scan),
297 FROM_HERE,
298 base::Bind(&ScanFolderOnBlockingPool,
299 folder_to_scan,
300 filter_callback_,
301 base::Unretained(scan_result),
302 base::Unretained(new_folders)),
303 base::Bind(&MediaFolderFinder::GotScanResults, 315 base::Bind(&MediaFolderFinder::GotScanResults,
304 weak_factory_.GetWeakPtr(), 316 weak_factory_.GetWeakPtr(),
305 folder_to_scan, 317 folder_to_scan));
306 base::Owned(scan_result),
307 base::Owned(new_folders)));
308 } 318 }
309 319
310 void MediaFolderFinder::GotScanResults( 320 void MediaFolderFinder::GotScanResults(const base::FilePath& path,
311 const base::FilePath& path, 321 const WorkerReply& reply) {
312 const MediaGalleryScanResult* scan_result,
313 const std::vector<base::FilePath>* new_folders) {
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
315 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 323 DCHECK_EQ(SCAN_STATE_STARTED, scan_state_);
316 DCHECK(!path.empty()); 324 DCHECK(!path.empty());
317 DCHECK(scan_result);
318 DCHECK(new_folders);
319 CHECK(!ContainsKey(results_, path)); 325 CHECK(!ContainsKey(results_, path));
320 326
321 if (!IsEmptyScanResult(*scan_result)) 327 const MediaGalleryScanResult& scan_result = reply.first;
322 results_[path] = *scan_result; 328 const std::vector<base::FilePath>& new_folders = reply.second;
329 if (!IsEmptyScanResult(scan_result))
330 results_[path] = scan_result;
323 331
324 // Push new folders to the |folders_to_scan_| in reverse order. 332 // Push new folders to the |folders_to_scan_| in reverse order.
325 std::copy(new_folders->rbegin(), new_folders->rend(), 333 std::copy(new_folders.rbegin(), new_folders.rend(),
326 std::back_inserter(folders_to_scan_)); 334 std::back_inserter(folders_to_scan_));
327 335
328 ScanFolder(); 336 ScanFolder();
329 } 337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698