Chromium Code Reviews| Index: chrome/browser/extensions/extension_prefs.cc |
| diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc |
| index c992e5d1ee6bf8878c261dc6f885a178abbd5f33..8928da8c62096d45d9ce8831b259dfd63bec95de 100644 |
| --- a/chrome/browser/extensions/extension_prefs.cc |
| +++ b/chrome/browser/extensions/extension_prefs.cc |
| @@ -67,7 +67,6 @@ const char kIdleInstallInfoCrxPath[] = "crx_path"; |
| const char kIdleInstallInfoVersion[] = "version"; |
| const char kIdleInstallInfoFetchTime[] = "fetch_time"; |
| - |
| // A preference that, if true, will allow this extension to run in incognito |
| // mode. |
| const char kPrefIncognitoEnabled[] = "incognito"; |
| @@ -100,12 +99,18 @@ const char kUpdateUrlData[] = "update_url_data"; |
| const char kBrowserActionVisible[] = "browser_action_visible"; |
| // Preferences that hold which permissions the user has granted the extension. |
| -// We explicitly keep track of these so that extensions can contain unknown |
| +// We explicity keep track of these so that extensions can contain unknown |
|
Matt Perry
2011/06/21 00:43:10
typo
jstritar
2011/06/21 23:12:16
Done.
|
| // permissions, for backwards compatibility reasons, and we can still prompt |
| // the user to accept them once recognized. |
| -const char kPrefGrantedPermissionsAPI[] = "granted_permissions.api"; |
| -const char kPrefGrantedPermissionsHost[] = "granted_permissions.host"; |
| -const char kPrefGrantedPermissionsAll[] = "granted_permissions.full"; |
| +const char kPrefGrantedAPIs[] = "granted_permissions.api"; |
| +const char kPrefGrantedExplicitHosts[] = "granted_permissions.explicit_host"; |
| +const char kPrefGrantedScriptableHosts[] = |
| + "granted_permissions.scriptable_host"; |
| + |
| +// The preference names for the old granted permissions scheme. |
| +const char kPrefOldGrantedFullAccess[] = "granted_permissions.full"; |
| +const char kPrefOldGrantedHosts[] = "granted_permissions.host"; |
| +const char kPrefOldGrantedAPIs[] = "granted_permissions.api"; |
| // A preference that indicates when an extension was installed. |
| const char kPrefInstallTime[] = "install_time"; |
| @@ -256,15 +261,6 @@ static void CleanupBadExtensionKeys(const FilePath& root_dir, |
| } |
| } |
| -static void ExtentToStringSet(const URLPatternSet& host_extent, |
| - std::set<std::string>* result) { |
| - URLPatternList patterns = host_extent.patterns(); |
| - URLPatternList::const_iterator i; |
| - |
| - for (i = patterns.begin(); i != patterns.end(); ++i) |
| - result->insert(i->GetAsString()); |
| -} |
| - |
| } // namespace |
| ExtensionPrefs::ExtensionPrefs( |
| @@ -437,42 +433,45 @@ bool ExtensionPrefs::ReadExtensionPrefList( |
| return out_value != NULL; |
| } |
| -bool ExtensionPrefs::ReadExtensionPrefStringSet( |
| +bool ExtensionPrefs::ReadExtensionPrefURLPatternSet( |
| const std::string& extension_id, |
| const std::string& pref_key, |
| - std::set<std::string>* result) { |
| + URLPatternSet* result, |
| + int valid_schemes) { |
| const ListValue* value = NULL; |
| if (!ReadExtensionPrefList(extension_id, pref_key, &value)) |
| return false; |
| - result->clear(); |
| + bool allow_file_access = AllowFileAccess(extension_id); |
|
Matt Perry
2011/06/21 00:43:10
should you clear result to be consistent with the
jstritar
2011/06/21 23:12:16
Yes, thanks. Done.
|
| for (size_t i = 0; i < value->GetSize(); ++i) { |
| std::string item; |
| if (!value->GetString(i, &item)) |
| return false; |
| - result->insert(item); |
| + URLPattern pattern(valid_schemes); |
| + if (pattern.Parse(item, URLPattern::PARSE_LENIENT) != |
| + URLPattern::PARSE_SUCCESS) { |
| + NOTREACHED(); |
| + return false; |
| + } |
| + if (!allow_file_access && pattern.MatchesScheme(chrome::kFileScheme)) { |
| + pattern.set_valid_schemes( |
| + pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); |
|
Matt Perry
2011/06/21 00:43:10
indent +2
jstritar
2011/06/21 23:12:16
Done.
|
| + } |
| + result->AddPattern(pattern); |
| } |
| return true; |
| } |
| -void ExtensionPrefs::AddToExtensionPrefStringSet( |
| +void ExtensionPrefs::SetExtensionPrefURLPatternSet( |
| const std::string& extension_id, |
| const std::string& pref_key, |
| - const std::set<std::string>& added_value) { |
| - std::set<std::string> old_value; |
| - std::set<std::string> new_value; |
| - ReadExtensionPrefStringSet(extension_id, pref_key, &old_value); |
| - |
| - std::set_union(old_value.begin(), old_value.end(), |
| - added_value.begin(), added_value.end(), |
| - std::inserter(new_value, new_value.begin())); |
| - |
| + const URLPatternSet& new_value) { |
| ListValue* value = new ListValue(); |
| - for (std::set<std::string>::const_iterator iter = new_value.begin(); |
| - iter != new_value.end(); ++iter) |
| - value->Append(Value::CreateStringValue(*iter)); |
| + for (URLPatternList::const_iterator i = new_value.patterns().begin(); |
| + i != new_value.patterns().end(); ++i) |
| + value->Append(Value::CreateStringValue(i->GetAsString())); |
| UpdateExtensionPref(extension_id, pref_key, value); |
| } |
| @@ -670,72 +669,132 @@ void ExtensionPrefs::SetActiveBit(const std::string& extension_id, |
| Value::CreateBooleanValue(active)); |
| } |
| -bool ExtensionPrefs::GetGrantedPermissions( |
| - const std::string& extension_id, |
| - bool* full_access, |
| - std::set<std::string>* api_permissions, |
| - URLPatternSet* host_extent) { |
| - CHECK(Extension::IdIsValid(extension_id)); |
| +void ExtensionPrefs::MigratePermissions(const ExtensionIdSet& extension_ids) { |
| + for (ExtensionIdSet::const_iterator ext_id = extension_ids.begin(); |
| + ext_id != extension_ids.end(); ++ext_id) { |
| - const DictionaryValue* ext = GetExtensionPref(extension_id); |
| - if (!ext || !ext->GetBoolean(kPrefGrantedPermissionsAll, full_access)) |
| - return false; |
| + // An extension's granted permissions need to be migrated if the |
| + // full_access bit is present. This bit was always present in the previous |
| + // scheme and is never present now. |
| + bool full_access; |
| + const DictionaryValue* ext = GetExtensionPref(*ext_id); |
| + if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access)) |
| + continue; |
| - ReadExtensionPrefStringSet( |
| - extension_id, kPrefGrantedPermissionsAPI, api_permissions); |
| + // Remove the full access bit (empty list will get trimmed). |
| + UpdateExtensionPref( |
| + *ext_id, kPrefOldGrantedFullAccess, new ListValue()); |
| + |
| + // Migrate the API permission list to use the enumeration values rather |
|
Matt Perry
2011/06/21 00:43:10
I think this is dangerous. It requires us to commi
jstritar
2011/06/21 23:12:16
Good point. We're already committed to preserving
|
| + // than string names. Also, add the plugin permission if the full |
| + // access bit had been set. |
| + ListValue* new_apis = new ListValue(); |
| + if (full_access) |
| + new_apis->Append(Value::CreateIntegerValue( |
| + ExtensionAPIPermission::kPlugin)); |
| + |
| + ListValue* apis = NULL; |
| + if (ext->GetList(kPrefGrantedAPIs, &apis)) { |
| + for (size_t i = 0; i < apis->GetSize(); ++i) { |
| + std::string api; |
| + if (apis->GetString(i, &api)) { |
| + ExtensionAPIPermission* perm = |
| + ExtensionPermissionsInfo::GetByName(api); |
| + if (perm) |
| + new_apis->Append(Value::CreateIntegerValue(perm->id())); |
| + } |
| + } |
| + } |
| + UpdateExtensionPref(*ext_id, kPrefGrantedAPIs, new_apis); |
| + |
| + |
| + // The granted permissions originally only held the effective hosts, |
| + // which are a combination of host and user script host permissions. |
| + // We now maintain these lists separately. For migration purposes, it |
| + // does not matter how we treat the old effective hosts as long as the |
| + // new effective hosts will be the same, so we move them to explicit |
| + // host permissions. |
| + ListValue* hosts; |
| + if (ext->GetList(kPrefOldGrantedHosts, &hosts)) { |
| + UpdateExtensionPref( |
| + *ext_id, kPrefGrantedExplicitHosts, hosts->DeepCopy()); |
| + |
| + // We can get rid of the old one by setting it to an empty list. |
| + UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new ListValue()); |
| + } |
| + } |
| + SavePrefs(); |
| +} |
| - std::set<std::string> host_permissions; |
| - ReadExtensionPrefStringSet( |
| - extension_id, kPrefGrantedPermissionsHost, &host_permissions); |
| - bool allow_file_access = AllowFileAccess(extension_id); |
| +ExtensionPermissionSet* ExtensionPrefs::GetGrantedPermissions( |
| + const std::string& extension_id) { |
| + CHECK(Extension::IdIsValid(extension_id)); |
| - // The granted host permissions contain hosts from the manifest's |
| - // "permissions" array and from the content script "matches" arrays, |
| - // so the URLPattern needs to accept valid schemes from both types. |
| - for (std::set<std::string>::iterator i = host_permissions.begin(); |
| - i != host_permissions.end(); ++i) { |
| - URLPattern pattern( |
| - Extension::kValidHostPermissionSchemes | |
| - UserScript::kValidUserScriptSchemes); |
| - |
| - // Parse without strict checks, so that new strict checks do not |
| - // fail on a pattern in an installed extension. |
| - if (URLPattern::PARSE_SUCCESS != pattern.Parse( |
| - *i, URLPattern::PARSE_LENIENT)) { |
| - NOTREACHED(); // Corrupt prefs? Hand editing? |
| - } else { |
| - if (!allow_file_access && pattern.MatchesScheme(chrome::kFileScheme)) { |
| - pattern.set_valid_schemes( |
| - pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); |
| - } |
| - host_extent->AddPattern(pattern); |
| + const DictionaryValue* ext = GetExtensionPref(extension_id); |
| + if (!ext) |
| + return NULL; |
| + |
| + // Retrieve the API permissions. |
| + ExtensionAPIPermissionSet apis; |
| + const ListValue* api_values = NULL; |
| + if (ReadExtensionPrefList(extension_id, kPrefGrantedAPIs, &api_values)) { |
| + for (size_t i = 0; i < api_values->GetSize(); ++i) { |
| + int api_id; |
| + if (api_values->GetInteger(i, &api_id)) |
| + apis.insert(static_cast<ExtensionAPIPermission::Id>(api_id)); |
| } |
| } |
| - return true; |
| + // Retrieve the explicit host permissions. |
| + URLPatternSet explicit_hosts; |
| + ReadExtensionPrefURLPatternSet( |
| + extension_id, kPrefGrantedExplicitHosts, |
| + &explicit_hosts, Extension::kValidHostPermissionSchemes); |
| + |
| + // Retrieve the scriptable host permissions. |
| + URLPatternSet scriptable_hosts; |
| + ReadExtensionPrefURLPatternSet( |
| + extension_id, kPrefGrantedScriptableHosts, |
| + &scriptable_hosts, UserScript::kValidUserScriptSchemes); |
| + |
| + return new ExtensionPermissionSet(apis, explicit_hosts, scriptable_hosts); |
| } |
| void ExtensionPrefs::AddGrantedPermissions( |
| const std::string& extension_id, |
| - const bool full_access, |
| - const std::set<std::string>& api_permissions, |
| - const URLPatternSet& host_extent) { |
| + const ExtensionPermissionSet* permissions) { |
| CHECK(Extension::IdIsValid(extension_id)); |
| - UpdateExtensionPref(extension_id, kPrefGrantedPermissionsAll, |
| - Value::CreateBooleanValue(full_access)); |
| - |
| - if (!api_permissions.empty()) { |
| - AddToExtensionPrefStringSet( |
| - extension_id, kPrefGrantedPermissionsAPI, api_permissions); |
| + scoped_ptr<ExtensionPermissionSet> granted_permissions( |
| + GetGrantedPermissions(extension_id)); |
| + |
| + // The new granted permissions are the union of the already granted |
| + // permissions and the newly granted permissions. |
| + scoped_ptr<ExtensionPermissionSet> new_perms( |
| + ExtensionPermissionSet::CreateUnion( |
| + permissions, granted_permissions.get())); |
| + |
| + // Set the API permissions. |
| + ListValue* api_values = new ListValue(); |
| + ExtensionAPIPermissionSet apis = new_perms->apis(); |
| + for (ExtensionAPIPermissionSet::const_iterator i = apis.begin(); |
| + i != apis.end(); ++i) { |
| + api_values->Append(Value::CreateIntegerValue(*i)); |
| } |
| + UpdateExtensionPref(extension_id, kPrefGrantedAPIs, api_values); |
| - if (!host_extent.is_empty()) { |
| - std::set<std::string> host_permissions; |
| - ExtentToStringSet(host_extent, &host_permissions); |
| + // Set the explicit host permissions. |
| + if (!new_perms->explicit_hosts().is_empty()) { |
| + SetExtensionPrefURLPatternSet(extension_id, |
| + kPrefGrantedExplicitHosts, |
| + new_perms->explicit_hosts()); |
| + } |
| - AddToExtensionPrefStringSet( |
| - extension_id, kPrefGrantedPermissionsHost, host_permissions); |
| + // Set the scriptable host permissions. |
| + if (!new_perms->scriptable_hosts().is_empty()) { |
| + SetExtensionPrefURLPatternSet(extension_id, |
| + kPrefGrantedScriptableHosts, |
| + new_perms->scriptable_hosts()); |
| } |
| } |
| @@ -909,6 +968,10 @@ void ExtensionPrefs::OnExtensionInstalled( |
| extension_dict->Set(kPrefManifest, |
| extension->manifest_value()->DeepCopy()); |
| } |
| + if (extension->location() == Extension::INTERNAL) { |
| + AddGrantedPermissions(extension->id(), |
| + extension->permission_set()); |
| + } |
| extension_dict->Set(kPrefAppLaunchIndex, |
| Value::CreateIntegerValue(GetNextAppLaunchIndex())); |
| extension_pref_value_map_->RegisterExtension( |
| @@ -1428,6 +1491,8 @@ void ExtensionPrefs::InitPrefStore() { |
| } |
| FixMissingPrefs(extension_ids); |
| + MigratePermissions(extension_ids); |
| + |
| // Store extension controlled preference values in the |
| // |extension_pref_value_map_|, which then informs the subscribers |
| // (ExtensionPrefStores) about the winning values. |
| @@ -1485,7 +1550,6 @@ void ExtensionPrefs::InitPrefStore() { |
| extension_pref_value_map_->NotifyInitializationCompleted(); |
| } |
| - |
| void ExtensionPrefs::SetExtensionControlledPref( |
| const std::string& extension_id, |
| const std::string& pref_key, |