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

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

Powered by Google App Engine
This is Rietveld 408576698