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

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

Issue 10649003: Move each permission classes to its own files in extensions/permissions (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase on HEAD Created 8 years, 5 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/basictypes.h"
11 #include "base/command_line.h"
12 #include "base/memory/singleton.h"
13 #include "base/values.h"
14 #include "base/string_number_conversions.h"
15 #include "base/utf_string_conversions.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/common/extensions/extension_constants.h"
19 #include "chrome/common/extensions/extension_l10n_util.h"
20 #include "chrome/common/extensions/url_pattern.h"
21 #include "chrome/common/extensions/url_pattern_set.h"
22 #include "content/public/common/url_constants.h"
23 #include "grit/generated_resources.h"
24 #include "net/base/registry_controlled_domain.h"
25 #include "ui/base/l10n/l10n_util.h"
26
27 namespace ids = extension_misc;
28 namespace {
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 can be used without listing it in the
44 // permissions section of the manifest.
45 const char* kNonPermissionModuleNames[] = {
46 "app",
47 "appWindow",
48 "browserAction",
49 "devtools",
50 "events",
51 "extension",
52 "i18n",
53 "omnibox",
54 "pageAction",
55 "pageActions",
56 "permissions",
57 "runtime",
58 "test",
59 "types"
60 };
61 const size_t kNumNonPermissionModuleNames =
62 arraysize(kNonPermissionModuleNames);
63
64 // Names of functions (within modules requiring permissions) that can be used
65 // without asking for the module permission. In other words, functions you can
66 // use with no permissions specified.
67 const char* kNonPermissionFunctionNames[] = {
68 "management.getPermissionWarningsByManifest",
69 "tabs.create",
70 "tabs.onRemoved",
71 "tabs.remove",
72 "tabs.update",
73 };
74 const size_t kNumNonPermissionFunctionNames =
75 arraysize(kNonPermissionFunctionNames);
76
77 const char kOldUnlimitedStoragePermission[] = "unlimited_storage";
78 const char kWindowsPermission[] = "windows";
79 const char kTemporaryBackgroundAlias[] = "background_alias_do_not_use";
80
81 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) {
82 DCHECK(out);
83 for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) {
84 URLPattern p = *i;
85 p.SetPath("/*");
86 out->AddPattern(p);
87 }
88 }
89
90 // Strips out the API name from a function or event name.
91 // Functions will be of the form api_name.function
92 // Events will be of the form api_name/id or api_name.optional.stuff
93 std::string GetPermissionName(const std::string& function_name) {
94 size_t separator = function_name.find_first_of("./");
95 if (separator != std::string::npos)
96 return function_name.substr(0, separator);
97 else
98 return function_name;
99 }
100
101 } // namespace
102
103 //
104 // PermissionMessage
105 //
106
107 // static
108 ExtensionPermissionMessage ExtensionPermissionMessage::CreateFromHostList(
109 const std::set<std::string>& hosts) {
110 std::vector<std::string> host_list(hosts.begin(), hosts.end());
111 DCHECK_GT(host_list.size(), 0UL);
112 ID message_id;
113 string16 message;
114
115 switch (host_list.size()) {
116 case 1:
117 message_id = kHosts1;
118 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
119 UTF8ToUTF16(host_list[0]));
120 break;
121 case 2:
122 message_id = kHosts2;
123 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
124 UTF8ToUTF16(host_list[0]),
125 UTF8ToUTF16(host_list[1]));
126 break;
127 case 3:
128 message_id = kHosts3;
129 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
130 UTF8ToUTF16(host_list[0]),
131 UTF8ToUTF16(host_list[1]),
132 UTF8ToUTF16(host_list[2]));
133 break;
134 default:
135 message_id = kHosts4OrMore;
136 message = l10n_util::GetStringFUTF16(
137 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
138 UTF8ToUTF16(host_list[0]),
139 UTF8ToUTF16(host_list[1]),
140 base::IntToString16(hosts.size() - 2));
141 break;
142 }
143
144 return ExtensionPermissionMessage(message_id, message);
145 }
146
147 ExtensionPermissionMessage::ExtensionPermissionMessage(
148 ExtensionPermissionMessage::ID id, const string16& message)
149 : id_(id), message_(message) {
150 }
151
152 ExtensionPermissionMessage::~ExtensionPermissionMessage() {}
153
154 //
155 // ExtensionPermission
156 //
157
158 ExtensionAPIPermission::~ExtensionAPIPermission() {}
159
160 ExtensionPermissionMessage ExtensionAPIPermission::GetMessage() const {
161 return ExtensionPermissionMessage(
162 message_id_, l10n_util::GetStringUTF16(l10n_message_id_));
163 }
164
165 ExtensionAPIPermission::ExtensionAPIPermission(
166 ID id,
167 const char* name,
168 int l10n_message_id,
169 ExtensionPermissionMessage::ID message_id,
170 int flags)
171 : id_(id),
172 name_(name),
173 flags_(flags),
174 l10n_message_id_(l10n_message_id),
175 message_id_(message_id) {}
176
177 // static
178 void ExtensionAPIPermission::RegisterAllPermissions(
179 ExtensionPermissionsInfo* info) {
180
181 struct PermissionRegistration {
182 ExtensionAPIPermission::ID id;
183 const char* name;
184 int flags;
185 int l10n_message_id;
186 ExtensionPermissionMessage::ID message_id;
187 } PermissionsToRegister[] = {
188 // Register permissions for all extension types.
189 { kBackground, "background" },
190 { kClipboardRead, "clipboardRead", kFlagNone,
191 IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD,
192 ExtensionPermissionMessage::kClipboard },
193 { kClipboardWrite, "clipboardWrite" },
194 { kDeclarative, "declarative" },
195 { kDeclarativeWebRequest, "declarativeWebRequest" },
196 { kDownloads, "downloads", kFlagNone,
197 IDS_EXTENSION_PROMPT_WARNING_DOWNLOADS,
198 ExtensionPermissionMessage::kDownloads },
199 { kExperimental, "experimental", kFlagCannotBeOptional },
200 { kGeolocation, "geolocation", kFlagCannotBeOptional,
201 IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
202 ExtensionPermissionMessage::kGeolocation },
203 { kNotification, "notifications" },
204 { kUnlimitedStorage, "unlimitedStorage", kFlagCannotBeOptional },
205
206 // Register hosted and packaged app permissions.
207 { kAppNotifications, "appNotifications" },
208
209 // Register extension permissions.
210 { kActiveTab, "activeTab" },
211 { kAlarms, "alarms" },
212 { kBookmark, "bookmarks", kFlagNone,
213 IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
214 ExtensionPermissionMessage::kBookmarks },
215 { kBrowsingData, "browsingData" },
216 { kContentSettings, "contentSettings", kFlagNone,
217 IDS_EXTENSION_PROMPT_WARNING_CONTENT_SETTINGS,
218 ExtensionPermissionMessage::kContentSettings },
219 { kContextMenus, "contextMenus" },
220 { kCookie, "cookies" },
221 { kFileBrowserHandler, "fileBrowserHandler", kFlagCannotBeOptional },
222 { kFileSystem, "fileSystem" },
223 { kHistory, "history", kFlagNone,
224 IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
225 ExtensionPermissionMessage::kBrowsingHistory },
226 { kKeybinding, "keybinding" },
227 { kIdle, "idle" },
228 { kInput, "input", kFlagNone,
229 IDS_EXTENSION_PROMPT_WARNING_INPUT,
230 ExtensionPermissionMessage::kInput },
231 { kManagement, "management", kFlagNone,
232 IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
233 ExtensionPermissionMessage::kManagement },
234 { kPageCapture, "pageCapture", kFlagNone,
235 IDS_EXTENSION_PROMPT_WARNING_ALL_PAGES_CONTENT,
236 ExtensionPermissionMessage::kAllPageContent },
237 { kPrivacy, "privacy", kFlagNone,
238 IDS_EXTENSION_PROMPT_WARNING_PRIVACY,
239 ExtensionPermissionMessage::kPrivacy },
240 { kStorage, "storage" },
241 { kTab, "tabs", kFlagNone,
242 IDS_EXTENSION_PROMPT_WARNING_TABS,
243 ExtensionPermissionMessage::kTabs },
244 { kTopSites, "topSites", kFlagNone,
245 IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
246 ExtensionPermissionMessage::kBrowsingHistory },
247 { kTts, "tts", 0, kFlagCannotBeOptional },
248 { kTtsEngine, "ttsEngine", kFlagCannotBeOptional,
249 IDS_EXTENSION_PROMPT_WARNING_TTS_ENGINE,
250 ExtensionPermissionMessage::kTtsEngine },
251 { kUsb, "usb", kFlagNone,
252 IDS_EXTENSION_PROMPT_WARNING_USB,
253 ExtensionPermissionMessage::kNone },
254 { kWebNavigation, "webNavigation", kFlagNone,
255 IDS_EXTENSION_PROMPT_WARNING_TABS, ExtensionPermissionMessage::kTabs },
256 { kWebRequest, "webRequest" },
257 { kWebRequestBlocking, "webRequestBlocking" },
258
259 // Register private permissions.
260 { kChromeosInfoPrivate, "chromeosInfoPrivate", kFlagCannotBeOptional },
261 { kFileBrowserHandlerInternal, "fileBrowserHandlerInternal",
262 kFlagCannotBeOptional },
263 { kFileBrowserPrivate, "fileBrowserPrivate", kFlagCannotBeOptional },
264 { kManagedModePrivate, "managedModePrivate", kFlagCannotBeOptional },
265 { kMediaPlayerPrivate, "mediaPlayerPrivate", kFlagCannotBeOptional },
266 { kMetricsPrivate, "metricsPrivate", kFlagCannotBeOptional },
267 { kSystemPrivate, "systemPrivate", kFlagCannotBeOptional },
268 { kChromeAuthPrivate, "chromeAuthPrivate", kFlagCannotBeOptional },
269 { kInputMethodPrivate, "inputMethodPrivate", kFlagCannotBeOptional },
270 { kEchoPrivate, "echoPrivate", kFlagCannotBeOptional },
271 { kTerminalPrivate, "terminalPrivate", kFlagCannotBeOptional },
272 { kWebRequestInternal, "webRequestInternal", kFlagCannotBeOptional },
273 { kWebSocketProxyPrivate, "webSocketProxyPrivate", kFlagCannotBeOptional },
274 { kWebstorePrivate, "webstorePrivate", kFlagCannotBeOptional },
275
276 // Full url access permissions.
277 { kProxy, "proxy", kFlagImpliesFullURLAccess | kFlagCannotBeOptional },
278 { kDebugger, "debugger", kFlagImpliesFullURLAccess | kFlagCannotBeOptional,
279 IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
280 ExtensionPermissionMessage::kDebugger },
281 { kDevtools, "devtools",
282 kFlagImpliesFullURLAccess | kFlagCannotBeOptional },
283 { kPlugin, "plugin",
284 kFlagImpliesFullURLAccess | kFlagImpliesFullAccess |
285 kFlagCannotBeOptional,
286 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS,
287 ExtensionPermissionMessage::kFullAccess },
288
289 // Platform-app permissions.
290 { kSocket, "socket", kFlagCannotBeOptional },
291 { kAudioCapture, "audioCapture", kFlagNone,
292 IDS_EXTENSION_PROMPT_WARNING_AUDIO_CAPTURE,
293 ExtensionPermissionMessage::kAudioCapture },
294 { kVideoCapture, "videoCapture", kFlagNone,
295 IDS_EXTENSION_PROMPT_WARNING_VIDEO_CAPTURE,
296 ExtensionPermissionMessage::kVideoCapture },
297 };
298
299 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(PermissionsToRegister); ++i) {
300 const PermissionRegistration& pr = PermissionsToRegister[i];
301 info->RegisterPermission(
302 pr.id, pr.name, pr.l10n_message_id,
303 pr.message_id ? pr.message_id : ExtensionPermissionMessage::kNone,
304 pr.flags);
305 }
306
307 // Register aliases.
308 info->RegisterAlias("unlimitedStorage", kOldUnlimitedStoragePermission);
309 info->RegisterAlias("tabs", kWindowsPermission);
310 // TODO(mihaip): Should be removed for the M20 branch, see
311 // http://crbug.com/120447 for more details.
312 info->RegisterAlias("background", kTemporaryBackgroundAlias);
313 }
314
315 //
316 // ExtensionPermissionsInfo
317 //
318
319 // static
320 ExtensionPermissionsInfo* ExtensionPermissionsInfo::GetInstance() {
321 return Singleton<ExtensionPermissionsInfo>::get();
322 }
323
324 ExtensionAPIPermission* ExtensionPermissionsInfo::GetByID(
325 ExtensionAPIPermission::ID id) {
326 IDMap::iterator i = id_map_.find(id);
327 return (i == id_map_.end()) ? NULL : i->second;
328 }
329
330 ExtensionAPIPermission* ExtensionPermissionsInfo::GetByName(
331 const std::string& name) {
332 NameMap::iterator i = name_map_.find(name);
333 return (i == name_map_.end()) ? NULL : i->second;
334 }
335
336 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAll() {
337 ExtensionAPIPermissionSet permissions;
338 for (IDMap::const_iterator i = id_map_.begin(); i != id_map_.end(); ++i)
339 permissions.insert(i->second->id());
340 return permissions;
341 }
342
343 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAllByName(
344 const std::set<std::string>& permission_names) {
345 ExtensionAPIPermissionSet permissions;
346 for (std::set<std::string>::const_iterator i = permission_names.begin();
347 i != permission_names.end(); ++i) {
348 ExtensionAPIPermission* permission = GetByName(*i);
349 if (permission)
350 permissions.insert(permission->id());
351 }
352 return permissions;
353 }
354
355 ExtensionPermissionsInfo::~ExtensionPermissionsInfo() {
356 for (IDMap::iterator i = id_map_.begin(); i != id_map_.end(); ++i)
357 delete i->second;
358 }
359
360 ExtensionPermissionsInfo::ExtensionPermissionsInfo()
361 : hosted_app_permission_count_(0),
362 permission_count_(0) {
363 ExtensionAPIPermission::RegisterAllPermissions(this);
364 }
365
366 void ExtensionPermissionsInfo::RegisterAlias(
367 const char* name,
368 const char* alias) {
369 DCHECK(name_map_.find(name) != name_map_.end());
370 DCHECK(name_map_.find(alias) == name_map_.end());
371 name_map_[alias] = name_map_[name];
372 }
373
374 ExtensionAPIPermission* ExtensionPermissionsInfo::RegisterPermission(
375 ExtensionAPIPermission::ID id,
376 const char* name,
377 int l10n_message_id,
378 ExtensionPermissionMessage::ID message_id,
379 int flags) {
380 DCHECK(id_map_.find(id) == id_map_.end());
381 DCHECK(name_map_.find(name) == name_map_.end());
382
383 ExtensionAPIPermission* permission = new ExtensionAPIPermission(
384 id, name, l10n_message_id, message_id, flags);
385
386 id_map_[id] = permission;
387 name_map_[name] = permission;
388
389 permission_count_++;
390
391 return permission;
392 }
393
394 //
395 // ExtensionPermissionSet
396 //
397
398 ExtensionPermissionSet::ExtensionPermissionSet() {}
399
400 ExtensionPermissionSet::ExtensionPermissionSet(
401 const extensions::Extension* extension,
402 const ExtensionAPIPermissionSet& apis,
403 const URLPatternSet& explicit_hosts,
404 const ExtensionOAuth2Scopes& scopes)
405 : apis_(apis),
406 scopes_(scopes) {
407 DCHECK(extension);
408 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
409 InitImplicitExtensionPermissions(extension);
410 InitEffectiveHosts();
411 }
412
413 ExtensionPermissionSet::ExtensionPermissionSet(
414 const ExtensionAPIPermissionSet& apis,
415 const URLPatternSet& explicit_hosts,
416 const URLPatternSet& scriptable_hosts)
417 : apis_(apis),
418 scriptable_hosts_(scriptable_hosts) {
419 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
420 InitEffectiveHosts();
421 }
422
423 ExtensionPermissionSet::ExtensionPermissionSet(
424 const ExtensionAPIPermissionSet& apis,
425 const URLPatternSet& explicit_hosts,
426 const URLPatternSet& scriptable_hosts,
427 const ExtensionOAuth2Scopes& scopes)
428 : apis_(apis),
429 scriptable_hosts_(scriptable_hosts),
430 scopes_(scopes) {
431 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
432 InitEffectiveHosts();
433 }
434
435 ExtensionPermissionSet::ExtensionPermissionSet(
436 const ExtensionOAuth2Scopes& scopes)
437 : scopes_(scopes) {
438 InitEffectiveHosts();
439 }
440
441 // static
442 ExtensionPermissionSet* ExtensionPermissionSet::CreateDifference(
443 const ExtensionPermissionSet* set1,
444 const ExtensionPermissionSet* set2) {
445 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
446 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
447 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
448
449 ExtensionAPIPermissionSet apis;
450 std::set_difference(set1_safe->apis().begin(), set1_safe->apis().end(),
451 set2_safe->apis().begin(), set2_safe->apis().end(),
452 std::insert_iterator<ExtensionAPIPermissionSet>(
453 apis, apis.begin()));
454
455 URLPatternSet explicit_hosts;
456 URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
457 set2_safe->explicit_hosts(),
458 &explicit_hosts);
459
460 URLPatternSet scriptable_hosts;
461 URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
462 set2_safe->scriptable_hosts(),
463 &scriptable_hosts);
464
465 ExtensionOAuth2Scopes scopes;
466 std::set_difference(set1_safe->scopes().begin(), set1_safe->scopes().end(),
467 set2_safe->scopes().begin(), set2_safe->scopes().end(),
468 std::insert_iterator<ExtensionOAuth2Scopes>(
469 scopes, scopes.begin()));
470
471 return new ExtensionPermissionSet(
472 apis, explicit_hosts, scriptable_hosts, scopes);
473 }
474
475 // static
476 ExtensionPermissionSet* ExtensionPermissionSet::CreateIntersection(
477 const ExtensionPermissionSet* set1,
478 const ExtensionPermissionSet* set2) {
479 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
480 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
481 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
482
483 ExtensionAPIPermissionSet apis;
484 std::set_intersection(set1_safe->apis().begin(), set1_safe->apis().end(),
485 set2_safe->apis().begin(), set2_safe->apis().end(),
486 std::insert_iterator<ExtensionAPIPermissionSet>(
487 apis, apis.begin()));
488 URLPatternSet explicit_hosts;
489 URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
490 set2_safe->explicit_hosts(),
491 &explicit_hosts);
492
493 URLPatternSet scriptable_hosts;
494 URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
495 set2_safe->scriptable_hosts(),
496 &scriptable_hosts);
497
498 ExtensionOAuth2Scopes scopes;
499 std::set_intersection(set1_safe->scopes().begin(), set1_safe->scopes().end(),
500 set2_safe->scopes().begin(), set2_safe->scopes().end(),
501 std::insert_iterator<ExtensionOAuth2Scopes>(
502 scopes, scopes.begin()));
503
504 return new ExtensionPermissionSet(
505 apis, explicit_hosts, scriptable_hosts, scopes);
506 }
507
508 // static
509 ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
510 const ExtensionPermissionSet* set1,
511 const ExtensionPermissionSet* set2) {
512 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
513 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
514 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
515
516 ExtensionAPIPermissionSet apis;
517 std::set_union(set1_safe->apis().begin(), set1_safe->apis().end(),
518 set2_safe->apis().begin(), set2_safe->apis().end(),
519 std::insert_iterator<ExtensionAPIPermissionSet>(
520 apis, apis.begin()));
521
522 URLPatternSet explicit_hosts;
523 URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
524 set2_safe->explicit_hosts(),
525 &explicit_hosts);
526
527 URLPatternSet scriptable_hosts;
528 URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
529 set2_safe->scriptable_hosts(),
530 &scriptable_hosts);
531
532 ExtensionOAuth2Scopes scopes;
533 std::set_union(set1_safe->scopes().begin(), set1_safe->scopes().end(),
534 set2_safe->scopes().begin(), set2_safe->scopes().end(),
535 std::insert_iterator<ExtensionOAuth2Scopes>(
536 scopes, scopes.begin()));
537
538 return new ExtensionPermissionSet(
539 apis, explicit_hosts, scriptable_hosts, scopes);
540 }
541
542 bool ExtensionPermissionSet::operator==(
543 const ExtensionPermissionSet& rhs) const {
544 return apis_ == rhs.apis_ &&
545 scriptable_hosts_ == rhs.scriptable_hosts_ &&
546 explicit_hosts_ == rhs.explicit_hosts_ &&
547 scopes_ == rhs.scopes_;
548 }
549
550 bool ExtensionPermissionSet::Contains(const ExtensionPermissionSet& set) const {
551 // Every set includes the empty set.
552 if (set.IsEmpty())
553 return true;
554
555 if (!std::includes(apis_.begin(), apis_.end(),
556 set.apis().begin(), set.apis().end()))
557 return false;
558
559 if (!explicit_hosts().Contains(set.explicit_hosts()))
560 return false;
561
562 if (!scriptable_hosts().Contains(set.scriptable_hosts()))
563 return false;
564
565 if (!std::includes(scopes_.begin(), scopes_.end(),
566 set.scopes().begin(), set.scopes().end()))
567 return false;
568
569 return true;
570 }
571
572 std::set<std::string> ExtensionPermissionSet::GetAPIsAsStrings() const {
573 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
574 std::set<std::string> apis_str;
575 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
576 i != apis_.end(); ++i) {
577 ExtensionAPIPermission* permission = info->GetByID(*i);
578 if (permission)
579 apis_str.insert(permission->name());
580 }
581 return apis_str;
582 }
583
584 std::set<std::string> ExtensionPermissionSet::
585 GetAPIsWithAnyAccessAsStrings() const {
586 std::set<std::string> result = GetAPIsAsStrings();
587 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i)
588 result.insert(kNonPermissionModuleNames[i]);
589 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i)
590 result.insert(GetPermissionName(kNonPermissionFunctionNames[i]));
591 return result;
592 }
593
594 bool ExtensionPermissionSet::HasAnyAccessToAPI(
595 const std::string& api_name) const {
596 if (HasAccessToFunction(api_name))
597 return true;
598
599 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
600 if (api_name == GetPermissionName(kNonPermissionFunctionNames[i]))
601 return true;
602 }
603
604 return false;
605 }
606
607 std::set<std::string>
608 ExtensionPermissionSet::GetDistinctHostsForDisplay() const {
609 return GetDistinctHosts(effective_hosts_, true, true);
610 }
611
612 ExtensionPermissionMessages
613 ExtensionPermissionSet::GetPermissionMessages() const {
614 ExtensionPermissionMessages messages;
615
616 if (HasEffectiveFullAccess()) {
617 messages.push_back(ExtensionPermissionMessage(
618 ExtensionPermissionMessage::kFullAccess,
619 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
620 return messages;
621 }
622
623 if (HasEffectiveAccessToAllHosts()) {
624 messages.push_back(ExtensionPermissionMessage(
625 ExtensionPermissionMessage::kHostsAll,
626 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
627 } else {
628 std::set<std::string> hosts = GetDistinctHostsForDisplay();
629 if (!hosts.empty())
630 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts));
631 }
632
633 std::set<ExtensionPermissionMessage> simple_msgs =
634 GetSimplePermissionMessages();
635 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
636
637 return messages;
638 }
639
640 std::vector<string16> ExtensionPermissionSet::GetWarningMessages() const {
641 std::vector<string16> messages;
642 ExtensionPermissionMessages permissions = GetPermissionMessages();
643
644 bool audio_capture = false;
645 bool video_capture = false;
646 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
647 i != permissions.end(); ++i) {
648 if (i->id() == ExtensionPermissionMessage::kAudioCapture)
649 audio_capture = true;
650 if (i->id() == ExtensionPermissionMessage::kVideoCapture)
651 video_capture = true;
652 }
653
654 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
655 i != permissions.end(); ++i) {
656 if (audio_capture && video_capture) {
657 if (i->id() == ExtensionPermissionMessage::kAudioCapture) {
658 messages.push_back(l10n_util::GetStringUTF16(
659 IDS_EXTENSION_PROMPT_WARNING_AUDIO_AND_VIDEO_CAPTURE));
660 continue;
661 } else if (i->id() == ExtensionPermissionMessage::kVideoCapture) {
662 // The combined message will be pushed above.
663 continue;
664 }
665 }
666
667 messages.push_back(i->message());
668 }
669
670 return messages;
671 }
672
673 bool ExtensionPermissionSet::IsEmpty() const {
674 // Not default if any host permissions are present.
675 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
676 return false;
677
678 // Or if it has no api permissions.
679 return apis().empty();
680 }
681
682 bool ExtensionPermissionSet::HasAPIPermission(
683 ExtensionAPIPermission::ID permission) const {
684 return apis().find(permission) != apis().end();
685 }
686
687 bool ExtensionPermissionSet::HasAccessToFunction(
688 const std::string& function_name) const {
689 // TODO(jstritar): Embed this information in each permission and add a method
690 // like GrantsAccess(function_name) to ExtensionAPIPermission. A "default"
691 // permission can then handle the modules and functions that everyone can
692 // access.
693 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
694 if (function_name == kNonPermissionFunctionNames[i])
695 return true;
696 }
697
698 std::string permission_name = GetPermissionName(function_name);
699 ExtensionAPIPermission* permission =
700 ExtensionPermissionsInfo::GetInstance()->GetByName(permission_name);
701 if (permission && apis_.count(permission->id()))
702 return true;
703
704 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
705 if (permission_name == kNonPermissionModuleNames[i]) {
706 return true;
707 }
708 }
709
710 return false;
711 }
712
713 bool ExtensionPermissionSet::HasExplicitAccessToOrigin(
714 const GURL& origin) const {
715 return explicit_hosts().MatchesURL(origin);
716 }
717
718 bool ExtensionPermissionSet::HasScriptableAccessToURL(
719 const GURL& origin) const {
720 // We only need to check our host list to verify access. The host list should
721 // already reflect any special rules (such as chrome://favicon, all hosts
722 // access, etc.).
723 return scriptable_hosts().MatchesURL(origin);
724 }
725
726 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const {
727 // There are two ways this set can have effective access to all hosts:
728 // 1) it has an <all_urls> URL pattern.
729 // 2) it has a named permission with implied full URL access.
730 for (URLPatternSet::const_iterator host = effective_hosts().begin();
731 host != effective_hosts().end(); ++host) {
732 if (host->match_all_urls() ||
733 (host->match_subdomains() && host->host().empty()))
734 return true;
735 }
736
737 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
738 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
739 i != apis().end(); ++i) {
740 ExtensionAPIPermission* permission = info->GetByID(*i);
741 if (permission->implies_full_url_access())
742 return true;
743 }
744 return false;
745 }
746
747 bool ExtensionPermissionSet::HasEffectiveAccessToURL(
748 const GURL& url) const {
749 return effective_hosts().MatchesURL(url);
750 }
751
752 bool ExtensionPermissionSet::HasEffectiveFullAccess() const {
753 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
754 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
755 i != apis().end(); ++i) {
756 ExtensionAPIPermission* permission = info->GetByID(*i);
757 if (permission->implies_full_access())
758 return true;
759 }
760 return false;
761 }
762
763 bool ExtensionPermissionSet::HasLessPrivilegesThan(
764 const ExtensionPermissionSet* permissions) const {
765 // Things can't get worse than native code access.
766 if (HasEffectiveFullAccess())
767 return false;
768
769 // Otherwise, it's a privilege increase if the new one has full access.
770 if (permissions->HasEffectiveFullAccess())
771 return true;
772
773 if (HasLessHostPrivilegesThan(permissions))
774 return true;
775
776 if (HasLessAPIPrivilegesThan(permissions))
777 return true;
778
779 if (HasLessScopesThan(permissions))
780 return true;
781
782 return false;
783 }
784
785 ExtensionPermissionSet::~ExtensionPermissionSet() {}
786
787 // static
788 std::set<std::string> ExtensionPermissionSet::GetDistinctHosts(
789 const URLPatternSet& host_patterns,
790 bool include_rcd,
791 bool exclude_file_scheme) {
792 // Use a vector to preserve order (also faster than a map on small sets).
793 // Each item is a host split into two parts: host without RCDs and
794 // current best RCD.
795 typedef std::vector<std::pair<std::string, std::string> > HostVector;
796 HostVector hosts_best_rcd;
797 for (URLPatternSet::const_iterator i = host_patterns.begin();
798 i != host_patterns.end(); ++i) {
799 if (exclude_file_scheme && i->scheme() == chrome::kFileScheme)
800 continue;
801
802 std::string host = i->host();
803
804 // Add the subdomain wildcard back to the host, if necessary.
805 if (i->match_subdomains())
806 host = "*." + host;
807
808 // If the host has an RCD, split it off so we can detect duplicates.
809 std::string rcd;
810 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
811 host, false);
812 if (reg_len && reg_len != std::string::npos) {
813 if (include_rcd) // else leave rcd empty
814 rcd = host.substr(host.size() - reg_len);
815 host = host.substr(0, host.size() - reg_len);
816 }
817
818 // Check if we've already seen this host.
819 HostVector::iterator it = hosts_best_rcd.begin();
820 for (; it != hosts_best_rcd.end(); ++it) {
821 if (it->first == host)
822 break;
823 }
824 // If this host was found, replace the RCD if this one is better.
825 if (it != hosts_best_rcd.end()) {
826 if (include_rcd && RcdBetterThan(rcd, it->second))
827 it->second = rcd;
828 } else { // Previously unseen host, append it.
829 hosts_best_rcd.push_back(std::make_pair(host, rcd));
830 }
831 }
832
833 // Build up the final vector by concatenating hosts and RCDs.
834 std::set<std::string> distinct_hosts;
835 for (HostVector::iterator it = hosts_best_rcd.begin();
836 it != hosts_best_rcd.end(); ++it)
837 distinct_hosts.insert(it->first + it->second);
838 return distinct_hosts;
839 }
840
841 void ExtensionPermissionSet::InitImplicitExtensionPermissions(
842 const extensions::Extension* extension) {
843 // Add the implied permissions.
844 if (!extension->plugins().empty())
845 apis_.insert(ExtensionAPIPermission::kPlugin);
846
847 if (!extension->devtools_url().is_empty())
848 apis_.insert(ExtensionAPIPermission::kDevtools);
849
850 // The webRequest permission implies the internal version as well.
851 if (apis_.find(ExtensionAPIPermission::kWebRequest) != apis_.end())
852 apis_.insert(ExtensionAPIPermission::kWebRequestInternal);
853
854 // The fileBrowserHandler permission implies the internal version as well.
855 if (apis_.find(ExtensionAPIPermission::kFileBrowserHandler) != apis_.end())
856 apis_.insert(ExtensionAPIPermission::kFileBrowserHandlerInternal);
857
858 // Add the scriptable hosts.
859 for (UserScriptList::const_iterator content_script =
860 extension->content_scripts().begin();
861 content_script != extension->content_scripts().end(); ++content_script) {
862 URLPatternSet::const_iterator pattern =
863 content_script->url_patterns().begin();
864 for (; pattern != content_script->url_patterns().end(); ++pattern)
865 scriptable_hosts_.AddPattern(*pattern);
866 }
867 }
868
869 void ExtensionPermissionSet::InitEffectiveHosts() {
870 effective_hosts_.ClearPatterns();
871
872 URLPatternSet::CreateUnion(
873 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
874 }
875
876 std::set<ExtensionPermissionMessage>
877 ExtensionPermissionSet::GetSimplePermissionMessages() const {
878 std::set<ExtensionPermissionMessage> messages;
879 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
880 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
881 i != apis_.end(); ++i) {
882 DCHECK_GT(ExtensionPermissionMessage::kNone,
883 ExtensionPermissionMessage::kUnknown);
884 ExtensionAPIPermission* perm = info->GetByID(*i);
885 if (perm && perm->message_id() > ExtensionPermissionMessage::kNone)
886 messages.insert(perm->GetMessage());
887 }
888 return messages;
889 }
890
891 bool ExtensionPermissionSet::HasLessAPIPrivilegesThan(
892 const ExtensionPermissionSet* permissions) const {
893 if (permissions == NULL)
894 return false;
895
896 std::set<ExtensionPermissionMessage> current_warnings =
897 GetSimplePermissionMessages();
898 std::set<ExtensionPermissionMessage> new_warnings =
899 permissions->GetSimplePermissionMessages();
900 std::set<ExtensionPermissionMessage> delta_warnings;
901 std::set_difference(new_warnings.begin(), new_warnings.end(),
902 current_warnings.begin(), current_warnings.end(),
903 std::inserter(delta_warnings, delta_warnings.begin()));
904
905 // We have less privileges if there are additional warnings present.
906 return !delta_warnings.empty();
907 }
908
909 bool ExtensionPermissionSet::HasLessHostPrivilegesThan(
910 const ExtensionPermissionSet* permissions) const {
911 // If this permission set can access any host, then it can't be elevated.
912 if (HasEffectiveAccessToAllHosts())
913 return false;
914
915 // Likewise, if the other permission set has full host access, then it must be
916 // a privilege increase.
917 if (permissions->HasEffectiveAccessToAllHosts())
918 return true;
919
920 const URLPatternSet& old_list = effective_hosts();
921 const URLPatternSet& new_list = permissions->effective_hosts();
922
923 // TODO(jstritar): This is overly conservative with respect to subdomains.
924 // For example, going from *.google.com to www.google.com will be
925 // considered an elevation, even though it is not (http://crbug.com/65337).
926 std::set<std::string> new_hosts_set(GetDistinctHosts(new_list, false, false));
927 std::set<std::string> old_hosts_set(GetDistinctHosts(old_list, false, false));
928 std::set<std::string> new_hosts_only;
929
930 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
931 old_hosts_set.begin(), old_hosts_set.end(),
932 std::inserter(new_hosts_only, new_hosts_only.begin()));
933
934 return !new_hosts_only.empty();
935 }
936
937 bool ExtensionPermissionSet::HasLessScopesThan(
938 const ExtensionPermissionSet* permissions) const {
939 if (permissions == NULL)
940 return false;
941
942 ExtensionOAuth2Scopes current_scopes = scopes();
943 ExtensionOAuth2Scopes new_scopes = permissions->scopes();
944 ExtensionOAuth2Scopes delta_scopes;
945 std::set_difference(new_scopes.begin(), new_scopes.end(),
946 current_scopes.begin(), current_scopes.end(),
947 std::inserter(delta_scopes, delta_scopes.begin()));
948
949 // We have less privileges if there are additional scopes present.
950 return !delta_scopes.empty();
951 }
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