Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/browser/extensions/extension_permissions_api.h" | 5 #include "chrome/browser/extensions/extension_permissions_api.h" |
| 6 | 6 |
| 7 #include "base/json/json_writer.h" | 7 #include "base/json/json_writer.h" |
| 8 #include "base/stringprintf.h" | |
| 9 #include "base/values.h" | 8 #include "base/values.h" |
| 10 #include "chrome/browser/extensions/extension_event_router.h" | 9 #include "chrome/browser/extensions/extension_event_router.h" |
| 11 #include "chrome/browser/extensions/extension_permissions_api_constants.h" | 10 #include "chrome/browser/extensions/extension_permissions_api_constants.h" |
| 12 #include "chrome/browser/extensions/extension_prefs.h" | 11 #include "chrome/browser/extensions/extension_prefs.h" |
| 13 #include "chrome/browser/extensions/extension_service.h" | 12 #include "chrome/browser/extensions/extension_service.h" |
| 14 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/common/chrome_notification_types.h" | 14 #include "chrome/common/chrome_notification_types.h" |
| 16 #include "chrome/common/extensions/extension.h" | 15 #include "chrome/common/extensions/extension.h" |
| 16 #include "chrome/common/extensions/extension_error_utils.h" | |
| 17 #include "chrome/common/extensions/extension_messages.h" | 17 #include "chrome/common/extensions/extension_messages.h" |
| 18 #include "chrome/common/extensions/extension_permission_set.h" | 18 #include "chrome/common/extensions/extension_permission_set.h" |
| 19 #include "chrome/common/extensions/url_pattern_set.h" | 19 #include "chrome/common/extensions/url_pattern_set.h" |
| 20 #include "content/common/notification_service.h" | 20 #include "content/common/notification_service.h" |
| 21 #include "googleurl/src/gurl.h" | 21 #include "googleurl/src/gurl.h" |
| 22 | 22 |
| 23 | 23 |
| 24 namespace keys = extension_permissions_module_constants; | 24 namespace keys = extension_permissions_module_constants; |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 enum AutoConfirmForTest { | 28 enum AutoConfirmForTest { |
| 29 DO_NOT_SKIP = 0, | 29 DO_NOT_SKIP = 0, |
| 30 PROCEED, | 30 PROCEED, |
| 31 ABORT | 31 ABORT |
| 32 }; | 32 }; |
| 33 AutoConfirmForTest auto_confirm_for_tests = DO_NOT_SKIP; | 33 AutoConfirmForTest auto_confirm_for_tests = DO_NOT_SKIP; |
| 34 | 34 |
| 35 DictionaryValue* PackPermissionsToValue(const ExtensionPermissionSet* set) { | 35 DictionaryValue* PackPermissionsToValue(const ExtensionPermissionSet* set) { |
| 36 DictionaryValue* value = new DictionaryValue(); | 36 DictionaryValue* value = new DictionaryValue(); |
| 37 | 37 |
| 38 // Generate the list of API permissions. | 38 // Generate the list of API permissions. |
| 39 ListValue* apis = new ListValue(); | 39 ListValue* apis = new ListValue(); |
| 40 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); | 40 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); |
| 41 for (ExtensionAPIPermissionSet::const_iterator i = set->apis().begin(); | 41 for (ExtensionAPIPermissionSet::const_iterator i = set->apis().begin(); |
| 42 i != set->apis().end(); ++i) | 42 i != set->apis().end(); ++i) |
| 43 apis->Append(Value::CreateStringValue(info->GetByID(*i)->name())); | 43 apis->Append(Value::CreateStringValue(info->GetByID(*i)->name())); |
| 44 | 44 |
| 45 // TODO(jstritar): Include hosts once the API supports them. At that point, | 45 // Generate the list of origin permissions. |
| 46 // we could also shared this code with ExtensionPermissionSet methods in | 46 URLPatternSet hosts = set->explicit_hosts(); |
| 47 // ExtensionPrefs. | 47 ListValue* origins = new ListValue(); |
| 48 for (URLPatternSet::const_iterator i = hosts.begin(); i != hosts.end(); ++i) | |
| 49 origins->Append(Value::CreateStringValue(i->GetAsString())); | |
| 48 | 50 |
| 49 value->Set(keys::kApisKey, apis); | 51 value->Set(keys::kApisKey, apis); |
| 52 value->Set(keys::kOriginsKey, origins); | |
| 50 return value; | 53 return value; |
| 51 } | 54 } |
| 52 | 55 |
| 53 // Creates a new ExtensionPermissionSet from its |value| and passes ownership to | 56 // Creates a new ExtensionPermissionSet from its |value| and passes ownership to |
| 54 // the caller through |ptr|. Sets |bad_message| to true if the message is badly | 57 // the caller through |ptr|. Sets |bad_message| to true if the message is badly |
| 55 // formed. Returns false if the method fails to unpack a permission set. | 58 // formed. Returns false if the method fails to unpack a permission set. |
| 56 bool UnpackPermissionsFromValue(DictionaryValue* value, | 59 bool UnpackPermissionsFromValue(DictionaryValue* value, |
| 57 scoped_refptr<ExtensionPermissionSet>* ptr, | 60 scoped_refptr<ExtensionPermissionSet>* ptr, |
| 58 bool* bad_message, | 61 bool* bad_message, |
| 59 std::string* error) { | 62 std::string* error) { |
| 60 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); | 63 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); |
| 61 ExtensionAPIPermissionSet apis; | 64 ExtensionAPIPermissionSet apis; |
| 62 if (value->HasKey(keys::kApisKey)) { | 65 if (value->HasKey(keys::kApisKey)) { |
| 63 ListValue* api_list = NULL; | 66 ListValue* api_list = NULL; |
| 64 if (!value->GetList(keys::kApisKey, &api_list)) { | 67 if (!value->GetList(keys::kApisKey, &api_list)) { |
| 65 *bad_message = true; | 68 *bad_message = true; |
| 66 return false; | 69 return false; |
| 67 } | 70 } |
| 68 for (size_t i = 0; i < api_list->GetSize(); ++i) { | 71 for (size_t i = 0; i < api_list->GetSize(); ++i) { |
| 69 std::string api_name; | 72 std::string api_name; |
| 70 if (!api_list->GetString(i, &api_name)) { | 73 if (!api_list->GetString(i, &api_name)) { |
| 71 *bad_message = true; | 74 *bad_message = true; |
| 72 return false; | 75 return false; |
| 73 } | 76 } |
| 74 | 77 |
| 75 ExtensionAPIPermission* permission = info->GetByName(api_name); | 78 ExtensionAPIPermission* permission = info->GetByName(api_name); |
| 76 if (!permission) { | 79 if (!permission) { |
| 77 *error = base::StringPrintf( | 80 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 78 keys::kUnknownPermissionError, api_name.c_str()); | 81 keys::kUnknownPermissionError, api_name); |
| 79 return false; | 82 return false; |
| 80 } | 83 } |
| 81 apis.insert(permission->id()); | 84 apis.insert(permission->id()); |
| 82 } | 85 } |
| 83 } | 86 } |
| 84 | 87 |
| 85 // Ignore host permissions for now. | 88 URLPatternSet origins; |
| 86 URLPatternSet empty_set; | 89 if (value->HasKey(keys::kOriginsKey)) { |
| 87 *ptr = new ExtensionPermissionSet(apis, empty_set, empty_set); | 90 ListValue* origin_list = NULL; |
| 91 if (!value->GetList(keys::kOriginsKey, &origin_list)) { | |
| 92 *bad_message = true; | |
| 93 return false; | |
| 94 } | |
| 95 for (size_t i = 0; i < origin_list->GetSize(); ++i) { | |
| 96 std::string pattern; | |
| 97 if (!origin_list->GetString(i, &pattern)) { | |
| 98 *bad_message = true; | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 URLPattern origin(Extension::kValidHostPermissionSchemes); | |
| 103 URLPattern::ParseResult parse_result = | |
| 104 origin.Parse(pattern, URLPattern::USE_PORTS); | |
|
Matt Perry
2011/08/03 22:08:14
shouldn't we use IGNORE_PORTS to match what we do
jstritar
2011/08/04 16:35:15
yes, thanks. done.
| |
| 105 if (URLPattern::PARSE_SUCCESS != parse_result) { | |
| 106 *error = ExtensionErrorUtils::FormatErrorMessage( | |
| 107 keys::kInvalidOrigin, | |
| 108 pattern, | |
| 109 URLPattern::GetParseResultString(parse_result)); | |
| 110 return false; | |
| 111 } | |
| 112 origins.AddPattern(origin); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 *ptr = new ExtensionPermissionSet(apis, origins, URLPatternSet()); | |
| 88 return true; | 117 return true; |
| 89 } | 118 } |
| 90 | 119 |
| 91 } // namespace | 120 } // namespace |
| 92 | 121 |
| 93 ExtensionPermissionsManager::ExtensionPermissionsManager( | 122 ExtensionPermissionsManager::ExtensionPermissionsManager( |
| 94 ExtensionService* extension_service) | 123 ExtensionService* extension_service) |
| 95 : extension_service_(extension_service) {} | 124 : extension_service_(extension_service) {} |
| 96 | 125 |
| 97 ExtensionPermissionsManager::~ExtensionPermissionsManager() {} | 126 ExtensionPermissionsManager::~ExtensionPermissionsManager() {} |
| 98 | 127 |
| 99 void ExtensionPermissionsManager::AddPermissions( | 128 void ExtensionPermissionsManager::AddPermissions( |
| 100 const Extension* extension, const ExtensionPermissionSet* permissions) { | 129 const Extension* extension, const ExtensionPermissionSet* permissions) { |
| 101 scoped_refptr<const ExtensionPermissionSet> existing( | 130 scoped_refptr<const ExtensionPermissionSet> existing( |
| 102 extension->GetActivePermissions()); | 131 extension->GetActivePermissions()); |
| 103 scoped_refptr<ExtensionPermissionSet> total( | 132 scoped_refptr<ExtensionPermissionSet> total( |
| 104 ExtensionPermissionSet::CreateUnion(existing, permissions)); | 133 ExtensionPermissionSet::CreateUnion(existing, permissions)); |
| 105 scoped_refptr<ExtensionPermissionSet> added( | 134 scoped_refptr<ExtensionPermissionSet> added( |
| 106 ExtensionPermissionSet::CreateDifference(total.get(), existing)); | 135 ExtensionPermissionSet::CreateDifference(total.get(), existing)); |
| 107 | 136 |
| 108 extension_service_->UpdateActivePermissions(extension, total.get()); | 137 extension_service_->UpdateActivePermissions(extension, total.get()); |
| 109 | 138 |
| 110 // Update the granted permissions so we don't auto-disable the extension. | 139 // Update the granted permissions so we don't auto-disable the extension. |
| 111 extension_service_->GrantPermissions(extension); | 140 extension_service_->GrantPermissions(extension); |
| 112 | 141 |
| 113 NotifyPermissionsUpdated(extension, total.get(), added.get(), ADDED); | 142 NotifyPermissionsUpdated(ADDED, extension, added.get()); |
| 114 } | 143 } |
| 115 | 144 |
| 116 void ExtensionPermissionsManager::RemovePermissions( | 145 void ExtensionPermissionsManager::RemovePermissions( |
| 117 const Extension* extension, const ExtensionPermissionSet* permissions) { | 146 const Extension* extension, const ExtensionPermissionSet* permissions) { |
| 118 scoped_refptr<const ExtensionPermissionSet> existing( | 147 scoped_refptr<const ExtensionPermissionSet> existing( |
| 119 extension->GetActivePermissions()); | 148 extension->GetActivePermissions()); |
| 120 scoped_refptr<ExtensionPermissionSet> total( | 149 scoped_refptr<ExtensionPermissionSet> total( |
| 121 ExtensionPermissionSet::CreateDifference(existing, permissions)); | 150 ExtensionPermissionSet::CreateDifference(existing, permissions)); |
| 122 scoped_refptr<ExtensionPermissionSet> removed( | 151 scoped_refptr<ExtensionPermissionSet> removed( |
| 123 ExtensionPermissionSet::CreateDifference(existing, total.get())); | 152 ExtensionPermissionSet::CreateDifference(existing, total.get())); |
| 124 | 153 |
| 125 // We update the active permissions, and not the granted permissions, because | 154 // We update the active permissions, and not the granted permissions, because |
| 126 // the extension, not the user, removed the permissions. This allows the | 155 // the extension, not the user, removed the permissions. This allows the |
| 127 // extension to add them again without prompting the user. | 156 // extension to add them again without prompting the user. |
| 128 extension_service_->UpdateActivePermissions(extension, total.get()); | 157 extension_service_->UpdateActivePermissions(extension, total.get()); |
| 129 | 158 |
| 130 NotifyPermissionsUpdated(extension, total.get(), removed.get(), REMOVED); | 159 NotifyPermissionsUpdated(REMOVED, extension, removed.get()); |
| 131 } | 160 } |
| 132 | 161 |
| 133 void ExtensionPermissionsManager::DispatchEvent( | 162 void ExtensionPermissionsManager::DispatchEvent( |
| 134 const std::string& extension_id, | 163 const std::string& extension_id, |
| 135 const char* event_name, | 164 const char* event_name, |
| 136 const ExtensionPermissionSet* changed_permissions) { | 165 const ExtensionPermissionSet* changed_permissions) { |
| 137 Profile* profile = extension_service_->profile(); | 166 Profile* profile = extension_service_->profile(); |
| 138 if (profile && profile->GetExtensionEventRouter()) { | 167 if (profile && profile->GetExtensionEventRouter()) { |
| 139 ListValue value; | 168 ListValue value; |
| 140 value.Append(PackPermissionsToValue(changed_permissions)); | 169 value.Append(PackPermissionsToValue(changed_permissions)); |
| 141 std::string json_value; | 170 std::string json_value; |
| 142 base::JSONWriter::Write(&value, false, &json_value); | 171 base::JSONWriter::Write(&value, false, &json_value); |
| 143 profile->GetExtensionEventRouter()->DispatchEventToExtension( | 172 profile->GetExtensionEventRouter()->DispatchEventToExtension( |
| 144 extension_id, event_name, json_value, profile, GURL()); | 173 extension_id, event_name, json_value, profile, GURL()); |
| 145 } | 174 } |
| 146 } | 175 } |
| 147 | 176 |
| 148 void ExtensionPermissionsManager::NotifyPermissionsUpdated( | 177 void ExtensionPermissionsManager::NotifyPermissionsUpdated( |
| 178 EventType event_type, | |
| 149 const Extension* extension, | 179 const Extension* extension, |
| 150 const ExtensionPermissionSet* active, | 180 const ExtensionPermissionSet* changed) { |
| 151 const ExtensionPermissionSet* changed, | |
| 152 EventType event_type) { | |
| 153 if (!changed || changed->IsEmpty()) | 181 if (!changed || changed->IsEmpty()) |
| 154 return; | 182 return; |
| 155 | 183 |
| 156 UpdatedExtensionPermissionsInfo::Reason reason; | 184 UpdatedExtensionPermissionsInfo::Reason reason; |
| 157 const char* event_name = NULL; | 185 const char* event_name = NULL; |
| 158 | 186 |
| 159 if (event_type == REMOVED) { | 187 if (event_type == REMOVED) { |
| 160 reason = UpdatedExtensionPermissionsInfo::REMOVED; | 188 reason = UpdatedExtensionPermissionsInfo::REMOVED; |
| 161 event_name = keys::kOnRemoved; | 189 event_name = keys::kOnRemoved; |
| 162 } else { | 190 } else { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 175 | 203 |
| 176 // Trigger the onAdded and onRemoved events in the extension. | 204 // Trigger the onAdded and onRemoved events in the extension. |
| 177 DispatchEvent(extension->id(), event_name, changed); | 205 DispatchEvent(extension->id(), event_name, changed); |
| 178 | 206 |
| 179 // Send the new permissions to the renderers. | 207 // Send the new permissions to the renderers. |
| 180 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 208 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 181 !i.IsAtEnd(); i.Advance()) { | 209 !i.IsAtEnd(); i.Advance()) { |
| 182 RenderProcessHost* host = i.GetCurrentValue(); | 210 RenderProcessHost* host = i.GetCurrentValue(); |
| 183 Profile* profile = Profile::FromBrowserContext(host->browser_context()); | 211 Profile* profile = Profile::FromBrowserContext(host->browser_context()); |
| 184 if (extension_service_->profile()->IsSameProfile(profile)) | 212 if (extension_service_->profile()->IsSameProfile(profile)) |
| 185 host->Send(new ExtensionMsg_UpdatePermissions( | 213 host->Send(new ExtensionMsg_UpdatePermissions( |
|
Matt Perry
2011/08/03 22:08:14
Since we're only sending updates to renderers, wha
jstritar
2011/08/04 16:35:15
The is handled by the ExtensionMsg_Loaded message,
| |
| 214 static_cast<int>(reason), | |
| 186 extension->id(), | 215 extension->id(), |
| 187 active->apis(), | 216 changed->apis(), |
| 188 active->explicit_hosts(), | 217 changed->explicit_hosts(), |
| 189 active->scriptable_hosts())); | 218 changed->scriptable_hosts())); |
| 190 } | 219 } |
| 191 } | 220 } |
| 192 | 221 |
| 193 bool ContainsPermissionsFunction::RunImpl() { | 222 bool ContainsPermissionsFunction::RunImpl() { |
| 194 DictionaryValue* args = NULL; | 223 DictionaryValue* args = NULL; |
| 195 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); | 224 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); |
| 196 std::string error; | 225 std::string error; |
| 197 if (!args) | 226 if (!args) |
| 198 return false; | 227 return false; |
| 199 | 228 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 228 ExtensionPermissionsManager* perms_manager = | 257 ExtensionPermissionsManager* perms_manager = |
| 229 profile()->GetExtensionService()->permissions_manager(); | 258 profile()->GetExtensionService()->permissions_manager(); |
| 230 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); | 259 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); |
| 231 | 260 |
| 232 // Make sure they're only trying to remove permissions supported by this API. | 261 // Make sure they're only trying to remove permissions supported by this API. |
| 233 ExtensionAPIPermissionSet apis = permissions->apis(); | 262 ExtensionAPIPermissionSet apis = permissions->apis(); |
| 234 for (ExtensionAPIPermissionSet::const_iterator i = apis.begin(); | 263 for (ExtensionAPIPermissionSet::const_iterator i = apis.begin(); |
| 235 i != apis.end(); ++i) { | 264 i != apis.end(); ++i) { |
| 236 const ExtensionAPIPermission* api = info->GetByID(*i); | 265 const ExtensionAPIPermission* api = info->GetByID(*i); |
| 237 if (!api->supports_optional()) { | 266 if (!api->supports_optional()) { |
| 238 error_ = base::StringPrintf(keys::kNotWhitelistedError, api->name()); | 267 error_ = ExtensionErrorUtils::FormatErrorMessage( |
| 268 keys::kNotWhitelistedError, api->name()); | |
| 239 return false; | 269 return false; |
| 240 } | 270 } |
| 241 } | 271 } |
| 242 | 272 |
| 243 // Make sure we don't remove any required pemissions. | 273 // Make sure we don't remove any required pemissions. |
| 244 const ExtensionPermissionSet* required = extension->required_permission_set(); | 274 const ExtensionPermissionSet* required = extension->required_permission_set(); |
| 245 scoped_refptr<ExtensionPermissionSet> intersection( | 275 scoped_refptr<ExtensionPermissionSet> intersection( |
| 246 ExtensionPermissionSet::CreateIntersection(permissions.get(), required)); | 276 ExtensionPermissionSet::CreateIntersection(permissions.get(), required)); |
| 247 if (!intersection->IsEmpty()) { | 277 if (!intersection->IsEmpty()) { |
| 248 error_ = keys::kCantRemoveRequiredPermissionsError; | 278 error_ = keys::kCantRemoveRequiredPermissionsError; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 279 ExtensionPermissionsManager* perms_manager = | 309 ExtensionPermissionsManager* perms_manager = |
| 280 profile()->GetExtensionService()->permissions_manager(); | 310 profile()->GetExtensionService()->permissions_manager(); |
| 281 ExtensionPrefs* prefs = profile()->GetExtensionService()->extension_prefs(); | 311 ExtensionPrefs* prefs = profile()->GetExtensionService()->extension_prefs(); |
| 282 | 312 |
| 283 // Make sure they're only requesting permissions supported by this API. | 313 // Make sure they're only requesting permissions supported by this API. |
| 284 ExtensionAPIPermissionSet apis = requested_permissions_->apis(); | 314 ExtensionAPIPermissionSet apis = requested_permissions_->apis(); |
| 285 for (ExtensionAPIPermissionSet::const_iterator i = apis.begin(); | 315 for (ExtensionAPIPermissionSet::const_iterator i = apis.begin(); |
| 286 i != apis.end(); ++i) { | 316 i != apis.end(); ++i) { |
| 287 const ExtensionAPIPermission* api = info->GetByID(*i); | 317 const ExtensionAPIPermission* api = info->GetByID(*i); |
| 288 if (!api->supports_optional()) { | 318 if (!api->supports_optional()) { |
| 289 error_ = base::StringPrintf(keys::kNotWhitelistedError, api->name()); | 319 error_ = ExtensionErrorUtils::FormatErrorMessage( |
| 320 keys::kNotWhitelistedError, api->name()); | |
| 290 return false; | 321 return false; |
| 291 } | 322 } |
| 292 } | 323 } |
| 293 | 324 |
| 294 // The requested permissions must be defined as optional in the manifest. | 325 // The requested permissions must be defined as optional in the manifest. |
| 295 if (!extension_->optional_permission_set()->Contains( | 326 if (!extension_->optional_permission_set()->Contains( |
| 296 *requested_permissions_)) { | 327 *requested_permissions_)) { |
| 297 error_ = keys::kNotInOptionalPermissionsError; | 328 error_ = keys::kNotInOptionalPermissionsError; |
| 298 result_.reset(Value::CreateBooleanValue(false)); | 329 result_.reset(Value::CreateBooleanValue(false)); |
| 299 return false; | 330 return false; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 } | 381 } |
| 351 | 382 |
| 352 void RequestPermissionsFunction::InstallUIAbort(bool user_initiated) { | 383 void RequestPermissionsFunction::InstallUIAbort(bool user_initiated) { |
| 353 install_ui_.reset(); | 384 install_ui_.reset(); |
| 354 result_.reset(Value::CreateBooleanValue(false)); | 385 result_.reset(Value::CreateBooleanValue(false)); |
| 355 requested_permissions_ = NULL; | 386 requested_permissions_ = NULL; |
| 356 | 387 |
| 357 SendResponse(true); | 388 SendResponse(true); |
| 358 Release(); | 389 Release(); |
| 359 } | 390 } |
| OLD | NEW |