| 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 |