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

Side by Side Diff: chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc

Issue 11358243: Redesigned and refactored ScopedMTPDeviceMapEntry, MTPDeviceMapService & MTPDeviceDelegate classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 8 years, 1 month 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/mtp_device_delegate_impl_linux.h" 5 #include "chrome/browser/media_gallery/mtp_device_delegate_impl_linux.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/sequenced_task_runner.h" 10 #include "base/sequenced_task_runner.h"
11 #include "base/sequenced_task_runner_helpers.h" 11 #include "base/sequenced_task_runner_helpers.h"
12 #include "base/synchronization/cancellation_flag.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 #include "base/threading/sequenced_worker_pool.h" 14 #include "base/threading/sequenced_worker_pool.h"
14 #include "chrome/browser/media_transfer_protocol/media_transfer_protocol_manager .h" 15 #include "chrome/browser/media_transfer_protocol/media_transfer_protocol_manager .h"
15 #include "chrome/browser/media_transfer_protocol/mtp_file_entry.pb.h" 16 #include "chrome/browser/media_transfer_protocol/mtp_file_entry.pb.h"
16 #include "chrome/common/chrome_notification_types.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h" 18 #include "third_party/cros_system_api/dbus/service_constants.h"
20 19
21 using base::Bind; 20 using base::Bind;
22 using base::PlatformFileError; 21 using base::PlatformFileError;
23 using base::PlatformFileInfo; 22 using base::PlatformFileInfo;
24 using base::SequencedTaskRunner; 23 using base::SequencedTaskRunner;
25 using base::Time; 24 using base::Time;
26 using content::BrowserThread; 25 using content::BrowserThread;
27 using fileapi::FileSystemFileUtil; 26 using fileapi::FileSystemFileUtil;
28 27
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 DCHECK(mtp_device_mgr); 60 DCHECK(mtp_device_mgr);
62 return mtp_device_mgr; 61 return mtp_device_mgr;
63 } 62 }
64 63
65 // Does nothing. 64 // Does nothing.
66 // This method is used to handle the results of 65 // This method is used to handle the results of
67 // MediaTransferProtocolManager::CloseStorage method call. 66 // MediaTransferProtocolManager::CloseStorage method call.
68 void DoNothing(bool error) { 67 void DoNothing(bool error) {
69 } 68 }
70 69
70 // Closes the device storage on the UI thread.
71 void CloseStorageOnUIThread(const std::string& device_handle) {
72 DCHECK(!device_handle.empty());
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 GetMediaTransferProtocolManager()->CloseStorage(device_handle,
75 Bind(&DoNothing));
76 }
77
71 // Returns the device relative file path given |file_path|. 78 // Returns the device relative file path given |file_path|.
72 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| 79 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path|
73 // is "/usb:2,2:12345", this function returns the device relative path which is 80 // is "/usb:2,2:12345", this function returns the device relative path which is
74 // "/DCIM". 81 // "/DCIM".
75 std::string GetDeviceRelativePath(const std::string& registered_dev_path, 82 std::string GetDeviceRelativePath(const std::string& registered_dev_path,
76 const std::string& file_path) { 83 const std::string& file_path) {
77 DCHECK(!registered_dev_path.empty()); 84 DCHECK(!registered_dev_path.empty());
78 DCHECK(!file_path.empty()); 85 DCHECK(!file_path.empty());
79 86
80 std::string actual_file_path; 87 std::string actual_file_path;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 if (on_shutdown_event_->IsSignaled()) { 122 if (on_shutdown_event_->IsSignaled()) {
116 // Process is in shutdown mode. 123 // Process is in shutdown mode.
117 // Do not post any task on |media_task_runner_|. 124 // Do not post any task on |media_task_runner_|.
118 return; 125 return;
119 } 126 }
120 127
121 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); 128 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
122 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 129 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
123 Bind(&OpenStorageWorker::DoWorkOnUIThread, this)); 130 Bind(&OpenStorageWorker::DoWorkOnUIThread, this));
124 on_task_completed_event_->Wait(); 131 on_task_completed_event_->Wait();
132
133 if (on_shutdown_event_->IsSignaled())
134 cancel_tasks_flag_.Set();
125 } 135 }
126 136
127 // Returns a device handle string if the OpenStorage() request was 137 // Returns a device handle string if the OpenStorage() request was
128 // successfully completed or an empty string otherwise. 138 // successfully completed or an empty string otherwise.
129 const std::string& device_handle() const { return device_handle_; } 139 const std::string& device_handle() const { return device_handle_; }
130 140
131 // Returns the |media_task_runner_| associated with this worker object. 141 // Returns the |media_task_runner_| associated with this worker object.
132 // This function is exposed for WorkerDeleter struct to access the 142 // This function is exposed for WorkerDeleter struct to access the
133 // |media_task_runner_|. 143 // |media_task_runner_|.
134 SequencedTaskRunner* media_task_runner() const { 144 SequencedTaskRunner* media_task_runner() const {
135 return media_task_runner_.get(); 145 return media_task_runner_.get();
136 } 146 }
137 147
138 private: 148 private:
139 friend struct WorkerDeleter<OpenStorageWorker>; 149 friend struct WorkerDeleter<OpenStorageWorker>;
140 friend class DeleteHelper<OpenStorageWorker>; 150 friend class DeleteHelper<OpenStorageWorker>;
141 friend class RefCountedThreadSafe<OpenStorageWorker, 151 friend class RefCountedThreadSafe<OpenStorageWorker,
142 OpenStorageWorkerDeleter>; 152 OpenStorageWorkerDeleter>;
143 153
144 // Destructed via OpenStorageWorkerDeleter struct. 154 // Destructed via OpenStorageWorkerDeleter struct.
145 virtual ~OpenStorageWorker() { 155 virtual ~OpenStorageWorker() {
146 // This object must be destructed on |media_task_runner_|. 156 // This object must be destructed on |media_task_runner_|.
147 } 157 }
148 158
149 // Dispatches a request to MediaTransferProtocolManager to open the MTP 159 // Dispatches a request to MediaTransferProtocolManager to open the MTP
150 // storage for communication. This is called on UI thread. 160 // storage for communication. This is called on UI thread.
151 void DoWorkOnUIThread() { 161 void DoWorkOnUIThread() {
152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
163 if (cancel_tasks_flag_.IsSet())
164 return;
153 165
154 GetMediaTransferProtocolManager()->OpenStorage( 166 GetMediaTransferProtocolManager()->OpenStorage(
155 storage_name_, mtpd::kReadOnlyMode, 167 storage_name_, mtpd::kReadOnlyMode,
156 Bind(&OpenStorageWorker::OnDidWorkOnUIThread, this)); 168 Bind(&OpenStorageWorker::OnDidWorkOnUIThread, this));
157 } 169 }
158 170
159 // Query callback for DoWorkOnUIThread(). |error| is set to true if the device 171 // Query callback for DoWorkOnUIThread(). |error| is set to true if the device
160 // did not open successfully. This function signals to unblock 172 // did not open successfully. This function signals to unblock
161 // |media_task_runner_|. 173 // |media_task_runner_|.
162 void OnDidWorkOnUIThread(const std::string& device_handle, bool error) { 174 void OnDidWorkOnUIThread(const std::string& device_handle, bool error) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 if (!error) 176 if (!error)
165 device_handle_ = device_handle; 177 device_handle_ = device_handle;
166 on_task_completed_event_->Signal(); 178 if (!cancel_tasks_flag_.IsSet())
179 on_task_completed_event_->Signal();
167 } 180 }
168 181
169 // Stores the storage name to open the device. 182 // Stores the storage name to open the device.
170 const std::string storage_name_; 183 const std::string storage_name_;
171 184
172 // Stores a reference to |media_task_runner_| to destruct this object on the 185 // Stores a reference to |media_task_runner_| to destruct this object on the
173 // correct thread. 186 // correct thread.
174 scoped_refptr<SequencedTaskRunner> media_task_runner_; 187 scoped_refptr<SequencedTaskRunner> media_task_runner_;
175 188
176 // |media_task_runner_| can wait on this event until the required operation 189 // |media_task_runner_| can wait on this event until the required operation
177 // is complete. 190 // is complete.
178 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 191 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
179 // DeviceMediaFileUtil functions as asynchronous functions. 192 // DeviceMediaFileUtil functions as asynchronous functions.
180 WaitableEvent* on_task_completed_event_; 193 WaitableEvent* on_task_completed_event_;
181 194
182 // Stores a reference to waitable event associated with the shut down message. 195 // Stores a reference to waitable event associated with the shut down message.
183 WaitableEvent* on_shutdown_event_; 196 WaitableEvent* on_shutdown_event_;
184 197
185 // Stores the result of OpenStorage() request. 198 // Stores the result of OpenStorage() request.
186 std::string device_handle_; 199 std::string device_handle_;
187 200
201 // Set to ignore the request results. This will be set when
202 // MTPDeviceDelegateImplLinux object is about to be deleted.
203 // |on_task_completed_event_| and |on_shutdown_event_| should not be
204 // dereferenced when this is set.
205 base::CancellationFlag cancel_tasks_flag_;
206
188 DISALLOW_COPY_AND_ASSIGN(OpenStorageWorker); 207 DISALLOW_COPY_AND_ASSIGN(OpenStorageWorker);
189 }; 208 };
190 209
191 // Worker class to get media device file information given a |path|. 210 // Worker class to get media device file information given a |path|.
192 class GetFileInfoWorker 211 class GetFileInfoWorker
193 : public RefCountedThreadSafe<GetFileInfoWorker, GetFileInfoWorkerDeleter> { 212 : public RefCountedThreadSafe<GetFileInfoWorker, GetFileInfoWorkerDeleter> {
194 public: 213 public:
195 // Constructed on |media_task_runner_| thread. 214 // Constructed on |media_task_runner_| thread.
196 GetFileInfoWorker(const std::string& handle, 215 GetFileInfoWorker(const std::string& handle,
197 const std::string& path, 216 const std::string& path,
(...skipping 15 matching lines...) Expand all
213 void Run() { 232 void Run() {
214 if (on_shutdown_event_->IsSignaled()) { 233 if (on_shutdown_event_->IsSignaled()) {
215 // Process is in shutdown mode. 234 // Process is in shutdown mode.
216 // Do not post any task on |media_task_runner_|. 235 // Do not post any task on |media_task_runner_|.
217 return; 236 return;
218 } 237 }
219 238
220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 239 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
221 Bind(&GetFileInfoWorker::DoWorkOnUIThread, this)); 240 Bind(&GetFileInfoWorker::DoWorkOnUIThread, this));
222 on_task_completed_event_->Wait(); 241 on_task_completed_event_->Wait();
242
243 if (on_shutdown_event_->IsSignaled())
244 cancel_tasks_flag_.Set();
223 } 245 }
224 246
225 // Returns GetFileInfo() result and fills in |file_info| with requested file 247 // Returns GetFileInfo() result and fills in |file_info| with requested file
226 // entry details. 248 // entry details.
227 PlatformFileError get_file_info(PlatformFileInfo* file_info) const { 249 PlatformFileError get_file_info(PlatformFileInfo* file_info) const {
228 if (file_info) 250 if (file_info)
229 *file_info = file_entry_info_; 251 *file_info = file_entry_info_;
230 return error_; 252 return error_;
231 } 253 }
232 254
(...skipping 12 matching lines...) Expand all
245 267
246 // Destructed via GetFileInfoWorkerDeleter. 268 // Destructed via GetFileInfoWorkerDeleter.
247 virtual ~GetFileInfoWorker() { 269 virtual ~GetFileInfoWorker() {
248 // This object must be destructed on |media_task_runner_|. 270 // This object must be destructed on |media_task_runner_|.
249 } 271 }
250 272
251 // Dispatches a request to MediaTransferProtocolManager to get file 273 // Dispatches a request to MediaTransferProtocolManager to get file
252 // information. 274 // information.
253 void DoWorkOnUIThread() { 275 void DoWorkOnUIThread() {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
277 if (cancel_tasks_flag_.IsSet())
278 return;
255 279
256 GetMediaTransferProtocolManager()->GetFileInfoByPath( 280 GetMediaTransferProtocolManager()->GetFileInfoByPath(
257 device_handle_, path_, 281 device_handle_, path_,
258 Bind(&GetFileInfoWorker::OnDidWorkOnUIThread, this)); 282 Bind(&GetFileInfoWorker::OnDidWorkOnUIThread, this));
259 } 283 }
260 284
261 // Query callback for DoWorkOnUIThread(). On success, |file_entry| has media 285 // Query callback for DoWorkOnUIThread(). On success, |file_entry| has media
262 // file information. On failure, |error| is set to true. This function signals 286 // file information. On failure, |error| is set to true. This function signals
263 // to unblock |media_task_runner_|. 287 // to unblock |media_task_runner_|.
264 void OnDidWorkOnUIThread(const MtpFileEntry& file_entry, bool error) { 288 void OnDidWorkOnUIThread(const MtpFileEntry& file_entry, bool error) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 if (error) { 290 if (error) {
267 error_ = base::PLATFORM_FILE_ERROR_NOT_FOUND; 291 error_ = base::PLATFORM_FILE_ERROR_NOT_FOUND;
268 } else { 292 } else {
269 file_entry_info_.size = file_entry.file_size(); 293 file_entry_info_.size = file_entry.file_size();
270 file_entry_info_.is_directory = 294 file_entry_info_.is_directory =
271 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER; 295 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER;
272 file_entry_info_.is_symbolic_link = false; 296 file_entry_info_.is_symbolic_link = false;
273 file_entry_info_.last_modified = 297 file_entry_info_.last_modified =
274 base::Time::FromTimeT(file_entry.modification_time()); 298 base::Time::FromTimeT(file_entry.modification_time());
275 file_entry_info_.last_accessed = 299 file_entry_info_.last_accessed =
276 base::Time::FromTimeT(file_entry.modification_time()); 300 base::Time::FromTimeT(file_entry.modification_time());
277 file_entry_info_.creation_time = base::Time(); 301 file_entry_info_.creation_time = base::Time();
278 } 302 }
279 on_task_completed_event_->Signal(); 303 if (!cancel_tasks_flag_.IsSet())
304 on_task_completed_event_->Signal();
280 } 305 }
281 306
282 // Stores the device handle to query the device. 307 // Stores the device handle to query the device.
283 const std::string device_handle_; 308 const std::string device_handle_;
284 309
285 // Stores the requested media device file path. 310 // Stores the requested media device file path.
286 const std::string path_; 311 const std::string path_;
287 312
288 // Stores a reference to |media_task_runner_| to destruct this object on the 313 // Stores a reference to |media_task_runner_| to destruct this object on the
289 // correct thread. 314 // correct thread.
290 scoped_refptr<SequencedTaskRunner> media_task_runner_; 315 scoped_refptr<SequencedTaskRunner> media_task_runner_;
291 316
292 // Stores the result of GetFileInfo(). 317 // Stores the result of GetFileInfo().
293 PlatformFileError error_; 318 PlatformFileError error_;
294 319
295 // Stores the media file entry information. 320 // Stores the media file entry information.
296 PlatformFileInfo file_entry_info_; 321 PlatformFileInfo file_entry_info_;
297 322
298 // |media_task_runner_| can wait on this event until the required operation 323 // |media_task_runner_| can wait on this event until the required operation
299 // is complete. 324 // is complete.
300 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 325 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
301 // DeviceMediaFileUtil functions as asynchronous functions. 326 // DeviceMediaFileUtil functions as asynchronous functions.
302 WaitableEvent* on_task_completed_event_; 327 WaitableEvent* on_task_completed_event_;
303 328
304 // Stores a reference to waitable event associated with the shut down message. 329 // Stores a reference to waitable event associated with the shut down message.
305 WaitableEvent* on_shutdown_event_; 330 WaitableEvent* on_shutdown_event_;
306 331
332 // Set to ignore the request results. This will be set when
333 // MTPDeviceDelegateImplLinux object is about to be deleted.
334 // |on_task_completed_event_| and |on_shutdown_event_| should not be
335 // dereferenced when this is set.
336 base::CancellationFlag cancel_tasks_flag_;
337
307 DISALLOW_COPY_AND_ASSIGN(GetFileInfoWorker); 338 DISALLOW_COPY_AND_ASSIGN(GetFileInfoWorker);
308 }; 339 };
309 340
310 // Worker class to read media device file data given a file |path|. 341 // Worker class to read media device file data given a file |path|.
311 class ReadFileWorker 342 class ReadFileWorker
312 : public RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter> { 343 : public RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter> {
313 public: 344 public:
314 // Constructed on |media_task_runner_| thread. 345 // Constructed on |media_task_runner_| thread.
315 ReadFileWorker(const std::string& handle, 346 ReadFileWorker(const std::string& handle,
316 const std::string& path, 347 const std::string& path,
(...skipping 14 matching lines...) Expand all
331 void Run() { 362 void Run() {
332 if (on_shutdown_event_->IsSignaled()) { 363 if (on_shutdown_event_->IsSignaled()) {
333 // Process is in shutdown mode. 364 // Process is in shutdown mode.
334 // Do not post any task on |media_task_runner_|. 365 // Do not post any task on |media_task_runner_|.
335 return; 366 return;
336 } 367 }
337 368
338 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 369 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
339 Bind(&ReadFileWorker::DoWorkOnUIThread, this)); 370 Bind(&ReadFileWorker::DoWorkOnUIThread, this));
340 on_task_completed_event_->Wait(); 371 on_task_completed_event_->Wait();
372 if (on_shutdown_event_->IsSignaled())
373 cancel_tasks_flag_.Set();
341 } 374 }
342 375
343 // Returns the media file contents received by ReadFileByPath() callback 376 // Returns the media file contents received by ReadFileByPath() callback
344 // function. 377 // function.
345 const std::string& data() const { return data_; } 378 const std::string& data() const { return data_; }
346 379
347 // Returns the |media_task_runner_| associated with this worker object. 380 // Returns the |media_task_runner_| associated with this worker object.
348 // This function is exposed for WorkerDeleter struct to access the 381 // This function is exposed for WorkerDeleter struct to access the
349 // |media_task_runner_|. 382 // |media_task_runner_|.
350 SequencedTaskRunner* media_task_runner() const { 383 SequencedTaskRunner* media_task_runner() const {
351 return media_task_runner_.get(); 384 return media_task_runner_.get();
352 } 385 }
353 386
354 private: 387 private:
355 friend struct WorkerDeleter<ReadFileWorker>; 388 friend struct WorkerDeleter<ReadFileWorker>;
356 friend class DeleteHelper<ReadFileWorker>; 389 friend class DeleteHelper<ReadFileWorker>;
357 friend class RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter>; 390 friend class RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter>;
358 391
359 // Destructed via ReadFileWorkerDeleter. 392 // Destructed via ReadFileWorkerDeleter.
360 virtual ~ReadFileWorker() { 393 virtual ~ReadFileWorker() {
361 // This object must be destructed on |media_task_runner_|. 394 // This object must be destructed on |media_task_runner_|.
362 } 395 }
363 396
364 // Dispatches a request to MediaTransferProtocolManager to get the media file 397 // Dispatches a request to MediaTransferProtocolManager to get the media file
365 // contents. 398 // contents.
366 void DoWorkOnUIThread() { 399 void DoWorkOnUIThread() {
367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
401 if (cancel_tasks_flag_.IsSet())
402 return;
403
368 GetMediaTransferProtocolManager()->ReadFileByPath( 404 GetMediaTransferProtocolManager()->ReadFileByPath(
369 device_handle_, path_, Bind(&ReadFileWorker::OnDidWorkOnUIThread, this)); 405 device_handle_, path_, Bind(&ReadFileWorker::OnDidWorkOnUIThread, this));
370 } 406 }
371 407
372 // Query callback for DoWorkOnUIThread(). On success, |data| has the media 408 // Query callback for DoWorkOnUIThread(). On success, |data| has the media
373 // file contents. On failure, |error| is set to true. This function signals 409 // file contents. On failure, |error| is set to true. This function signals
374 // to unblock |media_task_runner_|. 410 // to unblock |media_task_runner_|.
375 void OnDidWorkOnUIThread(const std::string& data, bool error) { 411 void OnDidWorkOnUIThread(const std::string& data, bool error) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
377 if (!error) { 413 if (!error) {
378 // TODO(kmadhusu): Data could be really huge. Consider passing data by 414 // TODO(kmadhusu): Data could be really huge. Consider passing data by
379 // pointer/ref rather than by value here to avoid an extra data copy. 415 // pointer/ref rather than by value here to avoid an extra data copy.
380 data_ = data; 416 data_ = data;
381 } 417 }
382 on_task_completed_event_->Signal(); 418 if (!cancel_tasks_flag_.IsSet())
419 on_task_completed_event_->Signal();
383 } 420 }
384 421
385 // Stores the device unique identifier to query the device. 422 // Stores the device unique identifier to query the device.
386 const std::string device_handle_; 423 const std::string device_handle_;
387 424
388 // Stores the media device file path. 425 // Stores the media device file path.
389 const std::string path_; 426 const std::string path_;
390 427
391 // Stores a reference to |media_task_runner_| to destruct this object on the 428 // Stores a reference to |media_task_runner_| to destruct this object on the
392 // correct thread. 429 // correct thread.
393 scoped_refptr<SequencedTaskRunner> media_task_runner_; 430 scoped_refptr<SequencedTaskRunner> media_task_runner_;
394 431
395 // Stores the result of ReadFileByPath() callback. 432 // Stores the result of ReadFileByPath() callback.
396 std::string data_; 433 std::string data_;
397 434
398 // |media_task_runner_| can wait on this event until the required operation 435 // |media_task_runner_| can wait on this event until the required operation
399 // is complete. 436 // is complete.
400 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 437 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
401 // DeviceMediaFileUtil functions as asynchronous functions. 438 // DeviceMediaFileUtil functions as asynchronous functions.
402 WaitableEvent* on_task_completed_event_; 439 WaitableEvent* on_task_completed_event_;
403 440
404 // Stores a reference to waitable event associated with the shut down message. 441 // Stores a reference to waitable event associated with the shut down message.
405 WaitableEvent* on_shutdown_event_; 442 WaitableEvent* on_shutdown_event_;
406 443
444 // Set to ignore the request results. This will be set when
445 // MTPDeviceDelegateImplLinux object is about to be deleted.
446 // |on_task_completed_event_| and |on_shutdown_event_| should not be
447 // dereferenced when this is set.
448 base::CancellationFlag cancel_tasks_flag_;
449
407 DISALLOW_COPY_AND_ASSIGN(ReadFileWorker); 450 DISALLOW_COPY_AND_ASSIGN(ReadFileWorker);
408 }; 451 };
409 452
410 // Worker class to read directory contents. Device is already opened for 453 // Worker class to read directory contents. Device is already opened for
411 // communication. 454 // communication.
412 class ReadDirectoryWorker 455 class ReadDirectoryWorker
413 : public RefCountedThreadSafe<ReadDirectoryWorker, 456 : public RefCountedThreadSafe<ReadDirectoryWorker,
414 ReadDirectoryWorkerDeleter> { 457 ReadDirectoryWorkerDeleter> {
415 public: 458 public:
416 // Construct a worker object given the directory |path|. This object is 459 // Construct a worker object given the directory |path|. This object is
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 void Run() { 495 void Run() {
453 if (on_shutdown_event_->IsSignaled()) { 496 if (on_shutdown_event_->IsSignaled()) {
454 // Process is in shutdown mode. 497 // Process is in shutdown mode.
455 // Do not post any task on |media_task_runner_|. 498 // Do not post any task on |media_task_runner_|.
456 return; 499 return;
457 } 500 }
458 501
459 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 502 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
460 Bind(&ReadDirectoryWorker::DoWorkOnUIThread, this)); 503 Bind(&ReadDirectoryWorker::DoWorkOnUIThread, this));
461 on_task_completed_event_->Wait(); 504 on_task_completed_event_->Wait();
505 if (on_shutdown_event_->IsSignaled())
506 cancel_tasks_flag_.Set();
462 } 507 }
463 508
464 // Returns the directory entries for the given directory path. 509 // Returns the directory entries for the given directory path.
465 const std::vector<MtpFileEntry>& get_file_entries() const { 510 const std::vector<MtpFileEntry>& get_file_entries() const {
466 return file_entries_; 511 return file_entries_;
467 } 512 }
468 513
469 // Returns the |media_task_runner_| associated with this worker object. 514 // Returns the |media_task_runner_| associated with this worker object.
470 // This function is exposed for WorkerDeleter struct to access the 515 // This function is exposed for WorkerDeleter struct to access the
471 // |media_task_runner_|. 516 // |media_task_runner_|.
472 SequencedTaskRunner* media_task_runner() const { 517 SequencedTaskRunner* media_task_runner() const {
473 return media_task_runner_.get(); 518 return media_task_runner_.get();
474 } 519 }
475 520
476 private: 521 private:
477 friend struct WorkerDeleter<ReadDirectoryWorker>; 522 friend struct WorkerDeleter<ReadDirectoryWorker>;
478 friend class DeleteHelper<ReadDirectoryWorker>; 523 friend class DeleteHelper<ReadDirectoryWorker>;
479 friend class RefCountedThreadSafe<ReadDirectoryWorker, 524 friend class RefCountedThreadSafe<ReadDirectoryWorker,
480 ReadDirectoryWorkerDeleter>; 525 ReadDirectoryWorkerDeleter>;
481 526
482 // Destructed via ReadDirectoryWorkerDeleter. 527 // Destructed via ReadDirectoryWorkerDeleter.
483 virtual ~ReadDirectoryWorker() { 528 virtual ~ReadDirectoryWorker() {
484 // This object must be destructed on |media_task_runner_|. 529 // This object must be destructed on |media_task_runner_|.
485 } 530 }
486 531
487 // Dispatches a request to MediaTransferProtocolManager to read the directory 532 // Dispatches a request to MediaTransferProtocolManager to read the directory
488 // entries. This is called on UI thread. 533 // entries. This is called on UI thread.
489 void DoWorkOnUIThread() { 534 void DoWorkOnUIThread() {
490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
536 if (cancel_tasks_flag_.IsSet())
537 return;
491 538
492 if (!dir_path_.empty()) { 539 if (!dir_path_.empty()) {
493 GetMediaTransferProtocolManager()->ReadDirectoryByPath( 540 GetMediaTransferProtocolManager()->ReadDirectoryByPath(
494 device_handle_, dir_path_, 541 device_handle_, dir_path_,
495 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this)); 542 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this));
496 } else { 543 } else {
497 GetMediaTransferProtocolManager()->ReadDirectoryById( 544 GetMediaTransferProtocolManager()->ReadDirectoryById(
498 device_handle_, dir_entry_id_, 545 device_handle_, dir_entry_id_,
499 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this)); 546 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this));
500 } 547 }
501 } 548 }
502 549
503 // Query callback for DoWorkOnUIThread(). On success, |file_entries| has the 550 // Query callback for DoWorkOnUIThread(). On success, |file_entries| has the
504 // directory file entries. |error| is true if there was an error. This 551 // directory file entries. |error| is true if there was an error. This
505 // function signals to unblock |media_task_runner_|. 552 // function signals to unblock |media_task_runner_|.
506 void OnDidWorkOnUIThread(const std::vector<MtpFileEntry>& file_entries, 553 void OnDidWorkOnUIThread(const std::vector<MtpFileEntry>& file_entries,
507 bool error) { 554 bool error) {
508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
509 if (!error) 556 if (!error)
510 file_entries_ = file_entries; 557 file_entries_ = file_entries;
511 on_task_completed_event_->Signal(); 558 if (!cancel_tasks_flag_.IsSet())
559 on_task_completed_event_->Signal();
512 } 560 }
513 561
514 // Stores the device handle to communicate with storage device. 562 // Stores the device handle to communicate with storage device.
515 const std::string device_handle_; 563 const std::string device_handle_;
516 564
517 // Stores the directory path whose contents needs to be listed. 565 // Stores the directory path whose contents needs to be listed.
518 const std::string dir_path_; 566 const std::string dir_path_;
519 567
520 // Stores the directory entry id whose contents needs to be listed. 568 // Stores the directory entry id whose contents needs to be listed.
521 const uint32_t dir_entry_id_; 569 const uint32_t dir_entry_id_;
522 570
523 // Stores a reference to |media_task_runner_| to destruct this object on the 571 // Stores a reference to |media_task_runner_| to destruct this object on the
524 // correct thread. 572 // correct thread.
525 scoped_refptr<SequencedTaskRunner> media_task_runner_; 573 scoped_refptr<SequencedTaskRunner> media_task_runner_;
526 574
527 // |media_task_runner_| can wait on this event until the required operation 575 // |media_task_runner_| can wait on this event until the required operation
528 // is complete. 576 // is complete.
529 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 577 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
530 // DeviceMediaFileUtil functions as asynchronous functions. 578 // DeviceMediaFileUtil functions as asynchronous functions.
531 WaitableEvent* on_task_completed_event_; 579 WaitableEvent* on_task_completed_event_;
532 580
533 // Stores a reference to waitable event associated with the shut down message. 581 // Stores a reference to waitable event associated with the shut down message.
534 WaitableEvent* on_shutdown_event_; 582 WaitableEvent* on_shutdown_event_;
535 583
536 // Stores the result of read directory request. 584 // Stores the result of read directory request.
537 std::vector<MtpFileEntry> file_entries_; 585 std::vector<MtpFileEntry> file_entries_;
538 586
587 // Set to ignore the request results. This will be set when
588 // MTPDeviceDelegateImplLinux object is about to be deleted.
589 // |on_task_completed_event_| and |on_shutdown_event_| should not be
590 // dereferenced when this is set.
591 base::CancellationFlag cancel_tasks_flag_;
592
539 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryWorker); 593 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryWorker);
540 }; 594 };
541 595
542 // Simply enumerate each files from a given file entry list. 596 // Simply enumerate each files from a given file entry list.
543 // Used to enumerate top-level files of an media file system. 597 // Used to enumerate top-level files of an media file system.
544 class MediaFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { 598 class MediaFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
545 public: 599 public:
546 explicit MediaFileEnumerator(const std::vector<MtpFileEntry>& entries) 600 explicit MediaFileEnumerator(const std::vector<MtpFileEntry>& entries)
547 : file_entries_(entries), 601 : file_entries_(entries),
548 file_entry_iter_(file_entries_.begin()) { 602 file_entry_iter_(file_entries_.begin()) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 const std::string& device_location) 755 const std::string& device_location)
702 : device_path_(device_location), 756 : device_path_(device_location),
703 on_task_completed_event_(false, false), 757 on_task_completed_event_(false, false),
704 on_shutdown_event_(true, false) { 758 on_shutdown_event_(true, false) {
705 CHECK(!device_path_.empty()); 759 CHECK(!device_path_.empty());
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 760 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
707 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 761 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
708 base::SequencedWorkerPool::SequenceToken media_sequence_token = 762 base::SequencedWorkerPool::SequenceToken media_sequence_token =
709 pool->GetNamedSequenceToken("media-task-runner"); 763 pool->GetNamedSequenceToken("media-task-runner");
710 media_task_runner_ = pool->GetSequencedTaskRunner(media_sequence_token); 764 media_task_runner_ = pool->GetSequencedTaskRunner(media_sequence_token);
711 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
712 content::NotificationService::AllSources());
713
714 DCHECK(media_task_runner_);
715 }
716
717 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
718 registrar_.RemoveAll();
719 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
720 GetMediaTransferProtocolManager()->CloseStorage(device_handle_,
721 Bind(&DoNothing));
722 } 765 }
723 766
724 PlatformFileError MTPDeviceDelegateImplLinux::GetFileInfo( 767 PlatformFileError MTPDeviceDelegateImplLinux::GetFileInfo(
725 const FilePath& file_path, 768 const FilePath& file_path,
726 PlatformFileInfo* file_info) { 769 PlatformFileInfo* file_info) {
727 if (!LazyInit()) 770 if (!LazyInit())
728 return base::PLATFORM_FILE_ERROR_FAILED; 771 return base::PLATFORM_FILE_ERROR_FAILED;
729 772
730 scoped_refptr<GetFileInfoWorker> worker(new GetFileInfoWorker( 773 scoped_refptr<GetFileInfoWorker> worker(new GetFileInfoWorker(
731 device_handle_, GetDeviceRelativePath(device_path_, file_path.value()), 774 device_handle_, GetDeviceRelativePath(device_path_, file_path.value()),
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 // Modify the last modified time to null. This prevents the time stamp 832 // Modify the last modified time to null. This prevents the time stamp
790 // verfication in LocalFileStreamReader. 833 // verfication in LocalFileStreamReader.
791 file_info->last_modified = base::Time(); 834 file_info->last_modified = base::Time();
792 return error; 835 return error;
793 } 836 }
794 837
795 SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() { 838 SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() {
796 return media_task_runner_.get(); 839 return media_task_runner_.get();
797 } 840 }
798 841
799 void MTPDeviceDelegateImplLinux::DeleteOnCorrectThread() const { 842 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
800 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 843 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
801 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 844 // Caution: This function is called on the IO thread. Access only the thread
802 return; 845 // safe member variables in this function. Do all the clean up operations in
803 } 846 // DeleteDelegateOnTaskRunner().
804 delete this; 847 on_shutdown_event_.Signal();
848 on_task_completed_event_.Signal();
849 media_task_runner_->PostTask(
850 FROM_HERE,
851 base::Bind(&MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner,
852 base::Unretained(this)));
805 } 853 }
806 854
807 void MTPDeviceDelegateImplLinux::Observe( 855 base::WeakPtr<fileapi::MTPDeviceDelegate> MTPDeviceDelegateImplLinux::
808 int type, 856 GetAsWeakPtrOnIOThread() {
809 const content::NotificationSource& source, 857 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
810 const content::NotificationDetails& details) { 858 base::WeakPtr<fileapi::MTPDeviceDelegate> delegate = AsWeakPtr();
811 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); 859 // This function is called on the IO thread but the member functions are
812 on_shutdown_event_.Signal(); 860 // accessed on |media_task_runner_|. Therefore, detach from the the current
813 on_task_completed_event_.Signal(); 861 // thread.
862 DetachFromThread();
863 return delegate;
864 }
865
866 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
867 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
868 // Do all the clean up operations on DeleteDelegateOnTaskRunner().
814 } 869 }
815 870
816 bool MTPDeviceDelegateImplLinux::LazyInit() { 871 bool MTPDeviceDelegateImplLinux::LazyInit() {
817 DCHECK(media_task_runner_); 872 DCHECK(media_task_runner_);
818 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); 873 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
819 874
820 if (!device_handle_.empty()) 875 if (!device_handle_.empty())
821 return true; // Already successfully initialized. 876 return true; // Already successfully initialized.
822 877
823 std::string storage_name; 878 std::string storage_name;
824 RemoveChars(device_path_, kRootPath, &storage_name); 879 RemoveChars(device_path_, kRootPath, &storage_name);
825 DCHECK(!storage_name.empty()); 880 DCHECK(!storage_name.empty());
826 scoped_refptr<OpenStorageWorker> worker(new OpenStorageWorker( 881 scoped_refptr<OpenStorageWorker> worker(new OpenStorageWorker(
827 storage_name, media_task_runner_, &on_task_completed_event_, 882 storage_name, media_task_runner_, &on_task_completed_event_,
828 &on_shutdown_event_)); 883 &on_shutdown_event_));
829 worker->Run(); 884 worker->Run();
830 device_handle_ = worker->device_handle(); 885 device_handle_ = worker->device_handle();
831 return !device_handle_.empty(); 886 return !device_handle_.empty();
832 } 887 }
833 888
889 void MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner() {
890 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
891 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
892 Bind(&CloseStorageOnUIThread, device_handle_));
893 delete this;
894 }
895
834 } // namespace chrome 896 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698