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

Side by Side Diff: chrome/browser/media_gallery/mac/mtp_device_delegate_impl_mac.mm

Issue 12255023: [Media Galleries] Switch Mac MTP delegate to async interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: No log lines Created 7 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_gallery/mac/mtp_device_delegate_impl_mac.h" 5 #include "chrome/browser/media_gallery/mac/mtp_device_delegate_impl_mac.h"
6 6
7 #include "base/memory/scoped_nsobject.h" 7 #include "base/memory/scoped_nsobject.h"
8 #include "base/sequenced_task_runner.h"
9 #include "base/sequenced_task_runner_helpers.h"
10 #include "base/threading/sequenced_worker_pool.h" 8 #include "base/threading/sequenced_worker_pool.h"
11 #include "chrome/browser/media_gallery/mtp_device_delegate_impl.h" 9 #include "chrome/browser/media_gallery/mtp_device_delegate_impl.h"
12 #include "chrome/browser/storage_monitor/image_capture_device.h" 10 #include "chrome/browser/storage_monitor/image_capture_device.h"
13 #include "chrome/browser/storage_monitor/image_capture_device_manager.h" 11 #include "chrome/browser/storage_monitor/image_capture_device_manager.h"
14 #include "chrome/browser/storage_monitor/media_storage_util.h" 12 #include "chrome/browser/storage_monitor/media_storage_util.h"
15 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
14 #include "webkit/fileapi/async_file_util.h"
15
16 using fileapi::MTPDeviceAsyncDelegate;
17 typedef MTPDeviceAsyncDelegate::CreateSnapshotFileSuccessCallback
18 CreateSnapshotFileSuccessCallback;
19 typedef MTPDeviceAsyncDelegate::ErrorCallback ErrorCallback;
20 typedef MTPDeviceAsyncDelegate::GetFileInfoSuccessCallback
21 GetFileInfoSuccessCallback;
kmadhusu 2013/02/26 17:59:15 Can you declare these type definitions in an anony
Greg Billock 2013/02/26 22:02:09 Done.
22 typedef MTPDeviceAsyncDelegate::ReadDirectorySuccessCallback
23 ReadDirectorySuccessCallback;
16 24
17 namespace chrome { 25 namespace chrome {
18 26
19 // This class handles the UI-thread hand-offs needed to interface 27 // This class handles the UI-thread hand-offs needed to interface
20 // with the ImageCapture library. It will forward callbacks to 28 // with the ImageCapture library. It will forward callbacks to
21 // its delegate on the task runner with which it is created. All 29 // its delegate on the task runner with which it is created. All
22 // interactions with it are done on the UI thread, but it may be 30 // interactions with it are done on the UI thread, but it may be
23 // created/destroyed on another thread. 31 // created/destroyed on another thread.
24 class MTPDeviceDelegateImplMac::DeviceListener 32 class MTPDeviceDelegateImplMac::DeviceListener
25 : public ImageCaptureDeviceListener, 33 : public ImageCaptureDeviceListener,
26 public base::SupportsWeakPtr<DeviceListener> { 34 public base::SupportsWeakPtr<DeviceListener> {
27 public: 35 public:
28 DeviceListener(MTPDeviceDelegateImplMac* delegate) 36 DeviceListener(MTPDeviceDelegateImplMac* delegate)
29 : delegate_(delegate) {} 37 : delegate_(delegate) {}
30 virtual ~DeviceListener() {} 38 virtual ~DeviceListener() {}
31 39
32 void OpenCameraSession(const std::string& device_id); 40 void OpenCameraSession(const std::string& device_id);
33 void CloseCameraSessionAndDelete(); 41 void CloseCameraSessionAndDelete();
34 42
35 void DownloadFile(const std::string& name, const base::FilePath& local_path); 43 void DownloadFile(const std::string& name, const base::FilePath& local_path);
36 44
37 // ImageCaptureDeviceListener 45 // ImageCaptureDeviceListener
38 virtual void ItemAdded(const std::string& name, 46 virtual void ItemAdded(const std::string& name,
39 const base::PlatformFileInfo& info) OVERRIDE; 47 const base::PlatformFileInfo& info) OVERRIDE;
40 virtual void NoMoreItems() OVERRIDE; 48 virtual void NoMoreItems() OVERRIDE;
41 virtual void DownloadedFile(const std::string& name, 49 virtual void DownloadedFile(const std::string& name,
42 base::PlatformFileError error) OVERRIDE; 50 base::PlatformFileError error) OVERRIDE;
43 virtual void DeviceRemoved() OVERRIDE; 51 virtual void DeviceRemoved() OVERRIDE;
44 52
53 virtual void ResetDelegate();
kmadhusu 2013/02/26 17:59:15 OVERRIDE?
Greg Billock 2013/02/26 22:02:09 No, this isn't an ImageCaptureDeviceListener metho
54
45 private: 55 private:
46 scoped_nsobject<ImageCaptureDevice> camera_device_; 56 scoped_nsobject<ImageCaptureDevice> camera_device_;
47 57
48 // Weak pointer 58 // Weak pointer
49 MTPDeviceDelegateImplMac* delegate_; 59 MTPDeviceDelegateImplMac* delegate_;
50 60
51 DISALLOW_COPY_AND_ASSIGN(DeviceListener); 61 DISALLOW_COPY_AND_ASSIGN(DeviceListener);
52 }; 62 };
53 63
54 void MTPDeviceDelegateImplMac::DeviceListener::OpenCameraSession( 64 void MTPDeviceDelegateImplMac::DeviceListener::OpenCameraSession(
(...skipping 13 matching lines...) Expand all
68 78
69 void MTPDeviceDelegateImplMac::DeviceListener::DownloadFile( 79 void MTPDeviceDelegateImplMac::DeviceListener::DownloadFile(
70 const std::string& name, 80 const std::string& name,
71 const base::FilePath& local_path) { 81 const base::FilePath& local_path) {
72 [camera_device_ downloadFile:name localPath:local_path]; 82 [camera_device_ downloadFile:name localPath:local_path];
73 } 83 }
74 84
75 void MTPDeviceDelegateImplMac::DeviceListener::ItemAdded( 85 void MTPDeviceDelegateImplMac::DeviceListener::ItemAdded(
76 const std::string& name, 86 const std::string& name,
77 const base::PlatformFileInfo& info) { 87 const base::PlatformFileInfo& info) {
78 delegate_->ItemAdded(name, info); 88 if (delegate_)
89 delegate_->ItemAdded(name, info);
79 } 90 }
80 91
81 void MTPDeviceDelegateImplMac::DeviceListener::NoMoreItems() { 92 void MTPDeviceDelegateImplMac::DeviceListener::NoMoreItems() {
82 delegate_->NoMoreItems(); 93 if (delegate_)
94 delegate_->NoMoreItems();
83 } 95 }
84 96
85 void MTPDeviceDelegateImplMac::DeviceListener::DownloadedFile( 97 void MTPDeviceDelegateImplMac::DeviceListener::DownloadedFile(
86 const std::string& name, 98 const std::string& name,
87 base::PlatformFileError error) { 99 base::PlatformFileError error) {
88 delegate_->DownloadedFile(name, error); 100 if (delegate_)
101 delegate_->DownloadedFile(name, error);
89 } 102 }
90 103
91 void MTPDeviceDelegateImplMac::DeviceListener::DeviceRemoved() { 104 void MTPDeviceDelegateImplMac::DeviceListener::DeviceRemoved() {
92 [camera_device_ close]; 105 [camera_device_ close];
93 camera_device_.reset(); 106 camera_device_.reset();
107 if (delegate_)
108 delegate_->NoMoreItems();
109 }
110
111 void MTPDeviceDelegateImplMac::DeviceListener::ResetDelegate() {
112 delegate_ = NULL;
94 } 113 }
95 114
96 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac( 115 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac(
97 const std::string& device_id, 116 const std::string& device_id,
98 const base::FilePath::StringType& synthetic_path, 117 const base::FilePath::StringType& synthetic_path)
99 base::SequencedTaskRunner* media_task_runner)
100 : device_id_(device_id), 118 : device_id_(device_id),
101 root_path_(synthetic_path), 119 root_path_(synthetic_path),
102 media_task_runner_(media_task_runner),
103 enumerator_(NULL),
104 file_download_event_(NULL),
105 file_download_error_(base::PLATFORM_FILE_OK),
106 received_all_files_(false) { 120 received_all_files_(false) {
107 121
kmadhusu 2013/02/26 17:59:15 Please add DCHECKs in all member functions to make
Greg Billock 2013/02/26 22:02:09 The important ones are the state-modifying ones. I
108 // Make a synthetic entry for the root of the filesystem. 122 // Make a synthetic entry for the root of the filesystem.
109 base::PlatformFileInfo info; 123 base::PlatformFileInfo info;
110 info.is_directory = true; 124 info.is_directory = true;
111 file_info_[root_path_.value()] = info; 125 file_info_[root_path_.value()] = info;
112 126
113 camera_interface_.reset(new DeviceListener(this)); 127 camera_interface_.reset(new DeviceListener(this));
114 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 128 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
115 base::Bind(&DeviceListener::OpenCameraSession, 129 base::Bind(&DeviceListener::OpenCameraSession,
116 base::Unretained(camera_interface_.get()), 130 base::Unretained(camera_interface_.get()),
117 device_id_)); 131 device_id_));
118 } 132 }
119 133
120 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() { 134 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() {
121 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
122 DCHECK(enumerator_ == NULL);
123 } 135 }
124 136
125 base::PlatformFileError MTPDeviceDelegateImplMac::GetFileInfo( 137 void ForwardGetFileInfo(
kmadhusu 2013/02/26 17:59:15 Can this go to the anonymous namespace?
Greg Billock 2013/02/26 22:02:09 Done.
138 base::PlatformFileInfo* info,
139 base::PlatformFileError* error,
140 const GetFileInfoSuccessCallback& success_callback,
141 const ErrorCallback& error_callback) {
142 scoped_ptr<base::PlatformFileInfo> info_deleter(info);
143 scoped_ptr<base::PlatformFileError> error_deleter(error);
144
145 if (*error == base::PLATFORM_FILE_OK) {
146 success_callback.Run(*info);
147 } else {
148 error_callback.Run(*error);
149 }
150 }
151
152 // Called on the IO thread by the async MTP file util.
153 void MTPDeviceDelegateImplMac::GetFileInfo(
126 const base::FilePath& file_path, 154 const base::FilePath& file_path,
127 base::PlatformFileInfo* file_info) { 155 const GetFileInfoSuccessCallback& success_callback,
128 base::AutoLock lock(mutex_); 156 const ErrorCallback& error_callback) {
157 base::PlatformFileInfo* info = new base::PlatformFileInfo;
158 base::PlatformFileError* error = new base::PlatformFileError;
159 content::BrowserThread::PostTaskAndReply(content::BrowserThread::UI,
160 FROM_HERE,
161 base::Bind(&MTPDeviceDelegateImplMac::GetFileInfoImpl,
162 base::Unretained(this), file_path, info, error),
163 base::Bind(&ForwardGetFileInfo,
kmadhusu 2013/02/26 17:59:15 Why this closure is not owning |error| and |info|?
Greg Billock 2013/02/26 22:02:09 There aren't good copy constructors for PlatformFi
164 info, error, success_callback, error_callback));
165 }
166
167 void MTPDeviceDelegateImplMac::GetFileInfoImpl(
168 const base::FilePath& file_path,
169 base::PlatformFileInfo* file_info,
170 base::PlatformFileError* error) {
129 base::hash_map<base::FilePath::StringType, 171 base::hash_map<base::FilePath::StringType,
130 base::PlatformFileInfo>::const_iterator i = 172 base::PlatformFileInfo>::const_iterator i =
131 file_info_.find(file_path.value()); 173 file_info_.find(file_path.value());
132 if (i == file_info_.end()) 174 if (i == file_info_.end()) {
133 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 175 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
134 176 return;
177 }
135 *file_info = i->second; 178 *file_info = i->second;
136 return base::PLATFORM_FILE_OK; 179 *error = base::PLATFORM_FILE_OK;
137 } 180 }
138 181
139 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> 182 // Called on the IO thread by the async MTP file util.
kmadhusu 2013/02/26 17:59:15 Please remove the comment and add a DCHECK in func
Greg Billock 2013/02/26 22:02:09 Added DCHECK to the UI thread functions.
140 MTPDeviceDelegateImplMac::CreateFileEnumerator(const base::FilePath& root, 183 void MTPDeviceDelegateImplMac::ReadDirectory(
141 bool recursive) { 184 const base::FilePath& root,
142 base::AutoLock lock(mutex_); 185 const ReadDirectorySuccessCallback& success_callback,
143 DCHECK(!enumerator_); 186 const ErrorCallback& error_callback) {
144 enumerator_ = new Enumerator(this); 187 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
145 return make_scoped_ptr(enumerator_) 188 base::Bind(&MTPDeviceDelegateImplMac::ReadDirectoryImpl,
146 .PassAs<fileapi::FileSystemFileUtil::AbstractFileEnumerator>(); 189 base::Unretained(this),
kmadhusu 2013/02/26 17:59:15 By using "base::Unretained(this)" in a bind call,
Greg Billock 2013/02/26 22:02:09 Yes. I added a note in the header that the owner i
190 root, success_callback, error_callback));
147 } 191 }
148 192
149 base::PlatformFileError MTPDeviceDelegateImplMac::CreateSnapshotFile( 193 void MTPDeviceDelegateImplMac::ReadDirectoryImpl(
kmadhusu 2013/02/26 17:59:15 This class is currently accessed on multiple threa
Greg Billock 2013/02/26 22:02:09 The IO-called methods don't do any state mutation
150 const base::FilePath& device_file_path, 194 const base::FilePath& root,
151 const base::FilePath& local_path, 195 const ReadDirectorySuccessCallback& success_callback,
152 base::PlatformFileInfo* file_info) { 196 const ErrorCallback& error_callback) {
153 base::PlatformFileError error = GetFileInfo(device_file_path, file_info); 197 read_directory_success_callback_ = success_callback;
154 if (error != base::PLATFORM_FILE_OK) 198 read_directory_error_callback_ = error_callback;
155 return error;
156 199
157 // Set up to wait for download. Callers are ensuring this particular function 200 if (received_all_files_)
158 // will not be re-entered. 201 NotifyReadDir();
159 base::WaitableEvent waiter(true, false); 202
160 { 203 // TODO(gbillock): Need to add a task on a timeout or something for
161 base::AutoLock lock(mutex_); 204 // the read dir failure?
162 DCHECK(file_download_event_ == NULL); 205 }
163 file_download_event_ = &waiter; 206
207 // Called on the IO thread by the async MTP file util.
208 void MTPDeviceDelegateImplMac::CreateSnapshotFile(
209 const base::FilePath& device_file_path,
210 const base::FilePath& local_path,
211 const CreateSnapshotFileSuccessCallback& success_callback,
212 const ErrorCallback& error_callback) {
213 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
214 base::Bind(&MTPDeviceDelegateImplMac::DownloadFile,
215 base::Unretained(this),
216 device_file_path, local_path,
217 success_callback, error_callback));
218 }
219
220 void MTPDeviceDelegateImplMac::DownloadFile(
221 const base::FilePath& device_file_path,
222 const base::FilePath& local_path,
223 const CreateSnapshotFileSuccessCallback& success_callback,
224 const ErrorCallback& error_callback) {
225 read_file_success_callback_ = success_callback;
226 read_file_error_callback_ = error_callback;
227
228 base::PlatformFileError error;
229 base::PlatformFileInfo info;
230 GetFileInfoImpl(device_file_path, &info, &error);
231 if (error != base::PLATFORM_FILE_OK) {
232 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
233 base::Bind(read_file_error_callback_,
234 error));
235 read_file_success_callback_.Reset();
236 read_file_error_callback_.Reset();
237 return;
164 } 238 }
165 239
166 // Start the download in the UI thread. 240 camera_interface_->DownloadFile(device_file_path.BaseName().value(),
167 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 241 local_path);
168 base::Bind(&DeviceListener::DownloadFile,
169 base::Unretained(camera_interface_.get()),
170 device_file_path.BaseName().value(), local_path));
171 waiter.Wait();
172 {
173 base::AutoLock lock(mutex_);
174 file_download_event_ = NULL;
175 error = file_download_error_;
176 }
177
178 // Modify the last modified time to null. This prevents the time stamp
179 // verification in LocalFileStreamReader.
180 file_info->last_modified = base::Time();
181
182 return error;
183 } 242 }
184 243
185 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() { 244 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() {
245 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
246 base::Bind(&MTPDeviceDelegateImplMac::CancelAndDelete,
247 base::Unretained(this)));
248 }
249
250 void MTPDeviceDelegateImplMac::CancelAndDelete() {
186 // Artificially pretend that we have already gotten all items we're going 251 // Artificially pretend that we have already gotten all items we're going
187 // to get. 252 // to get.
188 NoMoreItems(); 253 NoMoreItems();
189 254
190 { 255 CancelDownloads();
191 base::AutoLock lock(mutex_);
192 // Artificially wake up any downloads pending with an error code.
193 if (file_download_event_) {
194 file_download_error_ = base::PLATFORM_FILE_ERROR_FAILED;
195 file_download_event_->Signal();
196 }
197 }
198 256
199 // Schedule the camera session to be closed and the interface deleted. 257 // Schedule the camera session to be closed and the interface deleted.
258 camera_interface_->ResetDelegate();
200 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 259 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
201 base::Bind(&DeviceListener::CloseCameraSessionAndDelete, 260 base::Bind(&DeviceListener::CloseCameraSessionAndDelete,
202 base::Unretained(camera_interface_.release()))); 261 base::Unretained(camera_interface_.release())));
203 262
204 media_task_runner_->DeleteSoon(FROM_HERE, this); 263 delete this;
kmadhusu 2013/02/26 17:59:15 This class object is constructed on the IO thread
Greg Billock 2013/02/26 22:02:09 I don't see that as a problem. The object is threa
205 } 264 }
206 265
266 void MTPDeviceDelegateImplMac::CancelDownloads() {
267 // TODO(gbillock): implement.
268 read_file_success_callback_.Reset();
269 read_file_error_callback_.Reset();
270 }
271
272 // Called on the UI thread by the listener
207 void MTPDeviceDelegateImplMac::ItemAdded( 273 void MTPDeviceDelegateImplMac::ItemAdded(
208 const std::string& name, const base::PlatformFileInfo& info) { 274 const std::string& name, const base::PlatformFileInfo& info) {
209 base::AutoLock lock(mutex_);
210
211 // Make sure that if we're canceled and an enumerator is awake, that
212 // it will stay consistent. May need to revisit this if we need
213 // notifications of files added after we think we're done.
214 if (received_all_files_) 275 if (received_all_files_)
215 return; 276 return;
216 277
217 // TODO(gbillock): Currently we flatten all files into a single 278 // TODO(gbillock): Currently we flatten all files into a single
218 // directory. That's pretty much how PTP devices work, but if we want 279 // directory. That's pretty much how PTP devices work, but if we want
219 // to support ImageCapture for USB, we need to change this. 280 // to support ImageCapture for USB, we need to change this.
220 if (info.is_directory) 281 if (info.is_directory)
221 return; 282 return;
222 283
223 base::FilePath item_filename = root_path_.Append(name); 284 base::FilePath item_filename = root_path_.Append(name);
224 file_info_[item_filename.value()] = info; 285 file_info_[item_filename.value()] = info;
225 file_paths_.push_back(item_filename); 286 file_paths_.push_back(item_filename);
226 287
227 if (enumerator_) 288 // TODO(gbillock): Should we send new files to
228 enumerator_->ItemsChanged(); 289 // read_directory_success_callback?
229 } 290 }
230 291
292 // Called in the UI thread by delegate.
231 void MTPDeviceDelegateImplMac::NoMoreItems() { 293 void MTPDeviceDelegateImplMac::NoMoreItems() {
232 base::AutoLock lock(mutex_);
233 received_all_files_ = true; 294 received_all_files_ = true;
234 295 NotifyReadDir();
235 if (enumerator_)
236 enumerator_->ItemsChanged();
237 } 296 }
238 297
298 void ForwardReadDir(
299 const ReadDirectorySuccessCallback& success_callback,
300 fileapi::AsyncFileUtil::EntryList* entry_list,
301 bool has_more) {
302 scoped_ptr<fileapi::AsyncFileUtil::EntryList> list_deleter(entry_list);
303 success_callback.Run(*entry_list, has_more);
304 }
305
306 void MTPDeviceDelegateImplMac::NotifyReadDir() {
307 if (!read_directory_success_callback_.is_null()) {
308 // TODO(gbillock): should we just switch to using this directly internally
309 // instead of PlatformFileInfo?
310 fileapi::AsyncFileUtil::EntryList* entry_list =
311 new fileapi::AsyncFileUtil::EntryList;
312 for (size_t i = 0; i < file_paths_.size(); ++i) {
313 base::PlatformFileInfo info = file_info_[file_paths_[i].value()];
314 base::FileUtilProxy::Entry entry;
315 entry.name = file_paths_[i].value();
316 entry.is_directory = info.is_directory;
317 entry.size = info.size;
318 entry.last_modified_time = info.last_modified;
319 entry_list->push_back(entry);
320 }
321 content::BrowserThread::PostTask(content::BrowserThread::IO,
322 FROM_HERE,
323 base::Bind(&ForwardReadDir,
324 read_directory_success_callback_, entry_list, false));
325
326 read_directory_success_callback_.Reset();
327 read_directory_error_callback_.Reset();
328 }
329 }
330
331 // Invoked on UI thread from the listener.
239 void MTPDeviceDelegateImplMac::DownloadedFile( 332 void MTPDeviceDelegateImplMac::DownloadedFile(
240 const std::string& name, base::PlatformFileError error) { 333 const std::string& name, base::PlatformFileError error) {
241 // If we're cancelled and deleting, we have already signaled all enumerators. 334 // If we're cancelled and deleting, we may have deleted the camera.
242 if (!camera_interface_.get()) 335 if (!camera_interface_.get())
243 return; 336 return;
244 337
245 base::AutoLock lock(mutex_); 338 if (!read_file_success_callback_.is_null()) {
246 file_download_error_ = error; 339 if (error == base::PLATFORM_FILE_OK) {
247 file_download_event_->Signal(); 340 base::FilePath path(name);
341 base::PlatformFileInfo info = file_info_[path.value()];
342 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
343 base::Bind(read_file_success_callback_, info, path));
344 } else {
345 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
346 base::Bind(read_file_error_callback_, error));
347 }
348 read_file_success_callback_.Reset();
349 read_file_error_callback_.Reset();
350 }
248 } 351 }
249 352
250 base::FilePath MTPDeviceDelegateImplMac::GetFile(size_t index) { 353 void CreateMTPDeviceAsyncDelegate(
251 base::AutoLock lock(mutex_); 354 const base::FilePath::StringType& device_location,
252 if (index >= file_paths_.size()) 355 const CreateMTPDeviceAsyncDelegateCallback& cb) {
253 return base::FilePath(); 356 std::string device_name =
254 else 357 base::FilePath(device_location).BaseName().value();
255 return file_paths_[index];
256 }
257
258 bool MTPDeviceDelegateImplMac::ReceivedAllFiles() {
259 base::AutoLock lock(mutex_);
260 return received_all_files_;
261 }
262
263 void MTPDeviceDelegateImplMac::RemoveEnumerator(Enumerator* enumerator) {
264 base::AutoLock lock(mutex_);
265 DCHECK(enumerator_ == enumerator);
266 enumerator_ = NULL;
267 }
268
269 MTPDeviceDelegateImplMac::Enumerator::Enumerator(
270 MTPDeviceDelegateImplMac* delegate)
271 : delegate_(delegate),
272 position_(0),
273 wait_for_items_(false, false) {}
274
275 MTPDeviceDelegateImplMac::Enumerator::~Enumerator() {
276 delegate_->RemoveEnumerator(this);
277 }
278
279 base::FilePath MTPDeviceDelegateImplMac::Enumerator::Next() {
280 base::FilePath next_file = delegate_->GetFile(position_);
281 while (next_file.empty() && !delegate_->ReceivedAllFiles()) {
282 wait_for_items_.Wait();
283 next_file = delegate_->GetFile(position_);
284 }
285
286 position_++;
287 return next_file;
288 }
289
290 int64 MTPDeviceDelegateImplMac::Enumerator::Size() {
291 base::PlatformFileInfo info;
292 delegate_->GetFileInfo(delegate_->GetFile(position_ - 1), &info);
293 return info.size;
294 }
295
296 base::Time MTPDeviceDelegateImplMac::Enumerator::LastModifiedTime() {
297 base::PlatformFileInfo info;
298 delegate_->GetFileInfo(delegate_->GetFile(position_ - 1), &info);
299 return info.last_modified;
300 }
301
302 bool MTPDeviceDelegateImplMac::Enumerator::IsDirectory() {
303 base::PlatformFileInfo info;
304 delegate_->GetFileInfo(delegate_->GetFile(position_ - 1), &info);
305 return info.is_directory;
306 }
307
308 void MTPDeviceDelegateImplMac::Enumerator::ItemsChanged() {
309 wait_for_items_.Signal();
310 }
311
312 void CreateMTPDeviceDelegate(const std::string& device_location,
313 base::SequencedTaskRunner* media_task_runner,
314 const CreateMTPDeviceDelegateCallback& cb) {
315 std::string device_name = base::FilePath(device_location).BaseName().value();
316 std::string device_id; 358 std::string device_id;
317 MediaStorageUtil::Type type; 359 MediaStorageUtil::Type type;
318 bool cracked = MediaStorageUtil::CrackDeviceId(device_name, 360 bool cracked = MediaStorageUtil::CrackDeviceId(device_name,
319 &type, &device_id); 361 &type, &device_id);
320 DCHECK(cracked); 362 DCHECK(cracked);
321 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type); 363 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type);
322 364
323 cb.Run(new MTPDeviceDelegateImplMac(device_id, device_location, 365 cb.Run(new MTPDeviceDelegateImplMac(device_id, device_location));
324 media_task_runner));
325 } 366 }
326 367
327 } // namespace chrome 368 } // namespace chrome
328 369
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698