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

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

Issue 10675007: 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 again 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 "browserAction",
48 "devtools",
49 "events",
50 "extension",
51 "i18n",
52 "omnibox",
53 "pageAction",
54 "pageActions",
55 "permissions",
56 "runtime",
57 "scriptBadge",
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 { kAppWindow, "appWindow" },
292 { kAudioCapture, "audioCapture", kFlagNone,
293 IDS_EXTENSION_PROMPT_WARNING_AUDIO_CAPTURE,
294 ExtensionPermissionMessage::kAudioCapture },
295 { kVideoCapture, "videoCapture", kFlagNone,
296 IDS_EXTENSION_PROMPT_WARNING_VIDEO_CAPTURE,
297 ExtensionPermissionMessage::kVideoCapture },
298 };
299
300 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(PermissionsToRegister); ++i) {
301 const PermissionRegistration& pr = PermissionsToRegister[i];
302 info->RegisterPermission(
303 pr.id, pr.name, pr.l10n_message_id,
304 pr.message_id ? pr.message_id : ExtensionPermissionMessage::kNone,
305 pr.flags);
306 }
307
308 // Register aliases.
309 info->RegisterAlias("unlimitedStorage", kOldUnlimitedStoragePermission);
310 info->RegisterAlias("tabs", kWindowsPermission);
311 // TODO(mihaip): Should be removed for the M20 branch, see
312 // http://crbug.com/120447 for more details.
313 info->RegisterAlias("background", kTemporaryBackgroundAlias);
314 }
315
316 //
317 // ExtensionPermissionsInfo
318 //
319
320 // static
321 ExtensionPermissionsInfo* ExtensionPermissionsInfo::GetInstance() {
322 return Singleton<ExtensionPermissionsInfo>::get();
323 }
324
325 ExtensionAPIPermission* ExtensionPermissionsInfo::GetByID(
326 ExtensionAPIPermission::ID id) {
327 IDMap::iterator i = id_map_.find(id);
328 return (i == id_map_.end()) ? NULL : i->second;
329 }
330
331 ExtensionAPIPermission* ExtensionPermissionsInfo::GetByName(
332 const std::string& name) {
333 NameMap::iterator i = name_map_.find(name);
334 return (i == name_map_.end()) ? NULL : i->second;
335 }
336
337 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAll() {
338 ExtensionAPIPermissionSet permissions;
339 for (IDMap::const_iterator i = id_map_.begin(); i != id_map_.end(); ++i)
340 permissions.insert(i->second->id());
341 return permissions;
342 }
343
344 ExtensionAPIPermissionSet ExtensionPermissionsInfo::GetAllByName(
345 const std::set<std::string>& permission_names) {
346 ExtensionAPIPermissionSet permissions;
347 for (std::set<std::string>::const_iterator i = permission_names.begin();
348 i != permission_names.end(); ++i) {
349 ExtensionAPIPermission* permission = GetByName(*i);
350 if (permission)
351 permissions.insert(permission->id());
352 }
353 return permissions;
354 }
355
356 ExtensionPermissionsInfo::~ExtensionPermissionsInfo() {
357 for (IDMap::iterator i = id_map_.begin(); i != id_map_.end(); ++i)
358 delete i->second;
359 }
360
361 ExtensionPermissionsInfo::ExtensionPermissionsInfo()
362 : hosted_app_permission_count_(0),
363 permission_count_(0) {
364 ExtensionAPIPermission::RegisterAllPermissions(this);
365 }
366
367 void ExtensionPermissionsInfo::RegisterAlias(
368 const char* name,
369 const char* alias) {
370 DCHECK(name_map_.find(name) != name_map_.end());
371 DCHECK(name_map_.find(alias) == name_map_.end());
372 name_map_[alias] = name_map_[name];
373 }
374
375 ExtensionAPIPermission* ExtensionPermissionsInfo::RegisterPermission(
376 ExtensionAPIPermission::ID id,
377 const char* name,
378 int l10n_message_id,
379 ExtensionPermissionMessage::ID message_id,
380 int flags) {
381 DCHECK(id_map_.find(id) == id_map_.end());
382 DCHECK(name_map_.find(name) == name_map_.end());
383
384 ExtensionAPIPermission* permission = new ExtensionAPIPermission(
385 id, name, l10n_message_id, message_id, flags);
386
387 id_map_[id] = permission;
388 name_map_[name] = permission;
389
390 permission_count_++;
391
392 return permission;
393 }
394
395 //
396 // ExtensionPermissionSet
397 //
398
399 ExtensionPermissionSet::ExtensionPermissionSet() {}
400
401 ExtensionPermissionSet::ExtensionPermissionSet(
402 const extensions::Extension* extension,
403 const ExtensionAPIPermissionSet& apis,
404 const URLPatternSet& explicit_hosts,
405 const ExtensionOAuth2Scopes& scopes)
406 : apis_(apis),
407 scopes_(scopes) {
408 DCHECK(extension);
409 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
410 InitImplicitExtensionPermissions(extension);
411 InitEffectiveHosts();
412 }
413
414 ExtensionPermissionSet::ExtensionPermissionSet(
415 const ExtensionAPIPermissionSet& apis,
416 const URLPatternSet& explicit_hosts,
417 const URLPatternSet& scriptable_hosts)
418 : apis_(apis),
419 scriptable_hosts_(scriptable_hosts) {
420 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
421 InitEffectiveHosts();
422 }
423
424 ExtensionPermissionSet::ExtensionPermissionSet(
425 const ExtensionAPIPermissionSet& apis,
426 const URLPatternSet& explicit_hosts,
427 const URLPatternSet& scriptable_hosts,
428 const ExtensionOAuth2Scopes& scopes)
429 : apis_(apis),
430 scriptable_hosts_(scriptable_hosts),
431 scopes_(scopes) {
432 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
433 InitEffectiveHosts();
434 }
435
436 ExtensionPermissionSet::ExtensionPermissionSet(
437 const ExtensionOAuth2Scopes& scopes)
438 : scopes_(scopes) {
439 InitEffectiveHosts();
440 }
441
442 // static
443 ExtensionPermissionSet* ExtensionPermissionSet::CreateDifference(
444 const ExtensionPermissionSet* set1,
445 const ExtensionPermissionSet* set2) {
446 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
447 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
448 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
449
450 ExtensionAPIPermissionSet apis;
451 std::set_difference(set1_safe->apis().begin(), set1_safe->apis().end(),
452 set2_safe->apis().begin(), set2_safe->apis().end(),
453 std::insert_iterator<ExtensionAPIPermissionSet>(
454 apis, apis.begin()));
455
456 URLPatternSet explicit_hosts;
457 URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
458 set2_safe->explicit_hosts(),
459 &explicit_hosts);
460
461 URLPatternSet scriptable_hosts;
462 URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
463 set2_safe->scriptable_hosts(),
464 &scriptable_hosts);
465
466 ExtensionOAuth2Scopes scopes;
467 std::set_difference(set1_safe->scopes().begin(), set1_safe->scopes().end(),
468 set2_safe->scopes().begin(), set2_safe->scopes().end(),
469 std::insert_iterator<ExtensionOAuth2Scopes>(
470 scopes, scopes.begin()));
471
472 return new ExtensionPermissionSet(
473 apis, explicit_hosts, scriptable_hosts, scopes);
474 }
475
476 // static
477 ExtensionPermissionSet* ExtensionPermissionSet::CreateIntersection(
478 const ExtensionPermissionSet* set1,
479 const ExtensionPermissionSet* set2) {
480 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
481 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
482 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
483
484 ExtensionAPIPermissionSet apis;
485 std::set_intersection(set1_safe->apis().begin(), set1_safe->apis().end(),
486 set2_safe->apis().begin(), set2_safe->apis().end(),
487 std::insert_iterator<ExtensionAPIPermissionSet>(
488 apis, apis.begin()));
489 URLPatternSet explicit_hosts;
490 URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
491 set2_safe->explicit_hosts(),
492 &explicit_hosts);
493
494 URLPatternSet scriptable_hosts;
495 URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
496 set2_safe->scriptable_hosts(),
497 &scriptable_hosts);
498
499 ExtensionOAuth2Scopes scopes;
500 std::set_intersection(set1_safe->scopes().begin(), set1_safe->scopes().end(),
501 set2_safe->scopes().begin(), set2_safe->scopes().end(),
502 std::insert_iterator<ExtensionOAuth2Scopes>(
503 scopes, scopes.begin()));
504
505 return new ExtensionPermissionSet(
506 apis, explicit_hosts, scriptable_hosts, scopes);
507 }
508
509 // static
510 ExtensionPermissionSet* ExtensionPermissionSet::CreateUnion(
511 const ExtensionPermissionSet* set1,
512 const ExtensionPermissionSet* set2) {
513 scoped_refptr<ExtensionPermissionSet> empty = new ExtensionPermissionSet();
514 const ExtensionPermissionSet* set1_safe = (set1 == NULL) ? empty : set1;
515 const ExtensionPermissionSet* set2_safe = (set2 == NULL) ? empty : set2;
516
517 ExtensionAPIPermissionSet apis;
518 std::set_union(set1_safe->apis().begin(), set1_safe->apis().end(),
519 set2_safe->apis().begin(), set2_safe->apis().end(),
520 std::insert_iterator<ExtensionAPIPermissionSet>(
521 apis, apis.begin()));
522
523 URLPatternSet explicit_hosts;
524 URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
525 set2_safe->explicit_hosts(),
526 &explicit_hosts);
527
528 URLPatternSet scriptable_hosts;
529 URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
530 set2_safe->scriptable_hosts(),
531 &scriptable_hosts);
532
533 ExtensionOAuth2Scopes scopes;
534 std::set_union(set1_safe->scopes().begin(), set1_safe->scopes().end(),
535 set2_safe->scopes().begin(), set2_safe->scopes().end(),
536 std::insert_iterator<ExtensionOAuth2Scopes>(
537 scopes, scopes.begin()));
538
539 return new ExtensionPermissionSet(
540 apis, explicit_hosts, scriptable_hosts, scopes);
541 }
542
543 bool ExtensionPermissionSet::operator==(
544 const ExtensionPermissionSet& rhs) const {
545 return apis_ == rhs.apis_ &&
546 scriptable_hosts_ == rhs.scriptable_hosts_ &&
547 explicit_hosts_ == rhs.explicit_hosts_ &&
548 scopes_ == rhs.scopes_;
549 }
550
551 bool ExtensionPermissionSet::Contains(const ExtensionPermissionSet& set) const {
552 // Every set includes the empty set.
553 if (set.IsEmpty())
554 return true;
555
556 if (!std::includes(apis_.begin(), apis_.end(),
557 set.apis().begin(), set.apis().end()))
558 return false;
559
560 if (!explicit_hosts().Contains(set.explicit_hosts()))
561 return false;
562
563 if (!scriptable_hosts().Contains(set.scriptable_hosts()))
564 return false;
565
566 if (!std::includes(scopes_.begin(), scopes_.end(),
567 set.scopes().begin(), set.scopes().end()))
568 return false;
569
570 return true;
571 }
572
573 std::set<std::string> ExtensionPermissionSet::GetAPIsAsStrings() const {
574 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
575 std::set<std::string> apis_str;
576 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
577 i != apis_.end(); ++i) {
578 ExtensionAPIPermission* permission = info->GetByID(*i);
579 if (permission)
580 apis_str.insert(permission->name());
581 }
582 return apis_str;
583 }
584
585 std::set<std::string> ExtensionPermissionSet::
586 GetAPIsWithAnyAccessAsStrings() const {
587 std::set<std::string> result = GetAPIsAsStrings();
588 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i)
589 result.insert(kNonPermissionModuleNames[i]);
590 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i)
591 result.insert(GetPermissionName(kNonPermissionFunctionNames[i]));
592 return result;
593 }
594
595 bool ExtensionPermissionSet::HasAnyAccessToAPI(
596 const std::string& api_name) const {
597 if (HasAccessToFunction(api_name))
598 return true;
599
600 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
601 if (api_name == GetPermissionName(kNonPermissionFunctionNames[i]))
602 return true;
603 }
604
605 return false;
606 }
607
608 std::set<std::string>
609 ExtensionPermissionSet::GetDistinctHostsForDisplay() const {
610 return GetDistinctHosts(effective_hosts_, true, true);
611 }
612
613 ExtensionPermissionMessages
614 ExtensionPermissionSet::GetPermissionMessages() const {
615 ExtensionPermissionMessages messages;
616
617 if (HasEffectiveFullAccess()) {
618 messages.push_back(ExtensionPermissionMessage(
619 ExtensionPermissionMessage::kFullAccess,
620 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
621 return messages;
622 }
623
624 if (HasEffectiveAccessToAllHosts()) {
625 messages.push_back(ExtensionPermissionMessage(
626 ExtensionPermissionMessage::kHostsAll,
627 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
628 } else {
629 std::set<std::string> hosts = GetDistinctHostsForDisplay();
630 if (!hosts.empty())
631 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts));
632 }
633
634 std::set<ExtensionPermissionMessage> simple_msgs =
635 GetSimplePermissionMessages();
636 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
637
638 return messages;
639 }
640
641 std::vector<string16> ExtensionPermissionSet::GetWarningMessages() const {
642 std::vector<string16> messages;
643 ExtensionPermissionMessages permissions = GetPermissionMessages();
644
645 bool audio_capture = false;
646 bool video_capture = false;
647 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
648 i != permissions.end(); ++i) {
649 if (i->id() == ExtensionPermissionMessage::kAudioCapture)
650 audio_capture = true;
651 if (i->id() == ExtensionPermissionMessage::kVideoCapture)
652 video_capture = true;
653 }
654
655 for (ExtensionPermissionMessages::const_iterator i = permissions.begin();
656 i != permissions.end(); ++i) {
657 if (audio_capture && video_capture) {
658 if (i->id() == ExtensionPermissionMessage::kAudioCapture) {
659 messages.push_back(l10n_util::GetStringUTF16(
660 IDS_EXTENSION_PROMPT_WARNING_AUDIO_AND_VIDEO_CAPTURE));
661 continue;
662 } else if (i->id() == ExtensionPermissionMessage::kVideoCapture) {
663 // The combined message will be pushed above.
664 continue;
665 }
666 }
667
668 messages.push_back(i->message());
669 }
670
671 return messages;
672 }
673
674 bool ExtensionPermissionSet::IsEmpty() const {
675 // Not default if any host permissions are present.
676 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
677 return false;
678
679 // Or if it has no api permissions.
680 return apis().empty();
681 }
682
683 bool ExtensionPermissionSet::HasAPIPermission(
684 ExtensionAPIPermission::ID permission) const {
685 return apis().find(permission) != apis().end();
686 }
687
688 bool ExtensionPermissionSet::HasAccessToFunction(
689 const std::string& function_name) const {
690 // TODO(jstritar): Embed this information in each permission and add a method
691 // like GrantsAccess(function_name) to ExtensionAPIPermission. A "default"
692 // permission can then handle the modules and functions that everyone can
693 // access.
694 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
695 if (function_name == kNonPermissionFunctionNames[i])
696 return true;
697 }
698
699 std::string permission_name = GetPermissionName(function_name);
700 ExtensionAPIPermission* permission =
701 ExtensionPermissionsInfo::GetInstance()->GetByName(permission_name);
702 if (permission && apis_.count(permission->id()))
703 return true;
704
705 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
706 if (permission_name == kNonPermissionModuleNames[i]) {
707 return true;
708 }
709 }
710
711 return false;
712 }
713
714 bool ExtensionPermissionSet::HasExplicitAccessToOrigin(
715 const GURL& origin) const {
716 return explicit_hosts().MatchesURL(origin);
717 }
718
719 bool ExtensionPermissionSet::HasScriptableAccessToURL(
720 const GURL& origin) const {
721 // We only need to check our host list to verify access. The host list should
722 // already reflect any special rules (such as chrome://favicon, all hosts
723 // access, etc.).
724 return scriptable_hosts().MatchesURL(origin);
725 }
726
727 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const {
728 // There are two ways this set can have effective access to all hosts:
729 // 1) it has an <all_urls> URL pattern.
730 // 2) it has a named permission with implied full URL access.
731 for (URLPatternSet::const_iterator host = effective_hosts().begin();
732 host != effective_hosts().end(); ++host) {
733 if (host->match_all_urls() ||
734 (host->match_subdomains() && host->host().empty()))
735 return true;
736 }
737
738 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
739 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
740 i != apis().end(); ++i) {
741 ExtensionAPIPermission* permission = info->GetByID(*i);
742 if (permission->implies_full_url_access())
743 return true;
744 }
745 return false;
746 }
747
748 bool ExtensionPermissionSet::HasEffectiveAccessToURL(
749 const GURL& url) const {
750 return effective_hosts().MatchesURL(url);
751 }
752
753 bool ExtensionPermissionSet::HasEffectiveFullAccess() const {
754 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
755 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin();
756 i != apis().end(); ++i) {
757 ExtensionAPIPermission* permission = info->GetByID(*i);
758 if (permission->implies_full_access())
759 return true;
760 }
761 return false;
762 }
763
764 bool ExtensionPermissionSet::HasLessPrivilegesThan(
765 const ExtensionPermissionSet* permissions) const {
766 // Things can't get worse than native code access.
767 if (HasEffectiveFullAccess())
768 return false;
769
770 // Otherwise, it's a privilege increase if the new one has full access.
771 if (permissions->HasEffectiveFullAccess())
772 return true;
773
774 if (HasLessHostPrivilegesThan(permissions))
775 return true;
776
777 if (HasLessAPIPrivilegesThan(permissions))
778 return true;
779
780 if (HasLessScopesThan(permissions))
781 return true;
782
783 return false;
784 }
785
786 ExtensionPermissionSet::~ExtensionPermissionSet() {}
787
788 // static
789 std::set<std::string> ExtensionPermissionSet::GetDistinctHosts(
790 const URLPatternSet& host_patterns,
791 bool include_rcd,
792 bool exclude_file_scheme) {
793 // Use a vector to preserve order (also faster than a map on small sets).
794 // Each item is a host split into two parts: host without RCDs and
795 // current best RCD.
796 typedef std::vector<std::pair<std::string, std::string> > HostVector;
797 HostVector hosts_best_rcd;
798 for (URLPatternSet::const_iterator i = host_patterns.begin();
799 i != host_patterns.end(); ++i) {
800 if (exclude_file_scheme && i->scheme() == chrome::kFileScheme)
801 continue;
802
803 std::string host = i->host();
804
805 // Add the subdomain wildcard back to the host, if necessary.
806 if (i->match_subdomains())
807 host = "*." + host;
808
809 // If the host has an RCD, split it off so we can detect duplicates.
810 std::string rcd;
811 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
812 host, false);
813 if (reg_len && reg_len != std::string::npos) {
814 if (include_rcd) // else leave rcd empty
815 rcd = host.substr(host.size() - reg_len);
816 host = host.substr(0, host.size() - reg_len);
817 }
818
819 // Check if we've already seen this host.
820 HostVector::iterator it = hosts_best_rcd.begin();
821 for (; it != hosts_best_rcd.end(); ++it) {
822 if (it->first == host)
823 break;
824 }
825 // If this host was found, replace the RCD if this one is better.
826 if (it != hosts_best_rcd.end()) {
827 if (include_rcd && RcdBetterThan(rcd, it->second))
828 it->second = rcd;
829 } else { // Previously unseen host, append it.
830 hosts_best_rcd.push_back(std::make_pair(host, rcd));
831 }
832 }
833
834 // Build up the final vector by concatenating hosts and RCDs.
835 std::set<std::string> distinct_hosts;
836 for (HostVector::iterator it = hosts_best_rcd.begin();
837 it != hosts_best_rcd.end(); ++it)
838 distinct_hosts.insert(it->first + it->second);
839 return distinct_hosts;
840 }
841
842 void ExtensionPermissionSet::InitImplicitExtensionPermissions(
843 const extensions::Extension* extension) {
844 // Add the implied permissions.
845 if (!extension->plugins().empty())
846 apis_.insert(ExtensionAPIPermission::kPlugin);
847
848 if (!extension->devtools_url().is_empty())
849 apis_.insert(ExtensionAPIPermission::kDevtools);
850
851 // The webRequest permission implies the internal version as well.
852 if (apis_.find(ExtensionAPIPermission::kWebRequest) != apis_.end())
853 apis_.insert(ExtensionAPIPermission::kWebRequestInternal);
854
855 // The fileBrowserHandler permission implies the internal version as well.
856 if (apis_.find(ExtensionAPIPermission::kFileBrowserHandler) != apis_.end())
857 apis_.insert(ExtensionAPIPermission::kFileBrowserHandlerInternal);
858
859 // Add the scriptable hosts.
860 for (UserScriptList::const_iterator content_script =
861 extension->content_scripts().begin();
862 content_script != extension->content_scripts().end(); ++content_script) {
863 URLPatternSet::const_iterator pattern =
864 content_script->url_patterns().begin();
865 for (; pattern != content_script->url_patterns().end(); ++pattern)
866 scriptable_hosts_.AddPattern(*pattern);
867 }
868 }
869
870 void ExtensionPermissionSet::InitEffectiveHosts() {
871 effective_hosts_.ClearPatterns();
872
873 URLPatternSet::CreateUnion(
874 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
875 }
876
877 std::set<ExtensionPermissionMessage>
878 ExtensionPermissionSet::GetSimplePermissionMessages() const {
879 std::set<ExtensionPermissionMessage> messages;
880 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
881 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin();
882 i != apis_.end(); ++i) {
883 DCHECK_GT(ExtensionPermissionMessage::kNone,
884 ExtensionPermissionMessage::kUnknown);
885 ExtensionAPIPermission* perm = info->GetByID(*i);
886 if (perm && perm->message_id() > ExtensionPermissionMessage::kNone)
887 messages.insert(perm->GetMessage());
888 }
889 return messages;
890 }
891
892 bool ExtensionPermissionSet::HasLessAPIPrivilegesThan(
893 const ExtensionPermissionSet* permissions) const {
894 if (permissions == NULL)
895 return false;
896
897 std::set<ExtensionPermissionMessage> current_warnings =
898 GetSimplePermissionMessages();
899 std::set<ExtensionPermissionMessage> new_warnings =
900 permissions->GetSimplePermissionMessages();
901 std::set<ExtensionPermissionMessage> delta_warnings;
902 std::set_difference(new_warnings.begin(), new_warnings.end(),
903 current_warnings.begin(), current_warnings.end(),
904 std::inserter(delta_warnings, delta_warnings.begin()));
905
906 // We have less privileges if there are additional warnings present.
907 return !delta_warnings.empty();
908 }
909
910 bool ExtensionPermissionSet::HasLessHostPrivilegesThan(
911 const ExtensionPermissionSet* permissions) const {
912 // If this permission set can access any host, then it can't be elevated.
913 if (HasEffectiveAccessToAllHosts())
914 return false;
915
916 // Likewise, if the other permission set has full host access, then it must be
917 // a privilege increase.
918 if (permissions->HasEffectiveAccessToAllHosts())
919 return true;
920
921 const URLPatternSet& old_list = effective_hosts();
922 const URLPatternSet& new_list = permissions->effective_hosts();
923
924 // TODO(jstritar): This is overly conservative with respect to subdomains.
925 // For example, going from *.google.com to www.google.com will be
926 // considered an elevation, even though it is not (http://crbug.com/65337).
927 std::set<std::string> new_hosts_set(GetDistinctHosts(new_list, false, false));
928 std::set<std::string> old_hosts_set(GetDistinctHosts(old_list, false, false));
929 std::set<std::string> new_hosts_only;
930
931 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
932 old_hosts_set.begin(), old_hosts_set.end(),
933 std::inserter(new_hosts_only, new_hosts_only.begin()));
934
935 return !new_hosts_only.empty();
936 }
937
938 bool ExtensionPermissionSet::HasLessScopesThan(
939 const ExtensionPermissionSet* permissions) const {
940 if (permissions == NULL)
941 return false;
942
943 ExtensionOAuth2Scopes current_scopes = scopes();
944 ExtensionOAuth2Scopes new_scopes = permissions->scopes();
945 ExtensionOAuth2Scopes delta_scopes;
946 std::set_difference(new_scopes.begin(), new_scopes.end(),
947 current_scopes.begin(), current_scopes.end(),
948 std::inserter(delta_scopes, delta_scopes.begin()));
949
950 // We have less privileges if there are additional scopes present.
951 return !delta_scopes.empty();
952 }
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