Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 output->append(" "); | 1072 output->append(" "); |
| 1073 output->append(is_public ? kPublic : kPrivate); | 1073 output->append(is_public ? kPublic : kPrivate); |
| 1074 output->append(" "); | 1074 output->append(" "); |
| 1075 output->append(kKeyInfoEndMarker); | 1075 output->append(kKeyInfoEndMarker); |
| 1076 output->append("\n"); | 1076 output->append("\n"); |
| 1077 | 1077 |
| 1078 return true; | 1078 return true; |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 // static | 1081 // static |
| 1082 // TODO(aa): A problem with this code is that we silently allow upgrades to | 1082 bool Extension::IsPrivilegeIncrease(const std::set<std::string>& granted_apis, |
| 1083 // extensions that require less permissions than the current version, but then | 1083 const ExtensionExtent& granted_extent, |
| 1084 // we don't silently allow them to go back. In order to fix this, we would need | 1084 const Extension* old_extension, |
| 1085 // to remember the max set of permissions we ever granted a single extension. | |
| 1086 bool Extension::IsPrivilegeIncrease(const Extension* old_extension, | |
| 1087 const Extension* new_extension) { | 1085 const Extension* new_extension) { |
| 1088 // If the old extension had native code access, we don't need to go any | 1086 // COMPONENT extensions should never go through this code path. |
| 1089 // further. Things can't get any worse. | 1087 DCHECK(new_extension->location() != Extension::COMPONENT); |
|
Aaron Boodman
2010/11/22 07:57:53
Two things:
1) DCHECK is for wusses, and causes l
jstritar
2010/11/22 23:01:08
Thanks for the explanation... I went a little craz
| |
| 1090 if (old_extension->plugins().size() > 0) | |
| 1091 return false; | |
| 1092 | 1088 |
| 1093 // Otherwise, if the new extension has a plugin, it's a privilege increase. | 1089 if (old_extension) { |
| 1094 if (new_extension->plugins().size() > 0) | 1090 // If the old extension had native code access, we don't need to go any |
| 1095 return true; | 1091 // further. Things can't get any worse. |
| 1092 if (old_extension->plugins().size() > 0) | |
| 1093 return false; | |
| 1096 | 1094 |
| 1097 // If we are increasing the set of hosts we have access to (not | 1095 // Otherwise, if the new extension has a plugin, it's a privilege increase. |
| 1098 // counting scheme differences), it's a privilege increase. | 1096 if (new_extension->plugins().size() > 0) |
| 1099 if (!old_extension->HasEffectiveAccessToAllHosts()) { | 1097 return true; |
| 1098 } | |
| 1099 | |
| 1100 // If the extension hadn't been granted access to all hosts in the past, then | |
| 1101 // see if the extension requires more host permissions. | |
| 1102 if (!HasEffectiveAccessToAllHosts(granted_extent, granted_apis)) { | |
| 1100 if (new_extension->HasEffectiveAccessToAllHosts()) | 1103 if (new_extension->HasEffectiveAccessToAllHosts()) |
| 1101 return true; | 1104 return true; |
| 1102 | 1105 |
| 1103 // TODO(erikkay) This will trip when you add a new distinct hostname, | 1106 const ExtensionExtent new_extent = |
| 1104 // but we should unique based on RCD as well. crbug.com/57042 | 1107 new_extension->GetEffectiveHostPermissions(); |
| 1105 std::vector<std::string> old_hosts = old_extension->GetDistinctHosts(); | 1108 std::vector<std::string> new_hosts = |
| 1106 std::vector<std::string> new_hosts = new_extension->GetDistinctHosts(); | 1109 GetDistinctHosts(new_extent.patterns()); |
| 1110 std::vector<std::string> old_hosts = | |
| 1111 GetDistinctHosts(granted_extent.patterns()); | |
| 1112 | |
| 1107 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end()); | 1113 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end()); |
| 1108 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end()); | 1114 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end()); |
| 1109 std::set<std::string> new_only; | 1115 std::set<std::string> new_hosts_only; |
| 1116 | |
| 1110 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(), | 1117 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(), |
| 1111 old_hosts_set.begin(), old_hosts_set.end(), | 1118 old_hosts_set.begin(), old_hosts_set.end(), |
| 1112 std::inserter(new_only, new_only.end())); | 1119 std::inserter(new_hosts_only, new_hosts_only.end())); |
| 1113 if (new_only.size()) | 1120 |
| 1121 if (new_hosts_only.size()) | |
| 1114 return true; | 1122 return true; |
| 1115 } | 1123 } |
| 1116 | 1124 |
| 1117 std::set<string16> old_messages = | 1125 std::set<std::string> new_apis = new_extension->api_permissions(); |
| 1118 old_extension->GetSimplePermissionMessages(); | 1126 std::set<std::string> new_apis_only; |
| 1119 std::set<string16> new_messages = | 1127 std::set_difference(new_apis.begin(), new_apis.end(), |
| 1120 new_extension->GetSimplePermissionMessages(); | 1128 granted_apis.begin(), granted_apis.end(), |
| 1121 std::set<string16> new_only; | 1129 std::inserter(new_apis_only, new_apis_only.end())); |
| 1122 std::set_difference(new_messages.begin(), new_messages.end(), | |
| 1123 old_messages.begin(), old_messages.end(), | |
| 1124 std::inserter(new_only, new_only.end())); | |
| 1125 | 1130 |
| 1126 // If there are any new permission messages, then it's an increase. | 1131 // Ignore API permissions that don't require user approval when deciding if |
| 1127 if (!new_only.empty()) | 1132 // an extension has increased its privileges. |
| 1133 size_t new_api_count = 0; | |
| 1134 for (std::set<std::string>::iterator i = new_apis_only.begin(); | |
| 1135 i != new_apis_only.end(); ++i) { | |
| 1136 if (GetPermissionMessageId(*i)) | |
| 1137 new_api_count++; | |
| 1138 } | |
| 1139 | |
| 1140 if (new_api_count) | |
| 1128 return true; | 1141 return true; |
| 1129 | 1142 |
| 1130 return false; | 1143 return false; |
| 1131 } | 1144 } |
| 1132 | 1145 |
| 1133 // static | 1146 // static |
| 1134 void Extension::DecodeIcon(const Extension* extension, | 1147 void Extension::DecodeIcon(const Extension* extension, |
| 1135 Icons icon_size, | 1148 Icons icon_size, |
| 1136 scoped_ptr<SkBitmap>* result) { | 1149 scoped_ptr<SkBitmap>* result) { |
| 1137 FilePath icon_path = extension->GetIconResource( | 1150 FilePath icon_path = extension->GetIconResource( |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1699 continue; | 1712 continue; |
| 1700 } | 1713 } |
| 1701 } else { | 1714 } else { |
| 1702 // Hosted apps only get access to a subset of the valid permissions. | 1715 // Hosted apps only get access to a subset of the valid permissions. |
| 1703 if (IsHostedAppPermission(permission_str)) { | 1716 if (IsHostedAppPermission(permission_str)) { |
| 1704 api_permissions_.insert(permission_str); | 1717 api_permissions_.insert(permission_str); |
| 1705 continue; | 1718 continue; |
| 1706 } | 1719 } |
| 1707 } | 1720 } |
| 1708 | 1721 |
| 1709 // Otherwise, it's a host pattern permission. | 1722 // Check if it's a host pattern permission. |
| 1710 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ? | 1723 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ? |
| 1711 URLPattern::SCHEME_ALL : | 1724 URLPattern::SCHEME_ALL : |
| 1712 (UserScript::kValidUserScriptSchemes | | 1725 (UserScript::kValidUserScriptSchemes | |
| 1713 URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE); | 1726 URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE); |
| 1714 | 1727 |
| 1715 if (URLPattern::PARSE_SUCCESS != pattern.Parse(permission_str)) { | 1728 if (URLPattern::PARSE_SUCCESS == pattern.Parse(permission_str)) { |
| 1716 *error = ExtensionErrorUtils::FormatErrorMessage( | 1729 if (!CanSpecifyHostPermission(pattern)) { |
| 1717 errors::kInvalidPermission, base::IntToString(i)); | 1730 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 1718 return false; | 1731 errors::kInvalidPermissionScheme, base::IntToString(i)); |
| 1732 return false; | |
| 1733 } | |
| 1734 | |
| 1735 // The path component is not used for host permissions, so we force it | |
| 1736 // to match all paths. | |
| 1737 pattern.set_path("/*"); | |
| 1738 | |
| 1739 host_permissions_.push_back(pattern); | |
| 1719 } | 1740 } |
| 1720 | 1741 |
| 1721 if (!CanSpecifyHostPermission(pattern)) { | 1742 // If it's not a host permission, then it's probably an unknown API |
| 1722 *error = ExtensionErrorUtils::FormatErrorMessage( | 1743 // permission. Do not throw an error so extensions can retain |
| 1723 errors::kInvalidPermissionScheme, base::IntToString(i)); | 1744 // backwards compatability (http://crbug.com/42742). |
| 1724 return false; | 1745 // TODO(jstritar): We could add better validation of API permissions here |
| 1725 } | 1746 // if we'd like to improve error messages. |
| 1726 | |
| 1727 // The path component is not used for host permissions, so we force it to | |
| 1728 // match all paths. | |
| 1729 pattern.set_path("/*"); | |
| 1730 | |
| 1731 host_permissions_.push_back(pattern); | |
| 1732 } | 1747 } |
| 1733 } | 1748 } |
| 1734 | 1749 |
| 1735 if (source.HasKey(keys::kDefaultLocale)) { | 1750 if (source.HasKey(keys::kDefaultLocale)) { |
| 1736 if (!source.GetString(keys::kDefaultLocale, | 1751 if (!source.GetString(keys::kDefaultLocale, |
| 1737 &default_locale_) || | 1752 &default_locale_) || |
| 1738 default_locale_.empty()) { | 1753 default_locale_.empty()) { |
| 1739 *error = errors::kInvalidDefaultLocale; | 1754 *error = errors::kInvalidDefaultLocale; |
| 1740 return false; | 1755 return false; |
| 1741 } | 1756 } |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2115 } | 2130 } |
| 2116 | 2131 |
| 2117 if (error) { | 2132 if (error) { |
| 2118 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, | 2133 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, |
| 2119 page_url.spec()); | 2134 page_url.spec()); |
| 2120 } | 2135 } |
| 2121 | 2136 |
| 2122 return false; | 2137 return false; |
| 2123 } | 2138 } |
| 2124 | 2139 |
| 2125 bool Extension::HasEffectiveAccessToAllHosts() const { | 2140 // static |
| 2141 bool Extension::HasEffectiveAccessToAllHosts( | |
| 2142 const ExtensionExtent& effective_host_permissions, | |
| 2143 const std::set<std::string>& api_permissions) { | |
| 2126 // Some APIs effectively grant access to every site. New ones should be | 2144 // Some APIs effectively grant access to every site. New ones should be |
| 2127 // added here. (I'm looking at you, network API) | 2145 // added here. (I'm looking at you, network API) |
| 2128 if (HasApiPermission(kProxyPermission)) | 2146 if (HasApiPermission(api_permissions, kProxyPermission)) |
| 2129 return true; | 2147 return true; |
| 2130 | 2148 |
| 2131 for (URLPatternList::const_iterator host = host_permissions().begin(); | 2149 const URLPatternList patterns = effective_host_permissions.patterns(); |
| 2132 host != host_permissions().end(); ++host) { | 2150 for (URLPatternList::const_iterator host = patterns.begin(); |
| 2151 host != patterns.end(); ++host) { | |
| 2133 if (host->match_subdomains() && host->host().empty()) | 2152 if (host->match_subdomains() && host->host().empty()) |
| 2134 return true; | 2153 return true; |
| 2135 } | 2154 } |
| 2136 | 2155 |
| 2137 for (UserScriptList::const_iterator content_script = | |
| 2138 content_scripts().begin(); | |
| 2139 content_script != content_scripts().end(); ++content_script) { | |
| 2140 UserScript::PatternList::const_iterator pattern = | |
| 2141 content_script->url_patterns().begin(); | |
| 2142 for (; pattern != content_script->url_patterns().end(); ++pattern) { | |
| 2143 if (pattern->match_subdomains() && pattern->host().empty()) | |
| 2144 return true; | |
| 2145 } | |
| 2146 } | |
| 2147 | |
| 2148 return false; | 2156 return false; |
| 2149 } | 2157 } |
| 2150 | 2158 |
| 2159 bool Extension::HasEffectiveAccessToAllHosts() const { | |
| 2160 return HasEffectiveAccessToAllHosts(GetEffectiveHostPermissions(), | |
| 2161 api_permissions()); | |
| 2162 } | |
| 2163 | |
| 2151 bool Extension::IsAPIPermission(const std::string& str) const { | 2164 bool Extension::IsAPIPermission(const std::string& str) const { |
| 2152 for (size_t i = 0; i < Extension::kNumPermissions; ++i) { | 2165 for (size_t i = 0; i < Extension::kNumPermissions; ++i) { |
| 2153 if (str == Extension::kPermissions[i].name) { | 2166 if (str == Extension::kPermissions[i].name) { |
| 2154 // Only allow the experimental API permission if the command line | 2167 // Only allow the experimental API permission if the command line |
| 2155 // flag is present, or if the extension is a component of Chrome. | 2168 // flag is present, or if the extension is a component of Chrome. |
| 2156 if (str == Extension::kExperimentalPermission) { | 2169 if (str == Extension::kExperimentalPermission) { |
| 2157 if (CommandLine::ForCurrentProcess()->HasSwitch( | 2170 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 2158 switches::kEnableExperimentalExtensionApis)) { | 2171 switches::kEnableExperimentalExtensionApis)) { |
| 2159 return true; | 2172 return true; |
| 2160 } else if (location() == Extension::COMPONENT) { | 2173 } else if (location() == Extension::COMPONENT) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2209 UninstalledExtensionInfo::UninstalledExtensionInfo( | 2222 UninstalledExtensionInfo::UninstalledExtensionInfo( |
| 2210 const Extension& extension) | 2223 const Extension& extension) |
| 2211 : extension_id(extension.id()), | 2224 : extension_id(extension.id()), |
| 2212 extension_api_permissions(extension.api_permissions()), | 2225 extension_api_permissions(extension.api_permissions()), |
| 2213 is_theme(extension.is_theme()), | 2226 is_theme(extension.is_theme()), |
| 2214 is_app(extension.is_app()), | 2227 is_app(extension.is_app()), |
| 2215 converted_from_user_script(extension.converted_from_user_script()), | 2228 converted_from_user_script(extension.converted_from_user_script()), |
| 2216 update_url(extension.update_url()) {} | 2229 update_url(extension.update_url()) {} |
| 2217 | 2230 |
| 2218 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} | 2231 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} |
| OLD | NEW |