| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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> |
| 8 |
| 7 #include "base/base64.h" | 9 #include "base/base64.h" |
| 8 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 10 #include "base/file_path.h" | 12 #include "base/file_path.h" |
| 11 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 12 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 13 #include "base/logging.h" | 15 #include "base/logging.h" |
| 14 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
| 15 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 16 #include "base/string16.h" | 18 #include "base/string16.h" |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 return false; | 796 return false; |
| 795 } | 797 } |
| 796 | 798 |
| 797 (instance->*add_method)(glob); | 799 (instance->*add_method)(glob); |
| 798 } | 800 } |
| 799 | 801 |
| 800 return true; | 802 return true; |
| 801 } | 803 } |
| 802 | 804 |
| 803 scoped_ptr<ExtensionAction> Extension::LoadExtensionActionHelper( | 805 scoped_ptr<ExtensionAction> Extension::LoadExtensionActionHelper( |
| 804 const DictionaryValue* extension_action, string16* error) { | 806 const DictionaryValue* extension_action, |
| 807 ExtensionAction::Type action_type, |
| 808 string16* error) { |
| 805 scoped_ptr<ExtensionAction> result(new ExtensionAction(id())); | 809 scoped_ptr<ExtensionAction> result(new ExtensionAction(id())); |
| 806 | 810 |
| 807 // Page actions are hidden by default, and browser actions ignore | 811 // Page actions are hidden by default, and browser actions ignore |
| 808 // visibility. | 812 // visibility. |
| 809 result->SetIsVisible(ExtensionAction::kDefaultTabId, false); | 813 result->SetIsVisible(ExtensionAction::kDefaultTabId, false); |
| 810 | 814 |
| 811 if (manifest_version_ == 1) { | 815 if (manifest_version_ == 1) { |
| 812 ListValue* icons = NULL; | 816 ListValue* icons = NULL; |
| 813 if (extension_action->HasKey(keys::kPageActionIcons) && | 817 if (extension_action->HasKey(keys::kPageActionIcons) && |
| 814 extension_action->GetList(keys::kPageActionIcons, &icons)) { | 818 extension_action->GetList(keys::kPageActionIcons, &icons)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 830 *error = ASCIIToUTF16(errors::kInvalidPageActionId); | 834 *error = ASCIIToUTF16(errors::kInvalidPageActionId); |
| 831 return scoped_ptr<ExtensionAction>(); | 835 return scoped_ptr<ExtensionAction>(); |
| 832 } | 836 } |
| 833 result->set_id(id); | 837 result->set_id(id); |
| 834 } | 838 } |
| 835 } | 839 } |
| 836 | 840 |
| 837 std::string default_icon; | 841 std::string default_icon; |
| 838 // Read the page action |default_icon| (optional). | 842 // Read the page action |default_icon| (optional). |
| 839 if (extension_action->HasKey(keys::kPageActionDefaultIcon)) { | 843 if (extension_action->HasKey(keys::kPageActionDefaultIcon)) { |
| 840 if (!extension_action->GetString(keys::kPageActionDefaultIcon, | 844 if (action_type == ExtensionAction::TYPE_SCRIPT_BADGE) { |
| 841 &default_icon) || | 845 install_warnings_.push_back( |
| 842 default_icon.empty()) { | 846 InstallWarning(InstallWarning::FORMAT_TEXT, |
| 843 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); | 847 errors::kScriptBadgeIconIgnored)); |
| 844 return scoped_ptr<ExtensionAction>(); | 848 } else { |
| 849 if (!extension_action->GetString(keys::kPageActionDefaultIcon, |
| 850 &default_icon) || |
| 851 default_icon.empty()) { |
| 852 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); |
| 853 return scoped_ptr<ExtensionAction>(); |
| 854 } |
| 855 result->set_default_icon_path(default_icon); |
| 845 } | 856 } |
| 846 result->set_default_icon_path(default_icon); | |
| 847 } | 857 } |
| 848 | 858 |
| 849 // Read the page action title from |default_title| if present, |name| if not | 859 // Read the page action title from |default_title| if present, |name| if not |
| 850 // (both optional). | 860 // (both optional). |
| 851 std::string title; | 861 std::string title; |
| 852 if (extension_action->HasKey(keys::kPageActionDefaultTitle)) { | 862 if (extension_action->HasKey(keys::kPageActionDefaultTitle)) { |
| 853 if (!extension_action->GetString(keys::kPageActionDefaultTitle, &title)) { | 863 if (!extension_action->GetString(keys::kPageActionDefaultTitle, &title)) { |
| 854 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle); | 864 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle); |
| 855 return scoped_ptr<ExtensionAction>(); | 865 return scoped_ptr<ExtensionAction>(); |
| 856 } | 866 } |
| (...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 string16* error) { | 2029 string16* error) { |
| 2020 if (manifest_->HasKey(keys::kConvertedFromUserScript)) | 2030 if (manifest_->HasKey(keys::kConvertedFromUserScript)) |
| 2021 manifest_->GetBoolean(keys::kConvertedFromUserScript, | 2031 manifest_->GetBoolean(keys::kConvertedFromUserScript, |
| 2022 &converted_from_user_script_); | 2032 &converted_from_user_script_); |
| 2023 | 2033 |
| 2024 if (!LoadDevToolsPage(error) || | 2034 if (!LoadDevToolsPage(error) || |
| 2025 !LoadInputComponents(api_permissions, error) || | 2035 !LoadInputComponents(api_permissions, error) || |
| 2026 !LoadContentScripts(error) || | 2036 !LoadContentScripts(error) || |
| 2027 !LoadPageAction(error) || | 2037 !LoadPageAction(error) || |
| 2028 !LoadBrowserAction(error) || | 2038 !LoadBrowserAction(error) || |
| 2039 !LoadScriptBadge(error) || |
| 2029 !LoadFileBrowserHandlers(error) || | 2040 !LoadFileBrowserHandlers(error) || |
| 2030 !LoadChromeURLOverrides(error) || | 2041 !LoadChromeURLOverrides(error) || |
| 2031 !LoadOmnibox(error) || | 2042 !LoadOmnibox(error) || |
| 2032 !LoadTextToSpeechVoices(error) || | 2043 !LoadTextToSpeechVoices(error) || |
| 2033 !LoadIncognitoMode(error) || | 2044 !LoadIncognitoMode(error) || |
| 2034 !LoadContentSecurityPolicy(error)) | 2045 !LoadContentSecurityPolicy(error)) |
| 2035 return false; | 2046 return false; |
| 2036 | 2047 |
| 2037 return true; | 2048 return true; |
| 2038 } | 2049 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 } | 2250 } |
| 2240 } else if (manifest_->HasKey(keys::kPageAction)) { | 2251 } else if (manifest_->HasKey(keys::kPageAction)) { |
| 2241 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) { | 2252 if (!manifest_->GetDictionary(keys::kPageAction, &page_action_value)) { |
| 2242 *error = ASCIIToUTF16(errors::kInvalidPageAction); | 2253 *error = ASCIIToUTF16(errors::kInvalidPageAction); |
| 2243 return false; | 2254 return false; |
| 2244 } | 2255 } |
| 2245 } | 2256 } |
| 2246 | 2257 |
| 2247 // If page_action_value is not NULL, then there was a valid page action. | 2258 // If page_action_value is not NULL, then there was a valid page action. |
| 2248 if (page_action_value) { | 2259 if (page_action_value) { |
| 2249 page_action_ = LoadExtensionActionHelper(page_action_value, error); | 2260 page_action_ = LoadExtensionActionHelper( |
| 2261 page_action_value, ExtensionAction::TYPE_PAGE, error); |
| 2250 if (!page_action_.get()) | 2262 if (!page_action_.get()) |
| 2251 return false; // Failed to parse page action definition. | 2263 return false; // Failed to parse page action definition. |
| 2252 declared_action_type_ = ExtensionAction::TYPE_PAGE; | 2264 declared_action_type_ = ExtensionAction::TYPE_PAGE; |
| 2253 | 2265 |
| 2254 // The action box changes the meaning of the page action area, so we need | 2266 // The action box changes the meaning of the page action area, so we need |
| 2255 // to convert page actions into browser actions. | 2267 // to convert page actions into browser actions. |
| 2256 if (switch_utils::AreScriptBadgesEnabled()) { | 2268 if (switch_utils::AreScriptBadgesEnabled()) { |
| 2257 browser_action_ = page_action_.Pass(); | 2269 browser_action_ = page_action_.Pass(); |
| 2258 // declared_action_type_ stays the same; that's the point. | 2270 // declared_action_type_ stays the same; that's the point. |
| 2259 } | 2271 } |
| 2260 } | 2272 } |
| 2261 | 2273 |
| 2262 return true; | 2274 return true; |
| 2263 } | 2275 } |
| 2264 | 2276 |
| 2265 bool Extension::LoadBrowserAction(string16* error) { | 2277 bool Extension::LoadBrowserAction(string16* error) { |
| 2266 if (!manifest_->HasKey(keys::kBrowserAction)) | 2278 if (!manifest_->HasKey(keys::kBrowserAction)) |
| 2267 return true; | 2279 return true; |
| 2268 DictionaryValue* browser_action_value = NULL; | 2280 DictionaryValue* browser_action_value = NULL; |
| 2269 if (!manifest_->GetDictionary(keys::kBrowserAction, &browser_action_value)) { | 2281 if (!manifest_->GetDictionary(keys::kBrowserAction, &browser_action_value)) { |
| 2270 *error = ASCIIToUTF16(errors::kInvalidBrowserAction); | 2282 *error = ASCIIToUTF16(errors::kInvalidBrowserAction); |
| 2271 return false; | 2283 return false; |
| 2272 } | 2284 } |
| 2273 | 2285 |
| 2274 browser_action_ = LoadExtensionActionHelper(browser_action_value, error); | 2286 browser_action_ = LoadExtensionActionHelper( |
| 2287 browser_action_value, ExtensionAction::TYPE_BROWSER, error); |
| 2275 if (!browser_action_.get()) | 2288 if (!browser_action_.get()) |
| 2276 return false; // Failed to parse browser action definition. | 2289 return false; // Failed to parse browser action definition. |
| 2277 declared_action_type_ = ExtensionAction::TYPE_BROWSER; | 2290 declared_action_type_ = ExtensionAction::TYPE_BROWSER; |
| 2278 return true; | 2291 return true; |
| 2279 } | 2292 } |
| 2280 | 2293 |
| 2294 bool Extension::LoadScriptBadge(string16* error) { |
| 2295 if (manifest_->HasKey(keys::kScriptBadge)) { |
| 2296 if (!switch_utils::AreScriptBadgesEnabled()) { |
| 2297 // So as to not confuse developers if they specify a script badge section |
| 2298 // in the manifest, show a warning if the script badge declaration isn't |
| 2299 // going to have any effect. |
| 2300 install_warnings_.push_back( |
| 2301 InstallWarning(InstallWarning::FORMAT_TEXT, |
| 2302 errors::kScriptBadgeRequiresFlag)); |
| 2303 } |
| 2304 |
| 2305 DictionaryValue* script_badge_value = NULL; |
| 2306 if (!manifest_->GetDictionary(keys::kScriptBadge, &script_badge_value)) { |
| 2307 *error = ASCIIToUTF16(errors::kInvalidScriptBadge); |
| 2308 return false; |
| 2309 } |
| 2310 |
| 2311 script_badge_ = LoadExtensionActionHelper( |
| 2312 script_badge_value, ExtensionAction::TYPE_SCRIPT_BADGE, error); |
| 2313 if (!script_badge_.get()) |
| 2314 return false; // Failed to parse script badge definition. |
| 2315 |
| 2316 declared_action_type_ = ExtensionAction::TYPE_SCRIPT_BADGE; |
| 2317 } else { |
| 2318 script_badge_.reset(new ExtensionAction(id())); |
| 2319 |
| 2320 // Make sure there is always a title. |
| 2321 script_badge_->SetTitle(ExtensionAction::kDefaultTabId, name()); |
| 2322 } |
| 2323 |
| 2324 // Script badges always use their extension's icon so users can rely on the |
| 2325 // visual appearance to know which extension is running. This isn't |
| 2326 // bulletproof since an malicious extension could use a different 16x16 icon |
| 2327 // that matches the icon of a trusted extension, and users wouldn't be warned |
| 2328 // during installation. |
| 2329 |
| 2330 std::string icon16_path = icons().Get(ExtensionIconSet::EXTENSION_ICON_BITTY, |
| 2331 ExtensionIconSet::MATCH_EXACTLY); |
| 2332 if (!icon16_path.empty()) { |
| 2333 script_badge_->set_default_icon_path(icon16_path); |
| 2334 } else { |
| 2335 script_badge_->SetIcon( |
| 2336 ExtensionAction::kDefaultTabId, |
| 2337 *ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 2338 IDR_EXTENSIONS_FAVICON).ToSkBitmap()); |
| 2339 } |
| 2340 |
| 2341 script_badge_->SetIsVisible(ExtensionAction::kDefaultTabId, true); |
| 2342 |
| 2343 return true; |
| 2344 } |
| 2345 |
| 2281 bool Extension::LoadFileBrowserHandlers(string16* error) { | 2346 bool Extension::LoadFileBrowserHandlers(string16* error) { |
| 2282 if (!manifest_->HasKey(keys::kFileBrowserHandlers)) | 2347 if (!manifest_->HasKey(keys::kFileBrowserHandlers)) |
| 2283 return true; | 2348 return true; |
| 2284 ListValue* file_browser_handlers_value = NULL; | 2349 ListValue* file_browser_handlers_value = NULL; |
| 2285 if (!manifest_->GetList(keys::kFileBrowserHandlers, | 2350 if (!manifest_->GetList(keys::kFileBrowserHandlers, |
| 2286 &file_browser_handlers_value)) { | 2351 &file_browser_handlers_value)) { |
| 2287 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler); | 2352 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler); |
| 2288 return false; | 2353 return false; |
| 2289 } | 2354 } |
| 2290 file_browser_handlers_.reset( | 2355 file_browser_handlers_.reset( |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3610 // We want to sync any extensions that are internal and the chrome web store. | 3675 // We want to sync any extensions that are internal and the chrome web store. |
| 3611 return location() == Extension::INTERNAL || | 3676 return location() == Extension::INTERNAL || |
| 3612 id() == extension_misc::kWebStoreAppId; | 3677 id() == extension_misc::kWebStoreAppId; |
| 3613 } | 3678 } |
| 3614 | 3679 |
| 3615 bool Extension::ShouldDisplayInLauncher() const { | 3680 bool Extension::ShouldDisplayInLauncher() const { |
| 3616 // All apps should be displayed on the NTP except for the Cloud Print App. | 3681 // All apps should be displayed on the NTP except for the Cloud Print App. |
| 3617 return is_app() && id() != extension_misc::kCloudPrintAppId; | 3682 return is_app() && id() != extension_misc::kCloudPrintAppId; |
| 3618 } | 3683 } |
| 3619 | 3684 |
| 3685 bool Extension::InstallWarning::operator==(const InstallWarning& other) const { |
| 3686 return format == other.format && message == other.message; |
| 3687 } |
| 3688 |
| 3689 void PrintTo(const Extension::InstallWarning& warning, ::std::ostream* os){ |
| 3690 *os << "InstallWarning("; |
| 3691 switch (warning.format) { |
| 3692 case Extension::InstallWarning::FORMAT_TEXT: |
| 3693 *os << "FORMAT_TEXT, \""; |
| 3694 break; |
| 3695 case Extension::InstallWarning::FORMAT_HTML: |
| 3696 *os << "FORMAT_HTML, \""; |
| 3697 break; |
| 3698 } |
| 3699 // This is just for test error messages, so no need to escape '"' |
| 3700 // characters inside the message. |
| 3701 *os << warning.message << "\")"; |
| 3702 } |
| 3703 |
| 3620 ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest, | 3704 ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest, |
| 3621 const std::string& id, | 3705 const std::string& id, |
| 3622 const FilePath& path, | 3706 const FilePath& path, |
| 3623 Extension::Location location) | 3707 Extension::Location location) |
| 3624 : extension_id(id), | 3708 : extension_id(id), |
| 3625 extension_path(path), | 3709 extension_path(path), |
| 3626 extension_location(location) { | 3710 extension_location(location) { |
| 3627 if (manifest) | 3711 if (manifest) |
| 3628 extension_manifest.reset(manifest->DeepCopy()); | 3712 extension_manifest.reset(manifest->DeepCopy()); |
| 3629 } | 3713 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3657 | 3741 |
| 3658 bool Extension::HasContentScriptAtURL(const GURL& url) const { | 3742 bool Extension::HasContentScriptAtURL(const GURL& url) const { |
| 3659 for (UserScriptList::const_iterator it = content_scripts_.begin(); | 3743 for (UserScriptList::const_iterator it = content_scripts_.begin(); |
| 3660 it != content_scripts_.end(); ++it) { | 3744 it != content_scripts_.end(); ++it) { |
| 3661 if (it->MatchesURL(url)) | 3745 if (it->MatchesURL(url)) |
| 3662 return true; | 3746 return true; |
| 3663 } | 3747 } |
| 3664 return false; | 3748 return false; |
| 3665 } | 3749 } |
| 3666 | 3750 |
| 3667 ExtensionAction* Extension::GetScriptBadge() const { | |
| 3668 if (!script_badge_.get()) { | |
| 3669 script_badge_.reset(new ExtensionAction(id())); | |
| 3670 | |
| 3671 // On initialization, copy the default icon path from the browser action, | |
| 3672 // or generate a puzzle piece if there isn't one. Extensions may later | |
| 3673 // overwrite this icon using the browserAction API. | |
| 3674 if (browser_action() && !browser_action()->default_icon_path().empty()) { | |
| 3675 script_badge_->set_default_icon_path( | |
| 3676 browser_action()->default_icon_path()); | |
| 3677 } else { | |
| 3678 script_badge_->SetIcon( | |
| 3679 ExtensionAction::kDefaultTabId, | |
| 3680 *ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 3681 IDR_EXTENSIONS_FAVICON).ToSkBitmap()); | |
| 3682 } | |
| 3683 | |
| 3684 // Likewise, make sure there is always a title. | |
| 3685 script_badge_->SetTitle(ExtensionAction::kDefaultTabId, name()); | |
| 3686 } | |
| 3687 | |
| 3688 // Every time, re-initialize the script badge based on the current state of | |
| 3689 // the browser action. | |
| 3690 int kDefaultTabId = ExtensionAction::kDefaultTabId; | |
| 3691 | |
| 3692 script_badge_->SetIsVisible(kDefaultTabId, true); | |
| 3693 | |
| 3694 if (browser_action()) { | |
| 3695 SkBitmap icon = browser_action()->GetIcon(kDefaultTabId); | |
| 3696 if (!icon.isNull()) | |
| 3697 script_badge_->SetIcon(kDefaultTabId, icon); | |
| 3698 | |
| 3699 std::string title = browser_action()->GetTitle(kDefaultTabId); | |
| 3700 if (!title.empty()) | |
| 3701 script_badge_->SetTitle(kDefaultTabId, title); | |
| 3702 } | |
| 3703 | |
| 3704 return script_badge_.get(); | |
| 3705 } | |
| 3706 | |
| 3707 const URLPatternSet* Extension::GetTabSpecificHostPermissions( | 3751 const URLPatternSet* Extension::GetTabSpecificHostPermissions( |
| 3708 int tab_id) const { | 3752 int tab_id) const { |
| 3709 base::AutoLock auto_lock(runtime_data_lock_); | 3753 base::AutoLock auto_lock(runtime_data_lock_); |
| 3710 return runtime_data_.GetTabSpecificHostPermissions(tab_id); | 3754 return runtime_data_.GetTabSpecificHostPermissions(tab_id); |
| 3711 } | 3755 } |
| 3712 | 3756 |
| 3713 void Extension::SetTabSpecificHostPermissions( | 3757 void Extension::SetTabSpecificHostPermissions( |
| 3714 int tab_id, | 3758 int tab_id, |
| 3715 const URLPatternSet& permissions) const { | 3759 const URLPatternSet& permissions) const { |
| 3716 base::AutoLock auto_lock(runtime_data_lock_); | 3760 base::AutoLock auto_lock(runtime_data_lock_); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3797 | 3841 |
| 3798 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 3842 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 3799 const Extension* extension, | 3843 const Extension* extension, |
| 3800 const ExtensionPermissionSet* permissions, | 3844 const ExtensionPermissionSet* permissions, |
| 3801 Reason reason) | 3845 Reason reason) |
| 3802 : reason(reason), | 3846 : reason(reason), |
| 3803 extension(extension), | 3847 extension(extension), |
| 3804 permissions(permissions) {} | 3848 permissions(permissions) {} |
| 3805 | 3849 |
| 3806 } // namespace extensions | 3850 } // namespace extensions |
| OLD | NEW |