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

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

Powered by Google App Engine
This is Rietveld 408576698