Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Unified Diff: chrome/common/extensions/api/sockets/sockets_manifest_permission.cc

Issue 51433002: Enable permission warnings from ManifestHandlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address code review feedback. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/api/sockets/sockets_manifest_permission.cc
diff --git a/chrome/common/extensions/api/sockets/sockets_manifest_permission.cc b/chrome/common/extensions/api/sockets/sockets_manifest_permission.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eafa3494a4eaa2ad62c4b3906715d918f6e385cd
--- /dev/null
+++ b/chrome/common/extensions/api/sockets/sockets_manifest_permission.cc
@@ -0,0 +1,362 @@
+// Copyright 2013 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/api/sockets/sockets_manifest_permission.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/extensions/api/manifest_types.h"
+#include "chrome/common/extensions/api/sockets/sockets_manifest_data.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest_constants.h"
+#include "grit/generated_resources.h"
+#include "ipc/ipc_message.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+namespace sockets_errors {
+const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
+}
+
+namespace errors = sockets_errors;
+using api::manifest_types::Sockets;
+using content::SocketPermissionRequest;
+
+SocketsManifestPermission::SocketsManifestPermission()
+ : kinds_(kNone) {
+}
+
+SocketsManifestPermission::~SocketsManifestPermission() {}
+
+// static
+scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
+ const base::Value& value,
+ std::vector<InstallWarning>* install_warnings,
Yoyo Zhou 2013/11/14 00:26:55 You don't use this at all.
+ string16* error) {
+ scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
+ if (!sockets)
+ return scoped_ptr<SocketsManifestPermission>();
+
+ scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
+ if (sockets->udp) {
+ result->kinds_ |= kUdpPermission;
+ if (!ParseHostPattern(result.get(),
+ SocketPermissionRequest::UDP_BIND,
+ sockets->udp->bind,
+ error)) {
+ return scoped_ptr<SocketsManifestPermission>();
+ }
+ if (!ParseHostPattern(result.get(),
+ SocketPermissionRequest::UDP_SEND_TO,
+ sockets->udp->send,
+ error)) {
+ return scoped_ptr<SocketsManifestPermission>();
+ }
+ if (!ParseHostPattern(result.get(),
+ SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
+ sockets->udp->multicast_membership,
+ error)) {
+ return scoped_ptr<SocketsManifestPermission>();
+ }
+ }
+ if (sockets->tcp) {
+ result->kinds_ |= kTcpPermission;
+ if (!ParseHostPattern(result.get(),
+ SocketPermissionRequest::TCP_CONNECT,
+ sockets->tcp->connect,
+ error)) {
+ return scoped_ptr<SocketsManifestPermission>();
+ }
+ }
+ if (sockets->tcp_server) {
+ result->kinds_ |= kTcpServerPermission;
+ if (!ParseHostPattern(result.get(),
+ SocketPermissionRequest::TCP_LISTEN,
+ sockets->tcp_server->listen,
+ error)) {
+ return scoped_ptr<SocketsManifestPermission>();
+ }
+ }
+ return result.Pass();
+}
+
+bool SocketsManifestPermission::CheckRequest(
+ const Extension* extension,
+ const SocketPermissionRequest& request) const {
+ for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->Check(request))
+ return true;
+ }
+ return false;
+}
+
+std::string SocketsManifestPermission::name() const {
+ return manifest_keys::kSockets;
+}
+
+std::string SocketsManifestPermission::id() const {
+ return name();
+}
+
+bool SocketsManifestPermission::HasMessages() const {
+ bool is_empty = permissions_.empty() && (kinds_ == kNone);
+ return !is_empty;
+}
+
+PermissionMessages SocketsManifestPermission::GetMessages() const {
+ // TODO(rpaquay): This function and callees is (almost) a copy/paste
+ // from |extensions::SocketPermission|.
Yoyo Zhou 2013/11/14 00:26:55 nit: no |
+ PermissionMessages result;
+ if (!AddAnyHostMessage(result)) {
+ AddSpecificHostMessage(result);
+ AddSubdomainHostMessage(result);
+ }
+ AddNetworkListMessage(result);
+ return result;
+}
+
+bool SocketsManifestPermission::FromValue(const base::Value* value) {
+ if (!value)
+ return false;
+
+ std::vector<InstallWarning> warnings;
+ string16 error;
+ scoped_ptr<SocketsManifestPermission> data(
+ SocketsManifestPermission::FromValue(*value, &warnings, &error));
+
+ if (!data)
+ return false;
+
+ permissions_ = data->permissions_;
+ kinds_ = data->kinds_;
+ return true;
+}
+
+scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
+ Sockets sockets;
+ if (has_udp()) {
+ sockets.udp.reset(new Sockets::Udp());
+ sockets.udp->bind = CreateHostPattern(SocketPermissionRequest::UDP_BIND);
+ sockets.udp->send = CreateHostPattern(SocketPermissionRequest::UDP_SEND_TO);
+ sockets.udp->multicast_membership =
+ CreateHostPattern(SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
+ }
+ if (has_tcp()) {
+ sockets.tcp.reset(new Sockets::Tcp());
+ sockets.tcp->connect =
+ CreateHostPattern(SocketPermissionRequest::TCP_CONNECT);
+ }
+ if (has_tcp_server()) {
+ sockets.tcp_server.reset(new Sockets::TcpServer());
+ sockets.tcp_server->listen =
+ CreateHostPattern(SocketPermissionRequest::TCP_LISTEN);
+ }
+
+ return sockets.ToValue().Pass();
+}
+
+ManifestPermission* SocketsManifestPermission::Clone() const {
+ scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
+ result->permissions_ = permissions_;
+ result->kinds_ = kinds_;
+ return result.release();
+}
+
+ManifestPermission* SocketsManifestPermission::Diff(
+ const ManifestPermission* rhs) const {
+ const SocketsManifestPermission* other =
+ static_cast<const SocketsManifestPermission*>(rhs);
+
+ scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
+ std::set_difference(
+ permissions_.begin(), permissions_.end(),
+ other->permissions_.begin(), other->permissions_.end(),
+ std::inserter<SocketPermissionEntrySet>(
+ data->permissions_, data->permissions_.begin()));
+
+ data->kinds_ = (kinds_ & (~other->kinds_));
+ return data.release();
+}
+
+ManifestPermission* SocketsManifestPermission::Union(
+ const ManifestPermission* rhs) const {
+ const SocketsManifestPermission* other =
+ static_cast<const SocketsManifestPermission*>(rhs);
+
+ scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
+ std::set_union(
+ permissions_.begin(), permissions_.end(),
+ other->permissions_.begin(), other->permissions_.end(),
+ std::inserter<SocketPermissionEntrySet>(
+ data->permissions_, data->permissions_.begin()));
+
+ data->kinds_ = (kinds_ | other->kinds_);
+ return data.release();
+}
+
+ManifestPermission* SocketsManifestPermission::Intersect(
+ const ManifestPermission* rhs) const {
+ const SocketsManifestPermission* other =
+ static_cast<const SocketsManifestPermission*>(rhs);
+
+ scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
+ std::set_intersection(
+ permissions_.begin(), permissions_.end(),
+ other->permissions_.begin(), other->permissions_.end(),
+ std::inserter<SocketPermissionEntrySet>(
+ data->permissions_, data->permissions_.begin()));
+
+ data->kinds_ = (kinds_ & other->kinds_);
+ return data.release();
+}
+
+bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
+ const SocketsManifestPermission* other =
+ static_cast<const SocketsManifestPermission*>(rhs);
+
+ return std::includes(
+ permissions_.begin(), permissions_.end(),
+ other->permissions_.begin(), other->permissions_.end()) &&
+ ((kinds_ | other->kinds_) == kinds_);
+}
+
+bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
+ const SocketsManifestPermission* other =
+ static_cast<const SocketsManifestPermission*>(rhs);
+
+ return (permissions_ == other->permissions_) &&
+ (kinds_ == other->kinds_);
+}
+
+void SocketsManifestPermission::Write(IPC::Message* m) const {
+ IPC::WriteParam(m, permissions_);
+ IPC::WriteParam(m, kinds_);
+}
+
+bool SocketsManifestPermission::Read(const IPC::Message* m,
+ PickleIterator* iter) {
+ return IPC::ReadParam(m, iter, &permissions_) &&
+ IPC::ReadParam(m, iter, &kinds_);
+}
+
+void SocketsManifestPermission::Log(std::string* log) const {
+ IPC::LogParam(permissions_, log);
+ IPC::LogParam(kinds_, log);
+}
+
+// static
+bool SocketsManifestPermission::ParseHostPattern(
+ SocketsManifestPermission* manifest_data,
+ SocketPermissionRequest::OperationType operation_type,
+ const scoped_ptr<std::string>& value,
+ string16* error) {
+ if (value) {
+ SocketPermissionEntry entry;
+ if (!SocketPermissionEntry::ParseHostPattern(
+ operation_type, *value, &entry)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kErrorInvalidHostPattern, *value);
+ return false;
+ }
+ manifest_data->AddPermission(entry);
+ }
+ return true;
+}
+
+scoped_ptr<std::string> SocketsManifestPermission::CreateHostPattern(
+ SocketPermissionRequest::OperationType operation_type) const {
+ scoped_ptr<std::string> result;
+ for (SocketPermissionEntrySet::const_iterator it =
+ entries().begin(); it != entries().end() ; ++it) {
+ if (it->pattern().type == operation_type) {
+ result.reset(new std::string(it->GetHostPatternAsString()));
+ break;
+ }
+ }
+ return result.Pass();
+}
+
+void SocketsManifestPermission::AddPermission(
+ const SocketPermissionEntry& entry) {
+ permissions_.insert(entry);
+}
+
+bool SocketsManifestPermission::AddAnyHostMessage(
+ PermissionMessages& messages) const {
+ for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->IsAddressBoundType() &&
+ it->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 SocketsManifestPermission::AddSubdomainHostMessage(
+ PermissionMessages& messages) const {
+ std::set<string16> domains;
+ for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
+ domains.insert(UTF8ToUTF16(it->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<string16>(
+ domains.begin(), domains.end()), ' '))));
+ }
+}
+
+void SocketsManifestPermission::AddSpecificHostMessage(
+ PermissionMessages& messages) const {
+ std::set<string16> hostnames;
+ for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
+ hostnames.insert(UTF8ToUTF16(it->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<string16>(
+ hostnames.begin(), hostnames.end()), ' '))));
+ }
+}
+
+void SocketsManifestPermission::AddNetworkListMessage(
+ PermissionMessages& messages) const {
+ for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
+ messages.push_back(PermissionMessage(
+ PermissionMessage::kNetworkState,
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
+ }
+ }
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698