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

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

Issue 7003098: Start refractoring extension permissions into ExtensionPermissionSet. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase + small cleanup Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/extensions/extension.h" 5 #include "chrome/common/extensions/extension.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 91
92 bool IsBaseCrxKey(const std::string& key) { 92 bool IsBaseCrxKey(const std::string& key) {
93 for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) { 93 for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) {
94 if (key == kBaseCrxKeys[i]) 94 if (key == kBaseCrxKeys[i])
95 return true; 95 return true;
96 } 96 }
97 97
98 return false; 98 return false;
99 } 99 }
100 100
101 // Constant used to represent an undefined l10n message id.
102 const int kUndefinedMessageId = -1;
103
104 // Names of API modules that do not require a permission.
105 const char kBrowserActionModuleName[] = "browserAction";
106 const char kBrowserActionsModuleName[] = "browserActions";
107 const char kDevToolsModuleName[] = "devtools";
108 const char kExtensionModuleName[] = "extension";
109 const char kI18NModuleName[] = "i18n";
110 const char kOmniboxModuleName[] = "omnibox";
111 const char kPageActionModuleName[] = "pageAction";
112 const char kPageActionsModuleName[] = "pageActions";
113 const char kTestModuleName[] = "test";
114 const char kTypesModuleName[] = "types";
115
116 // Names of modules that can be used without listing it in the permissions
117 // section of the manifest.
118 const char* kNonPermissionModuleNames[] = {
119 kBrowserActionModuleName,
120 kBrowserActionsModuleName,
121 kDevToolsModuleName,
122 kExtensionModuleName,
123 kI18NModuleName,
124 kOmniboxModuleName,
125 kPageActionModuleName,
126 kPageActionsModuleName,
127 kTestModuleName,
128 kTypesModuleName
129 };
130 const size_t kNumNonPermissionModuleNames =
131 arraysize(kNonPermissionModuleNames);
132
133 // Names of functions (within modules requiring permissions) that can be used
134 // without asking for the module permission. In other words, functions you can
135 // use with no permissions specified.
136 const char* kNonPermissionFunctionNames[] = {
137 "tabs.create",
138 "tabs.onRemoved",
139 "tabs.remove",
140 "tabs.update",
141 };
142 const size_t kNumNonPermissionFunctionNames =
143 arraysize(kNonPermissionFunctionNames);
144
145 // A singleton object containing global data needed by the extension objects. 101 // A singleton object containing global data needed by the extension objects.
146 class ExtensionConfig { 102 class ExtensionConfig {
147 public: 103 public:
148 static ExtensionConfig* GetInstance() { 104 static ExtensionConfig* GetInstance() {
149 return Singleton<ExtensionConfig>::get(); 105 return Singleton<ExtensionConfig>::get();
150 } 106 }
151 107
152 Extension::PermissionMessage::MessageId GetPermissionMessageId(
153 const std::string& permission) {
154 return Extension::kPermissions[permission_map_[permission]].message_id;
155 }
156
157 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; } 108 Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; }
158 109
159 private: 110 private:
160 friend struct DefaultSingletonTraits<ExtensionConfig>; 111 friend struct DefaultSingletonTraits<ExtensionConfig>;
161 112
162 ExtensionConfig() { 113 ExtensionConfig() { }
163 for (size_t i = 0; i < Extension::kNumPermissions; ++i)
164 permission_map_[Extension::kPermissions[i].name] = i;
165 };
166
167 ~ExtensionConfig() { } 114 ~ExtensionConfig() { }
168 115
169 std::map<const std::string, size_t> permission_map_;
170
171 // A whitelist of extensions that can script anywhere. Do not add to this 116 // A whitelist of extensions that can script anywhere. Do not add to this
172 // list (except in tests) without consulting the Extensions team first. 117 // list (except in tests) without consulting the Extensions team first.
173 // Note: Component extensions have this right implicitly and do not need to be 118 // Note: Component extensions have this right implicitly and do not need to be
174 // added to this list. 119 // added to this list.
175 Extension::ScriptingWhitelist scripting_whitelist_; 120 Extension::ScriptingWhitelist scripting_whitelist_;
176 }; 121 };
177 122
178 // Aliased to kTabPermission for purposes of API checks, but not allowed
179 // in the permissions field of the manifest.
180 static const char kWindowPermission[] = "windows";
181
182 // Rank extension locations in a way that allows 123 // Rank extension locations in a way that allows
183 // Extension::GetHigherPriorityLocation() to compare locations. 124 // Extension::GetHigherPriorityLocation() to compare locations.
184 // An extension installed from two locations will have the location 125 // An extension installed from two locations will have the location
185 // with the higher rank, as returned by this function. The actual 126 // with the higher rank, as returned by this function. The actual
186 // integer values may change, and should never be persisted. 127 // integer values may change, and should never be persisted.
187 int GetLocationRank(Extension::Location location) { 128 int GetLocationRank(Extension::Location location) {
188 const int kInvalidRank = -1; 129 const int kInvalidRank = -1;
189 int rank = kInvalidRank; // Will CHECK that rank is not kInvalidRank. 130 int rank = kInvalidRank; // Will CHECK that rank is not kInvalidRank.
190 131
191 switch (location) { 132 switch (location) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 EXTENSION_ICON_MEDIUM, 198 EXTENSION_ICON_MEDIUM,
258 EXTENSION_ICON_SMALL, 199 EXTENSION_ICON_SMALL,
259 EXTENSION_ICON_SMALLISH, 200 EXTENSION_ICON_SMALLISH,
260 EXTENSION_ICON_BITTY 201 EXTENSION_ICON_BITTY
261 }; 202 };
262 203
263 const int Extension::kPageActionIconMaxSize = 19; 204 const int Extension::kPageActionIconMaxSize = 19;
264 const int Extension::kBrowserActionIconMaxSize = 19; 205 const int Extension::kBrowserActionIconMaxSize = 19;
265 const int Extension::kSidebarIconMaxSize = 16; 206 const int Extension::kSidebarIconMaxSize = 16;
266 207
267 // Explicit permissions -- permission declaration required.
268 const char Extension::kBackgroundPermission[] = "background";
269 const char Extension::kBookmarkPermission[] = "bookmarks";
270 const char Extension::kClipboardReadPermission[] = "clipboardRead";
271 const char Extension::kClipboardWritePermission[] = "clipboardWrite";
272 const char Extension::kContextMenusPermission[] = "contextMenus";
273 const char Extension::kContentSettingsPermission[] = "contentSettings";
274 const char Extension::kCookiePermission[] = "cookies";
275 const char Extension::kChromePrivatePermission[] = "chromePrivate";
276 const char Extension::kChromeosInfoPrivatePermission[] = "chromeosInfoPrivate";
277 const char Extension::kDebuggerPermission[] = "debugger";
278 const char Extension::kExperimentalPermission[] = "experimental";
279 const char Extension::kFileBrowserHandlerPermission[] = "fileBrowserHandler";
280 const char Extension::kFileBrowserPrivatePermission[] = "fileBrowserPrivate";
281 const char Extension::kGeolocationPermission[] = "geolocation";
282 const char Extension::kHistoryPermission[] = "history";
283 const char Extension::kIdlePermission[] = "idle";
284 const char Extension::kManagementPermission[] = "management";
285 const char Extension::kMediaPlayerPrivatePermission[] = "mediaPlayerPrivate";
286 const char Extension::kNotificationPermission[] = "notifications";
287 const char Extension::kProxyPermission[] = "proxy";
288 const char Extension::kTabPermission[] = "tabs";
289 const char Extension::kUnlimitedStoragePermission[] = "unlimitedStorage";
290 const char Extension::kWebstorePrivatePermission[] = "webstorePrivate";
291 const char Extension::kWebSocketProxyPrivatePermission[] =
292 "webSocketProxyPrivate";
293
294 // In general, all permissions should have an install message.
295 // See ExtensionsTest.PermissionMessages for an explanation of each
296 // exception.
297 const Extension::Permission Extension::kPermissions[] = {
298 { kBackgroundPermission, PermissionMessage::ID_NONE },
299 { kBookmarkPermission, PermissionMessage::ID_BOOKMARKS },
300 { kChromePrivatePermission, PermissionMessage::ID_NONE },
301 { kChromeosInfoPrivatePermission, PermissionMessage::ID_NONE },
302 { kClipboardReadPermission, PermissionMessage::ID_CLIPBOARD },
303 { kClipboardWritePermission, PermissionMessage::ID_NONE },
304 { kContentSettingsPermission, PermissionMessage::ID_NONE },
305 { kContextMenusPermission, PermissionMessage::ID_NONE },
306 { kCookiePermission, PermissionMessage::ID_NONE },
307 { kDebuggerPermission, PermissionMessage::ID_DEBUGGER },
308 { kExperimentalPermission, PermissionMessage::ID_NONE },
309 { kFileBrowserHandlerPermission, PermissionMessage::ID_NONE },
310 { kFileBrowserPrivatePermission, PermissionMessage::ID_NONE },
311 { kGeolocationPermission, PermissionMessage::ID_GEOLOCATION },
312 { kHistoryPermission, PermissionMessage::ID_BROWSING_HISTORY },
313 { kIdlePermission, PermissionMessage::ID_NONE },
314 { kManagementPermission, PermissionMessage::ID_MANAGEMENT },
315 { kMediaPlayerPrivatePermission, PermissionMessage::ID_NONE },
316 { kNotificationPermission, PermissionMessage::ID_NONE },
317 { kProxyPermission, PermissionMessage::ID_NONE },
318 { kTabPermission, PermissionMessage::ID_TABS },
319 { kUnlimitedStoragePermission, PermissionMessage::ID_NONE },
320 { kWebSocketProxyPrivatePermission, PermissionMessage::ID_NONE },
321 { kWebstorePrivatePermission, PermissionMessage::ID_NONE },
322 };
323 const size_t Extension::kNumPermissions = arraysize(Extension::kPermissions);
324
325 const char* const Extension::kHostedAppPermissionNames[] = {
326 Extension::kBackgroundPermission,
327 Extension::kChromePrivatePermission,
328 Extension::kClipboardReadPermission,
329 Extension::kClipboardWritePermission,
330 Extension::kExperimentalPermission,
331 Extension::kGeolocationPermission,
332 Extension::kNotificationPermission,
333 Extension::kUnlimitedStoragePermission,
334 Extension::kWebstorePrivatePermission,
335 };
336 const size_t Extension::kNumHostedAppPermissions =
337 arraysize(Extension::kHostedAppPermissionNames);
338
339 const char* const Extension::kComponentPrivatePermissionNames[] = {
340 Extension::kFileBrowserPrivatePermission,
341 Extension::kWebstorePrivatePermission,
342 Extension::kMediaPlayerPrivatePermission,
343 Extension::kChromeosInfoPrivatePermission,
344 };
345 const size_t Extension::kNumComponentPrivatePermissions =
346 arraysize(Extension::kComponentPrivatePermissionNames);
347
348 // We purposefully don't put this into kPermissionNames.
349 const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage";
350
351 const int Extension::kValidWebExtentSchemes = 208 const int Extension::kValidWebExtentSchemes =
352 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS; 209 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
353 210
354 const int Extension::kValidHostPermissionSchemes = 211 const int Extension::kValidHostPermissionSchemes =
355 UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI; 212 UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI;
356 213
357 Extension::InputComponentInfo::InputComponentInfo() 214 Extension::InputComponentInfo::InputComponentInfo()
358 : type(INPUT_COMPONENT_TYPE_NONE), 215 : type(INPUT_COMPONENT_TYPE_NONE),
359 shortcut_alt(false), 216 shortcut_alt(false),
360 shortcut_ctrl(false), 217 shortcut_ctrl(false),
361 shortcut_shift(false) { 218 shortcut_shift(false) {
362 } 219 }
363 220
364 Extension::InputComponentInfo::~InputComponentInfo() {} 221 Extension::InputComponentInfo::~InputComponentInfo() {}
365 222
366 // 223 //
367 // PermissionMessage
368 //
369
370 // static
371 Extension::PermissionMessage Extension::PermissionMessage::CreateFromMessageId(
372 Extension::PermissionMessage::MessageId message_id) {
373 DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
374 if (message_id <= ID_NONE)
375 return PermissionMessage(message_id, string16());
376
377 string16 message = l10n_util::GetStringUTF16(kMessageIds[message_id]);
378 return PermissionMessage(message_id, message);
379 }
380
381 // static
382 Extension::PermissionMessage Extension::PermissionMessage::CreateFromHostList(
383 const std::vector<std::string> hosts) {
384 CHECK(hosts.size() > 0);
385
386 MessageId message_id;
387 string16 message;
388 switch (hosts.size()) {
389 case 1:
390 message_id = ID_HOSTS_1;
391 message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
392 UTF8ToUTF16(hosts[0]));
393 break;
394 case 2:
395 message_id = ID_HOSTS_2;
396 message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
397 UTF8ToUTF16(hosts[0]),
398 UTF8ToUTF16(hosts[1]));
399 break;
400 case 3:
401 message_id = ID_HOSTS_3;
402 message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
403 UTF8ToUTF16(hosts[0]),
404 UTF8ToUTF16(hosts[1]),
405 UTF8ToUTF16(hosts[2]));
406 break;
407 default:
408 message_id = ID_HOSTS_4_OR_MORE;
409 message = l10n_util::GetStringFUTF16(
410 kMessageIds[message_id],
411 UTF8ToUTF16(hosts[0]),
412 UTF8ToUTF16(hosts[1]),
413 base::IntToString16(hosts.size() - 2));
414 break;
415 }
416
417 return PermissionMessage(message_id, message);
418 }
419
420 Extension::PermissionMessage::PermissionMessage(
421 Extension::PermissionMessage::MessageId message_id, string16 message)
422 : message_id_(message_id),
423 message_(message) {
424 }
425
426 const int Extension::PermissionMessage::kMessageIds[] = {
427 kUndefinedMessageId, // "unknown"
428 kUndefinedMessageId, // "none"
429 IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
430 IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
431 IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
432 IDS_EXTENSION_PROMPT_WARNING_TABS,
433 IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
434 IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
435 IDS_EXTENSION_PROMPT_WARNING_1_HOST,
436 IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
437 IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
438 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
439 IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS,
440 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS,
441 IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD
442 };
443
444 //
445 // Extension 224 // Extension
446 // 225 //
447 226
448 // static 227 // static
449 scoped_refptr<Extension> Extension::Create(const FilePath& path, 228 scoped_refptr<Extension> Extension::Create(const FilePath& path,
450 Location location, 229 Location location,
451 const DictionaryValue& value, 230 const DictionaryValue& value,
452 int flags, 231 int flags,
453 std::string* error) { 232 std::string* error) {
454 scoped_refptr<Extension> extension = new Extension(path, location); 233 scoped_refptr<Extension> extension = new Extension(path, location);
(...skipping 29 matching lines...) Expand all
484 int loc2_rank = GetLocationRank(loc2); 263 int loc2_rank = GetLocationRank(loc2);
485 264
486 // If two different locations have the same rank, then we can not 265 // If two different locations have the same rank, then we can not
487 // deterministicly choose a location. 266 // deterministicly choose a location.
488 CHECK(loc1_rank != loc2_rank); 267 CHECK(loc1_rank != loc2_rank);
489 268
490 // Lowest rank has highest priority. 269 // Lowest rank has highest priority.
491 return (loc1_rank > loc2_rank ? loc1 : loc2 ); 270 return (loc1_rank > loc2_rank ? loc1 : loc2 );
492 } 271 }
493 272
494 // static 273 ExtensionPermissionMessages Extension::GetPermissionMessages() const {
495 Extension::PermissionMessage::MessageId Extension::GetPermissionMessageId( 274 return permission_set_->GetPermissionMessages();
496 const std::string& permission) {
497 return ExtensionConfig::GetInstance()->GetPermissionMessageId(permission);
498 }
499
500 Extension::PermissionMessages Extension::GetPermissionMessages() const {
501 PermissionMessages messages;
502 if (!plugins().empty()) {
503 messages.push_back(PermissionMessage::CreateFromMessageId(
504 PermissionMessage::ID_FULL_ACCESS));
505 return messages;
506 }
507
508 if (HasEffectiveAccessToAllHosts()) {
509 messages.push_back(PermissionMessage::CreateFromMessageId(
510 PermissionMessage::ID_HOSTS_ALL));
511 } else {
512 std::vector<std::string> hosts = GetDistinctHostsForDisplay(
513 GetEffectiveHostPermissions().patterns());
514 if (!hosts.empty())
515 messages.push_back(PermissionMessage::CreateFromHostList(hosts));
516 }
517
518 std::set<PermissionMessage> simple_msgs = GetSimplePermissionMessages();
519 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
520
521 return messages;
522 } 275 }
523 276
524 std::vector<string16> Extension::GetPermissionMessageStrings() const { 277 std::vector<string16> Extension::GetPermissionMessageStrings() const {
525 std::vector<string16> messages; 278 return permission_set_->GetWarningMessages();
526 PermissionMessages permissions = GetPermissionMessages();
527 for (PermissionMessages::const_iterator i = permissions.begin();
528 i != permissions.end(); ++i)
529 messages.push_back(i->message());
530 return messages;
531 }
532
533 std::set<Extension::PermissionMessage>
534 Extension::GetSimplePermissionMessages() const {
535 std::set<PermissionMessage> messages;
536 std::set<std::string>::const_iterator i;
537 for (i = api_permissions().begin(); i != api_permissions().end(); ++i) {
538 PermissionMessage::MessageId message_id = GetPermissionMessageId(*i);
539 DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
540 if (message_id > PermissionMessage::ID_NONE)
541 messages.insert(PermissionMessage::CreateFromMessageId(message_id));
542 }
543 return messages;
544 }
545
546 // static
547 std::vector<std::string> Extension::GetDistinctHostsForDisplay(
548 const URLPatternList& list) {
549 return GetDistinctHosts(list, true);
550 }
551
552 // static
553 bool Extension::IsElevatedHostList(
554 const URLPatternList& old_list, const URLPatternList& new_list) {
555 // TODO(jstritar): This is overly conservative with respect to subdomains.
556 // For example, going from *.google.com to www.google.com will be
557 // considered an elevation, even though it is not (http://crbug.com/65337).
558
559 std::vector<std::string> new_hosts = GetDistinctHosts(new_list, false);
560 std::vector<std::string> old_hosts = GetDistinctHosts(old_list, false);
561
562 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end());
563 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end());
564 std::set<std::string> new_hosts_only;
565
566 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
567 old_hosts_set.begin(), old_hosts_set.end(),
568 std::inserter(new_hosts_only, new_hosts_only.begin()));
569
570 return !new_hosts_only.empty();
571 }
572
573 // Helper for GetDistinctHosts(): com > net > org > everything else.
574 static bool RcdBetterThan(const std::string& a, const std::string& b) {
575 if (a == b)
576 return false;
577 if (a == "com")
578 return true;
579 if (a == "net")
580 return b != "com";
581 if (a == "org")
582 return b != "com" && b != "net";
583 return false;
584 }
585
586 // static
587 std::vector<std::string> Extension::GetDistinctHosts(
588 const URLPatternList& host_patterns,
589 bool include_rcd) {
590 // Use a vector to preserve order (also faster than a map on small sets).
591 // Each item is a host split into two parts: host without RCDs and
592 // current best RCD.
593 typedef std::vector<std::pair<std::string, std::string> > HostVector;
594 HostVector hosts_best_rcd;
595 for (size_t i = 0; i < host_patterns.size(); ++i) {
596 std::string host = host_patterns[i].host();
597
598 // Add the subdomain wildcard back to the host, if necessary.
599 if (host_patterns[i].match_subdomains())
600 host = "*." + host;
601
602 // If the host has an RCD, split it off so we can detect duplicates.
603 std::string rcd;
604 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
605 host, false);
606 if (reg_len && reg_len != std::string::npos) {
607 if (include_rcd) // else leave rcd empty
608 rcd = host.substr(host.size() - reg_len);
609 host = host.substr(0, host.size() - reg_len);
610 }
611
612 // Check if we've already seen this host.
613 HostVector::iterator it = hosts_best_rcd.begin();
614 for (; it != hosts_best_rcd.end(); ++it) {
615 if (it->first == host)
616 break;
617 }
618 // If this host was found, replace the RCD if this one is better.
619 if (it != hosts_best_rcd.end()) {
620 if (include_rcd && RcdBetterThan(rcd, it->second))
621 it->second = rcd;
622 } else { // Previously unseen host, append it.
623 hosts_best_rcd.push_back(std::make_pair(host, rcd));
624 }
625 }
626
627 // Build up the final vector by concatenating hosts and RCDs.
628 std::vector<std::string> distinct_hosts;
629 for (HostVector::iterator it = hosts_best_rcd.begin();
630 it != hosts_best_rcd.end(); ++it)
631 distinct_hosts.push_back(it->first + it->second);
632 return distinct_hosts;
633 } 279 }
634 280
635 FilePath Extension::MaybeNormalizePath(const FilePath& path) { 281 FilePath Extension::MaybeNormalizePath(const FilePath& path) {
636 #if defined(OS_WIN) 282 #if defined(OS_WIN)
637 // Normalize any drive letter to upper-case. We do this for consistency with 283 // Normalize any drive letter to upper-case. We do this for consistency with
638 // net_utils::FilePathToFileURL(), which does the same thing, to make string 284 // net_utils::FilePathToFileURL(), which does the same thing, to make string
639 // comparisons simpler. 285 // comparisons simpler.
640 std::wstring path_str = path.value(); 286 std::wstring path_str = path.value();
641 if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' && 287 if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' &&
642 path_str[1] == ':') 288 path_str[1] == ':')
643 path_str[0] += ('A' - 'a'); 289 path_str[0] += ('A' - 'a');
644 290
645 return FilePath(path_str); 291 return FilePath(path_str);
646 #else 292 #else
647 return path; 293 return path;
648 #endif 294 #endif
649 } 295 }
650 296
651 // static
652 bool Extension::IsHostedAppPermission(const std::string& str) {
653 for (size_t i = 0; i < Extension::kNumHostedAppPermissions; ++i) {
654 if (str == Extension::kHostedAppPermissionNames[i]) {
655 return true;
656 }
657 }
658 return false;
659 }
660
661 const std::string Extension::VersionString() const { 297 const std::string Extension::VersionString() const {
662 return version()->GetString(); 298 return version()->GetString();
663 } 299 }
664 300
665 // static 301 // static
666 bool Extension::IsExtension(const FilePath& file_name) { 302 bool Extension::IsExtension(const FilePath& file_name) {
667 return file_name.MatchesExtension(chrome::kExtensionFileExtension); 303 return file_name.MatchesExtension(chrome::kExtensionFileExtension);
668 } 304 }
669 305
670 // static 306 // static
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 output->append(" "); 1253 output->append(" ");
1618 output->append(is_public ? kPublic : kPrivate); 1254 output->append(is_public ? kPublic : kPrivate);
1619 output->append(" "); 1255 output->append(" ");
1620 output->append(kKeyInfoEndMarker); 1256 output->append(kKeyInfoEndMarker);
1621 output->append("\n"); 1257 output->append("\n");
1622 1258
1623 return true; 1259 return true;
1624 } 1260 }
1625 1261
1626 // static 1262 // static
1627 bool Extension::IsPrivilegeIncrease(const bool granted_full_access,
1628 const std::set<std::string>& granted_apis,
1629 const URLPatternSet& granted_extent,
1630 const Extension* new_extension) {
1631 // If the extension had native code access, we don't need to go any further.
1632 // Things can't get any worse.
1633 if (granted_full_access)
1634 return false;
1635
1636 // Otherwise, if the new extension has a plugin, it's a privilege increase.
1637 if (new_extension->HasFullPermissions())
1638 return true;
1639
1640 // If the extension hadn't been granted access to all hosts in the past, then
1641 // see if the extension requires more host permissions.
1642 if (!HasEffectiveAccessToAllHosts(granted_extent, granted_apis)) {
1643 if (new_extension->HasEffectiveAccessToAllHosts())
1644 return true;
1645
1646 const URLPatternSet new_extent =
1647 new_extension->GetEffectiveHostPermissions();
1648
1649 if (IsElevatedHostList(granted_extent.patterns(), new_extent.patterns()))
1650 return true;
1651 }
1652
1653 std::set<std::string> new_apis = new_extension->api_permissions();
1654 std::set<std::string> new_apis_only;
1655 std::set_difference(new_apis.begin(), new_apis.end(),
1656 granted_apis.begin(), granted_apis.end(),
1657 std::inserter(new_apis_only, new_apis_only.begin()));
1658
1659 // Ignore API permissions that don't require user approval when deciding if
1660 // an extension has increased its privileges.
1661 size_t new_api_count = 0;
1662 for (std::set<std::string>::iterator i = new_apis_only.begin();
1663 i != new_apis_only.end(); ++i) {
1664 DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
1665 if (GetPermissionMessageId(*i) > PermissionMessage::ID_NONE)
1666 new_api_count++;
1667 }
1668
1669 if (new_api_count)
1670 return true;
1671
1672 return false;
1673 }
1674
1675 // static
1676 void Extension::DecodeIcon(const Extension* extension, 1263 void Extension::DecodeIcon(const Extension* extension,
1677 Icons icon_size, 1264 Icons icon_size,
1678 scoped_ptr<SkBitmap>* result) { 1265 scoped_ptr<SkBitmap>* result) {
1679 FilePath icon_path = extension->GetIconResource( 1266 FilePath icon_path = extension->GetIconResource(
1680 icon_size, ExtensionIconSet::MATCH_EXACTLY).GetFilePath(); 1267 icon_size, ExtensionIconSet::MATCH_EXACTLY).GetFilePath();
1681 DecodeIconFromPath(icon_path, icon_size, result); 1268 DecodeIconFromPath(icon_path, icon_size, result);
1682 } 1269 }
1683 1270
1684 // static 1271 // static
1685 void Extension::DecodeIconFromPath(const FilePath& icon_path, 1272 void Extension::DecodeIconFromPath(const FilePath& icon_path,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 chrome::kStandardSchemeSeparator + extension_id + "/"); 1319 chrome::kStandardSchemeSeparator + extension_id + "/");
1733 } 1320 }
1734 1321
1735 bool Extension::InitFromValue(const DictionaryValue& source, int flags, 1322 bool Extension::InitFromValue(const DictionaryValue& source, int flags,
1736 std::string* error) { 1323 std::string* error) {
1737 // When strict error checks are enabled, make URL pattern parsing strict. 1324 // When strict error checks are enabled, make URL pattern parsing strict.
1738 URLPattern::ParseOption parse_strictness = 1325 URLPattern::ParseOption parse_strictness =
1739 (flags & STRICT_ERROR_CHECKS ? URLPattern::PARSE_STRICT 1326 (flags & STRICT_ERROR_CHECKS ? URLPattern::PARSE_STRICT
1740 : URLPattern::PARSE_LENIENT); 1327 : URLPattern::PARSE_LENIENT);
1741 1328
1329 // Initialize permissions with an empty, default permission set.
1330 permission_set_.reset(new ExtensionPermissionSet());
1331
1742 if (source.HasKey(keys::kPublicKey)) { 1332 if (source.HasKey(keys::kPublicKey)) {
1743 std::string public_key_bytes; 1333 std::string public_key_bytes;
1744 if (!source.GetString(keys::kPublicKey, 1334 if (!source.GetString(keys::kPublicKey,
1745 &public_key_) || 1335 &public_key_) ||
1746 !ParsePEMKeyBytes(public_key_, 1336 !ParsePEMKeyBytes(public_key_,
1747 &public_key_bytes) || 1337 &public_key_bytes) ||
1748 !GenerateId(public_key_bytes, &id_)) { 1338 !GenerateId(public_key_bytes, &id_)) {
1749 *error = errors::kInvalidKey; 1339 *error = errors::kInvalidKey;
1750 return false; 1340 return false;
1751 } 1341 }
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 return false; 1840 return false;
2251 } 1841 }
2252 options_url_ = GetResourceURL(options_str); 1842 options_url_ = GetResourceURL(options_str);
2253 if (!options_url_.is_valid()) { 1843 if (!options_url_.is_valid()) {
2254 *error = errors::kInvalidOptionsPage; 1844 *error = errors::kInvalidOptionsPage;
2255 return false; 1845 return false;
2256 } 1846 }
2257 } 1847 }
2258 } 1848 }
2259 1849
1850 ExtensionAPIPermissionSet api_permissions;
1851 URLPatternSet host_permissions;
1852
2260 // Initialize the permissions (optional). 1853 // Initialize the permissions (optional).
2261 if (source.HasKey(keys::kPermissions)) { 1854 if (source.HasKey(keys::kPermissions)) {
2262 ListValue* permissions = NULL; 1855 ListValue* permissions = NULL;
2263 if (!source.GetList(keys::kPermissions, &permissions)) { 1856 if (!source.GetList(keys::kPermissions, &permissions)) {
2264 *error = ExtensionErrorUtils::FormatErrorMessage( 1857 *error = ExtensionErrorUtils::FormatErrorMessage(
2265 errors::kInvalidPermissions, ""); 1858 errors::kInvalidPermissions, "");
2266 return false; 1859 return false;
2267 } 1860 }
2268 1861
2269 for (size_t i = 0; i < permissions->GetSize(); ++i) { 1862 for (size_t i = 0; i < permissions->GetSize(); ++i) {
2270 std::string permission_str; 1863 std::string permission_str;
2271 if (!permissions->GetString(i, &permission_str)) { 1864 if (!permissions->GetString(i, &permission_str)) {
2272 *error = ExtensionErrorUtils::FormatErrorMessage( 1865 *error = ExtensionErrorUtils::FormatErrorMessage(
2273 errors::kInvalidPermission, base::IntToString(i)); 1866 errors::kInvalidPermission, base::IntToString(i));
2274 return false; 1867 return false;
2275 } 1868 }
2276 1869
1870 ExtensionAPIPermission* permission =
1871 ExtensionPermissionsInfo::GetInstance()->GetByName(permission_str);
1872
2277 // Only COMPONENT extensions can use private APIs. 1873 // Only COMPONENT extensions can use private APIs.
2278 // TODO(asargent) - We want a more general purpose mechanism for this, 1874 // TODO(asargent) - We want a more general purpose mechanism for this,
2279 // and better error messages. (http://crbug.com/54013) 1875 // and better error messages. (http://crbug.com/54013)
2280 if (!IsComponentOnlyPermission(permission_str) 1876 if (!IsComponentOnlyPermission(permission)
2281 #ifndef NDEBUG 1877 #ifndef NDEBUG
2282 && !CommandLine::ForCurrentProcess()->HasSwitch( 1878 && !CommandLine::ForCurrentProcess()->HasSwitch(
2283 switches::kExposePrivateExtensionApi) 1879 switches::kExposePrivateExtensionApi)
2284 #endif 1880 #endif
2285 ) { 1881 ) {
2286 continue; 1882 continue;
2287 } 1883 }
2288 1884
2289 // Remap the old unlimited storage permission name.
2290 if (permission_str == kOldUnlimitedStoragePermission)
2291 permission_str = kUnlimitedStoragePermission;
2292
2293 if (web_extent().is_empty() || location() == Extension::COMPONENT) { 1885 if (web_extent().is_empty() || location() == Extension::COMPONENT) {
2294 // Check if it's a module permission. If so, enable that permission. 1886 // Check if it's a module permission. If so, enable that permission.
2295 if (IsAPIPermission(permission_str)) { 1887 if (permission != NULL) {
2296 // Only allow the experimental API permission if the command line 1888 // Only allow the experimental API permission if the command line
2297 // flag is present, or if the extension is a component of Chrome. 1889 // flag is present, or if the extension is a component of Chrome.
2298 if (IsDisallowedExperimentalPermission(permission_str) && 1890 if (IsDisallowedExperimentalPermission(permission->id()) &&
2299 location() != Extension::COMPONENT) { 1891 location() != Extension::COMPONENT) {
2300 *error = errors::kExperimentalFlagRequired; 1892 *error = errors::kExperimentalFlagRequired;
2301 return false; 1893 return false;
2302 } 1894 }
2303 api_permissions_.insert(permission_str); 1895 api_permissions.insert(permission->id());
2304 continue; 1896 continue;
2305 } 1897 }
2306 } else { 1898 } else {
2307 // Hosted apps only get access to a subset of the valid permissions. 1899 // Hosted apps only get access to a subset of the valid permissions.
2308 if (IsHostedAppPermission(permission_str)) { 1900 if (permission != NULL && permission->is_hosted_app()) {
2309 if (IsDisallowedExperimentalPermission(permission_str)) { 1901 if (IsDisallowedExperimentalPermission(permission->id())) {
2310 *error = errors::kExperimentalFlagRequired; 1902 *error = errors::kExperimentalFlagRequired;
2311 return false; 1903 return false;
2312 } 1904 }
2313 api_permissions_.insert(permission_str); 1905 api_permissions.insert(permission->id());
2314 continue; 1906 continue;
2315 } 1907 }
2316 } 1908 }
2317 1909
2318 // Check if it's a host pattern permission. 1910 // Check if it's a host pattern permission.
2319 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ? 1911 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
2320 URLPattern::SCHEME_ALL : kValidHostPermissionSchemes); 1912 URLPattern::SCHEME_ALL : kValidHostPermissionSchemes);
2321 1913
2322 URLPattern::ParseResult parse_result = pattern.Parse(permission_str, 1914 URLPattern::ParseResult parse_result = pattern.Parse(permission_str,
2323 parse_strictness); 1915 parse_strictness);
2324 if (parse_result == URLPattern::PARSE_SUCCESS) { 1916 if (parse_result == URLPattern::PARSE_SUCCESS) {
2325 if (!CanSpecifyHostPermission(pattern)) { 1917 if (!CanSpecifyHostPermission(pattern)) {
2326 *error = ExtensionErrorUtils::FormatErrorMessage( 1918 *error = ExtensionErrorUtils::FormatErrorMessage(
2327 errors::kInvalidPermissionScheme, base::IntToString(i)); 1919 errors::kInvalidPermissionScheme, base::IntToString(i));
2328 return false; 1920 return false;
2329 } 1921 }
2330 1922
2331 // The path component is not used for host permissions, so we force it 1923 // The path component is not used for host permissions, so we force it
2332 // to match all paths. 1924 // to match all paths.
2333 pattern.SetPath("/*"); 1925 pattern.SetPath("/*");
2334 1926
2335 if (pattern.MatchesScheme(chrome::kFileScheme) && 1927 if (pattern.MatchesScheme(chrome::kFileScheme) &&
2336 !CanExecuteScriptEverywhere()) { 1928 !CanExecuteScriptEverywhere()) {
2337 wants_file_access_ = true; 1929 wants_file_access_ = true;
2338 if (!(flags & ALLOW_FILE_ACCESS)) 1930 if (!(flags & ALLOW_FILE_ACCESS))
2339 pattern.set_valid_schemes( 1931 pattern.set_valid_schemes(
2340 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); 1932 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
2341 } 1933 }
2342 1934
2343 host_permissions_.push_back(pattern); 1935 host_permissions.AddPattern(pattern);
2344 } 1936 }
2345 1937
2346 // If it's not a host permission, then it's probably an unknown API 1938 // If it's not a host permission, then it's probably an unknown API
2347 // permission. Do not throw an error so extensions can retain 1939 // permission. Do not throw an error so extensions can retain
2348 // backwards compatability (http://crbug.com/42742). 1940 // backwards compatability (http://crbug.com/42742).
2349 // TODO(jstritar): We can improve error messages by adding better 1941 // TODO(jstritar): We can improve error messages by adding better
2350 // validation of API permissions here. 1942 // validation of API permissions here.
2351 // TODO(skerner): Consider showing the reason |permission_str| is not 1943 // TODO(skerner): Consider showing the reason |permission_str| is not
2352 // a valid URL pattern if it is almost valid. For example, if it has 1944 // a valid URL pattern if it is almost valid. For example, if it has
2353 // a valid scheme, and failed to parse because it has a port, show an 1945 // a valid scheme, and failed to parse because it has a port, show an
2354 // error. 1946 // error.
2355 } 1947 }
2356 } 1948 }
2357 1949
2358 // Initialize background url (optional). 1950 // Initialize background url (optional).
2359 if (source.HasKey(keys::kBackground)) { 1951 if (source.HasKey(keys::kBackground)) {
2360 std::string background_str; 1952 std::string background_str;
2361 if (!source.GetString(keys::kBackground, &background_str)) { 1953 if (!source.GetString(keys::kBackground, &background_str)) {
2362 *error = errors::kInvalidBackground; 1954 *error = errors::kInvalidBackground;
2363 return false; 1955 return false;
2364 } 1956 }
2365 1957
2366 if (is_hosted_app()) { 1958 if (is_hosted_app()) {
2367 // Make sure "background" permission is set. 1959 // Make sure "background" permission is set.
2368 if (api_permissions_.find(kBackgroundPermission) == 1960 if (!api_permissions.count(ExtensionAPIPermission::kBackground)) {
2369 api_permissions_.end()) {
2370 *error = errors::kBackgroundPermissionNeeded; 1961 *error = errors::kBackgroundPermissionNeeded;
2371 return false; 1962 return false;
2372 } 1963 }
2373 // Hosted apps require an absolute URL. 1964 // Hosted apps require an absolute URL.
2374 GURL bg_page(background_str); 1965 GURL bg_page(background_str);
2375 if (!bg_page.is_valid()) { 1966 if (!bg_page.is_valid()) {
2376 *error = errors::kInvalidBackgroundInHostedApp; 1967 *error = errors::kInvalidBackgroundInHostedApp;
2377 return false; 1968 return false;
2378 } 1969 }
2379 1970
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
2598 content_security_policy_ = content_security_policy; 2189 content_security_policy_ = content_security_policy;
2599 } 2190 }
2600 2191
2601 // Initialize devtools page url (optional). 2192 // Initialize devtools page url (optional).
2602 if (source.HasKey(keys::kDevToolsPage)) { 2193 if (source.HasKey(keys::kDevToolsPage)) {
2603 std::string devtools_str; 2194 std::string devtools_str;
2604 if (!source.GetString(keys::kDevToolsPage, &devtools_str)) { 2195 if (!source.GetString(keys::kDevToolsPage, &devtools_str)) {
2605 *error = errors::kInvalidDevToolsPage; 2196 *error = errors::kInvalidDevToolsPage;
2606 return false; 2197 return false;
2607 } 2198 }
2608 if (!HasApiPermission(Extension::kExperimentalPermission)) { 2199 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
2609 *error = errors::kDevToolsExperimental; 2200 *error = errors::kDevToolsExperimental;
2610 return false; 2201 return false;
2611 } 2202 }
2612 devtools_url_ = GetResourceURL(devtools_str); 2203 devtools_url_ = GetResourceURL(devtools_str);
2613 } 2204 }
2614 2205
2615 // Initialize sidebar action (optional). 2206 // Initialize sidebar action (optional).
2616 if (source.HasKey(keys::kSidebar)) { 2207 if (source.HasKey(keys::kSidebar)) {
2617 DictionaryValue* sidebar_value = NULL; 2208 DictionaryValue* sidebar_value = NULL;
2618 if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) { 2209 if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) {
2619 *error = errors::kInvalidSidebar; 2210 *error = errors::kInvalidSidebar;
2620 return false; 2211 return false;
2621 } 2212 }
2622 if (!HasApiPermission(Extension::kExperimentalPermission)) { 2213 if (!api_permissions.count(ExtensionAPIPermission::kExperimental)) {
2623 *error = errors::kSidebarExperimental; 2214 *error = errors::kSidebarExperimental;
2624 return false; 2215 return false;
2625 } 2216 }
2626 sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error)); 2217 sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error));
2627 if (!sidebar_defaults_.get()) 2218 if (!sidebar_defaults_.get())
2628 return false; // Failed to parse sidebar definition. 2219 return false; // Failed to parse sidebar definition.
2629 } 2220 }
2630 2221
2631 // Initialize text-to-speech voices (optional). 2222 // Initialize text-to-speech voices (optional).
2632 if (source.HasKey(keys::kTts)) { 2223 if (source.HasKey(keys::kTts)) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 *error = errors::kInvalidIncognitoBehavior; 2289 *error = errors::kInvalidIncognitoBehavior;
2699 return false; 2290 return false;
2700 } 2291 }
2701 } 2292 }
2702 2293
2703 if (HasMultipleUISurfaces()) { 2294 if (HasMultipleUISurfaces()) {
2704 *error = errors::kOneUISurfaceOnly; 2295 *error = errors::kOneUISurfaceOnly;
2705 return false; 2296 return false;
2706 } 2297 }
2707 2298
2708 InitEffectiveHostPermissions(); 2299 permission_set_.reset(
2300 new ExtensionPermissionSet(this, api_permissions, host_permissions));
2709 2301
2710 // Although |source| is passed in as a const, it's still possible to modify 2302 // Although |source| is passed in as a const, it's still possible to modify
2711 // it. This is dangerous since the utility process re-uses |source| after 2303 // it. This is dangerous since the utility process re-uses |source| after
2712 // it calls InitFromValue, passing it up to the browser process which calls 2304 // it calls InitFromValue, passing it up to the browser process which calls
2713 // InitFromValue again. As a result, we need to make sure that nobody 2305 // InitFromValue again. As a result, we need to make sure that nobody
2714 // accidentally modifies it. 2306 // accidentally modifies it.
2715 DCHECK(source.Equals(manifest_value_.get())); 2307 DCHECK(source.Equals(manifest_value_.get()));
2716 2308
2717 return true; 2309 return true;
2718 } 2310 }
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2889 // Only allow access to chrome://favicon to regular extensions. Component 2481 // Only allow access to chrome://favicon to regular extensions. Component
2890 // extensions can have access to all of chrome://*. 2482 // extensions can have access to all of chrome://*.
2891 return (pattern.host() == chrome::kChromeUIFaviconHost || 2483 return (pattern.host() == chrome::kChromeUIFaviconHost ||
2892 CanExecuteScriptEverywhere()); 2484 CanExecuteScriptEverywhere());
2893 } 2485 }
2894 2486
2895 // Otherwise, the valid schemes were handled by URLPattern. 2487 // Otherwise, the valid schemes were handled by URLPattern.
2896 return true; 2488 return true;
2897 } 2489 }
2898 2490
2899 // static 2491 bool Extension::HasAPIPermission(
2900 bool Extension::HasApiPermission( 2492 ExtensionAPIPermission::ID permission) const {
2901 const std::set<std::string>& api_permissions, 2493 return permission_set()->HasAPIPermission(permission);
2902 const std::string& function_name) { 2494 }
2903 std::string permission_name = function_name;
2904 2495
2905 for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) { 2496 bool Extension::HasAPIPermission(
2906 if (permission_name == kNonPermissionFunctionNames[i]) 2497 const std::string& function_name) const {
2907 return true; 2498 return permission_set()->HasAccessToFunction(function_name);
2908 } 2499 }
2909 2500
2910 // See if this is a function or event name first and strip out the package. 2501 const URLPatternSet& Extension::GetEffectiveHostPermissions() const {
2911 // Functions will be of the form package.function 2502 return permission_set()->effective_hosts();
2912 // Events will be of the form package/id or package.optional.stuff
2913 size_t separator = function_name.find_first_of("./");
2914 if (separator != std::string::npos)
2915 permission_name = function_name.substr(0, separator);
2916
2917 // windows and tabs are the same permission.
2918 if (permission_name == kWindowPermission)
2919 permission_name = Extension::kTabPermission;
2920
2921 if (api_permissions.count(permission_name))
2922 return true;
2923
2924 for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
2925 if (permission_name == kNonPermissionModuleNames[i]) {
2926 return true;
2927 }
2928 }
2929
2930 return false;
2931 } 2503 }
2932 2504
2933 bool Extension::HasHostPermission(const GURL& url) const { 2505 bool Extension::HasHostPermission(const GURL& url) const {
2934 for (URLPatternList::const_iterator host = host_permissions().begin(); 2506 if (url.SchemeIs(chrome::kChromeUIScheme) &&
2935 host != host_permissions().end(); ++host) { 2507 url.host() != chrome::kChromeUIFaviconHost &&
2936 // Non-component extensions can only access chrome://favicon and no other 2508 location() != Extension::COMPONENT)
2937 // chrome:// scheme urls. 2509 return false;
2938 if (url.SchemeIs(chrome::kChromeUIScheme) && 2510 return permission_set()->HasExplicitAccessToOrigin(url);
2939 url.host() != chrome::kChromeUIFaviconHost &&
2940 location() != Extension::COMPONENT)
2941 return false;
2942
2943 if (host->MatchesURL(url))
2944 return true;
2945 }
2946 return false;
2947 } 2511 }
2948 2512
2949 void Extension::InitEffectiveHostPermissions() { 2513 bool Extension::IsComponentOnlyPermission(
2950 // Some APIs effectively grant access to every site. New ones should be 2514 const ExtensionAPIPermission* api) const {
2951 // added here. (I'm looking at you, network API)
2952 if (HasApiPermission(api_permissions_, kProxyPermission) ||
2953 !devtools_url_.is_empty()) {
2954 URLPattern all_urls(URLPattern::SCHEME_ALL);
2955 all_urls.set_match_all_urls(true);
2956 effective_host_permissions_.AddPattern(all_urls);
2957 return;
2958 }
2959
2960 for (URLPatternList::const_iterator host = host_permissions().begin();
2961 host != host_permissions().end(); ++host)
2962 effective_host_permissions_.AddPattern(*host);
2963
2964 for (UserScriptList::const_iterator content_script =
2965 content_scripts().begin();
2966 content_script != content_scripts().end(); ++content_script) {
2967 URLPatternList::const_iterator pattern =
2968 content_script->url_patterns().begin();
2969 for (; pattern != content_script->url_patterns().end(); ++pattern)
2970 effective_host_permissions_.AddPattern(*pattern);
2971 }
2972 }
2973
2974 bool Extension::IsComponentOnlyPermission(const std::string& permission) const {
2975 if (location() == Extension::COMPONENT) 2515 if (location() == Extension::COMPONENT)
2976 return true; 2516 return true;
2977 2517
2978 // Non-component extensions are not allowed to access private apis. 2518 if (api == NULL)
2979 for (size_t i = 0; i < Extension::kNumComponentPrivatePermissions; ++i) { 2519 return true;
2980 if (permission == Extension::kComponentPrivatePermissionNames[i]) 2520
2981 return false; 2521 return !api->is_component_only();
2982 }
2983 return true;
2984 } 2522 }
2985 2523
2986 bool Extension::HasMultipleUISurfaces() const { 2524 bool Extension::HasMultipleUISurfaces() const {
2987 int num_surfaces = 0; 2525 int num_surfaces = 0;
2988 2526
2989 if (page_action()) 2527 if (page_action())
2990 ++num_surfaces; 2528 ++num_surfaces;
2991 2529
2992 if (browser_action()) 2530 if (browser_action())
2993 ++num_surfaces; 2531 ++num_surfaces;
(...skipping 24 matching lines...) Expand all
3018 if (page_url.SchemeIs(chrome::kChromeUIScheme) && 2556 if (page_url.SchemeIs(chrome::kChromeUIScheme) &&
3019 !CanExecuteScriptEverywhere()) 2557 !CanExecuteScriptEverywhere())
3020 return false; 2558 return false;
3021 2559
3022 // If a script is specified, use its matches. 2560 // If a script is specified, use its matches.
3023 if (script) 2561 if (script)
3024 return script->MatchesURL(page_url); 2562 return script->MatchesURL(page_url);
3025 2563
3026 // Otherwise, see if this extension has permission to execute script 2564 // Otherwise, see if this extension has permission to execute script
3027 // programmatically on pages. 2565 // programmatically on pages.
3028 for (size_t i = 0; i < host_permissions_.size(); ++i) { 2566 if (permission_set()->HasExplicitAccessToOrigin(page_url))
3029 if (host_permissions_[i].MatchesURL(page_url)) 2567 return true;
3030 return true;
3031 }
3032 2568
3033 if (error) { 2569 if (error) {
3034 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, 2570 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
3035 page_url.spec()); 2571 page_url.spec());
3036 } 2572 }
3037 2573
3038 return false; 2574 return false;
3039 } 2575 }
3040 2576
3041 // static
3042 bool Extension::HasEffectiveAccessToAllHosts(
3043 const URLPatternSet& effective_host_permissions,
3044 const std::set<std::string>& api_permissions) {
3045 const URLPatternList patterns = effective_host_permissions.patterns();
3046 for (URLPatternList::const_iterator host = patterns.begin();
3047 host != patterns.end(); ++host) {
3048 if (host->match_all_urls() ||
3049 (host->match_subdomains() && host->host().empty()))
3050 return true;
3051 }
3052
3053 return false;
3054 }
3055
3056 bool Extension::HasEffectiveAccessToAllHosts() const { 2577 bool Extension::HasEffectiveAccessToAllHosts() const {
3057 return HasEffectiveAccessToAllHosts(GetEffectiveHostPermissions(), 2578 return permission_set_->HasEffectiveAccessToAllHosts();
3058 api_permissions());
3059 } 2579 }
3060 2580
3061 bool Extension::HasFullPermissions() const { 2581 bool Extension::HasFullPermissions() const {
3062 return !plugins().empty(); 2582 return permission_set_->HasEffectiveFullAccess();
3063 } 2583 }
3064 2584
3065 bool Extension::ShowConfigureContextMenus() const { 2585 bool Extension::ShowConfigureContextMenus() const {
3066 // Don't show context menu for component extensions. We might want to show 2586 // Don't show context menu for component extensions. We might want to show
3067 // options for component extension button but now there is no component 2587 // options for component extension button but now there is no component
3068 // extension with options. All other menu items like uninstall have 2588 // extension with options. All other menu items like uninstall have
3069 // no sense for component extensions. 2589 // no sense for component extensions.
3070 return location() != Extension::COMPONENT; 2590 return location() != Extension::COMPONENT;
3071 } 2591 }
3072 2592
3073 bool Extension::IsDisallowedExperimentalPermission( 2593 bool Extension::IsDisallowedExperimentalPermission(
3074 const std::string& permission_str) const { 2594 ExtensionAPIPermission::ID permission) const {
3075 return permission_str == Extension::kExperimentalPermission && 2595 return permission == ExtensionAPIPermission::kExperimental &&
3076 !CommandLine::ForCurrentProcess()->HasSwitch( 2596 !CommandLine::ForCurrentProcess()->HasSwitch(
3077 switches::kEnableExperimentalExtensionApis); 2597 switches::kEnableExperimentalExtensionApis);
3078 } 2598 }
3079 2599
3080 bool Extension::IsAPIPermission(const std::string& str) const {
3081 for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
3082 if (str == Extension::kPermissions[i].name) {
3083 return true;
3084 }
3085 }
3086 return false;
3087 }
3088
3089 bool Extension::CanExecuteScriptEverywhere() const { 2600 bool Extension::CanExecuteScriptEverywhere() const {
3090 if (location() == Extension::COMPONENT 2601 if (location() == Extension::COMPONENT
3091 #ifndef NDEBUG 2602 #ifndef NDEBUG
3092 || CommandLine::ForCurrentProcess()->HasSwitch( 2603 || CommandLine::ForCurrentProcess()->HasSwitch(
3093 switches::kExposePrivateExtensionApi) 2604 switches::kExposePrivateExtensionApi)
3094 #endif 2605 #endif
3095 ) 2606 )
3096 return true; 2607 return true;
3097 2608
3098 ScriptingWhitelist* whitelist = 2609 ScriptingWhitelist* whitelist =
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3154 extension_location(location) { 2665 extension_location(location) {
3155 if (manifest) 2666 if (manifest)
3156 extension_manifest.reset(manifest->DeepCopy()); 2667 extension_manifest.reset(manifest->DeepCopy());
3157 } 2668 }
3158 2669
3159 ExtensionInfo::~ExtensionInfo() {} 2670 ExtensionInfo::~ExtensionInfo() {}
3160 2671
3161 UninstalledExtensionInfo::UninstalledExtensionInfo( 2672 UninstalledExtensionInfo::UninstalledExtensionInfo(
3162 const Extension& extension) 2673 const Extension& extension)
3163 : extension_id(extension.id()), 2674 : extension_id(extension.id()),
3164 extension_api_permissions(extension.api_permissions()), 2675 extension_api_permissions(
2676 extension.permission_set()->GetAPIsAsStrings()),
3165 extension_type(extension.GetType()), 2677 extension_type(extension.GetType()),
3166 update_url(extension.update_url()) {} 2678 update_url(extension.update_url()) {}
3167 2679
3168 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} 2680 UninstalledExtensionInfo::~UninstalledExtensionInfo() {}
3169 2681
3170 2682
3171 UnloadedExtensionInfo::UnloadedExtensionInfo( 2683 UnloadedExtensionInfo::UnloadedExtensionInfo(
3172 const Extension* extension, 2684 const Extension* extension,
3173 Reason reason) 2685 Reason reason)
3174 : reason(reason), 2686 : reason(reason),
3175 already_disabled(false), 2687 already_disabled(false),
3176 extension(extension) {} 2688 extension(extension) {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698