diff options
Diffstat (limited to 'extensions/common/permissions/permission_set.cc')
-rw-r--r-- | extensions/common/permissions/permission_set.cc | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc new file mode 100644 index 0000000..d3f46fc --- /dev/null +++ b/extensions/common/permissions/permission_set.cc @@ -0,0 +1,251 @@ +// Copyright 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 "extensions/common/permissions/permission_set.h" + +#include <algorithm> +#include <iterator> +#include <string> + +#include "extensions/common/permissions/permissions_info.h" +#include "extensions/common/url_pattern.h" +#include "extensions/common/url_pattern_set.h" +#include "url/gurl.h" + +using extensions::URLPatternSet; + +namespace { + +void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) { + DCHECK(out); + for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) { + URLPattern p = *i; + p.SetPath("/*"); + out->AddPattern(p); + } +} + +} // namespace + +namespace extensions { + +// +// PermissionSet +// + +PermissionSet::PermissionSet() {} + +PermissionSet::PermissionSet( + const APIPermissionSet& apis, + const URLPatternSet& explicit_hosts, + const URLPatternSet& scriptable_hosts) + : apis_(apis), + scriptable_hosts_(scriptable_hosts) { + AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_); + InitImplicitPermissions(); + InitEffectiveHosts(); +} + +// static +PermissionSet* PermissionSet::CreateDifference( + const PermissionSet* set1, + const PermissionSet* set2) { + scoped_refptr<PermissionSet> empty = new PermissionSet(); + const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1; + const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2; + + APIPermissionSet apis; + APIPermissionSet::Difference(set1_safe->apis(), set2_safe->apis(), &apis); + + URLPatternSet explicit_hosts; + URLPatternSet::CreateDifference(set1_safe->explicit_hosts(), + set2_safe->explicit_hosts(), + &explicit_hosts); + + URLPatternSet scriptable_hosts; + URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(), + set2_safe->scriptable_hosts(), + &scriptable_hosts); + + return new PermissionSet(apis, explicit_hosts, scriptable_hosts); +} + +// static +PermissionSet* PermissionSet::CreateIntersection( + const PermissionSet* set1, + const PermissionSet* set2) { + scoped_refptr<PermissionSet> empty = new PermissionSet(); + const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1; + const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2; + + APIPermissionSet apis; + APIPermissionSet::Intersection(set1_safe->apis(), set2_safe->apis(), &apis); + + URLPatternSet explicit_hosts; + URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(), + set2_safe->explicit_hosts(), + &explicit_hosts); + + URLPatternSet scriptable_hosts; + URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(), + set2_safe->scriptable_hosts(), + &scriptable_hosts); + + return new PermissionSet(apis, explicit_hosts, scriptable_hosts); +} + +// static +PermissionSet* PermissionSet::CreateUnion( + const PermissionSet* set1, + const PermissionSet* set2) { + scoped_refptr<PermissionSet> empty = new PermissionSet(); + const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1; + const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2; + + APIPermissionSet apis; + APIPermissionSet::Union(set1_safe->apis(), set2_safe->apis(), &apis); + + URLPatternSet explicit_hosts; + URLPatternSet::CreateUnion(set1_safe->explicit_hosts(), + set2_safe->explicit_hosts(), + &explicit_hosts); + + URLPatternSet scriptable_hosts; + URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(), + set2_safe->scriptable_hosts(), + &scriptable_hosts); + + return new PermissionSet(apis, explicit_hosts, scriptable_hosts); +} + +bool PermissionSet::operator==( + const PermissionSet& rhs) const { + return apis_ == rhs.apis_ && + scriptable_hosts_ == rhs.scriptable_hosts_ && + explicit_hosts_ == rhs.explicit_hosts_; +} + +bool PermissionSet::Contains(const PermissionSet& set) const { + return apis_.Contains(set.apis()) && + explicit_hosts().Contains(set.explicit_hosts()) && + scriptable_hosts().Contains(set.scriptable_hosts()); +} + +std::set<std::string> PermissionSet::GetAPIsAsStrings() const { + std::set<std::string> apis_str; + for (APIPermissionSet::const_iterator i = apis_.begin(); + i != apis_.end(); ++i) { + apis_str.insert(i->name()); + } + return apis_str; +} + +bool PermissionSet::IsEmpty() const { + // Not default if any host permissions are present. + if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty())) + return false; + + // Or if it has no api permissions. + return apis().empty(); +} + +bool PermissionSet::HasAPIPermission( + APIPermission::ID id) const { + return apis().find(id) != apis().end(); +} + +bool PermissionSet::HasAPIPermission(const std::string& permission_name) const { + const APIPermissionInfo* permission = + PermissionsInfo::GetInstance()->GetByName(permission_name); + CHECK(permission) << permission_name; + return (permission && apis_.count(permission->id())); +} + +bool PermissionSet::CheckAPIPermission(APIPermission::ID permission) const { + return CheckAPIPermissionWithParam(permission, NULL); +} + +bool PermissionSet::CheckAPIPermissionWithParam( + APIPermission::ID permission, + const APIPermission::CheckParam* param) const { + APIPermissionSet::const_iterator iter = apis().find(permission); + if (iter == apis().end()) + return false; + return iter->Check(param); +} + +bool PermissionSet::HasExplicitAccessToOrigin( + const GURL& origin) const { + return explicit_hosts().MatchesURL(origin); +} + +bool PermissionSet::HasScriptableAccessToURL( + const GURL& origin) const { + // We only need to check our host list to verify access. The host list should + // already reflect any special rules (such as chrome://favicon, all hosts + // access, etc.). + return scriptable_hosts().MatchesURL(origin); +} + +bool PermissionSet::HasEffectiveAccessToAllHosts() const { + // There are two ways this set can have effective access to all hosts: + // 1) it has an <all_urls> URL pattern. + // 2) it has a named permission with implied full URL access. + for (URLPatternSet::const_iterator host = effective_hosts().begin(); + host != effective_hosts().end(); ++host) { + if (host->match_all_urls() || + (host->match_subdomains() && host->host().empty())) + return true; + } + + for (APIPermissionSet::const_iterator i = apis().begin(); + i != apis().end(); ++i) { + if (i->info()->implies_full_url_access()) + return true; + } + return false; +} + +bool PermissionSet::HasEffectiveAccessToURL(const GURL& url) const { + return effective_hosts().MatchesURL(url); +} + +bool PermissionSet::HasEffectiveFullAccess() const { + for (APIPermissionSet::const_iterator i = apis().begin(); + i != apis().end(); ++i) { + if (i->info()->implies_full_access()) + return true; + } + return false; +} + +PermissionSet::~PermissionSet() {} + +void PermissionSet::InitImplicitPermissions() { + // The downloads permission implies the internal version as well. + if (apis_.find(APIPermission::kDownloads) != apis_.end()) + apis_.insert(APIPermission::kDownloadsInternal); + + // TODO(fsamuel): Is there a better way to request access to the WebRequest + // API without exposing it to the Chrome App? + if (apis_.find(APIPermission::kWebView) != apis_.end()) + apis_.insert(APIPermission::kWebRequestInternal); + + // The webRequest permission implies the internal version as well. + if (apis_.find(APIPermission::kWebRequest) != apis_.end()) + apis_.insert(APIPermission::kWebRequestInternal); + + // The fileBrowserHandler permission implies the internal version as well. + if (apis_.find(APIPermission::kFileBrowserHandler) != apis_.end()) + apis_.insert(APIPermission::kFileBrowserHandlerInternal); +} + +void PermissionSet::InitEffectiveHosts() { + effective_hosts_.ClearPatterns(); + + URLPatternSet::CreateUnion( + explicit_hosts(), scriptable_hosts(), &effective_hosts_); +} + +} // namespace extensions |