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"
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"
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"
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
{
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());
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
);
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
;
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_
));
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();
113 storages
.push_back(it
->first
);
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 GetStorageInfoFromDevice(
128 const std::string
& storage_name
,
129 const GetStorageInfoFromDeviceCallback
& callback
) override
{
130 DCHECK(thread_checker_
.CalledOnValidThread());
131 if (!ContainsKey(storage_info_map_
, storage_name
) || !mtp_client_
) {
133 callback
.Run(info
, true /* error */);
136 get_storage_info_from_device_callbacks_
.push(callback
);
137 mtp_client_
->GetStorageInfoFromDevice(
140 &MediaTransferProtocolManagerImpl::OnGetStorageInfoFromDevice
,
141 weak_ptr_factory_
.GetWeakPtr()),
143 &MediaTransferProtocolManagerImpl::OnGetStorageInfoFromDeviceError
,
144 weak_ptr_factory_
.GetWeakPtr()));
147 // MediaTransferProtocolManager override.
148 void OpenStorage(const std::string
& storage_name
,
149 const std::string
& mode
,
150 const OpenStorageCallback
& callback
) override
{
151 DCHECK(thread_checker_
.CalledOnValidThread());
152 if (!ContainsKey(storage_info_map_
, storage_name
) || !mtp_client_
) {
153 callback
.Run(std::string(), true);
156 open_storage_callbacks_
.push(callback
);
157 mtp_client_
->OpenStorage(
160 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage
,
161 weak_ptr_factory_
.GetWeakPtr()),
162 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError
,
163 weak_ptr_factory_
.GetWeakPtr()));
166 // MediaTransferProtocolManager override.
167 void CloseStorage(const std::string
& storage_handle
,
168 const CloseStorageCallback
& callback
) override
{
169 DCHECK(thread_checker_
.CalledOnValidThread());
170 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
174 close_storage_callbacks_
.push(std::make_pair(callback
, storage_handle
));
175 mtp_client_
->CloseStorage(
177 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage
,
178 weak_ptr_factory_
.GetWeakPtr()),
179 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError
,
180 weak_ptr_factory_
.GetWeakPtr()));
183 void CreateDirectory(const std::string
& storage_handle
,
184 const uint32 parent_id
,
185 const std::string
& directory_name
,
186 const CreateDirectoryCallback
& callback
) override
{
187 DCHECK(thread_checker_
.CalledOnValidThread());
188 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
189 callback
.Run(true /* error */);
192 create_directory_callbacks_
.push(callback
);
193 mtp_client_
->CreateDirectory(
194 storage_handle
, parent_id
, directory_name
,
195 base::Bind(&MediaTransferProtocolManagerImpl::OnCreateDirectory
,
196 weak_ptr_factory_
.GetWeakPtr()),
197 base::Bind(&MediaTransferProtocolManagerImpl::OnCreateDirectoryError
,
198 weak_ptr_factory_
.GetWeakPtr()));
201 // MediaTransferProtocolManager override.
202 void ReadDirectory(const std::string
& storage_handle
,
203 const uint32 file_id
,
204 const size_t max_size
,
205 const ReadDirectoryCallback
& callback
) override
{
206 DCHECK(thread_checker_
.CalledOnValidThread());
207 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
208 callback
.Run(std::vector
<MtpFileEntry
>(),
209 false /* no more entries */,
213 read_directory_callbacks_
.push(callback
);
214 mtp_client_
->ReadDirectoryEntryIds(
215 storage_handle
, file_id
,
216 base::Bind(&MediaTransferProtocolManagerImpl::
217 OnReadDirectoryEntryIdsToReadDirectory
,
218 weak_ptr_factory_
.GetWeakPtr(), storage_handle
, max_size
),
219 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError
,
220 weak_ptr_factory_
.GetWeakPtr()));
223 // MediaTransferProtocolManager override.
224 void ReadFileChunk(const std::string
& storage_handle
,
228 const ReadFileCallback
& callback
) override
{
229 DCHECK(thread_checker_
.CalledOnValidThread());
230 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
231 callback
.Run(std::string(), true);
234 read_file_callbacks_
.push(callback
);
235 mtp_client_
->ReadFileChunk(
236 storage_handle
, file_id
, offset
, count
,
237 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile
,
238 weak_ptr_factory_
.GetWeakPtr()),
239 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError
,
240 weak_ptr_factory_
.GetWeakPtr()));
243 void GetFileInfo(const std::string
& storage_handle
,
245 const GetFileInfoCallback
& callback
) override
{
246 DCHECK(thread_checker_
.CalledOnValidThread());
247 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
248 callback
.Run(MtpFileEntry(), true);
251 std::vector
<uint32
> file_ids
;
252 file_ids
.push_back(file_id
);
253 get_file_info_callbacks_
.push(callback
);
254 mtp_client_
->GetFileInfo(
259 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo
,
260 weak_ptr_factory_
.GetWeakPtr()),
261 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError
,
262 weak_ptr_factory_
.GetWeakPtr()));
265 void RenameObject(const std::string
& storage_handle
,
266 const uint32 object_id
,
267 const std::string
& new_name
,
268 const RenameObjectCallback
& callback
) override
{
269 DCHECK(thread_checker_
.CalledOnValidThread());
270 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
271 callback
.Run(true /* error */);
274 rename_object_callbacks_
.push(callback
);
275 mtp_client_
->RenameObject(
276 storage_handle
, object_id
, new_name
,
277 base::Bind(&MediaTransferProtocolManagerImpl::OnRenameObject
,
278 weak_ptr_factory_
.GetWeakPtr()),
279 base::Bind(&MediaTransferProtocolManagerImpl::OnRenameObjectError
,
280 weak_ptr_factory_
.GetWeakPtr()));
283 void CopyFileFromLocal(const std::string
& storage_handle
,
284 const int source_file_descriptor
,
285 const uint32 parent_id
,
286 const std::string
& file_name
,
287 const CopyFileFromLocalCallback
& callback
) override
{
288 DCHECK(thread_checker_
.CalledOnValidThread());
289 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
290 callback
.Run(true /* error */);
293 copy_file_from_local_callbacks_
.push(callback
);
294 mtp_client_
->CopyFileFromLocal(
295 storage_handle
, source_file_descriptor
, parent_id
, file_name
,
296 base::Bind(&MediaTransferProtocolManagerImpl::OnCopyFileFromLocal
,
297 weak_ptr_factory_
.GetWeakPtr()),
298 base::Bind(&MediaTransferProtocolManagerImpl::OnCopyFileFromLocalError
,
299 weak_ptr_factory_
.GetWeakPtr()));
302 void DeleteObject(const std::string
& storage_handle
,
303 const uint32 object_id
,
304 const DeleteObjectCallback
& callback
) override
{
305 DCHECK(thread_checker_
.CalledOnValidThread());
306 if (!ContainsKey(handles_
, storage_handle
) || !mtp_client_
) {
307 callback
.Run(true /* error */);
310 delete_object_callbacks_
.push(callback
);
311 mtp_client_
->DeleteObject(
312 storage_handle
, object_id
,
313 base::Bind(&MediaTransferProtocolManagerImpl::OnDeleteObject
,
314 weak_ptr_factory_
.GetWeakPtr()),
315 base::Bind(&MediaTransferProtocolManagerImpl::OnDeleteObjectError
,
316 weak_ptr_factory_
.GetWeakPtr()));
320 // Map of storage names to storage info.
321 typedef std::map
<std::string
, MtpStorageInfo
> StorageInfoMap
;
322 typedef std::queue
<GetStorageInfoFromDeviceCallback
>
323 GetStorageInfoFromDeviceCallbackQueue
;
324 // Callback queues - DBus communication is in-order, thus callbacks are
325 // received in the same order as the requests.
326 typedef std::queue
<OpenStorageCallback
> OpenStorageCallbackQueue
;
327 // (callback, handle)
328 typedef std::queue
<std::pair
<CloseStorageCallback
, std::string
>
329 > CloseStorageCallbackQueue
;
330 typedef std::queue
<CreateDirectoryCallback
> CreateDirectoryCallbackQueue
;
331 typedef std::queue
<ReadDirectoryCallback
> ReadDirectoryCallbackQueue
;
332 typedef std::queue
<ReadFileCallback
> ReadFileCallbackQueue
;
333 typedef std::queue
<GetFileInfoCallback
> GetFileInfoCallbackQueue
;
334 typedef std::queue
<RenameObjectCallback
> RenameObjectCallbackQueue
;
335 typedef std::queue
<CopyFileFromLocalCallback
> CopyFileFromLocalCallbackQueue
;
336 typedef std::queue
<DeleteObjectCallback
> DeleteObjectCallbackQueue
;
338 void OnStorageAttached(const std::string
& storage_name
) {
339 DCHECK(thread_checker_
.CalledOnValidThread());
340 mtp_client_
->GetStorageInfo(
342 base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo
,
343 weak_ptr_factory_
.GetWeakPtr()),
344 base::Bind(&base::DoNothing
));
347 void OnStorageDetached(const std::string
& storage_name
) {
348 DCHECK(thread_checker_
.CalledOnValidThread());
349 if (storage_info_map_
.erase(storage_name
) == 0) {
350 // This can happen for a storage where
351 // MediaTransferProtocolDaemonClient::GetStorageInfo() failed.
352 // Return to avoid giving observers phantom detach events.
355 FOR_EACH_OBSERVER(Observer
,
357 StorageChanged(false /* detach */, storage_name
));
360 void OnStorageChanged(bool is_attach
, const std::string
& storage_name
) {
361 DCHECK(thread_checker_
.CalledOnValidThread());
364 OnStorageAttached(storage_name
);
366 OnStorageDetached(storage_name
);
369 void OnEnumerateStorages(const std::vector
<std::string
>& storage_names
) {
370 DCHECK(thread_checker_
.CalledOnValidThread());
372 for (size_t i
= 0; i
< storage_names
.size(); ++i
) {
373 if (ContainsKey(storage_info_map_
, storage_names
[i
])) {
374 // OnStorageChanged() might have gotten called first.
377 OnStorageAttached(storage_names
[i
]);
381 void OnGetStorageInfo(const MtpStorageInfo
& storage_info
) {
382 DCHECK(thread_checker_
.CalledOnValidThread());
383 const std::string
& storage_name
= storage_info
.storage_name();
384 if (ContainsKey(storage_info_map_
, storage_name
)) {
385 // This should not happen, since MediaTransferProtocolManagerImpl should
386 // only call EnumerateStorages() once, which populates |storage_info_map_|
387 // with the already-attached devices.
388 // After that, all incoming signals are either for new storage
389 // attachments, which should not be in |storage_info_map_|, or for
390 // storage detachments, which do not add to |storage_info_map_|.
391 // Return to avoid giving observers phantom detach events.
396 // New storage. Add it and let the observers know.
397 storage_info_map_
.insert(std::make_pair(storage_name
, storage_info
));
398 FOR_EACH_OBSERVER(Observer
,
400 StorageChanged(true /* is attach */, storage_name
));
403 void OnGetStorageInfoFromDevice(const MtpStorageInfo
& storage_info
) {
404 get_storage_info_from_device_callbacks_
.front().Run(storage_info
,
405 false /* no error */);
406 get_storage_info_from_device_callbacks_
.pop();
409 void OnGetStorageInfoFromDeviceError() {
411 get_storage_info_from_device_callbacks_
.front().Run(info
, true /* error */);
412 get_storage_info_from_device_callbacks_
.pop();
415 void OnOpenStorage(const std::string
& handle
) {
416 DCHECK(thread_checker_
.CalledOnValidThread());
417 if (!ContainsKey(handles_
, handle
)) {
418 handles_
.insert(handle
);
419 open_storage_callbacks_
.front().Run(handle
, false);
422 open_storage_callbacks_
.front().Run(std::string(), true);
424 open_storage_callbacks_
.pop();
427 void OnOpenStorageError() {
428 open_storage_callbacks_
.front().Run(std::string(), true);
429 open_storage_callbacks_
.pop();
432 void OnCloseStorage() {
433 DCHECK(thread_checker_
.CalledOnValidThread());
434 const std::string
& handle
= close_storage_callbacks_
.front().second
;
435 if (ContainsKey(handles_
, handle
)) {
436 handles_
.erase(handle
);
437 close_storage_callbacks_
.front().first
.Run(false);
440 close_storage_callbacks_
.front().first
.Run(true);
442 close_storage_callbacks_
.pop();
445 void OnCloseStorageError() {
446 DCHECK(thread_checker_
.CalledOnValidThread());
447 close_storage_callbacks_
.front().first
.Run(true);
448 close_storage_callbacks_
.pop();
451 void OnCreateDirectory() {
452 DCHECK(thread_checker_
.CalledOnValidThread());
453 create_directory_callbacks_
.front().Run(false /* no error */);
454 create_directory_callbacks_
.pop();
457 void OnCreateDirectoryError() {
458 DCHECK(thread_checker_
.CalledOnValidThread());
459 create_directory_callbacks_
.front().Run(true /* error */);
460 create_directory_callbacks_
.pop();
463 void OnReadDirectoryEntryIdsToReadDirectory(
464 const std::string
& storage_handle
,
465 const size_t max_size
,
466 const std::vector
<uint32
>& file_ids
) {
467 DCHECK(thread_checker_
.CalledOnValidThread());
469 if (file_ids
.empty()) {
470 OnGotDirectoryEntries(storage_handle
, file_ids
, kInitialOffset
, max_size
,
471 file_ids
, std::vector
<MtpFileEntry
>());
475 std::vector
<uint32
> sorted_file_ids
= file_ids
;
476 std::sort(sorted_file_ids
.begin(), sorted_file_ids
.end());
478 const size_t chunk_size
=
479 max_size
== 0 ? kFileInfoToFetchChunkSize
480 : std::min(max_size
, kFileInfoToFetchChunkSize
);
482 mtp_client_
->GetFileInfo(
483 storage_handle
, file_ids
, kInitialOffset
, chunk_size
,
484 base::Bind(&MediaTransferProtocolManagerImpl::OnGotDirectoryEntries
,
485 weak_ptr_factory_
.GetWeakPtr(), storage_handle
, file_ids
,
486 kInitialOffset
, max_size
, sorted_file_ids
),
487 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError
,
488 weak_ptr_factory_
.GetWeakPtr()));
491 void OnGotDirectoryEntries(const std::string
& storage_handle
,
492 const std::vector
<uint32
>& file_ids
,
494 const size_t max_size
,
495 const std::vector
<uint32
>& sorted_file_ids
,
496 const std::vector
<MtpFileEntry
>& file_entries
) {
497 DCHECK(thread_checker_
.CalledOnValidThread());
498 DCHECK_EQ(file_ids
.size(), sorted_file_ids
.size());
500 // Use |sorted_file_ids| to sanity check and make sure the results are a
501 // subset of the requested file ids.
502 for (size_t i
= 0; i
< file_entries
.size(); ++i
) {
503 std::vector
<uint32
>::const_iterator it
=
504 std::lower_bound(sorted_file_ids
.begin(),
505 sorted_file_ids
.end(),
506 file_entries
[i
].item_id());
507 if (it
== sorted_file_ids
.end()) {
508 OnReadDirectoryError();
513 const size_t directory_size
=
514 max_size
== 0 ? file_ids
.size() : std::min(file_ids
.size(), max_size
);
515 size_t next_offset
= directory_size
;
516 if (offset
< SIZE_MAX
- kFileInfoToFetchChunkSize
)
517 next_offset
= std::min(next_offset
, offset
+ kFileInfoToFetchChunkSize
);
518 bool has_more
= next_offset
< directory_size
;
519 read_directory_callbacks_
.front().Run(file_entries
,
521 false /* no error */);
524 const size_t chunk_size
=
525 std::min(directory_size
- next_offset
, kFileInfoToFetchChunkSize
);
527 mtp_client_
->GetFileInfo(
528 storage_handle
, file_ids
, next_offset
, chunk_size
,
529 base::Bind(&MediaTransferProtocolManagerImpl::OnGotDirectoryEntries
,
530 weak_ptr_factory_
.GetWeakPtr(), storage_handle
, file_ids
,
531 next_offset
, max_size
, sorted_file_ids
),
532 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError
,
533 weak_ptr_factory_
.GetWeakPtr()));
536 read_directory_callbacks_
.pop();
539 void OnReadDirectoryError() {
540 DCHECK(thread_checker_
.CalledOnValidThread());
541 read_directory_callbacks_
.front().Run(std::vector
<MtpFileEntry
>(),
542 false /* no more entries */,
544 read_directory_callbacks_
.pop();
547 void OnReadFile(const std::string
& data
) {
548 DCHECK(thread_checker_
.CalledOnValidThread());
549 read_file_callbacks_
.front().Run(data
, false);
550 read_file_callbacks_
.pop();
553 void OnReadFileError() {
554 DCHECK(thread_checker_
.CalledOnValidThread());
555 read_file_callbacks_
.front().Run(std::string(), true);
556 read_file_callbacks_
.pop();
559 void OnGetFileInfo(const std::vector
<MtpFileEntry
>& entries
) {
560 DCHECK(thread_checker_
.CalledOnValidThread());
561 if (entries
.size() == 1) {
562 get_file_info_callbacks_
.front().Run(entries
[0], false /* no error */);
563 get_file_info_callbacks_
.pop();
565 OnGetFileInfoError();
569 void OnGetFileInfoError() {
570 DCHECK(thread_checker_
.CalledOnValidThread());
571 get_file_info_callbacks_
.front().Run(MtpFileEntry(), true);
572 get_file_info_callbacks_
.pop();
575 void OnRenameObject() {
576 DCHECK(thread_checker_
.CalledOnValidThread());
577 rename_object_callbacks_
.front().Run(false /* no error */);
578 rename_object_callbacks_
.pop();
581 void OnRenameObjectError() {
582 DCHECK(thread_checker_
.CalledOnValidThread());
583 rename_object_callbacks_
.front().Run(true /* error */);
584 rename_object_callbacks_
.pop();
587 void OnCopyFileFromLocal() {
588 DCHECK(thread_checker_
.CalledOnValidThread());
589 copy_file_from_local_callbacks_
.front().Run(false /* no error */);
590 copy_file_from_local_callbacks_
.pop();
593 void OnCopyFileFromLocalError() {
594 DCHECK(thread_checker_
.CalledOnValidThread());
595 copy_file_from_local_callbacks_
.front().Run(true /* error */);
596 copy_file_from_local_callbacks_
.pop();
599 void OnDeleteObject() {
600 DCHECK(thread_checker_
.CalledOnValidThread());
601 delete_object_callbacks_
.front().Run(false /* no error */);
602 delete_object_callbacks_
.pop();
605 void OnDeleteObjectError() {
606 DCHECK(thread_checker_
.CalledOnValidThread());
607 delete_object_callbacks_
.front().Run(true /* error */);
608 delete_object_callbacks_
.pop();
611 // Get the Bus object used to communicate with mtpd.
612 dbus::Bus
* GetBus() {
613 DCHECK(thread_checker_
.CalledOnValidThread());
614 #if defined(OS_CHROMEOS)
615 return chromeos::DBusThreadManager::Get()->GetSystemBus();
617 return session_bus_
.get();
621 // Callback to finish initialization after figuring out if the mtpd service
622 // has an owner, or if the service owner has changed.
623 // |mtpd_service_owner| contains the name of the current owner, if any.
624 void FinishSetupOnOriginThread(const std::string
& mtpd_service_owner
) {
625 DCHECK(thread_checker_
.CalledOnValidThread());
627 if (mtpd_service_owner
== current_mtpd_owner_
)
630 // In the case of a new service owner, clear |storage_info_map_|.
631 // Assume all storages have been disconnected. If there is a new service
632 // owner, reconnecting to it will reconnect all the storages as well.
634 // Save a copy of |storage_info_map_| keys as |storage_info_map_| can
635 // change in OnStorageDetached().
636 std::vector
<std::string
> storage_names
;
637 for (StorageInfoMap::const_iterator it
= storage_info_map_
.begin();
638 it
!= storage_info_map_
.end();
640 storage_names
.push_back(it
->first
);
642 for (size_t i
= 0; i
!= storage_names
.size(); ++i
)
643 OnStorageDetached(storage_names
[i
]);
645 if (mtpd_service_owner
.empty()) {
646 current_mtpd_owner_
.clear();
651 current_mtpd_owner_
= mtpd_service_owner
;
653 mtp_client_
.reset(MediaTransferProtocolDaemonClient::Create(GetBus()));
655 // Set up signals and start initializing |storage_info_map_|.
656 mtp_client_
->ListenForChanges(
657 base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged
,
658 weak_ptr_factory_
.GetWeakPtr()));
659 mtp_client_
->EnumerateStorages(
660 base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages
,
661 weak_ptr_factory_
.GetWeakPtr()),
662 base::Bind(&base::DoNothing
));
666 scoped_ptr
<MediaTransferProtocolDaemonClient
> mtp_client_
;
668 #if !defined(OS_CHROMEOS)
669 // And a D-Bus session for talking to mtpd.
670 scoped_refptr
<dbus::Bus
> session_bus_
;
673 // Device attachment / detachment observers.
674 base::ObserverList
<Observer
> observers_
;
676 // Map to keep track of attached storages by name.
677 StorageInfoMap storage_info_map_
;
679 // Set of open storage handles.
680 std::set
<std::string
> handles_
;
682 dbus::Bus::GetServiceOwnerCallback mtpd_owner_changed_callback_
;
684 std::string current_mtpd_owner_
;
687 GetStorageInfoFromDeviceCallbackQueue get_storage_info_from_device_callbacks_
;
688 OpenStorageCallbackQueue open_storage_callbacks_
;
689 CloseStorageCallbackQueue close_storage_callbacks_
;
690 CreateDirectoryCallbackQueue create_directory_callbacks_
;
691 ReadDirectoryCallbackQueue read_directory_callbacks_
;
692 ReadFileCallbackQueue read_file_callbacks_
;
693 GetFileInfoCallbackQueue get_file_info_callbacks_
;
694 RenameObjectCallbackQueue rename_object_callbacks_
;
695 CopyFileFromLocalCallbackQueue copy_file_from_local_callbacks_
;
696 DeleteObjectCallbackQueue delete_object_callbacks_
;
698 base::ThreadChecker thread_checker_
;
700 base::WeakPtrFactory
<MediaTransferProtocolManagerImpl
> weak_ptr_factory_
;
702 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl
);
708 MediaTransferProtocolManager
* MediaTransferProtocolManager::Initialize(
709 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
710 DCHECK(!g_media_transfer_protocol_manager
);
712 g_media_transfer_protocol_manager
=
713 new MediaTransferProtocolManagerImpl(task_runner
);
714 VLOG(1) << "MediaTransferProtocolManager initialized";
716 return g_media_transfer_protocol_manager
;
719 } // namespace device