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 |