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

Side by Side Diff: chrome/browser/chromeos/mtp/media_transfer_protocol_manager.cc

Issue 10854048: ChromeOS: Implement MediaTransferProtocolManager. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 3 months 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/chromeos/mtp/media_transfer_protocol_manager.h"
6
7 #include <map>
8 #include <queue>
9 #include <set>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/observer_list.h"
15 #include "base/stl_util.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "content/public/browser/browser_thread.h"
18
19 using content::BrowserThread;
20
21 namespace chromeos {
22 namespace mtp {
23
24 namespace {
25
26 MediaTransferProtocolManager* g_media_transfer_protocol_manager = NULL;
27
28 // The MediaTransferProtocolManager implementation.
29 class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
30 public:
31 MediaTransferProtocolManagerImpl() : weak_ptr_factory_(this) {
32 DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get();
33 mtp_client_ = dbus_thread_manager->GetMediaTransferProtocolDaemonClient();
34
35 // Set up signals and start initializing |storage_info_map_|.
36 mtp_client_->SetUpConnections(
37 base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged,
38 weak_ptr_factory_.GetWeakPtr()));
39 mtp_client_->EnumerateStorage(
40 base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorage,
41 weak_ptr_factory_.GetWeakPtr()),
42 base::Bind(&base::DoNothing));
43 }
44
45 virtual ~MediaTransferProtocolManagerImpl() {
46 }
47
48 // MediaTransferProtocolManager override.
49 virtual void AddObserver(Observer* observer) OVERRIDE {
50 observers_.AddObserver(observer);
51 }
52
53 // MediaTransferProtocolManager override.
54 virtual void RemoveObserver(Observer* observer) OVERRIDE {
55 observers_.RemoveObserver(observer);
56 }
57
58 // MediaTransferProtocolManager override.
59 const std::vector<std::string> GetStorages() const OVERRIDE {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61 std::vector<std::string> storages;
62 for (StorageInfoMap::const_iterator it = storage_info_map_.begin();
63 it != storage_info_map_.end();
64 ++it) {
65 storages.push_back(it->first);
66 }
67 return storages;
68 }
69
70 // MediaTransferProtocolManager override.
71 virtual const StorageInfo* GetStorageInfo(
72 const std::string& storage_name) const OVERRIDE {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name);
75 if (it == storage_info_map_.end())
76 return NULL;
77 return &it->second;
78 }
79
80 // MediaTransferProtocolManager override.
81 virtual void OpenStorage(const std::string& storage_name,
82 OpenStorageMode mode,
83 const OpenStorageCallback& callback) OVERRIDE {
84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
85 if (!ContainsKey(storage_info_map_, storage_name)) {
86 callback.Run("", true);
87 return;
88 }
89 open_storage_callbacks_.push(callback);
90 mtp_client_->OpenStorage(
91 storage_name,
92 mode,
93 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage,
94 weak_ptr_factory_.GetWeakPtr()),
95 base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError,
96 weak_ptr_factory_.GetWeakPtr()));
97 }
98
99 // MediaTransferProtocolManager override.
100 virtual void CloseStorage(const std::string& storage_handle,
101 const CloseStorageCallback& callback) OVERRIDE {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103 if (!ContainsKey(handles_, storage_handle)) {
104 callback.Run(true);
105 return;
106 }
107 close_storage_callbacks_.push(std::make_pair(callback, storage_handle));
108 mtp_client_->CloseStorage(
109 storage_handle,
110 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage,
111 weak_ptr_factory_.GetWeakPtr()),
112 base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError,
113 weak_ptr_factory_.GetWeakPtr()));
114 }
115
116 // MediaTransferProtocolManager override.
117 virtual void ReadDirectoryByPath(
118 const std::string& storage_handle,
119 const std::string& path,
120 const ReadDirectoryCallback& callback) OVERRIDE {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 if (!ContainsKey(handles_, storage_handle)) {
123 callback.Run(std::vector<FileEntry>(), true);
124 return;
125 }
126 read_directory_callbacks_.push(callback);
127 mtp_client_->ReadDirectoryByPath(
128 storage_handle,
129 path,
130 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory,
131 weak_ptr_factory_.GetWeakPtr()),
132 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
133 weak_ptr_factory_.GetWeakPtr()));
134 }
135
136 // MediaTransferProtocolManager override.
137 virtual void ReadDirectoryById(
138 const std::string& storage_handle,
139 uint32 file_id,
140 const ReadDirectoryCallback& callback) OVERRIDE {
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
142 if (!ContainsKey(handles_, storage_handle)) {
143 callback.Run(std::vector<FileEntry>(), true);
144 return;
145 }
146 read_directory_callbacks_.push(callback);
147 mtp_client_->ReadDirectoryById(
148 storage_handle,
149 file_id,
150 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory,
151 weak_ptr_factory_.GetWeakPtr()),
152 base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError,
153 weak_ptr_factory_.GetWeakPtr()));
154 }
155
156 // MediaTransferProtocolManager override.
157 virtual void ReadFileByPath(const std::string& storage_handle,
158 const std::string& path,
159 const ReadFileCallback& callback) OVERRIDE {
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161 if (!ContainsKey(handles_, storage_handle)) {
162 callback.Run(std::string(), true);
163 return;
164 }
165 read_file_callbacks_.push(callback);
166 mtp_client_->ReadFileByPath(
167 storage_handle,
168 path,
169 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile,
170 weak_ptr_factory_.GetWeakPtr()),
171 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError,
172 weak_ptr_factory_.GetWeakPtr()));
173 }
174
175 // MediaTransferProtocolManager override.
176 virtual void ReadFileById(const std::string& storage_handle,
177 uint32 file_id,
178 const ReadFileCallback& callback) OVERRIDE {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
180 if (!ContainsKey(handles_, storage_handle)) {
181 callback.Run(std::string(), true);
182 return;
183 }
184 read_file_callbacks_.push(callback);
185 mtp_client_->ReadFileById(
186 storage_handle,
187 file_id,
188 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile,
189 weak_ptr_factory_.GetWeakPtr()),
190 base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError,
191 weak_ptr_factory_.GetWeakPtr()));
192 }
193
194 virtual void GetFileInfoByPath(const std::string& storage_handle,
195 const std::string& path,
196 const GetFileInfoCallback& callback) OVERRIDE {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 if (!ContainsKey(handles_, storage_handle)) {
199 callback.Run(FileEntry(), true);
200 return;
201 }
202 get_file_info_callbacks_.push(callback);
203 mtp_client_->GetFileInfoByPath(
204 storage_handle,
205 path,
206 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo,
207 weak_ptr_factory_.GetWeakPtr()),
208 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError,
209 weak_ptr_factory_.GetWeakPtr()));
210 }
211
212 virtual void GetFileInfoById(const std::string& storage_handle,
213 uint32 file_id,
214 const GetFileInfoCallback& callback) OVERRIDE {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216 if (!ContainsKey(handles_, storage_handle)) {
217 callback.Run(FileEntry(), true);
218 return;
219 }
220 get_file_info_callbacks_.push(callback);
221 mtp_client_->GetFileInfoById(
222 storage_handle,
223 file_id,
224 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo,
225 weak_ptr_factory_.GetWeakPtr()),
226 base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError,
227 weak_ptr_factory_.GetWeakPtr()));
228 }
229
230 private:
231 // Map of storage names to storage info.
232 typedef std::map<std::string, StorageInfo> StorageInfoMap;
233 // Callback queues - DBus communication is in-order, thus callbacks are
234 // received in the same order as the requests.
235 typedef std::queue<OpenStorageCallback> OpenStorageCallbackQueue;
236 // (callback, handle)
237 typedef std::queue<std::pair<CloseStorageCallback, std::string>
238 > CloseStorageCallbackQueue;
239 typedef std::queue<ReadDirectoryCallback> ReadDirectoryCallbackQueue;
240 typedef std::queue<ReadFileCallback> ReadFileCallbackQueue;
241 typedef std::queue<GetFileInfoCallback> GetFileInfoCallbackQueue;
242
243 void OnStorageChanged(bool is_attach, const std::string& storage_name) {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
245 if (is_attach) {
246 mtp_client_->GetStorageInfo(
247 storage_name,
248 base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo,
249 weak_ptr_factory_.GetWeakPtr()),
250 base::Bind(&base::DoNothing));
251 return;
252 }
253
254 // Detach case.
255 StorageInfoMap::iterator it = storage_info_map_.find(storage_name);
256 if (it == storage_info_map_.end()) {
257 // This might happen during initialization when |storage_info_map_| has
258 // not been fully populated yet?
259 return;
260 }
261 storage_info_map_.erase(it);
262 FOR_EACH_OBSERVER(Observer,
263 observers_,
264 StorageChanged(false /* detach */, storage_name));
265 }
266
267 void OnEnumerateStorage(const std::vector<std::string>& storage_names) {
268 for (size_t i = 0; i < storage_names.size(); ++i) {
269 mtp_client_->GetStorageInfo(
270 storage_names[i],
271 base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo,
272 weak_ptr_factory_.GetWeakPtr()),
273 base::Bind(&base::DoNothing));
274 }
275 }
276
277 void OnGetStorageInfo(const StorageInfo& storage_info) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 const std::string& storage_name = storage_info.storage_name();
280 if (ContainsKey(storage_info_map_, storage_name)) {
281 // This should not happen, since MediaTransferProtocolManagerImpl should
282 // only call EnumerateStorage() once, which populates |storage_info_map_|
283 // with the already-attached devices.
284 // After that, all incoming signals are either for new storage
285 // attachments, which should not be in |storage_info_map_|, or for
286 // storage detachements, which do not add to |storage_info_map_|.
287 NOTREACHED();
288 return;
289 }
290
291 // New storage. Add it and let the observers know.
292 storage_info_map_.insert(std::make_pair(storage_name, storage_info));
293 FOR_EACH_OBSERVER(Observer,
294 observers_,
295 StorageChanged(true /* is attach */, storage_name));
296 }
297
298 void OnOpenStorage(const std::string& handle) {
299 if (!ContainsKey(handles_, handle)) {
300 handles_.insert(handle);
301 open_storage_callbacks_.front().Run(handle, false);
302 } else {
303 NOTREACHED();
304 open_storage_callbacks_.front().Run("", true);
305 }
306 open_storage_callbacks_.pop();
307 }
308
309 void OnOpenStorageError() {
310 open_storage_callbacks_.front().Run("", true);
311 open_storage_callbacks_.pop();
312 }
313
314 void OnCloseStorage() {
315 const std::string& handle = close_storage_callbacks_.front().second;
316 if (ContainsKey(handles_, handle)) {
317 handles_.erase(handle);
318 close_storage_callbacks_.front().first.Run(false);
319 } else {
320 NOTREACHED();
321 close_storage_callbacks_.front().first.Run(true);
322 }
323 close_storage_callbacks_.pop();
324 }
325
326 void OnCloseStorageError() {
327 close_storage_callbacks_.front().first.Run(true);
328 close_storage_callbacks_.pop();
329 }
330
331 void OnReadDirectory(const std::vector<FileEntry>& file_entries) {
332 read_directory_callbacks_.front().Run(file_entries, false);
333 read_directory_callbacks_.pop();
334 }
335
336 void OnReadDirectoryError() {
337 read_directory_callbacks_.front().Run(std::vector<FileEntry>(), true);
338 read_directory_callbacks_.pop();
339 }
340
341 void OnReadFile(const std::string& data) {
342 read_file_callbacks_.front().Run(data, false);
343 read_file_callbacks_.pop();
344 }
345
346 void OnReadFileError() {
347 read_file_callbacks_.front().Run(std::string(), true);
348 read_file_callbacks_.pop();
349 }
350
351 void OnGetFileInfo(const FileEntry& entry) {
352 get_file_info_callbacks_.front().Run(entry, false);
353 get_file_info_callbacks_.pop();
354 }
355
356 void OnGetFileInfoError() {
357 get_file_info_callbacks_.front().Run(FileEntry(), true);
358 get_file_info_callbacks_.pop();
359 }
360
361 // Mtpd DBus client.
362 MediaTransferProtocolDaemonClient* mtp_client_;
363
364 // Device attachment / detachment observers.
365 ObserverList<Observer> observers_;
366
367 base::WeakPtrFactory<MediaTransferProtocolManagerImpl> weak_ptr_factory_;
368
369 // Everything below is only accessed on the UI thread.
370
371 // Map to keep track of attached storages by name.
372 StorageInfoMap storage_info_map_;
373
374 // Set of open storage handles.
375 std::set<std::string> handles_;
376
377 // Queued callbacks.
378 OpenStorageCallbackQueue open_storage_callbacks_;
379 CloseStorageCallbackQueue close_storage_callbacks_;
380 ReadDirectoryCallbackQueue read_directory_callbacks_;
381 ReadFileCallbackQueue read_file_callbacks_;
382 GetFileInfoCallbackQueue get_file_info_callbacks_;
383
384 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl);
385 };
386
387 } // namespace
388
389 // static
390 void MediaTransferProtocolManager::Initialize() {
391 if (g_media_transfer_protocol_manager) {
392 LOG(WARNING) << "MediaTransferProtocolManager was already initialized";
393 return;
394 }
395 g_media_transfer_protocol_manager = new MediaTransferProtocolManagerImpl();
396 VLOG(1) << "MediaTransferProtocolManager initialized";
397 }
398
399 // static
400 void MediaTransferProtocolManager::Shutdown() {
401 if (!g_media_transfer_protocol_manager) {
402 LOG(WARNING) << "MediaTransferProtocolManager::Shutdown() called with "
403 << "NULL manager";
404 return;
405 }
406 delete g_media_transfer_protocol_manager;
407 g_media_transfer_protocol_manager = NULL;
408 VLOG(1) << "MediaTransferProtocolManager Shutdown completed";
409 }
410
411 // static
412 MediaTransferProtocolManager* MediaTransferProtocolManager::GetInstance() {
413 return g_media_transfer_protocol_manager;
414 }
415
416 } // namespace mtp
417 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/mtp/media_transfer_protocol_manager.h ('k') | chrome/chrome_browser_chromeos.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698