| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "chrome/browser/media_galleries/media_folder_finder.h" | 
|  | 6 | 
|  | 7 #include "base/files/file_enumerator.h" | 
|  | 8 #include "base/stl_util.h" | 
|  | 9 #include "base/task_runner_util.h" | 
|  | 10 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" | 
|  | 11 #include "content/public/browser/browser_thread.h" | 
|  | 12 | 
|  | 13 using content::BrowserThread; | 
|  | 14 | 
|  | 15 namespace { | 
|  | 16 | 
|  | 17 bool IsValidScanPath(const base::FilePath& path) { | 
|  | 18   return !path.empty() && path.IsAbsolute(); | 
|  | 19 } | 
|  | 20 | 
|  | 21 MediaGalleryScanFileType FilterPath(MediaPathFilter* filter, | 
|  | 22                                     const base::FilePath& path) { | 
|  | 23   DCHECK(IsValidScanPath(path)); | 
|  | 24   return filter->GetType(path); | 
|  | 25 } | 
|  | 26 | 
|  | 27 void ScanFolderOnBlockingPool( | 
|  | 28     const base::FilePath& path, | 
|  | 29     const MediaFolderFinder::FilterCallback& filter_callback_, | 
|  | 30     MediaGalleryScanResult* scan_result, | 
|  | 31     std::vector<base::FilePath>* new_folders) { | 
|  | 32   CHECK(IsValidScanPath(path)); | 
|  | 33   DCHECK(scan_result); | 
|  | 34   DCHECK(new_folders); | 
|  | 35   DCHECK(IsEmptyScanResult(*scan_result)); | 
|  | 36 | 
|  | 37   base::FileEnumerator enumerator( | 
|  | 38       path, | 
|  | 39       false, /* recursive? */ | 
|  | 40       base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); | 
|  | 41   while (!enumerator.Next().empty()) { | 
|  | 42     base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); | 
|  | 43     base::FilePath full_path = path.Append(file_info.GetName()); | 
|  | 44     if (file_info.IsDirectory()) { | 
|  | 45       new_folders->push_back(full_path); | 
|  | 46       continue; | 
|  | 47     } | 
|  | 48     // TODO(thestig) Make sure there is at least 1 file above a size threshold: | 
|  | 49     // images >= 200KB, videos >= 1MB, music >= 500KB. | 
|  | 50     MediaGalleryScanFileType type = filter_callback_.Run(full_path); | 
|  | 51     if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN) | 
|  | 52       continue; | 
|  | 53 | 
|  | 54     if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE) | 
|  | 55       scan_result->image_count += 1; | 
|  | 56     if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO) | 
|  | 57       scan_result->audio_count += 1; | 
|  | 58     if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO) | 
|  | 59       scan_result->video_count += 1; | 
|  | 60   } | 
|  | 61 } | 
|  | 62 | 
|  | 63 }  // namespace | 
|  | 64 | 
|  | 65 MediaFolderFinder::MediaFolderFinder( | 
|  | 66     const std::vector<base::FilePath>& roots, | 
|  | 67     const MediaFolderFinderResultsCallback& callback) | 
|  | 68     : results_callback_(callback), | 
|  | 69       scan_state_(SCAN_STATE_NOT_STARTED), | 
|  | 70       weak_factory_(this) { | 
|  | 71   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 72 | 
|  | 73   for (size_t i = 0; i < roots.size(); ++i) { | 
|  | 74     const base::FilePath& path = roots[i]; | 
|  | 75     if (!IsValidScanPath(path)) | 
|  | 76       continue; | 
|  | 77     // TODO(thestig) Check |path| for overlap with the rest of |roots|. | 
|  | 78     folders_to_scan_.push(path); | 
|  | 79   } | 
|  | 80 } | 
|  | 81 | 
|  | 82 MediaFolderFinder::~MediaFolderFinder() { | 
|  | 83   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 84   if (scan_state_ == SCAN_STATE_FINISHED) | 
|  | 85     return; | 
|  | 86 | 
|  | 87   MediaFolderFinderResults empty_results; | 
|  | 88   results_callback_.Run(false /* success? */, empty_results); | 
|  | 89 } | 
|  | 90 | 
|  | 91 void MediaFolderFinder::StartScan() { | 
|  | 92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 93 | 
|  | 94   if (scan_state_ != SCAN_STATE_NOT_STARTED) | 
|  | 95     return; | 
|  | 96   scan_state_ = SCAN_STATE_STARTED; | 
|  | 97 | 
|  | 98   DCHECK(!token_.IsValid()); | 
|  | 99   DCHECK(filter_callback_.is_null()); | 
|  | 100   token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); | 
|  | 101   filter_callback_ = base::Bind(&FilterPath, | 
|  | 102                                 base::Owned(new MediaPathFilter())); | 
|  | 103   ScanFolder(); | 
|  | 104 } | 
|  | 105 | 
|  | 106 void MediaFolderFinder::ScanFolder() { | 
|  | 107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 108   DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); | 
|  | 109 | 
|  | 110   if (folders_to_scan_.empty()) { | 
|  | 111     scan_state_ = SCAN_STATE_FINISHED; | 
|  | 112     results_callback_.Run(true /* success? */, results_); | 
|  | 113     return; | 
|  | 114   } | 
|  | 115 | 
|  | 116   DCHECK(token_.IsValid()); | 
|  | 117   DCHECK(!filter_callback_.is_null()); | 
|  | 118 | 
|  | 119   base::FilePath folder_to_scan = folders_to_scan_.top(); | 
|  | 120   folders_to_scan_.pop(); | 
|  | 121   MediaGalleryScanResult* scan_result = new MediaGalleryScanResult(); | 
|  | 122   std::vector<base::FilePath>* new_folders = new std::vector<base::FilePath>(); | 
|  | 123   scoped_refptr<base::SequencedTaskRunner> task_runner = | 
|  | 124       BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(token_); | 
|  | 125   task_runner->PostTaskAndReply( | 
|  | 126       FROM_HERE, | 
|  | 127       base::Bind(&ScanFolderOnBlockingPool, | 
|  | 128                  folder_to_scan, | 
|  | 129                  filter_callback_, | 
|  | 130                  base::Unretained(scan_result), | 
|  | 131                  base::Unretained(new_folders)), | 
|  | 132       base::Bind(&MediaFolderFinder::GotScanResults, | 
|  | 133                  weak_factory_.GetWeakPtr(), | 
|  | 134                  folder_to_scan, | 
|  | 135                  base::Owned(scan_result), | 
|  | 136                  base::Owned(new_folders))); | 
|  | 137 } | 
|  | 138 | 
|  | 139 void MediaFolderFinder::GotScanResults( | 
|  | 140     const base::FilePath& path, | 
|  | 141     const MediaGalleryScanResult* scan_result, | 
|  | 142     const std::vector<base::FilePath>* new_folders) { | 
|  | 143   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 144   DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); | 
|  | 145   DCHECK(!path.empty()); | 
|  | 146   DCHECK(scan_result); | 
|  | 147   DCHECK(new_folders); | 
|  | 148   CHECK(!ContainsKey(results_, path)); | 
|  | 149 | 
|  | 150   if (!IsEmptyScanResult(*scan_result)) | 
|  | 151     results_[path] = *scan_result; | 
|  | 152 | 
|  | 153   // Push new folders to the |folders_to_scan_| stack in reverse order. | 
|  | 154   for (size_t i = new_folders->size(); i > 0; --i) { | 
|  | 155     const base::FilePath& path_to_add = (*new_folders)[i - 1]; | 
|  | 156     folders_to_scan_.push(path_to_add); | 
|  | 157   } | 
|  | 158 | 
|  | 159   ScanFolder(); | 
|  | 160 } | 
| OLD | NEW | 
|---|