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

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: fix a bad merge 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 // 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
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 };
62 const size_t kNumNonPermissionModuleNames =
63 arraysize(kNonPermissionModuleNames);
64
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 // Aliased to kTabPermission for purposes of API checks, but not allowed
79 // in the permissions field of the manifest.
80 static const char kWindowPermission[] = "windows";
81
82 const char kOldUnlimitedStoragePermission[] = "unlimited_storage";
83 const char kWindowsPermission[] = "windows";
84
85 } // namespace
86
87 //
88 // PermissionMessage
89 //
90
91 ExtensionPermissionMessage::ExtensionPermissionMessage(
92 ExtensionPermissionMessage::MessageId message_id, string16 message)
93 : message_id_(message_id),
94 message_(message) {
95 }
96
97 // static
98 ExtensionPermissionMessage ExtensionPermissionMessage::CreateFromHostList(
99 std::vector<std::string> hosts) {
100 CHECK(hosts.size() > 0);
101 MessageId message_id;
102 string16 message;
103 switch (hosts.size()) {
104 case 1:
105 message_id = ID_HOSTS_1;
106 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
107 UTF8ToUTF16(hosts[0]));
108 break;
109 case 2:
110 message_id = ID_HOSTS_2;
111 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
112 UTF8ToUTF16(hosts[0]),
113 UTF8ToUTF16(hosts[1]));
114 break;
115 case 3:
116 message_id = ID_HOSTS_3;
117 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
118 UTF8ToUTF16(hosts[0]),
119 UTF8ToUTF16(hosts[1]),
120 UTF8ToUTF16(hosts[2]));
121 break;
122 default:
123 message_id = ID_HOSTS_4_OR_MORE;
124 message = l10n_util::GetStringFUTF16(
125 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
126 UTF8ToUTF16(hosts[0]),
127 UTF8ToUTF16(hosts[1]),
128 base::IntToString16(hosts.size() - 2));
129 break;
130 }
131
132 return ExtensionPermissionMessage(message_id, message);
133 }
134
135 //
136 // ExtensionPermissionsInfo
137 //
138
139 // static
140 ExtensionPermissionsInfo* ExtensionPermissionsInfo::GetInstance() {
141 return Singleton<ExtensionPermissionsInfo>::get();
142 }
143
144 // TODO(jstritar): Figure out how to clean up this initialization. We may want
145 // initialize these dynamically based on data in extension_api.json.
146 ExtensionPermissionsInfo::ExtensionPermissionsInfo()
jstritar 2011/06/09 21:12:57 Any advice on how to make these initializations cl
147 : background_(this, "background", true, false, 0,
Matt Perry 2011/06/09 22:28:42 If you take my suggestion and switch to using an e
148 ExtensionPermissionMessage::ID_NONE),
149 bookmark_(this, "bookmarks", false, false,
150 IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
151 ExtensionPermissionMessage::ID_BOOKMARKS),
152 clipboard_read_(this, "clipboardRead", true, false,
153 IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD,
154 ExtensionPermissionMessage::ID_CLIPBOARD),
155 clipboard_write_(this, "clipboardWrite", true, false, 0,
156 ExtensionPermissionMessage::ID_NONE),
157 content_settings_(this, "contentSettings", false, false, 0,
158 ExtensionPermissionMessage::ID_NONE),
159 context_menus_(this, "contentSettings", false, false, 0,
160 ExtensionPermissionMessage::ID_NONE),
161 cookie_(this, "cookies", false, false, 0,
162 ExtensionPermissionMessage::ID_NONE),
163 chrome_private_(this, "chromePrivate", true, false, 0,
164 ExtensionPermissionMessage::ID_NONE),
165 chromeos_info_private_(this, "chromeosInfoPrivate", false, true, 0,
166 ExtensionPermissionMessage::ID_NONE),
167 debugger_(this, "debugger", false, false,
168 IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
169 ExtensionPermissionMessage::ID_DEBUGGER),
170 experimental_(this, "experimental", true, false, 0,
171 ExtensionPermissionMessage::ID_NONE),
172 file_browser_handler_(this, "fileBrowserHandler", false, false, 0,
173 ExtensionPermissionMessage::ID_NONE),
174 file_browser_private_(this, "fileBrowserPrivate", false, true, 0,
175 ExtensionPermissionMessage::ID_NONE),
176 geolocation_(this, "geolocation", true, false,
177 IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
178 ExtensionPermissionMessage::ID_GEOLOCATION),
179 history_(this, "history", false, false,
180 IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
181 ExtensionPermissionMessage::ID_BROWSING_HISTORY),
182 idle_(this, "idle", false, false, 0, ExtensionPermissionMessage::ID_NONE),
183 management_(this, "management", false, false,
184 IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
185 ExtensionPermissionMessage::ID_MANAGEMENT),
186 media_player_private_(this, "mediaPlayerPrivate", false, true, 0,
187 ExtensionPermissionMessage::ID_NONE),
188 notification_(this, "notifications", true, false, 0,
189 ExtensionPermissionMessage::ID_NONE),
190 proxy_(this, "proxy", false, false, 0,
191 ExtensionPermissionMessage::ID_NONE),
192 tab_(this, "tabs", false, false, IDS_EXTENSION_PROMPT_WARNING_TABS,
193 ExtensionPermissionMessage::ID_TABS),
194 unlimited_storage_(this, "unlimitedStorage", true, false, 0,
195 ExtensionPermissionMessage::ID_NONE),
196 web_socket_proxy_private_(this, "webSocketProxyPrivate", false, false, 0,
197 ExtensionPermissionMessage::ID_NONE),
198 webstore_private_(this, "webstorePrivate", true, true, 0,
199 ExtensionPermissionMessage::ID_NONE) {
200
201 // Map aliases for old permissions.
202 permissions_[kOldUnlimitedStoragePermission] = &unlimited_storage_;
203 permissions_[kWindowsPermission] = &tab_;
204 }
205
206 ExtensionPermissionsInfo::~ExtensionPermissionsInfo() {
207 }
208
209 //
210 // ExtensionPermission
211 //
212
213
214 // static
215 const ExtensionAPIPermission& ExtensionAPIPermission::Background() {
216 return ExtensionPermissionsInfo::GetInstance()->background_;
217 }
218
219 // static
220 const ExtensionAPIPermission& ExtensionAPIPermission::Bookmark() {
221 return ExtensionPermissionsInfo::GetInstance()->bookmark_;
222 }
223
224 // static
225 const ExtensionAPIPermission& ExtensionAPIPermission::ClipboardRead() {
226 return ExtensionPermissionsInfo::GetInstance()->clipboard_read_;
227 }
228
229 // static
230 const ExtensionAPIPermission& ExtensionAPIPermission::ClipboardWrite() {
231 return ExtensionPermissionsInfo::GetInstance()->clipboard_write_;
232 }
233
234 // static
235 const ExtensionAPIPermission& ExtensionAPIPermission::ContentSettings() {
236 return ExtensionPermissionsInfo::GetInstance()->content_settings_;
237 }
238
239 // static
240 const ExtensionAPIPermission& ExtensionAPIPermission::ContextMenus() {
241 return ExtensionPermissionsInfo::GetInstance()->context_menus_;
242 }
243
244 // static
245 const ExtensionAPIPermission& ExtensionAPIPermission::Cookie() {
246 return ExtensionPermissionsInfo::GetInstance()->cookie_;
247 }
248
249 // static
250 const ExtensionAPIPermission& ExtensionAPIPermission::ChromePrivate() {
251 return ExtensionPermissionsInfo::GetInstance()->chrome_private_;
252 }
253
254 // static
255 const ExtensionAPIPermission& ExtensionAPIPermission::ChromeosInfoPrivate() {
256 return ExtensionPermissionsInfo::GetInstance()->chromeos_info_private_;
257 }
258
259 // static
260 const ExtensionAPIPermission& ExtensionAPIPermission::Debugger() {
261 return ExtensionPermissionsInfo::GetInstance()->debugger_;
262 }
263
264 // static
265 const ExtensionAPIPermission& ExtensionAPIPermission::Experimental() {
266 return ExtensionPermissionsInfo::GetInstance()->experimental_;
267 }
268
269 // static
270 const ExtensionAPIPermission& ExtensionAPIPermission::FileBrowserHandler() {
271 return ExtensionPermissionsInfo::GetInstance()->file_browser_handler_;
272 }
273
274 // static
275 const ExtensionAPIPermission& ExtensionAPIPermission::FileBrowserPrivate() {
276 return ExtensionPermissionsInfo::GetInstance()->file_browser_private_;
277 }
278
279 // static
280 const ExtensionAPIPermission& ExtensionAPIPermission::Geolocation() {
281 return ExtensionPermissionsInfo::GetInstance()->geolocation_;
282 }
283
284 // static
285 const ExtensionAPIPermission& ExtensionAPIPermission::History() {
286 return ExtensionPermissionsInfo::GetInstance()->history_;
287 }
288
289 // static
290 const ExtensionAPIPermission& ExtensionAPIPermission::Idle() {
291 return ExtensionPermissionsInfo::GetInstance()->idle_;
292 }
293
294 // static
295 const ExtensionAPIPermission& ExtensionAPIPermission::Management() {
296 return ExtensionPermissionsInfo::GetInstance()->management_;
297 }
298
299 // static
300 const ExtensionAPIPermission& ExtensionAPIPermission::MediaPlayerPrivate() {
301 return ExtensionPermissionsInfo::GetInstance()->media_player_private_;
302 }
303
304 // static
305 const ExtensionAPIPermission& ExtensionAPIPermission::Notification() {
306 return ExtensionPermissionsInfo::GetInstance()->notification_;
307 }
308
309 // static
310 const ExtensionAPIPermission& ExtensionAPIPermission::Proxy() {
311 return ExtensionPermissionsInfo::GetInstance()->proxy_;
312 }
313
314 // static
315 const ExtensionAPIPermission& ExtensionAPIPermission::Tab() {
316 return ExtensionPermissionsInfo::GetInstance()->tab_;
317 }
318
319 // static
320 const ExtensionAPIPermission& ExtensionAPIPermission::UnlimitedStorage() {
321 return ExtensionPermissionsInfo::GetInstance()->unlimited_storage_;
322 }
323
324 // static
325 const ExtensionAPIPermission& ExtensionAPIPermission::WebstorePrivate() {
326 return ExtensionPermissionsInfo::GetInstance()->webstore_private_;
327 }
328
329 // static
330 const ExtensionAPIPermission& ExtensionAPIPermission::WebSocketProxyPrivate() {
331 return ExtensionPermissionsInfo::GetInstance()->web_socket_proxy_private_;
332 }
333
334 // static
335 std::set<ExtensionAPIPermission> ExtensionAPIPermission::GetAll() {
336 std::set<ExtensionAPIPermission> permissions;
337 ExtensionPermissionsInfo::PermissionMap permission_map =
338 ExtensionPermissionsInfo::GetInstance()->permissions_;
339 ExtensionPermissionsInfo::PermissionMap::const_iterator i =
340 permission_map.begin();
341 for (; i != permission_map.end(); ++i) {
342 permissions.insert(*(i->second));
343 }
344 return permissions;
345 }
346
347 // static
348 ExtensionAPIPermission* ExtensionAPIPermission::GetByName(std::string name) {
349 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
350 if (info->permissions_.count(name))
351 return info->permissions_.find(name)->second;
352 return NULL;
353 }
354
355 // static
356 std::set<ExtensionAPIPermission> ExtensionAPIPermission::GetAllByName(
357 const std::set<std::string>& permissions_str) {
358 std::set<ExtensionAPIPermission> permissions;
359 for (std::set<std::string>::iterator i = permissions_str.begin();
360 i != permissions_str.end(); ++i) {
361 ExtensionAPIPermission* permission =
362 ExtensionAPIPermission::GetByName(*i);
363 if (permission)
364 permissions.insert(*permission);
365 }
366 return permissions;
367 }
368
369 // static
370 size_t ExtensionAPIPermission::permission_count_ = 0;
371
372 // static
373 size_t ExtensionAPIPermission::hosted_app_permission_count_ = 0;
374
375 ExtensionPermissionMessage ExtensionAPIPermission::GetMessage() const {
376 return ExtensionPermissionMessage(
377 message_id_, l10n_util::GetStringUTF16(l10n_message_id_));
378 }
379
380 ExtensionAPIPermission::ExtensionAPIPermission(
381 ExtensionPermissionsInfo* info,
382 const char* name,
383 bool is_hosted_app,
384 bool is_component_only,
385 int l10n_message_id,
386 ExtensionPermissionMessage::MessageId message_id)
387 : name_(name),
388 is_hosted_app_(is_hosted_app),
389 is_component_only_(is_component_only),
390 l10n_message_id_(l10n_message_id),
391 message_id_(message_id) {
392 // Update the permission counts when we create a new one.
393 permission_count_++;
394
395 if (is_hosted_app)
396 hosted_app_permission_count_++;
397
398 info->permissions_[name] = this;
399 }
400
401 ExtensionAPIPermission::~ExtensionAPIPermission() {
402 }
403
404 bool ExtensionAPIPermission::operator==(
405 const ExtensionAPIPermission& permission) const {
406 return name_ == permission.name_;
407 }
408
409 bool ExtensionAPIPermission::operator<(
410 const ExtensionAPIPermission& permission) const {
411 return name_ < permission.name_;
412 }
413
414 //
415 // ExtensionPermissionSet
416 //
417
418
419 ExtensionPermissionSet::ExtensionPermissionSet()
420 : native_code_(false) {
421 }
422
423 ExtensionPermissionSet::ExtensionPermissionSet(
424 Extension* extension,
425 std::set<ExtensionAPIPermission> apis,
426 URLPatternList hosts) : apis_(apis),
427 native_code_(false) {
428 InitFromExtension(extension, hosts);
429 }
430
431 ExtensionPermissionSet::ExtensionPermissionSet(
432 bool native_code,
433 std::set<ExtensionAPIPermission> apis,
434 URLPatternSet effective_hosts) : apis_(apis),
435 effective_hosts_(effective_hosts),
436 native_code_(native_code) {
437 }
438
439 ExtensionPermissionSet::~ExtensionPermissionSet() {
440 }
441
442 // static
443 ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
444 const ExtensionPermissionSet& set1,
445 const ExtensionPermissionSet& set2) {
446 bool full_access = set1.native_code() || set2.native_code();
447
448 std::set<ExtensionAPIPermission> apis;
449 std::set_union(set1.apis_.begin(), set1.apis_.end(),
450 set2.apis_.begin(), set2.apis_.end(),
451 std::insert_iterator<std::set<ExtensionAPIPermission> >(
452 apis, apis.begin()));
453
454 URLPatternSet new_hosts = set1.effective_hosts_;
455 URLPatternList hosts2 = set2.effective_hosts_.patterns();
456 URLPatternList new_host_list = new_hosts.patterns();
457
458 for (URLPatternList::const_iterator i = hosts2.begin();
459 i != hosts2.end(); ++i) {
460 bool duplicate = false;
461 for (URLPatternList::const_iterator j = new_host_list.begin();
462 j != new_host_list.end(); ++j) {
463 if (j->GetAsString() == i->GetAsString()) {
464 duplicate = true;
465 break;
466 }
467 }
468 if (!duplicate)
469 new_hosts.AddPattern(*i);
470 }
471
472 return new ExtensionPermissionSet(full_access, apis, new_hosts);
473 }
474
475 // static
476 ExtensionPermissionSet* ExtensionPermissionSet::CreateDifference(
477 const ExtensionPermissionSet& set1,
478 const ExtensionPermissionSet& set2) {
479 NOTREACHED();
480 return NULL;
481 }
482
483 // static
484 ExtensionPermissionSet* ExtensionPermissionSet::CreateIntersection(
485 const ExtensionPermissionSet& set1,
486 const ExtensionPermissionSet& set2) {
487 NOTREACHED();
488 return NULL;
489 }
490
491 bool ExtensionPermissionSet::Contains(
492 const ExtensionPermissionSet& set) const {
493 NOTREACHED();
494 return false;
495 }
496
497 ExtensionPermissionMessages
498 ExtensionPermissionSet::GetPermissionMessages() const {
499 ExtensionPermissionMessages messages;
500
501 if (native_code_) {
502 messages.push_back(ExtensionPermissionMessage(
503 ExtensionPermissionMessage::ID_FULL_ACCESS,
504 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
505 return messages;
506 }
507
508 if (HasEffectiveAccessToAllHosts()) {
509 messages.push_back(ExtensionPermissionMessage(
510 ExtensionPermissionMessage::ID_HOSTS_ALL,
511 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
512 } else {
513 std::vector<std::string> hosts = GetDistinctHostsForDisplay();
514 if (!hosts.empty())
515 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts));
516 }
517
518 std::set<ExtensionPermissionMessage> simple_msgs =
519 GetSimplePermissionMessages();
520 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
521
522 return messages;
523 }
524
525 std::vector<string16> ExtensionPermissionSet::GetWarningMessages() const {
526 std::vector<string16> messages;
527 ExtensionPermissionMessages permissions = GetPermissionMessages();
528 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
529 i != permissions.end(); ++i)
530 messages.push_back(i->message());
531 return messages;
532 }
533
534 bool ExtensionPermissionSet::IsEmpty() const {
535 return !native_code_ && apis_.empty() && effective_hosts_.is_empty();
536 }
537
538 bool ExtensionPermissionSet::HasAPIPermission(
539 const ExtensionAPIPermission& permission) const {
540 return apis_.count(permission) > 0;
541 }
542
543 bool ExtensionPermissionSet::HasAccessToFunction(
544 const std::string& function_name) const {
545 // TODO(jstritar): Embed this information in each permission and add a method
546 // like GrantsAccess(function_name) to ExtensionAPIPermission. A "default"
547 // permission can then handle the modules and functions that everyone can
548 // access.
549
550 std::string permission_name = function_name;
551
552 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
553 if (permission_name == kNonPermissionFunctionNames[i])
554 return true;
555 }
556
557 // See if this is a function or event name first and strip out the package.
558 // Functions will be of the form package.function
559 // Events will be of the form package/id or package.optional.stuff
560 size_t separator = function_name.find_first_of("./");
561 if (separator != std::string::npos)
562 permission_name = function_name.substr(0, separator);
563
564 ExtensionAPIPermission* permission =
565 ExtensionAPIPermission::GetByName(permission_name);
566 if (permission && apis_.count(*permission))
567 return true;
568
569 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
570 if (permission_name == kNonPermissionModuleNames[i]) {
571 return true;
572 }
573 }
574
575 return false;
576 }
577
578 bool ExtensionPermissionSet::HasAccessToHost(const GURL& origin) const {
579 const URLPatternList patterns = effective_hosts_.patterns();
580 for (URLPatternList::const_iterator host = patterns.begin();
581 host != patterns.end(); ++host) {
582 if (host->MatchesURL(origin))
583 return true;
584 }
585
586 return false;
587 }
588
589 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const {
590 const URLPatternList patterns = effective_hosts_.patterns();
591 for (URLPatternList::const_iterator host = patterns.begin();
592 host != patterns.end(); ++host) {
593 if (host->match_all_urls() ||
594 (host->match_subdomains() && host->host().empty()))
595 return true;
596 }
597
598 return false;
599 }
600
601
602 bool ExtensionPermissionSet::HasPrivatePermissions() const {
603 for (std::set<ExtensionAPIPermission>::const_iterator i = apis_.begin();
604 i != apis_.end(); ++i) {
605 if (i->is_component_only())
606 return true;
607 }
608 return false;
609 }
610
611 // static
612 std::vector<std::string> ExtensionPermissionSet::GetDistinctHosts(
613 const URLPatternList& host_patterns, bool include_rcd) {
614 // Use a vector to preserve order (also faster than a map on small sets).
615 // Each item is a host split into two parts: host without RCDs and
616 // current best RCD.
617 typedef std::vector<std::pair<std::string, std::string> > HostVector;
618 HostVector hosts_best_rcd;
619 for (size_t i = 0; i < host_patterns.size(); ++i) {
620 std::string host = host_patterns[i].host();
621
622 // Add the subdomain wildcard back to the host, if necessary.
623 if (host_patterns[i].match_subdomains())
624 host = "*." + host;
625
626 // If the host has an RCD, split it off so we can detect duplicates.
627 std::string rcd;
628 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
629 host, false);
630 if (reg_len && reg_len != std::string::npos) {
631 if (include_rcd) // else leave rcd empty
632 rcd = host.substr(host.size() - reg_len);
633 host = host.substr(0, host.size() - reg_len);
634 }
635
636 // Check if we've already seen this host.
637 HostVector::iterator it = hosts_best_rcd.begin();
638 for (; it != hosts_best_rcd.end(); ++it) {
639 if (it->first == host)
640 break;
641 }
642 // If this host was found, replace the RCD if this one is better.
643 if (it != hosts_best_rcd.end()) {
644 if (include_rcd && RcdBetterThan(rcd, it->second))
645 it->second = rcd;
646 } else { // Previously unseen host, append it.
647 hosts_best_rcd.push_back(std::make_pair(host, rcd));
648 }
649 }
650
651 // Build up the final vector by concatenating hosts and RCDs.
652 std::vector<std::string> distinct_hosts;
653 for (HostVector::iterator it = hosts_best_rcd.begin();
654 it != hosts_best_rcd.end(); ++it)
655 distinct_hosts.push_back(it->first + it->second);
656 return distinct_hosts;
657 }
658
659 void ExtensionPermissionSet::InitFromExtension(
660 Extension* extension,
661 const URLPatternList& hosts_) {
662 native_code_ = !extension->plugins().empty();
663
664 // Initialize the effective host permissions.
665 for (URLPatternList::const_iterator host = hosts_.begin();
666 host != hosts_.end(); ++host)
667 effective_hosts_.AddPattern(*host);
668
669 for (UserScriptList::const_iterator content_script =
670 extension->content_scripts().begin();
671 content_script != extension->content_scripts().end(); ++content_script) {
672 URLPatternList::const_iterator pattern =
673 content_script->url_patterns().begin();
674 for (; pattern != content_script->url_patterns().end(); ++pattern)
675 effective_hosts_.AddPattern(*pattern);
676 }
677
678 if (HasAPIPermission(ExtensionAPIPermission::Proxy()) ||
679 !extension->devtools_url().is_empty()) {
680 URLPattern all_urls(URLPattern::SCHEME_ALL);
681 all_urls.set_match_all_urls(true);
682 effective_hosts_.AddPattern(all_urls);
683 }
684
685 }
686
687 std::set<std::string> ExtensionPermissionSet::GetAPIsAsStrings() const {
688 std::set<std::string> apis_str;
689 for (std::set<ExtensionAPIPermission>::iterator i = apis_.begin();
690 i != apis_.end(); ++i)
691 apis_str.insert(i->name());
692 return apis_str;
693 }
694
695 std::vector<std::string>
696 ExtensionPermissionSet::GetDistinctHostsForDisplay() const {
697 return GetDistinctHosts(effective_hosts_.patterns(), true);
698 }
699
700 string16 ExtensionPermissionSet::GetHostPermissionMessage() const {
701 if (HasEffectiveAccessToAllHosts())
702 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS);
703
704 std::vector<std::string> hosts = GetDistinctHostsForDisplay();
705
706 if (hosts.size() == 1) {
707 return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
708 UTF8ToUTF16(hosts[0]));
709 } else if (hosts.size() == 2) {
710 return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
711 UTF8ToUTF16(hosts[0]),
712 UTF8ToUTF16(hosts[1]));
713 } else if (hosts.size() == 3) {
714 return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
715 UTF8ToUTF16(hosts[0]),
716 UTF8ToUTF16(hosts[1]),
717 UTF8ToUTF16(hosts[2]));
718 } else if (hosts.size() >= 4) {
719 return l10n_util::GetStringFUTF16(
720 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
721 UTF8ToUTF16(hosts[0]),
722 UTF8ToUTF16(hosts[1]),
723 base::IntToString16(hosts.size() - 2));
724 }
725
726 return string16();
727 }
728
729 std::set<ExtensionPermissionMessage>
730 ExtensionPermissionSet::GetSimplePermissionMessages() const {
731 std::set<ExtensionPermissionMessage> messages;
732 std::set<ExtensionAPIPermission>::const_iterator i;
733 for (i = apis_.begin(); i != apis_.end(); ++i) {
734 DCHECK_GT(ExtensionPermissionMessage::ID_NONE,
735 ExtensionPermissionMessage::ID_UNKNOWN);
736 if (i->message_id() > ExtensionPermissionMessage::ID_NONE)
737 messages.insert(i->GetMessage());
738 }
739 return messages;
740 }
741
742 bool ExtensionPermissionSet::HasLessAPIPrivilegesThan(
743 const ExtensionPermissionSet& permissions) {
744 std::set<ExtensionAPIPermission> new_apis = permissions.apis_;
745 std::set<ExtensionAPIPermission> new_apis_only;
746 std::set_difference(new_apis.begin(), new_apis.end(),
747 apis_.begin(), apis_.end(),
748 std::inserter(new_apis_only, new_apis_only.begin()));
749
750 // Ignore API permissions that don't require user approval when deciding if
751 // an extension has increased its privileges.
752 size_t new_api_count = 0;
753 for (std::set<ExtensionAPIPermission>::iterator i = new_apis_only.begin();
754 i != new_apis_only.end(); ++i) {
755 if (i->message_id() > ExtensionPermissionMessage::ID_NONE)
756 new_api_count++;
757 }
758
759 return new_api_count > 0;
760 }
761
762 bool ExtensionPermissionSet::HasLessHostPrivilegesThan(
763 const ExtensionPermissionSet& permissions) {
764 // If this permission set can access any host, then it can't be elevated.
765 if (HasEffectiveAccessToAllHosts())
766 return false;
767
768 // Likewise, if the other permission set has full host access, then it must be
769 // a privilege increase.
770 if (permissions.HasEffectiveAccessToAllHosts())
771 return true;
772
773 const URLPatternList old_list = effective_hosts_.patterns();
774 const URLPatternList new_list =
775 permissions.effective_hosts_.patterns();
776
777 // TODO(jstritar): This is overly conservative with respect to subdomains.
778 // For example, going from *.google.com to www.google.com will be
779 // considered an elevation, even though it is not (http://crbug.com/65337).
780 std::vector<std::string> new_hosts = GetDistinctHosts(new_list, false);
781 std::vector<std::string> old_hosts = GetDistinctHosts(old_list, false);
782
783 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end());
784 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end());
785 std::set<std::string> new_hosts_only;
786
787 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
788 old_hosts_set.begin(), old_hosts_set.end(),
789 std::inserter(new_hosts_only, new_hosts_only.begin()));
790
791 return !new_hosts_only.empty();
792 }
793
794 bool ExtensionPermissionSet::HasLessPrivilegesThan(
795 const ExtensionPermissionSet& permissions) {
796 // Things can't get worse native code access.
797 if (native_code_)
798 return false;
799
800 // Otherwise, it's a privilege increase if the new one has full access.
801 if (permissions.native_code_)
802 return true;
803
804 if (HasLessHostPrivilegesThan(permissions))
805 return true;
806
807 if (HasLessAPIPrivilegesThan(permissions))
808 return true;
809
810 return false;
811
812 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698