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

Unified Diff: chrome/common/extensions/permissions/socket_permission_data.cc

Issue 10692160: Support socket endpoint permissions for AppsV2 Socket API. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase and fix a unit test Created 8 years, 4 months 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/permissions/socket_permission_data.cc
diff --git a/chrome/common/extensions/permissions/socket_permission_data.cc b/chrome/common/extensions/permissions/socket_permission_data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ef3c1918e5fe72c774db6750844008cf400e3766
--- /dev/null
+++ b/chrome/common/extensions/permissions/socket_permission_data.cc
@@ -0,0 +1,231 @@
+// 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/socket_permission_data.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
+#include "googleurl/src/url_canon.h"
+
+namespace {
+
+using extensions::SocketPermissionData;
+
+const char kColon = ':';
+const char kDot = '.';
+const char kWildcard[] = "*";
+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 int kAnyPort = 0;
+const int kInvalidPort = -1;
+
+SocketPermissionData::OperationType StringToType(const std::string& s) {
+ if (s == kTCPConnect)
+ return SocketPermissionData::TCP_CONNECT;
+ if (s == kTCPListen)
+ return SocketPermissionData::TCP_LISTEN;
+ if (s == kUDPBind)
+ return SocketPermissionData::UDP_BIND;
+ if (s == kUDPSendTo)
+ return SocketPermissionData::UDP_SEND_TO;
+ return SocketPermissionData::NONE;
+}
+
+const char* TypeToString(SocketPermissionData::OperationType type) {
+ switch (type) {
+ case SocketPermissionData::TCP_CONNECT:
+ return kTCPConnect;
+ case SocketPermissionData::TCP_LISTEN:
+ return kTCPListen;
+ case SocketPermissionData::UDP_BIND:
+ return kUDPBind;
+ case SocketPermissionData::UDP_SEND_TO:
+ return kUDPSendTo;
+ default:
+ return kInvalid;
+ }
+}
+
+bool StartsOrEndsWithWhitespace(const std::string& str) {
+ if (str.find_first_not_of(kWhitespaceASCII) != 0)
+ return true;
+ if (str.find_last_not_of(kWhitespaceASCII) != str.length() - 1)
+ return true;
+ return false;
+}
+
+} // namespace
+
+namespace extensions {
+
+SocketPermissionData::SocketPermissionData() {
+ Reset();
+}
+
+SocketPermissionData::~SocketPermissionData() {
+}
+
+bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
+ if (type_ < rhs.type_)
+ return true;
+ if (type_ > rhs.type_)
+ return false;
+
+ if (host_ < rhs.host_)
+ return true;
+ if (host_ > rhs.host_)
+ return false;
+
+ if (match_subdomains_ < rhs.match_subdomains_)
+ return true;
+ if (match_subdomains_ > rhs.match_subdomains_)
+ return false;
+
+ if (port_ < rhs.port_)
+ return true;
+ return false;
+}
+
+bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
+ return (type_ == rhs.type_) && (host_ == rhs.host_) &&
+ (match_subdomains_ == rhs.match_subdomains_) &&
+ (port_ == rhs.port_);
+}
+
+bool SocketPermissionData::Match(
+ OperationType type, const std::string& host, int port) const {
+ if (type_ != type)
+ return false;
+
+ std::string lhost = StringToLowerASCII(host);
+ if (host_ != lhost) {
+ if (!match_subdomains_)
+ return false;
+
+ if (!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() - host_.length();
+ if (i < 2)
+ return false;
+
+ if (lhost.compare(i, host_.length(), host_) != 0)
+ return false;
+
+ if (lhost[i - 1] != kDot)
+ return false;
+ }
+ }
+
+ if (port_ != port && port_ != kAnyPort)
+ return false;
+
+ return true;
+}
+
+bool SocketPermissionData::Parse(const std::string& permission) {
+ do {
+ host_.clear();
+ match_subdomains_ = true;
+ port_ = kAnyPort;
+ spec_.clear();
+
+ std::vector<std::string> tokens;
+ base::SplitStringDontTrim(permission, kColon, &tokens);
+
+ if (tokens.empty() || tokens.size() > 3)
+ break;
+
+ type_ = StringToType(tokens[0]);
+ if (type_ == NONE)
+ break;
+
+ if (tokens.size() == 1)
+ return true;
+
+ host_ = tokens[1];
+ if (!host_.empty()) {
+ if (StartsOrEndsWithWhitespace(host_))
+ break;
+ host_ = StringToLowerASCII(host_);
+
+ // The first component can optionally be '*' to match all subdomains.
+ std::vector<std::string> host_components;
+ base::SplitString(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 {
+ match_subdomains_ = false;
+ }
+ host_ = JoinString(host_components, kDot);
+ }
+
+ if (tokens.size() == 2 || tokens[2].empty() || tokens[2] == kWildcard)
+ return true;
+
+ if (StartsOrEndsWithWhitespace(tokens[2]))
+ break;
+
+ if (!base::StringToInt(tokens[2], &port_) ||
+ port_ < 1 || port_ > 65535)
+ break;
+ return true;
+ } while (false);
+
+ Reset();
+ return false;
+}
+
+const std::string& SocketPermissionData::GetAsString() const {
+ if (!spec_.empty())
+ return spec_;
+
+ spec_.reserve(64);
+ spec_.append(TypeToString(type_));
+
+ if (match_subdomains_) {
+ spec_.append(1, kColon).append(kWildcard);
+ if (!host_.empty())
+ spec_.append(1, kDot).append(host_);
+ } else {
+ spec_.append(1, kColon).append(host_);
+ }
+
+ if (port_ == kAnyPort)
+ spec_.append(1, kColon).append(kWildcard);
+ else
+ spec_.append(1, kColon).append(base::IntToString(port_));
+
+ return spec_;
+}
+
+void SocketPermissionData::Reset() {
+ type_ = NONE;
+ host_.clear();
+ match_subdomains_ = false;
+ port_ = kInvalidPort;
+ spec_.clear();
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698