1 // Copyright 2013 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.
5 #include "chrome/browser/media_galleries/fileapi/iapps_finder_impl.h"
8 #include "base/files/file_util.h"
9 #include "base/logging.h"
10 #import "base/mac/foundation_util.h"
11 #import "base/mac/scoped_nsobject.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "base/time/time.h"
14 #include "components/policy/core/common/preferences_mac.h"
15 #include "components/storage_monitor/storage_info.h"
16 #include "content/public/browser/browser_thread.h"
18 using base::mac::CFCast;
19 using base::mac::CFToNSCast;
20 using base::mac::NSToCFCast;
26 typedef base::Callback<base::FilePath(NSString*)> PListPathExtractor;
28 static MacPreferences* g_test_mac_preferences = NULL;
30 void FindMostRecentDatabase(
31 base::scoped_nsobject<NSString> recent_databases_key,
32 const PListPathExtractor& path_extractor,
33 const IAppsFinderCallback& callback) {
34 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
36 scoped_ptr<MacPreferences> real_preferences;
37 MacPreferences* prefs = g_test_mac_preferences;
39 real_preferences.reset(new MacPreferences());
40 prefs = real_preferences.get();
43 CFStringRef iapp_id = CFSTR("com.apple.iApps");
44 base::scoped_nsobject<NSArray> plist(CFToNSCast(CFCast<CFArrayRef>(
45 prefs->CopyAppValue(NSToCFCast(recent_databases_key.get()), iapp_id))));
47 callback.Run(std::string());
51 // Find the most recently used database from the list of database paths. Most
52 // of the time |plist| has a size of 1.
53 base::Time most_recent_db_time;
54 base::FilePath most_recent_db_path;
55 for (NSString* path_ns in plist.get()) {
56 base::FilePath db_path = path_extractor.Run(path_ns);
60 base::File::Info file_info;
61 if (!base::GetFileInfo(db_path, &file_info))
64 // In case of two databases with the same modified time, tie breaker goes
65 // to the first one on the list.
66 if (file_info.last_modified <= most_recent_db_time)
69 most_recent_db_time = file_info.last_modified;
70 most_recent_db_path = db_path;
72 callback.Run(most_recent_db_path.value());
75 base::FilePath ExtractIPhotoPath(NSString* path_ns) {
76 NSURL* url = [NSURL URLWithString:path_ns];
78 return base::FilePath();
80 NSString* expanded_path_ns = [url path];
81 return base::mac::NSStringToFilePath(expanded_path_ns);
84 base::FilePath ExtractITunesPath(NSString* path_ns) {
85 NSString* expanded_path_ns = [path_ns stringByExpandingTildeInPath];
86 return base::mac::NSStringToFilePath(expanded_path_ns);
91 NSString* const kIPhotoRecentDatabasesKey = @"iPhotoRecentDatabases";
92 NSString* const kITunesRecentDatabasePathsKey = @"iTunesRecentDatabasePaths";
94 void FindIPhotoLibrary(const IAppsFinderCallback& callback) {
95 FindIAppsOnFileThread(
96 storage_monitor::StorageInfo::IPHOTO,
97 base::Bind(&FindMostRecentDatabase,
98 base::scoped_nsobject<NSString>(kIPhotoRecentDatabasesKey),
99 base::Bind(&ExtractIPhotoPath)),
103 void FindITunesLibrary(const IAppsFinderCallback& callback) {
104 FindIAppsOnFileThread(
105 storage_monitor::StorageInfo::ITUNES,
106 base::Bind(&FindMostRecentDatabase,
107 base::scoped_nsobject<NSString>(kITunesRecentDatabasePathsKey),
108 base::Bind(&ExtractITunesPath)),
112 void SetMacPreferencesForTesting(MacPreferences* preferences) {
113 g_test_mac_preferences = preferences;
116 NSArray* NSArrayFromFilePath(const base::FilePath& path) {
118 [[NSURL fileURLWithPath:base::SysUTF8ToNSString(path.value())]
120 return [NSArray arrayWithObject:url];