 Chromium Code Reviews
 Chromium Code Reviews Issue 149363004:
  Media Galleries: Initial media scanner implementation.  (Closed) 
  Base URL: svn://chrome-svn/chrome/trunk/src/
    
  
    Issue 149363004:
  Media Galleries: Initial media scanner implementation.  (Closed) 
  Base URL: svn://chrome-svn/chrome/trunk/src/| 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 |