Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: chrome/common/extensions/extension.cc

Issue 4687005: Track permissions granted to extensions in prefs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: missed updating a method call Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 static void ConvertHexadecimalToIDAlphabet(std::string* id) { 64 static void ConvertHexadecimalToIDAlphabet(std::string* id) {
65 for (size_t i = 0; i < id->size(); ++i) { 65 for (size_t i = 0; i < id->size(); ++i) {
66 int val; 66 int val;
67 if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val)) 67 if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val))
68 (*id)[i] = val + 'a'; 68 (*id)[i] = val + 'a';
69 else 69 else
70 (*id)[i] = 'a'; 70 (*id)[i] = 'a';
71 } 71 }
72 } 72 }
73 73
74 const int kValidWebExtentSchemes =
75 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
76
77 // These keys are allowed by all crx files (apps, extensions, themes, etc). 74 // These keys are allowed by all crx files (apps, extensions, themes, etc).
78 static const char* kBaseCrxKeys[] = { 75 static const char* kBaseCrxKeys[] = {
79 keys::kCurrentLocale, 76 keys::kCurrentLocale,
80 keys::kDefaultLocale, 77 keys::kDefaultLocale,
81 keys::kDescription, 78 keys::kDescription,
82 keys::kIcons, 79 keys::kIcons,
83 keys::kName, 80 keys::kName,
84 keys::kPublicKey, 81 keys::kPublicKey,
85 keys::kSignature, 82 keys::kSignature,
86 keys::kVersion, 83 keys::kVersion,
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 Extension::kNotificationPermission, 240 Extension::kNotificationPermission,
244 Extension::kUnlimitedStoragePermission, 241 Extension::kUnlimitedStoragePermission,
245 Extension::kWebstorePrivatePermission, 242 Extension::kWebstorePrivatePermission,
246 }; 243 };
247 const size_t Extension::kNumHostedAppPermissions = 244 const size_t Extension::kNumHostedAppPermissions =
248 arraysize(Extension::kHostedAppPermissionNames); 245 arraysize(Extension::kHostedAppPermissionNames);
249 246
250 // We purposefully don't put this into kPermissionNames. 247 // We purposefully don't put this into kPermissionNames.
251 const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage"; 248 const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage";
252 249
250 const int Extension::kValidWebExtentSchemes =
251 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
252
253 // 253 //
254 // Extension 254 // Extension
255 // 255 //
256 256
257 // static 257 // static
258 scoped_refptr<Extension> Extension::Create(const FilePath& path, 258 scoped_refptr<Extension> Extension::Create(const FilePath& path,
259 Location location, 259 Location location,
260 const DictionaryValue& value, 260 const DictionaryValue& value,
261 bool require_key, 261 bool require_key,
262 std::string* error) { 262 std::string* error) {
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 bool granted_full_access,
1083 // extensions that require less permissions than the current version, but then 1083 const std::set<std::string>& granted_apis,
1084 // we don't silently allow them to go back. In order to fix this, we would need 1084 const ExtensionExtent& granted_extent,
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 // If the extension had native code access, we don't need to go any further.
1089 // further. Things can't get any worse. 1087 // Things can't get any worse.
1090 if (old_extension->plugins().size() > 0) 1088 if (granted_full_access)
1091 return false; 1089 return false;
1092 1090
1093 // Otherwise, if the new extension has a plugin, it's a privilege increase. 1091 // Otherwise, if the new extension has a plugin, it's a privilege increase.
1094 if (new_extension->plugins().size() > 0) 1092 if (new_extension->plugins().size() > 0)
1095 return true; 1093 return true;
1096 1094
1097 // If we are increasing the set of hosts we have access to (not 1095 // If the extension hadn't been granted access to all hosts in the past, then
1098 // counting scheme differences), it's a privilege increase. 1096 // see if the extension requires more host permissions.
1099 if (!old_extension->HasEffectiveAccessToAllHosts()) { 1097 if (!HasEffectiveAccessToAllHosts(granted_extent, granted_apis)) {
1100 if (new_extension->HasEffectiveAccessToAllHosts()) 1098 if (new_extension->HasEffectiveAccessToAllHosts())
1101 return true; 1099 return true;
1102 1100
1103 // TODO(erikkay) This will trip when you add a new distinct hostname, 1101 const ExtensionExtent new_extent =
1104 // but we should unique based on RCD as well. crbug.com/57042 1102 new_extension->GetEffectiveHostPermissions();
1105 std::vector<std::string> old_hosts = old_extension->GetDistinctHosts(); 1103 std::vector<std::string> new_hosts =
1106 std::vector<std::string> new_hosts = new_extension->GetDistinctHosts(); 1104 GetDistinctHosts(new_extent.patterns());
1105 std::vector<std::string> old_hosts =
1106 GetDistinctHosts(granted_extent.patterns());
1107
1107 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end()); 1108 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()); 1109 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end());
1109 std::set<std::string> new_only; 1110 std::set<std::string> new_hosts_only;
1111
1110 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(), 1112 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
1111 old_hosts_set.begin(), old_hosts_set.end(), 1113 old_hosts_set.begin(), old_hosts_set.end(),
1112 std::inserter(new_only, new_only.end())); 1114 std::inserter(new_hosts_only, new_hosts_only.end()));
1113 if (new_only.size()) 1115
1116 if (new_hosts_only.size())
1114 return true; 1117 return true;
1115 } 1118 }
1116 1119
1117 std::set<string16> old_messages = 1120 std::set<std::string> new_apis = new_extension->api_permissions();
1118 old_extension->GetSimplePermissionMessages(); 1121 std::set<std::string> new_apis_only;
1119 std::set<string16> new_messages = 1122 std::set_difference(new_apis.begin(), new_apis.end(),
1120 new_extension->GetSimplePermissionMessages(); 1123 granted_apis.begin(), granted_apis.end(),
1121 std::set<string16> new_only; 1124 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 1125
1126 // If there are any new permission messages, then it's an increase. 1126 // Ignore API permissions that don't require user approval when deciding if
1127 if (!new_only.empty()) 1127 // an extension has increased its privileges.
1128 size_t new_api_count = 0;
1129 for (std::set<std::string>::iterator i = new_apis_only.begin();
1130 i != new_apis_only.end(); ++i) {
1131 if (GetPermissionMessageId(*i))
1132 new_api_count++;
1133 }
1134
1135 if (new_api_count)
1128 return true; 1136 return true;
1129 1137
1130 return false; 1138 return false;
1131 } 1139 }
1132 1140
1133 // static 1141 // static
1134 void Extension::DecodeIcon(const Extension* extension, 1142 void Extension::DecodeIcon(const Extension* extension,
1135 Icons icon_size, 1143 Icons icon_size,
1136 scoped_ptr<SkBitmap>* result) { 1144 scoped_ptr<SkBitmap>* result) {
1137 FilePath icon_path = extension->GetIconResource( 1145 FilePath icon_path = extension->GetIconResource(
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 continue; 1707 continue;
1700 } 1708 }
1701 } else { 1709 } else {
1702 // Hosted apps only get access to a subset of the valid permissions. 1710 // Hosted apps only get access to a subset of the valid permissions.
1703 if (IsHostedAppPermission(permission_str)) { 1711 if (IsHostedAppPermission(permission_str)) {
1704 api_permissions_.insert(permission_str); 1712 api_permissions_.insert(permission_str);
1705 continue; 1713 continue;
1706 } 1714 }
1707 } 1715 }
1708 1716
1709 // Otherwise, it's a host pattern permission. 1717 // Check if it's a host pattern permission.
1710 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ? 1718 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
1711 URLPattern::SCHEME_ALL : 1719 URLPattern::SCHEME_ALL :
1712 (UserScript::kValidUserScriptSchemes | 1720 (UserScript::kValidUserScriptSchemes |
1713 URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE); 1721 URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE);
1714 1722
1715 if (URLPattern::PARSE_SUCCESS != pattern.Parse(permission_str)) { 1723 if (URLPattern::PARSE_SUCCESS == pattern.Parse(permission_str)) {
1716 *error = ExtensionErrorUtils::FormatErrorMessage( 1724 if (!CanSpecifyHostPermission(pattern)) {
1717 errors::kInvalidPermission, base::IntToString(i)); 1725 *error = ExtensionErrorUtils::FormatErrorMessage(
1718 return false; 1726 errors::kInvalidPermissionScheme, base::IntToString(i));
1727 return false;
1728 }
1729
1730 // The path component is not used for host permissions, so we force it
1731 // to match all paths.
1732 pattern.set_path("/*");
1733
1734 host_permissions_.push_back(pattern);
1719 } 1735 }
1720 1736
1721 if (!CanSpecifyHostPermission(pattern)) { 1737 // If it's not a host permission, then it's probably an unknown API
1722 *error = ExtensionErrorUtils::FormatErrorMessage( 1738 // permission. Do not throw an error so extensions can retain
1723 errors::kInvalidPermissionScheme, base::IntToString(i)); 1739 // backwards compatability (http://crbug.com/42742).
1724 return false; 1740 // TODO(jstritar): We can improve error messages by adding better
1725 } 1741 // validation of API permissions here.
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 } 1742 }
1733 } 1743 }
1734 1744
1735 if (source.HasKey(keys::kDefaultLocale)) { 1745 if (source.HasKey(keys::kDefaultLocale)) {
1736 if (!source.GetString(keys::kDefaultLocale, 1746 if (!source.GetString(keys::kDefaultLocale,
1737 &default_locale_) || 1747 &default_locale_) ||
1738 default_locale_.empty()) { 1748 default_locale_.empty()) {
1739 *error = errors::kInvalidDefaultLocale; 1749 *error = errors::kInvalidDefaultLocale;
1740 return false; 1750 return false;
1741 } 1751 }
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
2115 } 2125 }
2116 2126
2117 if (error) { 2127 if (error) {
2118 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, 2128 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
2119 page_url.spec()); 2129 page_url.spec());
2120 } 2130 }
2121 2131
2122 return false; 2132 return false;
2123 } 2133 }
2124 2134
2125 bool Extension::HasEffectiveAccessToAllHosts() const { 2135 // static
2136 bool Extension::HasEffectiveAccessToAllHosts(
2137 const ExtensionExtent& effective_host_permissions,
2138 const std::set<std::string>& api_permissions) {
2126 // Some APIs effectively grant access to every site. New ones should be 2139 // Some APIs effectively grant access to every site. New ones should be
2127 // added here. (I'm looking at you, network API) 2140 // added here. (I'm looking at you, network API)
2128 if (HasApiPermission(kProxyPermission)) 2141 if (HasApiPermission(api_permissions, kProxyPermission))
2129 return true; 2142 return true;
2130 2143
2131 for (URLPatternList::const_iterator host = host_permissions().begin(); 2144 const URLPatternList patterns = effective_host_permissions.patterns();
2132 host != host_permissions().end(); ++host) { 2145 for (URLPatternList::const_iterator host = patterns.begin();
2146 host != patterns.end(); ++host) {
2133 if (host->match_subdomains() && host->host().empty()) 2147 if (host->match_subdomains() && host->host().empty())
2134 return true; 2148 return true;
2135 } 2149 }
2136 2150
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; 2151 return false;
2149 } 2152 }
2150 2153
2154 bool Extension::HasEffectiveAccessToAllHosts() const {
2155 return HasEffectiveAccessToAllHosts(GetEffectiveHostPermissions(),
2156 api_permissions());
2157 }
2158
2151 bool Extension::IsAPIPermission(const std::string& str) const { 2159 bool Extension::IsAPIPermission(const std::string& str) const {
2152 for (size_t i = 0; i < Extension::kNumPermissions; ++i) { 2160 for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
2153 if (str == Extension::kPermissions[i].name) { 2161 if (str == Extension::kPermissions[i].name) {
2154 // Only allow the experimental API permission if the command line 2162 // Only allow the experimental API permission if the command line
2155 // flag is present, or if the extension is a component of Chrome. 2163 // flag is present, or if the extension is a component of Chrome.
2156 if (str == Extension::kExperimentalPermission) { 2164 if (str == Extension::kExperimentalPermission) {
2157 if (CommandLine::ForCurrentProcess()->HasSwitch( 2165 if (CommandLine::ForCurrentProcess()->HasSwitch(
2158 switches::kEnableExperimentalExtensionApis)) { 2166 switches::kEnableExperimentalExtensionApis)) {
2159 return true; 2167 return true;
2160 } else if (location() == Extension::COMPONENT) { 2168 } else if (location() == Extension::COMPONENT) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 UninstalledExtensionInfo::UninstalledExtensionInfo( 2217 UninstalledExtensionInfo::UninstalledExtensionInfo(
2210 const Extension& extension) 2218 const Extension& extension)
2211 : extension_id(extension.id()), 2219 : extension_id(extension.id()),
2212 extension_api_permissions(extension.api_permissions()), 2220 extension_api_permissions(extension.api_permissions()),
2213 is_theme(extension.is_theme()), 2221 is_theme(extension.is_theme()),
2214 is_app(extension.is_app()), 2222 is_app(extension.is_app()),
2215 converted_from_user_script(extension.converted_from_user_script()), 2223 converted_from_user_script(extension.converted_from_user_script()),
2216 update_url(extension.update_url()) {} 2224 update_url(extension.update_url()) {}
2217 2225
2218 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} 2226 UninstalledExtensionInfo::~UninstalledExtensionInfo() {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698