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

Side by Side Diff: chrome/browser/media_galleries/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: Constants &c Created 7 years, 8 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_galleries/mac/mtp_device_delegate_impl_mac.h" 5 #include "chrome/browser/media_galleries/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_galleries/mtp_device_delegate_impl.h" 9 #include "chrome/browser/media_galleries/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"
16 15
17 namespace chrome { 16 namespace chrome {
18 17
18 namespace {
19
20 int kReadDirectoryTimeLimitSeconds = 20;
21
22 using fileapi::MTPDeviceAsyncDelegate;
23 typedef MTPDeviceAsyncDelegate::CreateSnapshotFileSuccessCallback
24 CreateSnapshotFileSuccessCallback;
25 typedef MTPDeviceAsyncDelegate::ErrorCallback ErrorCallback;
26 typedef MTPDeviceAsyncDelegate::GetFileInfoSuccessCallback
27 GetFileInfoSuccessCallback;
28 typedef MTPDeviceAsyncDelegate::ReadDirectorySuccessCallback
29 ReadDirectorySuccessCallback;
30
31 } // namespace
32
19 // This class handles the UI-thread hand-offs needed to interface 33 // This class handles the UI-thread hand-offs needed to interface
20 // with the ImageCapture library. It will forward callbacks to 34 // with the ImageCapture library. It will forward callbacks to
21 // its delegate on the task runner with which it is created. All 35 // 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 36 // interactions with it are done on the UI thread, but it may be
23 // created/destroyed on another thread. 37 // created/destroyed on another thread.
24 class MTPDeviceDelegateImplMac::DeviceListener 38 class MTPDeviceDelegateImplMac::DeviceListener
25 : public ImageCaptureDeviceListener, 39 : public ImageCaptureDeviceListener,
26 public base::SupportsWeakPtr<DeviceListener> { 40 public base::SupportsWeakPtr<DeviceListener> {
27 public: 41 public:
28 DeviceListener(MTPDeviceDelegateImplMac* delegate) 42 DeviceListener(MTPDeviceDelegateImplMac* delegate)
29 : delegate_(delegate) {} 43 : delegate_(delegate) {}
30 virtual ~DeviceListener() {} 44 virtual ~DeviceListener() {}
31 45
32 void OpenCameraSession(const std::string& device_id); 46 void OpenCameraSession(const std::string& device_id);
33 void CloseCameraSessionAndDelete(); 47 void CloseCameraSessionAndDelete();
34 48
35 void DownloadFile(const std::string& name, const base::FilePath& local_path); 49 void DownloadFile(const std::string& name, const base::FilePath& local_path);
36 50
37 // ImageCaptureDeviceListener 51 // ImageCaptureDeviceListener
38 virtual void ItemAdded(const std::string& name, 52 virtual void ItemAdded(const std::string& name,
39 const base::PlatformFileInfo& info) OVERRIDE; 53 const base::PlatformFileInfo& info) OVERRIDE;
40 virtual void NoMoreItems() OVERRIDE; 54 virtual void NoMoreItems() OVERRIDE;
41 virtual void DownloadedFile(const std::string& name, 55 virtual void DownloadedFile(const std::string& name,
42 base::PlatformFileError error) OVERRIDE; 56 base::PlatformFileError error) OVERRIDE;
43 virtual void DeviceRemoved() OVERRIDE; 57 virtual void DeviceRemoved() OVERRIDE;
44 58
59 // Used during delegate destruction to ensure there are no more calls
60 // to the delegate by the listener.
61 virtual void ResetDelegate();
62
45 private: 63 private:
46 scoped_nsobject<ImageCaptureDevice> camera_device_; 64 scoped_nsobject<ImageCaptureDevice> camera_device_;
47 65
48 // Weak pointer 66 // Weak pointer
49 MTPDeviceDelegateImplMac* delegate_; 67 MTPDeviceDelegateImplMac* delegate_;
50 68
51 DISALLOW_COPY_AND_ASSIGN(DeviceListener); 69 DISALLOW_COPY_AND_ASSIGN(DeviceListener);
52 }; 70 };
53 71
54 void MTPDeviceDelegateImplMac::DeviceListener::OpenCameraSession( 72 void MTPDeviceDelegateImplMac::DeviceListener::OpenCameraSession(
(...skipping 13 matching lines...) Expand all
68 86
69 void MTPDeviceDelegateImplMac::DeviceListener::DownloadFile( 87 void MTPDeviceDelegateImplMac::DeviceListener::DownloadFile(
70 const std::string& name, 88 const std::string& name,
71 const base::FilePath& local_path) { 89 const base::FilePath& local_path) {
72 [camera_device_ downloadFile:name localPath:local_path]; 90 [camera_device_ downloadFile:name localPath:local_path];
73 } 91 }
74 92
75 void MTPDeviceDelegateImplMac::DeviceListener::ItemAdded( 93 void MTPDeviceDelegateImplMac::DeviceListener::ItemAdded(
76 const std::string& name, 94 const std::string& name,
77 const base::PlatformFileInfo& info) { 95 const base::PlatformFileInfo& info) {
78 delegate_->ItemAdded(name, info); 96 if (delegate_)
97 delegate_->ItemAdded(name, info);
79 } 98 }
80 99
81 void MTPDeviceDelegateImplMac::DeviceListener::NoMoreItems() { 100 void MTPDeviceDelegateImplMac::DeviceListener::NoMoreItems() {
82 delegate_->NoMoreItems(); 101 if (delegate_)
102 delegate_->NoMoreItems();
83 } 103 }
84 104
85 void MTPDeviceDelegateImplMac::DeviceListener::DownloadedFile( 105 void MTPDeviceDelegateImplMac::DeviceListener::DownloadedFile(
86 const std::string& name, 106 const std::string& name,
87 base::PlatformFileError error) { 107 base::PlatformFileError error) {
88 delegate_->DownloadedFile(name, error); 108 if (delegate_)
109 delegate_->DownloadedFile(name, error);
89 } 110 }
90 111
91 void MTPDeviceDelegateImplMac::DeviceListener::DeviceRemoved() { 112 void MTPDeviceDelegateImplMac::DeviceListener::DeviceRemoved() {
92 [camera_device_ close]; 113 [camera_device_ close];
93 camera_device_.reset(); 114 camera_device_.reset();
115 if (delegate_)
116 delegate_->NoMoreItems();
117 }
118
119 void MTPDeviceDelegateImplMac::DeviceListener::ResetDelegate() {
120 delegate_ = NULL;
94 } 121 }
95 122
96 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac( 123 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac(
97 const std::string& device_id, 124 const std::string& device_id,
98 const base::FilePath::StringType& synthetic_path, 125 const base::FilePath::StringType& synthetic_path)
99 base::SequencedTaskRunner* media_task_runner)
100 : device_id_(device_id), 126 : device_id_(device_id),
101 root_path_(synthetic_path), 127 root_path_(synthetic_path),
102 media_task_runner_(media_task_runner), 128 received_all_files_(false),
103 enumerator_(NULL), 129 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
104 file_download_event_(NULL),
105 file_download_error_(base::PLATFORM_FILE_OK),
106 received_all_files_(false) {
107 130
108 // Make a synthetic entry for the root of the filesystem. 131 // Make a synthetic entry for the root of the filesystem.
109 base::PlatformFileInfo info; 132 base::PlatformFileInfo info;
110 info.is_directory = true; 133 info.is_directory = true;
111 file_info_[root_path_.value()] = info; 134 file_info_[root_path_.value()] = info;
112 135
113 camera_interface_.reset(new DeviceListener(this)); 136 camera_interface_.reset(new DeviceListener(this));
114 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 137 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
115 base::Bind(&DeviceListener::OpenCameraSession, 138 base::Bind(&DeviceListener::OpenCameraSession,
116 base::Unretained(camera_interface_.get()), 139 base::Unretained(camera_interface_.get()),
117 device_id_)); 140 device_id_));
118 } 141 }
119 142
120 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() { 143 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() {
121 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
122 DCHECK(enumerator_ == NULL);
123 } 144 }
124 145
125 base::PlatformFileError MTPDeviceDelegateImplMac::GetFileInfo( 146 namespace {
147
148 void ForwardGetFileInfo(
149 base::PlatformFileInfo* info,
150 base::PlatformFileError* error,
151 const GetFileInfoSuccessCallback& success_callback,
152 const ErrorCallback& error_callback) {
153 if (*error == base::PLATFORM_FILE_OK) {
154 success_callback.Run(*info);
155 } else {
156 error_callback.Run(*error);
157 }
kinuko 2013/04/05 07:51:21 nit: no need of { } for one-line body in chromium
Greg Billock 2013/04/05 16:23:14 Done.
158 }
159
160 } // namespace
161
162 void MTPDeviceDelegateImplMac::GetFileInfo(
126 const base::FilePath& file_path, 163 const base::FilePath& file_path,
127 base::PlatformFileInfo* file_info) { 164 const GetFileInfoSuccessCallback& success_callback,
128 base::AutoLock lock(mutex_); 165 const ErrorCallback& error_callback) {
166 base::PlatformFileInfo* info = new base::PlatformFileInfo;
167 base::PlatformFileError* error = new base::PlatformFileError;
168 // Note: ownership of these objects passed into the reply callback.
169 content::BrowserThread::PostTaskAndReply(content::BrowserThread::UI,
170 FROM_HERE,
171 base::Bind(&MTPDeviceDelegateImplMac::GetFileInfoImpl,
172 base::Unretained(this), file_path, info, error),
173 base::Bind(&ForwardGetFileInfo,
174 base::Owned(info), base::Owned(error),
175 success_callback, error_callback));
176 }
177
178 void MTPDeviceDelegateImplMac::ReadDirectory(
179 const base::FilePath& root,
180 const ReadDirectorySuccessCallback& success_callback,
181 const ErrorCallback& error_callback) {
182 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
183 base::Bind(&MTPDeviceDelegateImplMac::ReadDirectoryImpl,
184 base::Unretained(this),
185 root, success_callback, error_callback));
186 }
187
188 void MTPDeviceDelegateImplMac::CreateSnapshotFile(
189 const base::FilePath& device_file_path,
190 const base::FilePath& local_path,
191 const CreateSnapshotFileSuccessCallback& success_callback,
192 const ErrorCallback& error_callback) {
193 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
194 base::Bind(&MTPDeviceDelegateImplMac::DownloadFile,
195 base::Unretained(this),
196 device_file_path, local_path,
197 success_callback, error_callback));
198 }
199
200 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() {
201 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
202 base::Bind(&MTPDeviceDelegateImplMac::CancelAndDelete,
203 base::Unretained(this)));
204 }
205
206 void MTPDeviceDelegateImplMac::GetFileInfoImpl(
207 const base::FilePath& file_path,
208 base::PlatformFileInfo* file_info,
209 base::PlatformFileError* error) {
210 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
129 base::hash_map<base::FilePath::StringType, 211 base::hash_map<base::FilePath::StringType,
130 base::PlatformFileInfo>::const_iterator i = 212 base::PlatformFileInfo>::const_iterator i =
131 file_info_.find(file_path.value()); 213 file_info_.find(file_path.value());
132 if (i == file_info_.end()) 214 if (i == file_info_.end()) {
133 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 215 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
134 216 return;
217 }
135 *file_info = i->second; 218 *file_info = i->second;
136 return base::PLATFORM_FILE_OK; 219 *error = base::PLATFORM_FILE_OK;
137 } 220 }
138 221
139 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> 222 void MTPDeviceDelegateImplMac::ReadDirectoryImpl(
140 MTPDeviceDelegateImplMac::CreateFileEnumerator(const base::FilePath& root, 223 const base::FilePath& root,
141 bool recursive) { 224 const ReadDirectorySuccessCallback& success_callback,
142 base::AutoLock lock(mutex_); 225 const ErrorCallback& error_callback) {
143 DCHECK(!enumerator_); 226 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
144 enumerator_ = new Enumerator(this); 227
145 return make_scoped_ptr(enumerator_) 228 read_dir_transactions_.push_back(ReadDirectoryRequest(
146 .PassAs<fileapi::FileSystemFileUtil::AbstractFileEnumerator>(); 229 root, success_callback, error_callback));
230
231 if (received_all_files_) {
232 NotifyReadDir();
233 return;
234 }
235
236 // Schedule a timeout in case the directory read doesn't complete.
237 content::BrowserThread::PostDelayedTask(
238 content::BrowserThread::UI, FROM_HERE,
239 base::Bind(&MTPDeviceDelegateImplMac::ReadDirectoryTimeout,
240 weak_factory_.GetWeakPtr(), root),
241 base::TimeDelta::FromSeconds(kReadDirectoryTimeLimitSeconds));
147 } 242 }
148 243
149 base::PlatformFileError MTPDeviceDelegateImplMac::CreateSnapshotFile( 244 void MTPDeviceDelegateImplMac::ReadDirectoryTimeout(
150 const base::FilePath& device_file_path, 245 const base::FilePath& root) {
151 const base::FilePath& local_path, 246 if (received_all_files_)
152 base::PlatformFileInfo* file_info) { 247 return;
153 base::PlatformFileError error = GetFileInfo(device_file_path, file_info);
154 if (error != base::PLATFORM_FILE_OK)
155 return error;
156 248
157 // Set up to wait for download. Callers are ensuring this particular function 249 for (ReadDirTransactionList::iterator iter = read_dir_transactions_.begin();
158 // will not be re-entered. 250 iter != read_dir_transactions_.end();) {
159 base::WaitableEvent waiter(true, false); 251 if (iter->directory != root) {
160 { 252 iter++;
161 base::AutoLock lock(mutex_); 253 continue;
162 DCHECK(file_download_event_ == NULL); 254 }
163 file_download_event_ = &waiter; 255 iter->error_callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
256 iter = read_dir_transactions_.erase(iter);
257 }
258 }
259
260 void MTPDeviceDelegateImplMac::DownloadFile(
261 const base::FilePath& device_file_path,
262 const base::FilePath& local_path,
263 const CreateSnapshotFileSuccessCallback& success_callback,
264 const ErrorCallback& error_callback) {
265 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
266
267 base::PlatformFileError error;
268 base::PlatformFileInfo info;
269 GetFileInfoImpl(device_file_path, &info, &error);
270 if (error != base::PLATFORM_FILE_OK) {
271 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
272 base::Bind(error_callback,
273 error));
274 return;
164 } 275 }
165 276
166 // Start the download in the UI thread. 277 read_file_transactions_[device_file_path.BaseName().value()] =
167 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 278 std::make_pair(success_callback, error_callback);
168 base::Bind(&DeviceListener::DownloadFile, 279 camera_interface_->DownloadFile(device_file_path.BaseName().value(),
169 base::Unretained(camera_interface_.get()), 280 local_path);
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 } 281 }
184 282
185 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() { 283 void MTPDeviceDelegateImplMac::CancelAndDelete() {
284 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
186 // Artificially pretend that we have already gotten all items we're going 285 // Artificially pretend that we have already gotten all items we're going
187 // to get. 286 // to get.
188 NoMoreItems(); 287 NoMoreItems();
189 288
190 { 289 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 290
199 // Schedule the camera session to be closed and the interface deleted. 291 // Schedule the camera session to be closed and the interface deleted.
292 camera_interface_->ResetDelegate();
200 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 293 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
201 base::Bind(&DeviceListener::CloseCameraSessionAndDelete, 294 base::Bind(&DeviceListener::CloseCameraSessionAndDelete,
202 base::Unretained(camera_interface_.release()))); 295 base::Unretained(camera_interface_.release())));
203 296
204 media_task_runner_->DeleteSoon(FROM_HERE, this); 297 delete this;
205 } 298 }
206 299
300 void MTPDeviceDelegateImplMac::CancelDownloads() {
301 // Cancel any outstanding callbacks.
302 for (ReadFileTransactionMap::iterator iter = read_file_transactions_.begin();
303 iter != read_file_transactions_.end(); ++iter) {
304 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
305 base::Bind(iter->second.second, base::PLATFORM_FILE_ERROR_ABORT));
306 }
307 read_file_transactions_.clear();
308
309 for (ReadDirTransactionList::iterator iter = read_dir_transactions_.begin();
310 iter != read_dir_transactions_.end(); ++iter) {
311 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
312 base::Bind(iter->error_callback, base::PLATFORM_FILE_ERROR_ABORT));
313 }
314 read_dir_transactions_.clear();
315
316 // TODO(gbillock): ImageCapture currently offers no way to cancel
317 // in-progress downloads.
318 }
319
320 // Called on the UI thread by the listener
207 void MTPDeviceDelegateImplMac::ItemAdded( 321 void MTPDeviceDelegateImplMac::ItemAdded(
208 const std::string& name, const base::PlatformFileInfo& info) { 322 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_) 323 if (received_all_files_)
215 return; 324 return;
216 325
217 // TODO(gbillock): Currently we flatten all files into a single 326 // TODO(gbillock): Currently we flatten all files into a single
218 // directory. That's pretty much how PTP devices work, but if we want 327 // directory. That's pretty much how PTP devices work, but if we want
219 // to support ImageCapture for USB, we need to change this. 328 // to support ImageCapture for USB, we need to change this.
220 if (info.is_directory) 329 if (info.is_directory)
221 return; 330 return;
222 331
223 base::FilePath item_filename = root_path_.Append(name); 332 base::FilePath item_filename = root_path_.Append(name);
224 file_info_[item_filename.value()] = info; 333 file_info_[item_filename.value()] = info;
225 file_paths_.push_back(item_filename); 334 file_paths_.push_back(item_filename);
226 335
227 if (enumerator_) 336 // TODO(gbillock): Should we send new files to
228 enumerator_->ItemsChanged(); 337 // read_dir_transactions_ callbacks?
229 } 338 }
230 339
340 // Called in the UI thread by delegate.
231 void MTPDeviceDelegateImplMac::NoMoreItems() { 341 void MTPDeviceDelegateImplMac::NoMoreItems() {
232 base::AutoLock lock(mutex_);
233 received_all_files_ = true; 342 received_all_files_ = true;
234 343 NotifyReadDir();
235 if (enumerator_)
236 enumerator_->ItemsChanged();
237 } 344 }
238 345
346 void MTPDeviceDelegateImplMac::NotifyReadDir() {
347 // Note: this assumes the only directory read we get is for the root.
348 // When this class supports directory hierarchies, this will change.
349 for (ReadDirTransactionList::iterator iter = read_dir_transactions_.begin();
350 iter != read_dir_transactions_.end(); ++iter) {
351 fileapi::AsyncFileUtil::EntryList entry_list;
352 for (size_t i = 0; i < file_paths_.size(); ++i) {
353 base::PlatformFileInfo info = file_info_[file_paths_[i].value()];
354 base::FileUtilProxy::Entry entry;
355 entry.name = file_paths_[i].value();
356 entry.is_directory = info.is_directory;
357 entry.size = info.size;
358 entry.last_modified_time = info.last_modified;
359 entry_list.push_back(entry);
360 }
361 content::BrowserThread::PostTask(content::BrowserThread::IO,
362 FROM_HERE,
363 base::Bind(iter->success_callback, entry_list, false));
364 }
365 }
366
367 // Invoked on UI thread from the listener.
239 void MTPDeviceDelegateImplMac::DownloadedFile( 368 void MTPDeviceDelegateImplMac::DownloadedFile(
240 const std::string& name, base::PlatformFileError error) { 369 const std::string& name, base::PlatformFileError error) {
241 // If we're cancelled and deleting, we have already signaled all enumerators. 370 // If we're cancelled and deleting, we may have deleted the camera.
242 if (!camera_interface_.get()) 371 if (!camera_interface_.get())
243 return; 372 return;
244 373
245 base::AutoLock lock(mutex_); 374 ReadFileTransactionMap::iterator iter = read_file_transactions_.find(name);
246 file_download_error_ = error; 375 if (iter == read_file_transactions_.end())
247 file_download_event_->Signal(); 376 return;
377
378 if (error != base::PLATFORM_FILE_OK) {
379 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
380 base::Bind(iter->second.second, error));
381 read_file_transactions_.erase(iter);
382 return;
383 }
384
385 base::PlatformFileInfo info = file_info_[name];
386 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
387 base::Bind(iter->second.first, info, base::FilePath(name)));
388 read_file_transactions_.erase(iter);
248 } 389 }
249 390
250 base::FilePath MTPDeviceDelegateImplMac::GetFile(size_t index) { 391 MTPDeviceDelegateImplMac::ReadDirectoryRequest::ReadDirectoryRequest(
251 base::AutoLock lock(mutex_); 392 const base::FilePath& dir,
252 if (index >= file_paths_.size()) 393 ReadDirectorySuccessCallback success_cb,
253 return base::FilePath(); 394 ErrorCallback error_cb)
254 else 395 : directory(dir),
255 return file_paths_[index]; 396 success_callback(success_cb),
256 } 397 error_callback(error_cb) {}
257 398
258 bool MTPDeviceDelegateImplMac::ReceivedAllFiles() { 399 MTPDeviceDelegateImplMac::ReadDirectoryRequest::~ReadDirectoryRequest() {}
259 base::AutoLock lock(mutex_);
260 return received_all_files_;
261 }
262 400
263 void MTPDeviceDelegateImplMac::RemoveEnumerator(Enumerator* enumerator) { 401 void CreateMTPDeviceAsyncDelegate(
264 base::AutoLock lock(mutex_); 402 const base::FilePath::StringType& device_location,
265 DCHECK(enumerator_ == enumerator); 403 const CreateMTPDeviceAsyncDelegateCallback& cb) {
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(); 404 std::string device_name = base::FilePath(device_location).BaseName().value();
316 std::string device_id; 405 std::string device_id;
317 MediaStorageUtil::Type type; 406 MediaStorageUtil::Type type;
318 bool cracked = MediaStorageUtil::CrackDeviceId(device_name, 407 bool cracked = MediaStorageUtil::CrackDeviceId(device_name,
319 &type, &device_id); 408 &type, &device_id);
320 DCHECK(cracked); 409 DCHECK(cracked);
321 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type); 410 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type);
322 411
323 cb.Run(new MTPDeviceDelegateImplMac(device_id, device_location, 412 cb.Run(new MTPDeviceDelegateImplMac(device_id, device_location));
324 media_task_runner));
325 } 413 }
326 414
327 } // namespace chrome 415 } // namespace chrome
328 416
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698