diff options
25 files changed, 402 insertions, 32 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index dca7efd..61859fd 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -5088,9 +5088,18 @@ Public Exponent (<ph name="PUBLIC_EXPONENT_NUM_BITS">$3<ex>24</ex></ph> bits): <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH" desc="Permission string for access to the Bluetooth API."> Access Bluetooth on your system </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICE" desc="Permission string for access to a specific the Bluetooth device."> + <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICE" desc="Permission string for access to a specific Bluetooth device."> Access the Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Galaxy Nexus</ex></ph>". </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_UNKNOWN_USB_VENDOR" desc="Description used within IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE when a vendor cannot be established for a USB device."> + Unknown Company + </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_UNKNOWN_USB_PRODUCT" desc="Description used within IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE when a product cannot be established for a USB device."> + Unknown Device + </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE" desc="Permission string for access to a specific USB device."> + Access the USB device "<ph name="PRODUCT_NAME">$1<ex>SoundKnob</ex></ph> (<ph name="VENDOR_NAME">$2<ex>Griffin Technology</ex></ph>)". + </message> <message name="IDS_EXTENSION_PROMPT_WARNING_AUDIO_CAPTURE" desc="Permission string for access to audio capture devices."> Use your microphone </message> diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc index 6168852..2400d5c 100644 --- a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc +++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc @@ -4,12 +4,14 @@ #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" +#include "base/json/json_reader.h" #include "base/values.h" #include "chrome/common/extensions/api/permissions.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/permissions/bluetooth_device_permission.h" #include "chrome/common/extensions/permissions/permission_set.h" #include "chrome/common/extensions/permissions/permissions_info.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" #include "extensions/common/error_utils.h" #include "extensions/common/url_pattern_set.h" @@ -25,12 +27,14 @@ namespace permissions_api_helpers { namespace { +const char kInvalidParameter[] = + "Invalid argument for permission '*'."; const char kInvalidOrigin[] = "Invalid value for origin pattern *: *"; const char kUnknownPermissionError[] = "'*' is not a recognized permission."; -const char kNonBluetoothPermissionWithArgument[] = - "Only the bluetoothDevice permission supports arguments."; +const char kUnsupportedPermissionId[] = + "Only the bluetoothDevice and usbDevice permissions support arguments."; } // namespace @@ -68,20 +72,36 @@ scoped_refptr<PermissionSet> UnpackPermissionSet( std::string permission_name = it->substr(0, delimiter); std::string permission_arg = it->substr(delimiter + 1); - // Restrict this to the bluetoothDevice permission for now, to - // discourage the use of this style of permission spreading until it is - // better supported. - const APIPermissionInfo* permission_info = info->GetByID( - APIPermission::kBluetoothDevice); - if (permission_name != permission_info->name()) { - *error = kNonBluetoothPermissionWithArgument; + scoped_ptr<base::Value> permission_json( + base::JSONReader::Read(permission_arg)); + if (!permission_json.get()) { + *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); return NULL; } - BluetoothDevicePermission *permission = - new BluetoothDevicePermission(permission_info); - permission->AddDevicesFromString(permission_arg); + APIPermission* permission = NULL; + + // Explicitly check the permissions that accept arguments until the bug + // referenced above is fixed. + const APIPermissionInfo* bluetooth_device_permission_info = + info->GetByID(APIPermission::kBluetoothDevice); + const APIPermissionInfo* usb_device_permission_info = + info->GetByID(APIPermission::kUsbDevice); + if (permission_name == bluetooth_device_permission_info->name()) { + permission = new BluetoothDevicePermission( + bluetooth_device_permission_info); + } else if (permission_name == usb_device_permission_info->name()) { + permission = new UsbDevicePermission(usb_device_permission_info); + } else { + *error = kUnsupportedPermissionId; + return NULL; + } + CHECK(permission); + if (!permission->FromValue(permission_json.get())) { + *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); + return NULL; + } apis.insert(permission); } else { const APIPermissionInfo* permission_info = info->GetByName(*it); diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc index 9fa26cf..1b2d7b6 100644 --- a/chrome/browser/extensions/api/usb/usb_api.cc +++ b/chrome/browser/extensions/api/usb/usb_api.cc @@ -14,6 +14,7 @@ #include "chrome/browser/usb/usb_service.h" #include "chrome/browser/usb/usb_service_factory.h" #include "chrome/common/extensions/api/usb.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" namespace BulkTransfer = extensions::api::usb::BulkTransfer; namespace ClaimInterface = extensions::api::usb::ClaimInterface; @@ -68,6 +69,8 @@ static const char* kErrorConvertRecipient = "Invalid transfer recipient."; static const char* kErrorConvertRequestType = "Invalid request type."; static const char* kErrorMalformedParameters = "Error parsing parameters."; static const char* kErrorNoDevice = "No such device."; +static const char* kErrorPermissionDenied = + "Permission to access device was denied"; static UsbDevice* device_for_test_ = NULL; @@ -298,6 +301,15 @@ void UsbFindDevicesFunction::AsyncWorkStart() { return; } + UsbDevicePermission::CheckParam param( + parameters_->vendor_id, parameters_->product_id); + if (!GetExtension()->CheckAPIPermissionWithParam( + APIPermission::kUsbDevice, ¶m)) { + LOG(WARNING) << "Insufficient permissions to access device."; + CompleteWithError(kErrorPermissionDenied); + return; + } + UsbService* const service = UsbServiceFactory::GetInstance()->GetForProfile( profile()); if (!service) { diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 315f6ca..b74ca0d 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -205,6 +205,10 @@ 'common/extensions/permissions/socket_permission.h', 'common/extensions/permissions/socket_permission_data.cc', 'common/extensions/permissions/socket_permission_data.h', + 'common/extensions/permissions/usb_device_permission.cc', + 'common/extensions/permissions/usb_device_permission.h', + 'common/extensions/permissions/usb_device_permission_data.cc', + 'common/extensions/permissions/usb_device_permission_data.h', 'common/extensions/request_media_access_permission_helper.cc', 'common/extensions/request_media_access_permission_helper.h', 'common/extensions/unpacker.cc', diff --git a/chrome/common/DEPS b/chrome/common/DEPS index f709bc3..c85a982 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+chrome/plugin", # For checking whether we're a plugin process. "+device/bluetooth", # For BluetoothDevicePermission + "+device/usb", # For UsbDevicePermission "+extensions/common", "+grit", # For generated headers "+libxml", diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index dea3b0c..7651c34 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json @@ -344,6 +344,10 @@ "channel": "dev", "extension_types": ["platform_app"] }, + "usbDevice": { + "channel": "dev", + "extension_types": ["platform_app"] + }, "videoCapture": { "channel": "stable", "extension_types": ["platform_app"] diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 97a125c..872ef54 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -1490,6 +1490,16 @@ bool Extension::InitFromValue(int flags, string16* error) { return false; } + // Check for any permissions that are optional only. + for (APIPermissionSet::const_iterator i = api_permissions.begin(); + i != api_permissions.end(); ++i) { + if ((*i)->info()->must_be_optional()) { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kPermissionMustBeOptional, (*i)->info()->name()); + return false; + } + } + // TODO(jeremya/kalman) do this via the features system by exposing the // app.window API to platform apps, with no dependency on any permissions. // See http://crbug.com/120069. diff --git a/chrome/common/extensions/extension_manifest_constants.cc b/chrome/common/extensions/extension_manifest_constants.cc index 43871ac..185f865 100644 --- a/chrome/common/extensions/extension_manifest_constants.cc +++ b/chrome/common/extensions/extension_manifest_constants.cc @@ -522,6 +522,8 @@ const char kNoWildCardsInPaths[] = "Wildcards are not allowed in extent URL pattern paths."; const char kOneUISurfaceOnly[] = "Only one of 'browser_action', 'page_action', and 'app' can be specified."; +const char kPermissionMustBeOptional[] = + "Permission '*' must be specified in the optional section of the manifest."; const char kPermissionNotAllowed[] = "Access to permission '*' denied."; const char kPermissionNotAllowedInManifest[] = diff --git a/chrome/common/extensions/extension_manifest_constants.h b/chrome/common/extensions/extension_manifest_constants.h index 23001cc..8271c88 100644 --- a/chrome/common/extensions/extension_manifest_constants.h +++ b/chrome/common/extensions/extension_manifest_constants.h @@ -339,6 +339,7 @@ namespace extension_manifest_errors { extern const char kMultipleOverrides[]; extern const char kNoPermissionForFileBrowserHandlerMIMETypes[]; extern const char kNoWildCardsInPaths[]; + extern const char kPermissionMustBeOptional[]; extern const char kPermissionNotAllowed[]; extern const char kPermissionNotAllowedInManifest[]; extern const char kPlatformAppNeedsManifestVersion2[]; diff --git a/chrome/common/extensions/extension_messages.cc b/chrome/common/extensions/extension_messages.cc index 95ae472..28fe74b 100644 --- a/chrome/common/extensions/extension_messages.cc +++ b/chrome/common/extensions/extension_messages.cc @@ -19,6 +19,7 @@ using extensions::Extension; using extensions::PermissionSet; using extensions::SocketPermissionData; using extensions::URLPatternSet; +using extensions::UsbDevicePermissionData; ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params() : location(Extension::INVALID), @@ -227,6 +228,25 @@ void ParamTraits<BluetoothDevicePermissionData>::Log( LogParam(std::string("<BluetoothDevicePermissionData>"), l); } +void ParamTraits<UsbDevicePermissionData>::Write( + Message* m, const param_type& p) { + WriteParam(m, p.GetAsString()); +} + +bool ParamTraits<UsbDevicePermissionData>::Read( + const Message* m, PickleIterator* iter, param_type* r) { + std::string spec; + if (!ReadParam(m, iter, &spec)) + return false; + + return r->Parse(spec); +} + +void ParamTraits<UsbDevicePermissionData>::Log( + const param_type& p, std::string* l) { + LogParam(std::string("<UsbDevicePermissionData>"), l); +} + void ParamTraits<ExtensionMsg_Loaded_Params>::Write(Message* m, const param_type& p) { WriteParam(m, p.location); diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h index 6058fbf..86210c6 100644 --- a/chrome/common/extensions/extension_messages.h +++ b/chrome/common/extensions/extension_messages.h @@ -12,6 +12,7 @@ #include "chrome/common/extensions/permissions/bluetooth_device_permission_data.h" #include "chrome/common/extensions/permissions/permission_set.h" #include "chrome/common/extensions/permissions/socket_permission_data.h" +#include "chrome/common/extensions/permissions/usb_device_permission_data.h" #include "chrome/common/view_type.h" #include "chrome/common/web_apps.h" #include "content/public/common/common_param_traits.h" @@ -210,6 +211,14 @@ struct ParamTraits<extensions::BluetoothDevicePermissionData> { static void Log(const param_type& p, std::string* l); }; +template <> +struct ParamTraits<extensions::UsbDevicePermissionData> { + typedef extensions::UsbDevicePermissionData param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, PickleIterator* iter, param_type* r); + static void Log(const param_type& p, std::string* l); +}; + } // namespace IPC #endif // CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGES_H_ diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index 7d26279..4c899f6 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -21,6 +21,7 @@ #include "chrome/common/extensions/permissions/api_permission.h" #include "chrome/common/extensions/permissions/permission_set.h" #include "chrome/common/extensions/permissions/socket_permission.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" #include "chrome/common/url_constants.h" #include "extensions/common/error_utils.h" #include "googleurl/src/gurl.h" @@ -40,6 +41,7 @@ using extensions::Feature; using extensions::PermissionSet; using extensions::SocketPermission; using extensions::URLPatternSet; +using extensions::UsbDevicePermission; namespace keys = extension_manifest_keys; namespace values = extension_manifest_values; @@ -1246,6 +1248,31 @@ TEST(ExtensionTest, DontSyncDefault) { EXPECT_FALSE(extension_default->IsSyncable()); } +TEST(ExtensionTest, OptionalOnlyPermission) { + // Set feature current channel to dev because the only permission that must + // be optional (usbDevice) is only available on dev channel. + Feature::ScopedCurrentChannel scoped_channel( + chrome::VersionInfo::CHANNEL_DEV); + + scoped_refptr<Extension> extension; + std::string error; + extension = LoadManifestUnchecked("optional_only_permission", + "manifest1.json", + Extension::INTERNAL, Extension::NO_FLAGS, + &error); + EXPECT_TRUE(extension == NULL); + ASSERT_EQ(ErrorUtils::FormatErrorMessage( + errors::kPermissionMustBeOptional, "usbDevice"), error); + + error.clear(); + extension = LoadManifestUnchecked("optional_only_permission", + "manifest2.json", + Extension::INTERNAL, Extension::NO_FLAGS, + &error); + EXPECT_TRUE(extension != NULL); + EXPECT_TRUE(error.empty()); +} + // These last 2 tests don't make sense on Chrome OS, where extension plugins // are not allowed. #if !defined(OS_CHROMEOS) diff --git a/chrome/common/extensions/permissions/api_permission.cc b/chrome/common/extensions/permissions/api_permission.cc index 5278fa1..03b23cd 100644 --- a/chrome/common/extensions/permissions/api_permission.cc +++ b/chrome/common/extensions/permissions/api_permission.cc @@ -7,6 +7,7 @@ #include "chrome/common/extensions/permissions/bluetooth_device_permission.h" #include "chrome/common/extensions/permissions/permissions_info.h" #include "chrome/common/extensions/permissions/socket_permission.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -339,6 +340,9 @@ void APIPermissionInfo::RegisterAllPermissions( { APIPermission::kUsb, "usb", kFlagNone, IDS_EXTENSION_PROMPT_WARNING_USB, PermissionMessage::kUsb }, + { APIPermission::kUsbDevice, "usbDevice", + kFlagMustBeOptional, 0, PermissionMessage::kNone, + &::CreateAPIPermission<UsbDevicePermission> }, { APIPermission::kSystemIndicator, "systemIndicator", kFlagNone, IDS_EXTENSION_PROMPT_WARNING_SYSTEM_INDICATOR, PermissionMessage::kSystemIndicator }, diff --git a/chrome/common/extensions/permissions/api_permission.h b/chrome/common/extensions/permissions/api_permission.h index de5eb92..d714f3d 100644 --- a/chrome/common/extensions/permissions/api_permission.h +++ b/chrome/common/extensions/permissions/api_permission.h @@ -106,6 +106,7 @@ class APIPermission { kTtsEngine, kUnlimitedStorage, kUsb, + kUsbDevice, kVideoCapture, kWallpaperPrivate, kWebNavigation, @@ -211,7 +212,10 @@ class APIPermissionInfo { kFlagImpliesFullURLAccess = 1 << 1, // Indicates that extensions cannot specify the permission as optional. - kFlagCannotBeOptional = 1 << 3 + kFlagCannotBeOptional = 1 << 3, + + // Indicates that extensions cannot specify the permission as optional. + kFlagMustBeOptional = 1 << 4 }; typedef APIPermission* (*APIPermissionConstructor)(const APIPermissionInfo*); @@ -251,6 +255,12 @@ class APIPermissionInfo { return (flags_ & kFlagCannotBeOptional) == 0; } + // Returns true if this permission must be added and removed via the + // optional permissions extension API. + bool must_be_optional() const { + return (flags_ & kFlagMustBeOptional) != 0; + } + private: // Instances should only be constructed from within PermissionsInfo. friend class PermissionsInfo; diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission.cc b/chrome/common/extensions/permissions/bluetooth_device_permission.cc index 83e2bd6..bc35443 100644 --- a/chrome/common/extensions/permissions/bluetooth_device_permission.cc +++ b/chrome/common/extensions/permissions/bluetooth_device_permission.cc @@ -4,12 +4,10 @@ #include "chrome/common/extensions/permissions/bluetooth_device_permission.h" -#include <algorithm> #include <string> #include <vector> #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" @@ -38,16 +36,6 @@ BluetoothDevicePermission::BluetoothDevicePermission( BluetoothDevicePermission::~BluetoothDevicePermission() { } -void BluetoothDevicePermission::AddDevicesFromString( - const std::string &devices_string) { - std::vector<std::string> devices; - Tokenize(devices_string, kSeparator, &devices); - for (std::vector<std::string>::const_iterator i = devices.begin(); - i != devices.end(); ++i) { - data_set_.insert(BluetoothDevicePermissionData(*i)); - } -} - std::string BluetoothDevicePermission::ToString() const { std::vector<std::string> parts; parts.push_back(name()); diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission.h b/chrome/common/extensions/permissions/bluetooth_device_permission.h index d12cada..e708ec8 100644 --- a/chrome/common/extensions/permissions/bluetooth_device_permission.h +++ b/chrome/common/extensions/permissions/bluetooth_device_permission.h @@ -5,7 +5,6 @@ #ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_H_ #define CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_H_ -#include <set> #include <string> #include "chrome/common/extensions/permissions/api_permission.h" @@ -30,10 +29,6 @@ class BluetoothDevicePermission explicit BluetoothDevicePermission(const APIPermissionInfo* info); virtual ~BluetoothDevicePermission(); - // Adds BluetoothDevices from |devices| to the set of allowed devices. - // |devices| should be a string of Bluetooth device addresses separated by |. - void AddDevicesFromString(const std::string &devices_string); - // APIPermission overrides virtual std::string ToString() const OVERRIDE; virtual bool ManifestEntryForbidden() const OVERRIDE; diff --git a/chrome/common/extensions/permissions/permission_message.h b/chrome/common/extensions/permissions/permission_message.h index 94a73e1..597fc36 100644 --- a/chrome/common/extensions/permissions/permission_message.h +++ b/chrome/common/extensions/permissions/permission_message.h @@ -55,6 +55,7 @@ class PermissionMessage { kUsb, kSystemIndicator, kBluetoothDevice, + kUsbDevice, kEnumBoundary }; diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index 8fb5895..0f01d71 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc @@ -730,6 +730,7 @@ TEST(PermissionsTest, PermissionMessages) { // Platform apps. skip.insert(APIPermission::kFileSystem); skip.insert(APIPermission::kSocket); + skip.insert(APIPermission::kUsbDevice); PermissionsInfo* info = PermissionsInfo::GetInstance(); APIPermissionSet permissions = info->GetAll(); diff --git a/chrome/common/extensions/permissions/usb_device_permission.cc b/chrome/common/extensions/permissions/usb_device_permission.cc new file mode 100644 index 0000000..cc13b93 --- /dev/null +++ b/chrome/common/extensions/permissions/usb_device_permission.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2012 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 "chrome/common/extensions/permissions/usb_device_permission.h" + +#include <set> +#include <string> + +#include "base/logging.h" +#include "base/string16.h" +#include "base/utf_string_conversions.h" +#include "chrome/common/extensions/permissions/permissions_info.h" +#include "device/usb/usb_ids.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace extensions { + +UsbDevicePermission::UsbDevicePermission( + const APIPermissionInfo* info) + : SetDisjunctionPermission<UsbDevicePermissionData, + UsbDevicePermission>(info) { +} + +UsbDevicePermission::~UsbDevicePermission() { +} + +PermissionMessages UsbDevicePermission::GetMessages() const { + DCHECK(HasMessages()); + PermissionMessages result; + + for (std::set<UsbDevicePermissionData>::const_iterator i = + data_set_.begin(); i != data_set_.end(); ++i) { + + const char* vendor = device::UsbIds::GetVendorName(i->vendor_id()); + string16 vendor_name; + if (vendor) { + vendor_name = ASCIIToUTF16(vendor); + } else { + vendor_name = l10n_util::GetStringUTF16( + IDS_EXTENSION_PROMPT_WARNING_UNKNOWN_USB_VENDOR); + } + + const char* product = + device::UsbIds::GetProductName(i->vendor_id(), i->product_id()); + string16 product_name; + if (product) { + product_name = ASCIIToUTF16(product); + } else { + product_name = l10n_util::GetStringUTF16( + IDS_EXTENSION_PROMPT_WARNING_UNKNOWN_USB_PRODUCT); + } + + result.push_back(PermissionMessage( + PermissionMessage::kUsbDevice, + l10n_util::GetStringFUTF16( + IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE, + product_name, + vendor_name))); + } + + return result; +} + +} // namespace extensions diff --git a/chrome/common/extensions/permissions/usb_device_permission.h b/chrome/common/extensions/permissions/usb_device_permission.h new file mode 100644 index 0000000..77ea15d --- /dev/null +++ b/chrome/common/extensions/permissions/usb_device_permission.h @@ -0,0 +1,35 @@ +// Copyright (c) 2012 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 CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_ +#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_ + +#include "base/basictypes.h" +#include "chrome/common/extensions/permissions/api_permission.h" +#include "chrome/common/extensions/permissions/set_disjunction_permission.h" +#include "chrome/common/extensions/permissions/usb_device_permission_data.h" + +namespace extensions { + +class UsbDevicePermission + : public SetDisjunctionPermission<UsbDevicePermissionData, + UsbDevicePermission> { + public: + struct CheckParam : public APIPermission::CheckParam { + CheckParam(uint16 vendor_id, uint16 product_id) + : vendor_id(vendor_id), product_id(product_id) {} + const uint16 vendor_id; + const uint16 product_id; + }; + + explicit UsbDevicePermission(const APIPermissionInfo* info); + virtual ~UsbDevicePermission(); + + // APIPermission overrides + virtual PermissionMessages GetMessages() const OVERRIDE; +}; + +} // namespace extensions + +#endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_ diff --git a/chrome/common/extensions/permissions/usb_device_permission_data.cc b/chrome/common/extensions/permissions/usb_device_permission_data.cc new file mode 100644 index 0000000..087d628 --- /dev/null +++ b/chrome/common/extensions/permissions/usb_device_permission_data.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2012 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 "chrome/common/extensions/permissions/usb_device_permission_data.h" + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/string_number_conversions.h" +#include "base/string_split.h" +#include "chrome/common/extensions/permissions/api_permission.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" + +namespace { + +const char kColon = ':'; + +} // namespace + +namespace extensions { + +UsbDevicePermissionData::UsbDevicePermissionData() + : vendor_id_(0), product_id_(0), spec_("") { +} + +UsbDevicePermissionData::UsbDevicePermissionData(uint16 vendor_id, + uint16 product_id) + : vendor_id_(vendor_id), product_id_(product_id), spec_("") { +} + +bool UsbDevicePermissionData::Check( + const APIPermission::CheckParam* param) const { + if (!param) + return false; + const UsbDevicePermission::CheckParam& specific_param = + *static_cast<const UsbDevicePermission::CheckParam*>(param); + return vendor_id_ == specific_param.vendor_id && + product_id_ == specific_param.product_id; +} + +bool UsbDevicePermissionData::Parse(const std::string& spec) { + spec_.clear(); + + std::vector<std::string> tokens; + base::SplitStringDontTrim(spec, kColon, &tokens); + if (tokens.size() != 2) + return false; + + int temp; + if (!base::StringToInt(tokens[0], &temp) || temp < 0 || temp > kuint16max) + return false; + vendor_id_ = temp; + + if (!base::StringToInt(tokens[1], &temp) || temp < 0 || temp > kuint16max) + return false; + product_id_ = temp; + + return true; +} + +const std::string& UsbDevicePermissionData::GetAsString() const { + if (spec_.empty()) { + spec_.append(base::IntToString(vendor_id_)); + spec_.append(1, kColon); + spec_.append(base::IntToString(product_id_)); + } + return spec_; +} + +bool UsbDevicePermissionData::operator<( + const UsbDevicePermissionData& rhs) const { + if (vendor_id_ == rhs.vendor_id_) + return product_id_ < rhs.product_id_; + return vendor_id_ < rhs.vendor_id_; +} + +bool UsbDevicePermissionData::operator==( + const UsbDevicePermissionData& rhs) const { + return vendor_id_ == rhs.vendor_id_ && product_id_ == rhs.product_id_; +} + +} // namespace extensions diff --git a/chrome/common/extensions/permissions/usb_device_permission_data.h b/chrome/common/extensions/permissions/usb_device_permission_data.h new file mode 100644 index 0000000..a83976e --- /dev/null +++ b/chrome/common/extensions/permissions/usb_device_permission_data.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012 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 CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_ +#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_ + +#include <string> + +#include "base/basictypes.h" +#include "chrome/common/extensions/permissions/api_permission.h" + +namespace extensions { + +// A pattern that can be used to match a USB device permission. +// Should be of the format: vendorId:productId, where both vendorId and +// productId are decimal strings representing uint16 values. +class UsbDevicePermissionData { + public: + UsbDevicePermissionData(); + UsbDevicePermissionData(uint16 vendor_id, uint16 product_id); + + bool Check(const APIPermission::CheckParam* param) const; + bool Parse(const std::string& spec); + const std::string& GetAsString() const; + + bool operator<(const UsbDevicePermissionData& rhs) const; + bool operator==(const UsbDevicePermissionData& rhs) const; + + uint16 vendor_id() const { return vendor_id_; } + uint16 product_id() const { return product_id_; } + + private: + uint16 vendor_id_; + uint16 product_id_; + mutable std::string spec_; +}; + +} // namespace extensions + +#endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_ diff --git a/chrome/renderer/resources/extensions/permissions_custom_bindings.js b/chrome/renderer/resources/extensions/permissions_custom_bindings.js index 82a0b0a..faf03f8 100644 --- a/chrome/renderer/resources/extensions/permissions_custom_bindings.js +++ b/chrome/renderer/resources/extensions/permissions_custom_bindings.js @@ -27,7 +27,8 @@ chromeHidden.registerCustomHook('permissions', function(api) { if (keys.length != 1) { throw new Error("Too many keys in object-style permission."); } - arguments[0].permissions[i] = keys[0] + '|' + a[keys[0]]; + arguments[0].permissions[i] = keys[0] + '|' + + JSON.stringify(a[keys[0]]); } } diff --git a/chrome/test/data/extensions/optional_only_permission/manifest1.json b/chrome/test/data/extensions/optional_only_permission/manifest1.json new file mode 100644 index 0000000..d29bdc1 --- /dev/null +++ b/chrome/test/data/extensions/optional_only_permission/manifest1.json @@ -0,0 +1,13 @@ +{ + "name": "optional only permission test", + "version": "1.0", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["main.js"] + } + }, + "permissions": [ + {"usbDevice":["0:0"]} + ] +} diff --git a/chrome/test/data/extensions/optional_only_permission/manifest2.json b/chrome/test/data/extensions/optional_only_permission/manifest2.json new file mode 100644 index 0000000..bd12900 --- /dev/null +++ b/chrome/test/data/extensions/optional_only_permission/manifest2.json @@ -0,0 +1,13 @@ +{ + "name": "optional only permission test", + "version": "1.0", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["main.js"] + } + }, + "optional_permissions": [ + {"usbDevice":["123:456"]} + ] +} |