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

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