summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/browser/DEPS1
-rw-r--r--extensions/browser/api/socket/socket_api.cc2
-rw-r--r--extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc2
-rw-r--r--extensions/common/DEPS3
-rw-r--r--extensions/common/api/messaging/message.h22
-rw-r--r--extensions/common/extension_messages.h8
-rw-r--r--extensions/common/permissions/media_galleries_permission.cc157
-rw-r--r--extensions/common/permissions/media_galleries_permission.h56
-rw-r--r--extensions/common/permissions/media_galleries_permission_data.cc62
-rw-r--r--extensions/common/permissions/media_galleries_permission_data.h51
-rw-r--r--extensions/common/permissions/permission_message_util.cc150
-rw-r--r--extensions/common/permissions/permission_message_util.h31
-rw-r--r--extensions/common/permissions/permissions_data_unittest.cc2
-rw-r--r--extensions/common/permissions/set_disjunction_permission.h172
-rw-r--r--extensions/common/permissions/settings_override_permission.cc107
-rw-r--r--extensions/common/permissions/settings_override_permission.h44
-rw-r--r--extensions/common/permissions/socket_permission.cc108
-rw-r--r--extensions/common/permissions/socket_permission.h43
-rw-r--r--extensions/common/permissions/socket_permission_data.cc158
-rw-r--r--extensions/common/permissions/socket_permission_data.h89
-rw-r--r--extensions/common/permissions/socket_permission_entry.cc226
-rw-r--r--extensions/common/permissions/socket_permission_entry.h84
-rw-r--r--extensions/common/permissions/usb_device_permission.cc74
-rw-r--r--extensions/common/permissions/usb_device_permission.h38
-rw-r--r--extensions/common/permissions/usb_device_permission_data.cc109
-rw-r--r--extensions/common/permissions/usb_device_permission_data.h71
-rw-r--r--extensions/extensions.gyp20
27 files changed, 1880 insertions, 10 deletions
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index 57b1dfc..0060709 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -20,7 +20,6 @@ include_rules = [
"+chrome/browser/renderer_host/chrome_render_message_filter.h",
"+chrome/common/extensions/api/sockets/sockets_manifest_data.h",
"+chrome/common/extensions/features/feature_channel.h",
- "+chrome/common/extensions/permissions",
"+grit/generated_resources.h",
]
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index 34a5517..dbe7a87 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/resource_context.h"
#include "extensions/browser/api/socket/socket.h"
@@ -18,6 +17,7 @@
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
index 6adc0fc..4a0c8e6e 100644
--- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
+++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -5,11 +5,11 @@
#include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h"
#include "chrome/common/extensions/api/sockets/sockets_manifest_data.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
#include "content/public/common/socket_permission_request.h"
#include "extensions/browser/api/socket/tcp_socket.h"
#include "extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
#include "net/base/net_errors.h"
using content::SocketPermissionRequest;
diff --git a/extensions/common/DEPS b/extensions/common/DEPS
index c75b833..12baab5 100644
--- a/extensions/common/DEPS
+++ b/extensions/common/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+device/usb",
"+net",
"+third_party/re2",
@@ -9,8 +10,6 @@ include_rules = [
#
# TODO(benwells): Remove these. http://crbug.com/162530
"+chrome/common/extensions/api/generated_schemas.h",
- "+chrome/common/extensions/api/messaging/message.h",
- "+chrome/common/extensions/permissions",
"+grit/chromium_strings.h",
"+grit/common_resources.h",
"+grit/extensions_api_resources.h",
diff --git a/extensions/common/api/messaging/message.h b/extensions/common/api/messaging/message.h
new file mode 100644
index 0000000..64ecb82
--- /dev/null
+++ b/extensions/common/api/messaging/message.h
@@ -0,0 +1,22 @@
+// 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_COMMON_API_MESSAGING_MESSAGE_H_
+#define EXTENSIONS_COMMON_API_MESSAGING_MESSAGE_H_
+
+namespace extensions {
+
+// A message consists of both the data itself as well as a user gesture state.
+struct Message {
+ std::string data;
+ bool user_gesture;
+
+ Message() : data(), user_gesture(false) {}
+ Message(const std::string& data, bool user_gesture)
+ : data(data), user_gesture(user_gesture) {}
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_API_MESSAGING_MESSAGE_H_
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h
index f5c2817..b7ce195 100644
--- a/extensions/common/extension_messages.h
+++ b/extensions/common/extension_messages.h
@@ -10,16 +10,16 @@
#include "base/memory/shared_memory.h"
#include "base/values.h"
-#include "chrome/common/extensions/api/messaging/message.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
-#include "chrome/common/extensions/permissions/socket_permission_data.h"
-#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/socket_permission_request.h"
+#include "extensions/common/api/messaging/message.h"
#include "extensions/common/draggable_region.h"
#include "extensions/common/extension.h"
#include "extensions/common/extensions_client.h"
+#include "extensions/common/permissions/media_galleries_permission_data.h"
#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/socket_permission_data.h"
+#include "extensions/common/permissions/usb_device_permission_data.h"
#include "extensions/common/url_pattern.h"
#include "extensions/common/url_pattern_set.h"
#include "extensions/common/view_type.h"
diff --git a/extensions/common/permissions/media_galleries_permission.cc b/extensions/common/permissions/media_galleries_permission.cc
new file mode 100644
index 0000000..baf7162
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission.cc
@@ -0,0 +1,157 @@
+// 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/common/permissions/media_galleries_permission.h"
+
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// copyTo permission requires delete permission as a prerequisite.
+// delete permission requires read permission as a prerequisite.
+bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete,
+ std::string* error) {
+ if (has_copy_to) {
+ if (has_read && has_delete)
+ return true;
+ if (error)
+ *error = "copyTo permission requires read and delete permissions";
+ return false;
+ }
+ if (has_delete) {
+ if (has_read)
+ return true;
+ if (error)
+ *error = "delete permission requires read permission";
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace extensions {
+
+const char MediaGalleriesPermission::kAllAutoDetectedPermission[] =
+ "allAutoDetected";
+const char MediaGalleriesPermission::kScanPermission[] = "scan";
+const char MediaGalleriesPermission::kReadPermission[] = "read";
+const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo";
+const char MediaGalleriesPermission::kDeletePermission[] = "delete";
+
+MediaGalleriesPermission::MediaGalleriesPermission(
+ const APIPermissionInfo* info)
+ : SetDisjunctionPermission<MediaGalleriesPermissionData,
+ MediaGalleriesPermission>(info) {
+}
+
+MediaGalleriesPermission::~MediaGalleriesPermission() {
+}
+
+bool MediaGalleriesPermission::FromValue(const base::Value* value,
+ std::string* error) {
+ if (!SetDisjunctionPermission<MediaGalleriesPermissionData,
+ MediaGalleriesPermission>::FromValue(value,
+ error)) {
+ return false;
+ }
+
+ bool has_read = false;
+ bool has_copy_to = false;
+ bool has_delete = false;
+ for (std::set<MediaGalleriesPermissionData>::const_iterator it =
+ data_set_.begin(); it != data_set_.end(); ++it) {
+ if (it->permission() == kAllAutoDetectedPermission ||
+ it->permission() == kScanPermission) {
+ continue;
+ }
+ if (it->permission() == kReadPermission) {
+ has_read = true;
+ continue;
+ }
+ if (it->permission() == kCopyToPermission) {
+ has_copy_to = true;
+ continue;
+ }
+ if (it->permission() == kDeletePermission) {
+ has_delete = true;
+ continue;
+ }
+
+ // No other permissions, so reaching this means
+ // MediaGalleriesPermissionData is probably out of sync in some way.
+ // Fail so developers notice this.
+ NOTREACHED();
+ return false;
+ }
+
+ return IsValidPermissionSet(has_read, has_copy_to, has_delete, error);
+}
+
+PermissionMessages MediaGalleriesPermission::GetMessages() const {
+ DCHECK(HasMessages());
+ PermissionMessages result;
+
+ bool has_all_auto_detected = false;
+ bool has_read = false;
+ bool has_copy_to = false;
+ bool has_delete = false;
+
+ for (std::set<MediaGalleriesPermissionData>::const_iterator it =
+ data_set_.begin(); it != data_set_.end(); ++it) {
+ if (it->permission() == kAllAutoDetectedPermission)
+ has_all_auto_detected = true;
+ else if (it->permission() == kReadPermission)
+ has_read = true;
+ else if (it->permission() == kCopyToPermission)
+ has_copy_to = true;
+ else if (it->permission() == kDeletePermission)
+ has_delete = true;
+ }
+
+ if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, NULL)) {
+ NOTREACHED();
+ return result;
+ }
+
+ // If |has_all_auto_detected| is false, then Chrome will prompt the user at
+ // runtime when the extension call the getMediaGalleries API.
+ if (!has_all_auto_detected)
+ return result;
+ // No access permission case.
+ if (!has_read)
+ return result;
+
+ // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an
+ // extension can silently gain new access capabilities.
+ result.push_back(PermissionMessage(
+ PermissionMessage::kMediaGalleriesAllGalleriesRead,
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ)));
+
+ // For copyTo and delete, the proper combined permission message will be
+ // derived in ChromePermissionMessageProvider::GetWarningMessages(), such
+ // that the user get 1 entry for all media galleries access permissions,
+ // rather than several separate entries.
+ if (has_copy_to) {
+ result.push_back(PermissionMessage(
+ PermissionMessage::kMediaGalleriesAllGalleriesCopyTo,
+ base::string16()));
+ }
+ if (has_delete) {
+ result.push_back(PermissionMessage(
+ PermissionMessage::kMediaGalleriesAllGalleriesDelete,
+ base::string16()));
+ }
+ return result;
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/media_galleries_permission.h b/extensions/common/permissions/media_galleries_permission.h
new file mode 100644
index 0000000..36b6dba
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission.h
@@ -0,0 +1,56 @@
+// 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_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
+
+#include "base/basictypes.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission_data.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+
+namespace extensions {
+
+// Media Galleries permissions are as follows:
+// <media-galleries-permission-pattern>
+// := <access> | <access> 'allAutoDetected' | 'allAutoDetected' |
+// <access> 'scan' | 'scan'
+// <access> := 'read' | 'read' <access> | 'read' <secondary-access>
+// <secondary-access>
+// := 'delete' | 'delete' <secondary-access> |
+// 'delete' <tertiary-access>
+// <tertiary-access>
+// := 'copyTo' | 'copyTo' <tertiary-access>
+class MediaGalleriesPermission
+ : public SetDisjunctionPermission<MediaGalleriesPermissionData,
+ MediaGalleriesPermission> {
+ public:
+ struct CheckParam : public APIPermission::CheckParam {
+ explicit CheckParam(const std::string& permission)
+ : permission(permission) {}
+ const std::string permission;
+ };
+
+ explicit MediaGalleriesPermission(const APIPermissionInfo* info);
+ virtual ~MediaGalleriesPermission();
+
+ // SetDisjunctionPermission overrides.
+ // MediaGalleriesPermission does additional checks to make sure the
+ // permissions do not contain unknown values.
+ virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
+
+ // APIPermission overrides.
+ virtual PermissionMessages GetMessages() const OVERRIDE;
+
+ // Permission strings.
+ static const char kAllAutoDetectedPermission[];
+ static const char kScanPermission[];
+ static const char kReadPermission[];
+ static const char kCopyToPermission[];
+ static const char kDeletePermission[];
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
diff --git a/extensions/common/permissions/media_galleries_permission_data.cc b/extensions/common/permissions/media_galleries_permission_data.cc
new file mode 100644
index 0000000..d7e7937
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission_data.cc
@@ -0,0 +1,62 @@
+// 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/common/permissions/media_galleries_permission_data.h"
+
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
+
+namespace extensions {
+
+MediaGalleriesPermissionData::MediaGalleriesPermissionData() {
+}
+
+bool MediaGalleriesPermissionData::Check(
+ const APIPermission::CheckParam* param) const {
+ if (!param)
+ return false;
+
+ const MediaGalleriesPermission::CheckParam& specific_param =
+ *static_cast<const MediaGalleriesPermission::CheckParam*>(param);
+ return permission_ == specific_param.permission;
+}
+
+scoped_ptr<base::Value> MediaGalleriesPermissionData::ToValue() const {
+ return scoped_ptr<base::Value>(new base::StringValue(permission_));
+}
+
+bool MediaGalleriesPermissionData::FromValue(const base::Value* value) {
+ if (!value)
+ return false;
+
+ std::string raw_permission;
+ if (!value->GetAsString(&raw_permission))
+ return false;
+
+ std::string permission;
+ base::TrimWhitespaceASCII(raw_permission, base::TRIM_ALL, &permission);
+
+ if (permission == MediaGalleriesPermission::kAllAutoDetectedPermission ||
+ permission == MediaGalleriesPermission::kScanPermission ||
+ permission == MediaGalleriesPermission::kReadPermission ||
+ permission == MediaGalleriesPermission::kCopyToPermission ||
+ permission == MediaGalleriesPermission::kDeletePermission) {
+ permission_ = permission;
+ return true;
+ }
+ return false;
+}
+
+bool MediaGalleriesPermissionData::operator<(
+ const MediaGalleriesPermissionData& rhs) const {
+ return permission_ < rhs.permission_;
+}
+
+bool MediaGalleriesPermissionData::operator==(
+ const MediaGalleriesPermissionData& rhs) const {
+ return permission_ == rhs.permission_;
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/media_galleries_permission_data.h b/extensions/common/permissions/media_galleries_permission_data.h
new file mode 100644
index 0000000..920a905
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission_data.h
@@ -0,0 +1,51 @@
+// 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_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "extensions/common/permissions/api_permission.h"
+
+namespace base {
+class Value;
+}
+
+namespace extensions {
+
+// A MediaGalleriesPermissionData instance represents a single part of the
+// MediaGalleriesPermission. e.g. "read" or "allAutoDetected".
+class MediaGalleriesPermissionData {
+ public:
+ MediaGalleriesPermissionData();
+
+ // Check if |param| (which must be a MediaGalleriesPermission::CheckParam)
+ // matches the encapsulated attribute.
+ bool Check(const APIPermission::CheckParam* param) const;
+
+ // Convert |this| into a base::Value.
+ scoped_ptr<base::Value> ToValue() const;
+
+ // Populate |this| from a base::Value.
+ bool FromValue(const base::Value* value);
+
+ bool operator<(const MediaGalleriesPermissionData& rhs) const;
+ bool operator==(const MediaGalleriesPermissionData& rhs) const;
+
+ std::string permission() const { return permission_; }
+
+ // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER. Please think
+ // twice before using it for anything else.
+ std::string& permission() { return permission_; }
+
+ private:
+ std::string permission_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
diff --git a/extensions/common/permissions/permission_message_util.cc b/extensions/common/permissions/permission_message_util.cc
new file mode 100644
index 0000000..76d1c61
--- /dev/null
+++ b/extensions/common/permissions/permission_message_util.cc
@@ -0,0 +1,150 @@
+// 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/common/permissions/permission_message_util.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/permissions/permission_message.h"
+#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/url_pattern_set.h"
+#include "grit/generated_resources.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using extensions::PermissionMessage;
+using extensions::PermissionSet;
+using extensions::URLPatternSet;
+
+namespace {
+
+// Helper for GetDistinctHosts(): com > net > org > everything else.
+bool RcdBetterThan(const std::string& a, const std::string& b) {
+ if (a == b)
+ return false;
+ if (a == "com")
+ return true;
+ if (a == "net")
+ return b != "com";
+ if (a == "org")
+ return b != "com" && b != "net";
+ return false;
+}
+
+} // namespace
+
+namespace permission_message_util {
+
+PermissionMessage CreateFromHostList(const std::set<std::string>& hosts) {
+ std::vector<std::string> host_list(hosts.begin(), hosts.end());
+ DCHECK(host_list.size());
+ PermissionMessage::ID message_id;
+ base::string16 message;
+ base::string16 details;
+
+ switch (host_list.size()) {
+ case 1:
+ message_id = PermissionMessage::kHosts1;
+ message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
+ base::UTF8ToUTF16(host_list[0]));
+ break;
+ case 2:
+ message_id = PermissionMessage::kHosts2;
+ message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
+ base::UTF8ToUTF16(host_list[0]),
+ base::UTF8ToUTF16(host_list[1]));
+ break;
+ case 3:
+ message_id = PermissionMessage::kHosts3;
+ message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
+ base::UTF8ToUTF16(host_list[0]),
+ base::UTF8ToUTF16(host_list[1]),
+ base::UTF8ToUTF16(host_list[2]));
+ break;
+ default:
+ message_id = PermissionMessage::kHosts4OrMore;
+
+ const int kRetainedFilesMessageIDs[6] = {
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_DEFAULT,
+ IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY, };
+ std::vector<int> message_ids;
+ for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
+ message_ids.push_back(kRetainedFilesMessageIDs[i]);
+ }
+ message = l10n_util::GetPluralStringFUTF16(message_ids, host_list.size());
+
+ for (size_t i = 0; i < host_list.size(); ++i) {
+ if (i > 0)
+ details += base::ASCIIToUTF16("\n");
+ details += l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_HOST_LIST_ENTRY,
+ base::UTF8ToUTF16(host_list[i]));
+ }
+ }
+
+ return PermissionMessage(message_id, message, details);
+}
+
+std::set<std::string> GetDistinctHosts(const URLPatternSet& host_patterns,
+ bool include_rcd,
+ bool exclude_file_scheme) {
+ // Use a vector to preserve order (also faster than a map on small sets).
+ // Each item is a host split into two parts: host without RCDs and
+ // current best RCD.
+ typedef std::vector<std::pair<std::string, std::string> > HostVector;
+ HostVector hosts_best_rcd;
+ for (URLPatternSet::const_iterator i = host_patterns.begin();
+ i != host_patterns.end();
+ ++i) {
+ if (exclude_file_scheme && i->scheme() == content::kFileScheme)
+ continue;
+
+ std::string host = i->host();
+
+ // Add the subdomain wildcard back to the host, if necessary.
+ if (i->match_subdomains())
+ host = "*." + host;
+
+ // If the host has an RCD, split it off so we can detect duplicates.
+ std::string rcd;
+ size_t reg_len = net::registry_controlled_domains::GetRegistryLength(
+ host,
+ net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+ net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+ if (reg_len && reg_len != std::string::npos) {
+ if (include_rcd) // else leave rcd empty
+ rcd = host.substr(host.size() - reg_len);
+ host = host.substr(0, host.size() - reg_len);
+ }
+
+ // Check if we've already seen this host.
+ HostVector::iterator it = hosts_best_rcd.begin();
+ for (; it != hosts_best_rcd.end(); ++it) {
+ if (it->first == host)
+ break;
+ }
+ // If this host was found, replace the RCD if this one is better.
+ if (it != hosts_best_rcd.end()) {
+ if (include_rcd && RcdBetterThan(rcd, it->second))
+ it->second = rcd;
+ } else { // Previously unseen host, append it.
+ hosts_best_rcd.push_back(std::make_pair(host, rcd));
+ }
+ }
+
+ // Build up the final vector by concatenating hosts and RCDs.
+ std::set<std::string> distinct_hosts;
+ for (HostVector::iterator it = hosts_best_rcd.begin();
+ it != hosts_best_rcd.end();
+ ++it)
+ distinct_hosts.insert(it->first + it->second);
+ return distinct_hosts;
+}
+
+} // namespace permission_message_util
diff --git a/extensions/common/permissions/permission_message_util.h b/extensions/common/permissions/permission_message_util.h
new file mode 100644
index 0000000..410e1a2
--- /dev/null
+++ b/extensions/common/permissions/permission_message_util.h
@@ -0,0 +1,31 @@
+// 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_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
+
+#include <set>
+#include <string>
+
+namespace extensions {
+class PermissionMessage;
+class PermissionSet;
+class URLPatternSet;
+}
+
+namespace permission_message_util {
+
+// Creates the corresponding permission message for a list of hosts.
+// The messages change depending on what hosts are present.
+extensions::PermissionMessage CreateFromHostList(
+ const std::set<std::string>& hosts);
+
+std::set<std::string> GetDistinctHosts(
+ const extensions::URLPatternSet& host_patterns,
+ bool include_rcd,
+ bool exclude_file_scheme);
+
+} // namespace permission_message_util
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
diff --git a/extensions/common/permissions/permissions_data_unittest.cc b/extensions/common/permissions/permissions_data_unittest.cc
index fda57f9..2ebc9ba 100644
--- a/extensions/common/permissions/permissions_data_unittest.cc
+++ b/extensions/common/permissions/permissions_data_unittest.cc
@@ -11,7 +11,6 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/common/extensions/features/feature_channel.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
#include "content/public/common/socket_permission_request.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
@@ -20,6 +19,7 @@
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
#include "extensions/common/switches.h"
#include "extensions/common/url_pattern_set.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/extensions/common/permissions/set_disjunction_permission.h b/extensions/common/permissions/set_disjunction_permission.h
new file mode 100644
index 0000000..3a3e9c5
--- /dev/null
+++ b/extensions/common/permissions/set_disjunction_permission.h
@@ -0,0 +1,172 @@
+// 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_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
+
+#include <algorithm>
+#include <set>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace extensions {
+
+// An abstract base class for permissions that are represented by the
+// disjunction of a set of conditions. Each condition is represented by a
+// |PermissionDataType| (e.g. SocketPermissionData). If an
+// APIPermission::CheckParam matches any of the conditions in the set, the
+// permission is granted.
+//
+// For an example of how to use this class, see SocketPermission.
+template <class PermissionDataType, class DerivedType>
+class SetDisjunctionPermission : public APIPermission {
+ public:
+ explicit SetDisjunctionPermission(const APIPermissionInfo* info)
+ : APIPermission(info) {}
+
+ ~SetDisjunctionPermission() {}
+
+ // APIPermission overrides
+ virtual bool HasMessages() const OVERRIDE { return !data_set_.empty(); }
+
+ virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE {
+ for (typename std::set<PermissionDataType>::const_iterator i =
+ data_set_.begin();
+ i != data_set_.end();
+ ++i) {
+ if (i->Check(param))
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool Contains(const APIPermission* rhs) const OVERRIDE {
+ CHECK(rhs->info() == info());
+ const SetDisjunctionPermission* perm =
+ static_cast<const SetDisjunctionPermission*>(rhs);
+ return std::includes(data_set_.begin(),
+ data_set_.end(),
+ perm->data_set_.begin(),
+ perm->data_set_.end());
+ }
+
+ virtual bool Equal(const APIPermission* rhs) const OVERRIDE {
+ CHECK(rhs->info() == info());
+ const SetDisjunctionPermission* perm =
+ static_cast<const SetDisjunctionPermission*>(rhs);
+ return data_set_ == perm->data_set_;
+ }
+
+ virtual APIPermission* Clone() const OVERRIDE {
+ SetDisjunctionPermission* result = new DerivedType(info());
+ result->data_set_ = data_set_;
+ return result;
+ }
+
+ virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE {
+ CHECK(rhs->info() == info());
+ const SetDisjunctionPermission* perm =
+ static_cast<const SetDisjunctionPermission*>(rhs);
+ scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+ std::set_difference(data_set_.begin(),
+ data_set_.end(),
+ perm->data_set_.begin(),
+ perm->data_set_.end(),
+ std::inserter<std::set<PermissionDataType> >(
+ result->data_set_, result->data_set_.begin()));
+ return result->data_set_.empty() ? NULL : result.release();
+ }
+
+ virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE {
+ CHECK(rhs->info() == info());
+ const SetDisjunctionPermission* perm =
+ static_cast<const SetDisjunctionPermission*>(rhs);
+ scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+ std::set_union(data_set_.begin(),
+ data_set_.end(),
+ perm->data_set_.begin(),
+ perm->data_set_.end(),
+ std::inserter<std::set<PermissionDataType> >(
+ result->data_set_, result->data_set_.begin()));
+ return result.release();
+ }
+
+ virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE {
+ CHECK(rhs->info() == info());
+ const SetDisjunctionPermission* perm =
+ static_cast<const SetDisjunctionPermission*>(rhs);
+ scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+ std::set_intersection(data_set_.begin(),
+ data_set_.end(),
+ perm->data_set_.begin(),
+ perm->data_set_.end(),
+ std::inserter<std::set<PermissionDataType> >(
+ result->data_set_, result->data_set_.begin()));
+ return result->data_set_.empty() ? NULL : result.release();
+ }
+
+ virtual bool FromValue(const base::Value* value,
+ std::string* error) OVERRIDE {
+ data_set_.clear();
+ const base::ListValue* list = NULL;
+
+ if (!value || !value->GetAsList(&list) || list->GetSize() == 0) {
+ if (error)
+ *error = "NULL or empty permission list";
+ return false;
+ }
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ const base::Value* item_value = NULL;
+ bool got_item = list->Get(i, &item_value);
+ DCHECK(got_item);
+ DCHECK(item_value);
+
+ PermissionDataType data;
+ if (!data.FromValue(item_value)) {
+ if (error)
+ *error = "Cannot parse an item from the permission list";
+ return false;
+ }
+
+ data_set_.insert(data);
+ }
+ return true;
+ }
+
+ virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
+ base::ListValue* list = new base::ListValue();
+ typename std::set<PermissionDataType>::const_iterator i;
+ for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+ scoped_ptr<base::Value> item_value(i->ToValue());
+ list->Append(item_value.release());
+ }
+ return scoped_ptr<base::Value>(list);
+ }
+
+ virtual void Write(IPC::Message* m) const OVERRIDE {
+ IPC::WriteParam(m, data_set_);
+ }
+
+ virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
+ return IPC::ReadParam(m, iter, &data_set_);
+ }
+
+ virtual void Log(std::string* log) const OVERRIDE {
+ IPC::LogParam(data_set_, log);
+ }
+
+ protected:
+ std::set<PermissionDataType> data_set_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
diff --git a/extensions/common/permissions/settings_override_permission.cc b/extensions/common/permissions/settings_override_permission.cc
new file mode 100644
index 0000000..b58d937
--- /dev/null
+++ b/extensions/common/permissions/settings_override_permission.cc
@@ -0,0 +1,107 @@
+// 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/common/permissions/settings_override_permission.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+SettingsOverrideAPIPermission::SettingsOverrideAPIPermission(
+ const APIPermissionInfo* permission,
+ const std::string& setting_value)
+ : APIPermission(permission), setting_value_(setting_value) {}
+
+SettingsOverrideAPIPermission::~SettingsOverrideAPIPermission() {}
+
+bool SettingsOverrideAPIPermission::HasMessages() const {
+ return info()->message_id() > PermissionMessage::kNone;
+}
+
+PermissionMessages SettingsOverrideAPIPermission::GetMessages() const {
+ DCHECK(HasMessages());
+ int string_id = -1;
+ switch (id()) {
+ case kHomepage: {
+ string_id = IDS_EXTENSION_PROMPT_WARNING_HOME_PAGE_SETTING_OVERRIDE;
+ break;
+ }
+ case kStartupPages: {
+ string_id = IDS_EXTENSION_PROMPT_WARNING_START_PAGE_SETTING_OVERRIDE;
+ break;
+ }
+ case kSearchProvider: {
+ string_id = IDS_EXTENSION_PROMPT_WARNING_SEARCH_SETTINGS_OVERRIDE;
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ PermissionMessages result;
+ result.push_back(
+ PermissionMessage(info()->message_id(),
+ l10n_util::GetStringFUTF16(
+ string_id, base::UTF8ToUTF16(setting_value_))));
+ return result;
+}
+
+bool SettingsOverrideAPIPermission::Check(
+ const APIPermission::CheckParam* param) const {
+ return (param == NULL);
+}
+
+bool SettingsOverrideAPIPermission::Contains(const APIPermission* rhs) const {
+ CHECK_EQ(info(), rhs->info());
+ return true;
+}
+
+bool SettingsOverrideAPIPermission::Equal(const APIPermission* rhs) const {
+ if (this != rhs)
+ CHECK_EQ(info(), rhs->info());
+ return true;
+}
+
+bool SettingsOverrideAPIPermission::FromValue(const base::Value* value,
+ std::string* /*error*/) {
+ return (value == NULL);
+}
+
+scoped_ptr<base::Value> SettingsOverrideAPIPermission::ToValue() const {
+ return scoped_ptr<base::Value>();
+}
+
+APIPermission* SettingsOverrideAPIPermission::Clone() const {
+ return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+APIPermission* SettingsOverrideAPIPermission::Diff(
+ const APIPermission* rhs) const {
+ CHECK_EQ(info(), rhs->info());
+ return NULL;
+}
+
+APIPermission* SettingsOverrideAPIPermission::Union(
+ const APIPermission* rhs) const {
+ CHECK_EQ(info(), rhs->info());
+ return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+APIPermission* SettingsOverrideAPIPermission::Intersect(
+ const APIPermission* rhs) const {
+ CHECK_EQ(info(), rhs->info());
+ return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+void SettingsOverrideAPIPermission::Write(IPC::Message* m) const {}
+
+bool SettingsOverrideAPIPermission::Read(const IPC::Message* m,
+ PickleIterator* iter) {
+ return true;
+}
+
+void SettingsOverrideAPIPermission::Log(std::string* log) const {}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/settings_override_permission.h b/extensions/common/permissions/settings_override_permission.h
new file mode 100644
index 0000000..48d3d71
--- /dev/null
+++ b/extensions/common/permissions/settings_override_permission.h
@@ -0,0 +1,44 @@
+// 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_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+
+namespace extensions {
+
+// Takes care of creating custom permission messages for extensions that
+// override settings.
+class SettingsOverrideAPIPermission : public APIPermission {
+ public:
+ SettingsOverrideAPIPermission(const APIPermissionInfo* permission,
+ const std::string& setting_value);
+ virtual ~SettingsOverrideAPIPermission();
+
+ // APIPermission overrides.
+ virtual bool HasMessages() const OVERRIDE;
+ virtual PermissionMessages GetMessages() const OVERRIDE;
+ virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE;
+ virtual bool Contains(const APIPermission* rhs) const OVERRIDE;
+ virtual bool Equal(const APIPermission* rhs) const OVERRIDE;
+ virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
+ virtual scoped_ptr<base::Value> ToValue() const OVERRIDE;
+ virtual APIPermission* Clone() const OVERRIDE;
+ virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE;
+ virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE;
+ virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE;
+ virtual void Write(IPC::Message* m) const OVERRIDE;
+ virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE;
+ virtual void Log(std::string* log) const OVERRIDE;
+
+ private:
+ std::string setting_value_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
diff --git a/extensions/common/permissions/socket_permission.cc b/extensions/common/permissions/socket_permission.cc
new file mode 100644
index 0000000..bc7d0c9
--- /dev/null
+++ b/extensions/common/permissions/socket_permission.cc
@@ -0,0 +1,108 @@
+// 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/common/permissions/socket_permission.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+SocketPermission::SocketPermission(const APIPermissionInfo* info)
+ : SetDisjunctionPermission<SocketPermissionData, SocketPermission>(info) {}
+
+SocketPermission::~SocketPermission() {}
+
+PermissionMessages SocketPermission::GetMessages() const {
+ DCHECK(HasMessages());
+ PermissionMessages result;
+ if (!AddAnyHostMessage(result)) {
+ AddSpecificHostMessage(result);
+ AddSubdomainHostMessage(result);
+ }
+ AddNetworkListMessage(result);
+ return result;
+}
+
+bool SocketPermission::AddAnyHostMessage(PermissionMessages& messages) const {
+ std::set<SocketPermissionData>::const_iterator i;
+ for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+ if (i->entry().IsAddressBoundType() &&
+ i->entry().GetHostType() == SocketPermissionEntry::ANY_HOST) {
+ messages.push_back(
+ PermissionMessage(PermissionMessage::kSocketAnyHost,
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
+ return true;
+ }
+ }
+ return false;
+}
+
+void SocketPermission::AddSubdomainHostMessage(
+ PermissionMessages& messages) const {
+ std::set<base::string16> domains;
+ std::set<SocketPermissionData>::const_iterator i;
+ for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+ if (i->entry().GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
+ domains.insert(base::UTF8ToUTF16(i->entry().pattern().host));
+ }
+ if (!domains.empty()) {
+ int id = (domains.size() == 1)
+ ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
+ : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
+ messages.push_back(PermissionMessage(
+ PermissionMessage::kSocketDomainHosts,
+ l10n_util::GetStringFUTF16(
+ id,
+ JoinString(
+ std::vector<base::string16>(domains.begin(), domains.end()),
+ ' '))));
+ }
+}
+
+void SocketPermission::AddSpecificHostMessage(
+ PermissionMessages& messages) const {
+ std::set<base::string16> hostnames;
+ std::set<SocketPermissionData>::const_iterator i;
+ for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+ if (i->entry().GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
+ hostnames.insert(base::UTF8ToUTF16(i->entry().pattern().host));
+ }
+ if (!hostnames.empty()) {
+ int id = (hostnames.size() == 1)
+ ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
+ : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
+ messages.push_back(PermissionMessage(
+ PermissionMessage::kSocketSpecificHosts,
+ l10n_util::GetStringFUTF16(
+ id,
+ JoinString(
+ std::vector<base::string16>(hostnames.begin(), hostnames.end()),
+ ' '))));
+ }
+}
+
+void SocketPermission::AddNetworkListMessage(
+ PermissionMessages& messages) const {
+ std::set<SocketPermissionData>::const_iterator i;
+ for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+ if (i->entry().pattern().type ==
+ content::SocketPermissionRequest::NETWORK_STATE) {
+ messages.push_back(
+ PermissionMessage(PermissionMessage::kNetworkState,
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
+ }
+ }
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/socket_permission.h b/extensions/common/permissions/socket_permission.h
new file mode 100644
index 0000000..2bfea7c
--- /dev/null
+++ b/extensions/common/permissions/socket_permission.h
@@ -0,0 +1,43 @@
+// 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_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "extensions/common/permissions/socket_permission_data.h"
+
+namespace extensions {
+
+class SocketPermission
+ : public SetDisjunctionPermission<SocketPermissionData, SocketPermission> {
+ public:
+ struct CheckParam : APIPermission::CheckParam {
+ CheckParam(content::SocketPermissionRequest::OperationType type,
+ const std::string& host,
+ int port)
+ : request(type, host, port) {}
+ content::SocketPermissionRequest request;
+ };
+
+ explicit SocketPermission(const APIPermissionInfo* info);
+
+ virtual ~SocketPermission();
+
+ // Returns the localized permission messages of this permission.
+ virtual PermissionMessages GetMessages() const OVERRIDE;
+
+ private:
+ bool AddAnyHostMessage(PermissionMessages& messages) const;
+ void AddSubdomainHostMessage(PermissionMessages& messages) const;
+ void AddSpecificHostMessage(PermissionMessages& messages) const;
+ void AddNetworkListMessage(PermissionMessages& messages) const;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
diff --git a/extensions/common/permissions/socket_permission_data.cc b/extensions/common/permissions/socket_permission_data.cc
new file mode 100644
index 0000000..b679268
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_data.cc
@@ -0,0 +1,158 @@
+// 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/common/permissions/socket_permission_data.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "url/url_canon.h"
+
+namespace {
+
+using content::SocketPermissionRequest;
+using extensions::SocketPermissionData;
+
+const char kColon = ':';
+const char kInvalid[] = "invalid";
+const char kTCPConnect[] = "tcp-connect";
+const char kTCPListen[] = "tcp-listen";
+const char kUDPBind[] = "udp-bind";
+const char kUDPSendTo[] = "udp-send-to";
+const char kUDPMulticastMembership[] = "udp-multicast-membership";
+const char kResolveHost[] = "resolve-host";
+const char kResolveProxy[] = "resolve-proxy";
+const char kNetworkState[] = "network-state";
+
+SocketPermissionRequest::OperationType StringToType(const std::string& s) {
+ if (s == kTCPConnect)
+ return SocketPermissionRequest::TCP_CONNECT;
+ if (s == kTCPListen)
+ return SocketPermissionRequest::TCP_LISTEN;
+ if (s == kUDPBind)
+ return SocketPermissionRequest::UDP_BIND;
+ if (s == kUDPSendTo)
+ return SocketPermissionRequest::UDP_SEND_TO;
+ if (s == kUDPMulticastMembership)
+ return SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP;
+ if (s == kResolveHost)
+ return SocketPermissionRequest::RESOLVE_HOST;
+ if (s == kResolveProxy)
+ return SocketPermissionRequest::RESOLVE_PROXY;
+ if (s == kNetworkState)
+ return SocketPermissionRequest::NETWORK_STATE;
+ return SocketPermissionRequest::NONE;
+}
+
+const char* TypeToString(SocketPermissionRequest::OperationType type) {
+ switch (type) {
+ case SocketPermissionRequest::TCP_CONNECT:
+ return kTCPConnect;
+ case SocketPermissionRequest::TCP_LISTEN:
+ return kTCPListen;
+ case SocketPermissionRequest::UDP_BIND:
+ return kUDPBind;
+ case SocketPermissionRequest::UDP_SEND_TO:
+ return kUDPSendTo;
+ case SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP:
+ return kUDPMulticastMembership;
+ case SocketPermissionRequest::RESOLVE_HOST:
+ return kResolveHost;
+ case SocketPermissionRequest::RESOLVE_PROXY:
+ return kResolveProxy;
+ case SocketPermissionRequest::NETWORK_STATE:
+ return kNetworkState;
+ default:
+ return kInvalid;
+ }
+}
+
+} // namespace
+
+namespace extensions {
+
+SocketPermissionData::SocketPermissionData() {}
+
+SocketPermissionData::~SocketPermissionData() {}
+
+bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
+ return entry_ < rhs.entry_;
+}
+
+bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
+ return entry_ == rhs.entry_;
+}
+
+bool SocketPermissionData::Check(const APIPermission::CheckParam* param) const {
+ if (!param)
+ return false;
+ const SocketPermission::CheckParam& specific_param =
+ *static_cast<const SocketPermission::CheckParam*>(param);
+ const SocketPermissionRequest& request = specific_param.request;
+
+ return entry_.Check(request);
+}
+
+scoped_ptr<base::Value> SocketPermissionData::ToValue() const {
+ return scoped_ptr<base::Value>(new base::StringValue(GetAsString()));
+}
+
+bool SocketPermissionData::FromValue(const base::Value* value) {
+ std::string spec;
+ if (!value->GetAsString(&spec))
+ return false;
+
+ return Parse(spec);
+}
+
+SocketPermissionEntry& SocketPermissionData::entry() {
+ // Clear the spec because the caller could mutate |this|.
+ spec_.clear();
+ return entry_;
+}
+
+// TODO(ikarienator): Rewrite this method to support IPv6.
+bool SocketPermissionData::Parse(const std::string& permission) {
+ Reset();
+
+ std::vector<std::string> tokens;
+ base::SplitStringDontTrim(permission, kColon, &tokens);
+ if (tokens.empty())
+ return false;
+
+ SocketPermissionRequest::OperationType type = StringToType(tokens[0]);
+ if (type == SocketPermissionRequest::NONE)
+ return false;
+
+ tokens.erase(tokens.begin());
+ return SocketPermissionEntry::ParseHostPattern(type, tokens, &entry_);
+}
+
+const std::string& SocketPermissionData::GetAsString() const {
+ if (!spec_.empty())
+ return spec_;
+
+ spec_.reserve(64);
+ spec_.append(TypeToString(entry_.pattern().type));
+ std::string pattern = entry_.GetHostPatternAsString();
+ if (!pattern.empty()) {
+ spec_.append(1, kColon).append(pattern);
+ }
+ return spec_;
+}
+
+void SocketPermissionData::Reset() {
+ entry_ = SocketPermissionEntry();
+ spec_.clear();
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/socket_permission_data.h b/extensions/common/permissions/socket_permission_data.h
new file mode 100644
index 0000000..f227f8d
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_data.h
@@ -0,0 +1,89 @@
+// 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_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission_entry.h"
+#include "ipc/ipc_param_traits.h"
+
+namespace ipc_fuzzer {
+template <class T>
+struct FuzzTraits;
+template <class T>
+struct GenerateTraits;
+} // namespace ipc_fuzzer
+
+namespace extensions {
+
+// A pattern that can be used to match socket permission.
+// <socket-permission-pattern>
+// := <op> |
+// <op> ':' <host> |
+// <op> ':' ':' <port> |
+// <op> ':' <host> ':' <port> |
+// 'udp-multicast-membership'
+// <op> := 'tcp-connect' |
+// 'tcp-listen' |
+// 'udp-bind' |
+// 'udp-send-to' |
+// 'udp-multicast-membership' |
+// 'resolve-host' |
+// 'resolve-proxy' |
+// 'network-state'
+// <host> := '*' |
+// '*.' <anychar except '/' and '*'>+ |
+// <anychar except '/' and '*'>+
+// <port> := '*' |
+// <port number between 0 and 65535>)
+// The multicast membership permission implies a permission to any address.
+class SocketPermissionData {
+ public:
+ SocketPermissionData();
+ ~SocketPermissionData();
+
+ // operators <, == are needed by container std::set and algorithms
+ // std::set_includes and std::set_differences.
+ bool operator<(const SocketPermissionData& rhs) const;
+ bool operator==(const SocketPermissionData& rhs) const;
+
+ // Check if |param| (which must be a SocketPermissionData::CheckParam)
+ // matches the spec of |this|.
+ bool Check(const APIPermission::CheckParam* param) const;
+
+ // Convert |this| into a base::Value.
+ scoped_ptr<base::Value> ToValue() const;
+
+ // Populate |this| from a base::Value.
+ bool FromValue(const base::Value* value);
+
+ // TODO(bryeung): SocketPermissionData should be encoded as a base::Value
+ // instead of a string. Until that is done, expose these methods for
+ // testing.
+ bool ParseForTest(const std::string& permission) { return Parse(permission); }
+ const std::string& GetAsStringForTest() const { return GetAsString(); }
+
+ const SocketPermissionEntry& entry() const { return entry_; }
+
+ private:
+ // Friend so ParamTraits can serialize us.
+ friend struct IPC::ParamTraits<SocketPermissionData>;
+ friend struct ipc_fuzzer::FuzzTraits<SocketPermissionData>;
+ friend struct ipc_fuzzer::GenerateTraits<SocketPermissionData>;
+
+ SocketPermissionEntry& entry();
+
+ bool Parse(const std::string& permission);
+ const std::string& GetAsString() const;
+ void Reset();
+
+ SocketPermissionEntry entry_;
+ mutable std::string spec_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
diff --git a/extensions/common/permissions/socket_permission_entry.cc b/extensions/common/permissions/socket_permission_entry.cc
new file mode 100644
index 0000000..8c21edc
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_entry.cc
@@ -0,0 +1,226 @@
+// 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/common/permissions/socket_permission_entry.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "url/url_canon.h"
+
+namespace {
+
+using content::SocketPermissionRequest;
+
+const char kColon = ':';
+const char kDot = '.';
+const char kWildcard[] = "*";
+const int kWildcardPortNumber = 0;
+const int kInvalidPort = -1;
+
+bool StartsOrEndsWithWhitespace(const std::string& str) {
+ if (str.find_first_not_of(base::kWhitespaceASCII) != 0)
+ return true;
+ if (str.find_last_not_of(base::kWhitespaceASCII) != str.length() - 1)
+ return true;
+ return false;
+}
+
+} // namespace
+
+namespace extensions {
+
+SocketPermissionEntry::SocketPermissionEntry()
+ : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort),
+ match_subdomains_(false) {}
+
+SocketPermissionEntry::~SocketPermissionEntry() {}
+
+bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const {
+ if (pattern_.type < rhs.pattern_.type)
+ return true;
+ if (pattern_.type > rhs.pattern_.type)
+ return false;
+
+ if (pattern_.host < rhs.pattern_.host)
+ return true;
+ if (pattern_.host > rhs.pattern_.host)
+ return false;
+
+ if (match_subdomains_ < rhs.match_subdomains_)
+ return true;
+ if (match_subdomains_ > rhs.match_subdomains_)
+ return false;
+
+ if (pattern_.port < rhs.pattern_.port)
+ return true;
+ return false;
+}
+
+bool SocketPermissionEntry::operator==(const SocketPermissionEntry& rhs) const {
+ return (pattern_.type == rhs.pattern_.type) &&
+ (pattern_.host == rhs.pattern_.host) &&
+ (match_subdomains_ == rhs.match_subdomains_) &&
+ (pattern_.port == rhs.pattern_.port);
+}
+
+bool SocketPermissionEntry::Check(
+ const content::SocketPermissionRequest& request) const {
+ if (pattern_.type != request.type)
+ return false;
+
+ std::string lhost = StringToLowerASCII(request.host);
+ if (pattern_.host != lhost) {
+ if (!match_subdomains_)
+ return false;
+
+ if (!pattern_.host.empty()) {
+ // Do not wildcard part of IP address.
+ url_parse::Component component(0, lhost.length());
+ url_canon::RawCanonOutputT<char, 128> ignored_output;
+ url_canon::CanonHostInfo host_info;
+ url_canon::CanonicalizeIPAddress(
+ lhost.c_str(), component, &ignored_output, &host_info);
+ if (host_info.IsIPAddress())
+ return false;
+
+ // host should equal one or more chars + "." + host_.
+ int i = lhost.length() - pattern_.host.length();
+ if (i < 2)
+ return false;
+
+ if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0)
+ return false;
+
+ if (lhost[i - 1] != kDot)
+ return false;
+ }
+ }
+
+ if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber)
+ return false;
+
+ return true;
+}
+
+SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const {
+ return pattern_.host.empty()
+ ? SocketPermissionEntry::ANY_HOST
+ : match_subdomains_ ? SocketPermissionEntry::HOSTS_IN_DOMAINS
+ : SocketPermissionEntry::SPECIFIC_HOSTS;
+}
+
+bool SocketPermissionEntry::IsAddressBoundType() const {
+ return pattern_.type == SocketPermissionRequest::TCP_CONNECT ||
+ pattern_.type == SocketPermissionRequest::TCP_LISTEN ||
+ pattern_.type == SocketPermissionRequest::UDP_BIND ||
+ pattern_.type == SocketPermissionRequest::UDP_SEND_TO;
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+ SocketPermissionRequest::OperationType type,
+ const std::string& pattern,
+ SocketPermissionEntry* entry) {
+ std::vector<std::string> tokens;
+ base::SplitStringDontTrim(pattern, kColon, &tokens);
+ return ParseHostPattern(type, tokens, entry);
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+ SocketPermissionRequest::OperationType type,
+ const std::vector<std::string>& pattern_tokens,
+ SocketPermissionEntry* entry) {
+
+ SocketPermissionEntry result;
+
+ if (type == SocketPermissionRequest::NONE)
+ return false;
+
+ if (pattern_tokens.size() > 2)
+ return false;
+
+ result.pattern_.type = type;
+ result.pattern_.port = kWildcardPortNumber;
+ result.match_subdomains_ = true;
+
+ if (pattern_tokens.size() == 0) {
+ *entry = result;
+ return true;
+ }
+
+ // Return an error if address is specified for permissions that don't
+ // need it (such as 'resolve-host').
+ if (!result.IsAddressBoundType())
+ return false;
+
+ result.pattern_.host = pattern_tokens[0];
+ if (!result.pattern_.host.empty()) {
+ if (StartsOrEndsWithWhitespace(result.pattern_.host))
+ return false;
+ result.pattern_.host = StringToLowerASCII(result.pattern_.host);
+
+ // The first component can optionally be '*' to match all subdomains.
+ std::vector<std::string> host_components;
+ base::SplitString(result.pattern_.host, kDot, &host_components);
+ DCHECK(!host_components.empty());
+
+ if (host_components[0] == kWildcard || host_components[0].empty()) {
+ host_components.erase(host_components.begin(),
+ host_components.begin() + 1);
+ } else {
+ result.match_subdomains_ = false;
+ }
+ result.pattern_.host = JoinString(host_components, kDot);
+ }
+
+ if (pattern_tokens.size() == 1 || pattern_tokens[1].empty() ||
+ pattern_tokens[1] == kWildcard) {
+ *entry = result;
+ return true;
+ }
+
+ if (StartsOrEndsWithWhitespace(pattern_tokens[1]))
+ return false;
+
+ if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) ||
+ result.pattern_.port < 1 || result.pattern_.port > 65535)
+ return false;
+
+ *entry = result;
+ return true;
+}
+
+std::string SocketPermissionEntry::GetHostPatternAsString() const {
+ std::string result;
+
+ if (!IsAddressBoundType())
+ return result;
+
+ if (match_subdomains()) {
+ result.append(kWildcard);
+ if (!pattern_.host.empty())
+ result.append(1, kDot).append(pattern_.host);
+ } else {
+ result.append(pattern_.host);
+ }
+
+ if (pattern_.port == kWildcardPortNumber)
+ result.append(1, kColon).append(kWildcard);
+ else
+ result.append(1, kColon).append(base::IntToString(pattern_.port));
+
+ return result;
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/socket_permission_entry.h b/extensions/common/permissions/socket_permission_entry.h
new file mode 100644
index 0000000..ee4e212
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_entry.h
@@ -0,0 +1,84 @@
+// 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_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "content/public/common/socket_permission_request.h"
+#include "ipc/ipc_param_traits.h"
+
+namespace ipc_fuzzer {
+template <class T>
+struct FuzzTraits;
+template <class T>
+struct GenerateTraits;
+} // namespace ipc_fuzzer
+
+namespace extensions {
+
+// Internal representation of a socket permission for a specific operation, such
+// as UDP "bind", host 127.0.0.1, port *.
+class SocketPermissionEntry {
+ public:
+ enum HostType { ANY_HOST, HOSTS_IN_DOMAINS, SPECIFIC_HOSTS, };
+
+ SocketPermissionEntry();
+ ~SocketPermissionEntry();
+
+ // operators <, == are needed by container std::set and algorithms
+ // std::set_includes and std::set_differences.
+ bool operator<(const SocketPermissionEntry& rhs) const;
+ bool operator==(const SocketPermissionEntry& rhs) const;
+
+ bool Check(const content::SocketPermissionRequest& request) const;
+
+ // Parse a host:port pattern for a given operation type.
+ // <pattern> := '' |
+ // <host> |
+ // ':' <port> |
+ // <host> ':' <port> |
+ //
+ // <host> := '*' |
+ // '*.' <anychar except '/' and '*'>+ |
+ // <anychar except '/' and '*'>+
+ //
+ // <port> := '*' |
+ // <port number between 0 and 65535>)
+ static bool ParseHostPattern(
+ content::SocketPermissionRequest::OperationType type,
+ const std::string& pattern,
+ SocketPermissionEntry* entry);
+
+ static bool ParseHostPattern(
+ content::SocketPermissionRequest::OperationType type,
+ const std::vector<std::string>& pattern_tokens,
+ SocketPermissionEntry* entry);
+
+ // Returns true if the permission type can be bound to a host or port.
+ bool IsAddressBoundType() const;
+
+ std::string GetHostPatternAsString() const;
+ HostType GetHostType() const;
+
+ const content::SocketPermissionRequest& pattern() const { return pattern_; }
+ bool match_subdomains() const { return match_subdomains_; }
+
+ private:
+ // Friend so ParamTraits can serialize us.
+ friend struct IPC::ParamTraits<SocketPermissionEntry>;
+ friend struct ipc_fuzzer::FuzzTraits<SocketPermissionEntry>;
+ friend struct ipc_fuzzer::GenerateTraits<SocketPermissionEntry>;
+
+ // The permission type, host and port.
+ content::SocketPermissionRequest pattern_;
+
+ // True if there was a wildcard in the host name.
+ bool match_subdomains_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
diff --git a/extensions/common/permissions/usb_device_permission.cc b/extensions/common/permissions/usb_device_permission.cc
new file mode 100644
index 0000000..c381b89a
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission.cc
@@ -0,0 +1,74 @@
+// 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/common/permissions/usb_device_permission.h"
+
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(ENABLE_EXTENSIONS)
+#include "device/usb/usb_ids.h"
+#endif
+
+namespace extensions {
+
+UsbDevicePermission::UsbDevicePermission(
+ const APIPermissionInfo* info)
+ : SetDisjunctionPermission<UsbDevicePermissionData,
+ UsbDevicePermission>(info) {
+}
+
+UsbDevicePermission::~UsbDevicePermission() {
+}
+
+PermissionMessages UsbDevicePermission::GetMessages() const {
+ DCHECK(HasMessages());
+ PermissionMessages result;
+
+#if defined(ENABLE_EXTENSIONS)
+ // //device/usb/usb.gyp:device_usb is not available when extensions are
+ // disabled.
+ for (std::set<UsbDevicePermissionData>::const_iterator i =
+ data_set_.begin(); i != data_set_.end(); ++i) {
+ const char* vendor = device::UsbIds::GetVendorName(i->vendor_id());
+
+ if (vendor) {
+ const char* product =
+ device::UsbIds::GetProductName(i->vendor_id(), i->product_id());
+ if (product) {
+ result.push_back(PermissionMessage(
+ PermissionMessage::kUsbDevice,
+ l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE,
+ base::ASCIIToUTF16(product),
+ base::ASCIIToUTF16(vendor))));
+ } else {
+ result.push_back(PermissionMessage(
+ PermissionMessage::kUsbDevice,
+ l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_PRODUCT,
+ base::ASCIIToUTF16(vendor))));
+ }
+ } else {
+ result.push_back(PermissionMessage(
+ PermissionMessage::kUsbDevice,
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_VENDOR)));
+ }
+ }
+#else
+ NOTREACHED();
+#endif // defined(ENABLE_EXTENSIONS)
+
+ return result;
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/usb_device_permission.h b/extensions/common/permissions/usb_device_permission.h
new file mode 100644
index 0000000..7f6b52a
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission.h
@@ -0,0 +1,38 @@
+// 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_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
+
+#include "base/basictypes.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "extensions/common/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, int interface_id)
+ : vendor_id(vendor_id),
+ product_id(product_id),
+ interface_id(interface_id) {}
+ const uint16 vendor_id;
+ const uint16 product_id;
+ const int interface_id;
+ };
+
+ explicit UsbDevicePermission(const APIPermissionInfo* info);
+ virtual ~UsbDevicePermission();
+
+ // APIPermission overrides
+ virtual PermissionMessages GetMessages() const OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc
new file mode 100644
index 0000000..532886d
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission_data.cc
@@ -0,0 +1,109 @@
+// 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/common/permissions/usb_device_permission_data.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/values.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/usb_device_permission.h"
+
+namespace {
+
+const char* kProductIdKey = "productId";
+const char* kVendorIdKey = "vendorId";
+const char* kInterfaceIdKey = "interfaceId";
+
+} // namespace
+
+namespace extensions {
+
+UsbDevicePermissionData::UsbDevicePermissionData()
+ : vendor_id_(0), product_id_(0), interface_id_(ANY_INTERFACE) {
+}
+
+UsbDevicePermissionData::UsbDevicePermissionData(uint16 vendor_id,
+ uint16 product_id,
+ int interface_id)
+ : vendor_id_(vendor_id),
+ product_id_(product_id),
+ interface_id_(interface_id) {
+}
+
+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 &&
+ (specific_param.interface_id == UNSPECIFIED_INTERFACE ||
+ interface_id_ == specific_param.interface_id);
+}
+
+scoped_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
+ base::DictionaryValue* result = new base::DictionaryValue();
+ result->SetInteger(kVendorIdKey, vendor_id_);
+ result->SetInteger(kProductIdKey, product_id_);
+ result->SetInteger(kInterfaceIdKey, interface_id_);
+ return scoped_ptr<base::Value>(result);
+}
+
+bool UsbDevicePermissionData::FromValue(const base::Value* value) {
+ if (!value)
+ return false;
+
+ const base::DictionaryValue* dict_value;
+ if (!value->GetAsDictionary(&dict_value))
+ return false;
+
+ int temp;
+ if (!dict_value->GetInteger(kVendorIdKey, &temp))
+ return false;
+ if (temp < 0 || temp > kuint16max)
+ return false;
+ vendor_id_ = temp;
+
+ if (!dict_value->GetInteger(kProductIdKey, &temp))
+ return false;
+ if (temp < 0 || temp > kuint16max)
+ return false;
+ product_id_ = temp;
+
+ if (!dict_value->GetInteger(kInterfaceIdKey, &temp))
+ interface_id_ = ANY_INTERFACE;
+ else if (temp < ANY_INTERFACE || temp > kuint8max)
+ return false;
+ else
+ interface_id_ = temp;
+
+ return true;
+}
+
+bool UsbDevicePermissionData::operator<(
+ const UsbDevicePermissionData& rhs) const {
+ if (vendor_id_ == rhs.vendor_id_) {
+ if (product_id_ == rhs.product_id_)
+ return interface_id_ < rhs.interface_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_ &&
+ interface_id_ == rhs.interface_id_;
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/usb_device_permission_data.h b/extensions/common/permissions/usb_device_permission_data.h
new file mode 100644
index 0000000..001b12c
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission_data.h
@@ -0,0 +1,71 @@
+// 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_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "extensions/common/permissions/api_permission.h"
+
+namespace base {
+
+class Value;
+
+} // namespace base
+
+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:
+ enum SpecialInterfaces {
+ // A special interface id for stating permissions for an entire USB device,
+ // no specific interface. This value must match value of Rule::ANY_INTERFACE
+ // from ChromeOS permission_broker project.
+ ANY_INTERFACE = -1,
+
+ // A special interface id for |Check| to indicate that interface field is
+ // not to be checked. Not used in manifest file.
+ UNSPECIFIED_INTERFACE = -2
+ };
+
+ UsbDevicePermissionData();
+ UsbDevicePermissionData(uint16 vendor_id,
+ uint16 product_id,
+ int interface_id);
+
+ // Check if |param| (which must be a UsbDevicePermissionData::CheckParam)
+ // matches the vendor and product IDs associated with |this|.
+ bool Check(const APIPermission::CheckParam* param) const;
+
+ // Convert |this| into a base::Value.
+ scoped_ptr<base::Value> ToValue() const;
+
+ // Populate |this| from a base::Value.
+ bool FromValue(const base::Value* value);
+
+ bool operator<(const UsbDevicePermissionData& rhs) const;
+ bool operator==(const UsbDevicePermissionData& rhs) const;
+
+ const uint16& vendor_id() const { return vendor_id_; }
+ const uint16& product_id() const { return product_id_; }
+
+ // These accessors are provided for IPC_STRUCT_TRAITS_MEMBER. Please
+ // think twice before using them for anything else.
+ uint16& vendor_id() { return vendor_id_; }
+ uint16& product_id() { return product_id_; }
+
+ private:
+ uint16 vendor_id_;
+ uint16 product_id_;
+ int interface_id_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index f64f675..2da4dc4 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -28,6 +28,7 @@
'<(INTERMEDIATE_DIR)',
],
'sources': [
+ 'common/api/messaging/message.h',
'common/common_manifest_handlers.cc',
'common/common_manifest_handlers.h',
'common/crx_file.cc',
@@ -112,10 +113,16 @@
'common/permissions/manifest_permission.h',
'common/permissions/manifest_permission_set.cc',
'common/permissions/manifest_permission_set.h',
+ 'common/permissions/media_galleries_permission.cc',
+ 'common/permissions/media_galleries_permission.h',
+ 'common/permissions/media_galleries_permission_data.cc',
+ 'common/permissions/media_galleries_permission_data.h',
'common/permissions/permission_message.cc',
'common/permissions/permission_message.h',
'common/permissions/permission_message_provider.cc',
'common/permissions/permission_message_provider.h',
+ 'common/permissions/permission_message_util.cc',
+ 'common/permissions/permission_message_util.h',
'common/permissions/permission_set.cc',
'common/permissions/permission_set.h',
'common/permissions/permissions_data.cc',
@@ -123,6 +130,19 @@
'common/permissions/permissions_info.cc',
'common/permissions/permissions_info.h',
'common/permissions/permissions_provider.h',
+ 'common/permissions/set_disjunction_permission.h',
+ 'common/permissions/settings_override_permission.cc',
+ 'common/permissions/settings_override_permission.h',
+ 'common/permissions/socket_permission.cc',
+ 'common/permissions/socket_permission.h',
+ 'common/permissions/socket_permission_data.cc',
+ 'common/permissions/socket_permission_data.h',
+ 'common/permissions/socket_permission_entry.cc',
+ 'common/permissions/socket_permission_entry.h',
+ 'common/permissions/usb_device_permission.cc',
+ 'common/permissions/usb_device_permission.h',
+ 'common/permissions/usb_device_permission_data.cc',
+ 'common/permissions/usb_device_permission_data.h',
'common/stack_frame.cc',
'common/stack_frame.h',
'common/switches.cc',