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
3 // found in the LICENSE file.
5 #include "extensions/browser/api/device_permissions_manager.h"
8 #include "base/memory/singleton.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "components/keyed_service/content/browser_context_dependency_manager.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "device/core/device_client.h"
16 #include "device/hid/hid_device_info.h"
17 #include "device/hid/hid_service.h"
18 #include "device/usb/usb_device.h"
19 #include "device/usb/usb_ids.h"
20 #include "extensions/browser/extension_host.h"
21 #include "extensions/browser/extension_prefs.h"
22 #include "extensions/browser/extensions_browser_client.h"
23 #include "extensions/browser/process_manager.h"
24 #include "extensions/browser/process_manager_factory.h"
25 #include "extensions/common/value_builder.h"
26 #include "extensions/strings/grit/extensions_strings.h"
27 #include "ui/base/l10n/l10n_util.h"
29 namespace extensions
{
31 using content::BrowserContext
;
32 using content::BrowserThread
;
33 using device::HidDeviceInfo
;
34 using device::HidService
;
35 using device::UsbDevice
;
36 using device::UsbService
;
37 using extensions::APIPermission
;
38 using extensions::Extension
;
39 using extensions::ExtensionHost
;
40 using extensions::ExtensionPrefs
;
46 // The device that the app has permission to access.
47 const char kDevices
[] = "devices";
49 // The type of device saved.
50 const char kDeviceType
[] = "type";
52 // Type identifier for USB devices.
53 const char kDeviceTypeUsb
[] = "usb";
55 // Type identifier for HID devices.
56 const char kDeviceTypeHid
[] = "hid";
58 // The vendor ID of the device that the app had permission to access.
59 const char kDeviceVendorId
[] = "vendor_id";
61 // The product ID of the device that the app had permission to access.
62 const char kDeviceProductId
[] = "product_id";
64 // The serial number of the device that the app has permission to access.
65 const char kDeviceSerialNumber
[] = "serial_number";
67 // The manufacturer string read from the device that the app has permission to
69 const char kDeviceManufacturerString
[] = "manufacturer_string";
71 // The product string read from the device that the app has permission to
73 const char kDeviceProductString
[] = "product_string";
75 // Serialized timestamp of the last time when the device was opened by the app.
76 const char kDeviceLastUsed
[] = "last_used_time";
78 // Converts a DevicePermissionEntry::Type to a string for the prefs file.
79 const char* TypeToString(DevicePermissionEntry::Type type
) {
81 case DevicePermissionEntry::Type::USB
:
82 return kDeviceTypeUsb
;
83 case DevicePermissionEntry::Type::HID
:
84 return kDeviceTypeHid
;
90 // Persists a DevicePermissionEntry in ExtensionPrefs.
91 void SaveDevicePermissionEntry(BrowserContext
* context
,
92 const std::string
& extension_id
,
93 scoped_refptr
<DevicePermissionEntry
> entry
) {
94 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
95 ExtensionPrefs::ScopedListUpdate
update(prefs
, extension_id
, kDevices
);
96 base::ListValue
* devices
= update
.Get();
98 devices
= update
.Create();
101 scoped_ptr
<base::Value
> device_entry(entry
->ToValue());
102 DCHECK(devices
->Find(*device_entry
.get()) == devices
->end());
103 devices
->Append(device_entry
.release());
106 bool MatchesDevicePermissionEntry(const base::DictionaryValue
* value
,
107 scoped_refptr
<DevicePermissionEntry
> entry
) {
109 if (!value
->GetStringWithoutPathExpansion(kDeviceType
, &type
) ||
110 type
!= TypeToString(entry
->type())) {
114 if (!value
->GetIntegerWithoutPathExpansion(kDeviceVendorId
, &vendor_id
) ||
115 vendor_id
!= entry
->vendor_id()) {
119 if (!value
->GetIntegerWithoutPathExpansion(kDeviceProductId
, &product_id
) ||
120 product_id
!= entry
->product_id()) {
123 base::string16 serial_number
;
124 if (!value
->GetStringWithoutPathExpansion(kDeviceSerialNumber
,
126 serial_number
!= entry
->serial_number()) {
132 // Updates the timestamp stored in ExtensionPrefs for the given
133 // DevicePermissionEntry.
134 void UpdateDevicePermissionEntry(BrowserContext
* context
,
135 const std::string
& extension_id
,
136 scoped_refptr
<DevicePermissionEntry
> entry
) {
137 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
138 ExtensionPrefs::ScopedListUpdate
update(prefs
, extension_id
, kDevices
);
139 base::ListValue
* devices
= update
.Get();
144 for (size_t i
= 0; i
< devices
->GetSize(); ++i
) {
145 base::DictionaryValue
* dict_value
;
146 if (!devices
->GetDictionary(i
, &dict_value
)) {
149 if (!MatchesDevicePermissionEntry(dict_value
, entry
)) {
152 devices
->Set(i
, entry
->ToValue().release());
157 // Removes the given DevicePermissionEntry from ExtensionPrefs.
158 void RemoveDevicePermissionEntry(BrowserContext
* context
,
159 const std::string
& extension_id
,
160 scoped_refptr
<DevicePermissionEntry
> entry
) {
161 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
162 ExtensionPrefs::ScopedListUpdate
update(prefs
, extension_id
, kDevices
);
163 base::ListValue
* devices
= update
.Get();
168 for (size_t i
= 0; i
< devices
->GetSize(); ++i
) {
169 base::DictionaryValue
* dict_value
;
170 if (!devices
->GetDictionary(i
, &dict_value
)) {
173 if (!MatchesDevicePermissionEntry(dict_value
, entry
)) {
176 devices
->Remove(i
, nullptr);
181 // Clears all DevicePermissionEntries for the app from ExtensionPrefs.
182 void ClearDevicePermissionEntries(ExtensionPrefs
* prefs
,
183 const std::string
& extension_id
) {
184 prefs
->UpdateExtensionPref(extension_id
, kDevices
, NULL
);
187 scoped_refptr
<DevicePermissionEntry
> ReadDevicePermissionEntry(
188 const base::DictionaryValue
* entry
) {
190 if (!entry
->GetIntegerWithoutPathExpansion(kDeviceVendorId
, &vendor_id
) ||
191 vendor_id
< 0 || vendor_id
> UINT16_MAX
) {
196 if (!entry
->GetIntegerWithoutPathExpansion(kDeviceProductId
, &product_id
) ||
197 product_id
< 0 || product_id
> UINT16_MAX
) {
201 base::string16 serial_number
;
202 if (!entry
->GetStringWithoutPathExpansion(kDeviceSerialNumber
,
207 base::string16 manufacturer_string
;
208 // Ignore failure as this string is optional.
209 entry
->GetStringWithoutPathExpansion(kDeviceManufacturerString
,
210 &manufacturer_string
);
212 base::string16 product_string
;
213 // Ignore failure as this string is optional.
214 entry
->GetStringWithoutPathExpansion(kDeviceProductString
, &product_string
);
216 // If a last used time is not stored in ExtensionPrefs last_used.is_null()
218 std::string last_used_str
;
219 int64 last_used_i64
= 0;
220 base::Time last_used
;
221 if (entry
->GetStringWithoutPathExpansion(kDeviceLastUsed
, &last_used_str
) &&
222 base::StringToInt64(last_used_str
, &last_used_i64
)) {
223 last_used
= base::Time::FromInternalValue(last_used_i64
);
227 if (!entry
->GetStringWithoutPathExpansion(kDeviceType
, &type
)) {
231 if (type
== kDeviceTypeUsb
) {
232 return new DevicePermissionEntry(
233 DevicePermissionEntry::Type::USB
, vendor_id
, product_id
, serial_number
,
234 manufacturer_string
, product_string
, last_used
);
235 } else if (type
== kDeviceTypeHid
) {
236 return new DevicePermissionEntry(
237 DevicePermissionEntry::Type::HID
, vendor_id
, product_id
, serial_number
,
238 base::string16(), product_string
, last_used
);
243 // Returns all DevicePermissionEntries for the app.
244 std::set
<scoped_refptr
<DevicePermissionEntry
>> GetDevicePermissionEntries(
245 ExtensionPrefs
* prefs
,
246 const std::string
& extension_id
) {
247 std::set
<scoped_refptr
<DevicePermissionEntry
>> result
;
248 const base::ListValue
* devices
= NULL
;
249 if (!prefs
->ReadPrefAsList(extension_id
, kDevices
, &devices
)) {
253 for (const base::Value
* entry
: *devices
) {
254 const base::DictionaryValue
* entry_dict
;
255 if (entry
->GetAsDictionary(&entry_dict
)) {
256 scoped_refptr
<DevicePermissionEntry
> device_entry
=
257 ReadDevicePermissionEntry(entry_dict
);
259 result
.insert(device_entry
);
268 DevicePermissionEntry::DevicePermissionEntry(scoped_refptr
<UsbDevice
> device
)
269 : usb_device_(device
),
271 vendor_id_(device
->vendor_id()),
272 product_id_(device
->product_id()),
273 serial_number_(device
->serial_number()),
274 manufacturer_string_(device
->manufacturer_string()),
275 product_string_(device
->product_string()) {
278 DevicePermissionEntry::DevicePermissionEntry(
279 scoped_refptr
<HidDeviceInfo
> device
)
280 : hid_device_(device
),
282 vendor_id_(device
->vendor_id()),
283 product_id_(device
->product_id()),
284 serial_number_(base::UTF8ToUTF16(device
->serial_number())),
285 product_string_(base::UTF8ToUTF16(device
->product_name())) {
288 DevicePermissionEntry::DevicePermissionEntry(
292 const base::string16
& serial_number
,
293 const base::string16
& manufacturer_string
,
294 const base::string16
& product_string
,
295 const base::Time
& last_used
)
297 vendor_id_(vendor_id
),
298 product_id_(product_id
),
299 serial_number_(serial_number
),
300 manufacturer_string_(manufacturer_string
),
301 product_string_(product_string
),
302 last_used_(last_used
) {
305 DevicePermissionEntry::~DevicePermissionEntry() {
308 bool DevicePermissionEntry::IsPersistent() const {
309 return !serial_number_
.empty();
312 scoped_ptr
<base::Value
> DevicePermissionEntry::ToValue() const {
313 if (!IsPersistent()) {
317 DCHECK(!serial_number_
.empty());
318 scoped_ptr
<base::DictionaryValue
> entry_dict(
320 .Set(kDeviceType
, TypeToString(type_
))
321 .Set(kDeviceVendorId
, vendor_id_
)
322 .Set(kDeviceProductId
, product_id_
)
323 .Set(kDeviceSerialNumber
, serial_number_
)
326 if (!manufacturer_string_
.empty()) {
327 entry_dict
->SetStringWithoutPathExpansion(kDeviceManufacturerString
,
328 manufacturer_string_
);
330 if (!product_string_
.empty()) {
331 entry_dict
->SetStringWithoutPathExpansion(kDeviceProductString
,
334 if (!last_used_
.is_null()) {
335 entry_dict
->SetStringWithoutPathExpansion(
336 kDeviceLastUsed
, base::Int64ToString(last_used_
.ToInternalValue()));
339 return entry_dict
.Pass();
342 base::string16
DevicePermissionEntry::GetPermissionMessageString() const {
343 return DevicePermissionsManager::GetPermissionMessage(
344 vendor_id_
, product_id_
, manufacturer_string_
, product_string_
,
345 serial_number_
, type_
== Type::USB
);
348 DevicePermissions::~DevicePermissions() {
351 scoped_refptr
<DevicePermissionEntry
> DevicePermissions::FindUsbDeviceEntry(
352 scoped_refptr
<UsbDevice
> device
) const {
353 const auto& ephemeral_device_entry
=
354 ephemeral_usb_devices_
.find(device
.get());
355 if (ephemeral_device_entry
!= ephemeral_usb_devices_
.end()) {
356 return ephemeral_device_entry
->second
;
359 if (device
->serial_number().empty()) {
363 for (const auto& entry
: entries_
) {
364 if (entry
->IsPersistent() && entry
->vendor_id() == device
->vendor_id() &&
365 entry
->product_id() == device
->product_id() &&
366 entry
->serial_number() == device
->serial_number()) {
373 scoped_refptr
<DevicePermissionEntry
> DevicePermissions::FindHidDeviceEntry(
374 scoped_refptr
<HidDeviceInfo
> device
) const {
375 const auto& ephemeral_device_entry
=
376 ephemeral_hid_devices_
.find(device
.get());
377 if (ephemeral_device_entry
!= ephemeral_hid_devices_
.end()) {
378 return ephemeral_device_entry
->second
;
381 if (device
->serial_number().empty()) {
385 base::string16 serial_number
= base::UTF8ToUTF16(device
->serial_number());
386 for (const auto& entry
: entries_
) {
387 if (entry
->IsPersistent() && entry
->vendor_id() == device
->vendor_id() &&
388 entry
->product_id() == device
->product_id() &&
389 entry
->serial_number() == serial_number
) {
396 DevicePermissions::DevicePermissions(BrowserContext
* context
,
397 const std::string
& extension_id
) {
398 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
399 entries_
= GetDevicePermissionEntries(prefs
, extension_id
);
403 DevicePermissionsManager
* DevicePermissionsManager::Get(
404 BrowserContext
* context
) {
405 return DevicePermissionsManagerFactory::GetForBrowserContext(context
);
409 base::string16
DevicePermissionsManager::GetPermissionMessage(
412 const base::string16
& manufacturer_string
,
413 const base::string16
& product_string
,
414 const base::string16
& serial_number
,
415 bool always_include_manufacturer
) {
416 base::string16 product
= product_string
;
417 if (product
.empty()) {
418 const char* product_name
=
419 device::UsbIds::GetProductName(vendor_id
, product_id
);
421 product
= base::UTF8ToUTF16(product_name
);
425 base::string16 manufacturer
= manufacturer_string
;
426 if (manufacturer_string
.empty()) {
427 const char* vendor_name
= device::UsbIds::GetVendorName(vendor_id
);
429 manufacturer
= base::UTF8ToUTF16(vendor_name
);
433 if (serial_number
.empty()) {
434 if (product
.empty()) {
435 product
= base::ASCIIToUTF16(base::StringPrintf("%04x", product_id
));
436 if (manufacturer
.empty()) {
438 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id
));
439 return l10n_util::GetStringFUTF16(
440 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_UNKNOWN_VENDOR
, product
,
443 return l10n_util::GetStringFUTF16(
444 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_VENDOR
, product
, manufacturer
);
447 if (always_include_manufacturer
) {
448 if (manufacturer
.empty()) {
450 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id
));
451 return l10n_util::GetStringFUTF16(
452 IDS_DEVICE_NAME_WITH_PRODUCT_UNKNOWN_VENDOR
, product
,
455 return l10n_util::GetStringFUTF16(IDS_DEVICE_NAME_WITH_PRODUCT_VENDOR
,
456 product
, manufacturer
);
463 if (product
.empty()) {
464 product
= base::ASCIIToUTF16(base::StringPrintf("%04x", product_id
));
465 if (manufacturer
.empty()) {
467 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id
));
468 return l10n_util::GetStringFUTF16(
469 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_UNKNOWN_VENDOR_SERIAL
, product
,
470 manufacturer
, serial_number
);
472 return l10n_util::GetStringFUTF16(
473 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_VENDOR_SERIAL
, product
,
474 manufacturer
, serial_number
);
477 if (always_include_manufacturer
) {
478 if (manufacturer
.empty()) {
480 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id
));
481 return l10n_util::GetStringFUTF16(
482 IDS_DEVICE_NAME_WITH_PRODUCT_UNKNOWN_VENDOR_SERIAL
, product
,
483 manufacturer
, serial_number
);
485 return l10n_util::GetStringFUTF16(
486 IDS_DEVICE_NAME_WITH_PRODUCT_VENDOR_SERIAL
, product
, manufacturer
,
490 return l10n_util::GetStringFUTF16(IDS_DEVICE_NAME_WITH_PRODUCT_SERIAL
,
491 product
, serial_number
);
497 DevicePermissions
* DevicePermissionsManager::GetForExtension(
498 const std::string
& extension_id
) {
499 DCHECK(thread_checker_
.CalledOnValidThread());
500 DevicePermissions
* device_permissions
= GetInternal(extension_id
);
501 if (!device_permissions
) {
502 device_permissions
= new DevicePermissions(context_
, extension_id
);
503 extension_id_to_device_permissions_
[extension_id
] = device_permissions
;
506 return device_permissions
;
509 std::vector
<base::string16
>
510 DevicePermissionsManager::GetPermissionMessageStrings(
511 const std::string
& extension_id
) const {
512 DCHECK(thread_checker_
.CalledOnValidThread());
513 std::vector
<base::string16
> messages
;
514 const DevicePermissions
* device_permissions
= GetInternal(extension_id
);
515 if (device_permissions
) {
516 for (const scoped_refptr
<DevicePermissionEntry
>& entry
:
517 device_permissions
->entries()) {
518 messages
.push_back(entry
->GetPermissionMessageString());
524 void DevicePermissionsManager::AllowUsbDevice(const std::string
& extension_id
,
525 scoped_refptr
<UsbDevice
> device
) {
526 DCHECK(thread_checker_
.CalledOnValidThread());
527 DevicePermissions
* device_permissions
= GetForExtension(extension_id
);
529 scoped_refptr
<DevicePermissionEntry
> device_entry(
530 new DevicePermissionEntry(device
));
532 if (device_entry
->IsPersistent()) {
533 for (const auto& entry
: device_permissions
->entries()) {
534 if (entry
->vendor_id() == device_entry
->vendor_id() &&
535 entry
->product_id() == device_entry
->product_id() &&
536 entry
->serial_number() == device_entry
->serial_number()) {
541 device_permissions
->entries_
.insert(device_entry
);
542 SaveDevicePermissionEntry(context_
, extension_id
, device_entry
);
543 } else if (!ContainsKey(device_permissions
->ephemeral_usb_devices_
,
545 // Non-persistent devices cannot be reliably identified when they are
546 // reconnected so such devices are only remembered until disconnect.
547 // Register an observer here so that this set doesn't grow undefinitely.
548 device_permissions
->entries_
.insert(device_entry
);
549 device_permissions
->ephemeral_usb_devices_
[device
.get()] = device_entry
;
551 // Only start observing when an ephemeral device has been added so that
552 // UsbService is not automatically initialized on profile creation (which it
553 // would be if this call were in the constructor).
554 UsbService
* usb_service
= device::DeviceClient::Get()->GetUsbService();
555 if (!usb_service_observer_
.IsObserving(usb_service
)) {
556 usb_service_observer_
.Add(usb_service
);
561 void DevicePermissionsManager::AllowHidDevice(
562 const std::string
& extension_id
,
563 scoped_refptr
<HidDeviceInfo
> device
) {
564 DCHECK(thread_checker_
.CalledOnValidThread());
565 DevicePermissions
* device_permissions
= GetForExtension(extension_id
);
567 scoped_refptr
<DevicePermissionEntry
> device_entry(
568 new DevicePermissionEntry(device
));
570 if (device_entry
->IsPersistent()) {
571 for (const auto& entry
: device_permissions
->entries()) {
572 if (entry
->vendor_id() == device_entry
->vendor_id() &&
573 entry
->product_id() == device_entry
->product_id() &&
574 entry
->serial_number() == device_entry
->serial_number()) {
579 device_permissions
->entries_
.insert(device_entry
);
580 SaveDevicePermissionEntry(context_
, extension_id
, device_entry
);
581 } else if (!ContainsKey(device_permissions
->ephemeral_hid_devices_
,
583 // Non-persistent devices cannot be reliably identified when they are
584 // reconnected so such devices are only remembered until disconnect.
585 // Register an observer here so that this set doesn't grow undefinitely.
586 device_permissions
->entries_
.insert(device_entry
);
587 device_permissions
->ephemeral_hid_devices_
[device
.get()] = device_entry
;
589 // Only start observing when an ephemeral device has been added so that
590 // HidService is not automatically initialized on profile creation (which it
591 // would be if this call were in the constructor).
592 HidService
* hid_service
= device::DeviceClient::Get()->GetHidService();
593 if (!hid_service_observer_
.IsObserving(hid_service
)) {
594 hid_service_observer_
.Add(hid_service
);
599 void DevicePermissionsManager::UpdateLastUsed(
600 const std::string
& extension_id
,
601 scoped_refptr
<DevicePermissionEntry
> entry
) {
602 DCHECK(thread_checker_
.CalledOnValidThread());
603 entry
->set_last_used(base::Time::Now());
604 if (entry
->IsPersistent()) {
605 UpdateDevicePermissionEntry(context_
, extension_id
, entry
);
609 void DevicePermissionsManager::RemoveEntry(
610 const std::string
& extension_id
,
611 scoped_refptr
<DevicePermissionEntry
> entry
) {
612 DCHECK(thread_checker_
.CalledOnValidThread());
613 DevicePermissions
* device_permissions
= GetInternal(extension_id
);
614 DCHECK(device_permissions
);
615 DCHECK(ContainsKey(device_permissions
->entries_
, entry
));
616 device_permissions
->entries_
.erase(entry
);
617 if (entry
->IsPersistent()) {
618 RemoveDevicePermissionEntry(context_
, extension_id
, entry
);
619 } else if (entry
->type_
== DevicePermissionEntry::Type::USB
) {
620 device_permissions
->ephemeral_usb_devices_
.erase(entry
->usb_device_
.get());
621 } else if (entry
->type_
== DevicePermissionEntry::Type::HID
) {
622 device_permissions
->ephemeral_hid_devices_
.erase(entry
->hid_device_
.get());
628 void DevicePermissionsManager::Clear(const std::string
& extension_id
) {
629 DCHECK(thread_checker_
.CalledOnValidThread());
631 ClearDevicePermissionEntries(ExtensionPrefs::Get(context_
), extension_id
);
632 DevicePermissions
* device_permissions
= GetInternal(extension_id
);
633 if (device_permissions
) {
634 extension_id_to_device_permissions_
.erase(extension_id
);
635 delete device_permissions
;
639 DevicePermissionsManager::DevicePermissionsManager(
640 content::BrowserContext
* context
)
642 process_manager_observer_(this),
643 usb_service_observer_(this),
644 hid_service_observer_(this) {
645 process_manager_observer_
.Add(ProcessManager::Get(context
));
648 DevicePermissionsManager::~DevicePermissionsManager() {
649 for (const auto& map_entry
: extension_id_to_device_permissions_
) {
650 DevicePermissions
* device_permissions
= map_entry
.second
;
651 delete device_permissions
;
655 DevicePermissions
* DevicePermissionsManager::GetInternal(
656 const std::string
& extension_id
) const {
657 std::map
<std::string
, DevicePermissions
*>::const_iterator it
=
658 extension_id_to_device_permissions_
.find(extension_id
);
659 if (it
!= extension_id_to_device_permissions_
.end()) {
666 void DevicePermissionsManager::OnBackgroundHostClose(
667 const std::string
& extension_id
) {
668 DCHECK(thread_checker_
.CalledOnValidThread());
670 DevicePermissions
* device_permissions
= GetInternal(extension_id
);
671 if (device_permissions
) {
672 // When all of the app's windows are closed and the background page is
673 // suspended all ephemeral device permissions are cleared.
674 for (const auto& map_entry
: device_permissions
->ephemeral_usb_devices_
) {
675 device_permissions
->entries_
.erase(map_entry
.second
);
677 device_permissions
->ephemeral_usb_devices_
.clear();
678 for (const auto& map_entry
: device_permissions
->ephemeral_hid_devices_
) {
679 device_permissions
->entries_
.erase(map_entry
.second
);
681 device_permissions
->ephemeral_hid_devices_
.clear();
685 void DevicePermissionsManager::OnDeviceRemovedCleanup(
686 scoped_refptr
<UsbDevice
> device
) {
687 DCHECK(thread_checker_
.CalledOnValidThread());
688 for (const auto& map_entry
: extension_id_to_device_permissions_
) {
689 // An ephemeral device cannot be identified if it is reconnected and so
690 // permission to access it is cleared on disconnect.
691 DevicePermissions
* device_permissions
= map_entry
.second
;
692 const auto& device_entry
=
693 device_permissions
->ephemeral_usb_devices_
.find(device
.get());
694 if (device_entry
!= device_permissions
->ephemeral_usb_devices_
.end()) {
695 device_permissions
->entries_
.erase(device_entry
->second
);
696 device_permissions
->ephemeral_usb_devices_
.erase(device_entry
);
701 void DevicePermissionsManager::OnDeviceRemovedCleanup(
702 scoped_refptr
<device::HidDeviceInfo
> device
) {
703 DCHECK(thread_checker_
.CalledOnValidThread());
704 for (const auto& map_entry
: extension_id_to_device_permissions_
) {
705 // An ephemeral device cannot be identified if it is reconnected and so
706 // permission to access it is cleared on disconnect.
707 DevicePermissions
* device_permissions
= map_entry
.second
;
708 const auto& device_entry
=
709 device_permissions
->ephemeral_hid_devices_
.find(device
.get());
710 if (device_entry
!= device_permissions
->ephemeral_hid_devices_
.end()) {
711 device_permissions
->entries_
.erase(device_entry
->second
);
712 device_permissions
->ephemeral_hid_devices_
.erase(device_entry
);
718 DevicePermissionsManager
* DevicePermissionsManagerFactory::GetForBrowserContext(
719 content::BrowserContext
* context
) {
720 return static_cast<DevicePermissionsManager
*>(
721 GetInstance()->GetServiceForBrowserContext(context
, true));
725 DevicePermissionsManagerFactory
*
726 DevicePermissionsManagerFactory::GetInstance() {
727 return Singleton
<DevicePermissionsManagerFactory
>::get();
730 DevicePermissionsManagerFactory::DevicePermissionsManagerFactory()
731 : BrowserContextKeyedServiceFactory(
732 "DevicePermissionsManager",
733 BrowserContextDependencyManager::GetInstance()) {
734 DependsOn(ProcessManagerFactory::GetInstance());
737 DevicePermissionsManagerFactory::~DevicePermissionsManagerFactory() {
740 KeyedService
* DevicePermissionsManagerFactory::BuildServiceInstanceFor(
741 content::BrowserContext
* context
) const {
742 return new DevicePermissionsManager(context
);
745 BrowserContext
* DevicePermissionsManagerFactory::GetBrowserContextToUse(
746 BrowserContext
* context
) const {
747 // Return the original (possibly off-the-record) browser context so that a
748 // separate instance of the DevicePermissionsManager is used in incognito
749 // mode. The parent class's implemenation returns NULL.
753 } // namespace extensions