| 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 <ostream> | 7 #include <ostream> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/file_path.h" | 12 #include "base/file_path.h" |
| 13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 14 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/string16.h" | 18 #include "base/string16.h" |
| 19 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
| 20 #include "base/string_piece.h" | 20 #include "base/string_piece.h" |
| 21 #include "base/string_util.h" | 21 #include "base/string_util.h" |
| 22 #include "base/stringprintf.h" | 22 #include "base/stringprintf.h" |
| 23 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 24 #include "base/values.h" | 24 #include "base/values.h" |
| 25 #include "base/version.h" | 25 #include "base/version.h" |
| 26 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
| 27 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 28 #include "chrome/common/chrome_version_info.h" | 28 #include "chrome/common/chrome_version_info.h" |
| 29 // TODO(rdevlin.cronin): Remove this once PageAction, BrowserAction, and |
| 30 // SystemIndicator have been moved out of Extension. |
| 31 #include "chrome/common/extensions/api/extension_action/action_info.h" |
| 29 #include "chrome/common/extensions/csp_validator.h" | 32 #include "chrome/common/extensions/csp_validator.h" |
| 30 #include "chrome/common/extensions/extension_manifest_constants.h" | 33 #include "chrome/common/extensions/extension_manifest_constants.h" |
| 31 #include "chrome/common/extensions/extension_resource.h" | 34 #include "chrome/common/extensions/extension_resource.h" |
| 32 #include "chrome/common/extensions/feature_switch.h" | 35 #include "chrome/common/extensions/feature_switch.h" |
| 33 #include "chrome/common/extensions/features/base_feature_provider.h" | 36 #include "chrome/common/extensions/features/base_feature_provider.h" |
| 34 #include "chrome/common/extensions/features/feature.h" | 37 #include "chrome/common/extensions/features/feature.h" |
| 35 #include "chrome/common/extensions/manifest.h" | 38 #include "chrome/common/extensions/manifest.h" |
| 36 #include "chrome/common/extensions/manifest_handler.h" | 39 #include "chrome/common/extensions/manifest_handler.h" |
| 40 #include "chrome/common/extensions/manifest_handler_helpers.h" |
| 37 #include "chrome/common/extensions/manifest_url_handler.h" | 41 #include "chrome/common/extensions/manifest_url_handler.h" |
| 38 #include "chrome/common/extensions/permissions/permission_set.h" | 42 #include "chrome/common/extensions/permissions/permission_set.h" |
| 39 #include "chrome/common/extensions/permissions/permissions_info.h" | 43 #include "chrome/common/extensions/permissions/permissions_info.h" |
| 40 #include "chrome/common/extensions/user_script.h" | 44 #include "chrome/common/extensions/user_script.h" |
| 41 #include "chrome/common/url_constants.h" | 45 #include "chrome/common/url_constants.h" |
| 42 #include "crypto/sha2.h" | 46 #include "crypto/sha2.h" |
| 43 #include "extensions/common/constants.h" | 47 #include "extensions/common/constants.h" |
| 44 #include "extensions/common/error_utils.h" | 48 #include "extensions/common/error_utils.h" |
| 45 #include "extensions/common/url_pattern_set.h" | 49 #include "extensions/common/url_pattern_set.h" |
| 46 #include "googleurl/src/url_util.h" | 50 #include "googleurl/src/url_util.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 if (base::HexStringToInt(base::StringPiece(id->begin() + i, | 124 if (base::HexStringToInt(base::StringPiece(id->begin() + i, |
| 121 id->begin() + i + 1), | 125 id->begin() + i + 1), |
| 122 &val)) { | 126 &val)) { |
| 123 (*id)[i] = val + 'a'; | 127 (*id)[i] = val + 'a'; |
| 124 } else { | 128 } else { |
| 125 (*id)[i] = 'a'; | 129 (*id)[i] = 'a'; |
| 126 } | 130 } |
| 127 } | 131 } |
| 128 } | 132 } |
| 129 | 133 |
| 130 // Strips leading slashes from the file path. Returns true iff the final path is | |
| 131 // non empty. | |
| 132 bool NormalizeAndValidatePath(std::string* path) { | |
| 133 size_t first_non_slash = path->find_first_not_of('/'); | |
| 134 if (first_non_slash == std::string::npos) { | |
| 135 *path = ""; | |
| 136 return false; | |
| 137 } | |
| 138 | |
| 139 *path = path->substr(first_non_slash); | |
| 140 return true; | |
| 141 } | |
| 142 | |
| 143 // Loads icon paths defined in dictionary |icons_value| into ExtensionIconSet | |
| 144 // |icons|. |icons_value| is a dictionary value {icon size -> icon path}. Icons | |
| 145 // in |icons_value| whose size is not in |icon_sizes| will be ignored. | |
| 146 // Returns success. If load fails, |error| will be set. | |
| 147 bool LoadIconsFromDictionary(const DictionaryValue* icons_value, | |
| 148 const int* icon_sizes, | |
| 149 size_t num_icon_sizes, | |
| 150 ExtensionIconSet* icons, | |
| 151 string16* error) { | |
| 152 DCHECK(icons); | |
| 153 for (size_t i = 0; i < num_icon_sizes; ++i) { | |
| 154 std::string key = base::IntToString(icon_sizes[i]); | |
| 155 if (icons_value->HasKey(key)) { | |
| 156 std::string icon_path; | |
| 157 if (!icons_value->GetString(key, &icon_path)) { | |
| 158 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 159 errors::kInvalidIconPath, key); | |
| 160 return false; | |
| 161 } | |
| 162 | |
| 163 if (!NormalizeAndValidatePath(&icon_path)) { | |
| 164 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 165 errors::kInvalidIconPath, key); | |
| 166 return false; | |
| 167 } | |
| 168 | |
| 169 icons->Add(icon_sizes[i], icon_path); | |
| 170 } | |
| 171 } | |
| 172 return true; | |
| 173 } | |
| 174 | |
| 175 // A singleton object containing global data needed by the extension objects. | 134 // A singleton object containing global data needed by the extension objects. |
| 176 class ExtensionConfig { | 135 class ExtensionConfig { |
| 177 public: | 136 public: |
| 178 static ExtensionConfig* GetInstance() { | 137 static ExtensionConfig* GetInstance() { |
| 179 return Singleton<ExtensionConfig>::get(); | 138 return Singleton<ExtensionConfig>::get(); |
| 180 } | 139 } |
| 181 | 140 |
| 182 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } | 141 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } |
| 183 | 142 |
| 184 private: | 143 private: |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 if ((*i)->ManifestEntryForbidden()) { | 257 if ((*i)->ManifestEntryForbidden()) { |
| 299 *error = ErrorUtils::FormatErrorMessageUTF16( | 258 *error = ErrorUtils::FormatErrorMessageUTF16( |
| 300 errors::kPermissionNotAllowedInManifest, | 259 errors::kPermissionNotAllowedInManifest, |
| 301 (*i)->info()->name()); | 260 (*i)->info()->name()); |
| 302 return true; | 261 return true; |
| 303 } | 262 } |
| 304 } | 263 } |
| 305 return false; | 264 return false; |
| 306 } | 265 } |
| 307 | 266 |
| 267 // Helper method to load an ExtensionAction from the page_action, script_badge, |
| 268 // browser_action, or system_indicator entries in the manifest. |
| 269 // TODO(rdevlin.cronin): Remove this once PageAction, BrowserAction, and |
| 270 // SystemIndicator have been moved out of Extension. |
| 271 scoped_ptr<ActionInfo> LoadExtensionActionInfoHelper( |
| 272 const Extension* extension, |
| 273 const DictionaryValue* extension_action, |
| 274 string16* error) { |
| 275 return manifest_handler_helpers::LoadActionInfo( |
| 276 extension, extension_action, error); |
| 277 } |
| 278 |
| 308 } // namespace | 279 } // namespace |
| 309 | 280 |
| 310 const FilePath::CharType Extension::kManifestFilename[] = | 281 const FilePath::CharType Extension::kManifestFilename[] = |
| 311 FILE_PATH_LITERAL("manifest.json"); | 282 FILE_PATH_LITERAL("manifest.json"); |
| 312 const FilePath::CharType Extension::kLocaleFolder[] = | 283 const FilePath::CharType Extension::kLocaleFolder[] = |
| 313 FILE_PATH_LITERAL("_locales"); | 284 FILE_PATH_LITERAL("_locales"); |
| 314 const FilePath::CharType Extension::kMessagesFilename[] = | 285 const FilePath::CharType Extension::kMessagesFilename[] = |
| 315 FILE_PATH_LITERAL("messages.json"); | 286 FILE_PATH_LITERAL("messages.json"); |
| 316 | 287 |
| 317 #if defined(OS_WIN) | 288 #if defined(OS_WIN) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 337 : webgl(false), | 308 : webgl(false), |
| 338 css3d(false), | 309 css3d(false), |
| 339 npapi(false) { | 310 npapi(false) { |
| 340 } | 311 } |
| 341 | 312 |
| 342 Extension::Requirements::~Requirements() {} | 313 Extension::Requirements::~Requirements() {} |
| 343 | 314 |
| 344 Extension::OAuth2Info::OAuth2Info() {} | 315 Extension::OAuth2Info::OAuth2Info() {} |
| 345 Extension::OAuth2Info::~OAuth2Info() {} | 316 Extension::OAuth2Info::~OAuth2Info() {} |
| 346 | 317 |
| 347 Extension::ActionInfo::ActionInfo() {} | |
| 348 Extension::ActionInfo::~ActionInfo() {} | |
| 349 | |
| 350 // | 318 // |
| 351 // Extension | 319 // Extension |
| 352 // | 320 // |
| 353 | 321 |
| 354 bool Extension::InstallWarning::operator==(const InstallWarning& other) const { | 322 bool Extension::InstallWarning::operator==(const InstallWarning& other) const { |
| 355 return format == other.format && message == other.message; | 323 return format == other.format && message == other.message; |
| 356 } | 324 } |
| 357 | 325 |
| 358 // static | 326 // static |
| 359 scoped_refptr<Extension> Extension::Create(const FilePath& path, | 327 scoped_refptr<Extension> Extension::Create(const FilePath& path, |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 } | 1256 } |
| 1289 | 1257 |
| 1290 const std::string& Extension::id() const { | 1258 const std::string& Extension::id() const { |
| 1291 return manifest_->extension_id(); | 1259 return manifest_->extension_id(); |
| 1292 } | 1260 } |
| 1293 | 1261 |
| 1294 const std::string Extension::VersionString() const { | 1262 const std::string Extension::VersionString() const { |
| 1295 return version()->GetString(); | 1263 return version()->GetString(); |
| 1296 } | 1264 } |
| 1297 | 1265 |
| 1266 void Extension::AddInstallWarning(const InstallWarning& new_warning) { |
| 1267 install_warnings_.push_back(new_warning); |
| 1268 } |
| 1269 |
| 1298 void Extension::AddInstallWarnings( | 1270 void Extension::AddInstallWarnings( |
| 1299 const InstallWarningVector& new_warnings) { | 1271 const InstallWarningVector& new_warnings) { |
| 1300 install_warnings_.insert(install_warnings_.end(), | 1272 install_warnings_.insert(install_warnings_.end(), |
| 1301 new_warnings.begin(), new_warnings.end()); | 1273 new_warnings.begin(), new_warnings.end()); |
| 1302 } | 1274 } |
| 1303 | 1275 |
| 1304 bool Extension::is_platform_app() const { | 1276 bool Extension::is_platform_app() const { |
| 1305 return manifest_->is_platform_app(); | 1277 return manifest_->is_platform_app(); |
| 1306 } | 1278 } |
| 1307 | 1279 |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2020 | 1992 |
| 2021 bool Extension::LoadIcons(string16* error) { | 1993 bool Extension::LoadIcons(string16* error) { |
| 2022 if (!manifest_->HasKey(keys::kIcons)) | 1994 if (!manifest_->HasKey(keys::kIcons)) |
| 2023 return true; | 1995 return true; |
| 2024 DictionaryValue* icons_value = NULL; | 1996 DictionaryValue* icons_value = NULL; |
| 2025 if (!manifest_->GetDictionary(keys::kIcons, &icons_value)) { | 1997 if (!manifest_->GetDictionary(keys::kIcons, &icons_value)) { |
| 2026 *error = ASCIIToUTF16(errors::kInvalidIcons); | 1998 *error = ASCIIToUTF16(errors::kInvalidIcons); |
| 2027 return false; | 1999 return false; |
| 2028 } | 2000 } |
| 2029 | 2001 |
| 2030 return LoadIconsFromDictionary(icons_value, | 2002 return manifest_handler_helpers::LoadIconsFromDictionary( |
| 2031 extension_misc::kExtensionIconSizes, | 2003 icons_value, |
| 2032 extension_misc::kNumExtensionIconSizes, | 2004 extension_misc::kExtensionIconSizes, |
| 2033 &icons_, | 2005 extension_misc::kNumExtensionIconSizes, |
| 2034 error); | 2006 &icons_, |
| 2007 error); |
| 2035 } | 2008 } |
| 2036 | 2009 |
| 2037 bool Extension::LoadCommands(string16* error) { | 2010 bool Extension::LoadCommands(string16* error) { |
| 2038 if (manifest_->HasKey(keys::kCommands)) { | 2011 if (manifest_->HasKey(keys::kCommands)) { |
| 2039 DictionaryValue* commands = NULL; | 2012 DictionaryValue* commands = NULL; |
| 2040 if (!manifest_->GetDictionary(keys::kCommands, &commands)) { | 2013 if (!manifest_->GetDictionary(keys::kCommands, &commands)) { |
| 2041 *error = ASCIIToUTF16(errors::kInvalidCommandsKey); | 2014 *error = ASCIIToUTF16(errors::kInvalidCommandsKey); |
| 2042 return false; | 2015 return false; |
| 2043 } | 2016 } |
| 2044 | 2017 |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2511 string16* error) { | 2484 string16* error) { |
| 2512 if (manifest_->HasKey(keys::kConvertedFromUserScript)) | 2485 if (manifest_->HasKey(keys::kConvertedFromUserScript)) |
| 2513 manifest_->GetBoolean(keys::kConvertedFromUserScript, | 2486 manifest_->GetBoolean(keys::kConvertedFromUserScript, |
| 2514 &converted_from_user_script_); | 2487 &converted_from_user_script_); |
| 2515 | 2488 |
| 2516 if (!LoadManifestHandlerFeatures(error) || | 2489 if (!LoadManifestHandlerFeatures(error) || |
| 2517 !LoadContentScripts(error) || | 2490 !LoadContentScripts(error) || |
| 2518 !LoadPageAction(error) || | 2491 !LoadPageAction(error) || |
| 2519 !LoadBrowserAction(error) || | 2492 !LoadBrowserAction(error) || |
| 2520 !LoadSystemIndicator(api_permissions, error) || | 2493 !LoadSystemIndicator(api_permissions, error) || |
| 2521 !LoadScriptBadge(error) || | |
| 2522 !LoadIncognitoMode(error) || | 2494 !LoadIncognitoMode(error) || |
| 2523 !LoadContentSecurityPolicy(error)) | 2495 !LoadContentSecurityPolicy(error)) |
| 2524 return false; | 2496 return false; |
| 2525 | 2497 |
| 2526 return true; | 2498 return true; |
| 2527 } | 2499 } |
| 2528 | 2500 |
| 2529 bool Extension::LoadManifestHandlerFeatures(string16* error) { | 2501 bool Extension::LoadManifestHandlerFeatures(string16* error) { |
| 2530 std::vector<std::string> keys = ManifestHandler::GetKeys(); | 2502 std::vector<std::string> keys = ManifestHandler::GetKeys(); |
| 2531 for (size_t i = 0; i < keys.size(); ++i) { | 2503 for (size_t i = 0; i < keys.size(); ++i) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2597 } else if (manifest_->HasKey(keys::kPageAction)) { | 2569 } else if (manifest_->HasKey(keys::kPageAction)) { |
| 2598 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) { | 2570 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) { |
| 2599 *error = ASCIIToUTF16(errors::kInvalidPageAction); | 2571 *error = ASCIIToUTF16(errors::kInvalidPageAction); |
| 2600 return false; | 2572 return false; |
| 2601 } | 2573 } |
| 2602 } | 2574 } |
| 2603 | 2575 |
| 2604 // If page_action_value is not NULL, then there was a valid page action. | 2576 // If page_action_value is not NULL, then there was a valid page action. |
| 2605 if (page_action_value) { | 2577 if (page_action_value) { |
| 2606 page_action_info_ = LoadExtensionActionInfoHelper( | 2578 page_action_info_ = LoadExtensionActionInfoHelper( |
| 2607 page_action_value, Extension::ActionInfo::TYPE_PAGE, error); | 2579 this, page_action_value, error); |
| 2608 if (!page_action_info_.get()) | 2580 if (!page_action_info_.get()) |
| 2609 return false; // Failed to parse page action definition. | 2581 return false; // Failed to parse page action definition. |
| 2610 } | 2582 } |
| 2611 | 2583 |
| 2612 return true; | 2584 return true; |
| 2613 } | 2585 } |
| 2614 | 2586 |
| 2615 bool Extension::LoadBrowserAction(string16* error) { | 2587 bool Extension::LoadBrowserAction(string16* error) { |
| 2616 if (!manifest_->HasKey(keys::kBrowserAction)) | 2588 if (!manifest_->HasKey(keys::kBrowserAction)) |
| 2617 return true; | 2589 return true; |
| 2618 DictionaryValue* browser_action_value = NULL; | 2590 DictionaryValue* browser_action_value = NULL; |
| 2619 if (!manifest_->GetDictionary(keys::kBrowserAction, &browser_action_value)) { | 2591 if (!manifest_->GetDictionary(keys::kBrowserAction, &browser_action_value)) { |
| 2620 *error = ASCIIToUTF16(errors::kInvalidBrowserAction); | 2592 *error = ASCIIToUTF16(errors::kInvalidBrowserAction); |
| 2621 return false; | 2593 return false; |
| 2622 } | 2594 } |
| 2623 | 2595 |
| 2624 browser_action_info_ = LoadExtensionActionInfoHelper( | 2596 browser_action_info_ = LoadExtensionActionInfoHelper( |
| 2625 browser_action_value, Extension::ActionInfo::TYPE_BROWSER, error); | 2597 this, browser_action_value, error); |
| 2626 if (!browser_action_info_.get()) | 2598 if (!browser_action_info_.get()) |
| 2627 return false; // Failed to parse browser action definition. | 2599 return false; // Failed to parse browser action definition. |
| 2628 return true; | 2600 return true; |
| 2629 } | 2601 } |
| 2630 | 2602 |
| 2631 bool Extension::LoadScriptBadge(string16* error) { | |
| 2632 if (manifest_->HasKey(keys::kScriptBadge)) { | |
| 2633 if (!FeatureSwitch::script_badges()->IsEnabled()) { | |
| 2634 // So as to not confuse developers if they specify a script badge section | |
| 2635 // in the manifest, show a warning if the script badge declaration isn't | |
| 2636 // going to have any effect. | |
| 2637 install_warnings_.push_back( | |
| 2638 InstallWarning(InstallWarning::FORMAT_TEXT, | |
| 2639 errors::kScriptBadgeRequiresFlag)); | |
| 2640 } | |
| 2641 | |
| 2642 DictionaryValue* script_badge_value = NULL; | |
| 2643 if (!manifest_->GetDictionary(keys::kScriptBadge, &script_badge_value)) { | |
| 2644 *error = ASCIIToUTF16(errors::kInvalidScriptBadge); | |
| 2645 return false; | |
| 2646 } | |
| 2647 | |
| 2648 script_badge_info_ = LoadExtensionActionInfoHelper( | |
| 2649 script_badge_value, Extension::ActionInfo::TYPE_SCRIPT_BADGE, error); | |
| 2650 if (!script_badge_info_.get()) | |
| 2651 return false; // Failed to parse script badge definition. | |
| 2652 } else { | |
| 2653 script_badge_info_.reset(new ActionInfo()); | |
| 2654 } | |
| 2655 | |
| 2656 // Script badges always use their extension's title and icon so users can rely | |
| 2657 // on the visual appearance to know which extension is running. This isn't | |
| 2658 // bulletproof since an malicious extension could use a different 16x16 icon | |
| 2659 // that matches the icon of a trusted extension, and users wouldn't be warned | |
| 2660 // during installation. | |
| 2661 | |
| 2662 if (!script_badge_info_->default_title.empty()) { | |
| 2663 install_warnings_.push_back( | |
| 2664 InstallWarning(InstallWarning::FORMAT_TEXT, | |
| 2665 errors::kScriptBadgeTitleIgnored)); | |
| 2666 } | |
| 2667 script_badge_info_->default_title = name(); | |
| 2668 | |
| 2669 if (!script_badge_info_->default_icon.empty()) { | |
| 2670 install_warnings_.push_back( | |
| 2671 InstallWarning(InstallWarning::FORMAT_TEXT, | |
| 2672 errors::kScriptBadgeIconIgnored)); | |
| 2673 } | |
| 2674 | |
| 2675 script_badge_info_->default_icon.Clear(); | |
| 2676 for (size_t i = 0; i < extension_misc::kNumScriptBadgeIconSizes; i++) { | |
| 2677 std::string path = icons().Get(extension_misc::kScriptBadgeIconSizes[i], | |
| 2678 ExtensionIconSet::MATCH_BIGGER); | |
| 2679 if (!path.empty()) | |
| 2680 script_badge_info_->default_icon.Add( | |
| 2681 extension_misc::kScriptBadgeIconSizes[i], path); | |
| 2682 } | |
| 2683 | |
| 2684 return true; | |
| 2685 } | |
| 2686 | |
| 2687 bool Extension::LoadSystemIndicator(APIPermissionSet* api_permissions, | 2603 bool Extension::LoadSystemIndicator(APIPermissionSet* api_permissions, |
| 2688 string16* error) { | 2604 string16* error) { |
| 2689 if (!manifest_->HasKey(keys::kSystemIndicator)) { | 2605 if (!manifest_->HasKey(keys::kSystemIndicator)) { |
| 2690 // There was no manifest entry for the system indicator. | 2606 // There was no manifest entry for the system indicator. |
| 2691 return true; | 2607 return true; |
| 2692 } | 2608 } |
| 2693 | 2609 |
| 2694 DictionaryValue* system_indicator_value = NULL; | 2610 DictionaryValue* system_indicator_value = NULL; |
| 2695 if (!manifest_->GetDictionary(keys::kSystemIndicator, | 2611 if (!manifest_->GetDictionary(keys::kSystemIndicator, |
| 2696 &system_indicator_value)) { | 2612 &system_indicator_value)) { |
| 2697 *error = ASCIIToUTF16(errors::kInvalidSystemIndicator); | 2613 *error = ASCIIToUTF16(errors::kInvalidSystemIndicator); |
| 2698 return false; | 2614 return false; |
| 2699 } | 2615 } |
| 2700 | 2616 |
| 2701 system_indicator_info_ = LoadExtensionActionInfoHelper( | 2617 system_indicator_info_ = LoadExtensionActionInfoHelper( |
| 2702 system_indicator_value, | 2618 this, system_indicator_value, error); |
| 2703 Extension::ActionInfo::TYPE_SYSTEM_INDICATOR, | |
| 2704 error); | |
| 2705 | 2619 |
| 2706 if (!system_indicator_info_.get()) { | 2620 if (!system_indicator_info_.get()) { |
| 2707 return false; | 2621 return false; |
| 2708 } | 2622 } |
| 2709 | 2623 |
| 2710 // Because the manifest was successfully parsed, auto-grant the permission. | 2624 // Because the manifest was successfully parsed, auto-grant the permission. |
| 2711 // TODO(dewittj) Add this for all extension action APIs. | 2625 // TODO(dewittj) Add this for all extension action APIs. |
| 2712 api_permissions->insert(APIPermission::kSystemIndicator); | 2626 api_permissions->insert(APIPermission::kSystemIndicator); |
| 2713 | 2627 |
| 2714 return true; | 2628 return true; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3133 base::IntToString(i)); | 3047 base::IntToString(i)); |
| 3134 return false; | 3048 return false; |
| 3135 } | 3049 } |
| 3136 | 3050 |
| 3137 (instance->*add_method)(glob); | 3051 (instance->*add_method)(glob); |
| 3138 } | 3052 } |
| 3139 | 3053 |
| 3140 return true; | 3054 return true; |
| 3141 } | 3055 } |
| 3142 | 3056 |
| 3143 scoped_ptr<Extension::ActionInfo> Extension::LoadExtensionActionInfoHelper( | |
| 3144 const DictionaryValue* extension_action, | |
| 3145 ActionInfo::Type action_type, | |
| 3146 string16* error) { | |
| 3147 scoped_ptr<ActionInfo> result(new ActionInfo()); | |
| 3148 | |
| 3149 if (manifest_version_ == 1) { | |
| 3150 // kPageActionIcons is obsolete, and used by very few extensions. Continue | |
| 3151 // loading it, but only take the first icon as the default_icon path. | |
| 3152 const ListValue* icons = NULL; | |
| 3153 if (extension_action->HasKey(keys::kPageActionIcons) && | |
| 3154 extension_action->GetList(keys::kPageActionIcons, &icons)) { | |
| 3155 for (ListValue::const_iterator iter = icons->begin(); | |
| 3156 iter != icons->end(); ++iter) { | |
| 3157 std::string path; | |
| 3158 if (!(*iter)->GetAsString(&path) || !NormalizeAndValidatePath(&path)) { | |
| 3159 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); | |
| 3160 return scoped_ptr<ActionInfo>(); | |
| 3161 } | |
| 3162 | |
| 3163 result->default_icon.Add(extension_misc::EXTENSION_ICON_ACTION, path); | |
| 3164 break; | |
| 3165 } | |
| 3166 } | |
| 3167 | |
| 3168 std::string id; | |
| 3169 if (extension_action->HasKey(keys::kPageActionId)) { | |
| 3170 if (!extension_action->GetString(keys::kPageActionId, &id)) { | |
| 3171 *error = ASCIIToUTF16(errors::kInvalidPageActionId); | |
| 3172 return scoped_ptr<ActionInfo>(); | |
| 3173 } | |
| 3174 result->id = id; | |
| 3175 } | |
| 3176 } | |
| 3177 | |
| 3178 // Read the page action |default_icon| (optional). | |
| 3179 // The |default_icon| value can be either dictionary {icon size -> icon path} | |
| 3180 // or non empty string value. | |
| 3181 if (extension_action->HasKey(keys::kPageActionDefaultIcon)) { | |
| 3182 const DictionaryValue* icons_value = NULL; | |
| 3183 std::string default_icon; | |
| 3184 if (extension_action->GetDictionary(keys::kPageActionDefaultIcon, | |
| 3185 &icons_value)) { | |
| 3186 if (!LoadIconsFromDictionary(icons_value, | |
| 3187 extension_misc::kExtensionActionIconSizes, | |
| 3188 extension_misc::kNumExtensionActionIconSizes, | |
| 3189 &result->default_icon, | |
| 3190 error)) { | |
| 3191 return scoped_ptr<ActionInfo>(); | |
| 3192 } | |
| 3193 } else if (extension_action->GetString(keys::kPageActionDefaultIcon, | |
| 3194 &default_icon) && | |
| 3195 NormalizeAndValidatePath(&default_icon)) { | |
| 3196 result->default_icon.Add(extension_misc::EXTENSION_ICON_ACTION, | |
| 3197 default_icon); | |
| 3198 } else { | |
| 3199 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); | |
| 3200 return scoped_ptr<ActionInfo>(); | |
| 3201 } | |
| 3202 } | |
| 3203 | |
| 3204 // Read the page action title from |default_title| if present, |name| if not | |
| 3205 // (both optional). | |
| 3206 if (extension_action->HasKey(keys::kPageActionDefaultTitle)) { | |
| 3207 if (!extension_action->GetString(keys::kPageActionDefaultTitle, | |
| 3208 &result->default_title)) { | |
| 3209 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle); | |
| 3210 return scoped_ptr<ActionInfo>(); | |
| 3211 } | |
| 3212 } else if (manifest_version_ == 1 && extension_action->HasKey(keys::kName)) { | |
| 3213 if (!extension_action->GetString(keys::kName, &result->default_title)) { | |
| 3214 *error = ASCIIToUTF16(errors::kInvalidPageActionName); | |
| 3215 return scoped_ptr<ActionInfo>(); | |
| 3216 } | |
| 3217 } | |
| 3218 | |
| 3219 // Read the action's |popup| (optional). | |
| 3220 const char* popup_key = NULL; | |
| 3221 if (extension_action->HasKey(keys::kPageActionDefaultPopup)) | |
| 3222 popup_key = keys::kPageActionDefaultPopup; | |
| 3223 | |
| 3224 if (manifest_version_ == 1 && | |
| 3225 extension_action->HasKey(keys::kPageActionPopup)) { | |
| 3226 if (popup_key) { | |
| 3227 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 3228 errors::kInvalidPageActionOldAndNewKeys, | |
| 3229 keys::kPageActionDefaultPopup, | |
| 3230 keys::kPageActionPopup); | |
| 3231 return scoped_ptr<ActionInfo>(); | |
| 3232 } | |
| 3233 popup_key = keys::kPageActionPopup; | |
| 3234 } | |
| 3235 | |
| 3236 if (popup_key) { | |
| 3237 const DictionaryValue* popup = NULL; | |
| 3238 std::string url_str; | |
| 3239 | |
| 3240 if (extension_action->GetString(popup_key, &url_str)) { | |
| 3241 // On success, |url_str| is set. Nothing else to do. | |
| 3242 } else if (manifest_version_ == 1 && | |
| 3243 extension_action->GetDictionary(popup_key, &popup)) { | |
| 3244 if (!popup->GetString(keys::kPageActionPopupPath, &url_str)) { | |
| 3245 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 3246 errors::kInvalidPageActionPopupPath, "<missing>"); | |
| 3247 return scoped_ptr<ActionInfo>(); | |
| 3248 } | |
| 3249 } else { | |
| 3250 *error = ASCIIToUTF16(errors::kInvalidPageActionPopup); | |
| 3251 return scoped_ptr<ActionInfo>(); | |
| 3252 } | |
| 3253 | |
| 3254 if (!url_str.empty()) { | |
| 3255 // An empty string is treated as having no popup. | |
| 3256 result->default_popup_url = GetResourceURL(url_str); | |
| 3257 if (!result->default_popup_url.is_valid()) { | |
| 3258 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 3259 errors::kInvalidPageActionPopupPath, url_str); | |
| 3260 return scoped_ptr<ActionInfo>(); | |
| 3261 } | |
| 3262 } else { | |
| 3263 DCHECK(result->default_popup_url.is_empty()) | |
| 3264 << "Shouldn't be possible for the popup to be set."; | |
| 3265 } | |
| 3266 } | |
| 3267 | |
| 3268 return result.Pass(); | |
| 3269 } | |
| 3270 | |
| 3271 bool Extension::LoadOAuth2Info(string16* error) { | 3057 bool Extension::LoadOAuth2Info(string16* error) { |
| 3272 if (!manifest_->HasKey(keys::kOAuth2)) | 3058 if (!manifest_->HasKey(keys::kOAuth2)) |
| 3273 return true; | 3059 return true; |
| 3274 | 3060 |
| 3275 if (!manifest_->GetString(keys::kOAuth2ClientId, &oauth2_info_.client_id) || | 3061 if (!manifest_->GetString(keys::kOAuth2ClientId, &oauth2_info_.client_id) || |
| 3276 oauth2_info_.client_id.empty()) { | 3062 oauth2_info_.client_id.empty()) { |
| 3277 *error = ASCIIToUTF16(errors::kInvalidOAuth2ClientId); | 3063 *error = ASCIIToUTF16(errors::kInvalidOAuth2ClientId); |
| 3278 return false; | 3064 return false; |
| 3279 } | 3065 } |
| 3280 | 3066 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3480 | 3266 |
| 3481 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 3267 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 3482 const Extension* extension, | 3268 const Extension* extension, |
| 3483 const PermissionSet* permissions, | 3269 const PermissionSet* permissions, |
| 3484 Reason reason) | 3270 Reason reason) |
| 3485 : reason(reason), | 3271 : reason(reason), |
| 3486 extension(extension), | 3272 extension(extension), |
| 3487 permissions(permissions) {} | 3273 permissions(permissions) {} |
| 3488 | 3274 |
| 3489 } // namespace extensions | 3275 } // namespace extensions |
| OLD | NEW |