| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/common/extensions/api/sockets/sockets_manifest_permission.h" | |
| 6 | |
| 7 #include "base/memory/scoped_ptr.h" | |
| 8 #include "base/stl_util.h" | |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 10 #include "base/values.h" | |
| 11 #include "chrome/common/extensions/api/manifest_types.h" | |
| 12 #include "chrome/common/extensions/api/sockets/sockets_manifest_data.h" | |
| 13 #include "extensions/common/error_utils.h" | |
| 14 #include "extensions/common/extension_messages.h" | |
| 15 #include "extensions/common/manifest_constants.h" | |
| 16 #include "grit/generated_resources.h" | |
| 17 #include "ipc/ipc_message.h" | |
| 18 #include "ui/base/l10n/l10n_util.h" | |
| 19 | |
| 20 namespace extensions { | |
| 21 | |
| 22 namespace sockets_errors { | |
| 23 const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'"; | |
| 24 } | |
| 25 | |
| 26 namespace errors = sockets_errors; | |
| 27 using api::manifest_types::Sockets; | |
| 28 using api::manifest_types::SocketHostPatterns; | |
| 29 using content::SocketPermissionRequest; | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 static bool ParseHostPattern( | |
| 34 SocketsManifestPermission* permission, | |
| 35 content::SocketPermissionRequest::OperationType operation_type, | |
| 36 const std::string& host_pattern, | |
| 37 base::string16* error) { | |
| 38 SocketPermissionEntry entry; | |
| 39 if (!SocketPermissionEntry::ParseHostPattern( | |
| 40 operation_type, host_pattern, &entry)) { | |
| 41 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 42 errors::kErrorInvalidHostPattern, host_pattern); | |
| 43 return false; | |
| 44 } | |
| 45 permission->AddPermission(entry); | |
| 46 return true; | |
| 47 } | |
| 48 | |
| 49 static bool ParseHostPatterns( | |
| 50 SocketsManifestPermission* permission, | |
| 51 content::SocketPermissionRequest::OperationType operation_type, | |
| 52 const scoped_ptr<SocketHostPatterns>& host_patterns, | |
| 53 base::string16* error) { | |
| 54 if (!host_patterns) | |
| 55 return true; | |
| 56 | |
| 57 if (host_patterns->as_string) { | |
| 58 return ParseHostPattern(permission, operation_type, | |
| 59 *host_patterns->as_string, error); | |
| 60 } | |
| 61 | |
| 62 CHECK(host_patterns->as_strings); | |
| 63 for (std::vector<std::string>::const_iterator it = | |
| 64 host_patterns->as_strings->begin(); | |
| 65 it != host_patterns->as_strings->end(); ++it) { | |
| 66 if (!ParseHostPattern(permission, operation_type, *it, error)) { | |
| 67 return false; | |
| 68 } | |
| 69 } | |
| 70 return true; | |
| 71 } | |
| 72 | |
| 73 static void SetHostPatterns( | |
| 74 scoped_ptr<SocketHostPatterns>& host_patterns, | |
| 75 const SocketsManifestPermission* permission, | |
| 76 content::SocketPermissionRequest::OperationType operation_type) { | |
| 77 host_patterns.reset(new SocketHostPatterns()); | |
| 78 host_patterns->as_strings.reset(new std::vector<std::string>()); | |
| 79 for (SocketsManifestPermission::SocketPermissionEntrySet::const_iterator it = | |
| 80 permission->entries().begin(); it != permission->entries().end() ; ++it) { | |
| 81 if (it->pattern().type == operation_type) { | |
| 82 host_patterns->as_strings->push_back(it->GetHostPatternAsString()); | |
| 83 } | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 } // namespace | |
| 88 | |
| 89 SocketsManifestPermission::SocketsManifestPermission() {} | |
| 90 | |
| 91 SocketsManifestPermission::~SocketsManifestPermission() {} | |
| 92 | |
| 93 // static | |
| 94 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue( | |
| 95 const base::Value& value, | |
| 96 base::string16* error) { | |
| 97 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error); | |
| 98 if (!sockets) | |
| 99 return scoped_ptr<SocketsManifestPermission>(); | |
| 100 | |
| 101 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
| 102 if (sockets->udp) { | |
| 103 if (!ParseHostPatterns(result.get(), | |
| 104 SocketPermissionRequest::UDP_BIND, | |
| 105 sockets->udp->bind, | |
| 106 error)) { | |
| 107 return scoped_ptr<SocketsManifestPermission>(); | |
| 108 } | |
| 109 if (!ParseHostPatterns(result.get(), | |
| 110 SocketPermissionRequest::UDP_SEND_TO, | |
| 111 sockets->udp->send, | |
| 112 error)) { | |
| 113 return scoped_ptr<SocketsManifestPermission>(); | |
| 114 } | |
| 115 if (!ParseHostPatterns(result.get(), | |
| 116 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
| 117 sockets->udp->multicast_membership, | |
| 118 error)) { | |
| 119 return scoped_ptr<SocketsManifestPermission>(); | |
| 120 } | |
| 121 } | |
| 122 if (sockets->tcp) { | |
| 123 if (!ParseHostPatterns(result.get(), | |
| 124 SocketPermissionRequest::TCP_CONNECT, | |
| 125 sockets->tcp->connect, | |
| 126 error)) { | |
| 127 return scoped_ptr<SocketsManifestPermission>(); | |
| 128 } | |
| 129 } | |
| 130 if (sockets->tcp_server) { | |
| 131 if (!ParseHostPatterns(result.get(), | |
| 132 SocketPermissionRequest::TCP_LISTEN, | |
| 133 sockets->tcp_server->listen, | |
| 134 error)) { | |
| 135 return scoped_ptr<SocketsManifestPermission>(); | |
| 136 } | |
| 137 } | |
| 138 return result.Pass(); | |
| 139 } | |
| 140 | |
| 141 bool SocketsManifestPermission::CheckRequest( | |
| 142 const Extension* extension, | |
| 143 const SocketPermissionRequest& request) const { | |
| 144 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
| 145 it != permissions_.end(); ++it) { | |
| 146 if (it->Check(request)) | |
| 147 return true; | |
| 148 } | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 152 std::string SocketsManifestPermission::name() const { | |
| 153 return manifest_keys::kSockets; | |
| 154 } | |
| 155 | |
| 156 std::string SocketsManifestPermission::id() const { | |
| 157 return name(); | |
| 158 } | |
| 159 | |
| 160 bool SocketsManifestPermission::HasMessages() const { | |
| 161 bool is_empty = permissions_.empty(); | |
| 162 return !is_empty; | |
| 163 } | |
| 164 | |
| 165 PermissionMessages SocketsManifestPermission::GetMessages() const { | |
| 166 // TODO(rpaquay): This function and callees is (almost) a copy/paste | |
| 167 // from extensions::SocketPermissiona. | |
| 168 PermissionMessages result; | |
| 169 if (!AddAnyHostMessage(result)) { | |
| 170 AddSpecificHostMessage(result); | |
| 171 AddSubdomainHostMessage(result); | |
| 172 } | |
| 173 AddNetworkListMessage(result); | |
| 174 return result; | |
| 175 } | |
| 176 | |
| 177 bool SocketsManifestPermission::FromValue(const base::Value* value) { | |
| 178 if (!value) | |
| 179 return false; | |
| 180 base::string16 error; | |
| 181 scoped_ptr<SocketsManifestPermission> manifest_permission( | |
| 182 SocketsManifestPermission::FromValue(*value, &error)); | |
| 183 | |
| 184 if (!manifest_permission) | |
| 185 return false; | |
| 186 | |
| 187 permissions_ = manifest_permission->permissions_; | |
| 188 return true; | |
| 189 } | |
| 190 | |
| 191 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const { | |
| 192 Sockets sockets; | |
| 193 | |
| 194 sockets.udp.reset(new Sockets::Udp()); | |
| 195 SetHostPatterns(sockets.udp->bind, this, | |
| 196 SocketPermissionRequest::UDP_BIND); | |
| 197 SetHostPatterns(sockets.udp->send, this, | |
| 198 SocketPermissionRequest::UDP_SEND_TO); | |
| 199 SetHostPatterns(sockets.udp->multicast_membership, this, | |
| 200 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP); | |
| 201 if (sockets.udp->bind->as_strings->size() == 0 && | |
| 202 sockets.udp->send->as_strings->size() == 0 && | |
| 203 sockets.udp->multicast_membership->as_strings->size() == 0) { | |
| 204 sockets.udp.reset(NULL); | |
| 205 } | |
| 206 | |
| 207 sockets.tcp.reset(new Sockets::Tcp()); | |
| 208 SetHostPatterns(sockets.tcp->connect, this, | |
| 209 SocketPermissionRequest::TCP_CONNECT); | |
| 210 if (sockets.tcp->connect->as_strings->size() == 0) { | |
| 211 sockets.tcp.reset(NULL); | |
| 212 } | |
| 213 | |
| 214 sockets.tcp_server.reset(new Sockets::TcpServer()); | |
| 215 SetHostPatterns(sockets.tcp_server->listen, this, | |
| 216 SocketPermissionRequest::TCP_LISTEN); | |
| 217 if (sockets.tcp_server->listen->as_strings->size() == 0) { | |
| 218 sockets.tcp_server.reset(NULL); | |
| 219 } | |
| 220 | |
| 221 return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass(); | |
| 222 } | |
| 223 | |
| 224 ManifestPermission* SocketsManifestPermission::Clone() const { | |
| 225 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
| 226 result->permissions_ = permissions_; | |
| 227 return result.release(); | |
| 228 } | |
| 229 | |
| 230 ManifestPermission* SocketsManifestPermission::Diff( | |
| 231 const ManifestPermission* rhs) const { | |
| 232 const SocketsManifestPermission* other = | |
| 233 static_cast<const SocketsManifestPermission*>(rhs); | |
| 234 | |
| 235 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
| 236 result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>( | |
| 237 permissions_, other->permissions_); | |
| 238 return result.release(); | |
| 239 } | |
| 240 | |
| 241 ManifestPermission* SocketsManifestPermission::Union( | |
| 242 const ManifestPermission* rhs) const { | |
| 243 const SocketsManifestPermission* other = | |
| 244 static_cast<const SocketsManifestPermission*>(rhs); | |
| 245 | |
| 246 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
| 247 result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>( | |
| 248 permissions_, other->permissions_); | |
| 249 return result.release(); | |
| 250 } | |
| 251 | |
| 252 ManifestPermission* SocketsManifestPermission::Intersect( | |
| 253 const ManifestPermission* rhs) const { | |
| 254 const SocketsManifestPermission* other = | |
| 255 static_cast<const SocketsManifestPermission*>(rhs); | |
| 256 | |
| 257 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
| 258 result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>( | |
| 259 permissions_, other->permissions_); | |
| 260 return result.release(); | |
| 261 } | |
| 262 | |
| 263 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const { | |
| 264 const SocketsManifestPermission* other = | |
| 265 static_cast<const SocketsManifestPermission*>(rhs); | |
| 266 | |
| 267 return base::STLIncludes<SocketPermissionEntrySet>(permissions_, | |
| 268 other->permissions_); | |
| 269 } | |
| 270 | |
| 271 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const { | |
| 272 const SocketsManifestPermission* other = | |
| 273 static_cast<const SocketsManifestPermission*>(rhs); | |
| 274 | |
| 275 return (permissions_ == other->permissions_); | |
| 276 } | |
| 277 | |
| 278 void SocketsManifestPermission::Write(IPC::Message* m) const { | |
| 279 IPC::WriteParam(m, permissions_); | |
| 280 } | |
| 281 | |
| 282 bool SocketsManifestPermission::Read(const IPC::Message* m, | |
| 283 PickleIterator* iter) { | |
| 284 return IPC::ReadParam(m, iter, &permissions_); | |
| 285 } | |
| 286 | |
| 287 void SocketsManifestPermission::Log(std::string* log) const { | |
| 288 IPC::LogParam(permissions_, log); | |
| 289 } | |
| 290 | |
| 291 void SocketsManifestPermission::AddPermission( | |
| 292 const SocketPermissionEntry& entry) { | |
| 293 permissions_.insert(entry); | |
| 294 } | |
| 295 | |
| 296 bool SocketsManifestPermission::AddAnyHostMessage( | |
| 297 PermissionMessages& messages) const { | |
| 298 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
| 299 it != permissions_.end(); ++it) { | |
| 300 if (it->IsAddressBoundType() && | |
| 301 it->GetHostType() == SocketPermissionEntry::ANY_HOST) { | |
| 302 messages.push_back(PermissionMessage( | |
| 303 PermissionMessage::kSocketAnyHost, | |
| 304 l10n_util::GetStringUTF16( | |
| 305 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST))); | |
| 306 return true; | |
| 307 } | |
| 308 } | |
| 309 return false; | |
| 310 } | |
| 311 | |
| 312 void SocketsManifestPermission::AddSubdomainHostMessage( | |
| 313 PermissionMessages& messages) const { | |
| 314 std::set<base::string16> domains; | |
| 315 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
| 316 it != permissions_.end(); ++it) { | |
| 317 if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS) | |
| 318 domains.insert(base::UTF8ToUTF16(it->pattern().host)); | |
| 319 } | |
| 320 if (!domains.empty()) { | |
| 321 int id = (domains.size() == 1) ? | |
| 322 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN : | |
| 323 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS; | |
| 324 messages.push_back(PermissionMessage( | |
| 325 PermissionMessage::kSocketDomainHosts, | |
| 326 l10n_util::GetStringFUTF16( | |
| 327 id, | |
| 328 JoinString( | |
| 329 std::vector<base::string16>( | |
| 330 domains.begin(), domains.end()), ' ')))); | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 void SocketsManifestPermission::AddSpecificHostMessage( | |
| 335 PermissionMessages& messages) const { | |
| 336 std::set<base::string16> hostnames; | |
| 337 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
| 338 it != permissions_.end(); ++it) { | |
| 339 if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS) | |
| 340 hostnames.insert(base::UTF8ToUTF16(it->pattern().host)); | |
| 341 } | |
| 342 if (!hostnames.empty()) { | |
| 343 int id = (hostnames.size() == 1) ? | |
| 344 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST : | |
| 345 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS; | |
| 346 messages.push_back(PermissionMessage( | |
| 347 PermissionMessage::kSocketSpecificHosts, | |
| 348 l10n_util::GetStringFUTF16( | |
| 349 id, | |
| 350 JoinString( | |
| 351 std::vector<base::string16>( | |
| 352 hostnames.begin(), hostnames.end()), ' ')))); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 void SocketsManifestPermission::AddNetworkListMessage( | |
| 357 PermissionMessages& messages) const { | |
| 358 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
| 359 it != permissions_.end(); ++it) { | |
| 360 if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) { | |
| 361 messages.push_back(PermissionMessage( | |
| 362 PermissionMessage::kNetworkState, | |
| 363 l10n_util::GetStringUTF16( | |
| 364 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE))); | |
| 365 } | |
| 366 } | |
| 367 } | |
| 368 | |
| 369 } // namespace extensions | |
| OLD | NEW |