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/extension.h" 12 #include "chrome/common/extensions/permissions/permission_set.h" 13 #include "chrome/common/extensions/permissions/permissions_info.h" 14 #include "chrome/common/extensions/permissions/usb_device_permission.h" 15 #include "extensions/common/error_utils.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 permissions->origins.reset(new std::vector<std::string>()); 60 URLPatternSet hosts = set->explicit_hosts(); 61 for (URLPatternSet::const_iterator i = hosts.begin(); i != hosts.end(); ++i) 62 permissions->origins->push_back(i->GetAsString()); 63 64 return scoped_ptr<Permissions>(permissions); 65 } 66 67 scoped_refptr<PermissionSet> UnpackPermissionSet( 68 const Permissions& permissions, 69 bool allow_file_access, 70 std::string* error) { 71 APIPermissionSet apis; 72 std::vector<std::string>* permissions_list = permissions.permissions.get(); 73 if (permissions_list) { 74 PermissionsInfo* info = PermissionsInfo::GetInstance(); 75 for (std::vector<std::string>::iterator it = permissions_list->begin(); 76 it != permissions_list->end(); ++it) { 77 // This is a compromise: we currently can't switch to a blend of 78 // objects/strings all the way through the API. Until then, put this 79 // processing here. 80 // http://code.google.com/p/chromium/issues/detail?id=162042 81 if (it->find(kDelimiter) != std::string::npos) { 82 size_t delimiter = it->find(kDelimiter); 83 std::string permission_name = it->substr(0, delimiter); 84 std::string permission_arg = it->substr(delimiter + 1); 85 86 scoped_ptr<base::Value> permission_json( 87 base::JSONReader::Read(permission_arg)); 88 if (!permission_json.get()) { 89 *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); 90 return NULL; 91 } 92 93 APIPermission* permission = NULL; 94 95 // Explicitly check the permissions that accept arguments until the bug 96 // referenced above is fixed. 97 const APIPermissionInfo* usb_device_permission_info = 98 info->GetByID(APIPermission::kUsbDevice); 99 if (permission_name == usb_device_permission_info->name()) { 100 permission = new UsbDevicePermission(usb_device_permission_info); 101 } else { 102 *error = kUnsupportedPermissionId; 103 return NULL; 104 } 105 106 CHECK(permission); 107 if (!permission->FromValue(permission_json.get())) { 108 *error = ErrorUtils::FormatErrorMessage(kInvalidParameter, *it); 109 return NULL; 110 } 111 apis.insert(permission); 112 } else { 113 const APIPermissionInfo* permission_info = info->GetByName(*it); 114 if (!permission_info) { 115 *error = ErrorUtils::FormatErrorMessage( 116 kUnknownPermissionError, *it); 117 return NULL; 118 } 119 apis.insert(permission_info->id()); 120 } 121 } 122 } 123 124 URLPatternSet origins; 125 if (permissions.origins.get()) { 126 for (std::vector<std::string>::iterator it = permissions.origins->begin(); 127 it != permissions.origins->end(); ++it) { 128 int allowed_schemes = Extension::kValidHostPermissionSchemes; 129 if (!allow_file_access) 130 allowed_schemes &= ~URLPattern::SCHEME_FILE; 131 URLPattern origin(allowed_schemes); 132 URLPattern::ParseResult parse_result = origin.Parse(*it); 133 if (URLPattern::PARSE_SUCCESS != parse_result) { 134 *error = ErrorUtils::FormatErrorMessage( 135 kInvalidOrigin, 136 *it, 137 URLPattern::GetParseResultString(parse_result)); 138 return NULL; 139 } 140 origins.AddPattern(origin); 141 } 142 } 143 144 return scoped_refptr<PermissionSet>( 145 new PermissionSet(apis, origins, URLPatternSet())); 146 } 147 148 } // namespace permissions_api 149 } // namespace extensions 150