OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/api/hid/hid_device_manager.h" | 5 #include "extensions/browser/api/hid/hid_device_manager.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "device/core/device_client.h" | 11 #include "device/core/device_client.h" |
12 #include "device/hid/hid_device_filter.h" | 12 #include "device/hid/hid_device_filter.h" |
13 #include "device/hid/hid_service.h" | 13 #include "device/hid/hid_service.h" |
14 #include "extensions/common/permissions/permissions_data.h" | 14 #include "extensions/common/permissions/permissions_data.h" |
15 #include "extensions/common/permissions/usb_device_permission.h" | 15 #include "extensions/common/permissions/usb_device_permission.h" |
16 | 16 |
17 namespace hid = extensions::core_api::hid; | 17 namespace hid = extensions::core_api::hid; |
18 | 18 |
19 using device::HidDeviceFilter; | 19 using device::HidDeviceFilter; |
20 using device::HidDeviceId; | 20 using device::HidDeviceId; |
21 using device::HidDeviceInfo; | 21 using device::HidDeviceInfo; |
22 using device::HidService; | 22 using device::HidService; |
23 | 23 |
24 namespace extensions { | 24 namespace extensions { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 void PopulateHidDeviceInfo(hid::HidDeviceInfo* output, | 28 void PopulateHidDeviceInfo(hid::HidDeviceInfo* output, |
29 const HidDeviceInfo& input) { | 29 scoped_refptr<HidDeviceInfo> input) { |
30 output->vendor_id = input.vendor_id; | 30 output->vendor_id = input->vendor_id(); |
31 output->product_id = input.product_id; | 31 output->product_id = input->product_id(); |
32 output->max_input_report_size = input.max_input_report_size; | 32 output->max_input_report_size = input->max_input_report_size(); |
33 output->max_output_report_size = input.max_output_report_size; | 33 output->max_output_report_size = input->max_output_report_size(); |
34 output->max_feature_report_size = input.max_feature_report_size; | 34 output->max_feature_report_size = input->max_feature_report_size(); |
35 | 35 |
36 for (const device::HidCollectionInfo& collection : input.collections) { | 36 for (const device::HidCollectionInfo& collection : input->collections()) { |
37 // Don't expose sensitive data. | 37 // Don't expose sensitive data. |
38 if (collection.usage.IsProtected()) { | 38 if (collection.usage.IsProtected()) { |
39 continue; | 39 continue; |
40 } | 40 } |
41 | 41 |
42 hid::HidCollectionInfo* api_collection = new hid::HidCollectionInfo(); | 42 hid::HidCollectionInfo* api_collection = new hid::HidCollectionInfo(); |
43 api_collection->usage_page = collection.usage.usage_page; | 43 api_collection->usage_page = collection.usage.usage_page; |
44 api_collection->usage = collection.usage.usage; | 44 api_collection->usage = collection.usage.usage; |
45 | 45 |
46 api_collection->report_ids.resize(collection.report_ids.size()); | 46 api_collection->report_ids.resize(collection.report_ids.size()); |
47 std::copy(collection.report_ids.begin(), collection.report_ids.end(), | 47 std::copy(collection.report_ids.begin(), collection.report_ids.end(), |
48 api_collection->report_ids.begin()); | 48 api_collection->report_ids.begin()); |
49 | 49 |
50 output->collections.push_back(make_linked_ptr(api_collection)); | 50 output->collections.push_back(make_linked_ptr(api_collection)); |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 bool WillDispatchDeviceEvent(const HidDeviceInfo& device_info, | 54 bool WillDispatchDeviceEvent(scoped_refptr<HidDeviceInfo> device_info, |
55 content::BrowserContext* context, | 55 content::BrowserContext* context, |
56 const Extension* extension, | 56 const Extension* extension, |
57 base::ListValue* event_args) { | 57 base::ListValue* event_args) { |
58 if (extension) { | 58 if (extension) { |
59 return HidDeviceManager::HasPermission(extension, device_info); | 59 return HidDeviceManager::HasPermission(extension, device_info); |
60 } | 60 } |
61 return false; | 61 return false; |
62 } | 62 } |
63 | 63 |
64 } // namespace | 64 } // namespace |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 scoped_ptr<base::ListValue> devices = | 112 scoped_ptr<base::ListValue> devices = |
113 CreateApiDeviceList(extension, filters); | 113 CreateApiDeviceList(extension, filters); |
114 base::MessageLoop::current()->PostTask( | 114 base::MessageLoop::current()->PostTask( |
115 FROM_HERE, base::Bind(callback, base::Passed(&devices))); | 115 FROM_HERE, base::Bind(callback, base::Passed(&devices))); |
116 } else { | 116 } else { |
117 pending_enumerations_.push_back( | 117 pending_enumerations_.push_back( |
118 new GetApiDevicesParams(extension, filters, callback)); | 118 new GetApiDevicesParams(extension, filters, callback)); |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 bool HidDeviceManager::GetDeviceInfo(int resource_id, | 122 scoped_refptr<HidDeviceInfo> HidDeviceManager::GetDeviceInfo(int resource_id) { |
123 HidDeviceInfo* device_info) { | |
124 DCHECK(thread_checker_.CalledOnValidThread()); | 123 DCHECK(thread_checker_.CalledOnValidThread()); |
125 HidService* hid_service = device::DeviceClient::Get()->GetHidService(); | 124 HidService* hid_service = device::DeviceClient::Get()->GetHidService(); |
126 DCHECK(hid_service); | 125 DCHECK(hid_service); |
127 | 126 |
128 ResourceIdToDeviceIdMap::const_iterator device_iter = | 127 ResourceIdToDeviceIdMap::const_iterator device_iter = |
129 device_ids_.find(resource_id); | 128 device_ids_.find(resource_id); |
130 if (device_iter == device_ids_.end()) { | 129 if (device_iter == device_ids_.end()) { |
131 return false; | 130 return nullptr; |
132 } | 131 } |
133 | 132 |
134 return hid_service->GetDeviceInfo(device_iter->second, device_info); | 133 return hid_service->GetDeviceInfo(device_iter->second); |
135 } | 134 } |
136 | 135 |
137 // static | 136 // static |
138 bool HidDeviceManager::HasPermission(const Extension* extension, | 137 bool HidDeviceManager::HasPermission(const Extension* extension, |
139 const HidDeviceInfo& device_info) { | 138 scoped_refptr<HidDeviceInfo> device_info) { |
140 UsbDevicePermission::CheckParam usbParam( | 139 UsbDevicePermission::CheckParam usbParam( |
141 device_info.vendor_id, | 140 device_info->vendor_id(), device_info->product_id(), |
142 device_info.product_id, | |
143 UsbDevicePermissionData::UNSPECIFIED_INTERFACE); | 141 UsbDevicePermissionData::UNSPECIFIED_INTERFACE); |
144 if (extension->permissions_data()->CheckAPIPermissionWithParam( | 142 if (extension->permissions_data()->CheckAPIPermissionWithParam( |
145 APIPermission::kUsbDevice, &usbParam)) { | 143 APIPermission::kUsbDevice, &usbParam)) { |
146 return true; | 144 return true; |
147 } | 145 } |
148 | 146 |
149 if (extension->permissions_data()->HasAPIPermission( | 147 if (extension->permissions_data()->HasAPIPermission( |
150 APIPermission::kU2fDevices)) { | 148 APIPermission::kU2fDevices)) { |
151 HidDeviceFilter u2f_filter; | 149 HidDeviceFilter u2f_filter; |
152 u2f_filter.SetUsagePage(0xF1D0); | 150 u2f_filter.SetUsagePage(0xF1D0); |
153 if (u2f_filter.Matches(device_info)) { | 151 if (u2f_filter.Matches(device_info)) { |
154 return true; | 152 return true; |
155 } | 153 } |
156 } | 154 } |
157 | 155 |
158 return false; | 156 return false; |
159 } | 157 } |
160 | 158 |
161 void HidDeviceManager::Shutdown() { | 159 void HidDeviceManager::Shutdown() { |
162 if (event_router_) { | 160 if (event_router_) { |
163 event_router_->UnregisterObserver(this); | 161 event_router_->UnregisterObserver(this); |
164 } | 162 } |
165 } | 163 } |
166 | 164 |
167 void HidDeviceManager::OnListenerAdded(const EventListenerInfo& details) { | 165 void HidDeviceManager::OnListenerAdded(const EventListenerInfo& details) { |
168 LazyInitialize(); | 166 LazyInitialize(); |
169 } | 167 } |
170 | 168 |
171 void HidDeviceManager::OnDeviceAdded(const HidDeviceInfo& device_info) { | 169 void HidDeviceManager::OnDeviceAdded(scoped_refptr<HidDeviceInfo> device_info) { |
172 DCHECK(thread_checker_.CalledOnValidThread()); | 170 DCHECK(thread_checker_.CalledOnValidThread()); |
173 DCHECK_LT(next_resource_id_, std::numeric_limits<int>::max()); | 171 DCHECK_LT(next_resource_id_, std::numeric_limits<int>::max()); |
174 int new_id = next_resource_id_++; | 172 int new_id = next_resource_id_++; |
175 DCHECK(!ContainsKey(resource_ids_, device_info.device_id)); | 173 DCHECK(!ContainsKey(resource_ids_, device_info->device_id())); |
176 resource_ids_[device_info.device_id] = new_id; | 174 resource_ids_[device_info->device_id()] = new_id; |
177 device_ids_[new_id] = device_info.device_id; | 175 device_ids_[new_id] = device_info->device_id(); |
178 | 176 |
179 // Don't generate events during the initial enumeration. | 177 // Don't generate events during the initial enumeration. |
180 if (enumeration_ready_ && event_router_) { | 178 if (enumeration_ready_ && event_router_) { |
181 core_api::hid::HidDeviceInfo api_device_info; | 179 core_api::hid::HidDeviceInfo api_device_info; |
182 api_device_info.device_id = new_id; | 180 api_device_info.device_id = new_id; |
183 PopulateHidDeviceInfo(&api_device_info, device_info); | 181 PopulateHidDeviceInfo(&api_device_info, device_info); |
184 | 182 |
185 if (api_device_info.collections.size() > 0) { | 183 if (api_device_info.collections.size() > 0) { |
186 scoped_ptr<base::ListValue> args( | 184 scoped_ptr<base::ListValue> args( |
187 hid::OnDeviceAdded::Create(api_device_info)); | 185 hid::OnDeviceAdded::Create(api_device_info)); |
188 DispatchEvent(hid::OnDeviceAdded::kEventName, args.Pass(), device_info); | 186 DispatchEvent(hid::OnDeviceAdded::kEventName, args.Pass(), device_info); |
189 } | 187 } |
190 } | 188 } |
191 } | 189 } |
192 | 190 |
193 void HidDeviceManager::OnDeviceRemoved(const HidDeviceInfo& device_info) { | 191 void HidDeviceManager::OnDeviceRemoved( |
| 192 scoped_refptr<HidDeviceInfo> device_info) { |
194 DCHECK(thread_checker_.CalledOnValidThread()); | 193 DCHECK(thread_checker_.CalledOnValidThread()); |
195 const auto& resource_entry = resource_ids_.find(device_info.device_id); | 194 const auto& resource_entry = resource_ids_.find(device_info->device_id()); |
196 DCHECK(resource_entry != resource_ids_.end()); | 195 DCHECK(resource_entry != resource_ids_.end()); |
197 int resource_id = resource_entry->second; | 196 int resource_id = resource_entry->second; |
198 const auto& device_entry = device_ids_.find(resource_id); | 197 const auto& device_entry = device_ids_.find(resource_id); |
199 DCHECK(device_entry != device_ids_.end()); | 198 DCHECK(device_entry != device_ids_.end()); |
200 resource_ids_.erase(resource_entry); | 199 resource_ids_.erase(resource_entry); |
201 device_ids_.erase(device_entry); | 200 device_ids_.erase(device_entry); |
202 | 201 |
203 if (event_router_) { | 202 if (event_router_) { |
204 DCHECK(enumeration_ready_); | 203 DCHECK(enumeration_ready_); |
205 scoped_ptr<base::ListValue> args(hid::OnDeviceRemoved::Create(resource_id)); | 204 scoped_ptr<base::ListValue> args(hid::OnDeviceRemoved::Create(resource_id)); |
(...skipping 21 matching lines...) Expand all Loading... |
227 const Extension* extension, | 226 const Extension* extension, |
228 const std::vector<HidDeviceFilter>& filters) { | 227 const std::vector<HidDeviceFilter>& filters) { |
229 HidService* hid_service = device::DeviceClient::Get()->GetHidService(); | 228 HidService* hid_service = device::DeviceClient::Get()->GetHidService(); |
230 DCHECK(hid_service); | 229 DCHECK(hid_service); |
231 | 230 |
232 scoped_ptr<base::ListValue> api_devices(new base::ListValue()); | 231 scoped_ptr<base::ListValue> api_devices(new base::ListValue()); |
233 for (const std::pair<int, HidDeviceId>& map_entry : device_ids_) { | 232 for (const std::pair<int, HidDeviceId>& map_entry : device_ids_) { |
234 int resource_id = map_entry.first; | 233 int resource_id = map_entry.first; |
235 const HidDeviceId& device_id = map_entry.second; | 234 const HidDeviceId& device_id = map_entry.second; |
236 | 235 |
237 HidDeviceInfo device_info; | 236 scoped_refptr<HidDeviceInfo> device_info = |
238 if (!hid_service->GetDeviceInfo(device_id, &device_info)) { | 237 hid_service->GetDeviceInfo(device_id); |
| 238 if (!device_info) { |
239 continue; | 239 continue; |
240 } | 240 } |
241 | 241 |
242 if (!filters.empty() && | 242 if (!filters.empty() && |
243 !HidDeviceFilter::MatchesAny(device_info, filters)) { | 243 !HidDeviceFilter::MatchesAny(device_info, filters)) { |
244 continue; | 244 continue; |
245 } | 245 } |
246 | 246 |
247 if (!HasPermission(extension, device_info)) { | 247 if (!HasPermission(extension, device_info)) { |
248 continue; | 248 continue; |
249 } | 249 } |
250 | 250 |
251 hid::HidDeviceInfo api_device_info; | 251 hid::HidDeviceInfo api_device_info; |
252 api_device_info.device_id = resource_id; | 252 api_device_info.device_id = resource_id; |
253 PopulateHidDeviceInfo(&api_device_info, device_info); | 253 PopulateHidDeviceInfo(&api_device_info, device_info); |
254 | 254 |
255 // Expose devices with which user can communicate. | 255 // Expose devices with which user can communicate. |
256 if (api_device_info.collections.size() > 0) { | 256 if (api_device_info.collections.size() > 0) { |
257 api_devices->Append(api_device_info.ToValue().release()); | 257 api_devices->Append(api_device_info.ToValue().release()); |
258 } | 258 } |
259 } | 259 } |
260 | 260 |
261 return api_devices.Pass(); | 261 return api_devices.Pass(); |
262 } | 262 } |
263 | 263 |
264 void HidDeviceManager::OnEnumerationComplete( | 264 void HidDeviceManager::OnEnumerationComplete( |
265 const std::vector<HidDeviceInfo>& devices) { | 265 const std::vector<scoped_refptr<HidDeviceInfo>>& devices) { |
266 DCHECK(resource_ids_.empty()); | 266 DCHECK(resource_ids_.empty()); |
267 DCHECK(device_ids_.empty()); | 267 DCHECK(device_ids_.empty()); |
268 for (const device::HidDeviceInfo& device_info : devices) { | 268 for (const scoped_refptr<HidDeviceInfo>& device_info : devices) { |
269 OnDeviceAdded(device_info); | 269 OnDeviceAdded(device_info); |
270 } | 270 } |
271 enumeration_ready_ = true; | 271 enumeration_ready_ = true; |
272 | 272 |
273 for (const GetApiDevicesParams* params : pending_enumerations_) { | 273 for (const GetApiDevicesParams* params : pending_enumerations_) { |
274 scoped_ptr<base::ListValue> devices = | 274 scoped_ptr<base::ListValue> devices = |
275 CreateApiDeviceList(params->extension, params->filters); | 275 CreateApiDeviceList(params->extension, params->filters); |
276 params->callback.Run(devices.Pass()); | 276 params->callback.Run(devices.Pass()); |
277 } | 277 } |
278 pending_enumerations_.clear(); | 278 pending_enumerations_.clear(); |
279 } | 279 } |
280 | 280 |
281 void HidDeviceManager::DispatchEvent(const std::string& event_name, | 281 void HidDeviceManager::DispatchEvent(const std::string& event_name, |
282 scoped_ptr<base::ListValue> event_args, | 282 scoped_ptr<base::ListValue> event_args, |
283 const HidDeviceInfo& device_info) { | 283 scoped_refptr<HidDeviceInfo> device_info) { |
284 scoped_ptr<Event> event(new Event(event_name, event_args.Pass())); | 284 scoped_ptr<Event> event(new Event(event_name, event_args.Pass())); |
285 event->will_dispatch_callback = | 285 event->will_dispatch_callback = |
286 base::Bind(&WillDispatchDeviceEvent, device_info); | 286 base::Bind(&WillDispatchDeviceEvent, device_info); |
287 event_router_->BroadcastEvent(event.Pass()); | 287 event_router_->BroadcastEvent(event.Pass()); |
288 } | 288 } |
289 | 289 |
290 } // namespace extensions | 290 } // namespace extensions |
OLD | NEW |