Make push messaging not create InvalidationService for login and guest
[chromium-blink-merge.git] / device / media_transfer_protocol / media_transfer_protocol_manager.cc
blob3ba793479c1447564cb9dd1fe86d989737fe28ee
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 <map>
8 #include <queue>
9 #include <set>
10 #include <utility>
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/location.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/sequenced_task_runner.h"
18 #include "base/stl_util.h"
19 #include "base/threading/thread_checker.h"
20 #include "dbus/bus.h"
21 #include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h"
22 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
23 #include "device/media_transfer_protocol/mtp_storage_info.pb.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
26 #if defined(OS_CHROMEOS)
27 #include "chromeos/dbus/dbus_thread_manager.h"
28 #endif
30 namespace device {
32 namespace {
34 MediaTransferProtocolManager* g_media_transfer_protocol_manager = NULL;
36 // The MediaTransferProtocolManager implementation.
37 class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
38 public:
39 explicit MediaTransferProtocolManagerImpl(
40 scoped_refptr<base::SequencedTaskRunner> task_runner)
41 : weak_ptr_factory_(this) {
42 #if defined(OS_CHROMEOS)
43 DCHECK(!task_runner.get());
44 #else
45 DCHECK(task_runner.get());
46 dbus::Bus::Options options;
47 options.bus_type = dbus::Bus::SYSTEM;
48 options.connection_type = dbus::Bus::PRIVATE;
49 options.dbus_task_runner = task_runner;
50 session_bus_ = new dbus::Bus(options);
51 #endif
53 if (GetBus()) {
54 // Listen for future mtpd service owner changes, in case it is not
55 // available right now. There is no guarantee on Linux or ChromeOS that
56 // mtpd is running already.
57 mtpd_owner_changed_callback_ = base::Bind(
58 &MediaTransferProtocolManagerImpl::FinishSetupOnOriginThread,
59 weak_ptr_factory_.GetWeakPtr());
60 GetBus()->ListenForServiceOwnerChange(mtpd::kMtpdServiceName,
61 mtpd_owner_changed_callback_);
62 GetBus()->GetServiceOwner(mtpd::kMtpdServiceName,
63 mtpd_owner_changed_callback_);
67 virtual ~MediaTransferProtocolManagerImpl() {
68 DCHECK(g_media_transfer_protocol_manager);
69 g_media_transfer_protocol_manager = NULL;
70 if (GetBus()) {
71 GetBus()->UnlistenForServiceOwnerChange(mtpd::kMtpdServiceName,
72 mtpd_owner_changed_callback_);
75 #if !defined(OS_CHROMEOS)
76 session_bus_->GetDBusTaskRunner()->PostTask(
77 FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, session_bus_));
78 #endif
80 VLOG(1) << "MediaTransferProtocolManager Shutdown completed";
83 // MediaTransferProtocolManager override.
84 virtual void AddObserver(Observer* observer) OVERRIDE {
85 DCHECK(thread_checker_.CalledOnValidThread());
86 observers_.AddObserver(observer);
89 // MediaTransferProtocolManager override.
90 virtual void RemoveObserver(Observer* observer) OVERRIDE {
91 DCHECK(thread_checker_.CalledOnValidThread());
92 observers_.RemoveObserver(observer);
95 // MediaTransferProtocolManager override.
96 virtual const std::vector<std::string> GetStorages() const OVERRIDE {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 std::vector<std::string> storages;
99 for (StorageInfoMap::const_iterator it = storage_info_map_.begin();
100 it != storage_info_map_.end();
101 ++it) {
102 storages.push_back(it->first);
104 return storages;
107 // MediaTransferProtocolManager override.
108 virtual const MtpStorageInfo* GetStorageInfo(
109 const std::string& storage_name) const OVERRIDE {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name);
112 return it != storage_info_map_.end() ? &it->second : NULL;
115 // MediaTransferProtocolManager override.
116 virtual void OpenStorage(const std::string& storage_name,
117 const std::string& mode,
118 const OpenStorageCallback& callback) OVERRIDE {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 if (!ContainsKey(storage_info_map_, storage_name) || !mtp_client_) {
121 callback.Run(std::string(), true);
122 return;
124 open_storage_callbacks_.push(callback);
125 mtp_client_->OpenStorage(
126 storage_name,
127 mode,
128 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage,
129 weak_ptr_factory_.GetWeakPtr()),
130 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError,
131 weak_ptr_factory_.GetWeakPtr()));
134 // MediaTransferProtocolManager override.
135 virtual void CloseStorage(const std::string& storage_handle,
136 const CloseStorageCallback& callback) OVERRIDE {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
139 callback.Run(true);
140 return;
142 close_storage_callbacks_.push(std::make_pair(callback, storage_handle));
143 mtp_client_->CloseStorage(
144 storage_handle,
145 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage,
146 weak_ptr_factory_.GetWeakPtr()),
147 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError,
148 weak_ptr_factory_.GetWeakPtr()));
151 // MediaTransferProtocolManager override.
152 virtual void ReadDirectoryByPath(
153 const std::string& storage_handle,
154 const std::string& path,
155 const ReadDirectoryCallback& callback) OVERRIDE {
156 DCHECK(thread_checker_.CalledOnValidThread());
157 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
158 callback.Run(std::vector<MtpFileEntry>(), true);
159 return;
161 read_directory_callbacks_.push(callback);
162 mtp_client_->ReadDirectoryByPath(
163 storage_handle,
164 path,
165 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory,
166 weak_ptr_factory_.GetWeakPtr()),
167 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
168 weak_ptr_factory_.GetWeakPtr()));
171 // MediaTransferProtocolManager override.
172 virtual void ReadDirectoryById(
173 const std::string& storage_handle,
174 uint32 file_id,
175 const ReadDirectoryCallback& callback) OVERRIDE {
176 DCHECK(thread_checker_.CalledOnValidThread());
177 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
178 callback.Run(std::vector<MtpFileEntry>(), true);
179 return;
181 read_directory_callbacks_.push(callback);
182 mtp_client_->ReadDirectoryById(
183 storage_handle,
184 file_id,
185 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory,
186 weak_ptr_factory_.GetWeakPtr()),
187 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
188 weak_ptr_factory_.GetWeakPtr()));
191 // MediaTransferProtocolManager override.
192 virtual void ReadFileChunkByPath(const std::string& storage_handle,
193 const std::string& path,
194 uint32 offset,
195 uint32 count,
196 const ReadFileCallback& callback) OVERRIDE {
197 DCHECK(thread_checker_.CalledOnValidThread());
198 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
199 callback.Run(std::string(), true);
200 return;
202 read_file_callbacks_.push(callback);
203 mtp_client_->ReadFileChunkByPath(
204 storage_handle, path, offset, count,
205 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile,
206 weak_ptr_factory_.GetWeakPtr()),
207 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError,
208 weak_ptr_factory_.GetWeakPtr()));
211 // MediaTransferProtocolManager override.
212 virtual void ReadFileChunkById(const std::string& storage_handle,
213 uint32 file_id,
214 uint32 offset,
215 uint32 count,
216 const ReadFileCallback& callback) OVERRIDE {
217 DCHECK(thread_checker_.CalledOnValidThread());
218 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
219 callback.Run(std::string(), true);
220 return;
222 read_file_callbacks_.push(callback);
223 mtp_client_->ReadFileChunkById(
224 storage_handle, file_id, offset, count,
225 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile,
226 weak_ptr_factory_.GetWeakPtr()),
227 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError,
228 weak_ptr_factory_.GetWeakPtr()));
231 virtual void GetFileInfoByPath(const std::string& storage_handle,
232 const std::string& path,
233 const GetFileInfoCallback& callback) OVERRIDE {
234 DCHECK(thread_checker_.CalledOnValidThread());
235 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
236 callback.Run(MtpFileEntry(), true);
237 return;
239 get_file_info_callbacks_.push(callback);
240 mtp_client_->GetFileInfoByPath(
241 storage_handle,
242 path,
243 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo,
244 weak_ptr_factory_.GetWeakPtr()),
245 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError,
246 weak_ptr_factory_.GetWeakPtr()));
249 virtual void GetFileInfoById(const std::string& storage_handle,
250 uint32 file_id,
251 const GetFileInfoCallback& callback) OVERRIDE {
252 DCHECK(thread_checker_.CalledOnValidThread());
253 if (!ContainsKey(handles_, storage_handle) || !mtp_client_) {
254 callback.Run(MtpFileEntry(), true);
255 return;
257 get_file_info_callbacks_.push(callback);
258 mtp_client_->GetFileInfoById(
259 storage_handle,
260 file_id,
261 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo,
262 weak_ptr_factory_.GetWeakPtr()),
263 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError,
264 weak_ptr_factory_.GetWeakPtr()));
267 private:
268 // Map of storage names to storage info.
269 typedef std::map<std::string, MtpStorageInfo> StorageInfoMap;
270 // Callback queues - DBus communication is in-order, thus callbacks are
271 // received in the same order as the requests.
272 typedef std::queue<OpenStorageCallback> OpenStorageCallbackQueue;
273 // (callback, handle)
274 typedef std::queue<std::pair<CloseStorageCallback, std::string>
275 > CloseStorageCallbackQueue;
276 typedef std::queue<ReadDirectoryCallback> ReadDirectoryCallbackQueue;
277 typedef std::queue<ReadFileCallback> ReadFileCallbackQueue;
278 typedef std::queue<GetFileInfoCallback> GetFileInfoCallbackQueue;
280 void OnStorageAttached(const std::string& storage_name) {
281 DCHECK(thread_checker_.CalledOnValidThread());
282 mtp_client_->GetStorageInfo(
283 storage_name,
284 base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo,
285 weak_ptr_factory_.GetWeakPtr()),
286 base::Bind(&base::DoNothing));
289 void OnStorageDetached(const std::string& storage_name) {
290 DCHECK(thread_checker_.CalledOnValidThread());
291 if (storage_info_map_.erase(storage_name) == 0) {
292 // This can happen for a storage where
293 // MediaTransferProtocolDaemonClient::GetStorageInfo() failed.
294 // Return to avoid giving observers phantom detach events.
295 return;
297 FOR_EACH_OBSERVER(Observer,
298 observers_,
299 StorageChanged(false /* detach */, storage_name));
302 void OnStorageChanged(bool is_attach, const std::string& storage_name) {
303 DCHECK(thread_checker_.CalledOnValidThread());
304 DCHECK(mtp_client_);
305 if (is_attach)
306 OnStorageAttached(storage_name);
307 else
308 OnStorageDetached(storage_name);
311 void OnEnumerateStorages(const std::vector<std::string>& storage_names) {
312 DCHECK(thread_checker_.CalledOnValidThread());
313 DCHECK(mtp_client_);
314 for (size_t i = 0; i < storage_names.size(); ++i) {
315 if (ContainsKey(storage_info_map_, storage_names[i])) {
316 // OnStorageChanged() might have gotten called first.
317 continue;
319 OnStorageAttached(storage_names[i]);
323 void OnGetStorageInfo(const MtpStorageInfo& storage_info) {
324 DCHECK(thread_checker_.CalledOnValidThread());
325 const std::string& storage_name = storage_info.storage_name();
326 if (ContainsKey(storage_info_map_, storage_name)) {
327 // This should not happen, since MediaTransferProtocolManagerImpl should
328 // only call EnumerateStorages() once, which populates |storage_info_map_|
329 // with the already-attached devices.
330 // After that, all incoming signals are either for new storage
331 // attachments, which should not be in |storage_info_map_|, or for
332 // storage detachments, which do not add to |storage_info_map_|.
333 // Return to avoid giving observers phantom detach events.
334 NOTREACHED();
335 return;
338 // New storage. Add it and let the observers know.
339 storage_info_map_.insert(std::make_pair(storage_name, storage_info));
340 FOR_EACH_OBSERVER(Observer,
341 observers_,
342 StorageChanged(true /* is attach */, storage_name));
345 void OnOpenStorage(const std::string& handle) {
346 DCHECK(thread_checker_.CalledOnValidThread());
347 if (!ContainsKey(handles_, handle)) {
348 handles_.insert(handle);
349 open_storage_callbacks_.front().Run(handle, false);
350 } else {
351 NOTREACHED();
352 open_storage_callbacks_.front().Run(std::string(), true);
354 open_storage_callbacks_.pop();
357 void OnOpenStorageError() {
358 open_storage_callbacks_.front().Run(std::string(), true);
359 open_storage_callbacks_.pop();
362 void OnCloseStorage() {
363 DCHECK(thread_checker_.CalledOnValidThread());
364 const std::string& handle = close_storage_callbacks_.front().second;
365 if (ContainsKey(handles_, handle)) {
366 handles_.erase(handle);
367 close_storage_callbacks_.front().first.Run(false);
368 } else {
369 NOTREACHED();
370 close_storage_callbacks_.front().first.Run(true);
372 close_storage_callbacks_.pop();
375 void OnCloseStorageError() {
376 DCHECK(thread_checker_.CalledOnValidThread());
377 close_storage_callbacks_.front().first.Run(true);
378 close_storage_callbacks_.pop();
381 void OnReadDirectory(const std::vector<MtpFileEntry>& file_entries) {
382 DCHECK(thread_checker_.CalledOnValidThread());
383 read_directory_callbacks_.front().Run(file_entries, false);
384 read_directory_callbacks_.pop();
387 void OnReadDirectoryError() {
388 DCHECK(thread_checker_.CalledOnValidThread());
389 read_directory_callbacks_.front().Run(std::vector<MtpFileEntry>(), true);
390 read_directory_callbacks_.pop();
393 void OnReadFile(const std::string& data) {
394 DCHECK(thread_checker_.CalledOnValidThread());
395 read_file_callbacks_.front().Run(data, false);
396 read_file_callbacks_.pop();
399 void OnReadFileError() {
400 DCHECK(thread_checker_.CalledOnValidThread());
401 read_file_callbacks_.front().Run(std::string(), true);
402 read_file_callbacks_.pop();
405 void OnGetFileInfo(const MtpFileEntry& entry) {
406 DCHECK(thread_checker_.CalledOnValidThread());
407 get_file_info_callbacks_.front().Run(entry, false);
408 get_file_info_callbacks_.pop();
411 void OnGetFileInfoError() {
412 DCHECK(thread_checker_.CalledOnValidThread());
413 get_file_info_callbacks_.front().Run(MtpFileEntry(), true);
414 get_file_info_callbacks_.pop();
417 // Get the Bus object used to communicate with mtpd.
418 dbus::Bus* GetBus() {
419 DCHECK(thread_checker_.CalledOnValidThread());
420 #if defined(OS_CHROMEOS)
421 return chromeos::DBusThreadManager::Get()->GetSystemBus();
422 #else
423 return session_bus_.get();
424 #endif
427 // Callback to finish initialization after figuring out if the mtpd service
428 // has an owner, or if the service owner has changed.
429 // |mtpd_service_owner| contains the name of the current owner, if any.
430 void FinishSetupOnOriginThread(const std::string& mtpd_service_owner) {
431 DCHECK(thread_checker_.CalledOnValidThread());
433 if (mtpd_service_owner == current_mtpd_owner_)
434 return;
436 // In the case of a new service owner, clear |storage_info_map_|.
437 // Assume all storages have been disconnected. If there is a new service
438 // owner, reconnecting to it will reconnect all the storages as well.
440 // Save a copy of |storage_info_map_| keys as |storage_info_map_| can
441 // change in OnStorageDetached().
442 std::vector<std::string> storage_names;
443 for (StorageInfoMap::const_iterator it = storage_info_map_.begin();
444 it != storage_info_map_.end();
445 ++it) {
446 storage_names.push_back(it->first);
448 for (size_t i = 0; i != storage_names.size(); ++i)
449 OnStorageDetached(storage_names[i]);
451 if (mtpd_service_owner.empty()) {
452 current_mtpd_owner_.clear();
453 mtp_client_.reset();
454 return;
457 current_mtpd_owner_ = mtpd_service_owner;
459 mtp_client_.reset(MediaTransferProtocolDaemonClient::Create(GetBus()));
461 // Set up signals and start initializing |storage_info_map_|.
462 mtp_client_->ListenForChanges(
463 base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged,
464 weak_ptr_factory_.GetWeakPtr()));
465 mtp_client_->EnumerateStorages(
466 base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages,
467 weak_ptr_factory_.GetWeakPtr()),
468 base::Bind(&base::DoNothing));
471 // Mtpd DBus client.
472 scoped_ptr<MediaTransferProtocolDaemonClient> mtp_client_;
474 #if !defined(OS_CHROMEOS)
475 // And a D-Bus session for talking to mtpd.
476 scoped_refptr<dbus::Bus> session_bus_;
477 #endif
479 // Device attachment / detachment observers.
480 ObserverList<Observer> observers_;
482 // Map to keep track of attached storages by name.
483 StorageInfoMap storage_info_map_;
485 // Set of open storage handles.
486 std::set<std::string> handles_;
488 dbus::Bus::GetServiceOwnerCallback mtpd_owner_changed_callback_;
490 std::string current_mtpd_owner_;
492 // Queued callbacks.
493 OpenStorageCallbackQueue open_storage_callbacks_;
494 CloseStorageCallbackQueue close_storage_callbacks_;
495 ReadDirectoryCallbackQueue read_directory_callbacks_;
496 ReadFileCallbackQueue read_file_callbacks_;
497 GetFileInfoCallbackQueue get_file_info_callbacks_;
499 base::ThreadChecker thread_checker_;
501 base::WeakPtrFactory<MediaTransferProtocolManagerImpl> weak_ptr_factory_;
503 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl);
506 } // namespace
508 // static
509 MediaTransferProtocolManager* MediaTransferProtocolManager::Initialize(
510 scoped_refptr<base::SequencedTaskRunner> task_runner) {
511 DCHECK(!g_media_transfer_protocol_manager);
513 g_media_transfer_protocol_manager =
514 new MediaTransferProtocolManagerImpl(task_runner);
515 VLOG(1) << "MediaTransferProtocolManager initialized";
517 return g_media_transfer_protocol_manager;
520 } // namespace device