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

Side by Side Diff: chrome/browser/extensions/extension_permissions_api.cc

Issue 7508029: Add origin permissions to the extension permissions API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 4 months 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) 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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698