| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 #include "chrome/common/extensions/features/feature.h" | 40 #include "chrome/common/extensions/features/feature.h" |
| 41 #include "chrome/common/extensions/manifest.h" | 41 #include "chrome/common/extensions/manifest.h" |
| 42 #include "chrome/common/extensions/manifest_handler.h" | 42 #include "chrome/common/extensions/manifest_handler.h" |
| 43 #include "chrome/common/extensions/manifest_handler_helpers.h" | 43 #include "chrome/common/extensions/manifest_handler_helpers.h" |
| 44 #include "chrome/common/extensions/manifest_url_handler.h" | 44 #include "chrome/common/extensions/manifest_url_handler.h" |
| 45 #include "chrome/common/extensions/permissions/api_permission_set.h" | 45 #include "chrome/common/extensions/permissions/api_permission_set.h" |
| 46 #include "chrome/common/extensions/permissions/permission_set.h" | 46 #include "chrome/common/extensions/permissions/permission_set.h" |
| 47 #include "chrome/common/extensions/permissions/permissions_info.h" | 47 #include "chrome/common/extensions/permissions/permissions_info.h" |
| 48 #include "chrome/common/extensions/user_script.h" | 48 #include "chrome/common/extensions/user_script.h" |
| 49 #include "chrome/common/url_constants.h" | 49 #include "chrome/common/url_constants.h" |
| 50 #include "crypto/sha2.h" | |
| 51 #include "extensions/common/constants.h" | 50 #include "extensions/common/constants.h" |
| 52 #include "extensions/common/error_utils.h" | 51 #include "extensions/common/error_utils.h" |
| 52 #include "extensions/common/id_util.h" |
| 53 #include "extensions/common/url_pattern_set.h" | 53 #include "extensions/common/url_pattern_set.h" |
| 54 #include "googleurl/src/url_util.h" | 54 #include "googleurl/src/url_util.h" |
| 55 #include "grit/chromium_strings.h" | 55 #include "grit/chromium_strings.h" |
| 56 #include "grit/theme_resources.h" | 56 #include "grit/theme_resources.h" |
| 57 #include "third_party/skia/include/core/SkBitmap.h" | 57 #include "third_party/skia/include/core/SkBitmap.h" |
| 58 #include "ui/base/l10n/l10n_util.h" | 58 #include "ui/base/l10n/l10n_util.h" |
| 59 | 59 |
| 60 #if defined(OS_WIN) | 60 #if defined(OS_WIN) |
| 61 #include "grit/generated_resources.h" | 61 #include "grit/generated_resources.h" |
| 62 #endif | 62 #endif |
| (...skipping 22 matching lines...) Expand all Loading... |
| 85 const char kKeyBeginFooterMarker[] = "-----END"; | 85 const char kKeyBeginFooterMarker[] = "-----END"; |
| 86 const char kKeyInfoEndMarker[] = "KEY-----"; | 86 const char kKeyInfoEndMarker[] = "KEY-----"; |
| 87 const char kPublic[] = "PUBLIC"; | 87 const char kPublic[] = "PUBLIC"; |
| 88 const char kPrivate[] = "PRIVATE"; | 88 const char kPrivate[] = "PRIVATE"; |
| 89 | 89 |
| 90 const int kRSAKeySize = 1024; | 90 const int kRSAKeySize = 1024; |
| 91 | 91 |
| 92 const char kDefaultSandboxedPageContentSecurityPolicy[] = | 92 const char kDefaultSandboxedPageContentSecurityPolicy[] = |
| 93 "sandbox allow-scripts allow-forms allow-popups"; | 93 "sandbox allow-scripts allow-forms allow-popups"; |
| 94 | 94 |
| 95 // Converts a normal hexadecimal string into the alphabet used by extensions. | |
| 96 // We use the characters 'a'-'p' instead of '0'-'f' to avoid ever having a | |
| 97 // completely numeric host, since some software interprets that as an IP | |
| 98 // address. | |
| 99 static void ConvertHexadecimalToIDAlphabet(std::string* id) { | |
| 100 for (size_t i = 0; i < id->size(); ++i) { | |
| 101 int val; | |
| 102 if (base::HexStringToInt(base::StringPiece(id->begin() + i, | |
| 103 id->begin() + i + 1), | |
| 104 &val)) { | |
| 105 (*id)[i] = val + 'a'; | |
| 106 } else { | |
| 107 (*id)[i] = 'a'; | |
| 108 } | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 // A singleton object containing global data needed by the extension objects. | 95 // A singleton object containing global data needed by the extension objects. |
| 113 class ExtensionConfig { | 96 class ExtensionConfig { |
| 114 public: | 97 public: |
| 115 static ExtensionConfig* GetInstance() { | 98 static ExtensionConfig* GetInstance() { |
| 116 return Singleton<ExtensionConfig>::get(); | 99 return Singleton<ExtensionConfig>::get(); |
| 117 } | 100 } |
| 118 | 101 |
| 119 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } | 102 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } |
| 120 | 103 |
| 121 private: | 104 private: |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 scoped_ptr<ActionInfo> LoadExtensionActionInfoHelper( | 173 scoped_ptr<ActionInfo> LoadExtensionActionInfoHelper( |
| 191 const Extension* extension, | 174 const Extension* extension, |
| 192 const DictionaryValue* extension_action, | 175 const DictionaryValue* extension_action, |
| 193 string16* error) { | 176 string16* error) { |
| 194 return manifest_handler_helpers::LoadActionInfo( | 177 return manifest_handler_helpers::LoadActionInfo( |
| 195 extension, extension_action, error); | 178 extension, extension_action, error); |
| 196 } | 179 } |
| 197 | 180 |
| 198 } // namespace | 181 } // namespace |
| 199 | 182 |
| 200 const base::FilePath::CharType Extension::kManifestFilename[] = | |
| 201 FILE_PATH_LITERAL("manifest.json"); | |
| 202 const base::FilePath::CharType Extension::kLocaleFolder[] = | |
| 203 FILE_PATH_LITERAL("_locales"); | |
| 204 const base::FilePath::CharType Extension::kMessagesFilename[] = | |
| 205 FILE_PATH_LITERAL("messages.json"); | |
| 206 const base::FilePath::CharType Extension::kPlatformSpecificFolder[] = | |
| 207 FILE_PATH_LITERAL("_platform_specific"); | |
| 208 | |
| 209 #if defined(OS_WIN) | 183 #if defined(OS_WIN) |
| 210 const char Extension::kExtensionRegistryPath[] = | 184 const char Extension::kExtensionRegistryPath[] = |
| 211 "Software\\Google\\Chrome\\Extensions"; | 185 "Software\\Google\\Chrome\\Extensions"; |
| 212 #endif | 186 #endif |
| 213 | 187 |
| 214 // first 16 bytes of SHA256 hashed public key. | |
| 215 const size_t Extension::kIdSize = 16; | |
| 216 | |
| 217 const char Extension::kMimeType[] = "application/x-chrome-extension"; | 188 const char Extension::kMimeType[] = "application/x-chrome-extension"; |
| 218 | 189 |
| 219 const int Extension::kValidWebExtentSchemes = | 190 const int Extension::kValidWebExtentSchemes = |
| 220 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS; | 191 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS; |
| 221 | 192 |
| 222 const int Extension::kValidHostPermissionSchemes = URLPattern::SCHEME_CHROMEUI | | 193 const int Extension::kValidHostPermissionSchemes = URLPattern::SCHEME_CHROMEUI | |
| 223 URLPattern::SCHEME_HTTP | | 194 URLPattern::SCHEME_HTTP | |
| 224 URLPattern::SCHEME_HTTPS | | 195 URLPattern::SCHEME_HTTPS | |
| 225 URLPattern::SCHEME_FILE | | 196 URLPattern::SCHEME_FILE | |
| 226 URLPattern::SCHEME_FTP; | 197 URLPattern::SCHEME_FTP; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 *utf8_error = UTF16ToUTF8(error); | 259 *utf8_error = UTF16ToUTF8(error); |
| 289 return NULL; | 260 return NULL; |
| 290 } | 261 } |
| 291 | 262 |
| 292 return extension; | 263 return extension; |
| 293 } | 264 } |
| 294 | 265 |
| 295 // static | 266 // static |
| 296 bool Extension::IdIsValid(const std::string& id) { | 267 bool Extension::IdIsValid(const std::string& id) { |
| 297 // Verify that the id is legal. | 268 // Verify that the id is legal. |
| 298 if (id.size() != (kIdSize * 2)) | 269 if (id.size() != (id_util::kIdSize * 2)) |
| 299 return false; | 270 return false; |
| 300 | 271 |
| 301 // We only support lowercase IDs, because IDs can be used as URL components | 272 // We only support lowercase IDs, because IDs can be used as URL components |
| 302 // (where GURL will lowercase it). | 273 // (where GURL will lowercase it). |
| 303 std::string temp = StringToLowerASCII(id); | 274 std::string temp = StringToLowerASCII(id); |
| 304 for (size_t i = 0; i < temp.size(); i++) | 275 for (size_t i = 0; i < temp.size(); i++) |
| 305 if (temp[i] < 'a' || temp[i] > 'p') | 276 if (temp[i] < 'a' || temp[i] > 'p') |
| 306 return false; | 277 return false; |
| 307 | 278 |
| 308 return true; | 279 return true; |
| 309 } | 280 } |
| 310 | 281 |
| 311 // static | 282 // static |
| 312 std::string Extension::GenerateIdForPath(const base::FilePath& path) { | |
| 313 base::FilePath new_path = Extension::MaybeNormalizePath(path); | |
| 314 std::string path_bytes = | |
| 315 std::string(reinterpret_cast<const char*>(new_path.value().data()), | |
| 316 new_path.value().size() * sizeof(base::FilePath::CharType)); | |
| 317 std::string id; | |
| 318 return GenerateId(path_bytes, &id) ? id : ""; | |
| 319 } | |
| 320 | |
| 321 // static | |
| 322 bool Extension::IsExtension(const base::FilePath& file_name) { | 283 bool Extension::IsExtension(const base::FilePath& file_name) { |
| 323 return file_name.MatchesExtension(chrome::kExtensionFileExtension); | 284 return file_name.MatchesExtension(chrome::kExtensionFileExtension); |
| 324 } | 285 } |
| 325 | 286 |
| 326 void Extension::GetBasicInfo(bool enabled, | 287 void Extension::GetBasicInfo(bool enabled, |
| 327 DictionaryValue* info) const { | 288 DictionaryValue* info) const { |
| 328 info->SetString(info_keys::kIdKey, id()); | 289 info->SetString(info_keys::kIdKey, id()); |
| 329 info->SetString(info_keys::kNameKey, name()); | 290 info->SetString(info_keys::kNameKey, name()); |
| 330 info->SetBoolean(info_keys::kEnabledKey, enabled); | 291 info->SetBoolean(info_keys::kEnabledKey, enabled); |
| 331 info->SetBoolean(info_keys::kKioskEnabledKey, kiosk_enabled()); | 292 info->SetBoolean(info_keys::kKioskEnabledKey, kiosk_enabled()); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 return base::Base64Decode(working, output); | 405 return base::Base64Decode(working, output); |
| 445 } | 406 } |
| 446 | 407 |
| 447 // static | 408 // static |
| 448 bool Extension::ProducePEM(const std::string& input, std::string* output) { | 409 bool Extension::ProducePEM(const std::string& input, std::string* output) { |
| 449 DCHECK(output); | 410 DCHECK(output); |
| 450 return (input.length() == 0) ? false : base::Base64Encode(input, output); | 411 return (input.length() == 0) ? false : base::Base64Encode(input, output); |
| 451 } | 412 } |
| 452 | 413 |
| 453 // static | 414 // static |
| 454 bool Extension::GenerateId(const std::string& input, std::string* output) { | |
| 455 DCHECK(output); | |
| 456 uint8 hash[Extension::kIdSize]; | |
| 457 crypto::SHA256HashString(input, hash, sizeof(hash)); | |
| 458 *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash))); | |
| 459 ConvertHexadecimalToIDAlphabet(output); | |
| 460 | |
| 461 return true; | |
| 462 } | |
| 463 | |
| 464 // static | |
| 465 bool Extension::FormatPEMForFileOutput(const std::string& input, | 415 bool Extension::FormatPEMForFileOutput(const std::string& input, |
| 466 std::string* output, | 416 std::string* output, |
| 467 bool is_public) { | 417 bool is_public) { |
| 468 DCHECK(output); | 418 DCHECK(output); |
| 469 if (input.length() == 0) | 419 if (input.length() == 0) |
| 470 return false; | 420 return false; |
| 471 *output = ""; | 421 *output = ""; |
| 472 output->append(kKeyBeginHeaderMarker); | 422 output->append(kKeyBeginHeaderMarker); |
| 473 output->append(" "); | 423 output->append(" "); |
| 474 output->append(is_public ? kPublic : kPrivate); | 424 output->append(is_public ? kPublic : kPrivate); |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 int creation_flags, | 1133 int creation_flags, |
| 1184 string16* error) { | 1134 string16* error) { |
| 1185 if (!explicit_id.empty()) { | 1135 if (!explicit_id.empty()) { |
| 1186 manifest->set_extension_id(explicit_id); | 1136 manifest->set_extension_id(explicit_id); |
| 1187 return true; | 1137 return true; |
| 1188 } | 1138 } |
| 1189 | 1139 |
| 1190 if (manifest->HasKey(keys::kPublicKey)) { | 1140 if (manifest->HasKey(keys::kPublicKey)) { |
| 1191 std::string public_key; | 1141 std::string public_key; |
| 1192 std::string public_key_bytes; | 1142 std::string public_key_bytes; |
| 1193 std::string extension_id; | |
| 1194 if (!manifest->GetString(keys::kPublicKey, &public_key) || | 1143 if (!manifest->GetString(keys::kPublicKey, &public_key) || |
| 1195 !ParsePEMKeyBytes(public_key, &public_key_bytes) || | 1144 !ParsePEMKeyBytes(public_key, &public_key_bytes)) { |
| 1196 !GenerateId(public_key_bytes, &extension_id)) { | |
| 1197 *error = ASCIIToUTF16(errors::kInvalidKey); | 1145 *error = ASCIIToUTF16(errors::kInvalidKey); |
| 1198 return false; | 1146 return false; |
| 1199 } | 1147 } |
| 1148 std::string extension_id = id_util::GenerateId(public_key_bytes); |
| 1200 manifest->set_extension_id(extension_id); | 1149 manifest->set_extension_id(extension_id); |
| 1201 return true; | 1150 return true; |
| 1202 } | 1151 } |
| 1203 | 1152 |
| 1204 if (creation_flags & REQUIRE_KEY) { | 1153 if (creation_flags & REQUIRE_KEY) { |
| 1205 *error = ASCIIToUTF16(errors::kInvalidKey); | 1154 *error = ASCIIToUTF16(errors::kInvalidKey); |
| 1206 return false; | 1155 return false; |
| 1207 } else { | 1156 } else { |
| 1208 // If there is a path, we generate the ID from it. This is useful for | 1157 // If there is a path, we generate the ID from it. This is useful for |
| 1209 // development mode, because it keeps the ID stable across restarts and | 1158 // development mode, because it keeps the ID stable across restarts and |
| 1210 // reloading the extension. | 1159 // reloading the extension. |
| 1211 std::string extension_id = GenerateIdForPath(path); | 1160 std::string extension_id = id_util::GenerateIdForPath(path); |
| 1212 if (extension_id.empty()) { | 1161 if (extension_id.empty()) { |
| 1213 NOTREACHED() << "Could not create ID from path."; | 1162 NOTREACHED() << "Could not create ID from path."; |
| 1214 return false; | 1163 return false; |
| 1215 } | 1164 } |
| 1216 manifest->set_extension_id(extension_id); | 1165 manifest->set_extension_id(extension_id); |
| 1217 return true; | 1166 return true; |
| 1218 } | 1167 } |
| 1219 } | 1168 } |
| 1220 | 1169 |
| 1221 // static | |
| 1222 base::FilePath Extension::MaybeNormalizePath(const base::FilePath& path) { | |
| 1223 #if defined(OS_WIN) | |
| 1224 // Normalize any drive letter to upper-case. We do this for consistency with | |
| 1225 // net_utils::FilePathToFileURL(), which does the same thing, to make string | |
| 1226 // comparisons simpler. | |
| 1227 std::wstring path_str = path.value(); | |
| 1228 if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' && | |
| 1229 path_str[1] == ':') | |
| 1230 path_str[0] += ('A' - 'a'); | |
| 1231 | |
| 1232 return base::FilePath(path_str); | |
| 1233 #else | |
| 1234 return path; | |
| 1235 #endif | |
| 1236 } | |
| 1237 | |
| 1238 bool Extension::LoadManagedModeFeatures(string16* error) { | 1170 bool Extension::LoadManagedModeFeatures(string16* error) { |
| 1239 if (!manifest_->HasKey(keys::kContentPack)) | 1171 if (!manifest_->HasKey(keys::kContentPack)) |
| 1240 return true; | 1172 return true; |
| 1241 const DictionaryValue* content_pack_value = NULL; | 1173 const DictionaryValue* content_pack_value = NULL; |
| 1242 if (!manifest_->GetDictionary(keys::kContentPack, &content_pack_value)) { | 1174 if (!manifest_->GetDictionary(keys::kContentPack, &content_pack_value)) { |
| 1243 *error = ASCIIToUTF16(errors::kInvalidContentPack); | 1175 *error = ASCIIToUTF16(errors::kInvalidContentPack); |
| 1244 return false; | 1176 return false; |
| 1245 } | 1177 } |
| 1246 | 1178 |
| 1247 if (!LoadManagedModeSites(content_pack_value, error)) | 1179 if (!LoadManagedModeSites(content_pack_value, error)) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 finished_parsing_manifest_(false), | 1225 finished_parsing_manifest_(false), |
| 1294 is_storage_isolated_(false), | 1226 is_storage_isolated_(false), |
| 1295 launch_container_(extension_misc::LAUNCH_TAB), | 1227 launch_container_(extension_misc::LAUNCH_TAB), |
| 1296 launch_width_(0), | 1228 launch_width_(0), |
| 1297 launch_height_(0), | 1229 launch_height_(0), |
| 1298 display_in_launcher_(true), | 1230 display_in_launcher_(true), |
| 1299 display_in_new_tab_page_(true), | 1231 display_in_new_tab_page_(true), |
| 1300 wants_file_access_(false), | 1232 wants_file_access_(false), |
| 1301 creation_flags_(0) { | 1233 creation_flags_(0) { |
| 1302 DCHECK(path.empty() || path.IsAbsolute()); | 1234 DCHECK(path.empty() || path.IsAbsolute()); |
| 1303 path_ = MaybeNormalizePath(path); | 1235 path_ = id_util::MaybeNormalizePath(path); |
| 1304 } | 1236 } |
| 1305 | 1237 |
| 1306 Extension::~Extension() { | 1238 Extension::~Extension() { |
| 1307 } | 1239 } |
| 1308 | 1240 |
| 1309 bool Extension::InitFromValue(int flags, string16* error) { | 1241 bool Extension::InitFromValue(int flags, string16* error) { |
| 1310 DCHECK(error); | 1242 DCHECK(error); |
| 1311 | 1243 |
| 1312 base::AutoLock auto_lock(runtime_data_lock_); | 1244 base::AutoLock auto_lock(runtime_data_lock_); |
| 1313 | 1245 |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2513 | 2445 |
| 2514 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 2446 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 2515 const Extension* extension, | 2447 const Extension* extension, |
| 2516 const PermissionSet* permissions, | 2448 const PermissionSet* permissions, |
| 2517 Reason reason) | 2449 Reason reason) |
| 2518 : reason(reason), | 2450 : reason(reason), |
| 2519 extension(extension), | 2451 extension(extension), |
| 2520 permissions(permissions) {} | 2452 permissions(permissions) {} |
| 2521 | 2453 |
| 2522 } // namespace extensions | 2454 } // namespace extensions |
| OLD | NEW |