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

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

Issue 7003098: Start refractoring extension permissions into ExtensionPermissionSet. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup and update ExtensionPermissionSet data model. Created 9 years, 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/common/extensions/extension_permission_set.h"
6
7 #include <string>
8
9 #include "base/memory/singleton.h"
10 #include "base/values.h"
11 #include "base/string_number_conversions.h"
12 #include "base/utf_string_conversions.h"
13 #include "chrome/browser/extensions/extension_prefs.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "chrome/common/extensions/extension_l10n_util.h"
17 #include "chrome/common/extensions/url_pattern.h"
18 #include "chrome/common/extensions/url_pattern_set.h"
19 #include "grit/generated_resources.h"
20 #include "net/base/registry_controlled_domain.h"
21 #include "ui/base/l10n/l10n_util.h"
22
23 namespace {
24
25 ExtensionAPIPermission* GetAPIPermissionById(
26 ExtensionAPIPermission::Id id) {
27 return ExtensionPermissionsInfo::GetInstance()->GetById(id);
28 }
29
30 // Helper for GetDistinctHosts(): com > net > org > everything else.
31 bool RcdBetterThan(std::string a, std::string b) {
32 if (a == b)
33 return false;
34 if (a == "com")
35 return true;
36 if (a == "net")
37 return b != "com";
38 if (a == "org")
39 return b != "com" && b != "net";
40 return false;
41 }
42
43 // Names of API modules that do not require a permission.
44 const char kBrowserActionModuleName[] = "browserAction";
45 const char kBrowserActionsModuleName[] = "browserActions";
46 const char kDevToolsModuleName[] = "devtools";
47 const char kExtensionModuleName[] = "extension";
48 const char kI18NModuleName[] = "i18n";
49 const char kOmniboxModuleName[] = "omnibox";
50 const char kPageActionModuleName[] = "pageAction";
51 const char kPageActionsModuleName[] = "pageActions";
52 const char kTestModuleName[] = "test";
53
54 // Names of modules that can be used without listing it in the permissions
55 // section of the manifest.
56 const char* kNonPermissionModuleNames[] = {
57 kBrowserActionModuleName,
58 kBrowserActionsModuleName,
59 kDevToolsModuleName,
60 kExtensionModuleName,
61 kI18NModuleName,
62 kOmniboxModuleName,
63 kPageActionModuleName,
64 kPageActionsModuleName,
65 kTestModuleName
66 };
67 const size_t kNumNonPermissionModuleNames =
68 arraysize(kNonPermissionModuleNames);
69
70 // Names of functions (within modules requiring permissions) that can be used
71 // without asking for the module permission. In other words, functions you can
72 // use with no permissions specified.
73 const char* kNonPermissionFunctionNames[] = {
74 "tabs.create",
75 "tabs.onRemoved",
76 "tabs.remove",
77 "tabs.update",
78 };
79 const size_t kNumNonPermissionFunctionNames =
80 arraysize(kNonPermissionFunctionNames);
81
82 const char kOldUnlimitedStoragePermission[] = "unlimited_storage";
83 const char kWindowsPermission[] = "windows";
84
85 } // namespace
86
87 //
88 // PermissionMessage
89 //
90
91 // static
92 ExtensionPermissionMessage ExtensionPermissionMessage::CreateFromHostList(
93 std::vector<std::string> hosts) {
94 CHECK(hosts.size() > 0);
95 Id message_id;
96 string16 message;
97 switch (hosts.size()) {
98 case 1:
99 message_id = kHosts1;
100 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
101 UTF8ToUTF16(hosts[0]));
102 break;
103 case 2:
104 message_id = kHosts2;
105 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
106 UTF8ToUTF16(hosts[0]),
107 UTF8ToUTF16(hosts[1]));
108 break;
109 case 3:
110 message_id = kHosts3;
111 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
112 UTF8ToUTF16(hosts[0]),
113 UTF8ToUTF16(hosts[1]),
114 UTF8ToUTF16(hosts[2]));
115 break;
116 default:
117 message_id = kHosts4OrMore;
118 message = l10n_util::GetStringFUTF16(
119 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
120 UTF8ToUTF16(hosts[0]),
121 UTF8ToUTF16(hosts[1]),
122 base::IntToString16(hosts.size() - 2));
123 break;
124 }
125
126 return ExtensionPermissionMessage(message_id, message);
127 }
128
129 ExtensionPermissionMessage::ExtensionPermissionMessage(
130 ExtensionPermissionMessage::Id id, string16 message) : id_(id),
Matt Perry 2011/06/21 00:43:10 Format like: cons( foo) : a_(a), b_(b) { }
jstritar 2011/06/21 23:12:16 Thanks... Done.
131 message_(message) {
132 }
133
134 //
135 // ExtensionPermission
136 //
137
138 ExtensionPermissionMessage ExtensionAPIPermission::GetMessage() const {
139 return ExtensionPermissionMessage(
140 message_id_, l10n_util::GetStringUTF16(l10n_message_id_));
141 }
142
143 ExtensionAPIPermission::ExtensionAPIPermission(
144 Id id,
145 const char* name,
146 bool is_hosted_app,
147 bool is_component_only,
148 int l10n_message_id,
149 ExtensionPermissionMessage::Id message_id,
150 bool implies_full_access,
151 bool implies_full_url_access)
152 : id_(id),
153 name_(name),
154 implies_full_access_(implies_full_access),
155 implies_full_url_access_(implies_full_url_access),
156 is_hosted_app_(is_hosted_app),
157 is_component_only_(is_component_only),
158 l10n_message_id_(l10n_message_id),
159 message_id_(message_id) {
160 }
161
162 ExtensionAPIPermission::~ExtensionAPIPermission() {
163 }
164
165 //
166 // ExtensionPermissionsInfo
167 //
168
169 // static
170 ExtensionPermissionsInfo* ExtensionPermissionsInfo::GetInstance() {
171 return Singleton<ExtensionPermissionsInfo>::get();
172 }
173
174 // static
175 ExtensionAPIPermission* ExtensionPermissionsInfo::GetById(
176 ExtensionAPIPermission::Id id) {
177 IdMap ids = GetInstance()->id_map_;
Matt Perry 2011/06/21 00:43:10 use a ref here to avoid making a copy. though if
jstritar 2011/06/21 23:12:16 This is now a member function. Done.
178 IdMap::iterator i = ids.find(id);
179 return (i == ids.end()) ? NULL : i->second;
180 }
181
182 // static
183 ExtensionAPIPermission* ExtensionPermissionsInfo::GetByName(std::string name) {
184 NameMap names = GetInstance()->name_map_;
Matt Perry 2011/06/21 00:43:10 ditto
jstritar 2011/06/21 23:12:16 same here... Done.
185 NameMap::iterator i = names.find(name);
186 return (i == names.end()) ? NULL : i->second;
187 }
188
189 // static
190 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAll() {
191 ExtensionAPIPermissionSet permissions;
192 IdMap ids = GetInstance()->id_map_;
193 for (IdMap::const_iterator i = ids.begin(); i != ids.end(); ++i)
194 permissions.insert(i->second->id());
195 return permissions;
196 }
197
198 // static
199 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAllByName(
200 const std::set<std::string>& permission_names) {
201 ExtensionAPIPermissionSet permissions;
202 for (std::set<std::string>::iterator i = permission_names.begin();
203 i != permission_names.end(); ++i) {
204 ExtensionAPIPermission* permission = GetByName(*i);
205 if (permission)
206 permissions.insert(permission->id());
207 }
208 return permissions;
209 }
210
211 // static
212 size_t ExtensionPermissionsInfo::GetHostedAppPermissionCount() {
213 return GetInstance()->hosted_app_permission_count_;
214 }
215
216 // static
217 size_t ExtensionPermissionsInfo::GetPermissionCount() {
218 return GetInstance()->permission_count_;
219 }
220
221 ExtensionPermissionsInfo::~ExtensionPermissionsInfo() {
222 for (IdMap::iterator i = id_map_.begin(); i != id_map_.end(); ++i)
223 delete i->second;
224
225 id_map_.clear();
Matt Perry 2011/06/21 00:43:10 this will happen in the map's destructor automatic
jstritar 2011/06/21 23:12:16 Done.
226 name_map_.clear();
227 }
228
229 ExtensionPermissionsInfo::ExtensionPermissionsInfo()
230 : hosted_app_permission_count_(0),
231 permission_count_(0) {
232 // Hosted app permissions
233 RegisterHostedAppPermission(
234 ExtensionAPIPermission::kBackground, "background", 0,
235 ExtensionPermissionMessage::kNone);
236 RegisterHostedAppPermission(
237 ExtensionAPIPermission::kClipboardRead, "clipboardRead",
238 IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD,
239 ExtensionPermissionMessage::kClipboard);
240 RegisterHostedAppPermission(
241 ExtensionAPIPermission::kClipboardWrite, "clipboardWrite", 0,
242 ExtensionPermissionMessage::kNone);
243 RegisterHostedAppPermission(
244 ExtensionAPIPermission::kChromePrivate, "chromePrivate", 0,
245 ExtensionPermissionMessage::kNone);
246 RegisterHostedAppPermission(
247 ExtensionAPIPermission::kExperimental, "experimental", 0,
248 ExtensionPermissionMessage::kNone);
249 RegisterHostedAppPermission(
250 ExtensionAPIPermission::kGeolocation, "geolocation",
251 IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
252 ExtensionPermissionMessage::kGeolocation);
253 RegisterHostedAppPermission(
254 ExtensionAPIPermission::kNotification, "notifications", 0,
255 ExtensionPermissionMessage::kNone);
256 RegisterHostedAppPermission(
257 ExtensionAPIPermission::kUnlimitedStorage, "unlimitedStorage", 0,
258 ExtensionPermissionMessage::kNone);
259
260 // Hosted app and private permissions.
261 RegisterPermission(
262 ExtensionAPIPermission::kWebstorePrivate, "webstorePrivate", 0,
263 ExtensionPermissionMessage::kNone,
264 true, true, false, false);
265
266 // Extension permissions.
267 RegisterExtensionPermission(
268 ExtensionAPIPermission::kBookmark, "bookmarks",
269 IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
270 ExtensionPermissionMessage::kBookmarks);
271 RegisterExtensionPermission(
272 ExtensionAPIPermission::kContentSettings, "contentSettings", 0,
273 ExtensionPermissionMessage::kNone);
274 RegisterExtensionPermission(
275 ExtensionAPIPermission::kContextMenus, "contextMenus", 0,
276 ExtensionPermissionMessage::kNone);
277 RegisterExtensionPermission(
278 ExtensionAPIPermission::kCookie, "cookies", 0,
279 ExtensionPermissionMessage::kNone);
280 RegisterExtensionPermission(
281 ExtensionAPIPermission::kDebugger, "debugger",
282 IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
283 ExtensionPermissionMessage::kDebugger);
284 RegisterExtensionPermission(
285 ExtensionAPIPermission::kFileBrowserHandler, "fileBrowserHandler", 0,
286 ExtensionPermissionMessage::kNone);
287 RegisterExtensionPermission(
288 ExtensionAPIPermission::kHistory, "history",
289 IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
290 ExtensionPermissionMessage::kBrowsingHistory);
291 RegisterExtensionPermission(
292 ExtensionAPIPermission::kIdle, "idle", 0,
293 ExtensionPermissionMessage::kNone);
294 RegisterExtensionPermission(
295 ExtensionAPIPermission::kManagement, "management",
296 IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
297 ExtensionPermissionMessage::kManagement);
298 RegisterExtensionPermission(
299 ExtensionAPIPermission::kTab, "tabs",
300 IDS_EXTENSION_PROMPT_WARNING_TABS,
301 ExtensionPermissionMessage::kTabs);
302 RegisterExtensionPermission(
303 ExtensionAPIPermission::kWebSocketProxyPrivate,
304 "webSocketProxyPrivate", 0,
305 ExtensionPermissionMessage::kNone);
306
307 // Private permissions
308 RegisterPrivatePermission(
309 ExtensionAPIPermission::kChromeosInfoPrivate, "chromeosInfoPrivate");
310 RegisterPrivatePermission(
311 ExtensionAPIPermission::kFileBrowserPrivate, "fileBrowserPrivate");
312 RegisterPrivatePermission(
313 ExtensionAPIPermission::kMediaPlayerPrivate, "mediaPlayerPrivate");
314
315 // Full url access permissions.
316
317 RegisterPermission(
318 ExtensionAPIPermission::kProxy, "proxy", 0,
319 ExtensionPermissionMessage::kNone, false, false, false, true);
320
321 RegisterPermission(
322 ExtensionAPIPermission::kDevtools, "devtools", 0,
323 ExtensionPermissionMessage::kNone, false, false, false, true);
324
325 RegisterPermission(
326 ExtensionAPIPermission::kPlugin, "plugin",
327 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS,
328 ExtensionPermissionMessage::kFullAccess, false, false, true, true);
329
330 RegisterPermission(
331 ExtensionAPIPermission::kDefault, "default", 0,
332 ExtensionPermissionMessage::kNone, false, false, false, false);
333
334 // Register Aliases
335 RegisterAlias("unlimitedStorage", kOldUnlimitedStoragePermission);
336 RegisterAlias("tabs", kWindowsPermission);
337 }
338
339 void ExtensionPermissionsInfo::RegisterAlias(
340 const char* name, const char* alias) {
341 CHECK(name_map_.find(name) != name_map_.end());
342 CHECK(name_map_.find(alias) == name_map_.end());
343 name_map_[alias] = name_map_[name];
344 }
345
346 void ExtensionPermissionsInfo::RegisterExtensionPermission(
347 ExtensionAPIPermission::Id id,
348 const char* name,
349 int l10n_message_id,
350 ExtensionPermissionMessage::Id message_id) {
351 RegisterPermission(id, name, l10n_message_id, message_id,
352 false, false, false, false);
353 }
354
355 void ExtensionPermissionsInfo::RegisterHostedAppPermission(
356 ExtensionAPIPermission::Id id,
357 const char* name,
358 int l10n_message_id,
359 ExtensionPermissionMessage::Id message_id) {
360 RegisterPermission(id, name, l10n_message_id, message_id,
361 true, false, false, false);
362 }
363
364 void ExtensionPermissionsInfo::RegisterPrivatePermission(
365 ExtensionAPIPermission::Id id, const char* name) {
366 RegisterPermission(id, name, 0, ExtensionPermissionMessage::kNone,
367 false, true, false, false);
368 }
369
370 void ExtensionPermissionsInfo::RegisterPermission(
371 ExtensionAPIPermission::Id id,
372 const char* name,
373 int l10n_message_id,
374 ExtensionPermissionMessage::Id message_id,
375 bool is_hosted_app,
376 bool is_component_only,
377 bool implies_full_access,
378 bool implies_full_url_access) {
379 CHECK(id_map_.find(id) == id_map_.end());
380 CHECK(name_map_.find(name) == name_map_.end());
381
382 ExtensionAPIPermission* permission =
383 new ExtensionAPIPermission(id,
384 name,
385 is_hosted_app,
386 is_component_only,
387 l10n_message_id,
388 message_id,
389 implies_full_access,
390 implies_full_url_access);
391 id_map_[id] = permission;
392 name_map_[name] = permission;
393
394 permission_count_++;
395 if (permission->is_hosted_app())
396 hosted_app_permission_count_++;
397 }
398
399 //
400 // ExtensionPermissionSet
401 //
402
403 ExtensionPermissionSet::ExtensionPermissionSet() {
404 }
405
406 ExtensionPermissionSet::ExtensionPermissionSet(
407 const Extension* extension,
408 ExtensionAPIPermissionSet apis,
409 URLPatternSet explicit_hosts) : apis_(apis),
Matt Perry 2011/06/21 00:43:10 formatting
jstritar 2011/06/21 23:12:16 Done.
410 explicit_hosts_(explicit_hosts) {
411 CHECK(extension);
412 InitFromExtension(extension);
413 InitEffectiveHosts();
414 }
415
416 ExtensionPermissionSet::ExtensionPermissionSet(
417 ExtensionAPIPermissionSet apis,
418 URLPatternSet explicit_hosts,
419 URLPatternSet scriptable_hosts) : apis_(apis),
Matt Perry 2011/06/21 00:43:10 ditto
jstritar 2011/06/21 23:12:16 Done.
420 explicit_hosts_(explicit_hosts),
421 scriptable_hosts_(scriptable_hosts) {
422 InitEffectiveHosts();
423 }
424
425 ExtensionPermissionSet::~ExtensionPermissionSet() {
426 }
427
428 // static
429 ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
430 const ExtensionPermissionSet* set1,
431 const ExtensionPermissionSet* set2) {
432 ExtensionPermissionSet empty;
433 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? &empty : set1;
434 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? &empty : set2;
435
436 ExtensionAPIPermissionSet apis;
437 std::set_union(set1_safe->apis().begin(), set1_safe->apis().end(),
438 set2_safe->apis().begin(), set2_safe->apis().end(),
439 std::insert_iterator<ExtensionAPIPermissionSet>(
440 apis, apis.begin()));
441
Matt Perry 2011/06/21 00:43:10 nit: kill extra newline
jstritar 2011/06/21 23:12:16 Done.
442
443 URLPatternSet explicit_hosts;
444 URLPatternSet scriptable_hosts;
445 URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
446 set2_safe->explicit_hosts(),
447 &explicit_hosts);
448 URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
449 set2_safe->scriptable_hosts(),
450 &scriptable_hosts);
451
452 return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts);
453 }
454
455 std::set<std::string> ExtensionPermissionSet::GetAPIsAsStrings() const {
456 std::set<std::string> apis_str;
457 for (ExtensionAPIPermissionSet::iterator i = apis_.begin();
458 i != apis_.end(); ++i) {
459 ExtensionAPIPermission* permission = GetAPIPermissionById(*i);
460 if (permission)
461 apis_str.insert(permission->name());
462 }
463 return apis_str;
464 }
465
466 std::vector<std::string>
467 ExtensionPermissionSet::GetDistinctHostsForDisplay() const {
468 return GetDistinctHosts(effective_hosts_.patterns(), true);
469 }
470
471 ExtensionPermissionMessages
472 ExtensionPermissionSet::GetPermissionMessages() const {
473 ExtensionPermissionMessages messages;
474
475 if (HasEffectiveFullAccess()) {
476 messages.push_back(ExtensionPermissionMessage(
477 ExtensionPermissionMessage::kFullAccess,
478 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
479 return messages;
480 }
481
482 if (HasEffectiveAccessToAllHosts()) {
483 messages.push_back(ExtensionPermissionMessage(
484 ExtensionPermissionMessage::kHostsAll,
485 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
486 } else {
487 std::vector<std::string> hosts = GetDistinctHostsForDisplay();
488 if (!hosts.empty())
489 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts));
490 }
491
492 std::set<ExtensionPermissionMessage> simple_msgs =
493 GetSimplePermissionMessages();
494 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
495
496 return messages;
497 }
498
499 std::vector<string16> ExtensionPermissionSet::GetWarningMessages() const {
500 std::vector<string16> messages;
501 ExtensionPermissionMessages permissions = GetPermissionMessages();
502 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
503 i != permissions.end(); ++i)
504 messages.push_back(i->message());
505 return messages;
506 }
507
508 bool ExtensionPermissionSet::IsDefault() const {
509 // Not default if any host permissions are present.
510 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
511 return false;
512
513 // The set is default if it has the default permission.
514 if (apis().size() == 1 && apis().count(ExtensionAPIPermission::kDefault))
Matt Perry 2011/06/21 00:43:10 What's the purpose of the Default permission? How
jstritar 2011/06/21 23:12:16 I'm planning adding a method, GrantsAccessToFuncti
515 return true;
516
517 // Or if it has no api permissions.
518 return apis().empty();
519 }
520
521 bool ExtensionPermissionSet::HasAPIPermission(
522 ExtensionAPIPermission::Id permission) const {
523 return apis().find(permission) != apis().end();
524 }
525
526 bool ExtensionPermissionSet::HasAccessToFunction(
527 const std::string& function_name) const {
528 // TODO(jstritar): Embed this information in each permission and add a method
529 // like GrantsAccess(function_name) to ExtensionAPIPermission. A "default"
530 // permission can then handle the modules and functions that everyone can
531 // access.
532 std::string permission_name = function_name;
533
534 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
535 if (permission_name == kNonPermissionFunctionNames[i])
536 return true;
537 }
538
539 // See if this is a function or event name first and strip out the package.
540 // Functions will be of the form package.function
541 // Events will be of the form package/id or package.optional.stuff
542 size_t separator = function_name.find_first_of("./");
543 if (separator != std::string::npos)
544 permission_name = function_name.substr(0, separator);
545
546 ExtensionAPIPermission* permission =
547 ExtensionPermissionsInfo::GetByName(permission_name);
548 if (permission && apis_.count(permission->id()))
549 return true;
550
551 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
552 if (permission_name == kNonPermissionModuleNames[i]) {
553 return true;
554 }
555 }
556
557 return false;
558 }
559
560 bool ExtensionPermissionSet::HasExplicitAccessToOrigin(
561 const GURL& origin) const {
562 return explicit_hosts().MatchesURL(origin);
563 }
564
565 bool ExtensionPermissionSet::HasScriptableAccessToURL(
566 const GURL& origin) const {
567 // We only need to check our host list to verify access. The host list should
568 // already reflect any special rules (such as chrome://favicon, component
569 // all hosts access, etc.).
570 return scriptable_hosts().MatchesURL(origin);
571 }
572
573 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const {
574 // There are two ways this set can have effective access to all hosts:
575 // 1) it has an <all_urls> URL pattern.
576 // 2) it has a named permission with implied full URL access.
577 const URLPatternList patterns = effective_hosts().patterns();
578 for (URLPatternList::const_iterator host = patterns.begin();
579 host != patterns.end(); ++host) {
580 if (host->match_all_urls() ||
581 (host->match_subdomains() && host->host().empty()))
582 return true;
583 }
584
585 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
586 i != apis().end(); ++i) {
587 ExtensionAPIPermission* permission = GetAPIPermissionById(*i);
588 if (permission->implies_full_url_access())
589 return true;
590 }
591 return false;
592 }
593
594 bool ExtensionPermissionSet::HasEffectiveAccessToHost(
595 const GURL& origin) const {
596 return effective_hosts().MatchesURL(origin);
597 }
598
599 bool ExtensionPermissionSet::HasEffectiveFullAccess() const {
600 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
601 i != apis().end(); ++i) {
602 ExtensionAPIPermission* permission = GetAPIPermissionById(*i);
603 if (permission->implies_full_access())
604 return true;
605 }
606 return false;
607 }
608
609 bool ExtensionPermissionSet::HasPrivatePermissions() const {
610 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
611 i != apis_.end(); ++i) {
612 ExtensionAPIPermission* permission = GetAPIPermissionById(*i);
613 if (permission && permission->is_component_only())
614 return true;
615 }
616 return false;
617 }
618
619 bool ExtensionPermissionSet::HasLessPrivilegesThan(
620 const ExtensionPermissionSet* permissions) const {
621 // Things can't get worse native code access.
Matt Perry 2011/06/21 00:43:10 worse than
jstritar 2011/06/21 23:12:16 Done.
622 if (HasEffectiveFullAccess())
623 return false;
624
625 // Otherwise, it's a privilege increase if the new one has full access.
626 if (permissions->HasEffectiveFullAccess())
627 return true;
628
629 if (HasLessHostPrivilegesThan(permissions))
630 return true;
631
632 if (HasLessAPIPrivilegesThan(permissions))
633 return true;
634
635 return false;
636 }
637
638 // static
639 std::vector<std::string> ExtensionPermissionSet::GetDistinctHosts(
640 const URLPatternList& host_patterns, bool include_rcd) {
641 // Use a vector to preserve order (also faster than a map on small sets).
642 // Each item is a host split into two parts: host without RCDs and
643 // current best RCD.
644 typedef std::vector<std::pair<std::string, std::string> > HostVector;
645 HostVector hosts_best_rcd;
646 for (size_t i = 0; i < host_patterns.size(); ++i) {
647 std::string host = host_patterns[i].host();
648
649 // Add the subdomain wildcard back to the host, if necessary.
650 if (host_patterns[i].match_subdomains())
651 host = "*." + host;
652
653 // If the host has an RCD, split it off so we can detect duplicates.
654 std::string rcd;
655 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
656 host, false);
657 if (reg_len && reg_len != std::string::npos) {
658 if (include_rcd) // else leave rcd empty
659 rcd = host.substr(host.size() - reg_len);
660 host = host.substr(0, host.size() - reg_len);
661 }
662
663 // Check if we've already seen this host.
664 HostVector::iterator it = hosts_best_rcd.begin();
665 for (; it != hosts_best_rcd.end(); ++it) {
666 if (it->first == host)
667 break;
668 }
669 // If this host was found, replace the RCD if this one is better.
670 if (it != hosts_best_rcd.end()) {
671 if (include_rcd && RcdBetterThan(rcd, it->second))
672 it->second = rcd;
673 } else { // Previously unseen host, append it.
674 hosts_best_rcd.push_back(std::make_pair(host, rcd));
675 }
676 }
677
678 // Build up the final vector by concatenating hosts and RCDs.
679 std::vector<std::string> distinct_hosts;
680 for (HostVector::iterator it = hosts_best_rcd.begin();
681 it != hosts_best_rcd.end(); ++it)
682 distinct_hosts.push_back(it->first + it->second);
683 return distinct_hosts;
684 }
685
686 void ExtensionPermissionSet::InitEffectiveHosts() {
687 effective_hosts_.ClearPatterns();
688
689 if (HasEffectiveAccessToAllHosts()) {
690 URLPattern all_urls(URLPattern::SCHEME_ALL);
691 all_urls.set_match_all_urls(true);
692 effective_hosts_.AddPattern(all_urls);
693 return;
694 }
695
696 URLPatternSet::CreateUnion(
697 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
698 }
699
700 void ExtensionPermissionSet::InitFromExtension(const Extension* extension) {
Matt Perry 2011/06/21 00:43:10 I'm confused. This only initializes some permissio
jstritar 2011/06/21 23:12:16 Yes, this initializes implicit permissions and ext
701 // Add the implied permissions.
702 if (!extension->plugins().empty())
703 apis_.insert(ExtensionAPIPermission::kPlugin);
704
705 if (!extension->devtools_url().is_empty())
706 apis_.insert(ExtensionAPIPermission::kDevtools);
707
708 // Add the scriptable hosts.
709 for (UserScriptList::const_iterator content_script =
710 extension->content_scripts().begin();
711 content_script != extension->content_scripts().end(); ++content_script) {
712 URLPatternList::const_iterator pattern =
713 content_script->url_patterns().begin();
714 for (; pattern != content_script->url_patterns().end(); ++pattern)
715 scriptable_hosts_.AddPattern(*pattern);
716 }
717 }
718
719 std::set<ExtensionPermissionMessage>
720 ExtensionPermissionSet::GetSimplePermissionMessages() const {
721 std::set<ExtensionPermissionMessage> messages;
722 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
723 i != apis_.end(); ++i) {
724 DCHECK_GT(ExtensionPermissionMessage::kNone,
725 ExtensionPermissionMessage::kUnknown);
726 ExtensionAPIPermission* perm = GetAPIPermissionById(*i);
727 if (perm && perm->message_id() > ExtensionPermissionMessage::kNone)
728 messages.insert(perm->GetMessage());
729 }
730 return messages;
731 }
732
733 bool ExtensionPermissionSet::HasLessAPIPrivilegesThan(
734 const ExtensionPermissionSet* permissions) const {
735 if (permissions == NULL)
736 return false;
737
738 ExtensionAPIPermissionSet new_apis = permissions->apis_;
739 ExtensionAPIPermissionSet new_apis_only;
740 std::set_difference(new_apis.begin(), new_apis.end(),
741 apis_.begin(), apis_.end(),
742 std::inserter(new_apis_only, new_apis_only.begin()));
743
744 // Ignore API permissions that don't require user approval when deciding if
745 // an extension has increased its privileges.
746 size_t new_api_count = 0;
747 for (ExtensionAPIPermissionSet::iterator i = new_apis_only.begin();
748 i != new_apis_only.end(); ++i) {
749 ExtensionAPIPermission* perm = GetAPIPermissionById(*i);
750 if (perm && perm->message_id() > ExtensionPermissionMessage::kNone)
751 new_api_count++;
Matt Perry 2011/06/21 00:43:10 could just return true from here rather than count
jstritar 2011/06/21 23:12:16 Oh, good point. Done.
752 }
753 return new_api_count > 0;
754 }
755
756 bool ExtensionPermissionSet::HasLessHostPrivilegesThan(
757 const ExtensionPermissionSet* permissions) const {
758 // If this permission set can access any host, then it can't be elevated.
759 if (HasEffectiveAccessToAllHosts())
760 return false;
761
762 // Likewise, if the other permission set has full host access, then it must be
763 // a privilege increase.
764 if (permissions->HasEffectiveAccessToAllHosts())
765 return true;
766
767 const URLPatternList old_list = effective_hosts().patterns();
768 const URLPatternList new_list = permissions->effective_hosts().patterns();
769
770 // TODO(jstritar): This is overly conservative with respect to subdomains.
771 // For example, going from *.google.com to www.google.com will be
772 // considered an elevation, even though it is not (http://crbug.com/65337).
773 std::vector<std::string> new_hosts = GetDistinctHosts(new_list, false);
774 std::vector<std::string> old_hosts = GetDistinctHosts(old_list, false);
775
776 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end());
777 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end());
778 std::set<std::string> new_hosts_only;
779
780 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
781 old_hosts_set.begin(), old_hosts_set.end(),
782 std::inserter(new_hosts_only, new_hosts_only.begin()));
783
784 return !new_hosts_only.empty();
785 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698