diff options
Diffstat (limited to 'chrome')
19 files changed, 520 insertions, 368 deletions
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc index 41ff365..a840e14 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc @@ -583,8 +583,8 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetDevicesError) { } IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Permissions) { - PermissionsRequestFunction::SetAutoConfirmForTests(true); - PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); + extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true); + extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); event_router()->AddProfile( "00001101-0000-1000-8000-00805f9b34fb", profile1_.get()); diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc index d7aec6f3..ab523a5 100644 --- a/chrome/browser/extensions/api/permissions/permissions_api.cc +++ b/chrome/browser/extensions/api/permissions/permissions_api.cc @@ -13,26 +13,21 @@ #include "chrome/common/chrome_notification_types.h" #include "chrome/common/extensions/api/permissions.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "chrome/common/extensions/permissions/permissions_info.h" #include "extensions/common/error_utils.h" #include "extensions/common/url_pattern_set.h" #include "googleurl/src/gurl.h" -using extensions::api::permissions::Permissions; -using extensions::APIPermission; -using extensions::APIPermissionSet; -using extensions::ErrorUtils; -using extensions::ExtensionPrefs; -using extensions::ExtensionSystem; -using extensions::PermissionSet; -using extensions::PermissionsInfo; -using extensions::PermissionsUpdater; - -namespace Contains = extensions::api::permissions::Contains; -namespace GetAll = extensions::api::permissions::GetAll; -namespace Remove = extensions::api::permissions::Remove; -namespace Request = extensions::api::permissions::Request; -namespace helpers = extensions::permissions_api_helpers; +namespace extensions { + +using api::permissions::Permissions; + +namespace Contains = api::permissions::Contains; +namespace GetAll = api::permissions::GetAll; +namespace Remove = api::permissions::Remove; +namespace Request = api::permissions::Request; +namespace helpers = permissions_api_helpers; namespace { @@ -91,7 +86,7 @@ bool PermissionsRemoveFunction::RunImpl() { if (!permissions.get()) return false; - const extensions::Extension* extension = GetExtension(); + const Extension* extension = GetExtension(); // Make sure they're only trying to remove permissions supported by this API. APIPermissionSet apis = permissions->apis(); @@ -105,7 +100,8 @@ bool PermissionsRemoveFunction::RunImpl() { } // Make sure we don't remove any required pemissions. - const PermissionSet* required = extension->required_permission_set(); + const PermissionSet* required = + PermissionsData::GetRequiredPermissions(extension); scoped_refptr<PermissionSet> intersection( PermissionSet::CreateIntersection(permissions.get(), required)); if (!intersection->IsEmpty()) { @@ -182,13 +178,12 @@ bool PermissionsRequestFunction::RunImpl() { // Filter out permissions that do not need to be listed in the optional // section of the manifest. - scoped_refptr<extensions::PermissionSet> - manifest_required_requested_permissions = - PermissionSet::ExcludeNotInManifestPermissions( - requested_permissions_.get()); + scoped_refptr<PermissionSet> manifest_required_requested_permissions = + PermissionSet::ExcludeNotInManifestPermissions( + requested_permissions_.get()); // The requested permissions must be defined as optional in the manifest. - if (!GetExtension()->optional_permission_set()->Contains( + if (!PermissionsData::GetOptionalPermissions(GetExtension())->Contains( *manifest_required_requested_permissions)) { error_ = kNotInOptionalPermissionsError; return false; @@ -231,3 +226,5 @@ bool PermissionsRequestFunction::RunImpl() { return true; } + +} // namespace extensions diff --git a/chrome/browser/extensions/api/permissions/permissions_api.h b/chrome/browser/extensions/api/permissions/permissions_api.h index e15f64c..a0d6ccb 100644 --- a/chrome/browser/extensions/api/permissions/permissions_api.h +++ b/chrome/browser/extensions/api/permissions/permissions_api.h @@ -14,6 +14,8 @@ class ExtensionService; +namespace extensions { + // chrome.permissions.contains class PermissionsContainsFunction : public SyncExtensionFunction { public: @@ -77,4 +79,6 @@ class PermissionsRequestFunction : public AsyncExtensionFunction, scoped_refptr<extensions::PermissionSet> requested_permissions_; }; +} // namespace extensions + #endif // CHROME_BROWSER_EXTENSIONS_API_PERMISSIONS_PERMISSIONS_API_H_ diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc index 73ec0fa..82bd17f 100644 --- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc +++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc @@ -12,10 +12,7 @@ #include "chrome/common/extensions/permissions/permission_set.h" #include "net/dns/mock_host_resolver.h" -using extensions::APIPermission; -using extensions::APIPermissionSet; -using extensions::PermissionSet; -using extensions::URLPatternSet; +namespace extensions { namespace { @@ -80,7 +77,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OptionalPermissionsGranted) { scoped_refptr<PermissionSet> granted_permissions = new PermissionSet(apis, explicit_hosts, URLPatternSet()); - extensions::ExtensionPrefs* prefs = + ExtensionPrefs* prefs = browser()->profile()->GetExtensionService()->extension_prefs(); prefs->AddGrantedPermissions("kjmkgkdkpedkejedfhmfcenooemhbpbo", granted_permissions); @@ -137,7 +134,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OptionalPermissionsFileAccess) { PermissionsRequestFunction::SetAutoConfirmForTests(false); PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); - extensions::ExtensionPrefs* prefs = + ExtensionPrefs* prefs = browser()->profile()->GetExtensionService()->extension_prefs(); EXPECT_TRUE( @@ -163,3 +160,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, HostSubsets) { PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); EXPECT_TRUE(RunExtensionTest("permissions/host_subsets")) << message_; } + +} // namespace extensions diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc index 7cf66d3..c5db010 100644 --- a/chrome/browser/extensions/bundle_installer.cc +++ b/chrome/browser/extensions/bundle_installer.cc @@ -22,6 +22,7 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/web_contents.h" #include "grit/generated_resources.h" @@ -260,7 +261,8 @@ void BundleInstaller::ShowPrompt() { scoped_refptr<PermissionSet> permissions; for (size_t i = 0; i < dummy_extensions_.size(); ++i) { permissions = PermissionSet::CreateUnion( - permissions, dummy_extensions_[i]->required_permission_set()); + permissions, + PermissionsData::GetRequiredPermissions(dummy_extensions_[i])); } if (g_auto_approve_for_test == PROCEED) { diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc index f3d5035..52d28c3 100644 --- a/chrome/browser/extensions/content_script_apitest.cc +++ b/chrome/browser/extensions/content_script_apitest.cc @@ -163,8 +163,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionAPIs) { } IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptPermissionsApi) { - PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); - PermissionsRequestFunction::SetAutoConfirmForTests(true); + extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); + extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true); host_resolver()->AddRule("*.com", "127.0.0.1"); ASSERT_TRUE(StartTestServer()); ASSERT_TRUE(RunExtensionTest("content_scripts/permissions")) << message_; diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index c7171e6..2cfc144 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -89,6 +89,7 @@ #include "chrome/common/extensions/manifest.h" #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" #include "chrome/common/extensions/manifest_url_handler.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "chrome/common/pref_names.h" #include "chrome/common/startup_metric_utils.h" #include "chrome/common/url_constants.h" @@ -2151,8 +2152,8 @@ void ExtensionService::UpdateActivePermissions(const Extension* extension) { // b) active permissions must contains all default permissions scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion( - extension->required_permission_set(), - extension->optional_permission_set()); + extensions::PermissionsData::GetRequiredPermissions(extension), + extensions::PermissionsData::GetOptionalPermissions(extension)); // Make sure the active permissions contain no more than optional + default. scoped_refptr<PermissionSet> adjusted_active = @@ -2161,7 +2162,8 @@ void ExtensionService::UpdateActivePermissions(const Extension* extension) { // Make sure the active permissions contain the default permissions. adjusted_active = PermissionSet::CreateUnion( - extension->required_permission_set(), adjusted_active.get()); + extensions::PermissionsData::GetRequiredPermissions(extension), + adjusted_active.get()); extensions::PermissionsUpdater perms_updater(profile()); perms_updater.UpdateActivePermissions(extension, adjusted_active); diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 9fc8534..72b9527 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -295,6 +295,8 @@ 'common/extensions/permissions/permission_message.h', 'common/extensions/permissions/permission_set.cc', 'common/extensions/permissions/permission_set.h', + 'common/extensions/permissions/permissions_data.cc', + 'common/extensions/permissions/permissions_data.h', 'common/extensions/permissions/permissions_info.cc', 'common/extensions/permissions/permissions_info.h', 'common/extensions/permissions/set_disjunction_permission.h', diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc index b158aa9..029c8fd 100644 --- a/chrome/common/extensions/api/extension_api.cc +++ b/chrome/common/extensions/api/extension_api.cc @@ -21,6 +21,7 @@ #include "chrome/common/extensions/features/base_feature_provider.h" #include "chrome/common/extensions/features/simple_feature.h" #include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "googleurl/src/gurl.h" #include "grit/common_resources.h" #include "grit/extensions_api_resources.h" @@ -576,8 +577,10 @@ std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name, bool ExtensionAPI::IsAPIAllowed(const std::string& name, const Extension* extension) { - return extension->required_permission_set()->HasAnyAccessToAPI(name) || - extension->optional_permission_set()->HasAnyAccessToAPI(name); + return PermissionsData::GetRequiredPermissions(extension)-> + HasAnyAccessToAPI(name) || + PermissionsData::GetOptionalPermissions(extension)-> + HasAnyAccessToAPI(name); } bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) { diff --git a/chrome/common/extensions/api/plugins/plugins_handler.cc b/chrome/common/extensions/api/plugins/plugins_handler.cc index 2f255f1..618aa7d 100644 --- a/chrome/common/extensions/api/plugins/plugins_handler.cc +++ b/chrome/common/extensions/api/plugins/plugins_handler.cc @@ -12,6 +12,7 @@ #include "chrome/common/extensions/manifest.h" #include "chrome/common/extensions/permissions/api_permission.h" #include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "extensions/common/error_utils.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -117,7 +118,8 @@ bool PluginsHandler::Parse(Extension* extension, string16* error) { if (!plugins_data->plugins.empty()) { extension->SetManifestData(keys::kPlugins, plugins_data.release()); - extension->initial_api_permissions()->insert(APIPermission::kPlugin); + PermissionsData::GetInitialAPIPermissions(extension)->insert( + APIPermission::kPlugin); } return true; diff --git a/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc b/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc index 638b539..17246c3 100644 --- a/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc +++ b/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc @@ -11,6 +11,7 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" namespace extensions { @@ -36,7 +37,8 @@ bool SystemIndicatorHandler::Parse(Extension* extension, string16* error) { // Because the manifest was successfully parsed, auto-grant the permission. // TODO(dewittj) Add this for all extension action APIs. - extension->initial_api_permissions()->insert(APIPermission::kSystemIndicator); + PermissionsData::GetInitialAPIPermissions(extension)->insert( + APIPermission::kSystemIndicator); ActionInfo::SetSystemIndicatorInfo(extension, action_info.release()); return true; diff --git a/chrome/common/extensions/background_info.cc b/chrome/common/extensions/background_info.cc index f995c54..77dd5af 100644 --- a/chrome/common/extensions/background_info.cc +++ b/chrome/common/extensions/background_info.cc @@ -15,6 +15,7 @@ #include "chrome/common/extensions/extension_file_util.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "extensions/common/error_utils.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -149,7 +150,7 @@ bool BackgroundInfo::LoadBackgroundPage(const Extension* extension, if (extension->is_hosted_app()) { background_url_ = GURL(background_str); - if (!extension->initial_api_permissions()->count( + if (!PermissionsData::GetInitialAPIPermissions(extension)->count( APIPermission::kBackground)) { *error = ASCIIToUTF16(errors::kBackgroundPermissionNeeded); return false; diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index aa7b5f4..8f7bf79 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -30,19 +30,15 @@ #include "chrome/common/extensions/api/plugins/plugins_handler.h" #include "chrome/common/extensions/background_info.h" #include "chrome/common/extensions/extension_manifest_constants.h" -#include "chrome/common/extensions/feature_switch.h" -#include "chrome/common/extensions/features/base_feature_provider.h" -#include "chrome/common/extensions/features/feature.h" #include "chrome/common/extensions/incognito_handler.h" #include "chrome/common/extensions/manifest.h" #include "chrome/common/extensions/manifest_handler.h" -#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" -#include "chrome/common/extensions/manifest_handlers/icons_handler.h" #include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h" #include "chrome/common/extensions/manifest_handlers/offline_enabled_info.h" #include "chrome/common/extensions/manifest_url_handler.h" #include "chrome/common/extensions/permissions/api_permission_set.h" #include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "chrome/common/extensions/permissions/permissions_info.h" #include "chrome/common/extensions/user_script.h" #include "chrome/common/url_constants.h" @@ -81,8 +77,6 @@ const char kPrivate[] = "PRIVATE"; const int kRSAKeySize = 1024; -const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh"; - // A singleton object containing global data needed by the extension objects. class ExtensionConfig { public: @@ -142,21 +136,6 @@ bool ReadLaunchDimension(const extensions::Manifest* manifest, return true; } -bool ContainsManifestForbiddenPermission(const APIPermissionSet& apis, - string16* error) { - CHECK(error); - for (APIPermissionSet::const_iterator i = apis.begin(); - i != apis.end(); ++i) { - if ((*i)->ManifestEntryForbidden()) { - *error = ErrorUtils::FormatErrorMessageUTF16( - errors::kPermissionNotAllowedInManifest, - (*i)->info()->name()); - return true; - } - } - return false; -} - } // namespace #if defined(OS_WIN) @@ -426,147 +405,6 @@ const Extension::ScriptingWhitelist* Extension::GetScriptingWhitelist() { return ExtensionConfig::GetInstance()->whitelist(); } -bool Extension::ParsePermissions(const char* key, - string16* error, - APIPermissionSet* api_permissions, - URLPatternSet* host_permissions) { - if (manifest_->HasKey(key)) { - const ListValue* permissions = NULL; - if (!manifest_->GetList(key, &permissions)) { - *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions, - std::string()); - return false; - } - - // NOTE: We need to get the APIPermission before we check if features - // associated with them are available because the feature system does not - // know about aliases. - - std::vector<std::string> host_data; - if (!APIPermissionSet::ParseFromJSON(permissions, api_permissions, - error, &host_data)) - return false; - - // Verify feature availability of permissions. - std::vector<APIPermission::ID> to_remove; - FeatureProvider* permission_features = - BaseFeatureProvider::GetByName("permission"); - for (APIPermissionSet::const_iterator it = api_permissions->begin(); - it != api_permissions->end(); ++it) { - extensions::Feature* feature = - permission_features->GetFeature(it->name()); - - // The feature should exist since we just got an APIPermission - // for it. The two systems should be updated together whenever a - // permission is added. - DCHECK(feature); - // http://crbug.com/176381 - if (!feature) { - to_remove.push_back(it->id()); - continue; - } - - Feature::Availability availability = - feature->IsAvailableToManifest( - id(), - GetType(), - Feature::ConvertLocation(location()), - manifest_version()); - if (!availability.is_available()) { - // Don't fail, but warn the developer that the manifest contains - // unrecognized permissions. This may happen legitimately if the - // extensions requests platform- or channel-specific permissions. - install_warnings_.push_back(InstallWarning(InstallWarning::FORMAT_TEXT, - availability.message())); - to_remove.push_back(it->id()); - continue; - } - - if (it->id() == APIPermission::kExperimental) { - if (!CanSpecifyExperimentalPermission()) { - *error = ASCIIToUTF16(errors::kExperimentalFlagRequired); - return false; - } - } - } - - // Remove permissions that are not available to this extension. - for (std::vector<APIPermission::ID>::const_iterator it = to_remove.begin(); - it != to_remove.end(); ++it) { - api_permissions->erase(*it); - } - - // Parse host pattern permissions. - const int kAllowedSchemes = CanExecuteScriptEverywhere() ? - URLPattern::SCHEME_ALL : kValidHostPermissionSchemes; - - for (std::vector<std::string>::const_iterator it = host_data.begin(); - it != host_data.end(); ++it) { - const std::string& permission_str = *it; - - // Check if it's a host pattern permission. - URLPattern pattern = URLPattern(kAllowedSchemes); - URLPattern::ParseResult parse_result = pattern.Parse(permission_str); - if (parse_result == URLPattern::PARSE_SUCCESS) { - // The path component is not used for host permissions, so we force it - // to match all paths. - pattern.SetPath("/*"); - int valid_schemes = pattern.valid_schemes(); - if (pattern.MatchesScheme(chrome::kFileScheme) && - !CanExecuteScriptEverywhere()) { - wants_file_access_ = true; - if (!(creation_flags_ & ALLOW_FILE_ACCESS)) - valid_schemes &= ~URLPattern::SCHEME_FILE; - } - - if (pattern.scheme() != chrome::kChromeUIScheme && - !CanExecuteScriptEverywhere()) { - // Keep chrome:// in allowed schemes only if it's explicitly requested - // or CanExecuteScriptEverywhere is true. If the - // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission - // will fail, so don't check the flag here. - valid_schemes &= ~URLPattern::SCHEME_CHROMEUI; - } - pattern.SetValidSchemes(valid_schemes); - - if (!CanSpecifyHostPermission(pattern, *api_permissions)) { - // TODO(aboxhall): make a warning (see line 633) - *error = ErrorUtils::FormatErrorMessageUTF16( - errors::kInvalidPermissionScheme, permission_str); - return false; - } - - host_permissions->AddPattern(pattern); - - // We need to make sure all_urls matches chrome://favicon and - // (maybe) chrome://thumbnail, so add them back in to host_permissions - // separately. - if (pattern.match_all_urls()) { - host_permissions->AddPattern( - URLPattern(URLPattern::SCHEME_CHROMEUI, - chrome::kChromeUIFaviconURL)); - if (api_permissions->find(APIPermission::kExperimental) != - api_permissions->end()) { - host_permissions->AddPattern( - URLPattern(URLPattern::SCHEME_CHROMEUI, - chrome::kChromeUIThumbnailURL)); - } - } - continue; - } - - // It's probably an unknown API permission. Do not throw an error so - // extensions can retain backwards compatability (http://crbug.com/42742). - install_warnings_.push_back(InstallWarning( - InstallWarning::FORMAT_TEXT, - base::StringPrintf( - "Permission '%s' is unknown or URL pattern is malformed.", - permission_str.c_str()))); - } - } - return true; -} - bool Extension::HasAPIPermission(APIPermission::ID permission) const { base::AutoLock auto_lock(runtime_data_lock_); return runtime_data_.GetActivePermissions()->HasAPIPermission(permission); @@ -643,14 +481,12 @@ bool Extension::ShouldSkipPermissionWarnings() const { return IsTrustedId(id()); } -void Extension::SetActivePermissions( - const PermissionSet* permissions) const { +void Extension::SetActivePermissions(const PermissionSet* permissions) const { base::AutoLock auto_lock(runtime_data_lock_); runtime_data_.SetActivePermissions(permissions); } -scoped_refptr<const PermissionSet> - Extension::GetActivePermissions() const { +scoped_refptr<const PermissionSet> Extension::GetActivePermissions() const { base::AutoLock auto_lock(runtime_data_lock_); return runtime_data_.GetActivePermissions(); } @@ -1095,13 +931,6 @@ Extension::~Extension() { bool Extension::InitFromValue(int flags, string16* error) { DCHECK(error); - base::AutoLock auto_lock(runtime_data_lock_); - - // Initialize permissions with an empty, default permission set. - runtime_data_.SetActivePermissions(new PermissionSet()); - optional_permission_set_ = new PermissionSet(); - required_permission_set_ = new PermissionSet(); - creation_flags_ = flags; // Important to load manifest version first because many other features @@ -1128,47 +957,9 @@ bool Extension::InitFromValue(int flags, string16* error) { if (is_app() && !LoadAppFeatures(error)) return false; - initial_api_permissions_.reset(new APIPermissionSet); - URLPatternSet host_permissions; - if (!ParsePermissions(keys::kPermissions, - error, - initial_api_permissions_.get(), - &host_permissions)) { + permissions_data_.reset(new PermissionsData); + if (!permissions_data_->ParsePermissions(this, error)) return false; - } - - // Check for any permissions that are optional only. - for (APIPermissionSet::const_iterator i = initial_api_permissions_->begin(); - i != initial_api_permissions_->end(); ++i) { - if ((*i)->info()->must_be_optional()) { - *error = ErrorUtils::FormatErrorMessageUTF16( - errors::kPermissionMustBeOptional, (*i)->info()->name()); - return false; - } - } - - // TODO(jeremya/kalman) do this via the features system by exposing the - // app.window API to platform apps, with no dependency on any permissions. - // See http://crbug.com/120069. - if (is_platform_app()) { - initial_api_permissions_->insert(APIPermission::kAppCurrentWindowInternal); - initial_api_permissions_->insert(APIPermission::kAppRuntime); - initial_api_permissions_->insert(APIPermission::kAppWindow); - } - - APIPermissionSet optional_api_permissions; - URLPatternSet optional_host_permissions; - if (!ParsePermissions(keys::kOptionalPermissions, - error, - &optional_api_permissions, - &optional_host_permissions)) { - return false; - } - - if (ContainsManifestForbiddenPermission(*initial_api_permissions_, error) || - ContainsManifestForbiddenPermission(optional_api_permissions, error)) { - return false; - } if (!LoadSharedFeatures(error)) return false; @@ -1182,17 +973,9 @@ bool Extension::InitFromValue(int flags, string16* error) { return false; } - URLPatternSet scriptable_hosts = ContentScriptsInfo::GetScriptableHosts(this); - finished_parsing_manifest_ = true; - runtime_data_.SetActivePermissions(new PermissionSet( - *initial_api_permissions_, host_permissions, scriptable_hosts)); - required_permission_set_ = new PermissionSet( - *initial_api_permissions_, host_permissions, scriptable_hosts); - optional_permission_set_ = new PermissionSet( - optional_api_permissions, optional_host_permissions, URLPatternSet()); - initial_api_permissions_.reset(); + permissions_data_->FinalizePermissions(this); return true; } @@ -1274,8 +1057,8 @@ bool Extension::LoadExtent(const char* key, std::string pattern_string; if (!pattern_list->GetString(i, &pattern_string)) { *error = ErrorUtils::FormatErrorMessageUTF16(value_error, - base::UintToString(i), - errors::kExpectString); + base::UintToString(i), + errors::kExpectString); return false; } @@ -1609,61 +1392,6 @@ void Extension::OverrideLaunchUrl(const GURL& override_url) { } } -bool Extension::CanSpecifyExperimentalPermission() const { - if (location() == Manifest::COMPONENT) - return true; - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalExtensionApis)) { - return true; - } - - // We rely on the webstore to check access to experimental. This way we can - // whitelist extensions to have access to experimental in just the store, and - // not have to push a new version of the client. - if (from_webstore()) - return true; - - return false; -} - -bool Extension::CanSpecifyHostPermission(const URLPattern& pattern, - const APIPermissionSet& permissions) const { - if (!pattern.match_all_urls() && - pattern.MatchesScheme(chrome::kChromeUIScheme)) { - // Regular extensions are only allowed access to chrome://favicon. - if (pattern.host() == chrome::kChromeUIFaviconHost) - return true; - - // Experimental extensions are also allowed chrome://thumb. - // - // TODO: A public API should be created for retrieving thumbnails. - // See http://crbug.com/222856. A temporary hack is implemented here to - // make chrome://thumbs available to NTP Russia extension as - // non-experimental. - if (pattern.host() == chrome::kChromeUIThumbnailHost) { - return - permissions.find(APIPermission::kExperimental) != permissions.end() || - (id() == kThumbsWhiteListedExtension && from_webstore()); - } - - // Component extensions can have access to all of chrome://*. - if (CanExecuteScriptEverywhere()) - return true; - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kExtensionsOnChromeURLs)) - return true; - - // TODO(aboxhall): return from_webstore() when webstore handles blocking - // extensions which request chrome:// urls - return false; - } - - // Otherwise, the valid schemes were handled by URLPattern. - return true; -} - bool Extension::CheckMinimumChromeVersion(string16* error) const { if (!manifest_->HasKey(keys::kMinimumChromeVersion)) return true; diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index 4f8674c..7f05620 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -47,6 +47,7 @@ class ImageSkia; } namespace extensions { +class PermissionsData; class APIPermissionSet; class PermissionSet; @@ -170,11 +171,11 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // In a few special circumstances, we want to create an Extension and give it // an explicit id. Most consumers should just use the other Create() method. static scoped_refptr<Extension> Create(const base::FilePath& path, - Manifest::Location location, - const base::DictionaryValue& value, - int flags, - const std::string& explicit_id, - std::string* error); + Manifest::Location location, + const base::DictionaryValue& value, + int flags, + const std::string& explicit_id, + std::string* error); // Valid schemes for web extent URLPatterns. static const int kValidWebExtentSchemes; @@ -246,13 +247,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> { static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist); static const ScriptingWhitelist* GetScriptingWhitelist(); - // Parses the host and api permissions from the specified permission |key| - // from |manifest_|. - bool ParsePermissions(const char* key, - string16* error, - APIPermissionSet* api_permissions, - URLPatternSet* host_permissions); - // Returns true if this extension has the given permission. Prefer // IsExtensionWithPermissionOrSuggestInConsole when developers may be using an // api that requires a permission they didn't know about, e.g. open web apis. @@ -260,7 +254,8 @@ class Extension : public base::RefCountedThreadSafe<Extension> { bool HasAPIPermission(const std::string& function_name) const; bool HasAPIPermissionForTab(int tab_id, APIPermission::ID permission) const; - bool CheckAPIPermissionWithParam(APIPermission::ID permission, + bool CheckAPIPermissionWithParam( + APIPermission::ID permission, const APIPermission::CheckParam* param) const; const URLPatternSet& GetEffectiveHostPermissions() const; @@ -409,20 +404,11 @@ class Extension : public base::RefCountedThreadSafe<Extension> { const std::vector<NaClModuleInfo>& nacl_modules() const { return nacl_modules_; } - const PermissionSet* optional_permission_set() const { - return optional_permission_set_.get(); - } - const PermissionSet* required_permission_set() const { - return required_permission_set_.get(); - } - // Returns the temporary APIPermissionSet used in initialization. - // (NULL after initialization is completed.) - APIPermissionSet* initial_api_permissions() { - return initial_api_permissions_.get(); - } - const APIPermissionSet* initial_api_permissions() const { - return initial_api_permissions_.get(); + PermissionsData* permissions_data() { return permissions_data_.get(); } + const PermissionsData* permissions_data() const { + return permissions_data_.get(); } + // Appends |new_warning[s]| to install_warnings_. void AddInstallWarning(const InstallWarning& new_warning); void AddInstallWarnings(const std::vector<InstallWarning>& new_warnings); @@ -549,15 +535,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // |override_url|. void OverrideLaunchUrl(const GURL& override_url); - // Custom checks for the experimental permission that can't be expressed in - // _permission_features.json. - bool CanSpecifyExperimentalPermission() const; - - // Checks whether the host |pattern| is allowed for this extension, given API - // permissions |permissions|. - bool CanSpecifyHostPermission(const URLPattern& pattern, - const APIPermissionSet& permissions) const; - bool CheckMinimumChromeVersion(string16* error) const; // Check that platform app features are valid. Called after InitFromValue. @@ -594,15 +571,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> { mutable base::Lock runtime_data_lock_; mutable RuntimeData runtime_data_; - // The API permission set; used during extension initialization. - // Cleared after permissions are finalized by SetActivePermissions. - scoped_ptr<APIPermissionSet> initial_api_permissions_; - - // The set of permissions the extension can request at runtime. - scoped_refptr<const PermissionSet> optional_permission_set_; - - // The extension's required / default set of permissions. - scoped_refptr<const PermissionSet> required_permission_set_; + scoped_ptr<PermissionsData> permissions_data_; // Any warnings that occurred when trying to create/parse the extension. std::vector<InstallWarning> install_warnings_; diff --git a/chrome/common/extensions/features/permission_feature.cc b/chrome/common/extensions/features/permission_feature.cc index 4681aa2..5fa2ba2 100644 --- a/chrome/common/extensions/features/permission_feature.cc +++ b/chrome/common/extensions/features/permission_feature.cc @@ -5,6 +5,7 @@ #include "chrome/common/extensions/features/permission_feature.h" #include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" namespace extensions { @@ -29,7 +30,8 @@ Feature::Availability PermissionFeature::IsAvailableToContext( // Optional permissions need to be checked so an API will not be set to // undefined forever, when it could just need optional permissions. if (extension && !extension->HasAPIPermission(name()) && - !extension->optional_permission_set()->HasAnyAccessToAPI(name())) { + !PermissionsData::GetOptionalPermissions(extension)-> + HasAnyAccessToAPI(name())) { return CreateAvailability(NOT_PRESENT, extension->GetType()); } diff --git a/chrome/common/extensions/manifest_handlers/app_isolation_info.cc b/chrome/common/extensions/manifest_handlers/app_isolation_info.cc index 0d667a9..4b126c0 100644 --- a/chrome/common/extensions/manifest_handlers/app_isolation_info.cc +++ b/chrome/common/extensions/manifest_handlers/app_isolation_info.cc @@ -11,6 +11,7 @@ #include "base/values.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "extensions/common/error_utils.h" namespace keys = extension_manifest_keys; @@ -47,7 +48,7 @@ bool AppIsolationHandler::Parse(Extension* extension, string16* error) { // Other apps only get it if it is requested _and_ experimental APIs are // enabled. if (!extension->is_app() || - !extension->initial_api_permissions()->count( + !PermissionsData::GetInitialAPIPermissions(extension)->count( APIPermission::kExperimental)) { return true; } diff --git a/chrome/common/extensions/manifest_url_handler.cc b/chrome/common/extensions/manifest_url_handler.cc index 20b399a..1d15f40 100644 --- a/chrome/common/extensions/manifest_url_handler.cc +++ b/chrome/common/extensions/manifest_url_handler.cc @@ -17,6 +17,7 @@ #include "chrome/common/extensions/manifest.h" #include "chrome/common/extensions/permissions/api_permission.h" #include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" #include "chrome/common/url_constants.h" #include "extensions/common/error_utils.h" #include "grit/generated_resources.h" @@ -110,7 +111,8 @@ bool DevToolsPageHandler::Parse(Extension* extension, string16* error) { } manifest_url->url_ = extension->GetResourceURL(devtools_str); extension->SetManifestData(keys::kDevToolsPage, manifest_url.release()); - extension->initial_api_permissions()->insert(APIPermission::kDevtools); + PermissionsData::GetInitialAPIPermissions(extension)->insert( + APIPermission::kDevtools); return true; } diff --git a/chrome/common/extensions/permissions/permissions_data.cc b/chrome/common/extensions/permissions/permissions_data.cc new file mode 100644 index 0000000..445da12 --- /dev/null +++ b/chrome/common/extensions/permissions/permissions_data.cc @@ -0,0 +1,371 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/extensions/permissions/permissions_data.h" + +#include "base/command_line.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" +#include "base/stringprintf.h" +#include "base/strings/string_number_conversions.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_manifest_constants.h" +#include "chrome/common/extensions/features/base_feature_provider.h" +#include "chrome/common/extensions/features/feature.h" +#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" +#include "chrome/common/extensions/permissions/api_permission_set.h" +#include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_info.h" +#include "chrome/common/url_constants.h" +#include "extensions/common/error_utils.h" + +namespace keys = extension_manifest_keys; +namespace errors = extension_manifest_errors; + +namespace extensions { + +namespace { + +const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh"; + +bool ContainsManifestForbiddenPermission(const APIPermissionSet& apis, + string16* error) { + CHECK(error); + for (APIPermissionSet::const_iterator iter = apis.begin(); + iter != apis.end(); ++iter) { + if ((*iter)->ManifestEntryForbidden()) { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kPermissionNotAllowedInManifest, + (*iter)->info()->name()); + return true; + } + } + return false; +} + +// Custom checks for the experimental permission that can't be expressed in +// _permission_features.json. +bool CanSpecifyExperimentalPermission(const Extension* extension) { + if (extension->location() == Manifest::COMPONENT) + return true; + + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExperimentalExtensionApis)) { + return true; + } + + // We rely on the webstore to check access to experimental. This way we can + // whitelist extensions to have access to experimental in just the store, and + // not have to push a new version of the client. + if (extension->from_webstore()) + return true; + + return false; +} + +// Checks whether the host |pattern| is allowed for the given |extension|, +// given API permissions |permissions|. +bool CanSpecifyHostPermission(const Extension* extension, + const URLPattern& pattern, + const APIPermissionSet& permissions) { + if (!pattern.match_all_urls() && + pattern.MatchesScheme(chrome::kChromeUIScheme)) { + // Regular extensions are only allowed access to chrome://favicon. + if (pattern.host() == chrome::kChromeUIFaviconHost) + return true; + + // Experimental extensions are also allowed chrome://thumb. + // + // TODO: A public API should be created for retrieving thumbnails. + // See http://crbug.com/222856. A temporary hack is implemented here to + // make chrome://thumbs available to NTP Russia extension as + // non-experimental. + if (pattern.host() == chrome::kChromeUIThumbnailHost) { + return + permissions.find(APIPermission::kExperimental) != permissions.end() || + (extension->id() == kThumbsWhiteListedExtension && + extension->from_webstore()); + } + + // Component extensions can have access to all of chrome://*. + if (extension->CanExecuteScriptEverywhere()) + return true; + + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kExtensionsOnChromeURLs)) { + return true; + } + + // TODO(aboxhall): return from_webstore() when webstore handles blocking + // extensions which request chrome:// urls + return false; + } + + // Otherwise, the valid schemes were handled by URLPattern. + return true; +} + +// Parses the host and api permissions from the specified permission |key| +// from |extension|'s manifest. +bool ParseHelper(Extension* extension, + const char* key, + APIPermissionSet* api_permissions, + URLPatternSet* host_permissions, + string16* error) { + if (!extension->manifest()->HasKey(key)) + return true; + + const ListValue* permissions = NULL; + if (!extension->manifest()->GetList(key, &permissions)) { + *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions, + std::string()); + return false; + } + + // NOTE: We need to get the APIPermission before we check if features + // associated with them are available because the feature system does not + // know about aliases. + + std::vector<std::string> host_data; + if (!APIPermissionSet::ParseFromJSON( + permissions, api_permissions, error, &host_data)) { + return false; + } + + // Verify feature availability of permissions. + std::vector<APIPermission::ID> to_remove; + FeatureProvider* permission_features = + BaseFeatureProvider::GetByName("permission"); + for (APIPermissionSet::const_iterator iter = api_permissions->begin(); + iter != api_permissions->end(); ++iter) { + Feature* feature = permission_features->GetFeature(iter->name()); + + // The feature should exist since we just got an APIPermission for it. The + // two systems should be updated together whenever a permission is added. + DCHECK(feature); + // http://crbug.com/176381 + if (!feature) { + to_remove.push_back(iter->id()); + continue; + } + + Feature::Availability availability = feature->IsAvailableToManifest( + extension->id(), + extension->GetType(), + Feature::ConvertLocation(extension->location()), + extension->manifest_version()); + + if (!availability.is_available()) { + // Don't fail, but warn the developer that the manifest contains + // unrecognized permissions. This may happen legitimately if the + // extensions requests platform- or channel-specific permissions. + extension->AddInstallWarning(InstallWarning(InstallWarning::FORMAT_TEXT, + availability.message())); + to_remove.push_back(iter->id()); + continue; + } + + if (iter->id() == APIPermission::kExperimental) { + if (!CanSpecifyExperimentalPermission(extension)) { + *error = ASCIIToUTF16(errors::kExperimentalFlagRequired); + return false; + } + } + } + + // Remove permissions that are not available to this extension. + for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin(); + iter != to_remove.end(); ++iter) { + api_permissions->erase(*iter); + } + + // Parse host pattern permissions. + const int kAllowedSchemes = extension->CanExecuteScriptEverywhere() ? + URLPattern::SCHEME_ALL : Extension::kValidHostPermissionSchemes; + + for (std::vector<std::string>::const_iterator iter = host_data.begin(); + iter != host_data.end(); ++iter) { + const std::string& permission_str = *iter; + + // Check if it's a host pattern permission. + URLPattern pattern = URLPattern(kAllowedSchemes); + URLPattern::ParseResult parse_result = pattern.Parse(permission_str); + if (parse_result == URLPattern::PARSE_SUCCESS) { + // The path component is not used for host permissions, so we force it + // to match all paths. + pattern.SetPath("/*"); + int valid_schemes = pattern.valid_schemes(); + if (pattern.MatchesScheme(chrome::kFileScheme) && + !extension->CanExecuteScriptEverywhere()) { + extension->set_wants_file_access(true); + if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS)) + valid_schemes &= ~URLPattern::SCHEME_FILE; + } + + if (pattern.scheme() != chrome::kChromeUIScheme && + !extension->CanExecuteScriptEverywhere()) { + // Keep chrome:// in allowed schemes only if it's explicitly requested + // or CanExecuteScriptEverywhere is true. If the + // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission + // will fail, so don't check the flag here. + valid_schemes &= ~URLPattern::SCHEME_CHROMEUI; + } + pattern.SetValidSchemes(valid_schemes); + + if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) { + // TODO(aboxhall): make a warning (see pattern.match_all_urls() block + // below). + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kInvalidPermissionScheme, permission_str); + return false; + } + + host_permissions->AddPattern(pattern); + + // We need to make sure all_urls matches chrome://favicon and (maybe) + // chrome://thumbnail, so add them back in to host_permissions separately. + if (pattern.match_all_urls()) { + host_permissions->AddPattern( + URLPattern(URLPattern::SCHEME_CHROMEUI, + chrome::kChromeUIFaviconURL)); + if (api_permissions->find(APIPermission::kExperimental) != + api_permissions->end()) { + host_permissions->AddPattern( + URLPattern(URLPattern::SCHEME_CHROMEUI, + chrome::kChromeUIThumbnailURL)); + } + } + continue; + } + + // It's probably an unknown API permission. Do not throw an error so + // extensions can retain backwards compatability (http://crbug.com/42742). + extension->AddInstallWarning(InstallWarning( + InstallWarning::FORMAT_TEXT, + base::StringPrintf( + "Permission '%s' is unknown or URL pattern is malformed.", + permission_str.c_str()))); + } + + return true; +} + +} // namespace + +struct PermissionsData::InitialPermissions { + APIPermissionSet api_permissions; + URLPatternSet host_permissions; +}; + +PermissionsData::PermissionsData() { +} + +PermissionsData::~PermissionsData() { +} + +// static +const PermissionSet* PermissionsData::GetOptionalPermissions( + const Extension* extension) { + return extension->permissions_data()->optional_permission_set_.get(); +} + +// static +const PermissionSet* PermissionsData::GetRequiredPermissions( + const Extension* extension) { + return extension->permissions_data()->required_permission_set_.get(); +} + +// static +const APIPermissionSet* PermissionsData::GetInitialAPIPermissions( + const Extension* extension) { + return &extension->permissions_data()-> + initial_required_permissions_->api_permissions; +} + +// static +APIPermissionSet* PermissionsData::GetInitialAPIPermissions( + Extension* extension) { + return &extension->permissions_data()-> + initial_required_permissions_->api_permissions; +} + +bool PermissionsData::ParsePermissions(Extension* extension, string16* error) { + initial_required_permissions_.reset(new InitialPermissions); + if (!ParseHelper(extension, + keys::kPermissions, + &initial_required_permissions_->api_permissions, + &initial_required_permissions_->host_permissions, + error)) { + return false; + } + + // Check for any permissions that are optional only. + for (APIPermissionSet::const_iterator iter = + initial_required_permissions_->api_permissions.begin(); + iter != initial_required_permissions_->api_permissions.end(); ++iter) { + if ((*iter)->info()->must_be_optional()) { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kPermissionMustBeOptional, (*iter)->info()->name()); + return false; + } + } + + // TODO(jeremya/kalman) do this via the features system by exposing the + // app.window API to platform apps, with no dependency on any permissions. + // See http://crbug.com/120069. + if (extension->is_platform_app()) { + initial_required_permissions_->api_permissions.insert( + APIPermission::kAppCurrentWindowInternal); + initial_required_permissions_->api_permissions.insert( + APIPermission::kAppRuntime); + initial_required_permissions_->api_permissions.insert( + APIPermission::kAppWindow); + } + + initial_optional_permissions_.reset(new InitialPermissions); + if (!ParseHelper(extension, + keys::kOptionalPermissions, + &initial_optional_permissions_->api_permissions, + &initial_optional_permissions_->host_permissions, + error)) { + return false; + } + + if (ContainsManifestForbiddenPermission( + initial_required_permissions_->api_permissions, error) || + ContainsManifestForbiddenPermission( + initial_optional_permissions_->api_permissions, error)) { + return false; + } + + return true; +} + +void PermissionsData::FinalizePermissions(Extension* extension) { + URLPatternSet scriptable_hosts = + ContentScriptsInfo::GetScriptableHosts(extension); + + extension->SetActivePermissions(new PermissionSet( + initial_required_permissions_->api_permissions, + initial_required_permissions_->host_permissions, + scriptable_hosts)); + + required_permission_set_ = new PermissionSet( + initial_required_permissions_->api_permissions, + initial_required_permissions_->host_permissions, + scriptable_hosts); + + optional_permission_set_ = new PermissionSet( + initial_optional_permissions_->api_permissions, + initial_optional_permissions_->host_permissions, + URLPatternSet()); + + initial_required_permissions_.reset(); + initial_optional_permissions_.reset(); +} + +} // namespace extensions diff --git a/chrome/common/extensions/permissions/permissions_data.h b/chrome/common/extensions/permissions/permissions_data.h new file mode 100644 index 0000000..95c26c6 --- /dev/null +++ b/chrome/common/extensions/permissions/permissions_data.h @@ -0,0 +1,65 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSIONS_DATA_H_ +#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSIONS_DATA_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" + +namespace extensions { + +class PermissionSet; +class APIPermissionSet; +class Extension; + +// A container for the permissions data of the extension; also responsible for +// parsing the "permissions" and "optional_permissions" manifest keys. +// This class holds the permissions which were established in the extension's +// manifest; the runtime extensions of the extension (which may be different) +// are stored in Extension::RuntimeData. +class PermissionsData { + public: + PermissionsData(); + ~PermissionsData(); + + // Parse the permissions of a given extension in the initialization process. + bool ParsePermissions(Extension* extension, string16* error); + + // Finalize permissions after the initialization process completes. + void FinalizePermissions(Extension* extension); + + // Return the optional or required permission set for the given |extension|. + static const PermissionSet* GetOptionalPermissions( + const Extension* extension); + static const PermissionSet* GetRequiredPermissions( + const Extension* extension); + + // Return the temporary API permission set which is used during extension + // initialization. Once initialization completes, this is NULL. + static const APIPermissionSet* GetInitialAPIPermissions( + const Extension* extension); + static APIPermissionSet* GetInitialAPIPermissions(Extension* extension); + + private: + struct InitialPermissions; + + // Temporary permissions during the initialization process; NULL after + // initialization completes. + scoped_ptr<InitialPermissions> initial_required_permissions_; + scoped_ptr<InitialPermissions> initial_optional_permissions_; + + // The set of permissions the extension can request at runtime. + scoped_refptr<const PermissionSet> optional_permission_set_; + + // The extension's required / default set of permissions. + scoped_refptr<const PermissionSet> required_permission_set_; + + DISALLOW_COPY_AND_ASSIGN(PermissionsData); +}; + +} // namespace extensions + +#endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSIONS_DATA_H_ |