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 "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
10 #include "base/stl_util.h"
11 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "storage/browser/fileapi/external_mount_points.h"
17 base::LazyInstance
<MTPDeviceMapService
> g_mtp_device_map_service
=
18 LAZY_INSTANCE_INITIALIZER
;
23 MTPDeviceMapService
* MTPDeviceMapService::GetInstance() {
24 return g_mtp_device_map_service
.Pointer();
27 void MTPDeviceMapService::RegisterMTPFileSystem(
28 const base::FilePath::StringType
& device_location
,
29 const std::string
& filesystem_id
,
30 const bool read_only
) {
31 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
32 DCHECK(!device_location
.empty());
33 DCHECK(!filesystem_id
.empty());
35 const AsyncDelegateKey key
= GetAsyncDelegateKey(device_location
, read_only
);
36 if (!ContainsKey(mtp_device_usage_map_
, key
)) {
37 // Note that this initializes the delegate asynchronously, but since
38 // the delegate will only be used from the IO thread, it is guaranteed
39 // to be created before use of it expects it to be there.
40 CreateMTPDeviceAsyncDelegate(
41 device_location
, read_only
,
42 base::Bind(&MTPDeviceMapService::AddAsyncDelegate
,
43 base::Unretained(this), device_location
, read_only
));
44 mtp_device_usage_map_
[key
] = 0;
47 mtp_device_usage_map_
[key
]++;
48 mtp_device_map_
[filesystem_id
] = make_pair(device_location
, read_only
);
51 void MTPDeviceMapService::RevokeMTPFileSystem(
52 const std::string
& filesystem_id
) {
53 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
54 DCHECK(!filesystem_id
.empty());
56 MTPDeviceFileSystemMap::iterator it
= mtp_device_map_
.find(filesystem_id
);
57 if (it
!= mtp_device_map_
.end()) {
58 const base::FilePath::StringType device_location
= it
->second
.first
;
59 const bool read_only
= it
->second
.second
;
61 mtp_device_map_
.erase(it
);
63 const AsyncDelegateKey key
=
64 GetAsyncDelegateKey(device_location
, read_only
);
65 MTPDeviceUsageMap::iterator delegate_it
= mtp_device_usage_map_
.find(key
);
66 DCHECK(delegate_it
!= mtp_device_usage_map_
.end());
68 mtp_device_usage_map_
[key
]--;
69 if (mtp_device_usage_map_
[key
] == 0) {
70 mtp_device_usage_map_
.erase(delegate_it
);
71 RemoveAsyncDelegate(device_location
, read_only
);
76 void MTPDeviceMapService::AddAsyncDelegate(
77 const base::FilePath::StringType
& device_location
,
79 MTPDeviceAsyncDelegate
* delegate
) {
80 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
82 DCHECK(!device_location
.empty());
84 const AsyncDelegateKey key
= GetAsyncDelegateKey(device_location
, read_only
);
85 if (ContainsKey(async_delegate_map_
, key
))
87 async_delegate_map_
[key
] = delegate
;
90 void MTPDeviceMapService::RemoveAsyncDelegate(
91 const base::FilePath::StringType
& device_location
,
92 const bool read_only
) {
93 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
94 DCHECK(!device_location
.empty());
96 const AsyncDelegateKey key
= GetAsyncDelegateKey(device_location
, read_only
);
97 AsyncDelegateMap::iterator it
= async_delegate_map_
.find(key
);
98 DCHECK(it
!= async_delegate_map_
.end());
99 it
->second
->CancelPendingTasksAndDeleteDelegate();
100 async_delegate_map_
.erase(it
);
104 MTPDeviceMapService::AsyncDelegateKey
MTPDeviceMapService::GetAsyncDelegateKey(
105 const base::FilePath::StringType
& device_location
,
106 const bool read_only
) {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
109 base::FilePath::StringType key
;
110 key
.append(read_only
? FILE_PATH_LITERAL("ReadOnly")
111 : FILE_PATH_LITERAL("ReadWrite"));
112 key
.append(FILE_PATH_LITERAL("|"));
113 key
.append(device_location
);
117 MTPDeviceAsyncDelegate
* MTPDeviceMapService::GetMTPDeviceAsyncDelegate(
118 const std::string
& filesystem_id
) {
119 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
120 DCHECK(!filesystem_id
.empty());
122 // File system may be already revoked on ExternalMountPoints side, we check
123 // here that the file system is still valid.
124 base::FilePath device_path
;
125 if (!storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
126 filesystem_id
, &device_path
)) {
130 const base::FilePath::StringType
& device_location
= device_path
.value();
132 MTPDeviceFileSystemMap::const_iterator mtp_device_map_it
=
133 mtp_device_map_
.find(filesystem_id
);
134 if (mtp_device_map_it
== mtp_device_map_
.end())
137 DCHECK_EQ(device_path
.value(), mtp_device_map_it
->second
.first
);
138 const bool read_only
= mtp_device_map_it
->second
.second
;
139 const AsyncDelegateKey key
= GetAsyncDelegateKey(device_location
, read_only
);
141 AsyncDelegateMap::const_iterator async_delegate_map_it
=
142 async_delegate_map_
.find(key
);
143 return (async_delegate_map_it
!= async_delegate_map_
.end())
144 ? async_delegate_map_it
->second
148 MTPDeviceMapService::MTPDeviceMapService() {
151 MTPDeviceMapService::~MTPDeviceMapService() {
152 DCHECK(mtp_device_usage_map_
.empty());