summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/BUILD.gn5
-rw-r--r--apps/DEPS1
-rw-r--r--apps/apps.gypi4
-rw-r--r--apps/saved_devices_service.cc316
-rw-r--r--apps/saved_devices_service.h123
-rw-r--r--apps/saved_devices_service_factory.cc39
-rw-r--r--apps/saved_devices_service_factory.h35
-rw-r--r--chrome/browser/extensions/api/device_permissions_manager_unittest.cc (renamed from apps/saved_devices_service_unittest.cc)96
-rw-r--r--chrome/chrome_tests_unit.gypi2
-rw-r--r--extensions/browser/BUILD.gn2
-rw-r--r--extensions/browser/DEPS1
-rw-r--r--extensions/browser/api/device_permissions_manager.cc384
-rw-r--r--extensions/browser/api/device_permissions_manager.h151
-rw-r--r--extensions/browser/api/usb/DEPS1
-rw-r--r--extensions/browser/api/usb_private/DEPS1
-rw-r--r--extensions/extensions.gyp2
-rw-r--r--extensions/extensions_strings.grd9
17 files changed, 596 insertions, 576 deletions
diff --git a/apps/BUILD.gn b/apps/BUILD.gn
index 4070818..d46feaa 100644
--- a/apps/BUILD.gn
+++ b/apps/BUILD.gn
@@ -26,10 +26,6 @@ static_library("apps") {
"launcher.cc",
"launcher.h",
"metrics_names.h",
- "saved_devices_service.cc",
- "saved_devices_service.h",
- "saved_devices_service_factory.cc",
- "saved_devices_service_factory.h",
"saved_files_service.cc",
"saved_files_service.h",
"saved_files_service_factory.cc",
@@ -45,7 +41,6 @@ static_library("apps") {
"//chrome/browser/extensions",
"//chrome/common/extensions/api:api",
"//components/web_modal",
- "//device/usb",
"//skia",
]
diff --git a/apps/DEPS b/apps/DEPS
index 01144ad..e2f3d69 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -9,7 +9,6 @@ include_rules = [
"+components/sessions",
"+components/user_manager",
"+components/web_modal",
- "+device/usb",
"+extensions",
"+net/base",
"+skia/ext",
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 1b464ae..cb8478d 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -45,10 +45,6 @@
'launcher.cc',
'launcher.h',
'metrics_names.h',
- 'saved_devices_service.cc',
- 'saved_devices_service.h',
- 'saved_devices_service_factory.cc',
- 'saved_devices_service_factory.h',
'saved_files_service.cc',
'saved_files_service.h',
'saved_files_service_factory.cc',
diff --git a/apps/saved_devices_service.cc b/apps/saved_devices_service.cc
deleted file mode 100644
index d7e894c..0000000
--- a/apps/saved_devices_service.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "apps/saved_devices_service.h"
-
-#include <set>
-#include <vector>
-
-#include "apps/saved_devices_service_factory.h"
-#include "base/basictypes.h"
-#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "device/usb/usb_device.h"
-#include "device/usb/usb_device_handle.h"
-#include "extensions/browser/extension_host.h"
-#include "extensions/browser/extension_prefs.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/extension_util.h"
-#include "extensions/browser/notification_types.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "extensions/common/permissions/permission_set.h"
-#include "extensions/common/permissions/permissions_data.h"
-
-namespace apps {
-
-using device::UsbDevice;
-using device::UsbDeviceHandle;
-using extensions::APIPermission;
-using extensions::Extension;
-using extensions::ExtensionHost;
-using extensions::ExtensionPrefs;
-
-namespace {
-
-// Preference keys
-
-// The device that the app has permission to access.
-const char kDevices[] = "devices";
-
-// The type of device saved.
-const char kDeviceType[] = "type";
-
-// Type identifier for USB devices.
-const char kDeviceTypeUsb[] = "usb";
-
-// The vendor ID of the device that the app had permission to access.
-const char kDeviceVendorId[] = "vendor_id";
-
-// The product ID of the device that the app had permission to access.
-const char kDeviceProductId[] = "product_id";
-
-// The serial number of the device that the app has permission to access.
-const char kDeviceSerialNumber[] = "serial_number";
-
-// Persists a SavedDeviceEntry in ExtensionPrefs.
-void AddSavedDeviceEntry(Profile* profile,
- const std::string& extension_id,
- const SavedDeviceEntry& device) {
- ExtensionPrefs* prefs = ExtensionPrefs::Get(profile);
- ExtensionPrefs::ScopedListUpdate update(prefs, extension_id, kDevices);
- base::ListValue* devices = update.Get();
- if (!devices) {
- devices = update.Create();
- }
-
- base::Value* device_entry = device.ToValue();
- DCHECK(devices->Find(*device_entry) == devices->end());
- devices->Append(device_entry);
-}
-
-// Clears all SavedDeviceEntry for the app from ExtensionPrefs.
-void ClearSavedDeviceEntries(ExtensionPrefs* prefs,
- const std::string& extension_id) {
- prefs->UpdateExtensionPref(extension_id, kDevices, NULL);
-}
-
-// Returns all SavedDeviceEntries for the app.
-std::vector<SavedDeviceEntry> GetSavedDeviceEntries(
- ExtensionPrefs* prefs,
- const std::string& extension_id) {
- std::vector<SavedDeviceEntry> result;
- const base::ListValue* devices = NULL;
- if (!prefs->ReadPrefAsList(extension_id, kDevices, &devices)) {
- return result;
- }
-
- for (base::ListValue::const_iterator it = devices->begin();
- it != devices->end();
- ++it) {
- const base::DictionaryValue* device_entry = NULL;
- if (!(*it)->GetAsDictionary(&device_entry)) {
- continue;
- }
- int vendor_id;
- if (!device_entry->GetIntegerWithoutPathExpansion(kDeviceVendorId,
- &vendor_id) ||
- vendor_id < 0 || vendor_id > UINT16_MAX) {
- continue;
- }
- int product_id;
- if (!device_entry->GetIntegerWithoutPathExpansion(kDeviceProductId,
- &product_id) ||
- product_id < 0 || product_id > UINT16_MAX) {
- continue;
- }
- base::string16 serial_number;
- if (!device_entry->GetStringWithoutPathExpansion(kDeviceSerialNumber,
- &serial_number)) {
- continue;
- }
-
- result.push_back(SavedDeviceEntry(vendor_id, product_id, serial_number));
- }
- return result;
-}
-
-} // namespace
-
-SavedDeviceEntry::SavedDeviceEntry(uint16_t vendor_id,
- uint16_t product_id,
- const base::string16& serial_number)
- : vendor_id(vendor_id),
- product_id(product_id),
- serial_number(serial_number) {
-}
-
-base::Value* SavedDeviceEntry::ToValue() const {
- base::DictionaryValue* device_entry_dict = new base::DictionaryValue();
- device_entry_dict->SetStringWithoutPathExpansion(kDeviceType, kDeviceTypeUsb);
- device_entry_dict->SetIntegerWithoutPathExpansion(kDeviceVendorId, vendor_id);
- device_entry_dict->SetIntegerWithoutPathExpansion(kDeviceProductId,
- product_id);
- device_entry_dict->SetStringWithoutPathExpansion(kDeviceSerialNumber,
- serial_number);
- return device_entry_dict;
-}
-
-bool SavedDevicesService::SavedDevices::IsRegistered(
- scoped_refptr<UsbDevice> device) const {
- if (ephemeral_devices_.find(device) != ephemeral_devices_.end()) {
- return true;
- }
-
- bool have_serial_number = false;
- base::string16 serial_number;
- for (std::vector<SavedDeviceEntry>::const_iterator it =
- persistent_devices_.begin();
- it != persistent_devices_.end();
- ++it) {
- if (it->vendor_id != device->vendor_id()) {
- continue;
- }
- if (it->product_id != device->product_id()) {
- continue;
- }
- if (!have_serial_number) {
- if (!device->GetSerialNumber(&serial_number)) {
- break;
- }
- have_serial_number = true;
- }
- if (it->serial_number != serial_number) {
- continue;
- }
- return true;
- }
- return false;
-}
-
-void SavedDevicesService::SavedDevices::RegisterDevice(
- scoped_refptr<device::UsbDevice> device,
- base::string16* serial_number) {
- if (serial_number) {
- for (std::vector<SavedDeviceEntry>::const_iterator it =
- persistent_devices_.begin();
- it != persistent_devices_.end();
- ++it) {
- if (it->vendor_id != device->vendor_id()) {
- continue;
- }
- if (it->product_id != device->product_id()) {
- continue;
- }
- if (it->serial_number == *serial_number) {
- return;
- }
- }
- SavedDeviceEntry device_entry = SavedDeviceEntry(
- device->vendor_id(), device->product_id(), *serial_number);
- persistent_devices_.push_back(device_entry);
-
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(AddSavedDeviceEntry, profile_, extension_id_, device_entry));
- } else {
- // Without a serial number a device cannot be reliably identified when it
- // is reconnected so such devices are only remembered until disconnect.
- // Register an observer here so that this set doesn't grow undefinitely.
- ephemeral_devices_.insert(device);
- device->AddObserver(this);
- }
-}
-
-SavedDevicesService::SavedDevices::SavedDevices(Profile* profile,
- const std::string& extension_id)
- : profile_(profile), extension_id_(extension_id) {
- ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
- persistent_devices_ = GetSavedDeviceEntries(prefs, extension_id_);
-}
-
-SavedDevicesService::SavedDevices::~SavedDevices() {
- // Only ephemeral devices have an observer registered.
- for (std::set<scoped_refptr<UsbDevice> >::iterator it =
- ephemeral_devices_.begin();
- it != ephemeral_devices_.end();
- ++it) {
- (*it)->RemoveObserver(this);
- }
-}
-
-void SavedDevicesService::SavedDevices::OnDisconnect(
- scoped_refptr<UsbDevice> device) {
- // Permission for an ephemeral device lasts only as long as the device is
- // plugged in.
- ephemeral_devices_.erase(device);
- device->RemoveObserver(this);
-}
-
-SavedDevicesService::SavedDevicesService(Profile* profile) : profile_(profile) {
- registrar_.Add(this,
- extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
- content::NotificationService::AllSources());
- registrar_.Add(this,
- chrome::NOTIFICATION_APP_TERMINATING,
- content::NotificationService::AllSources());
-}
-
-SavedDevicesService::~SavedDevicesService() {
- for (std::map<std::string, SavedDevices*>::iterator it =
- extension_id_to_saved_devices_.begin();
- it != extension_id_to_saved_devices_.end();
- ++it) {
- delete it->second;
- }
-}
-
-// static
-SavedDevicesService* SavedDevicesService::Get(Profile* profile) {
- return SavedDevicesServiceFactory::GetForProfile(profile);
-}
-
-SavedDevicesService::SavedDevices* SavedDevicesService::GetOrInsert(
- const std::string& extension_id) {
- SavedDevices* saved_devices = Get(extension_id);
- if (saved_devices) {
- return saved_devices;
- }
-
- saved_devices = new SavedDevices(profile_, extension_id);
- extension_id_to_saved_devices_[extension_id] = saved_devices;
- return saved_devices;
-}
-
-std::vector<SavedDeviceEntry> SavedDevicesService::GetAllDevices(
- const std::string& extension_id) const {
- ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
- return GetSavedDeviceEntries(prefs, extension_id);
-}
-
-void SavedDevicesService::Clear(const std::string& extension_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ClearSavedDeviceEntries(ExtensionPrefs::Get(profile_), extension_id);
- std::map<std::string, SavedDevices*>::iterator it =
- extension_id_to_saved_devices_.find(extension_id);
- if (it != extension_id_to_saved_devices_.end()) {
- delete it->second;
- extension_id_to_saved_devices_.erase(it);
- }
-}
-
-void SavedDevicesService::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
- Clear(content::Details<ExtensionHost>(details)->extension_id());
- break;
- }
-
- case chrome::NOTIFICATION_APP_TERMINATING: {
- // Stop listening to NOTIFICATION_EXTENSION_HOST_DESTROYED in particular
- // as all extension hosts will be destroyed as a result of shutdown.
- registrar_.RemoveAll();
- break;
- }
- }
-}
-
-SavedDevicesService::SavedDevices* SavedDevicesService::Get(
- const std::string& extension_id) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::map<std::string, SavedDevices*>::const_iterator it =
- extension_id_to_saved_devices_.find(extension_id);
- if (it != extension_id_to_saved_devices_.end()) {
- return it->second;
- }
-
- return NULL;
-}
-
-} // namespace apps
diff --git a/apps/saved_devices_service.h b/apps/saved_devices_service.h
deleted file mode 100644
index 52a1874..0000000
--- a/apps/saved_devices_service.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef APPS_SAVED_DEVICES_SERVICE_H_
-#define APPS_SAVED_DEVICES_SERVICE_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/threading/thread_checker.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "device/usb/usb_device.h"
-
-class Profile;
-
-namespace base {
-class Value;
-}
-
-namespace extensions {
-class Extension;
-}
-
-namespace apps {
-
-// Represents a device that a user has given an app permission to access. It
-// will be persisted to disk (in the Preferences file) and so should remain
-// serializable.
-struct SavedDeviceEntry {
- SavedDeviceEntry(uint16_t vendor_id,
- uint16_t product_id,
- const base::string16& serial_number);
-
- base::Value* ToValue() const;
-
- // The vendor ID of this device.
- uint16_t vendor_id;
-
- // The product ID of this device.
- uint16_t product_id;
-
- // The serial number (possibly alphanumeric) of this device.
- base::string16 serial_number;
-};
-
-// Tracks the devices that apps have retained access to both while running and
-// when suspended.
-class SavedDevicesService : public KeyedService,
- public content::NotificationObserver {
- public:
- // Tracks the devices that a particular extension has retained access to.
- // Unlike SavedDevicesService the functions of this class can be called from
- // the FILE thread.
- class SavedDevices : device::UsbDevice::Observer {
- public:
- bool IsRegistered(scoped_refptr<device::UsbDevice> device) const;
- void RegisterDevice(scoped_refptr<device::UsbDevice> device,
- /* optional */ base::string16* serial_number);
-
- private:
- friend class SavedDevicesService;
-
- SavedDevices(Profile* profile, const std::string& extension_id);
- virtual ~SavedDevices();
-
- // device::UsbDevice::Observer
- virtual void OnDisconnect(scoped_refptr<device::UsbDevice> device) OVERRIDE;
-
- Profile* profile_;
- const std::string extension_id_;
-
- // Devices with serial numbers are written to the prefs file.
- std::vector<SavedDeviceEntry> persistent_devices_;
- // Other devices are ephemeral devices and cleared when the extension host
- // is destroyed.
- std::set<scoped_refptr<device::UsbDevice> > ephemeral_devices_;
-
- DISALLOW_COPY_AND_ASSIGN(SavedDevices);
- };
-
- explicit SavedDevicesService(Profile* profile);
- virtual ~SavedDevicesService();
-
- static SavedDevicesService* Get(Profile* profile);
-
- // Returns the SavedDevices for |extension_id|, creating it if necessary.
- SavedDevices* GetOrInsert(const std::string& extension_id);
-
- std::vector<SavedDeviceEntry> GetAllDevices(
- const std::string& extension_id) const;
-
- // Clears the SavedDevices for |extension_id|.
- void Clear(const std::string& extension_id);
-
- private:
- // content::NotificationObserver.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
- // Returns the SavedDevices for |extension_id| or NULL if one does not exist.
- SavedDevices* Get(const std::string& extension_id) const;
-
- std::map<std::string, SavedDevices*> extension_id_to_saved_devices_;
- Profile* profile_;
- content::NotificationRegistrar registrar_;
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(SavedDevicesService);
-};
-
-} // namespace apps
-
-#endif // APPS_SAVED_DEVICES_SERVICE_H_
diff --git a/apps/saved_devices_service_factory.cc b/apps/saved_devices_service_factory.cc
deleted file mode 100644
index 1153eac..0000000
--- a/apps/saved_devices_service_factory.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "apps/saved_devices_service_factory.h"
-
-#include "apps/saved_devices_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-namespace apps {
-
-// static
-SavedDevicesService* SavedDevicesServiceFactory::GetForProfile(
- Profile* profile) {
- return static_cast<SavedDevicesService*>(
- GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-SavedDevicesServiceFactory* SavedDevicesServiceFactory::GetInstance() {
- return Singleton<SavedDevicesServiceFactory>::get();
-}
-
-SavedDevicesServiceFactory::SavedDevicesServiceFactory()
- : BrowserContextKeyedServiceFactory(
- "SavedDevicesService",
- BrowserContextDependencyManager::GetInstance()) {
-}
-
-SavedDevicesServiceFactory::~SavedDevicesServiceFactory() {
-}
-
-KeyedService* SavedDevicesServiceFactory::BuildServiceInstanceFor(
- content::BrowserContext* profile) const {
- return new SavedDevicesService(static_cast<Profile*>(profile));
-}
-
-} // namespace apps
diff --git a/apps/saved_devices_service_factory.h b/apps/saved_devices_service_factory.h
deleted file mode 100644
index d1b39a1..0000000
--- a/apps/saved_devices_service_factory.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef APPS_SAVED_DEVICES_SERVICE_FACTORY_H_
-#define APPS_SAVED_DEVICES_SERVICE_FACTORY_H_
-
-#include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class Profile;
-
-namespace apps {
-
-class SavedDevicesService;
-
-// BrowserContextKeyedServiceFactory for SavedDevicesService.
-class SavedDevicesServiceFactory : public BrowserContextKeyedServiceFactory {
- public:
- static SavedDevicesService* GetForProfile(Profile* profile);
-
- static SavedDevicesServiceFactory* GetInstance();
-
- private:
- SavedDevicesServiceFactory();
- virtual ~SavedDevicesServiceFactory();
- friend struct DefaultSingletonTraits<SavedDevicesServiceFactory>;
-
- virtual KeyedService* BuildServiceInstanceFor(
- content::BrowserContext* profile) const OVERRIDE;
-};
-
-} // namespace apps
-
-#endif // APPS_SAVED_DEVICES_SERVICE_FACTORY_H_
diff --git a/apps/saved_devices_service_unittest.cc b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
index b48e8a6..3990933 100644
--- a/apps/saved_devices_service_unittest.cc
+++ b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "apps/saved_devices_service.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/values_test_util.h"
@@ -10,19 +9,18 @@
#include "chrome/test/base/testing_profile.h"
#include "device/usb/usb_device.h"
#include "device/usb/usb_device_handle.h"
+#include "extensions/browser/api/device_permissions_manager.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace apps {
+namespace extensions {
namespace {
using device::UsbDevice;
using device::UsbDeviceHandle;
-using device::UsbEndpointDirection;
-using device::UsbTransferCallback;
using testing::Return;
class MockUsbDevice : public UsbDevice {
@@ -39,12 +37,12 @@ class MockUsbDevice : public UsbDevice {
MOCK_METHOD1(GetManufacturer, bool(base::string16*));
MOCK_METHOD1(GetProduct, bool(base::string16*));
- bool GetSerialNumber(base::string16* serial) OVERRIDE {
+ virtual bool GetSerialNumber(base::string16* serial_number) OVERRIDE {
if (serial_number_.empty()) {
return false;
}
- *serial = base::UTF8ToUTF16(serial_number_);
+ *serial_number = base::UTF8ToUTF16(serial_number_);
return true;
}
@@ -55,9 +53,10 @@ class MockUsbDevice : public UsbDevice {
const std::string serial_number_;
};
-}
-class SavedDevicesServiceTest : public testing::Test {
+} // namespace
+
+class DevicePermissionsManagerTest : public testing::Test {
protected:
virtual void SetUp() OVERRIDE {
testing::Test::SetUp();
@@ -73,7 +72,6 @@ class SavedDevicesServiceTest : public testing::Test {
" \"usb\""
" ]"
"}"));
- service_ = SavedDevicesService::Get(env_.profile());
device0 = new MockUsbDevice("ABCDE", 0);
device1 = new MockUsbDevice("", 1);
device2 = new MockUsbDevice("12345", 2);
@@ -82,53 +80,49 @@ class SavedDevicesServiceTest : public testing::Test {
extensions::TestExtensionEnvironment env_;
const extensions::Extension* extension_;
- SavedDevicesService* service_;
scoped_refptr<MockUsbDevice> device0;
scoped_refptr<MockUsbDevice> device1;
scoped_refptr<MockUsbDevice> device2;
scoped_refptr<MockUsbDevice> device3;
};
-TEST_F(SavedDevicesServiceTest, RegisterDevices) {
- SavedDevicesService::SavedDevices* saved_devices =
- service_->GetOrInsert(extension_->id());
-
- base::string16 serial_number(base::ASCIIToUTF16("ABCDE"));
- saved_devices->RegisterDevice(device0, &serial_number);
- saved_devices->RegisterDevice(device1, NULL);
-
- // This is necessary as writing out registered devices happens in a task on
- // the UI thread.
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
-
- ASSERT_TRUE(saved_devices->IsRegistered(device0));
- ASSERT_TRUE(saved_devices->IsRegistered(device1));
- ASSERT_FALSE(saved_devices->IsRegistered(device2));
- ASSERT_FALSE(saved_devices->IsRegistered(device3));
-
- std::vector<SavedDeviceEntry> device_entries =
- service_->GetAllDevices(extension_->id());
- ASSERT_EQ(1U, device_entries.size());
- ASSERT_EQ(base::ASCIIToUTF16("ABCDE"), device_entries[0].serial_number);
+TEST_F(DevicePermissionsManagerTest, RegisterDevices) {
+ DevicePermissionsManager* manager =
+ DevicePermissionsManager::Get(env_.profile());
+ manager->AllowUsbDevice(
+ extension_->id(), device0, base::ASCIIToUTF16("ABCDE"));
+ manager->AllowUsbDevice(extension_->id(), device1, base::string16());
+
+ scoped_ptr<DevicePermissions> device_permissions =
+ manager->GetForExtension(extension_->id());
+ ASSERT_TRUE(device_permissions->CheckUsbDevice(device0));
+ ASSERT_TRUE(device_permissions->CheckUsbDevice(device1));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device2));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device3));
+
+ std::vector<base::string16> device_messages =
+ manager->GetPermissionMessageStrings(extension_->id());
+ ASSERT_EQ(1U, device_messages.size());
+ ASSERT_NE(device_messages[0].find(base::ASCIIToUTF16("ABCDE")),
+ base::string16::npos);
device1->NotifyDisconnect();
- ASSERT_TRUE(saved_devices->IsRegistered(device0));
- ASSERT_FALSE(saved_devices->IsRegistered(device1));
- ASSERT_FALSE(saved_devices->IsRegistered(device2));
- ASSERT_FALSE(saved_devices->IsRegistered(device3));
+ device_permissions = manager->GetForExtension(extension_->id());
+ ASSERT_TRUE(device_permissions->CheckUsbDevice(device0));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device1));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device2));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device3));
- service_->Clear(extension_->id());
+ manager->Clear(extension_->id());
- // App is normally restarted, clearing its reference to the SavedDevices.
- saved_devices = service_->GetOrInsert(extension_->id());
- ASSERT_FALSE(saved_devices->IsRegistered(device0));
- device_entries = service_->GetAllDevices(extension_->id());
- ASSERT_EQ(0U, device_entries.size());
+ device_permissions = manager->GetForExtension(extension_->id());
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device0));
+ device_messages = manager->GetPermissionMessageStrings(extension_->id());
+ ASSERT_EQ(0U, device_messages.size());
}
-TEST_F(SavedDevicesServiceTest, LoadPrefs) {
+TEST_F(DevicePermissionsManagerTest, LoadPrefs) {
scoped_ptr<base::Value> prefs_value = base::test::ParseJson(
"["
" {"
@@ -141,12 +135,14 @@ TEST_F(SavedDevicesServiceTest, LoadPrefs) {
env_.GetExtensionPrefs()->UpdateExtensionPref(
extension_->id(), "devices", prefs_value.release());
- SavedDevicesService::SavedDevices* saved_devices =
- service_->GetOrInsert(extension_->id());
- ASSERT_TRUE(saved_devices->IsRegistered(device0));
- ASSERT_FALSE(saved_devices->IsRegistered(device1));
- ASSERT_FALSE(saved_devices->IsRegistered(device2));
- ASSERT_FALSE(saved_devices->IsRegistered(device3));
+ DevicePermissionsManager* manager =
+ DevicePermissionsManager::Get(env_.profile());
+ scoped_ptr<DevicePermissions> device_permissions =
+ manager->GetForExtension(extension_->id());
+ ASSERT_TRUE(device_permissions->CheckUsbDevice(device0));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device1));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device2));
+ ASSERT_FALSE(device_permissions->CheckUsbDevice(device3));
}
-} // namespace apps
+} // namespace extensions
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index d982db2..ffff874 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -4,7 +4,6 @@
{
'variables': {
'chrome_unit_tests_sources': [
- '../apps/saved_devices_service_unittest.cc',
'../apps/saved_files_service_unittest.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.h',
@@ -317,6 +316,7 @@
'browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc',
'browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc',
'browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc',
+ 'browser/extensions/api/device_permissions_manager_unittest.cc',
'browser/extensions/api/dial/dial_device_data_unittest.cc',
'browser/extensions/api/dial/dial_registry_unittest.cc',
'browser/extensions/api/dial/dial_service_unittest.cc',
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 0b7e062..55dbed7 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -122,6 +122,8 @@ source_set("browser") {
"api/declarative_webrequest/webrequest_constants.h",
"api/declarative_webrequest/webrequest_rules_registry.cc",
"api/declarative_webrequest/webrequest_rules_registry.h",
+ "api/device_permissions_manager.cc",
+ "api/device_permissions_manager.h",
"api/dns/dns_api.cc",
"api/dns/dns_api.h",
"api/dns/host_resolver_wrapper.cc",
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index e540b13..c1d5be8 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"+components/web_modal",
"+content/public/browser",
"+device/bluetooth",
+ "+device/usb",
"+grit/extensions_strings.h",
"+net",
"+skia/ext/image_operations.h",
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc
new file mode 100644
index 0000000..a005adb
--- /dev/null
+++ b/extensions/browser/api/device_permissions_manager.cc
@@ -0,0 +1,384 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/device_permissions_manager.h"
+
+#include "base/memory/singleton.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/notification_service.h"
+#include "device/usb/usb_ids.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/notification_types.h"
+#include "extensions/strings/grit/extensions_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+using content::BrowserContext;
+using device::UsbDevice;
+using extensions::APIPermission;
+using extensions::Extension;
+using extensions::ExtensionHost;
+using extensions::ExtensionPrefs;
+
+namespace {
+
+// Preference keys
+
+// The device that the app has permission to access.
+const char kDevices[] = "devices";
+
+// The type of device saved.
+const char kDeviceType[] = "type";
+
+// Type identifier for USB devices.
+const char kDeviceTypeUsb[] = "usb";
+
+// The vendor ID of the device that the app had permission to access.
+const char kDeviceVendorId[] = "vendor_id";
+
+// The product ID of the device that the app had permission to access.
+const char kDeviceProductId[] = "product_id";
+
+// The serial number of the device that the app has permission to access.
+const char kDeviceSerialNumber[] = "serial_number";
+
+// Persists a DevicePermissionEntry in ExtensionPrefs.
+void SaveDevicePermissionEntry(BrowserContext* context,
+ const std::string& extension_id,
+ const DevicePermissionEntry& device) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
+ ExtensionPrefs::ScopedListUpdate update(prefs, extension_id, kDevices);
+ base::ListValue* devices = update.Get();
+ if (!devices) {
+ devices = update.Create();
+ }
+
+ base::Value* device_entry = device.ToValue();
+ DCHECK(devices->Find(*device_entry) == devices->end());
+ devices->Append(device_entry);
+}
+
+// Clears all DevicePermissionEntries for the app from ExtensionPrefs.
+void ClearDevicePermissionEntries(ExtensionPrefs* prefs,
+ const std::string& extension_id) {
+ prefs->UpdateExtensionPref(extension_id, kDevices, NULL);
+}
+
+// Returns all DevicePermissionEntries for the app.
+std::vector<DevicePermissionEntry> GetDevicePermissionEntries(
+ ExtensionPrefs* prefs,
+ const std::string& extension_id) {
+ std::vector<DevicePermissionEntry> result;
+ const base::ListValue* devices = NULL;
+ if (!prefs->ReadPrefAsList(extension_id, kDevices, &devices)) {
+ return result;
+ }
+
+ for (base::ListValue::const_iterator it = devices->begin();
+ it != devices->end();
+ ++it) {
+ const base::DictionaryValue* device_entry = NULL;
+ if (!(*it)->GetAsDictionary(&device_entry)) {
+ continue;
+ }
+ int vendor_id;
+ if (!device_entry->GetIntegerWithoutPathExpansion(kDeviceVendorId,
+ &vendor_id) ||
+ vendor_id < 0 || vendor_id > UINT16_MAX) {
+ continue;
+ }
+ int product_id;
+ if (!device_entry->GetIntegerWithoutPathExpansion(kDeviceProductId,
+ &product_id) ||
+ product_id < 0 || product_id > UINT16_MAX) {
+ continue;
+ }
+ base::string16 serial_number;
+ if (!device_entry->GetStringWithoutPathExpansion(kDeviceSerialNumber,
+ &serial_number)) {
+ continue;
+ }
+
+ result.push_back(
+ DevicePermissionEntry(vendor_id, product_id, serial_number));
+ }
+ return result;
+}
+}
+
+DevicePermissionEntry::DevicePermissionEntry(
+ uint16_t vendor_id,
+ uint16_t product_id,
+ const base::string16& serial_number)
+ : vendor_id(vendor_id),
+ product_id(product_id),
+ serial_number(serial_number) {
+}
+
+base::Value* DevicePermissionEntry::ToValue() const {
+ base::DictionaryValue* device_entry_dict = new base::DictionaryValue();
+ device_entry_dict->SetStringWithoutPathExpansion(kDeviceType, kDeviceTypeUsb);
+ device_entry_dict->SetIntegerWithoutPathExpansion(kDeviceVendorId, vendor_id);
+ device_entry_dict->SetIntegerWithoutPathExpansion(kDeviceProductId,
+ product_id);
+ device_entry_dict->SetStringWithoutPathExpansion(kDeviceSerialNumber,
+ serial_number);
+ return device_entry_dict;
+}
+
+DevicePermissions::~DevicePermissions() {
+}
+
+bool DevicePermissions::CheckUsbDevice(
+ scoped_refptr<device::UsbDevice> device) const {
+ if (ephemeral_devices_.find(device) != ephemeral_devices_.end()) {
+ return true;
+ }
+
+ bool have_serial_number = false;
+ base::string16 serial_number;
+ for (const auto& entry : permission_entries_) {
+ if (entry.vendor_id != device->vendor_id()) {
+ continue;
+ }
+ if (entry.product_id != device->product_id()) {
+ continue;
+ }
+ if (!have_serial_number) {
+ if (!device->GetSerialNumber(&serial_number)) {
+ break;
+ }
+ have_serial_number = true;
+ }
+ if (entry.serial_number != serial_number) {
+ continue;
+ }
+ return true;
+ }
+ return false;
+}
+
+DevicePermissions::DevicePermissions(BrowserContext* context,
+ const std::string& extension_id) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
+ permission_entries_ = GetDevicePermissionEntries(prefs, extension_id);
+}
+
+DevicePermissions::DevicePermissions(
+ const std::vector<DevicePermissionEntry>& permission_entries,
+ const std::set<scoped_refptr<device::UsbDevice>>& ephemeral_devices)
+ : permission_entries_(permission_entries),
+ ephemeral_devices_(ephemeral_devices) {
+}
+
+std::vector<DevicePermissionEntry>& DevicePermissions::permission_entries() {
+ return permission_entries_;
+}
+
+std::set<scoped_refptr<device::UsbDevice>>&
+DevicePermissions::ephemeral_devices() {
+ return ephemeral_devices_;
+}
+
+// static
+DevicePermissionsManager* DevicePermissionsManager::Get(
+ BrowserContext* context) {
+ return DevicePermissionsManagerFactory::GetForBrowserContext(context);
+}
+
+scoped_ptr<DevicePermissions> DevicePermissionsManager::GetForExtension(
+ const std::string& extension_id) {
+ DCHECK(CalledOnValidThread());
+
+ DevicePermissions* device_permissions = GetOrInsert(extension_id);
+ return make_scoped_ptr(
+ new DevicePermissions(device_permissions->permission_entries(),
+ device_permissions->ephemeral_devices()));
+}
+
+std::vector<base::string16>
+DevicePermissionsManager::GetPermissionMessageStrings(
+ const std::string& extension_id) {
+ DCHECK(CalledOnValidThread());
+
+ std::vector<base::string16> messages;
+ DevicePermissions* device_permissions = Get(extension_id);
+ if (!device_permissions) {
+ return messages;
+ }
+
+ for (const auto& entry : device_permissions->permission_entries()) {
+ const char* vendorName = device::UsbIds::GetVendorName(entry.vendor_id);
+ const char* productName =
+ device::UsbIds::GetProductName(entry.vendor_id, entry.product_id);
+ if (vendorName) {
+ if (productName) {
+ messages.push_back(l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_SERIAL,
+ base::UTF8ToUTF16(vendorName),
+ base::UTF8ToUTF16(productName),
+ entry.serial_number));
+ } else {
+ messages.push_back(l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_PID_SERIAL,
+ base::UTF8ToUTF16(vendorName),
+ base::ASCIIToUTF16(base::StringPrintf("0x%04X", entry.product_id)),
+ entry.serial_number));
+ }
+ } else {
+ messages.push_back(l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_VID_PID_SERIAL,
+ base::ASCIIToUTF16(base::StringPrintf("0x%04X", entry.vendor_id)),
+ base::ASCIIToUTF16(base::StringPrintf("0x%04X", entry.product_id)),
+ entry.serial_number));
+ }
+ }
+ return messages;
+}
+
+void DevicePermissionsManager::AllowUsbDevice(
+ const std::string& extension_id,
+ scoped_refptr<device::UsbDevice> device,
+ const base::string16& serial_number) {
+ DCHECK(CalledOnValidThread());
+ DevicePermissions* device_permissions = GetOrInsert(extension_id);
+
+ if (!serial_number.empty()) {
+ for (const auto& entry : device_permissions->permission_entries()) {
+ if (entry.vendor_id != device->vendor_id()) {
+ continue;
+ }
+ if (entry.product_id != device->product_id()) {
+ continue;
+ }
+ if (entry.serial_number == serial_number) {
+ return;
+ }
+ }
+
+ DevicePermissionEntry device_entry = DevicePermissionEntry(
+ device->vendor_id(), device->product_id(), serial_number);
+ device_permissions->permission_entries().push_back(device_entry);
+ SaveDevicePermissionEntry(context_, extension_id, device_entry);
+ } else {
+ // Without a serial number a device cannot be reliably identified when it
+ // is reconnected so such devices are only remembered until disconnect.
+ // Register an observer here so that this set doesn't grow undefinitely.
+ device_permissions->ephemeral_devices().insert(device);
+ device->AddObserver(this);
+ }
+}
+
+void DevicePermissionsManager::Clear(const std::string& extension_id) {
+ DCHECK(CalledOnValidThread());
+
+ ClearDevicePermissionEntries(ExtensionPrefs::Get(context_), extension_id);
+ std::map<std::string, DevicePermissions*>::iterator it =
+ extension_id_to_device_permissions_.find(extension_id);
+ if (it != extension_id_to_device_permissions_.end()) {
+ delete it->second;
+ extension_id_to_device_permissions_.erase(it);
+ }
+}
+
+DevicePermissionsManager::DevicePermissionsManager(
+ content::BrowserContext* context)
+ : context_(context) {
+ registrar_.Add(this,
+ extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ content::NotificationService::AllSources());
+}
+
+DevicePermissionsManager::~DevicePermissionsManager() {
+ for (const auto& map_entry : extension_id_to_device_permissions_) {
+ delete map_entry.second;
+ }
+}
+
+DevicePermissions* DevicePermissionsManager::Get(
+ const std::string& extension_id) const {
+ std::map<std::string, DevicePermissions*>::const_iterator it =
+ extension_id_to_device_permissions_.find(extension_id);
+ if (it != extension_id_to_device_permissions_.end()) {
+ return it->second;
+ }
+
+ return NULL;
+}
+
+DevicePermissions* DevicePermissionsManager::GetOrInsert(
+ const std::string& extension_id) {
+ DevicePermissions* device_permissions = Get(extension_id);
+ if (!device_permissions) {
+ device_permissions = new DevicePermissions(context_, extension_id);
+ extension_id_to_device_permissions_[extension_id] = device_permissions;
+ }
+
+ return device_permissions;
+}
+
+void DevicePermissionsManager::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, type);
+
+ ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
+ DevicePermissions* device_permissions = Get(host->extension_id());
+ if (device_permissions) {
+ // When the extension is unloaded all ephemeral device permissions are
+ // cleared.
+ for (std::set<scoped_refptr<UsbDevice>>::iterator it =
+ device_permissions->ephemeral_devices().begin();
+ it != device_permissions->ephemeral_devices().end();
+ ++it) {
+ (*it)->RemoveObserver(this);
+ }
+ device_permissions->ephemeral_devices().clear();
+ }
+}
+
+void DevicePermissionsManager::OnDisconnect(scoped_refptr<UsbDevice> device) {
+ for (const auto& map_entry : extension_id_to_device_permissions_) {
+ // An ephemeral device cannot be identified if it is reconnected and so
+ // permission to access it is cleared on disconnect.
+ map_entry.second->ephemeral_devices().erase(device);
+ device->RemoveObserver(this);
+ }
+}
+
+// static
+DevicePermissionsManager* DevicePermissionsManagerFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<DevicePermissionsManager*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+DevicePermissionsManagerFactory*
+DevicePermissionsManagerFactory::GetInstance() {
+ return Singleton<DevicePermissionsManagerFactory>::get();
+}
+
+DevicePermissionsManagerFactory::DevicePermissionsManagerFactory()
+ : BrowserContextKeyedServiceFactory(
+ "DevicePermissionsManager",
+ BrowserContextDependencyManager::GetInstance()) {
+}
+
+DevicePermissionsManagerFactory::~DevicePermissionsManagerFactory() {
+}
+
+KeyedService* DevicePermissionsManagerFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new DevicePermissionsManager(context);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/api/device_permissions_manager.h b/extensions/browser/api/device_permissions_manager.h
new file mode 100644
index 0000000..9b79233
--- /dev/null
+++ b/extensions/browser/api/device_permissions_manager.h
@@ -0,0 +1,151 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_
+#define EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "base/threading/thread_checker.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "device/usb/usb_device.h"
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+namespace base {
+class Value;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace device {
+class UsbDevice;
+}
+
+namespace extensions {
+
+// Stores information about a device saved with access granted.
+struct DevicePermissionEntry {
+ DevicePermissionEntry(uint16_t vendor_id,
+ uint16_t product_id,
+ const base::string16& serial_number);
+
+ base::Value* ToValue() const;
+
+ // The vendor ID of this device.
+ uint16_t vendor_id;
+
+ // The product ID of this device.
+ uint16_t product_id;
+
+ // The serial number (possibly alphanumeric) of this device.
+ base::string16 serial_number;
+};
+
+// Stores a copy of device permissions associated with a particular extension.
+class DevicePermissions {
+ public:
+ virtual ~DevicePermissions();
+
+ bool CheckUsbDevice(scoped_refptr<device::UsbDevice> device) const;
+
+ private:
+ friend class DevicePermissionsManager;
+
+ DevicePermissions(content::BrowserContext* context,
+ const std::string& extension_id);
+ DevicePermissions(
+ const std::vector<DevicePermissionEntry>& permission_entries,
+ const std::set<scoped_refptr<device::UsbDevice>>& ephemeral_devices);
+
+ std::vector<DevicePermissionEntry>& permission_entries();
+ std::set<scoped_refptr<device::UsbDevice>>& ephemeral_devices();
+
+ std::vector<DevicePermissionEntry> permission_entries_;
+ std::set<scoped_refptr<device::UsbDevice>> ephemeral_devices_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevicePermissions);
+};
+
+// Manages saved device permissions for all extensions.
+class DevicePermissionsManager : public KeyedService,
+ public base::NonThreadSafe,
+ public content::NotificationObserver,
+ public device::UsbDevice::Observer {
+ public:
+ static DevicePermissionsManager* Get(content::BrowserContext* context);
+
+ // Returns a copy of the DevicePermissions object for a given extension that
+ // can be used by any thread.
+ scoped_ptr<DevicePermissions> GetForExtension(
+ const std::string& extension_id);
+
+ std::vector<base::string16> GetPermissionMessageStrings(
+ const std::string& extension_id);
+
+ void AllowUsbDevice(const std::string& extension_id,
+ scoped_refptr<device::UsbDevice> device,
+ const base::string16& serial_number);
+
+ void Clear(const std::string& extension_id);
+
+ private:
+ friend class DevicePermissionsManagerFactory;
+
+ DevicePermissionsManager(content::BrowserContext* context);
+ virtual ~DevicePermissionsManager();
+
+ DevicePermissions* Get(const std::string& extension_id) const;
+ DevicePermissions* GetOrInsert(const std::string& extension_id);
+
+ // content::NotificationObserver.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // device::UsbDevice::Observer
+ virtual void OnDisconnect(scoped_refptr<device::UsbDevice> device) OVERRIDE;
+
+ content::BrowserContext* context_;
+ std::map<std::string, DevicePermissions*> extension_id_to_device_permissions_;
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevicePermissionsManager);
+};
+
+class DevicePermissionsManagerFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ static DevicePermissionsManager* GetForBrowserContext(
+ content::BrowserContext* context);
+ static DevicePermissionsManagerFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<DevicePermissionsManagerFactory>;
+
+ DevicePermissionsManagerFactory();
+ virtual ~DevicePermissionsManagerFactory();
+
+ // BrowserContextKeyedServiceFactory
+ virtual KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(DevicePermissionsManagerFactory);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_
diff --git a/extensions/browser/api/usb/DEPS b/extensions/browser/api/usb/DEPS
index dce2c70..76a2fb6 100644
--- a/extensions/browser/api/usb/DEPS
+++ b/extensions/browser/api/usb/DEPS
@@ -1,4 +1,3 @@
include_rules = [
"+device/core",
- "+device/usb",
]
diff --git a/extensions/browser/api/usb_private/DEPS b/extensions/browser/api/usb_private/DEPS
index dce2c70..76a2fb6 100644
--- a/extensions/browser/api/usb_private/DEPS
+++ b/extensions/browser/api/usb_private/DEPS
@@ -1,4 +1,3 @@
include_rules = [
"+device/core",
- "+device/usb",
]
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 94cc3c4..e2ef5d0 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -394,6 +394,8 @@
'browser/api/declarative_webrequest/webrequest_constants.h',
'browser/api/declarative_webrequest/webrequest_rules_registry.cc',
'browser/api/declarative_webrequest/webrequest_rules_registry.h',
+ 'browser/api/device_permissions_manager.cc',
+ 'browser/api/device_permissions_manager.h',
'browser/api/dns/dns_api.cc',
'browser/api/dns/dns_api.h',
'browser/api/dns/host_resolver_wrapper.cc',
diff --git a/extensions/extensions_strings.grd b/extensions/extensions_strings.grd
index 7eb2f32..1553014 100644
--- a/extensions/extensions_strings.grd
+++ b/extensions/extensions_strings.grd
@@ -323,6 +323,15 @@
<message name="IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX" desc="The prefix for a guest page loaded in a webview tag in the Task Manager">
Webview: <ph name="WEBVIEW_TAG_NAME">$1<ex>Google</ex></ph>
</message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_SERIAL" desc="Permission string for accessing a USB device with a known vendor name, product name and serial number.">
+ <ph name="PRODUCT_NAME">$2<ex>Nexus 5</ex></ph> from <ph name="VENDOR_NAME">$1<ex>Google Inc.</ex></ph> (serial number <ph name="SERIAL_NUMBER">$3<ex>ABCDEF123456</ex></ph>)
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_PID_SERIAL" desc="Permission string for accessing a USB device with a known vendor name and serial number and a hexidecimal product ID.">
+ Product <ph name="PRODUCT_ID">$2<ex>0x1234</ex></ph> from <ph name="VENDOR_NAME">$1<ex>Google Inc.</ex></ph> (serial number <ph name="SERIAL_NUMBER">$3<ex>ABCDEF123456</ex></ph>)
+ </message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_VID_PID_SERIAL" desc="Permission string for accessing a USB device with a known serial number and a hexidecimal vendor and product IDs.">
+ Product <ph name="PRODUCT_ID">$2<ex>0x5678</ex></ph> from Vendor <ph name="VENDOR_ID">$1<ex>0x1234</ex></ph> (serial number <ph name="SERIAL_NUMBER">$3<ex>ABCDEF123456</ex></ph>)
+ </message>
<!-- Global error messages for extensions. Please keep alphabetized. -->
<message name="IDS_EXTENSION_WARNINGS_NETWORK_DELAY" desc="Warning message indicating that an extension caused excessive network delays for web requests">