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

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: Depth first traversal 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 213 struct ContainerCount {
214 // containing any media itself. In fact, the primary purpose of that directory 214 int seen_count, entries_count;
215 // may be to contain media directories. This function tries to find those 215 bool is_qualified;
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 216
234 // Skip sensitive folders and their ancestors. 217 ContainerCount() : seen_count(0), entries_count(-1), is_qualified(false) {}
235 bool is_sensitive = false; 218 };
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 219
282 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences, 220 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences,
283 const extensions::Extension* extension, 221 const extensions::Extension* extension,
284 MediaGalleryScanResult* file_counts) { 222 MediaGalleryScanResult* file_counts) {
285 int gallery_count = 0; 223 int gallery_count = 0;
286 224
287 MediaGalleryPrefIdSet permitted_galleries = 225 MediaGalleryPrefIdSet permitted_galleries =
288 preferences->GalleriesForExtension(*extension); 226 preferences->GalleriesForExtension(*extension);
289 const MediaGalleriesPrefInfoMap& known_galleries = 227 const MediaGalleriesPrefInfoMap& known_galleries =
290 preferences->known_galleries(); 228 preferences->known_galleries();
291 for (MediaGalleriesPrefInfoMap::const_iterator it = known_galleries.begin(); 229 for (MediaGalleriesPrefInfoMap::const_iterator it = known_galleries.begin();
292 it != known_galleries.end(); 230 it != known_galleries.end();
293 ++it) { 231 ++it) {
294 if (it->second.type == MediaGalleryPrefInfo::kScanResult && 232 if (it->second.type == MediaGalleryPrefInfo::kScanResult &&
295 !ContainsKey(permitted_galleries, it->first)) { 233 !ContainsKey(permitted_galleries, it->first)) {
296 gallery_count++; 234 gallery_count++;
297 file_counts->audio_count += it->second.audio_count; 235 file_counts->audio_count += it->second.audio_count;
298 file_counts->image_count += it->second.image_count; 236 file_counts->image_count += it->second.image_count;
299 file_counts->video_count += it->second.video_count; 237 file_counts->video_count += it->second.video_count;
300 } 238 }
301 } 239 }
302 return gallery_count; 240 return gallery_count;
303 } 241 }
304 242
243 int CountDirectoryEntries(const base::FilePath& path) {
244 base::FileEnumerator dir_counter(path, false /*recursive*/,
245 base::FileEnumerator::DIRECTORIES);
246 int count = 0;
247 base::FileEnumerator::FileInfo info;
248 for (base::FilePath name = dir_counter.Next();
249 !name.empty();
250 name = dir_counter.Next()) {
251 if (!base::IsLink(name))
252 ++count;
253 }
254 return count;
255 }
256
305 } // namespace 257 } // namespace
306 258
307 MediaScanManager::MediaScanManager() 259 MediaScanManager::MediaScanManager()
308 : scoped_extension_registry_observer_(this), 260 : scoped_extension_registry_observer_(this),
309 weak_factory_(this) { 261 weak_factory_(this) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 262 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
311 } 263 }
312 264
313 MediaScanManager::~MediaScanManager() { 265 MediaScanManager::~MediaScanManager() {
314 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 266 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_); 368 base::Time::Now() - scan_start_time_);
417 scan_start_time_ = base::Time(); 369 scan_start_time_ = base::Time();
418 } 370 }
419 } 371 }
420 372
421 void MediaScanManager::SetMediaFolderFinderFactory( 373 void MediaScanManager::SetMediaFolderFinderFactory(
422 const MediaFolderFinderFactory& factory) { 374 const MediaFolderFinderFactory& factory) {
423 testing_folder_finder_factory_ = factory; 375 testing_folder_finder_factory_ = factory;
424 } 376 }
425 377
378 // A single directory may contain many folders with media in them, without
379 // containing any media itself. In fact, the primary purpose of that directory
380 // may be to contain media directories. This function tries to find those
381 // container directories.
382 MediaFolderFinder::MediaFolderFinderResults
383 MediaScanManager::FindContainerScanResults(
384 const MediaFolderFinder::MediaFolderFinderResults& found_folders,
385 const std::vector<base::FilePath>& sensitive_locations) {
386 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
387 std::vector<base::FilePath> abs_sensitive_locations;
388 for (size_t i = 0; i < sensitive_locations.size(); ++i) {
389 base::FilePath path = base::MakeAbsoluteFilePath(sensitive_locations[i]);
390 if (!path.empty())
391 abs_sensitive_locations.push_back(path);
392 }
393 // Find parent directories with majority of media directories,
vandebo (ex-Chrome) 2014/06/02 16:29:25 Recursively find... ?
Kevin Bailey 2014/06/02 21:03:43 Done.
394 // or container directories.
395 // |candidates| keeps track of directories which might have enough
396 // media directories to have us return them.
397 typedef std::map<base::FilePath, ContainerCount> ContainerCandidates;
398 ContainerCandidates candidates;
399 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it =
400 found_folders.begin(); it != found_folders.end(); ++it) {
401 base::FilePath candidate = it->first;
vandebo (ex-Chrome) 2014/06/02 16:29:25 nit: it->first is already in, it's the parent that
Kevin Bailey 2014/06/02 21:03:43 Indeed, I reused the name. But since it follows |p
402 base::FilePath parent_directory = candidate.DirName();
403
404 // Parent of root is root.
405 while (!parent_directory.empty() && candidate != parent_directory) {
406 // Skip sensitive folders and their ancestors.
407 base::FilePath abs_parent_directory =
408 base::MakeAbsoluteFilePath(parent_directory);
409 if (abs_parent_directory.empty())
410 break;
411 bool is_sensitive = false;
412 for (size_t i = 0; i < abs_sensitive_locations.size(); ++i) {
413 if (abs_parent_directory == abs_sensitive_locations[i] ||
414 abs_parent_directory.IsParent(abs_sensitive_locations[i])) {
415 is_sensitive = true;
416 break;
417 }
418 }
419 if (is_sensitive)
420 break;
421
422 // Don't bother with ones we already have.
423 if (found_folders.find(parent_directory) != found_folders.end())
424 continue;
425
426 ContainerCandidates::iterator parent_it =
427 candidates.find(parent_directory);
428 if (parent_it == candidates.end()) {
429 ContainerCount count;
430 count.seen_count = 1;
431 count.entries_count = CountDirectoryEntries(parent_directory);
432 parent_it = candidates.insert(std::make_pair(parent_directory,
433 count)).first;
434 } else {
435 ++candidates[parent_directory].seen_count;
436 }
437 // If was insufficient, but is now sufficient, mark qualified and
438 // check parent.
439 if ((parent_it->second.seen_count - 1) * 100 /
vandebo (ex-Chrome) 2014/06/02 16:29:25 Instead of doing the extra math, just check that i
Kevin Bailey 2014/06/02 21:03:43 Done. For some reason, I thought it wouldn't work
vandebo (ex-Chrome) 2014/06/03 16:27:21 You didn't do the early exit, which makes things e
Kevin Bailey 2014/06/03 18:01:20 Done.
440 parent_it->second.entries_count < kContainerDirectoryMinimumPercent &&
441 parent_it->second.seen_count * 100 / parent_it->second.entries_count
442 >= kContainerDirectoryMinimumPercent) {
443 parent_it->second.is_qualified = true;
444 } else {
445 break;
446 }
447 candidate = parent_directory;
448 parent_directory = candidate.DirName();
449 }
450 }
451 MediaFolderFinder::MediaFolderFinderResults result;
452 // Copy and return worthy results.
453 for (ContainerCandidates::const_iterator it = candidates.begin();
454 it != candidates.end(); ++it) {
455 if (it->second.is_qualified && it->second.seen_count >= 2)
vandebo (ex-Chrome) 2014/06/02 16:29:25 Are you sure this is sufficient? It seems that you
Kevin Bailey 2014/06/02 21:03:43 Neither X nor Y will be qualified, due to 80% rule
vandebo (ex-Chrome) 2014/06/03 16:27:21 Hmm, indeed. SG then.
456 result[it->first] = MediaGalleryScanResult();
457 }
458 return result;
459 }
460
426 MediaScanManager::ScanObservers::ScanObservers() : observer(NULL) {} 461 MediaScanManager::ScanObservers::ScanObservers() : observer(NULL) {}
427 MediaScanManager::ScanObservers::~ScanObservers() {} 462 MediaScanManager::ScanObservers::~ScanObservers() {}
428 463
429 void MediaScanManager::OnExtensionUnloaded( 464 void MediaScanManager::OnExtensionUnloaded(
430 content::BrowserContext* browser_context, 465 content::BrowserContext* browser_context,
431 const extensions::Extension* extension, 466 const extensions::Extension* extension,
432 extensions::UnloadedExtensionInfo::Reason reason) { 467 extensions::UnloadedExtensionInfo::Reason reason) {
433 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 468 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
434 CancelScan(Profile::FromBrowserContext(browser_context), extension); 469 CancelScan(Profile::FromBrowserContext(browser_context), extension);
435 } 470 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 gallery_count, 543 gallery_count,
509 file_counts); 544 file_counts);
510 } 545 }
511 } 546 }
512 scanning_extensions->clear(); 547 scanning_extensions->clear();
513 preferences->SetLastScanCompletionTime(base::Time::Now()); 548 preferences->SetLastScanCompletionTime(base::Time::Now());
514 } 549 }
515 scoped_extension_registry_observer_.RemoveAll(); 550 scoped_extension_registry_observer_.RemoveAll();
516 folder_finder_.reset(); 551 folder_finder_.reset();
517 } 552 }
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