Chromium Code Reviews| Index: chrome/browser/media_galleries/fileapi/media_scanner.cc |
| =================================================================== |
| --- chrome/browser/media_galleries/fileapi/media_scanner.cc (revision 0) |
| +++ chrome/browser/media_galleries/fileapi/media_scanner.cc (revision 0) |
| @@ -0,0 +1,165 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/media_galleries/fileapi/media_scanner.h" |
| + |
| +#include "base/files/file_enumerator.h" |
| +#include "base/stl_util.h" |
| +#include "base/task_runner_util.h" |
| +#include "base/threading/sequenced_worker_pool.h" |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
nit: you may omit this - in header
Lei Zhang
2014/01/30 00:10:49
Done.
|
| +#include "chrome/browser/media_galleries/fileapi/media_path_filter.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +using content::BrowserThread; |
| + |
| +namespace { |
| + |
| +bool IsValidScanPath(const base::FilePath& path) { |
| + return !path.empty() && path.IsAbsolute(); |
| +} |
| + |
| +bool IsEmptyScanResult(const MediaGalleryScanResult& scan_result) { |
| + return (scan_result.image_count == 0 && |
| + scan_result.audio_count == 0 && |
| + scan_result.video_count == 0); |
| +} |
| + |
| +MediaGalleryScanFileType FilterPath(MediaPathFilter* filter, |
| + const base::FilePath& path) { |
| + DCHECK(IsValidScanPath(path)); |
| + return filter->GetType(path); |
| +} |
| + |
| +void DoScanOnBlockingPool(const base::FilePath& path, |
| + const MediaScanner::FilterCallback& filter_callback_, |
| + std::vector<base::FilePath>* new_folders, |
| + MediaGalleryScanResult* scan_result) { |
| + DCHECK(IsValidScanPath(path)); |
| + DCHECK(new_folders); |
| + DCHECK(scan_result); |
| + DCHECK(IsEmptyScanResult(*scan_result)); |
| + |
| + base::FileEnumerator enumerator( |
| + path, |
| + false, /* recursive? */ |
| + base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); |
| + while (!enumerator.Next().empty()) { |
| + base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
Feel free to do in a follow up CL, but we want to
Lei Zhang
2014/01/30 00:10:49
Heh, I knew we had more requirements. I'll follow
|
| + base::FilePath full_path = path.Append(file_info.GetName()); |
| + if (file_info.IsDirectory()) { |
| + new_folders->push_back(full_path); |
| + continue; |
| + } |
| + MediaGalleryScanFileType type = filter_callback_.Run(full_path); |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
Some types might be audio or video (.ogg ?) Count
Lei Zhang
2014/01/30 00:10:49
Done.
|
| + switch (type) { |
| + case MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE: |
| + scan_result->image_count += 1; |
| + break; |
| + case MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO: |
| + scan_result->audio_count += 1; |
| + break; |
| + case MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO: |
| + scan_result->video_count += 1; |
| + break; |
| + case MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +MediaScanner::MediaScanner(const std::vector<base::FilePath>& roots, |
| + const MediaScannerResultsCallback& callback) |
| + : callback_(callback), |
| + started_scan_(false), |
| + weak_factory_(this) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + for (size_t i = 0; i < roots.size(); ++i) { |
| + if (!IsValidScanPath(roots[i])) |
| + continue; |
| + folders_to_scan_.push(roots[i]); |
| + } |
| +} |
| + |
| +MediaScanner::~MediaScanner() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| +} |
| + |
| +void MediaScanner::StartScan() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + if (started_scan_) |
| + return; |
| + |
| + DCHECK(!token_.IsValid()); |
| + DCHECK(filter_callback_.is_null()); |
| + token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); |
| + filter_callback_ = base::Bind(&FilterPath, |
| + base::Owned(new MediaPathFilter())); |
| + started_scan_ = true; |
| + DoScan(); |
| +} |
| + |
| +void MediaScanner::CancelScan() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
Looks like you also need to set a bool scan_cancel
Lei Zhang
2014/01/30 00:10:49
I removed CancelScan() and added |scan_state_|.
|
| + MediaScannerResults empty_results; |
| + callback_.Run(false, empty_results); |
| +} |
| + |
| +void MediaScanner::DoScan() { |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
DoScan -> ScanDirectory ?
Lei Zhang
2014/01/30 00:10:49
Done.
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + if (folders_to_scan_.empty()) { |
| + callback_.Run(false, results_); |
| + return; |
| + } |
| + |
| + DCHECK(token_.IsValid()); |
| + DCHECK(!filter_callback_.is_null()); |
| + std::vector<base::FilePath>* new_folders = new std::vector<base::FilePath>(); |
| + MediaGalleryScanResult* scan_result = new MediaGalleryScanResult(); |
| + scoped_refptr<base::SequencedTaskRunner> task_runner = |
| + BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(token_); |
| + task_runner->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&DoScanOnBlockingPool, |
| + folders_to_scan_.top(), |
| + filter_callback_, |
| + base::Unretained(new_folders), |
| + base::Unretained(scan_result)), |
| + base::Bind(&MediaScanner::GotScanResults, |
| + weak_factory_.GetWeakPtr(), |
| + folders_to_scan_.top(), |
| + base::Owned(new_folders), |
| + base::Owned(scan_result))); |
| + folders_to_scan_.pop(); |
|
vandebo (ex-Chrome)
2014/01/29 18:41:45
nit: easier to reason about if you pop it off befo
Lei Zhang
2014/01/30 00:10:49
Done.
|
| +} |
| + |
| +void MediaScanner::GotScanResults( |
| + const base::FilePath& path, |
| + const std::vector<base::FilePath>* new_folders, |
| + const MediaGalleryScanResult* scan_result) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(!path.empty()); |
| + DCHECK(new_folders); |
| + DCHECK(scan_result); |
| + CHECK(!ContainsKey(results_, path)); |
| + |
| + if (!IsEmptyScanResult(*scan_result)) |
| + results_[path] = *scan_result; |
| + |
| + // Push new folders to the |folders_to_scan_| stack in reverse order. |
| + if (!new_folders->empty()) { |
| + for (size_t i = new_folders->size(); i > 0; --i) { |
| + const base::FilePath& path_to_add = (*new_folders)[i - 1]; |
| + CHECK(!path_to_add.empty()); |
| + folders_to_scan_.push(path_to_add); |
| + } |
| + } |
| + |
| + DoScan(); |
| +} |
| Property changes on: chrome/browser/media_galleries/fileapi/media_scanner.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |