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

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

Issue 11416089: [Media Galleries] Filesystem interface for Mac PTP/MTP devices using ImageCaptureCore (part 3) (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Review fixes Created 7 years, 11 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media_gallery/mac/mtp_device_delegate_impl_mac.h"
6
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"
11 #include "chrome/browser/media_gallery/mtp_device_delegate_impl.h"
12 #include "chrome/browser/system_monitor/image_capture_device.h"
13 #include "chrome/browser/system_monitor/image_capture_device_manager.h"
14 #include "chrome/browser/system_monitor/media_storage_util.h"
15 #include "content/public/browser/browser_thread.h"
16
17 namespace chrome {
18
19 // This class handles the UI-thread hand-offs needed to interface
20 // with the ImageCapture library. It will forward callbacks to
21 // 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
23 // created/destroyed on another thread.
24 class DeviceListenerImpl
25 : public ImageCaptureDeviceListener,
26 public base::SupportsWeakPtr<DeviceListenerImpl> {
27 public:
28 DeviceListenerImpl(MTPDeviceDelegateImplMac* delegate,
29 base::SequencedTaskRunner* task_runner)
30 : delegate_(delegate),
31 task_runner_(task_runner) {}
32 virtual ~DeviceListenerImpl() {}
33
34 void OpenCameraSession(const std::string& device_id);
35 void CloseCameraSessionAndDelete();
36
37 void DownloadFile(const std::string& name, const FilePath& local_path);
38
39 // ImageCaptureDeviceListener
40 virtual void ItemAdded(const std::string& name,
41 const base::PlatformFileInfo& info) OVERRIDE;
42 virtual void NoMoreItems() OVERRIDE;
43 virtual void DownloadedFile(const std::string& name,
44 base::PlatformFileError error) OVERRIDE;
45 virtual void DeviceRemoved() OVERRIDE;
46
47 private:
48 scoped_nsobject<ImageCaptureDevice> camera_device_;
49
50 // Weak pointer
51 MTPDeviceDelegateImplMac* delegate_;
52
53 // Weak pointer
54 base::SequencedTaskRunner* task_runner_;
55 };
sail 2013/01/03 23:10:43 DISALLOW_COPY_AND_ASSIGN
Greg Billock 2013/01/04 18:05:05 Done.
56
57 void DeviceListenerImpl::OpenCameraSession(const std::string& device_id) {
58 camera_device_.reset(
59 [ImageCaptureDeviceManager::deviceForUUID(device_id) retain]);
60 [camera_device_ setListener:AsWeakPtr()];
61 [camera_device_ open];
62 }
63
64 void DeviceListenerImpl::CloseCameraSessionAndDelete() {
65 [camera_device_ close];
66 [camera_device_ setListener:base::WeakPtr<DeviceListenerImpl>()];
67
68 delete this;
69 }
70
71 void DeviceListenerImpl::DownloadFile(const std::string& name,
72 const FilePath& local_path) {
73 [camera_device_ downloadFile:name localPath:local_path];
74 }
75
76 void DeviceListenerImpl::ItemAdded(const std::string& name,
77 const base::PlatformFileInfo& info) {
78 task_runner_->PostTask(FROM_HERE,
79 base::Bind(&MTPDeviceDelegateImplMac::ItemAdded,
80 base::Unretained(delegate_), name, info));
81 }
82
83 void DeviceListenerImpl::NoMoreItems() {
84 task_runner_->PostTask(FROM_HERE,
85 base::Bind(&MTPDeviceDelegateImplMac::NoMoreItems,
86 base::Unretained(delegate_)));
87 }
88
89 void DeviceListenerImpl::DownloadedFile(const std::string& name,
90 base::PlatformFileError error) {
91 task_runner_->PostTask(FROM_HERE,
92 base::Bind(&MTPDeviceDelegateImplMac::DownloadedFile,
93 base::Unretained(delegate_), name, error));
94 }
95
96 void DeviceListenerImpl::DeviceRemoved() {
97 [camera_device_ close];
98 camera_device_.reset();
99 }
100
101 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac(
102 const FilePath::StringType& location,
103 base::SequencedTaskRunner* media_task_runner)
104 : root_path_(location),
105 media_task_runner_(media_task_runner),
106 enumerator_(NULL),
107 received_all_files_(false) {
108 std::string device_id = FilePath(location).BaseName().value();
109 MediaStorageUtil::Type type;
110 bool cracked = MediaStorageUtil::CrackDeviceId(device_id, &type, &device_id_);
111 DCHECK(cracked);
112 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type);
113
114 // Make a synthetic entry for the root of the filesystem.
115 base::PlatformFileInfo info;
116 info.is_directory = true;
117 file_info_[root_path_.value()] = info;
118
119 camera_interface_.reset(new DeviceListenerImpl(this, media_task_runner));
120 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
121 base::Bind(&DeviceListenerImpl::OpenCameraSession,
122 base::Unretained(camera_interface_.get()),
123 device_id_));
124 }
125
126 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() {
127 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
128 DCHECK(enumerator_ == NULL);
129 }
130
131 base::PlatformFileError MTPDeviceDelegateImplMac::GetFileInfo(
132 const FilePath& file_path,
133 base::PlatformFileInfo* file_info) {
134 base::hash_map<FilePath::StringType,
135 base::PlatformFileInfo>::const_iterator i =
136 file_info_.find(file_path.value());
137 if (i == file_info_.end())
138 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
139
140 *file_info = i->second;
141 return base::PLATFORM_FILE_OK;
142 }
143
144 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator>
145 MTPDeviceDelegateImplMac::CreateFileEnumerator(const FilePath& root,
146 bool recursive) {
147 DCHECK(!enumerator_);
148 enumerator_ = new Enumerator(this);
149 return make_scoped_ptr(enumerator_)
150 .PassAs<fileapi::FileSystemFileUtil::AbstractFileEnumerator>();
151 }
152
153 base::PlatformFileError MTPDeviceDelegateImplMac::CreateSnapshotFile(
154 const FilePath& device_file_path,
155 const FilePath& local_path,
156 base::PlatformFileInfo* file_info) {
157 base::PlatformFileError error = GetFileInfo(device_file_path, file_info);
158 if (error != base::PLATFORM_FILE_OK)
159 return error;
160
161 // Set up to wait for download.
162 base::WaitableEvent waiter(true, false);
163 DCHECK(file_download_event_ == NULL);
164 file_download_event_ = &waiter;
165
166 // Start the download in the UI thread.
167 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
168 base::Bind(&DeviceListenerImpl::DownloadFile,
169 base::Unretained(camera_interface_.get()),
170 device_file_path.BaseName().value(), local_path));
171 waiter.Wait();
172 file_download_event_ = NULL;
173 error = file_download_error_;
174
175 // Modify the last modified time to null. This prevents the time stamp
176 // verification in LocalFileStreamReader.
177 file_info->last_modified = base::Time();
178
179 return error;
180 }
181
182 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() {
183 // Artificially pretend that we have already gotten all items we're going
184 // to get.
185 NoMoreItems();
186
187 // Artificially wake up any downloads pending with an error code.
188 if (file_download_event_) {
189 file_download_error_ = base::PLATFORM_FILE_ERROR_FAILED;
190 file_download_event_->Signal();
191 }
192
193 // Schedule the camera session to be closed and the interface deleted.
194 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
195 base::Bind(&DeviceListenerImpl::CloseCameraSessionAndDelete,
196 base::Unretained(camera_interface_.release())));
197
198 media_task_runner_->DeleteSoon(FROM_HERE, this);
199 }
200
201 void MTPDeviceDelegateImplMac::ItemAdded(
202 const std::string& name, const base::PlatformFileInfo& info) {
203 // Make sure if we're canceled and enumerators are awake, that
204 // they will stay consistent. May need to revisit this if we need
205 // notifications of files added after we think we're done.
206 if (received_all_files_)
207 return;
208
209 if (info.is_directory)
210 return;
211 FilePath fp = root_path_.Append(name);
212 file_info_[fp.value()] = info;
213 file_paths_.push_back(fp);
214
215 if (enumerator_)
216 enumerator_->ItemsChanged();
217 }
218
219 void MTPDeviceDelegateImplMac::NoMoreItems() {
220 received_all_files_ = true;
221
222 if (enumerator_)
223 enumerator_->ItemsChanged();
224 }
225
226 void MTPDeviceDelegateImplMac::DownloadedFile(
227 const std::string& name, base::PlatformFileError error) {
228 // If we're cancelled and deleting, we have already signaled all enumerators.
229 if (!camera_interface_.get())
230 return;
231
232 file_download_error_ = error;
233 file_download_event_->Signal();
234 }
235
236 FilePath MTPDeviceDelegateImplMac::GetFile(size_t index) {
237 if (index >= file_paths_.size())
238 return FilePath();
239 else
240 return file_paths_[index];
241 }
242
243 bool MTPDeviceDelegateImplMac::ReceivedAllFiles() {
244 return received_all_files_;
245 }
246
247 void MTPDeviceDelegateImplMac::RemoveEnumerator(Enumerator* enumerator) {
248 DCHECK(enumerator_ == enumerator);
249 enumerator_ = NULL;
250 }
251
252 MTPDeviceDelegateImplMac::Enumerator::Enumerator(
253 MTPDeviceDelegateImplMac* delegate)
254 : delegate_(delegate),
255 position_(0),
256 wait_for_items_(false, false) {}
257
258 MTPDeviceDelegateImplMac::Enumerator::~Enumerator() {
259 delegate_->RemoveEnumerator(this);
260 }
261
262 FilePath MTPDeviceDelegateImplMac::Enumerator::Next() {
263 FilePath fp = delegate_->GetFile(position_);
264 while (fp.empty() && !delegate_->ReceivedAllFiles()) {
265 wait_for_items_.Wait();
266 fp = delegate_->GetFile(position_);
267 }
268
269 position_++;
270 return fp;
271 }
272
273 int64 MTPDeviceDelegateImplMac::Enumerator::Size() {
274 FilePath fp = delegate_->GetFile(position_ - 1);
275 base::PlatformFileInfo info;
276 delegate_->GetFileInfo(fp, &info);
277 return info.size;
278 }
279
280 base::Time MTPDeviceDelegateImplMac::Enumerator::LastModifiedTime() {
281 FilePath fp = delegate_->GetFile(position_ - 1);
282 base::PlatformFileInfo info;
283 delegate_->GetFileInfo(fp, &info);
284 return info.last_modified;
285 }
286
287 bool MTPDeviceDelegateImplMac::Enumerator::IsDirectory() {
288 FilePath fp = delegate_->GetFile(position_ - 1);
289 base::PlatformFileInfo info;
290 delegate_->GetFileInfo(fp, &info);
291 return info.is_directory;
292 }
293
294 void MTPDeviceDelegateImplMac::Enumerator::ItemsChanged() {
295 wait_for_items_.Signal();
296 }
297
298 void CreateMTPDeviceDelegate(const std::string& device_location,
299 base::SequencedTaskRunner* media_task_runner,
300 const CreateMTPDeviceDelegateCallback& cb) {
301 cb.Run(new MTPDeviceDelegateImplMac(device_location, media_task_runner));
302 }
303
304 } // namespace chrome
305
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698