Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / extensions / browser / api / device_permissions_manager.cc
blobf18e271766dd243206dac4e5c6afaab7e809abbf
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"
7 #include "base/bind.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/common/value_builder.h"
24 #include "extensions/strings/grit/extensions_strings.h"
25 #include "ui/base/l10n/l10n_util.h"
27 namespace extensions {
29 using content::BrowserContext;
30 using content::BrowserThread;
31 using device::HidDeviceInfo;
32 using device::HidService;
33 using device::UsbDevice;
34 using device::UsbService;
35 using extensions::APIPermission;
36 using extensions::Extension;
37 using extensions::ExtensionHost;
38 using extensions::ExtensionPrefs;
40 namespace {
42 // Preference keys
44 // The device that the app has permission to access.
45 const char kDevices[] = "devices";
47 // The type of device saved.
48 const char kDeviceType[] = "type";
50 // Type identifier for USB devices.
51 const char kDeviceTypeUsb[] = "usb";
53 // Type identifier for HID devices.
54 const char kDeviceTypeHid[] = "hid";
56 // The vendor ID of the device that the app had permission to access.
57 const char kDeviceVendorId[] = "vendor_id";
59 // The product ID of the device that the app had permission to access.
60 const char kDeviceProductId[] = "product_id";
62 // The serial number of the device that the app has permission to access.
63 const char kDeviceSerialNumber[] = "serial_number";
65 // The manufacturer string read from the device that the app has permission to
66 // access.
67 const char kDeviceManufacturerString[] = "manufacturer_string";
69 // The product string read from the device that the app has permission to
70 // access.
71 const char kDeviceProductString[] = "product_string";
73 // Serialized timestamp of the last time when the device was opened by the app.
74 const char kDeviceLastUsed[] = "last_used_time";
76 // Converts a DevicePermissionEntry::Type to a string for the prefs file.
77 const char* TypeToString(DevicePermissionEntry::Type type) {
78 switch (type) {
79 case DevicePermissionEntry::Type::USB:
80 return kDeviceTypeUsb;
81 case DevicePermissionEntry::Type::HID:
82 return kDeviceTypeHid;
84 NOTREACHED();
85 return "";
88 // Persists a DevicePermissionEntry in ExtensionPrefs.
89 void SaveDevicePermissionEntry(BrowserContext* context,
90 const std::string& extension_id,
91 scoped_refptr<DevicePermissionEntry> entry) {
92 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
93 ExtensionPrefs::ScopedListUpdate update(prefs, extension_id, kDevices);
94 base::ListValue* devices = update.Get();
95 if (!devices) {
96 devices = update.Create();
99 scoped_ptr<base::Value> device_entry(entry->ToValue());
100 DCHECK(devices->Find(*device_entry.get()) == devices->end());
101 devices->Append(device_entry.release());
104 bool MatchesDevicePermissionEntry(const base::DictionaryValue* value,
105 scoped_refptr<DevicePermissionEntry> entry) {
106 std::string type;
107 if (!value->GetStringWithoutPathExpansion(kDeviceType, &type) ||
108 type != TypeToString(entry->type())) {
109 return false;
111 int vendor_id;
112 if (!value->GetIntegerWithoutPathExpansion(kDeviceVendorId, &vendor_id) ||
113 vendor_id != entry->vendor_id()) {
114 return false;
116 int product_id;
117 if (!value->GetIntegerWithoutPathExpansion(kDeviceProductId, &product_id) ||
118 product_id != entry->product_id()) {
119 return false;
121 base::string16 serial_number;
122 if (!value->GetStringWithoutPathExpansion(kDeviceSerialNumber,
123 &serial_number) ||
124 serial_number != entry->serial_number()) {
125 return false;
127 return true;
130 // Updates the timestamp stored in ExtensionPrefs for the given
131 // DevicePermissionEntry.
132 void UpdateDevicePermissionEntry(BrowserContext* context,
133 const std::string& extension_id,
134 scoped_refptr<DevicePermissionEntry> entry) {
135 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
136 ExtensionPrefs::ScopedListUpdate update(prefs, extension_id, kDevices);
137 base::ListValue* devices = update.Get();
138 if (!devices) {
139 return;
142 for (size_t i = 0; i < devices->GetSize(); ++i) {
143 base::DictionaryValue* dict_value;
144 if (!devices->GetDictionary(i, &dict_value)) {
145 continue;
147 if (!MatchesDevicePermissionEntry(dict_value, entry)) {
148 continue;
150 devices->Set(i, entry->ToValue().release());
151 break;
155 // Removes the given DevicePermissionEntry from ExtensionPrefs.
156 void RemoveDevicePermissionEntry(BrowserContext* context,
157 const std::string& extension_id,
158 scoped_refptr<DevicePermissionEntry> entry) {
159 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
160 ExtensionPrefs::ScopedListUpdate update(prefs, extension_id, kDevices);
161 base::ListValue* devices = update.Get();
162 if (!devices) {
163 return;
166 for (size_t i = 0; i < devices->GetSize(); ++i) {
167 base::DictionaryValue* dict_value;
168 if (!devices->GetDictionary(i, &dict_value)) {
169 continue;
171 if (!MatchesDevicePermissionEntry(dict_value, entry)) {
172 continue;
174 devices->Remove(i, nullptr);
175 break;
179 // Clears all DevicePermissionEntries for the app from ExtensionPrefs.
180 void ClearDevicePermissionEntries(ExtensionPrefs* prefs,
181 const std::string& extension_id) {
182 prefs->UpdateExtensionPref(extension_id, kDevices, NULL);
185 scoped_refptr<DevicePermissionEntry> ReadDevicePermissionEntry(
186 const base::DictionaryValue* entry) {
187 int vendor_id;
188 if (!entry->GetIntegerWithoutPathExpansion(kDeviceVendorId, &vendor_id) ||
189 vendor_id < 0 || vendor_id > UINT16_MAX) {
190 return nullptr;
193 int product_id;
194 if (!entry->GetIntegerWithoutPathExpansion(kDeviceProductId, &product_id) ||
195 product_id < 0 || product_id > UINT16_MAX) {
196 return nullptr;
199 base::string16 serial_number;
200 if (!entry->GetStringWithoutPathExpansion(kDeviceSerialNumber,
201 &serial_number)) {
202 return nullptr;
205 base::string16 manufacturer_string;
206 // Ignore failure as this string is optional.
207 entry->GetStringWithoutPathExpansion(kDeviceManufacturerString,
208 &manufacturer_string);
210 base::string16 product_string;
211 // Ignore failure as this string is optional.
212 entry->GetStringWithoutPathExpansion(kDeviceProductString, &product_string);
214 // If a last used time is not stored in ExtensionPrefs last_used.is_null()
215 // will be true.
216 std::string last_used_str;
217 int64 last_used_i64 = 0;
218 base::Time last_used;
219 if (entry->GetStringWithoutPathExpansion(kDeviceLastUsed, &last_used_str) &&
220 base::StringToInt64(last_used_str, &last_used_i64)) {
221 last_used = base::Time::FromInternalValue(last_used_i64);
224 std::string type;
225 if (!entry->GetStringWithoutPathExpansion(kDeviceType, &type)) {
226 return nullptr;
229 if (type == kDeviceTypeUsb) {
230 return new DevicePermissionEntry(
231 DevicePermissionEntry::Type::USB, vendor_id, product_id, serial_number,
232 manufacturer_string, product_string, last_used);
233 } else if (type == kDeviceTypeHid) {
234 return new DevicePermissionEntry(
235 DevicePermissionEntry::Type::HID, vendor_id, product_id, serial_number,
236 base::string16(), product_string, last_used);
238 return nullptr;
241 // Returns all DevicePermissionEntries for the app.
242 std::set<scoped_refptr<DevicePermissionEntry>> GetDevicePermissionEntries(
243 ExtensionPrefs* prefs,
244 const std::string& extension_id) {
245 std::set<scoped_refptr<DevicePermissionEntry>> result;
246 const base::ListValue* devices = NULL;
247 if (!prefs->ReadPrefAsList(extension_id, kDevices, &devices)) {
248 return result;
251 for (const base::Value* entry : *devices) {
252 const base::DictionaryValue* entry_dict;
253 if (entry->GetAsDictionary(&entry_dict)) {
254 scoped_refptr<DevicePermissionEntry> device_entry =
255 ReadDevicePermissionEntry(entry_dict);
256 if (entry_dict) {
257 result.insert(device_entry);
261 return result;
264 } // namespace
266 DevicePermissionEntry::DevicePermissionEntry(scoped_refptr<UsbDevice> device)
267 : usb_device_(device),
268 type_(Type::USB),
269 vendor_id_(device->vendor_id()),
270 product_id_(device->product_id()),
271 serial_number_(device->serial_number()),
272 manufacturer_string_(device->manufacturer_string()),
273 product_string_(device->product_string()) {
276 DevicePermissionEntry::DevicePermissionEntry(
277 scoped_refptr<HidDeviceInfo> device)
278 : hid_device_(device),
279 type_(Type::HID),
280 vendor_id_(device->vendor_id()),
281 product_id_(device->product_id()),
282 serial_number_(base::UTF8ToUTF16(device->serial_number())),
283 product_string_(base::UTF8ToUTF16(device->product_name())) {
286 DevicePermissionEntry::DevicePermissionEntry(
287 Type type,
288 uint16_t vendor_id,
289 uint16_t product_id,
290 const base::string16& serial_number,
291 const base::string16& manufacturer_string,
292 const base::string16& product_string,
293 const base::Time& last_used)
294 : type_(type),
295 vendor_id_(vendor_id),
296 product_id_(product_id),
297 serial_number_(serial_number),
298 manufacturer_string_(manufacturer_string),
299 product_string_(product_string),
300 last_used_(last_used) {
303 DevicePermissionEntry::~DevicePermissionEntry() {
306 bool DevicePermissionEntry::IsPersistent() const {
307 return !serial_number_.empty();
310 scoped_ptr<base::Value> DevicePermissionEntry::ToValue() const {
311 if (!IsPersistent()) {
312 return nullptr;
315 DCHECK(!serial_number_.empty());
316 scoped_ptr<base::DictionaryValue> entry_dict(
317 DictionaryBuilder()
318 .Set(kDeviceType, TypeToString(type_))
319 .Set(kDeviceVendorId, vendor_id_)
320 .Set(kDeviceProductId, product_id_)
321 .Set(kDeviceSerialNumber, serial_number_)
322 .Build());
324 if (!manufacturer_string_.empty()) {
325 entry_dict->SetStringWithoutPathExpansion(kDeviceManufacturerString,
326 manufacturer_string_);
328 if (!product_string_.empty()) {
329 entry_dict->SetStringWithoutPathExpansion(kDeviceProductString,
330 product_string_);
332 if (!last_used_.is_null()) {
333 entry_dict->SetStringWithoutPathExpansion(
334 kDeviceLastUsed, base::Int64ToString(last_used_.ToInternalValue()));
337 return entry_dict.Pass();
340 base::string16 DevicePermissionEntry::GetPermissionMessageString() const {
341 return DevicePermissionsManager::GetPermissionMessage(
342 vendor_id_, product_id_, manufacturer_string_, product_string_,
343 serial_number_, type_ == Type::USB);
346 DevicePermissions::~DevicePermissions() {
349 scoped_refptr<DevicePermissionEntry> DevicePermissions::FindUsbDeviceEntry(
350 scoped_refptr<UsbDevice> device) const {
351 const auto& ephemeral_device_entry =
352 ephemeral_usb_devices_.find(device.get());
353 if (ephemeral_device_entry != ephemeral_usb_devices_.end()) {
354 return ephemeral_device_entry->second;
357 if (device->serial_number().empty()) {
358 return nullptr;
361 for (const auto& entry : entries_) {
362 if (entry->IsPersistent() && entry->vendor_id() == device->vendor_id() &&
363 entry->product_id() == device->product_id() &&
364 entry->serial_number() == device->serial_number()) {
365 return entry;
368 return nullptr;
371 scoped_refptr<DevicePermissionEntry> DevicePermissions::FindHidDeviceEntry(
372 scoped_refptr<HidDeviceInfo> device) const {
373 const auto& ephemeral_device_entry =
374 ephemeral_hid_devices_.find(device.get());
375 if (ephemeral_device_entry != ephemeral_hid_devices_.end()) {
376 return ephemeral_device_entry->second;
379 if (device->serial_number().empty()) {
380 return nullptr;
383 base::string16 serial_number = base::UTF8ToUTF16(device->serial_number());
384 for (const auto& entry : entries_) {
385 if (entry->IsPersistent() && entry->vendor_id() == device->vendor_id() &&
386 entry->product_id() == device->product_id() &&
387 entry->serial_number() == serial_number) {
388 return entry;
391 return nullptr;
394 DevicePermissions::DevicePermissions(BrowserContext* context,
395 const std::string& extension_id) {
396 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
397 entries_ = GetDevicePermissionEntries(prefs, extension_id);
400 // static
401 DevicePermissionsManager* DevicePermissionsManager::Get(
402 BrowserContext* context) {
403 return DevicePermissionsManagerFactory::GetForBrowserContext(context);
406 // static
407 base::string16 DevicePermissionsManager::GetPermissionMessage(
408 uint16 vendor_id,
409 uint16 product_id,
410 const base::string16& manufacturer_string,
411 const base::string16& product_string,
412 const base::string16& serial_number,
413 bool always_include_manufacturer) {
414 base::string16 product = product_string;
415 if (product.empty()) {
416 const char* product_name =
417 device::UsbIds::GetProductName(vendor_id, product_id);
418 if (product_name) {
419 product = base::UTF8ToUTF16(product_name);
423 base::string16 manufacturer = manufacturer_string;
424 if (manufacturer_string.empty()) {
425 const char* vendor_name = device::UsbIds::GetVendorName(vendor_id);
426 if (vendor_name) {
427 manufacturer = base::UTF8ToUTF16(vendor_name);
431 if (serial_number.empty()) {
432 if (product.empty()) {
433 product = base::ASCIIToUTF16(base::StringPrintf("%04x", product_id));
434 if (manufacturer.empty()) {
435 manufacturer =
436 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id));
437 return l10n_util::GetStringFUTF16(
438 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_UNKNOWN_VENDOR, product,
439 manufacturer);
440 } else {
441 return l10n_util::GetStringFUTF16(
442 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_VENDOR, product, manufacturer);
444 } else {
445 if (always_include_manufacturer) {
446 if (manufacturer.empty()) {
447 manufacturer =
448 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id));
449 return l10n_util::GetStringFUTF16(
450 IDS_DEVICE_NAME_WITH_PRODUCT_UNKNOWN_VENDOR, product,
451 manufacturer);
452 } else {
453 return l10n_util::GetStringFUTF16(IDS_DEVICE_NAME_WITH_PRODUCT_VENDOR,
454 product, manufacturer);
456 } else {
457 return product;
460 } else {
461 if (product.empty()) {
462 product = base::ASCIIToUTF16(base::StringPrintf("%04x", product_id));
463 if (manufacturer.empty()) {
464 manufacturer =
465 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id));
466 return l10n_util::GetStringFUTF16(
467 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_UNKNOWN_VENDOR_SERIAL, product,
468 manufacturer, serial_number);
469 } else {
470 return l10n_util::GetStringFUTF16(
471 IDS_DEVICE_NAME_WITH_UNKNOWN_PRODUCT_VENDOR_SERIAL, product,
472 manufacturer, serial_number);
474 } else {
475 if (always_include_manufacturer) {
476 if (manufacturer.empty()) {
477 manufacturer =
478 base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id));
479 return l10n_util::GetStringFUTF16(
480 IDS_DEVICE_NAME_WITH_PRODUCT_UNKNOWN_VENDOR_SERIAL, product,
481 manufacturer, serial_number);
482 } else {
483 return l10n_util::GetStringFUTF16(
484 IDS_DEVICE_NAME_WITH_PRODUCT_VENDOR_SERIAL, product, manufacturer,
485 serial_number);
487 } else {
488 return l10n_util::GetStringFUTF16(IDS_DEVICE_NAME_WITH_PRODUCT_SERIAL,
489 product, serial_number);
495 DevicePermissions* DevicePermissionsManager::GetForExtension(
496 const std::string& extension_id) {
497 DCHECK(thread_checker_.CalledOnValidThread());
498 DevicePermissions* device_permissions = GetInternal(extension_id);
499 if (!device_permissions) {
500 device_permissions = new DevicePermissions(context_, extension_id);
501 extension_id_to_device_permissions_[extension_id] = device_permissions;
504 return device_permissions;
507 std::vector<base::string16>
508 DevicePermissionsManager::GetPermissionMessageStrings(
509 const std::string& extension_id) const {
510 DCHECK(thread_checker_.CalledOnValidThread());
511 std::vector<base::string16> messages;
512 const DevicePermissions* device_permissions = GetInternal(extension_id);
513 if (device_permissions) {
514 for (const scoped_refptr<DevicePermissionEntry>& entry :
515 device_permissions->entries()) {
516 messages.push_back(entry->GetPermissionMessageString());
519 return messages;
522 void DevicePermissionsManager::AllowUsbDevice(const std::string& extension_id,
523 scoped_refptr<UsbDevice> device) {
524 DCHECK(thread_checker_.CalledOnValidThread());
525 DevicePermissions* device_permissions = GetForExtension(extension_id);
527 scoped_refptr<DevicePermissionEntry> device_entry(
528 new DevicePermissionEntry(device));
530 if (device_entry->IsPersistent()) {
531 for (const auto& entry : device_permissions->entries()) {
532 if (entry->vendor_id() == device_entry->vendor_id() &&
533 entry->product_id() == device_entry->product_id() &&
534 entry->serial_number() == device_entry->serial_number()) {
535 return;
539 device_permissions->entries_.insert(device_entry);
540 SaveDevicePermissionEntry(context_, extension_id, device_entry);
541 } else if (!ContainsKey(device_permissions->ephemeral_usb_devices_,
542 device.get())) {
543 // Non-persistent devices cannot be reliably identified when they are
544 // reconnected so such devices are only remembered until disconnect.
545 // Register an observer here so that this set doesn't grow undefinitely.
546 device_permissions->entries_.insert(device_entry);
547 device_permissions->ephemeral_usb_devices_[device.get()] = device_entry;
549 // Only start observing when an ephemeral device has been added so that
550 // UsbService is not automatically initialized on profile creation (which it
551 // would be if this call were in the constructor).
552 UsbService* usb_service = device::DeviceClient::Get()->GetUsbService();
553 if (!usb_service_observer_.IsObserving(usb_service)) {
554 usb_service_observer_.Add(usb_service);
559 void DevicePermissionsManager::AllowHidDevice(
560 const std::string& extension_id,
561 scoped_refptr<HidDeviceInfo> device) {
562 DCHECK(thread_checker_.CalledOnValidThread());
563 DevicePermissions* device_permissions = GetForExtension(extension_id);
565 scoped_refptr<DevicePermissionEntry> device_entry(
566 new DevicePermissionEntry(device));
568 if (device_entry->IsPersistent()) {
569 for (const auto& entry : device_permissions->entries()) {
570 if (entry->vendor_id() == device_entry->vendor_id() &&
571 entry->product_id() == device_entry->product_id() &&
572 entry->serial_number() == device_entry->serial_number()) {
573 return;
577 device_permissions->entries_.insert(device_entry);
578 SaveDevicePermissionEntry(context_, extension_id, device_entry);
579 } else if (!ContainsKey(device_permissions->ephemeral_hid_devices_,
580 device.get())) {
581 // Non-persistent devices cannot be reliably identified when they are
582 // reconnected so such devices are only remembered until disconnect.
583 // Register an observer here so that this set doesn't grow undefinitely.
584 device_permissions->entries_.insert(device_entry);
585 device_permissions->ephemeral_hid_devices_[device.get()] = device_entry;
587 // Only start observing when an ephemeral device has been added so that
588 // HidService is not automatically initialized on profile creation (which it
589 // would be if this call were in the constructor).
590 HidService* hid_service = device::DeviceClient::Get()->GetHidService();
591 if (!hid_service_observer_.IsObserving(hid_service)) {
592 hid_service_observer_.Add(hid_service);
597 void DevicePermissionsManager::UpdateLastUsed(
598 const std::string& extension_id,
599 scoped_refptr<DevicePermissionEntry> entry) {
600 DCHECK(thread_checker_.CalledOnValidThread());
601 entry->set_last_used(base::Time::Now());
602 if (entry->IsPersistent()) {
603 UpdateDevicePermissionEntry(context_, extension_id, entry);
607 void DevicePermissionsManager::RemoveEntry(
608 const std::string& extension_id,
609 scoped_refptr<DevicePermissionEntry> entry) {
610 DCHECK(thread_checker_.CalledOnValidThread());
611 DevicePermissions* device_permissions = GetInternal(extension_id);
612 DCHECK(device_permissions);
613 DCHECK(ContainsKey(device_permissions->entries_, entry));
614 device_permissions->entries_.erase(entry);
615 if (entry->IsPersistent()) {
616 RemoveDevicePermissionEntry(context_, extension_id, entry);
617 } else if (entry->type_ == DevicePermissionEntry::Type::USB) {
618 device_permissions->ephemeral_usb_devices_.erase(entry->usb_device_.get());
619 } else if (entry->type_ == DevicePermissionEntry::Type::HID) {
620 device_permissions->ephemeral_hid_devices_.erase(entry->hid_device_.get());
621 } else {
622 NOTREACHED();
626 void DevicePermissionsManager::Clear(const std::string& extension_id) {
627 DCHECK(thread_checker_.CalledOnValidThread());
629 ClearDevicePermissionEntries(ExtensionPrefs::Get(context_), extension_id);
630 DevicePermissions* device_permissions = GetInternal(extension_id);
631 if (device_permissions) {
632 extension_id_to_device_permissions_.erase(extension_id);
633 delete device_permissions;
637 DevicePermissionsManager::DevicePermissionsManager(
638 content::BrowserContext* context)
639 : context_(context),
640 usb_service_observer_(this),
641 hid_service_observer_(this) {
644 DevicePermissionsManager::~DevicePermissionsManager() {
645 for (const auto& map_entry : extension_id_to_device_permissions_) {
646 DevicePermissions* device_permissions = map_entry.second;
647 delete device_permissions;
651 DevicePermissions* DevicePermissionsManager::GetInternal(
652 const std::string& extension_id) const {
653 std::map<std::string, DevicePermissions*>::const_iterator it =
654 extension_id_to_device_permissions_.find(extension_id);
655 if (it != extension_id_to_device_permissions_.end()) {
656 return it->second;
659 return NULL;
662 void DevicePermissionsManager::OnDeviceRemovedCleanup(
663 scoped_refptr<UsbDevice> device) {
664 DCHECK(thread_checker_.CalledOnValidThread());
665 for (const auto& map_entry : extension_id_to_device_permissions_) {
666 // An ephemeral device cannot be identified if it is reconnected and so
667 // permission to access it is cleared on disconnect.
668 DevicePermissions* device_permissions = map_entry.second;
669 const auto& device_entry =
670 device_permissions->ephemeral_usb_devices_.find(device.get());
671 if (device_entry != device_permissions->ephemeral_usb_devices_.end()) {
672 device_permissions->entries_.erase(device_entry->second);
673 device_permissions->ephemeral_usb_devices_.erase(device_entry);
678 void DevicePermissionsManager::OnDeviceRemovedCleanup(
679 scoped_refptr<device::HidDeviceInfo> device) {
680 DCHECK(thread_checker_.CalledOnValidThread());
681 for (const auto& map_entry : extension_id_to_device_permissions_) {
682 // An ephemeral device cannot be identified if it is reconnected and so
683 // permission to access it is cleared on disconnect.
684 DevicePermissions* device_permissions = map_entry.second;
685 const auto& device_entry =
686 device_permissions->ephemeral_hid_devices_.find(device.get());
687 if (device_entry != device_permissions->ephemeral_hid_devices_.end()) {
688 device_permissions->entries_.erase(device_entry->second);
689 device_permissions->ephemeral_hid_devices_.erase(device_entry);
694 // static
695 DevicePermissionsManager* DevicePermissionsManagerFactory::GetForBrowserContext(
696 content::BrowserContext* context) {
697 return static_cast<DevicePermissionsManager*>(
698 GetInstance()->GetServiceForBrowserContext(context, true));
701 // static
702 DevicePermissionsManagerFactory*
703 DevicePermissionsManagerFactory::GetInstance() {
704 return base::Singleton<DevicePermissionsManagerFactory>::get();
707 DevicePermissionsManagerFactory::DevicePermissionsManagerFactory()
708 : BrowserContextKeyedServiceFactory(
709 "DevicePermissionsManager",
710 BrowserContextDependencyManager::GetInstance()) {
713 DevicePermissionsManagerFactory::~DevicePermissionsManagerFactory() {
716 KeyedService* DevicePermissionsManagerFactory::BuildServiceInstanceFor(
717 content::BrowserContext* context) const {
718 return new DevicePermissionsManager(context);
721 BrowserContext* DevicePermissionsManagerFactory::GetBrowserContextToUse(
722 BrowserContext* context) const {
723 // Return the original (possibly off-the-record) browser context so that a
724 // separate instance of the DevicePermissionsManager is used in incognito
725 // mode. The parent class's implemenation returns NULL.
726 return context;
729 } // namespace extensions