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

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: Fixed GetFileInfoWorker Created 8 years 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/string_util.h" 12 #include "base/string_util.h"
13 #include "base/synchronization/cancellation_flag.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));
176 if (cancel_tasks_flag_.IsSet())
177 return;
178
164 if (!error) 179 if (!error)
165 device_handle_ = device_handle; 180 device_handle_ = device_handle;
166 on_task_completed_event_->Signal(); 181 on_task_completed_event_->Signal();
167 } 182 }
168 183
169 // Stores the storage name to open the device. 184 // Stores the storage name to open the device.
170 const std::string storage_name_; 185 const std::string storage_name_;
171 186
172 // Stores a reference to |media_task_runner_| to destruct this object on the 187 // Stores a reference to |media_task_runner_| to destruct this object on the
173 // correct thread. 188 // correct thread.
174 scoped_refptr<SequencedTaskRunner> media_task_runner_; 189 scoped_refptr<SequencedTaskRunner> media_task_runner_;
175 190
176 // |media_task_runner_| can wait on this event until the required operation 191 // |media_task_runner_| can wait on this event until the required operation
177 // is complete. 192 // is complete.
178 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 193 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
179 // DeviceMediaFileUtil functions as asynchronous functions. 194 // DeviceMediaFileUtil functions as asynchronous functions.
180 WaitableEvent* on_task_completed_event_; 195 WaitableEvent* on_task_completed_event_;
181 196
182 // Stores a reference to waitable event associated with the shut down message. 197 // Stores a reference to waitable event associated with the shut down message.
183 WaitableEvent* on_shutdown_event_; 198 WaitableEvent* on_shutdown_event_;
184 199
185 // Stores the result of OpenStorage() request. 200 // Stores the result of OpenStorage() request.
186 std::string device_handle_; 201 std::string device_handle_;
187 202
203 // Set to ignore the request results. This will be set when
204 // MTPDeviceDelegateImplLinux object is about to be deleted.
205 // |on_task_completed_event_| and |on_shutdown_event_| should not be
206 // dereferenced when this is set.
207 base::CancellationFlag cancel_tasks_flag_;
208
188 DISALLOW_COPY_AND_ASSIGN(OpenStorageWorker); 209 DISALLOW_COPY_AND_ASSIGN(OpenStorageWorker);
189 }; 210 };
190 211
191 // Worker class to get media device file information given a |path|. 212 // Worker class to get media device file information given a |path|.
192 class GetFileInfoWorker 213 class GetFileInfoWorker
193 : public RefCountedThreadSafe<GetFileInfoWorker, GetFileInfoWorkerDeleter> { 214 : public RefCountedThreadSafe<GetFileInfoWorker, GetFileInfoWorkerDeleter> {
194 public: 215 public:
195 // Constructed on |media_task_runner_| thread. 216 // Constructed on |media_task_runner_| thread.
196 GetFileInfoWorker(const std::string& handle, 217 GetFileInfoWorker(const std::string& handle,
197 const std::string& path, 218 const std::string& path,
(...skipping 15 matching lines...) Expand all
213 void Run() { 234 void Run() {
214 if (on_shutdown_event_->IsSignaled()) { 235 if (on_shutdown_event_->IsSignaled()) {
215 // Process is in shutdown mode. 236 // Process is in shutdown mode.
216 // Do not post any task on |media_task_runner_|. 237 // Do not post any task on |media_task_runner_|.
217 return; 238 return;
218 } 239 }
219 240
220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 241 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
221 Bind(&GetFileInfoWorker::DoWorkOnUIThread, this)); 242 Bind(&GetFileInfoWorker::DoWorkOnUIThread, this));
222 on_task_completed_event_->Wait(); 243 on_task_completed_event_->Wait();
244
245 if (on_shutdown_event_->IsSignaled())
246 cancel_tasks_flag_.Set();
223 } 247 }
224 248
225 // Returns GetFileInfo() result and fills in |file_info| with requested file 249 // Returns GetFileInfo() result and fills in |file_info| with requested file
226 // entry details. 250 // entry details.
227 PlatformFileError get_file_info(PlatformFileInfo* file_info) const { 251 PlatformFileError get_file_info(PlatformFileInfo* file_info) const {
228 if (file_info) 252 if (file_info)
229 *file_info = file_entry_info_; 253 *file_info = file_entry_info_;
230 return error_; 254 return error_;
231 } 255 }
232 256
(...skipping 12 matching lines...) Expand all
245 269
246 // Destructed via GetFileInfoWorkerDeleter. 270 // Destructed via GetFileInfoWorkerDeleter.
247 virtual ~GetFileInfoWorker() { 271 virtual ~GetFileInfoWorker() {
248 // This object must be destructed on |media_task_runner_|. 272 // This object must be destructed on |media_task_runner_|.
249 } 273 }
250 274
251 // Dispatches a request to MediaTransferProtocolManager to get file 275 // Dispatches a request to MediaTransferProtocolManager to get file
252 // information. 276 // information.
253 void DoWorkOnUIThread() { 277 void DoWorkOnUIThread() {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 if (cancel_tasks_flag_.IsSet()) {
280 error_ = base::PLATFORM_FILE_ERROR_FAILED;
281 return;
282 }
255 283
256 GetMediaTransferProtocolManager()->GetFileInfoByPath( 284 GetMediaTransferProtocolManager()->GetFileInfoByPath(
257 device_handle_, path_, 285 device_handle_, path_,
258 Bind(&GetFileInfoWorker::OnDidWorkOnUIThread, this)); 286 Bind(&GetFileInfoWorker::OnDidWorkOnUIThread, this));
259 } 287 }
260 288
261 // Query callback for DoWorkOnUIThread(). On success, |file_entry| has media 289 // Query callback for DoWorkOnUIThread(). On success, |file_entry| has media
262 // file information. On failure, |error| is set to true. This function signals 290 // file information. On failure, |error| is set to true. This function signals
263 // to unblock |media_task_runner_|. 291 // to unblock |media_task_runner_|.
264 void OnDidWorkOnUIThread(const MtpFileEntry& file_entry, bool error) { 292 void OnDidWorkOnUIThread(const MtpFileEntry& file_entry, bool error) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
294 if (cancel_tasks_flag_.IsSet()) {
295 error_ = base::PLATFORM_FILE_ERROR_FAILED;
296 return;
297 }
298
266 if (error) { 299 if (error) {
267 error_ = base::PLATFORM_FILE_ERROR_NOT_FOUND; 300 error_ = base::PLATFORM_FILE_ERROR_NOT_FOUND;
268 } else { 301 } else {
269 file_entry_info_.size = file_entry.file_size(); 302 file_entry_info_.size = file_entry.file_size();
270 file_entry_info_.is_directory = 303 file_entry_info_.is_directory =
271 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER; 304 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER;
272 file_entry_info_.is_symbolic_link = false; 305 file_entry_info_.is_symbolic_link = false;
273 file_entry_info_.last_modified = 306 file_entry_info_.last_modified =
274 base::Time::FromTimeT(file_entry.modification_time()); 307 base::Time::FromTimeT(file_entry.modification_time());
275 file_entry_info_.last_accessed = 308 file_entry_info_.last_accessed =
(...skipping 21 matching lines...) Expand all
297 330
298 // |media_task_runner_| can wait on this event until the required operation 331 // |media_task_runner_| can wait on this event until the required operation
299 // is complete. 332 // is complete.
300 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 333 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
301 // DeviceMediaFileUtil functions as asynchronous functions. 334 // DeviceMediaFileUtil functions as asynchronous functions.
302 WaitableEvent* on_task_completed_event_; 335 WaitableEvent* on_task_completed_event_;
303 336
304 // Stores a reference to waitable event associated with the shut down message. 337 // Stores a reference to waitable event associated with the shut down message.
305 WaitableEvent* on_shutdown_event_; 338 WaitableEvent* on_shutdown_event_;
306 339
340 // Set to ignore the request results. This will be set when
341 // MTPDeviceDelegateImplLinux object is about to be deleted.
342 // |on_task_completed_event_| and |on_shutdown_event_| should not be
343 // dereferenced when this is set.
344 base::CancellationFlag cancel_tasks_flag_;
345
307 DISALLOW_COPY_AND_ASSIGN(GetFileInfoWorker); 346 DISALLOW_COPY_AND_ASSIGN(GetFileInfoWorker);
308 }; 347 };
309 348
310 // Worker class to read media device file data given a file |path|. 349 // Worker class to read media device file data given a file |path|.
311 class ReadFileWorker 350 class ReadFileWorker
312 : public RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter> { 351 : public RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter> {
313 public: 352 public:
314 // Constructed on |media_task_runner_| thread. 353 // Constructed on |media_task_runner_| thread.
315 ReadFileWorker(const std::string& handle, 354 ReadFileWorker(const std::string& handle,
316 const std::string& path, 355 const std::string& path,
(...skipping 14 matching lines...) Expand all
331 370
332 // This function is invoked on |media_task_runner_| to post the task on UI 371 // This function is invoked on |media_task_runner_| to post the task on UI
333 // thread. This blocks the |media_task_runner_| until the task is complete. 372 // thread. This blocks the |media_task_runner_| until the task is complete.
334 void Run() { 373 void Run() {
335 if (on_shutdown_event_->IsSignaled()) { 374 if (on_shutdown_event_->IsSignaled()) {
336 // Process is in shutdown mode. 375 // Process is in shutdown mode.
337 // Do not post any task on |media_task_runner_|. 376 // Do not post any task on |media_task_runner_|.
338 return; 377 return;
339 } 378 }
340 379
341 while (!error_occurred_ && (data_.size() < total_bytes_)) { 380 while (!error_occurred_ && (data_.size() < total_bytes_) &&
381 !cancel_tasks_flag_.IsSet()) {
342 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 382 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
343 Bind(&ReadFileWorker::DoWorkOnUIThread, this)); 383 Bind(&ReadFileWorker::DoWorkOnUIThread, this));
344 on_task_completed_event_->Wait(); 384 on_task_completed_event_->Wait();
385 if (on_shutdown_event_->IsSignaled())
386 cancel_tasks_flag_.Set();
345 } 387 }
346 } 388 }
347 389
348 // Returns the media file contents received from mtpd. 390 // Returns the media file contents received from mtpd.
349 const std::string& data() const { return data_; } 391 const std::string& data() const { return data_; }
350 392
351 // Returns the |media_task_runner_| associated with this worker object. 393 // Returns the |media_task_runner_| associated with this worker object.
352 // This function is exposed for WorkerDeleter struct to access the 394 // This function is exposed for WorkerDeleter struct to access the
353 // |media_task_runner_|. 395 // |media_task_runner_|.
354 SequencedTaskRunner* media_task_runner() const { 396 SequencedTaskRunner* media_task_runner() const {
355 return media_task_runner_.get(); 397 return media_task_runner_.get();
356 } 398 }
357 399
358 private: 400 private:
359 friend struct WorkerDeleter<ReadFileWorker>; 401 friend struct WorkerDeleter<ReadFileWorker>;
360 friend class DeleteHelper<ReadFileWorker>; 402 friend class DeleteHelper<ReadFileWorker>;
361 friend class RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter>; 403 friend class RefCountedThreadSafe<ReadFileWorker, ReadFileWorkerDeleter>;
362 404
363 // Destructed via ReadFileWorkerDeleter. 405 // Destructed via ReadFileWorkerDeleter.
364 virtual ~ReadFileWorker() { 406 virtual ~ReadFileWorker() {
365 // This object must be destructed on |media_task_runner_|. 407 // This object must be destructed on |media_task_runner_|.
366 } 408 }
367 409
368 // Dispatches a request to MediaTransferProtocolManager to get the media file 410 // Dispatches a request to MediaTransferProtocolManager to get the media file
369 // contents. 411 // contents.
370 void DoWorkOnUIThread() { 412 void DoWorkOnUIThread() {
371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 if (cancel_tasks_flag_.IsSet())
415 return;
416
372 GetMediaTransferProtocolManager()->ReadFileChunkByPath( 417 GetMediaTransferProtocolManager()->ReadFileChunkByPath(
373 device_handle_, path_, data_.size(), BytesToRead(), 418 device_handle_, path_, data_.size(), BytesToRead(),
374 Bind(&ReadFileWorker::OnDidWorkOnUIThread, this)); 419 Bind(&ReadFileWorker::OnDidWorkOnUIThread, this));
375 } 420 }
376 421
377 // Query callback for DoWorkOnUIThread(). On success, |data| has the media 422 // Query callback for DoWorkOnUIThread(). On success, |data| has the media
378 // file contents. On failure, |error| is set to true. This function signals 423 // file contents. On failure, |error| is set to true. This function signals
379 // to unblock |media_task_runner_|. 424 // to unblock |media_task_runner_|.
380 void OnDidWorkOnUIThread(const std::string& data, bool error) { 425 void OnDidWorkOnUIThread(const std::string& data, bool error) {
381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
427 if (cancel_tasks_flag_.IsSet())
428 return;
429
382 error_occurred_ = error; 430 error_occurred_ = error;
383 if (!error) { 431 if (!error) {
384 if ((BytesToRead() == data.size())) { 432 if ((BytesToRead() == data.size())) {
385 // TODO(kmadhusu): Data could be really huge. Consider passing data by 433 // TODO(kmadhusu): Data could be really huge. Consider passing data by
386 // pointer/ref rather than by value here to avoid an extra data copy. 434 // pointer/ref rather than by value here to avoid an extra data copy.
387 data_.append(data); 435 data_.append(data);
388 } else { 436 } else {
389 NOTREACHED(); 437 NOTREACHED();
390 error_occurred_ = true; 438 error_occurred_ = true;
391 } 439 }
(...skipping 29 matching lines...) Expand all
421 469
422 // |media_task_runner_| can wait on this event until the required operation 470 // |media_task_runner_| can wait on this event until the required operation
423 // is complete. 471 // is complete.
424 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 472 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
425 // DeviceMediaFileUtil functions as asynchronous functions. 473 // DeviceMediaFileUtil functions as asynchronous functions.
426 WaitableEvent* on_task_completed_event_; 474 WaitableEvent* on_task_completed_event_;
427 475
428 // Stores a reference to waitable event associated with the shut down message. 476 // Stores a reference to waitable event associated with the shut down message.
429 WaitableEvent* on_shutdown_event_; 477 WaitableEvent* on_shutdown_event_;
430 478
479 // Set to ignore the request results. This will be set when
480 // MTPDeviceDelegateImplLinux object is about to be deleted.
481 // |on_task_completed_event_| and |on_shutdown_event_| should not be
482 // dereferenced when this is set.
483 base::CancellationFlag cancel_tasks_flag_;
484
431 DISALLOW_COPY_AND_ASSIGN(ReadFileWorker); 485 DISALLOW_COPY_AND_ASSIGN(ReadFileWorker);
432 }; 486 };
433 487
434 // Worker class to read directory contents. Device is already opened for 488 // Worker class to read directory contents. Device is already opened for
435 // communication. 489 // communication.
436 class ReadDirectoryWorker 490 class ReadDirectoryWorker
437 : public RefCountedThreadSafe<ReadDirectoryWorker, 491 : public RefCountedThreadSafe<ReadDirectoryWorker,
438 ReadDirectoryWorkerDeleter> { 492 ReadDirectoryWorkerDeleter> {
439 public: 493 public:
440 // Construct a worker object given the directory |path|. This object is 494 // Construct a worker object given the directory |path|. This object is
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 void Run() { 530 void Run() {
477 if (on_shutdown_event_->IsSignaled()) { 531 if (on_shutdown_event_->IsSignaled()) {
478 // Process is in shutdown mode. 532 // Process is in shutdown mode.
479 // Do not post any task on |media_task_runner_|. 533 // Do not post any task on |media_task_runner_|.
480 return; 534 return;
481 } 535 }
482 536
483 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 537 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
484 Bind(&ReadDirectoryWorker::DoWorkOnUIThread, this)); 538 Bind(&ReadDirectoryWorker::DoWorkOnUIThread, this));
485 on_task_completed_event_->Wait(); 539 on_task_completed_event_->Wait();
540 if (on_shutdown_event_->IsSignaled())
541 cancel_tasks_flag_.Set();
486 } 542 }
487 543
488 // Returns the directory entries for the given directory path. 544 // Returns the directory entries for the given directory path.
489 const std::vector<MtpFileEntry>& get_file_entries() const { 545 const std::vector<MtpFileEntry>& get_file_entries() const {
490 return file_entries_; 546 return file_entries_;
491 } 547 }
492 548
493 // Returns the |media_task_runner_| associated with this worker object. 549 // Returns the |media_task_runner_| associated with this worker object.
494 // This function is exposed for WorkerDeleter struct to access the 550 // This function is exposed for WorkerDeleter struct to access the
495 // |media_task_runner_|. 551 // |media_task_runner_|.
496 SequencedTaskRunner* media_task_runner() const { 552 SequencedTaskRunner* media_task_runner() const {
497 return media_task_runner_.get(); 553 return media_task_runner_.get();
498 } 554 }
499 555
500 private: 556 private:
501 friend struct WorkerDeleter<ReadDirectoryWorker>; 557 friend struct WorkerDeleter<ReadDirectoryWorker>;
502 friend class DeleteHelper<ReadDirectoryWorker>; 558 friend class DeleteHelper<ReadDirectoryWorker>;
503 friend class RefCountedThreadSafe<ReadDirectoryWorker, 559 friend class RefCountedThreadSafe<ReadDirectoryWorker,
504 ReadDirectoryWorkerDeleter>; 560 ReadDirectoryWorkerDeleter>;
505 561
506 // Destructed via ReadDirectoryWorkerDeleter. 562 // Destructed via ReadDirectoryWorkerDeleter.
507 virtual ~ReadDirectoryWorker() { 563 virtual ~ReadDirectoryWorker() {
508 // This object must be destructed on |media_task_runner_|. 564 // This object must be destructed on |media_task_runner_|.
509 } 565 }
510 566
511 // Dispatches a request to MediaTransferProtocolManager to read the directory 567 // Dispatches a request to MediaTransferProtocolManager to read the directory
512 // entries. This is called on UI thread. 568 // entries. This is called on UI thread.
513 void DoWorkOnUIThread() { 569 void DoWorkOnUIThread() {
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
571 if (cancel_tasks_flag_.IsSet())
572 return;
515 573
516 if (!dir_path_.empty()) { 574 if (!dir_path_.empty()) {
517 GetMediaTransferProtocolManager()->ReadDirectoryByPath( 575 GetMediaTransferProtocolManager()->ReadDirectoryByPath(
518 device_handle_, dir_path_, 576 device_handle_, dir_path_,
519 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this)); 577 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this));
520 } else { 578 } else {
521 GetMediaTransferProtocolManager()->ReadDirectoryById( 579 GetMediaTransferProtocolManager()->ReadDirectoryById(
522 device_handle_, dir_entry_id_, 580 device_handle_, dir_entry_id_,
523 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this)); 581 Bind(&ReadDirectoryWorker::OnDidWorkOnUIThread, this));
524 } 582 }
525 } 583 }
526 584
527 // Query callback for DoWorkOnUIThread(). On success, |file_entries| has the 585 // Query callback for DoWorkOnUIThread(). On success, |file_entries| has the
528 // directory file entries. |error| is true if there was an error. This 586 // directory file entries. |error| is true if there was an error. This
529 // function signals to unblock |media_task_runner_|. 587 // function signals to unblock |media_task_runner_|.
530 void OnDidWorkOnUIThread(const std::vector<MtpFileEntry>& file_entries, 588 void OnDidWorkOnUIThread(const std::vector<MtpFileEntry>& file_entries,
531 bool error) { 589 bool error) {
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
591 if (cancel_tasks_flag_.IsSet())
592 return;
593
533 if (!error) 594 if (!error)
534 file_entries_ = file_entries; 595 file_entries_ = file_entries;
535 on_task_completed_event_->Signal(); 596 on_task_completed_event_->Signal();
536 } 597 }
537 598
538 // Stores the device handle to communicate with storage device. 599 // Stores the device handle to communicate with storage device.
539 const std::string device_handle_; 600 const std::string device_handle_;
540 601
541 // Stores the directory path whose contents needs to be listed. 602 // Stores the directory path whose contents needs to be listed.
542 const std::string dir_path_; 603 const std::string dir_path_;
(...skipping 10 matching lines...) Expand all
553 // TODO(kmadhusu): Remove this WaitableEvent after modifying the 614 // TODO(kmadhusu): Remove this WaitableEvent after modifying the
554 // DeviceMediaFileUtil functions as asynchronous functions. 615 // DeviceMediaFileUtil functions as asynchronous functions.
555 WaitableEvent* on_task_completed_event_; 616 WaitableEvent* on_task_completed_event_;
556 617
557 // Stores a reference to waitable event associated with the shut down message. 618 // Stores a reference to waitable event associated with the shut down message.
558 WaitableEvent* on_shutdown_event_; 619 WaitableEvent* on_shutdown_event_;
559 620
560 // Stores the result of read directory request. 621 // Stores the result of read directory request.
561 std::vector<MtpFileEntry> file_entries_; 622 std::vector<MtpFileEntry> file_entries_;
562 623
624 // Set to ignore the request results. This will be set when
625 // MTPDeviceDelegateImplLinux object is about to be deleted.
626 // |on_task_completed_event_| and |on_shutdown_event_| should not be
627 // dereferenced when this is set.
628 base::CancellationFlag cancel_tasks_flag_;
629
563 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryWorker); 630 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryWorker);
564 }; 631 };
565 632
566 // Simply enumerate each files from a given file entry list. 633 // Simply enumerate each files from a given file entry list.
567 // Used to enumerate top-level files of an media file system. 634 // Used to enumerate top-level files of an media file system.
568 class MediaFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { 635 class MediaFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
569 public: 636 public:
570 explicit MediaFileEnumerator(const std::vector<MtpFileEntry>& entries) 637 explicit MediaFileEnumerator(const std::vector<MtpFileEntry>& entries)
571 : file_entries_(entries), 638 : file_entries_(entries),
572 file_entry_iter_(file_entries_.begin()) { 639 file_entry_iter_(file_entries_.begin()) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 const std::string& device_location) 792 const std::string& device_location)
726 : device_path_(device_location), 793 : device_path_(device_location),
727 on_task_completed_event_(false, false), 794 on_task_completed_event_(false, false),
728 on_shutdown_event_(true, false) { 795 on_shutdown_event_(true, false) {
729 CHECK(!device_path_.empty()); 796 CHECK(!device_path_.empty());
730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 797 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
731 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 798 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
732 base::SequencedWorkerPool::SequenceToken media_sequence_token = 799 base::SequencedWorkerPool::SequenceToken media_sequence_token =
733 pool->GetNamedSequenceToken("media-task-runner"); 800 pool->GetNamedSequenceToken("media-task-runner");
734 media_task_runner_ = pool->GetSequencedTaskRunner(media_sequence_token); 801 media_task_runner_ = pool->GetSequencedTaskRunner(media_sequence_token);
735 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
736 content::NotificationService::AllSources());
737
738 DCHECK(media_task_runner_);
739 }
740
741 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
742 registrar_.RemoveAll();
743 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
744 GetMediaTransferProtocolManager()->CloseStorage(device_handle_,
745 Bind(&DoNothing));
746 } 802 }
747 803
748 PlatformFileError MTPDeviceDelegateImplLinux::GetFileInfo( 804 PlatformFileError MTPDeviceDelegateImplLinux::GetFileInfo(
749 const FilePath& file_path, 805 const FilePath& file_path,
750 PlatformFileInfo* file_info) { 806 PlatformFileInfo* file_info) {
751 if (!LazyInit()) 807 if (!LazyInit())
752 return base::PLATFORM_FILE_ERROR_FAILED; 808 return base::PLATFORM_FILE_ERROR_FAILED;
753 809
754 scoped_refptr<GetFileInfoWorker> worker(new GetFileInfoWorker( 810 scoped_refptr<GetFileInfoWorker> worker(new GetFileInfoWorker(
755 device_handle_, GetDeviceRelativePath(device_path_, file_path.value()), 811 device_handle_, GetDeviceRelativePath(device_path_, file_path.value()),
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 // Modify the last modified time to null. This prevents the time stamp 875 // Modify the last modified time to null. This prevents the time stamp
820 // verfication in LocalFileStreamReader. 876 // verfication in LocalFileStreamReader.
821 file_info->last_modified = base::Time(); 877 file_info->last_modified = base::Time();
822 return error; 878 return error;
823 } 879 }
824 880
825 SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() { 881 SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() {
826 return media_task_runner_.get(); 882 return media_task_runner_.get();
827 } 883 }
828 884
829 void MTPDeviceDelegateImplLinux::DeleteOnCorrectThread() const { 885 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
830 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 886 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
831 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 887 // Caution: This function is called on the IO thread. Access only the thread
832 return; 888 // safe member variables in this function. Do all the clean up operations in
833 } 889 // DeleteDelegateOnTaskRunner().
834 delete this; 890 on_shutdown_event_.Signal();
891 on_task_completed_event_.Signal();
892 media_task_runner_->PostTask(
893 FROM_HERE,
894 base::Bind(&MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner,
895 base::Unretained(this)));
835 } 896 }
836 897
837 void MTPDeviceDelegateImplLinux::Observe( 898 base::WeakPtr<fileapi::MTPDeviceDelegate> MTPDeviceDelegateImplLinux::
838 int type, 899 GetAsWeakPtrOnIOThread() {
839 const content::NotificationSource& source, 900 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
840 const content::NotificationDetails& details) { 901 base::WeakPtr<fileapi::MTPDeviceDelegate> delegate = AsWeakPtr();
841 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); 902 // The weak pointer is instantiated on the IO thread, but only accessed on
842 on_shutdown_event_.Signal(); 903 // |media_task_runner_|. Therefore, detach from the current thread.
843 on_task_completed_event_.Signal(); 904 DetachFromThread();
905 return delegate;
906 }
907
908 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
909 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
910 // Do all the clean up operations on DeleteDelegateOnTaskRunner().
844 } 911 }
845 912
846 bool MTPDeviceDelegateImplLinux::LazyInit() { 913 bool MTPDeviceDelegateImplLinux::LazyInit() {
847 DCHECK(media_task_runner_); 914 DCHECK(media_task_runner_);
848 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); 915 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
849 916
850 if (!device_handle_.empty()) 917 if (!device_handle_.empty())
851 return true; // Already successfully initialized. 918 return true; // Already successfully initialized.
852 919
853 std::string storage_name; 920 std::string storage_name;
854 RemoveChars(device_path_, kRootPath, &storage_name); 921 RemoveChars(device_path_, kRootPath, &storage_name);
855 DCHECK(!storage_name.empty()); 922 DCHECK(!storage_name.empty());
856 scoped_refptr<OpenStorageWorker> worker(new OpenStorageWorker( 923 scoped_refptr<OpenStorageWorker> worker(new OpenStorageWorker(
857 storage_name, media_task_runner_, &on_task_completed_event_, 924 storage_name, media_task_runner_, &on_task_completed_event_,
858 &on_shutdown_event_)); 925 &on_shutdown_event_));
859 worker->Run(); 926 worker->Run();
860 device_handle_ = worker->device_handle(); 927 device_handle_ = worker->device_handle();
861 return !device_handle_.empty(); 928 return !device_handle_.empty();
862 } 929 }
863 930
931 void MTPDeviceDelegateImplLinux::DeleteDelegateOnTaskRunner() {
932 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
933 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
934 Bind(&CloseStorageOnUIThread, device_handle_));
935 delete this;
936 }
937
864 } // namespace chrome 938 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/media_gallery/mtp_device_delegate_impl_linux.h ('k') | webkit/fileapi/file_system_operation_context.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698