Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 // 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 | 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 | 215 // may be to contain media directories. This function tries to find those |
| 216 // immediate container directories. | 216 // immediate container directories. |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
nit: remove "immediate"
Kevin Bailey
2014/05/20 16:21:39
Done.
| |
| 217 MediaFolderFinder::MediaFolderFinderResults FindContainerScanResults( | 217 MediaFolderFinder::MediaFolderFinderResults FindContainerScanResults( |
| 218 const MediaFolderFinder::MediaFolderFinderResults& found_folders, | 218 const MediaFolderFinder::MediaFolderFinderResults& found_folders, |
| 219 const std::vector<base::FilePath>& sensitive_locations) { | 219 const std::vector<base::FilePath>& sensitive_locations) { |
| 220 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); | 220 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); |
| 221 std::vector<base::FilePath> abs_sensitive_locations; | 221 std::vector<base::FilePath> abs_sensitive_locations; |
| 222 for (size_t i = 0; i < sensitive_locations.size(); ++i) { | 222 for (size_t i = 0; i < sensitive_locations.size(); ++i) { |
| 223 base::FilePath path = base::MakeAbsoluteFilePath(sensitive_locations[i]); | 223 base::FilePath path = base::MakeAbsoluteFilePath(sensitive_locations[i]); |
| 224 if (!path.empty()) | 224 if (!path.empty()) |
| 225 abs_sensitive_locations.push_back(path); | 225 abs_sensitive_locations.push_back(path); |
| 226 } | 226 } |
| 227 // Count the number of scan results with the same parent directory. | 227 // Count the number of scan results with the same parent directory. |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
This comment seems wrong now
Kevin Bailey
2014/05/20 16:21:39
Better?
| |
| 228 MediaFolderFinder::MediaFolderFinderResults result; | |
| 228 typedef std::map<base::FilePath, int /*count*/> ContainerCandidates; | 229 typedef std::map<base::FilePath, int /*count*/> ContainerCandidates; |
| 229 ContainerCandidates candidates; | 230 ContainerCandidates candidates; |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
Having result, candidates, and interesting_candida
Kevin Bailey
2014/05/20 16:21:39
I renamed to |candidates_to_check|, and commented
| |
| 231 std::set<base::FilePath> interesting_candidates; | |
| 232 // Add incoming folders to all the lists. | |
| 230 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it = | 233 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it = |
| 231 found_folders.begin(); it != found_folders.end(); ++it) { | 234 found_folders.begin(); it != found_folders.end(); ++it) { |
| 232 base::FilePath parent_directory = it->first.DirName(); | 235 // All original folders are "permanent" candidates. |
| 236 // If not subsumed by parent, they get reported. | |
| 237 // TODO: We could even keep the original audio_count, ... | |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
Container results should be reported with zero cou
Kevin Bailey
2014/05/20 16:21:39
Done.
| |
| 238 result[it->first] = MediaGalleryScanResult(); | |
| 239 // We have to use this count in case this candidate is treated like a | |
| 240 // parent. Media files have to outnumber non-media entries. | |
| 241 candidates[it->first] = it->second.audio_count + it->second.image_count + | |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
Why do we need the counts of media files?
Kevin Bailey
2014/05/20 16:21:39
Gone.
| |
| 242 it->second.video_count; | |
| 243 // Add it to the list to be considered. | |
| 244 interesting_candidates.insert(it->first); | |
| 245 } | |
| 246 base::FilePath candidate; | |
| 247 while (!interesting_candidates.empty()) { | |
| 248 candidate = *interesting_candidates.begin(); | |
| 249 // Remove in case it gets added back. | |
| 250 interesting_candidates.erase(interesting_candidates.begin()); | |
| 251 // It *could* have been nuked. | |
| 252 ContainerCandidates::iterator it = candidates.find(candidate); | |
| 253 if (it == candidates.end()) | |
| 254 continue; | |
| 255 base::FilePath parent_directory = candidate.DirName(); | |
| 233 | 256 |
| 234 // Skip sensitive folders and their ancestors. | 257 // Skip sensitive folders and their ancestors. |
| 235 bool is_sensitive = false; | 258 bool is_sensitive = false; |
| 236 base::FilePath abs_parent_directory = | 259 base::FilePath abs_parent_directory = |
| 237 base::MakeAbsoluteFilePath(parent_directory); | 260 base::MakeAbsoluteFilePath(parent_directory); |
| 238 if (abs_parent_directory.empty()) | 261 if (abs_parent_directory.empty()) { |
| 262 result.erase(result.find(candidate)); | |
| 263 candidates.erase(it); | |
| 239 continue; | 264 continue; |
| 265 } | |
| 240 for (size_t i = 0; i < abs_sensitive_locations.size(); ++i) { | 266 for (size_t i = 0; i < abs_sensitive_locations.size(); ++i) { |
| 241 if (abs_parent_directory == abs_sensitive_locations[i] || | 267 if (abs_parent_directory == abs_sensitive_locations[i] || |
| 242 abs_parent_directory.IsParent(abs_sensitive_locations[i])) { | 268 abs_parent_directory.IsParent(abs_sensitive_locations[i])) { |
| 243 is_sensitive = true; | 269 is_sensitive = true; |
| 244 continue; | 270 break; |
| 245 } | 271 } |
| 246 } | 272 } |
| 247 if (is_sensitive) | 273 if (is_sensitive) { |
| 274 result.erase(result.find(candidate)); | |
| 275 candidates.erase(it); | |
| 248 continue; | 276 continue; |
| 249 | 277 } |
| 250 ContainerCandidates::iterator existing = candidates.find(parent_directory); | 278 ContainerCandidates::iterator it_parent = candidates.find(parent_directory); |
| 251 if (existing == candidates.end()) { | 279 if (it_parent == candidates.end()) { |
| 252 candidates[parent_directory] = 1; | 280 candidates[parent_directory] = 1; |
| 253 } else { | 281 continue; |
| 254 existing->second++; | |
| 255 } | 282 } |
| 256 } | 283 it_parent->second++; |
| 257 | 284 // If a parent directory has more than one scan result, consider it. |
| 258 // If a parent directory has more than one scan result, consider it. | 285 base::FileEnumerator dir_counter(it_parent->first, false /*recursive*/, |
| 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); | 286 base::FileEnumerator::DIRECTORIES); |
| 268 base::FileEnumerator::FileInfo info; | 287 base::FileEnumerator::FileInfo info; |
| 269 int count = 0; | 288 int count = 0; |
| 270 for (base::FilePath name = dir_counter.Next(); | 289 for (base::FilePath name = dir_counter.Next(); |
| 271 !name.empty(); | 290 !name.empty(); |
| 272 name = dir_counter.Next()) { | 291 name = dir_counter.Next()) { |
| 273 if (!base::IsLink(name)) | 292 if (!base::IsLink(name)) |
| 274 count++; | 293 count++; |
| 275 } | 294 } |
| 276 if (it->second * 100 / count >= kContainerDirectoryMinimumPercent) | 295 if (it_parent->second * 100 / count >= kContainerDirectoryMinimumPercent) { |
| 277 result[it->first] = MediaGalleryScanResult(); | 296 // We're keeping this parent. Remove all children. |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
Which children to remove is Profile specific, so y
Kevin Bailey
2014/05/20 16:21:39
Gone, but we do remove children that we've added.
| |
| 297 for (ContainerCandidates::iterator it_child = candidates.begin(); | |
| 298 it_child != candidates.end(); ) { | |
| 299 if (it_child != it_parent && | |
| 300 it_child->first.DirName() == it_parent->first) { | |
| 301 ContainerCandidates::iterator next(it_child); | |
| 302 ++next; | |
| 303 result.erase(result.find(it_child->first)); | |
| 304 candidates.erase(it_child); | |
| 305 it_child = next; | |
| 306 } else { | |
| 307 ++it_child; | |
| 308 } | |
| 309 } | |
| 310 // It's a qualified candidate now. | |
| 311 result[it_parent->first] = MediaGalleryScanResult(); | |
| 312 interesting_candidates.insert(it_parent->first); | |
| 313 } | |
| 278 } | 314 } |
| 279 return result; | 315 return result; |
| 280 } | 316 } |
| 281 | 317 |
| 282 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences, | 318 int CountScanResultsForExtension(MediaGalleriesPreferences* preferences, |
| 283 const extensions::Extension* extension, | 319 const extensions::Extension* extension, |
| 284 MediaGalleryScanResult* file_counts) { | 320 MediaGalleryScanResult* file_counts) { |
| 285 int gallery_count = 0; | 321 int gallery_count = 0; |
| 286 | 322 |
| 287 MediaGalleryPrefIdSet permitted_galleries = | 323 MediaGalleryPrefIdSet permitted_galleries = |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 UMA_HISTOGRAM_LONG_TIMES("MediaGalleries.ScanFinishedTime", | 495 UMA_HISTOGRAM_LONG_TIMES("MediaGalleries.ScanFinishedTime", |
| 460 base::Time::Now() - scan_start_time_); | 496 base::Time::Now() - scan_start_time_); |
| 461 scan_start_time_ = base::Time(); | 497 scan_start_time_ = base::Time(); |
| 462 | 498 |
| 463 content::BrowserThread::PostTaskAndReplyWithResult( | 499 content::BrowserThread::PostTaskAndReplyWithResult( |
| 464 content::BrowserThread::FILE, FROM_HERE, | 500 content::BrowserThread::FILE, FROM_HERE, |
| 465 base::Bind(FindContainerScanResults, | 501 base::Bind(FindContainerScanResults, |
| 466 found_folders, | 502 found_folders, |
| 467 folder_finder_->graylisted_folders()), | 503 folder_finder_->graylisted_folders()), |
| 468 base::Bind(&MediaScanManager::OnFoundContainerDirectories, | 504 base::Bind(&MediaScanManager::OnFoundContainerDirectories, |
| 469 weak_factory_.GetWeakPtr(), | 505 weak_factory_.GetWeakPtr())); |
| 470 found_folders)); | |
| 471 } | 506 } |
| 472 | 507 |
| 473 void MediaScanManager::OnFoundContainerDirectories( | 508 void MediaScanManager::OnFoundContainerDirectories( |
| 474 const MediaFolderFinder::MediaFolderFinderResults& found_folders, | |
| 475 const MediaFolderFinder::MediaFolderFinderResults& container_folders) { | 509 const MediaFolderFinder::MediaFolderFinderResults& container_folders) { |
| 476 MediaFolderFinder::MediaFolderFinderResults folders; | |
| 477 folders.insert(found_folders.begin(), found_folders.end()); | |
| 478 folders.insert(container_folders.begin(), container_folders.end()); | |
| 479 | 510 |
| 480 for (ScanObserverMap::iterator scans_for_profile = observers_.begin(); | 511 for (ScanObserverMap::iterator scans_for_profile = observers_.begin(); |
| 481 scans_for_profile != observers_.end(); | 512 scans_for_profile != observers_.end(); |
| 482 ++scans_for_profile) { | 513 ++scans_for_profile) { |
| 483 if (scans_for_profile->second.scanning_extensions.empty()) | 514 if (scans_for_profile->second.scanning_extensions.empty()) |
| 484 continue; | 515 continue; |
| 485 Profile* profile = scans_for_profile->first; | 516 Profile* profile = scans_for_profile->first; |
| 486 MediaGalleriesPreferences* preferences = | 517 MediaGalleriesPreferences* preferences = |
| 487 MediaGalleriesPreferencesFactory::GetForProfile(profile); | 518 MediaGalleriesPreferencesFactory::GetForProfile(profile); |
| 488 ExtensionService* extension_service = | 519 ExtensionService* extension_service = |
| 489 extensions::ExtensionSystem::Get(profile)->extension_service(); | 520 extensions::ExtensionSystem::Get(profile)->extension_service(); |
| 490 if (!extension_service) | 521 if (!extension_service) |
| 491 continue; | 522 continue; |
| 492 | 523 |
| 493 AddScanResultsForProfile(preferences, folders); | 524 AddScanResultsForProfile(preferences, container_folders); |
|
vandebo (ex-Chrome)
2014/05/14 22:33:08
We need to add all the scan results - this is the
Kevin Bailey
2014/05/20 16:21:39
Restored original code.
| |
| 494 | 525 |
| 495 ScanningExtensionIdSet* scanning_extensions = | 526 ScanningExtensionIdSet* scanning_extensions = |
| 496 &scans_for_profile->second.scanning_extensions; | 527 &scans_for_profile->second.scanning_extensions; |
| 497 for (ScanningExtensionIdSet::const_iterator extension_id_it = | 528 for (ScanningExtensionIdSet::const_iterator extension_id_it = |
| 498 scanning_extensions->begin(); | 529 scanning_extensions->begin(); |
| 499 extension_id_it != scanning_extensions->end(); | 530 extension_id_it != scanning_extensions->end(); |
| 500 ++extension_id_it) { | 531 ++extension_id_it) { |
| 501 const extensions::Extension* extension = | 532 const extensions::Extension* extension = |
| 502 extension_service->GetExtensionById(*extension_id_it, false); | 533 extension_service->GetExtensionById(*extension_id_it, false); |
| 503 if (extension) { | 534 if (extension) { |
| 504 MediaGalleryScanResult file_counts; | 535 MediaGalleryScanResult file_counts; |
| 505 int gallery_count = CountScanResultsForExtension(preferences, extension, | 536 int gallery_count = CountScanResultsForExtension(preferences, extension, |
| 506 &file_counts); | 537 &file_counts); |
| 507 scans_for_profile->second.observer->OnScanFinished(*extension_id_it, | 538 scans_for_profile->second.observer->OnScanFinished(*extension_id_it, |
| 508 gallery_count, | 539 gallery_count, |
| 509 file_counts); | 540 file_counts); |
| 510 } | 541 } |
| 511 } | 542 } |
| 512 scanning_extensions->clear(); | 543 scanning_extensions->clear(); |
| 513 preferences->SetLastScanCompletionTime(base::Time::Now()); | 544 preferences->SetLastScanCompletionTime(base::Time::Now()); |
| 514 } | 545 } |
| 515 scoped_extension_registry_observer_.RemoveAll(); | 546 scoped_extension_registry_observer_.RemoveAll(); |
| 516 folder_finder_.reset(); | 547 folder_finder_.reset(); |
| 517 } | 548 } |
| OLD | NEW |