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 |