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

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: Use single enumerator Created 7 years, 12 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 CameraDeviceInterface
sail 2012/12/26 21:30:43 The "Interface" part of the name doesn't add anyth
Greg Billock 2013/01/03 22:41:32 Done, but just to "DeviceListenerImpl" to economiz
sail 2013/01/03 23:10:43 Ok.
25 : public ImageCaptureDeviceListener,
26 public base::SupportsWeakPtr<CameraDeviceInterface> {
sail 2012/12/26 21:30:43 Should avoid multiple inheritance. Use base::WeakP
Greg Billock 2013/01/03 22:41:32 Could; this is pretty common though, and easy enou
sail 2013/01/03 23:10:43 That's not a good argument. Please avoid using mul
Greg Billock 2013/01/04 18:05:05 Neither of these are good arguments. The listener
27 public:
28 CameraDeviceInterface(MTPDeviceDelegateImplMac* delegate,
29 base::SequencedTaskRunner* task_runner)
30 : delegate_(delegate),
31 task_runner_(task_runner) {}
32 virtual ~CameraDeviceInterface() {}
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 };
56
57 void CameraDeviceInterface::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 CameraDeviceInterface::CloseCameraSessionAndDelete() {
65 if (camera_device_.get()) {
sail 2012/12/26 21:30:43 don't need this, method calls to nil are no-op
Greg Billock 2013/01/03 22:41:32 Done.
66 [camera_device_ close];
67 [camera_device_ setListener:base::WeakPtr<CameraDeviceInterface>()];
68 }
69
70 delete this;
71 }
72
73 void CameraDeviceInterface::DownloadFile(const std::string& name,
74 const FilePath& local_path) {
75 [camera_device_ downloadFile:name localPath:local_path];
76 }
77
78 void CameraDeviceInterface::ItemAdded(const std::string& name,
79 const base::PlatformFileInfo& info) {
80 task_runner_->PostTask(FROM_HERE,
81 base::Bind(&MTPDeviceDelegateImplMac::ItemAdded,
82 base::Unretained(delegate_), name, info));
83 }
84
85 void CameraDeviceInterface::NoMoreItems() {
86 task_runner_->PostTask(FROM_HERE,
87 base::Bind(&MTPDeviceDelegateImplMac::NoMoreItems,
88 base::Unretained(delegate_)));
89 }
90
91 void CameraDeviceInterface::DownloadedFile(const std::string& name,
92 base::PlatformFileError error) {
93 task_runner_->PostTask(FROM_HERE,
94 base::Bind(&MTPDeviceDelegateImplMac::DownloadedFile,
95 base::Unretained(delegate_), name, error));
96 }
97
98 void CameraDeviceInterface::DeviceRemoved() {
99 [camera_device_ close];
100 camera_device_.reset();
101 }
102
103 MTPDeviceDelegateImplMac::MTPDeviceDelegateImplMac(
104 const FilePath::StringType& location,
105 base::SequencedTaskRunner* media_task_runner)
106 : root_path_(location),
107 media_task_runner_(media_task_runner),
108 received_all_files_(false) {
sail 2012/12/26 21:30:43 need to initialize enumerator_
Greg Billock 2013/01/03 22:41:32 Done.
109 std::string device_id = FilePath(location).BaseName().value();
sail 2012/12/26 21:30:43 instead of implicitly encoding the device ID in th
Greg Billock 2013/01/03 22:41:32 Yes. The machinery surrounding this doesn't allow
sail 2013/01/03 23:10:43 In that case can you move this out to the code tha
Greg Billock 2013/01/04 18:05:05 The outside code is in the File API, and introduci
sail 2013/01/08 20:16:41 Either way, it should be fixed before this can lan
Greg Billock 2013/01/16 01:15:29 Moved to the factory method. I think that's cosmet
110 MediaStorageUtil::Type type;
111 bool cracked = MediaStorageUtil::CrackDeviceId(device_id, &type, &device_id_);
112 DCHECK(cracked);
113 DCHECK_EQ(MediaStorageUtil::MAC_IMAGE_CAPTURE, type);
114
115 // Make a synthetic entry for the root of the filesystem.
116 base::PlatformFileInfo info;
117 info.is_directory = true;
118 file_info_[root_path_.value()] = info;
119
120 camera_interface_.reset(new CameraDeviceInterface(this, media_task_runner));
121 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
122 base::Bind(&CameraDeviceInterface::OpenCameraSession,
123 base::Unretained(camera_interface_.get()),
124 device_id_));
125 }
126
127 MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() {
128 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
129 DCHECK(enumerator_ == NULL);
130 }
131
132 base::PlatformFileError MTPDeviceDelegateImplMac::GetFileInfo(
133 const FilePath& file_path,
134 base::PlatformFileInfo* file_info) {
135 base::hash_map<FilePath::StringType,
136 base::PlatformFileInfo>::const_iterator i =
137 file_info_.find(file_path.value());
138 if (i != file_info_.end()) {
139 file_info->size = i->second.size;
sail 2012/12/26 21:30:43 would this work: *file_info = i->second
Greg Billock 2013/01/03 22:41:32 I think so. I thought I did that, but maybe I merg
140 file_info->is_directory = i->second.is_directory;
141 file_info->is_symbolic_link = i->second.is_symbolic_link;
142 file_info->last_modified = i->second.last_modified;
143 file_info->last_accessed = i->second.last_accessed;
144 file_info->creation_time = i->second.creation_time;
145 return base::PLATFORM_FILE_OK;
146 } else {
147 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
sail 2012/12/26 21:30:43 early return above instead?
Greg Billock 2013/01/03 22:41:32 Done.
148 }
149 }
150
151 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator>
152 MTPDeviceDelegateImplMac::CreateFileEnumerator(const FilePath& root,
153 bool recursive) {
154 DCHECK(!enumerator_);
155 enumerator_ = new Enumerator(this);
156 return make_scoped_ptr(enumerator_)
157 .PassAs<fileapi::FileSystemFileUtil::AbstractFileEnumerator>();
158 }
159
160 base::PlatformFileError MTPDeviceDelegateImplMac::CreateSnapshotFile(
161 const FilePath& device_file_path,
162 const FilePath& local_path,
163 base::PlatformFileInfo* file_info) {
164 std::string name = device_file_path.BaseName().value();
sail 2012/12/26 21:30:43 should move to first use
Greg Billock 2013/01/03 22:41:32 eliminated. I think I had earlier code that used i
165 base::PlatformFileError error = GetFileInfo(device_file_path, file_info);
166 if (error != base::PLATFORM_FILE_OK)
167 return error;
168
169 // Set up to wait for download.
170 base::WaitableEvent waiter(true, false);
171 download_events_[name] = &waiter;
172 // Start the download in the UI thread.
173 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
174 base::Bind(&CameraDeviceInterface::DownloadFile,
175 base::Unretained(camera_interface_.get()),
176 name, local_path));
177 waiter.Wait();
178 download_events_.erase(download_events_.find(name));
179 base::hash_map<std::string, base::PlatformFileError>::iterator iter =
180 download_errors_.find(name);
181 error = iter->second;
182 download_errors_.erase(iter);
183
184 // Modify the last modified time to null. This prevents the time stamp
185 // verification in LocalFileStreamReader.
186 file_info->last_modified = base::Time();
187
188 return error;
189 }
190
191 void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() {
192 // Artificially pretend that we have already gotten all items we're going
193 // to get.
194 NoMoreItems();
195
196 // Artificially wake up any downloads pending with an error code.
197 for (base::hash_map<std::string, base::WaitableEvent*>::const_iterator iter =
198 download_events_.begin(); iter != download_events_.end(); ++iter) {
199 download_errors_[iter->first] = base::PLATFORM_FILE_ERROR_FAILED;
200 iter->second->Signal();
201 }
202
203 // Schedule the camera session to be closed and the interface deleted.
204 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
205 base::Bind(&CameraDeviceInterface::CloseCameraSessionAndDelete,
206 base::Unretained(camera_interface_.release())));
207
208 media_task_runner_->DeleteSoon(FROM_HERE, this);
209 }
210
211 void MTPDeviceDelegateImplMac::ItemAdded(
212 const std::string& name, const base::PlatformFileInfo& info) {
213 // Make sure if we're canceled and enumerators are awake, that
214 // they will stay consistent. May need to revisit this if we need
215 // notifications of files added after we think we're done.
216 if (received_all_files_)
217 return;
218
219 if (info.is_directory)
220 return;
221 FilePath fp = root_path_.Append(name);
sail 2012/12/26 21:30:43 avoid abbreviations (more below)
Greg Billock 2013/01/03 22:41:32 These are just aliasing abbreviations, like "i" or
sail 2013/01/03 23:10:43 i and iter are used in all C++ programs. FilePath
Greg Billock 2013/01/04 18:05:05 OK, I can make them more self-documenting names, a
222 file_info_[fp.value()] = info;
223 file_paths_.push_back(fp.value());
224
225 if (enumerator_)
226 enumerator_->ItemsChanged();
227 }
228
229 void MTPDeviceDelegateImplMac::NoMoreItems() {
230 received_all_files_ = true;
231
232 if (enumerator_)
233 enumerator_->ItemsChanged();
234 }
235
236 void MTPDeviceDelegateImplMac::DownloadedFile(
237 const std::string& name, base::PlatformFileError error) {
238 // If we're cancelled and deleting, we have already signaled all enumerators.
239 if (!camera_interface_.get())
240 return;
241
242 download_errors_[name] = error;
243 download_events_[name]->Signal();
244 }
245
246 FilePath MTPDeviceDelegateImplMac::GetFile(size_t index) {
247 if (index >= file_paths_.size())
248 return FilePath();
249 else
250 return FilePath(file_paths_[index]);
251 }
252
253 bool MTPDeviceDelegateImplMac::HasAllFiles() {
254 return received_all_files_;
255 }
256
257 void MTPDeviceDelegateImplMac::RemoveEnumerator(Enumerator* enumerator) {
258 DCHECK(enumerator_ == enumerator);
259 enumerator_ = NULL;
260 }
261
262 MTPDeviceDelegateImplMac::Enumerator::Enumerator(
263 MTPDeviceDelegateImplMac* delegate)
264 : delegate_(delegate),
265 position_(0),
266 wait_for_items_(false, false) {}
267
268 MTPDeviceDelegateImplMac::Enumerator::~Enumerator() {
269 delegate_->RemoveEnumerator(this);
270 }
271
272 FilePath MTPDeviceDelegateImplMac::Enumerator::Next() {
273 FilePath fp = delegate_->GetFile(position_);
274 while (fp.empty() && !delegate_->HasAllFiles()) {
275 wait_for_items_.Wait();
276 fp = delegate_->GetFile(position_);
277 }
278
279 position_++;
280 return fp;
281 }
282
283 int64 MTPDeviceDelegateImplMac::Enumerator::Size() {
284 FilePath fp = delegate_->GetFile(position_ - 1);
285 base::PlatformFileInfo info;
286 delegate_->GetFileInfo(fp, &info);
287 return info.size;
288 return 0;
sail 2012/12/26 21:30:43 remove
Greg Billock 2013/01/03 22:41:32 Oops! What happened to dead code detection... On
sail 2013/01/03 23:10:43 I'm not sure how the dead code detection works. Th
Greg Billock 2013/01/04 18:05:05 Two returns means the second must be unreachable;
289 }
290
291 base::Time MTPDeviceDelegateImplMac::Enumerator::LastModifiedTime() {
292 FilePath fp = delegate_->GetFile(position_ - 1);
293 base::PlatformFileInfo info;
294 delegate_->GetFileInfo(fp, &info);
295 return info.last_modified;
296 }
297
298 bool MTPDeviceDelegateImplMac::Enumerator::IsDirectory() {
299 FilePath fp = delegate_->GetFile(position_ - 1);
300 base::PlatformFileInfo info;
301 delegate_->GetFileInfo(fp, &info);
302 return info.is_directory;
303 }
304
305 void MTPDeviceDelegateImplMac::Enumerator::ItemsChanged() {
306 wait_for_items_.Signal();
307 }
308
309 void CreateMTPDeviceDelegate(const std::string& device_location,
310 base::SequencedTaskRunner* media_task_runner,
311 const CreateMTPDeviceDelegateCallback& cb) {
312 cb.Run(new MTPDeviceDelegateImplMac(device_location, media_task_runner));
313 }
314
315 } // namespace chrome
316
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698