15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/media_galleries/media_folder_finder.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <set> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_enumerator.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/path_service.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/sequence_checker.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner_util.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/api/file_system/file_system_api.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/storage_monitor.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chromeos/dbus/cros_disks_client.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using storage_monitor::StorageInfo; 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using storage_monitor::StorageMonitor; 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef base::Callback<void(const std::vector<base::FilePath>& /*roots*/)> 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DefaultScanRootsCallback; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64 kMinimumImageSize = 200 * 1024; // 200 KB 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64 kMinimumAudioSize = 500 * 1024; // 500 KB 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64 kMinimumVideoSize = 1024 * 1024; // 1 MB 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kPrunedPaths[] = { 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_IE_INTERNET_CACHE, 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_PROGRAM_FILES, 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_PROGRAM_FILESX86, 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_WINDOWS, 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_MACOSX) && !defined(OS_IOS) 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::DIR_USER_APPLICATIONS, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::DIR_USER_LIBRARY, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_LINUX) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_CACHE, 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_LINUX) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DIR_TEMP, 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsValidScanPath(const base::FilePath& path) { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !path.empty() && path.IsAbsolute(); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CountScanResult(MediaGalleryScanFileType type, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaGalleryScanResult* scan_result) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_result->image_count += 1; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_result->audio_count += 1; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_result->video_count += 1; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool FileMeetsSizeRequirement(MediaGalleryScanFileType type, int64 size) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (size >= kMinimumImageSize) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (size >= kMinimumAudioSize) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type & MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (size >= kMinimumVideoSize) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Return true if |path| should not be considered as the starting point for a 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// media scan. 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldIgnoreScanRoot(const base::FilePath& path) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_MACOSX) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Scanning root is of little value. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (path.value() == "/"); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_CHROMEOS) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sanity check to make sure mount points are where they should be. 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath mount_point = 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chromeos::CrosDisksClient::GetRemovableDiskMountPoint(); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return mount_point.IsParent(path); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_LINUX) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // /media and /mnt are likely the only places with interesting mount points. 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (StartsWithASCII(path.value(), "/media", true) || 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StartsWithASCII(path.value(), "/mnt", true)) { 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_WIN) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTIMPLEMENTED(); 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Return a location that is likely to have user data to scan, if any. 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::FilePath GetPlatformSpecificDefaultScanRoot() { 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath root; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE, &root); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_MACOSX) || defined(OS_LINUX) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PathService::Get(base::DIR_HOME, &root); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_WIN) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Nothing to add. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTIMPLEMENTED(); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return root; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Find the likely locations with user media files and pass them to 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |callback|. Locations are platform specific. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetDefaultScanRoots(const DefaultScanRootsCallback& callback, 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_override, 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::FilePath>& override_paths) { 134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (has_override) { 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(override_paths); 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StorageMonitor* monitor = StorageMonitor::GetInstance(); 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(monitor->IsInitialized()); 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<base::FilePath> roots; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<StorageInfo> storages = monitor->GetAllAvailableStorages(); 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < storages.size(); ++i) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StorageInfo::Type type; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!StorageInfo::CrackDeviceId(storages[i].device_id(), &type, NULL) || 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (type != StorageInfo::FIXED_MASS_STORAGE && 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type != StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM)) { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath path(storages[i].location()); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldIgnoreScanRoot(path)) 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) roots.push_back(path); 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath platform_root = GetPlatformSpecificDefaultScanRoot(); 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!platform_root.empty()) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) roots.push_back(platform_root); 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(roots); 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::WorkerReply::WorkerReply() {} 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::WorkerReply::~WorkerReply() {} 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The Worker is created on the UI thread, but does all its work on a blocking 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// SequencedTaskRunner. 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MediaFolderFinder::Worker { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) explicit Worker(const std::vector<base::FilePath>& graylisted_folders); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Worker(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Scans |path| and return the results. 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WorkerReply ScanFolder(const base::FilePath& path); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void MakeFolderPathsAbsolute(); 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool folder_paths_are_absolute_; 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath> graylisted_folders_; 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath> pruned_folders_; 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<MediaPathFilter> filter_; 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::SequenceChecker sequence_checker_; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Worker); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MediaFolderFinder::Worker::Worker( 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::vector<base::FilePath>& graylisted_folders) 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : folder_paths_are_absolute_(false), 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) graylisted_folders_(graylisted_folders), 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) filter_(new MediaPathFilter) { 200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < arraysize(kPrunedPaths); ++i) { 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath path; 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (PathService::Get(kPrunedPaths[i], &path)) 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pruned_folders_.push_back(path); 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sequence_checker_.DetachFromSequence(); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::Worker::~Worker() { 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::WorkerReply MediaFolderFinder::Worker::ScanFolder( 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path) { 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(IsValidScanPath(path)); 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!folder_paths_are_absolute_) 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeFolderPathsAbsolute(); 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WorkerReply reply; 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool folder_meets_size_requirement = false; 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_graylisted_folder = false; 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath abspath = base::MakeAbsoluteFilePath(path); 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (abspath.empty()) 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return reply; 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < graylisted_folders_.size(); ++i) { 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (abspath == graylisted_folders_[i] || 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) abspath.IsParent(graylisted_folders_[i])) { 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_graylisted_folder = true; 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FileEnumerator enumerator( 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) path, 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, /* recursive? */ 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_POSIX) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) | base::FileEnumerator::SHOW_SYM_LINKS // show symlinks, not follow. 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ); // NOLINT 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (!enumerator.Next().empty()) { 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath full_path = path.Append(file_info.GetName()); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (MediaPathFilter::ShouldSkip(full_path)) 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Enumerating a directory. 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (file_info.IsDirectory()) { 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_pruned_folder = false; 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath abs_full_path = base::MakeAbsoluteFilePath(full_path); 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (abs_full_path.empty()) 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < pruned_folders_.size(); ++i) { 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (abs_full_path == pruned_folders_[i]) { 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_pruned_folder = true; 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!is_pruned_folder) 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reply.new_folders.push_back(full_path); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Enumerating a file. 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Do not include scan results for graylisted folders. 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_graylisted_folder) 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaGalleryScanFileType type = filter_->GetType(full_path); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type == MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN) 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CountScanResult(type, &reply.scan_result); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!folder_meets_size_requirement) { 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) folder_meets_size_requirement = 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileMeetsSizeRequirement(type, file_info.GetSize()); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make sure there is at least 1 file above a size threshold. 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!folder_meets_size_requirement) 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reply.scan_result = MediaGalleryScanResult(); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return reply; 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MediaFolderFinder::Worker::MakeFolderPathsAbsolute() { 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!folder_paths_are_absolute_); 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) folder_paths_are_absolute_ = true; 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath> abs_paths; 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < graylisted_folders_.size(); ++i) { 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath path = base::MakeAbsoluteFilePath(graylisted_folders_[i]); 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!path.empty()) 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) abs_paths.push_back(path); 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) graylisted_folders_ = abs_paths; 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) abs_paths.clear(); 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < pruned_folders_.size(); ++i) { 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath path = base::MakeAbsoluteFilePath(pruned_folders_[i]); 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!path.empty()) 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) abs_paths.push_back(path); 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pruned_folders_ = abs_paths; 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::MediaFolderFinder( 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MediaFolderFinderResultsCallback& callback) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : results_callback_(callback), 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) graylisted_folders_( 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::file_system_api::GetGrayListedDirectories()), 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_state_(SCAN_STATE_NOT_STARTED), 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) worker_(new Worker(graylisted_folders_)), 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_roots_for_testing_(false), 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_(this) { 322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker_task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaFolderFinder::~MediaFolderFinder() { 329e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker_task_runner_->DeleteSoon(FROM_HERE, worker_); 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (scan_state_ == SCAN_STATE_FINISHED) 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaFolderFinderResults empty_results; 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results_callback_.Run(false /* success? */, empty_results); 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaFolderFinder::StartScan() { 341e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (scan_state_ != SCAN_STATE_NOT_STARTED) 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_state_ = SCAN_STATE_STARTED; 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDefaultScanRoots( 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&MediaFolderFinder::OnInitialized, weak_factory_.GetWeakPtr()), 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_roots_for_testing_, 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) roots_for_testing_); 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const std::vector<base::FilePath>& 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MediaFolderFinder::graylisted_folders() const { 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return graylisted_folders_; 356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaFolderFinder::SetRootsForTesting( 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::FilePath>& roots) { 360e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SCAN_STATE_NOT_STARTED, scan_state_); 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_roots_for_testing_ = true; 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) roots_for_testing_ = roots; 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaFolderFinder::OnInitialized( 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::FilePath>& roots) { 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<base::FilePath> valid_roots; 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < roots.size(); ++i) { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Skip if |path| is invalid or redundant. 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path = roots[i]; 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!IsValidScanPath(path)) 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ContainsKey(valid_roots, path)) 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check for overlap. 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool valid_roots_contains_path = false; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<base::FilePath> overlapping_paths_to_remove; 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::set<base::FilePath>::iterator it = valid_roots.begin(); 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != valid_roots.end(); ++it) { 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->IsParent(path)) { 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) valid_roots_contains_path = true; 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& other_path = *it; 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (path.IsParent(other_path)) 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) overlapping_paths_to_remove.push_back(other_path); 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (valid_roots_contains_path) 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remove anything |path| overlaps from |valid_roots|. 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < overlapping_paths_to_remove.size(); ++i) 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) valid_roots.erase(overlapping_paths_to_remove[i]); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) valid_roots.insert(path); 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::copy(valid_roots.begin(), valid_roots.end(), 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::back_inserter(folders_to_scan_)); 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScanFolder(); 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaFolderFinder::ScanFolder() { 408e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (folders_to_scan_.empty()) { 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scan_state_ = SCAN_STATE_FINISHED; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results_callback_.Run(true /* success? */, results_); 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath folder_to_scan = folders_to_scan_.back(); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) folders_to_scan_.pop_back(); 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::PostTaskAndReplyWithResult( 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci worker_task_runner_.get(), 4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind( 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &Worker::ScanFolder, base::Unretained(worker_), folder_to_scan), 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&MediaFolderFinder::GotScanResults, 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr(), 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) folder_to_scan)); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaFolderFinder::GotScanResults(const base::FilePath& path, 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const WorkerReply& reply) { 431e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SCAN_STATE_STARTED, scan_state_); 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!path.empty()); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(!ContainsKey(results_, path)); 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!IsEmptyScanResult(reply.scan_result)) 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results_[path] = reply.scan_result; 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Push new folders to the |folders_to_scan_| in reverse order. 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::copy(reply.new_folders.rbegin(), reply.new_folders.rend(), 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::back_inserter(folders_to_scan_)); 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScanFolder(); 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 445