Make multiple-connections.html less aggressive.
[chromium-blink-merge.git] / device / media_transfer_protocol / media_transfer_protocol_manager.cc
blob314c2b8f73c0f3eab4ce98461136a7d51215bab4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
7 #include <algorithm>
8 #include <map>
9 #include <queue>
10 #include <set>
11 #include <utility>
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/location.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/sequenced_task_runner.h"
19 #include "base/stl_util.h"
20 #include "base/threading/thread_checker.h"
21 #include "dbus/bus.h"
22 #include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h"
23 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
24 #include "device/media_transfer_protocol/mtp_storage_info.pb.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
27 #if defined(OS_CHROMEOS)
28 #include "chromeos/dbus/dbus_thread_manager.h"
29 #endif
31 namespace device {
33 namespace {
35 MediaTransferProtocolManager* g_media_transfer_protocol_manager = NULL;
37 // When reading directory entries, this is the number of entries for
38 // GetFileInfo() to read in one operation. If set too low, efficiency goes down
39 // slightly due to the overhead of D-Bus calls. If set too high, then slow
40 // devices may trigger a D-Bus timeout.
41 // The value below is a good initial estimate.
42 const size_t kFileInfoToFetchChunkSize = 25;
44 // On the first call to GetFileInfo, the offset to use is 0.
45 const size_t kInitialOffset = 0;
47 // The MediaTransferProtocolManager implementation.
48 class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
49 public:
50 explicit MediaTransferProtocolManagerImpl(
51 scoped_refptr<base::SequencedTaskRunner> task_runner)
52 : weak_ptr_factory_(this) {
53 #if defined(OS_CHROMEOS)
54 DCHECK(!task_runner.get());
55 #else
56 DCHECK(task_runner.get());
57 dbus::Bus::Options options;
58 options.bus_type = dbus::Bus::SYSTEM;
59 options.connection_type = dbus::Bus::PRIVATE;
60 options.dbus_task_runner = task_runner;
61 session_bus_ = new dbus::Bus(options);
62 #endif
64 if (GetBus()) {
65 // Listen for future mtpd service owner changes, in case it is not
66 // available right now. There is no guarantee on Linux or ChromeOS that
67 // mtpd is running already.
68 mtpd_owner_changed_callback_ = base::Bind(
69 &MediaTransferProtocolManagerImpl::FinishSetupOnOriginThread,
70 weak_ptr_factory_.GetWeakPtr());
71 GetBus()->ListenForServiceOwnerChange(mtpd::kMtpdServiceName,
72 mtpd_owner_changed_callback_);
73 GetBus()->GetServiceOwner(mtpd::kMtpdServiceName,
74 mtpd_owner_changed_callback_);
78 ~MediaTransferProtocolManagerImpl() override {
79 DCHECK(g_media_transfer_protocol_manager);
80 g_media_transfer_protocol_manager = NULL;
81 if (GetBus()) {
82 GetBus()->UnlistenForServiceOwnerChange(mtpd::kMtpdServiceName,
83 mtpd_owner_changed_callback_);
86 #if !defined(OS_CHROMEOS)
87 session_bus_->GetDBusTaskRunner()->PostTask(
88 FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, session_bus_));
89 #endif
91 VLOG(1) << "MediaTransferProtocolManager Shutdown completed";
94 // MediaTransferProtocolManager override.
95 void AddObserver(Observer* observer) override {
96 DCHECK(thread_checker_.CalledOnValidThread());
97 observers_.AddObserver(observer);
100 // MediaTransferProtocolManager override.
101 void RemoveObserver(Observer* observer) override {
102 DCHECK(thread_checker_.CalledOnValidThread());
103 observers_.RemoveObserver(observer);
106 // MediaTransferProtocolManager override.
107 const std::vector<std::string> GetStorages() const override {
108 DCHECK(thread_checker_.CalledOnValidThread());
109 std::vector<std::string> storages;
110 for (StorageInfoMap::const_iterator it = storage_info_map_.begin();
111 it != storage_info_map_.end();
112 ++it) {
113 storages.push_back(it->first);
115 return storages;
118 // MediaTransferProtocolManager override.
119 const MtpStorageInfo* GetStorageInfo(
120 const std::string& storage_name) const override {
121 DCHECK(thread_checker_.CalledOnValidThread());
122 StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name);
123 return it != storage_info_map_.end() ? &it->second : NULL;
126 // MediaTransferProtocolManager override.
127 void OpenStorage(const std::string& storage_name,
128 const std::string& mode,
129 const OpenStorageCallback& callback) override {
130 DCHECK(thread_checker_.CalledOnValidThread());
131 if (!ContainsKey(storage_info_map_, storage_name) || !mtp_client_) {
132 callback.Run(std::string(), true);
133 return;
135 open_storage_callbacks_.push(callback);
136 mtp_client_->OpenStorage(
137 storage_name,
138 mode,
139 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage,
140 weak_ptr_factory_.GetWeakPtr()),
141 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError,
142 weak_ptr_factory_.GetWeakPtr()));
145 // MediaTransferProtocolManager override.
146 void CloseStorage(const std::string& storage_handle,
147 const CloseStorageCallback& callback) override {
148 DCHECK(thread_checker_.CalledOnValidThread());
149 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
150 callback.Run(true);
151 return;
153 close_storage_callbacks_.push(std::make_pair(callback, storage_handle));
154 mtp_client_->CloseStorage(
155 storage_handle,
156 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage,
157 weak_ptr_factory_.GetWeakPtr()),
158 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError,
159 weak_ptr_factory_.GetWeakPtr()));
162 void CreateDirectory(const std::string& storage_handle,
163 const uint32 parent_id,
164 const std::string& directory_name,
165 const CreateDirectoryCallback& callback) override {
166 DCHECK(thread_checker_.CalledOnValidThread());
167 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
168 callback.Run(true /* error */);
169 return;
171 create_directory_callbacks_.push(callback);
172 mtp_client_->CreateDirectory(
173 storage_handle, parent_id, directory_name,
174 base::Bind(&MediaTransferProtocolManagerImpl::OnCreateDirectory,
175 weak_ptr_factory_.GetWeakPtr()),
176 base::Bind(&MediaTransferProtocolManagerImpl::OnCreateDirectoryError,
177 weak_ptr_factory_.GetWeakPtr()));
180 // MediaTransferProtocolManager override.
181 void ReadDirectory(const std::string& storage_handle,
182 const uint32 file_id,
183 const size_t max_size,
184 const ReadDirectoryCallback& callback) override {
185 DCHECK(thread_checker_.CalledOnValidThread());
186 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
187 callback.Run(std::vector<MtpFileEntry>(),
188 false /* no more entries */,
189 true /* error */);
190 return;
192 read_directory_callbacks_.push(callback);
193 mtp_client_->ReadDirectoryEntryIds(
194 storage_handle, file_id,
195 base::Bind(&MediaTransferProtocolManagerImpl::
196 OnReadDirectoryEntryIdsToReadDirectory,
197 weak_ptr_factory_.GetWeakPtr(), storage_handle, max_size),
198 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
199 weak_ptr_factory_.GetWeakPtr()));
202 // MediaTransferProtocolManager override.
203 void ReadFileChunk(const std::string& storage_handle,
204 uint32 file_id,
205 uint32 offset,
206 uint32 count,
207 const ReadFileCallback& callback) override {
208 DCHECK(thread_checker_.CalledOnValidThread());
209 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
210 callback.Run(std::string(), true);
211 return;
213 read_file_callbacks_.push(callback);
214 mtp_client_->ReadFileChunk(
215 storage_handle, file_id, offset, count,
216 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile,
217 weak_ptr_factory_.GetWeakPtr()),
218 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError,
219 weak_ptr_factory_.GetWeakPtr()));
222 void GetFileInfo(const std::string& storage_handle,
223 uint32 file_id,
224 const GetFileInfoCallback& callback) override {
225 DCHECK(thread_checker_.CalledOnValidThread());
226 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
227 callback.Run(MtpFileEntry(), true);
228 return;
230 std::vector<uint32> file_ids;
231 file_ids.push_back(file_id);
232 get_file_info_callbacks_.push(callback);
233 mtp_client_->GetFileInfo(
234 storage_handle,
235 file_ids,
236 kInitialOffset,
237 file_ids.size(),
238 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo,
239 weak_ptr_factory_.GetWeakPtr()),
240 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError,
241 weak_ptr_factory_.GetWeakPtr()));
244 void RenameObject(const std::string& storage_handle,
245 const uint32 object_id,
246 const std::string& new_name,
247 const RenameObjectCallback& callback) override {
248 DCHECK(thread_checker_.CalledOnValidThread());
249 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
250 callback.Run(true /* error */);
251 return;
253 rename_object_callbacks_.push(callback);
254 mtp_client_->RenameObject(
255 storage_handle, object_id, new_name,
256 base::Bind(&MediaTransferProtocolManagerImpl::OnRenameObject,
257 weak_ptr_factory_.GetWeakPtr()),
258 base::Bind(&MediaTransferProtocolManagerImpl::OnRenameObjectError,
259 weak_ptr_factory_.GetWeakPtr()));
262 void CopyFileFromLocal(const std::string& storage_handle,
263 const int source_file_descriptor,
264 const uint32 parent_id,
265 const std::string& file_name,
266 const CopyFileFromLocalCallback& callback) override {
267 DCHECK(thread_checker_.CalledOnValidThread());
268 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
269 callback.Run(true /* error */);
270 return;
272 copy_file_from_local_callbacks_.push(callback);
273 mtp_client_->CopyFileFromLocal(
274 storage_handle, source_file_descriptor, parent_id, file_name,
275 base::Bind(&MediaTransferProtocolManagerImpl::OnCopyFileFromLocal,
276 weak_ptr_factory_.GetWeakPtr()),
277 base::Bind(&MediaTransferProtocolManagerImpl::OnCopyFileFromLocalError,
278 weak_ptr_factory_.GetWeakPtr()));
281 void DeleteObject(const std::string& storage_handle,
282 const uint32 object_id,
283 const DeleteObjectCallback& callback) override {
284 DCHECK(thread_checker_.CalledOnValidThread());
285 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
286 callback.Run(true /* error */);
287 return;
289 delete_object_callbacks_.push(callback);
290 mtp_client_->DeleteObject(
291 storage_handle, object_id,
292 base::Bind(&MediaTransferProtocolManagerImpl::OnDeleteObject,
293 weak_ptr_factory_.GetWeakPtr()),
294 base::Bind(&MediaTransferProtocolManagerImpl::OnDeleteObjectError,
295 weak_ptr_factory_.GetWeakPtr()));
298 private:
299 // Map of storage names to storage info.
300 typedef std::map<std::string, MtpStorageInfo> StorageInfoMap;
301 // Callback queues - DBus communication is in-order, thus callbacks are
302 // received in the same order as the requests.
303 typedef std::queue<OpenStorageCallback> OpenStorageCallbackQueue;
304 // (callback, handle)
305 typedef std::queue<std::pair<CloseStorageCallback, std::string>
306 > CloseStorageCallbackQueue;
307 typedef std::queue<CreateDirectoryCallback> CreateDirectoryCallbackQueue;
308 typedef std::queue<ReadDirectoryCallback> ReadDirectoryCallbackQueue;
309 typedef std::queue<ReadFileCallback> ReadFileCallbackQueue;
310 typedef std::queue<GetFileInfoCallback> GetFileInfoCallbackQueue;
311 typedef std::queue<RenameObjectCallback> RenameObjectCallbackQueue;
312 typedef std::queue<CopyFileFromLocalCallback> CopyFileFromLocalCallbackQueue;
313 typedef std::queue<DeleteObjectCallback> DeleteObjectCallbackQueue;
315 void OnStorageAttached(const std::string& storage_name) {
316 DCHECK(thread_checker_.CalledOnValidThread());
317 mtp_client_->GetStorageInfo(
318 storage_name,
319 base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo,
320 weak_ptr_factory_.GetWeakPtr()),
321 base::Bind(&base::DoNothing));
324 void OnStorageDetached(const std::string& storage_name) {
325 DCHECK(thread_checker_.CalledOnValidThread());
326 if (storage_info_map_.erase(storage_name) == 0) {
327 // This can happen for a storage where
328 // MediaTransferProtocolDaemonClient::GetStorageInfo() failed.
329 // Return to avoid giving observers phantom detach events.
330 return;
332 FOR_EACH_OBSERVER(Observer,
333 observers_,
334 StorageChanged(false /* detach */, storage_name));
337 void OnStorageChanged(bool is_attach, const std::string& storage_name) {
338 DCHECK(thread_checker_.CalledOnValidThread());
339 DCHECK(mtp_client_);
340 if (is_attach)
341 OnStorageAttached(storage_name);
342 else
343 OnStorageDetached(storage_name);
346 void OnEnumerateStorages(const std::vector<std::string>& storage_names) {
347 DCHECK(thread_checker_.CalledOnValidThread());
348 DCHECK(mtp_client_);
349 for (size_t i = 0; i < storage_names.size(); ++i) {
350 if (ContainsKey(storage_info_map_, storage_names[i])) {
351 // OnStorageChanged() might have gotten called first.
352 continue;
354 OnStorageAttached(storage_names[i]);
358 void OnGetStorageInfo(const MtpStorageInfo& storage_info) {
359 DCHECK(thread_checker_.CalledOnValidThread());
360 const std::string& storage_name = storage_info.storage_name();
361 if (ContainsKey(storage_info_map_, storage_name)) {
362 // This should not happen, since MediaTransferProtocolManagerImpl should
363 // only call EnumerateStorages() once, which populates |storage_info_map_|
364 // with the already-attached devices.
365 // After that, all incoming signals are either for new storage
366 // attachments, which should not be in |storage_info_map_|, or for
367 // storage detachments, which do not add to |storage_info_map_|.
368 // Return to avoid giving observers phantom detach events.
369 NOTREACHED();
370 return;
373 // New storage. Add it and let the observers know.
374 storage_info_map_.insert(std::make_pair(storage_name, storage_info));
375 FOR_EACH_OBSERVER(Observer,
376 observers_,
377 StorageChanged(true /* is attach */, storage_name));
380 void OnOpenStorage(const std::string& handle) {
381 DCHECK(thread_checker_.CalledOnValidThread());
382 if (!ContainsKey(handles_, handle)) {
383 handles_.insert(handle);
384 open_storage_callbacks_.front().Run(handle, false);
385 } else {
386 NOTREACHED();
387 open_storage_callbacks_.front().Run(std::string(), true);
389 open_storage_callbacks_.pop();
392 void OnOpenStorageError() {
393 open_storage_callbacks_.front().Run(std::string(), true);
394 open_storage_callbacks_.pop();
397 void OnCloseStorage() {
398 DCHECK(thread_checker_.CalledOnValidThread());
399 const std::string& handle = close_storage_callbacks_.front().second;
400 if (ContainsKey(handles_, handle)) {
401 handles_.erase(handle);
402 close_storage_callbacks_.front().first.Run(false);
403 } else {
404 NOTREACHED();
405 close_storage_callbacks_.front().first.Run(true);
407 close_storage_callbacks_.pop();
410 void OnCloseStorageError() {
411 DCHECK(thread_checker_.CalledOnValidThread());
412 close_storage_callbacks_.front().first.Run(true);
413 close_storage_callbacks_.pop();
416 void OnCreateDirectory() {
417 DCHECK(thread_checker_.CalledOnValidThread());
418 create_directory_callbacks_.front().Run(false /* no error */);
419 create_directory_callbacks_.pop();
422 void OnCreateDirectoryError() {
423 DCHECK(thread_checker_.CalledOnValidThread());
424 create_directory_callbacks_.front().Run(true /* error */);
425 create_directory_callbacks_.pop();
428 void OnReadDirectoryEntryIdsToReadDirectory(
429 const std::string& storage_handle,
430 const size_t max_size,
431 const std::vector<uint32>& file_ids) {
432 DCHECK(thread_checker_.CalledOnValidThread());
434 if (file_ids.empty()) {
435 OnGotDirectoryEntries(storage_handle, file_ids, kInitialOffset, max_size,
436 file_ids, std::vector<MtpFileEntry>());
437 return;
440 std::vector<uint32> sorted_file_ids = file_ids;
441 std::sort(sorted_file_ids.begin(), sorted_file_ids.end());
443 const size_t chunk_size =
444 max_size == 0 ? kFileInfoToFetchChunkSize
445 : std::min(max_size, kFileInfoToFetchChunkSize);
447 mtp_client_->GetFileInfo(
448 storage_handle, file_ids, kInitialOffset, chunk_size,
449 base::Bind(&MediaTransferProtocolManagerImpl::OnGotDirectoryEntries,
450 weak_ptr_factory_.GetWeakPtr(), storage_handle, file_ids,
451 kInitialOffset, max_size, sorted_file_ids),
452 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
453 weak_ptr_factory_.GetWeakPtr()));
456 void OnGotDirectoryEntries(const std::string& storage_handle,
457 const std::vector<uint32>& file_ids,
458 const size_t offset,
459 const size_t max_size,
460 const std::vector<uint32>& sorted_file_ids,
461 const std::vector<MtpFileEntry>& file_entries) {
462 DCHECK(thread_checker_.CalledOnValidThread());
463 DCHECK_EQ(file_ids.size(), sorted_file_ids.size());
465 // Use |sorted_file_ids| to sanity check and make sure the results are a
466 // subset of the requested file ids.
467 for (size_t i = 0; i < file_entries.size(); ++i) {
468 std::vector<uint32>::const_iterator it =
469 std::lower_bound(sorted_file_ids.begin(),
470 sorted_file_ids.end(),
471 file_entries[i].item_id());
472 if (it == sorted_file_ids.end()) {
473 OnReadDirectoryError();
474 return;
478 const size_t directory_size =
479 max_size == 0 ? file_ids.size() : std::min(file_ids.size(), max_size);
480 size_t next_offset = directory_size;
481 if (offset < SIZE_MAX - kFileInfoToFetchChunkSize)
482 next_offset = std::min(next_offset, offset + kFileInfoToFetchChunkSize);
483 bool has_more = next_offset < directory_size;
484 read_directory_callbacks_.front().Run(file_entries,
485 has_more,
486 false /* no error */);
488 if (has_more) {
489 const size_t chunk_size =
490 std::min(directory_size - next_offset, kFileInfoToFetchChunkSize);
492 mtp_client_->GetFileInfo(
493 storage_handle, file_ids, next_offset, chunk_size,
494 base::Bind(&MediaTransferProtocolManagerImpl::OnGotDirectoryEntries,
495 weak_ptr_factory_.GetWeakPtr(), storage_handle, file_ids,
496 next_offset, max_size, sorted_file_ids),
497 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
498 weak_ptr_factory_.GetWeakPtr()));
499 return;
501 read_directory_callbacks_.pop();
504 void OnReadDirectoryError() {
505 DCHECK(thread_checker_.CalledOnValidThread());
506 read_directory_callbacks_.front().Run(std::vector<MtpFileEntry>(),
507 false /* no more entries */,
508 true /* error */);
509 read_directory_callbacks_.pop();
512 void OnReadFile(const std::string& data) {
513 DCHECK(thread_checker_.CalledOnValidThread());
514 read_file_callbacks_.front().Run(data, false);
515 read_file_callbacks_.pop();
518 void OnReadFileError() {
519 DCHECK(thread_checker_.CalledOnValidThread());
520 read_file_callbacks_.front().Run(std::string(), true);
521 read_file_callbacks_.pop();
524 void OnGetFileInfo(const std::vector<MtpFileEntry>& entries) {
525 DCHECK(thread_checker_.CalledOnValidThread());
526 if (entries.size() == 1) {
527 get_file_info_callbacks_.front().Run(entries[0], false /* no error */);
528 get_file_info_callbacks_.pop();
529 } else {
530 OnGetFileInfoError();
534 void OnGetFileInfoError() {
535 DCHECK(thread_checker_.CalledOnValidThread());
536 get_file_info_callbacks_.front().Run(MtpFileEntry(), true);
537 get_file_info_callbacks_.pop();
540 void OnRenameObject() {
541 DCHECK(thread_checker_.CalledOnValidThread());
542 rename_object_callbacks_.front().Run(false /* no error */);
543 rename_object_callbacks_.pop();
546 void OnRenameObjectError() {
547 DCHECK(thread_checker_.CalledOnValidThread());
548 rename_object_callbacks_.front().Run(true /* error */);
549 rename_object_callbacks_.pop();
552 void OnCopyFileFromLocal() {
553 DCHECK(thread_checker_.CalledOnValidThread());
554 copy_file_from_local_callbacks_.front().Run(false /* no error */);
555 copy_file_from_local_callbacks_.pop();
558 void OnCopyFileFromLocalError() {
559 DCHECK(thread_checker_.CalledOnValidThread());
560 copy_file_from_local_callbacks_.front().Run(true /* error */);
561 copy_file_from_local_callbacks_.pop();
564 void OnDeleteObject() {
565 DCHECK(thread_checker_.CalledOnValidThread());
566 delete_object_callbacks_.front().Run(false /* no error */);
567 delete_object_callbacks_.pop();
570 void OnDeleteObjectError() {
571 DCHECK(thread_checker_.CalledOnValidThread());
572 delete_object_callbacks_.front().Run(true /* error */);
573 delete_object_callbacks_.pop();
576 // Get the Bus object used to communicate with mtpd.
577 dbus::Bus* GetBus() {
578 DCHECK(thread_checker_.CalledOnValidThread());
579 #if defined(OS_CHROMEOS)
580 return chromeos::DBusThreadManager::Get()->GetSystemBus();
581 #else
582 return session_bus_.get();
583 #endif
586 // Callback to finish initialization after figuring out if the mtpd service
587 // has an owner, or if the service owner has changed.
588 // |mtpd_service_owner| contains the name of the current owner, if any.
589 void FinishSetupOnOriginThread(const std::string& mtpd_service_owner) {
590 DCHECK(thread_checker_.CalledOnValidThread());
592 if (mtpd_service_owner == current_mtpd_owner_)
593 return;
595 // In the case of a new service owner, clear |storage_info_map_|.
596 // Assume all storages have been disconnected. If there is a new service
597 // owner, reconnecting to it will reconnect all the storages as well.
599 // Save a copy of |storage_info_map_| keys as |storage_info_map_| can
600 // change in OnStorageDetached().
601 std::vector<std::string> storage_names;
602 for (StorageInfoMap::const_iterator it = storage_info_map_.begin();
603 it != storage_info_map_.end();
604 ++it) {
605 storage_names.push_back(it->first);
607 for (size_t i = 0; i != storage_names.size(); ++i)
608 OnStorageDetached(storage_names[i]);
610 if (mtpd_service_owner.empty()) {
611 current_mtpd_owner_.clear();
612 mtp_client_.reset();
613 return;
616 current_mtpd_owner_ = mtpd_service_owner;
618 mtp_client_.reset(MediaTransferProtocolDaemonClient::Create(GetBus()));
620 // Set up signals and start initializing |storage_info_map_|.
621 mtp_client_->ListenForChanges(
622 base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged,
623 weak_ptr_factory_.GetWeakPtr()));
624 mtp_client_->EnumerateStorages(
625 base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages,
626 weak_ptr_factory_.GetWeakPtr()),
627 base::Bind(&base::DoNothing));
630 // Mtpd DBus client.
631 scoped_ptr<MediaTransferProtocolDaemonClient> mtp_client_;
633 #if !defined(OS_CHROMEOS)
634 // And a D-Bus session for talking to mtpd.
635 scoped_refptr<dbus::Bus> session_bus_;
636 #endif
638 // Device attachment / detachment observers.
639 ObserverList<Observer> observers_;
641 // Map to keep track of attached storages by name.
642 StorageInfoMap storage_info_map_;
644 // Set of open storage handles.
645 std::set<std::string> handles_;
647 dbus::Bus::GetServiceOwnerCallback mtpd_owner_changed_callback_;
649 std::string current_mtpd_owner_;
651 // Queued callbacks.
652 OpenStorageCallbackQueue open_storage_callbacks_;
653 CloseStorageCallbackQueue close_storage_callbacks_;
654 CreateDirectoryCallbackQueue create_directory_callbacks_;
655 ReadDirectoryCallbackQueue read_directory_callbacks_;
656 ReadFileCallbackQueue read_file_callbacks_;
657 GetFileInfoCallbackQueue get_file_info_callbacks_;
658 RenameObjectCallbackQueue rename_object_callbacks_;
659 CopyFileFromLocalCallbackQueue copy_file_from_local_callbacks_;
660 DeleteObjectCallbackQueue delete_object_callbacks_;
662 base::ThreadChecker thread_checker_;
664 base::WeakPtrFactory<MediaTransferProtocolManagerImpl> weak_ptr_factory_;
666 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl);
669 } // namespace
671 // static
672 MediaTransferProtocolManager* MediaTransferProtocolManager::Initialize(
673 scoped_refptr<base::SequencedTaskRunner> task_runner) {
674 DCHECK(!g_media_transfer_protocol_manager);
676 g_media_transfer_protocol_manager =
677 new MediaTransferProtocolManagerImpl(task_runner);
678 VLOG(1) << "MediaTransferProtocolManager initialized";
680 return g_media_transfer_protocol_manager;
683 } // namespace device