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

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

Issue 285433004: Have FindContainerScanResults() find broader media container directories (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed recursive fix-up, other responses Created 6 years, 6 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
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_scan_manager.h" 5 #include "chrome/browser/media_galleries/media_scan_manager.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_enumerator.h" 8 #include "base/files/file_enumerator.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 MediaGalleryPrefInfo::kScanResult, 203 MediaGalleryPrefInfo::kScanResult,
204 gallery.volume_label, gallery.vendor_name, 204 gallery.volume_label, gallery.vendor_name,
205 gallery.model_name, gallery.total_size_in_bytes, 205 gallery.model_name, gallery.total_size_in_bytes,
206 gallery.last_attach_time, file_counts.audio_count, 206 gallery.last_attach_time, file_counts.audio_count,
207 file_counts.image_count, file_counts.video_count); 207 file_counts.image_count, file_counts.video_count);
208 } 208 }
209 UMA_HISTOGRAM_COUNTS_10000("MediaGalleries.ScanGalleriesPopulated", 209 UMA_HISTOGRAM_COUNTS_10000("MediaGalleries.ScanGalleriesPopulated",
210 unique_found_folders.size() + to_update.size()); 210 unique_found_folders.size() + to_update.size());
211 } 211 }
212 212
213 // A single directory may contain many folders with media in them, without
214 // containing any media itself. In fact, the primary purpose of that directory
215 // may be to contain media directories. This function tries to find those
216 // immediate container directories.
217 MediaFolderFinder::MediaFolderFinderResults FindContainerScanResults(
218 const MediaFolderFinder::MediaFolderFinderResults& found_folders,
219 const std::vector<base::FilePath>& sensitive_locations) {
220 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
221 std::vector<base::FilePath> abs_sensitive_locations;
222 for (size_t i = 0; i < sensitive_locations.size(); ++i) {
223 base::FilePath path = base::MakeAbsoluteFilePath(sensitive_locations[i]);
224 if (!path.empty())
225 abs_sensitive_locations.push_back(path);
226 }
227 // Count the number of scan results with the same parent directory.
228 typedef std::map<base::FilePath, int /*count*/> ContainerCandidates;
229 ContainerCandidates candidates;
230 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it =
231 found_folders.begin(); it != found_folders.end(); ++it) {
232 base::FilePath parent_directory = it->first.DirName();
233
234 // Skip sensitive folders and their ancestors.
235 bool is_sensitive = false;
236 base::FilePath abs_parent_directory =
237 base::MakeAbsoluteFilePath(parent_directory);
238 if (abs_parent_directory.empty())
239 continue;
240 for (size_t i = 0; i < abs_sensitive_locations.size(); ++i) {
241 if (abs_parent_directory == abs_sensitive_locations[i] ||
242 abs_parent_directory.IsParent(abs_sensitive_locations[i])) {
243 is_sensitive = true;
244 continue;
245 }
246 }
247 if (is_sensitive)
248 continue;
249
250 ContainerCandidates::iterator existing = candidates.find(parent_directory);
251 if (existing == candidates.end()) {
252 candidates[parent_directory] = 1;
253 } else {
254 existing->second++;
255 }
256 }
257
258 // If a parent directory has more than one scan result, consider it.
259 MediaFolderFinder::MediaFolderFinderResults result;
260 for (ContainerCandidates::const_iterator it = candidates.begin();
261 it != candidates.end();
262 ++it) {
263 if (it->second <= 1)
264 continue;
265
266 base::FileEnumerator dir_counter(it->first, false /*recursive*/,
267 base::FileEnumerator::DIRECTORIES);
268 base::FileEnumerator::FileInfo info;
269 int count = 0;
270 for (base::FilePath name = dir_counter.Next();
271 !name.empty();
272 name = dir_counter.Next()) {
273 if (!base::IsLink(name))
274 count++;
275 }
276 if (it->second * 100 / count >= kContainerDirectoryMinimumPercent)
277 result[it->first] = MediaGalleryScanResult();
278 }
279 return result;
280 }
281
282 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences, 213 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences,
283 const extensions::Extension* extension, 214 const extensions::Extension* extension,
284 MediaGalleryScanResult* file_counts) { 215 MediaGalleryScanResult* file_counts) {
285 int gallery_count = 0; 216 int gallery_count = 0;
286 217
287 MediaGalleryPrefIdSet permitted_galleries = 218 MediaGalleryPrefIdSet permitted_galleries =
288 preferences->GalleriesForExtension(*extension); 219 preferences->GalleriesForExtension(*extension);
289 const MediaGalleriesPrefInfoMap& known_galleries = 220 const MediaGalleriesPrefInfoMap& known_galleries =
290 preferences->known_galleries(); 221 preferences->known_galleries();
291 for (MediaGalleriesPrefInfoMap::const_iterator it = known_galleries.begin(); 222 for (MediaGalleriesPrefInfoMap::const_iterator it = known_galleries.begin();
292 it != known_galleries.end(); 223 it != known_galleries.end();
293 ++it) { 224 ++it) {
294 if (it->second.type == MediaGalleryPrefInfo::kScanResult && 225 if (it->second.type == MediaGalleryPrefInfo::kScanResult &&
295 !ContainsKey(permitted_galleries, it->first)) { 226 !ContainsKey(permitted_galleries, it->first)) {
296 gallery_count++; 227 gallery_count++;
297 file_counts->audio_count += it->second.audio_count; 228 file_counts->audio_count += it->second.audio_count;
298 file_counts->image_count += it->second.image_count; 229 file_counts->image_count += it->second.image_count;
299 file_counts->video_count += it->second.video_count; 230 file_counts->video_count += it->second.video_count;
300 } 231 }
301 } 232 }
302 return gallery_count; 233 return gallery_count;
303 } 234 }
304 235
236 int CountDirectoryEntries(const base::FilePath& path) {
237 base::FileEnumerator dir_counter(path, false /*recursive*/,
238 base::FileEnumerator::DIRECTORIES);
239 int count = 0;
240 base::FileEnumerator::FileInfo info;
241 for (base::FilePath name = dir_counter.Next();
242 !name.empty();
243 name = dir_counter.Next()) {
244 if (!base::IsLink(name))
245 ++count;
246 }
247 return count;
248 }
249
250 struct ContainerCount {
251 int seen_count, entries_count;
252 bool is_qualified;
253
254 ContainerCount() : seen_count(0), entries_count(-1), is_qualified(false) {}
255 };
256
257 typedef std::map<base::FilePath, ContainerCount> ContainerCandidates;
258
305 } // namespace 259 } // namespace
306 260
307 MediaScanManager::MediaScanManager() 261 MediaScanManager::MediaScanManager()
308 : scoped_extension_registry_observer_(this), 262 : scoped_extension_registry_observer_(this),
309 weak_factory_(this) { 263 weak_factory_(this) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 264 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
311 } 265 }
312 266
313 MediaScanManager::~MediaScanManager() { 267 MediaScanManager::~MediaScanManager() {
314 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 268 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 base::Time::Now() - scan_start_time_); 370 base::Time::Now() - scan_start_time_);
417 scan_start_time_ = base::Time(); 371 scan_start_time_ = base::Time();
418 } 372 }
419 } 373 }
420 374
421 void MediaScanManager::SetMediaFolderFinderFactory( 375 void MediaScanManager::SetMediaFolderFinderFactory(
422 const MediaFolderFinderFactory& factory) { 376 const MediaFolderFinderFactory& factory) {
423 testing_folder_finder_factory_ = factory; 377 testing_folder_finder_factory_ = factory;
424 } 378 }
425 379
380 // A single directory may contain many folders with media in them, without
381 // containing any media itself. In fact, the primary purpose of that directory
382 // may be to contain media directories. This function tries to find those
383 // container directories.
384 MediaFolderFinder::MediaFolderFinderResults
385 MediaScanManager::FindContainerScanResults(
386 const MediaFolderFinder::MediaFolderFinderResults& found_folders,
387 const std::vector<base::FilePath>& sensitive_locations) {
388 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
389 std::vector<base::FilePath> abs_sensitive_locations;
390 for (size_t i = 0; i < sensitive_locations.size(); ++i) {
391 base::FilePath path = base::MakeAbsoluteFilePath(sensitive_locations[i]);
392 if (!path.empty())
393 abs_sensitive_locations.push_back(path);
394 }
395 // Recursively find parent directories with majority of media directories,
396 // or container directories.
397 // |candidates| keeps track of directories which might have enough
398 // such directories to have us return them.
399 typedef std::map<base::FilePath, ContainerCount> ContainerCandidates;
400 ContainerCandidates candidates;
401 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it =
402 found_folders.begin(); it != found_folders.end(); ++it) {
403 base::FilePath child_directory = it->first;
404 base::FilePath parent_directory = child_directory.DirName();
405
406 // Parent of root is root.
407 while (!parent_directory.empty() && child_directory != parent_directory) {
408 // Skip sensitive folders and their ancestors.
409 base::FilePath abs_parent_directory =
410 base::MakeAbsoluteFilePath(parent_directory);
411 if (abs_parent_directory.empty())
412 break;
413 bool is_sensitive = false;
414 for (size_t i = 0; i < abs_sensitive_locations.size(); ++i) {
415 if (abs_parent_directory == abs_sensitive_locations[i] ||
416 abs_parent_directory.IsParent(abs_sensitive_locations[i])) {
417 is_sensitive = true;
418 break;
419 }
420 }
421 if (is_sensitive)
422 break;
423
424 // Don't bother with ones we already have.
425 if (found_folders.find(parent_directory) != found_folders.end())
426 continue;
427
428 ContainerCandidates::iterator parent_it =
429 candidates.find(parent_directory);
430 if (parent_it == candidates.end()) {
431 ContainerCount count;
432 count.seen_count = 1;
433 count.entries_count = CountDirectoryEntries(parent_directory);
434 parent_it = candidates.insert(std::make_pair(parent_directory,
435 count)).first;
436 } else {
437 ++candidates[parent_directory].seen_count;
438 }
439 // If already sufficient, bail.
440 if (parent_it->second.is_qualified)
441 break;
442 // If now sufficient, mark qualified and check parent.
443 if (parent_it->second.seen_count * 100 / parent_it->second.entries_count
444 >= kContainerDirectoryMinimumPercent) {
445 parent_it->second.is_qualified = true;
446 } else {
447 break;
vandebo (ex-Chrome) 2014/06/03 18:08:31 nit: This else break construct is kind of hard to
Kevin Bailey 2014/06/03 18:31:25 Couldn't make it *exactly* the same due to line le
vandebo (ex-Chrome) 2014/06/03 18:42:31 Assumed... as is, it violated style guide. I'd sug
448 }
449 child_directory = parent_directory;
450 parent_directory = child_directory.DirName();
451 }
452 }
453 MediaFolderFinder::MediaFolderFinderResults result;
454 // Copy and return worthy results.
455 for (ContainerCandidates::const_iterator it = candidates.begin();
456 it != candidates.end(); ++it) {
457 if (it->second.is_qualified && it->second.seen_count >= 2)
458 result[it->first] = MediaGalleryScanResult();
459 }
460 return result;
461 }
462
426 MediaScanManager::ScanObservers::ScanObservers() : observer(NULL) {} 463 MediaScanManager::ScanObservers::ScanObservers() : observer(NULL) {}
427 MediaScanManager::ScanObservers::~ScanObservers() {} 464 MediaScanManager::ScanObservers::~ScanObservers() {}
428 465
429 void MediaScanManager::OnExtensionUnloaded( 466 void MediaScanManager::OnExtensionUnloaded(
430 content::BrowserContext* browser_context, 467 content::BrowserContext* browser_context,
431 const extensions::Extension* extension, 468 const extensions::Extension* extension,
432 extensions::UnloadedExtensionInfo::Reason reason) { 469 extensions::UnloadedExtensionInfo::Reason reason) {
433 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 470 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
434 CancelScan(Profile::FromBrowserContext(browser_context), extension); 471 CancelScan(Profile::FromBrowserContext(browser_context), extension);
435 } 472 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 gallery_count, 545 gallery_count,
509 file_counts); 546 file_counts);
510 } 547 }
511 } 548 }
512 scanning_extensions->clear(); 549 scanning_extensions->clear();
513 preferences->SetLastScanCompletionTime(base::Time::Now()); 550 preferences->SetLastScanCompletionTime(base::Time::Now());
514 } 551 }
515 scoped_extension_registry_observer_.RemoveAll(); 552 scoped_extension_registry_observer_.RemoveAll();
516 folder_finder_.reset(); 553 folder_finder_.reset();
517 } 554 }
OLDNEW
« no previous file with comments | « chrome/browser/media_galleries/media_scan_manager.h ('k') | chrome/browser/media_galleries/media_scan_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698