1 // Copyright (c) 2012 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/browser/extensions/api/permissions/permissions_api_helpers.h" 6 7 #include "base/json/json_reader.h" 8 #include "base/json/json_writer.h" 9 #include "base/values.h" 10 #include "chrome/common/extensions/api/permissions.h" 11 #include "chrome/common/extensions/permissions/usb_device_permission.h" 12 #include "extensions/common/error_utils.h" 13 #include "extensions/common/extension.h" 14 #include "extensions/common/permissions/permission_set.h" 15 #include "extensions/common/permissions/permissions_info.h" 16 #include "extensions/common/url_pattern_set.h" 17 18 using extensions::APIPermission; 19 using extensions::PermissionSet; 20 using extensions::PermissionsInfo; 21 22 namespace extensions { 23 24 using api::permissions::Permissions; 25 26 namespace permissions_api_helpers { 27 28 namespace { 29 30 const char kDelimiter[] = "|"; 31 const char kInvalidParameter[] = 32 "Invalid argument for permission '*'."; 33 const char kInvalidOrigin[] = 34 "Invalid value for origin pattern *: *"; 35 const char kUnknownPermissionError[] = 36 "'*' is not a recognized permission."; 37 const char kUnsupportedPermissionId[] = 38 "Only the usbDevices permission supports arguments."; 39 40 } // namespace 41 42 scoped_ptr<Permissions> PackPermissionSet(const PermissionSet* set) { 43 Permissions* permissions(new Permissions()); 44 45 permissions->permissions.reset(new std::vector<std::string>()); 46 for (APIPermissionSet::const_iterator i = set->apis().begin(); 47 i != set->apis().end(); ++i) { 48 scoped_ptr<base::Value> value(i->ToValue()); 49 if (!value) { 50 permissions->permissions->push_back(i->name()); 51 } else { 52 std::string name(i->name()); 53 std::string json; 54 base::JSONWriter::Write(value.get(), &json); 55 permissions->permissions->push_back(name + kDelimiter + json); 56 } 57 } 58 59 // TODO(rpaquay): We currently don't expose manifest permissions 60 // to apps/extensions via the permissions API. 61 62 permissions->origins.reset(new std::vector<std::string>()); 63 URLPatternSet hosts = set->explicit_hosts(); 64 for (URLPatternSet::const_iterator i = hosts.begin(); i != hosts.end(); ++i) 65 permissions->origins->push_back(i->GetAsString()); 66 67 return scoped_ptr<Permissions>(permissions); 68 } 69 70 scoped_refptr<PermissionSet> UnpackPermissionSet( 71 const Permissions& permissions, 72 bool allow_file_access, 73 std::string* error) { 74 APIPermissionSet apis; 75 std::vector<std::string>* permissions_list = permissions.permissions.get(); 76 if (permissions_list) { 77 PermissionsInfo* info = PermissionsInfo::GetInstance(); 78 for (std::vector<std::string>::iterator it = permissions_list->begin(); 79 it != permissions_list->end(); ++it) { 80 // This is a compromise: we currently can't switch to a blend of 81 // objects/strings all the way through the API. Until then, put this 82 // processing here. 83 // http://code.google.com/p/chromium/issues/detail?id=162042 84 if (it->find(kDelimiter) != std::string::npos) { 85 size_t delimiter = it->find(kDelimiter); 86 std::string permission_name = it->substr(0, delimiter); 87 std::string permission_arg = it->substr(delimiter + 1); 88 89 scoped_ptr<base::Value> permission_json( 90 base::JSONReader::Read(permission_arg)); 91 if (!permission_json.get()) { 92 *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); 93 return NULL; 94 } 95 96 APIPermission* permission = NULL; 97 98 // Explicitly check the permissions that accept arguments until the bug 99 // referenced above is fixed. 100 const APIPermissionInfo* usb_device_permission_info = 101 info->GetByID(APIPermission::kUsbDevice); 102 if (permission_name == usb_device_permission_info->name()) { 103 permission = new UsbDevicePermission(usb_device_permission_info); 104 } else { 105 *error = kUnsupportedPermissionId; 106 return NULL; 107 } 108 109 CHECK(permission); 110 if (!permission->FromValue(permission_json.get())) { 111 *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); 112 return NULL; 113 } 114 apis.insert(permission); 115 } else { 116 const APIPermissionInfo* permission_info = info->GetByName(*it); 117 if (!permission_info) { 118 *error = ErrorUtils::FormatErrorMessage( 119 kUnknownPermissionError, *it); 120 return NULL; 121 } 122 apis.insert(permission_info->id()); 123 } 124 } 125 } 126 127 // TODO(rpaquay): We currently don't expose manifest permissions 128 // to apps/extensions via the permissions API. 129 ManifestPermissionSet manifest_permissions; 130 131 URLPatternSet origins; 132 if (permissions.origins.get()) { 133 for (std::vector<std::string>::iterator it = permissions.origins->begin(); 134 it != permissions.origins->end(); ++it) { 135 int allowed_schemes = Extension::kValidHostPermissionSchemes; 136 if (!allow_file_access) 137 allowed_schemes &= ~URLPattern::SCHEME_FILE; 138 URLPattern origin(allowed_schemes); 139 URLPattern::ParseResult parse_result = origin.Parse(*it); 140 if (URLPattern::PARSE_SUCCESS != parse_result) { 141 *error = ErrorUtils::FormatErrorMessage( 142 kInvalidOrigin, 143 *it, 144 URLPattern::GetParseResultString(parse_result)); 145 return NULL; 146 } 147 origins.AddPattern(origin); 148 } 149 } 150 151 return scoped_refptr<PermissionSet>( 152 new PermissionSet(apis, manifest_permissions, origins, URLPatternSet())); 153 } 154 155 } // namespace permissions_api_helpers 156 } // namespace extensions 157