Index: extensions/common/permissions/permissions_data.cc |
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc |
index 7fdbd2c36a79eea46b681b1f3ef464be2be27b15..6757298e4067268ba897e74a2bab1c5fa60ab538 100644 |
--- a/extensions/common/permissions/permissions_data.cc |
+++ b/extensions/common/permissions/permissions_data.cc |
@@ -25,19 +25,31 @@ namespace { |
PermissionsData::PolicyDelegate* g_policy_delegate = NULL; |
+class AutoLockOnValidThread { |
+ public: |
+ AutoLockOnValidThread(base::Lock& lock, base::ThreadChecker* thread_checker) |
+ : auto_lock_(lock) { |
+ DCHECK(!thread_checker || thread_checker->CalledOnValidThread()); |
+ } |
+ |
+ private: |
+ base::AutoLock auto_lock_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AutoLockOnValidThread); |
+}; |
+ |
} // namespace |
PermissionsData::PermissionsData(const Extension* extension) |
: extension_id_(extension->id()), manifest_type_(extension->GetType()) { |
- base::AutoLock auto_lock(runtime_lock_); |
- scoped_refptr<const PermissionSet> required_permissions = |
+ const PermissionSet* required_permissions = |
PermissionsParser::GetRequiredPermissions(extension); |
- active_permissions_unsafe_ = |
+ active_permissions_unsafe_.reset( |
new PermissionSet(required_permissions->apis(), |
required_permissions->manifest_permissions(), |
required_permissions->explicit_hosts(), |
- required_permissions->scriptable_hosts()); |
- withheld_permissions_unsafe_ = new PermissionSet(); |
+ required_permissions->scriptable_hosts())); |
+ withheld_permissions_unsafe_.reset(new PermissionSet()); |
} |
PermissionsData::~PermissionsData() { |
@@ -75,6 +87,7 @@ bool PermissionsData::ScriptsMayRequireActionForExtension( |
permissions->ShouldWarnAllHosts(); |
} |
+// static |
bool PermissionsData::ShouldSkipPermissionWarnings( |
const std::string& extension_id) { |
// See http://b/4946060 for more details. |
@@ -121,60 +134,74 @@ bool PermissionsData::IsRestrictedUrl(const GURL& document_url, |
return false; |
} |
+void PermissionsData::BindToCurrentThread() const { |
+ DCHECK(!thread_checker_); |
+ thread_checker_.reset(new base::ThreadChecker()); |
+} |
+ |
void PermissionsData::SetPermissions( |
- const scoped_refptr<const PermissionSet>& active, |
- const scoped_refptr<const PermissionSet>& withheld) const { |
- base::AutoLock auto_lock(runtime_lock_); |
- active_permissions_unsafe_ = active; |
- withheld_permissions_unsafe_ = withheld; |
+ scoped_ptr<const PermissionSet> active, |
+ scoped_ptr<const PermissionSet> withheld) const { |
+ AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
+ active_permissions_unsafe_ = active.Pass(); |
+ withheld_permissions_unsafe_ = withheld.Pass(); |
+} |
+ |
+void PermissionsData::SetActivePermissions( |
+ scoped_ptr<const PermissionSet> active) const { |
+ AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
+ active_permissions_unsafe_ = active.Pass(); |
} |
void PermissionsData::UpdateTabSpecificPermissions( |
int tab_id, |
- scoped_refptr<const PermissionSet> permissions) const { |
- base::AutoLock auto_lock(runtime_lock_); |
+ const PermissionSet& permissions) const { |
+ AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
CHECK_GE(tab_id, 0); |
- TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id); |
- if (iter == tab_specific_permissions_.end()) |
- tab_specific_permissions_[tab_id] = permissions; |
- else |
- iter->second = PermissionSet::CreateUnion(*(iter->second), *permissions); |
+ TabPermissionsMap::const_iterator iter = |
+ tab_specific_permissions_.find(tab_id); |
+ scoped_ptr<const PermissionSet> new_permissions = PermissionSet::CreateUnion( |
+ iter == tab_specific_permissions_.end() |
+ ? static_cast<const PermissionSet&>(PermissionSet()) |
+ : *iter->second, |
+ permissions); |
+ tab_specific_permissions_.set(tab_id, new_permissions.Pass()); |
} |
void PermissionsData::ClearTabSpecificPermissions(int tab_id) const { |
- base::AutoLock auto_lock(runtime_lock_); |
+ AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
CHECK_GE(tab_id, 0); |
tab_specific_permissions_.erase(tab_id); |
} |
bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const { |
- return active_permissions()->HasAPIPermission(permission); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return active_permissions_unsafe_->HasAPIPermission(permission); |
} |
bool PermissionsData::HasAPIPermission( |
const std::string& permission_name) const { |
- return active_permissions()->HasAPIPermission(permission_name); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return active_permissions_unsafe_->HasAPIPermission(permission_name); |
} |
bool PermissionsData::HasAPIPermissionForTab( |
int tab_id, |
APIPermission::ID permission) const { |
- if (HasAPIPermission(permission)) |
+ base::AutoLock auto_lock(runtime_lock_); |
+ if (active_permissions_unsafe_->HasAPIPermission(permission)) |
return true; |
- scoped_refptr<const PermissionSet> tab_permissions = |
- GetTabSpecificPermissions(tab_id); |
- |
- // Place autolock below the HasAPIPermission() and |
- // GetTabSpecificPermissions(), since each already acquires the lock. |
- base::AutoLock auto_lock(runtime_lock_); |
- return tab_permissions.get() && tab_permissions->HasAPIPermission(permission); |
+ const PermissionSet* tab_permissions = GetTabSpecificPermissions(tab_id); |
+ return tab_permissions && tab_permissions->HasAPIPermission(permission); |
} |
bool PermissionsData::CheckAPIPermissionWithParam( |
APIPermission::ID permission, |
const APIPermission::CheckParam* param) const { |
- return active_permissions()->CheckAPIPermissionWithParam(permission, param); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return active_permissions_unsafe_->CheckAPIPermissionWithParam(permission, |
+ param); |
} |
URLPatternSet PermissionsData::GetEffectiveHostPermissions() const { |
@@ -186,24 +213,28 @@ URLPatternSet PermissionsData::GetEffectiveHostPermissions() const { |
} |
bool PermissionsData::HasHostPermission(const GURL& url) const { |
- return active_permissions()->HasExplicitAccessToOrigin(url); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return active_permissions_unsafe_->HasExplicitAccessToOrigin(url); |
} |
bool PermissionsData::HasEffectiveAccessToAllHosts() const { |
- return active_permissions()->HasEffectiveAccessToAllHosts(); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return active_permissions_unsafe_->HasEffectiveAccessToAllHosts(); |
} |
PermissionMessages PermissionsData::GetPermissionMessages() const { |
+ base::AutoLock auto_lock(runtime_lock_); |
return PermissionMessageProvider::Get()->GetPermissionMessages( |
PermissionMessageProvider::Get()->GetAllPermissionIDs( |
- active_permissions().get(), manifest_type_)); |
+ active_permissions_unsafe_.get(), manifest_type_)); |
} |
bool PermissionsData::HasWithheldImpliedAllHosts() const { |
+ base::AutoLock auto_lock(runtime_lock_); |
// Since we currently only withhold all_hosts, it's sufficient to check |
// that either set is not empty. |
- return !withheld_permissions()->explicit_hosts().is_empty() || |
- !withheld_permissions()->scriptable_hosts().is_empty(); |
+ return !withheld_permissions_unsafe_->explicit_hosts().is_empty() || |
+ !withheld_permissions_unsafe_->scriptable_hosts().is_empty(); |
} |
bool PermissionsData::CanAccessPage(const Extension* extension, |
@@ -211,13 +242,11 @@ bool PermissionsData::CanAccessPage(const Extension* extension, |
int tab_id, |
int process_id, |
std::string* error) const { |
- AccessType result = CanRunOnPage(extension, |
- document_url, |
- tab_id, |
- process_id, |
- active_permissions()->explicit_hosts(), |
- withheld_permissions()->explicit_hosts(), |
- error); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ AccessType result = |
+ CanRunOnPage(extension, document_url, tab_id, process_id, |
+ active_permissions_unsafe_->explicit_hosts(), |
+ withheld_permissions_unsafe_->explicit_hosts(), error); |
// TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED. |
return result == ACCESS_ALLOWED || result == ACCESS_WITHHELD; |
} |
@@ -228,13 +257,10 @@ PermissionsData::AccessType PermissionsData::GetPageAccess( |
int tab_id, |
int process_id, |
std::string* error) const { |
- return CanRunOnPage(extension, |
- document_url, |
- tab_id, |
- process_id, |
- active_permissions()->explicit_hosts(), |
- withheld_permissions()->explicit_hosts(), |
- error); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return CanRunOnPage(extension, document_url, tab_id, process_id, |
+ active_permissions_unsafe_->explicit_hosts(), |
+ withheld_permissions_unsafe_->explicit_hosts(), error); |
} |
bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension, |
@@ -242,13 +268,11 @@ bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension, |
int tab_id, |
int process_id, |
std::string* error) const { |
- AccessType result = CanRunOnPage(extension, |
- document_url, |
- tab_id, |
- process_id, |
- active_permissions()->scriptable_hosts(), |
- withheld_permissions()->scriptable_hosts(), |
- error); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ AccessType result = |
+ CanRunOnPage(extension, document_url, tab_id, process_id, |
+ active_permissions_unsafe_->scriptable_hosts(), |
+ withheld_permissions_unsafe_->scriptable_hosts(), error); |
// TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED. |
return result == ACCESS_ALLOWED || result == ACCESS_WITHHELD; |
} |
@@ -259,13 +283,10 @@ PermissionsData::AccessType PermissionsData::GetContentScriptAccess( |
int tab_id, |
int process_id, |
std::string* error) const { |
- return CanRunOnPage(extension, |
- document_url, |
- tab_id, |
- process_id, |
- active_permissions()->scriptable_hosts(), |
- withheld_permissions()->scriptable_hosts(), |
- error); |
+ base::AutoLock auto_lock(runtime_lock_); |
+ return CanRunOnPage(extension, document_url, tab_id, process_id, |
+ active_permissions_unsafe_->scriptable_hosts(), |
+ withheld_permissions_unsafe_->scriptable_hosts(), error); |
} |
bool PermissionsData::CanCaptureVisiblePage(int tab_id, |
@@ -273,13 +294,13 @@ bool PermissionsData::CanCaptureVisiblePage(int tab_id, |
const URLPattern all_urls(URLPattern::SCHEME_ALL, |
URLPattern::kAllUrlsPattern); |
- if (active_permissions()->explicit_hosts().ContainsPattern(all_urls)) |
+ base::AutoLock auto_lock(runtime_lock_); |
+ if (active_permissions_unsafe_->explicit_hosts().ContainsPattern(all_urls)) |
return true; |
if (tab_id >= 0) { |
- scoped_refptr<const PermissionSet> tab_permissions = |
- GetTabSpecificPermissions(tab_id); |
- if (tab_permissions.get() && |
+ const PermissionSet* tab_permissions = GetTabSpecificPermissions(tab_id); |
+ if (tab_permissions && |
tab_permissions->HasAPIPermission(APIPermission::kTab)) { |
return true; |
} |
@@ -293,28 +314,22 @@ bool PermissionsData::CanCaptureVisiblePage(int tab_id, |
return false; |
} |
-PermissionsData::TabPermissionsMap |
-PermissionsData::CopyTabSpecificPermissionsMap() const { |
- base::AutoLock auto_lock(runtime_lock_); |
- return tab_specific_permissions_; |
-} |
- |
-scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( |
+const PermissionSet* PermissionsData::GetTabSpecificPermissions( |
int tab_id) const { |
- base::AutoLock auto_lock(runtime_lock_); |
CHECK_GE(tab_id, 0); |
+ runtime_lock_.AssertAcquired(); |
TabPermissionsMap::const_iterator iter = |
tab_specific_permissions_.find(tab_id); |
- return (iter != tab_specific_permissions_.end()) ? iter->second : NULL; |
+ return (iter != tab_specific_permissions_.end()) ? iter->second : nullptr; |
} |
bool PermissionsData::HasTabSpecificPermissionToExecuteScript( |
int tab_id, |
const GURL& url) const { |
+ runtime_lock_.AssertAcquired(); |
if (tab_id >= 0) { |
- scoped_refptr<const PermissionSet> tab_permissions = |
- GetTabSpecificPermissions(tab_id); |
- if (tab_permissions.get() && |
+ const PermissionSet* tab_permissions = GetTabSpecificPermissions(tab_id); |
+ if (tab_permissions && |
tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { |
return true; |
} |
@@ -330,6 +345,7 @@ PermissionsData::AccessType PermissionsData::CanRunOnPage( |
const URLPatternSet& permitted_url_patterns, |
const URLPatternSet& withheld_url_patterns, |
std::string* error) const { |
+ runtime_lock_.AssertAcquired(); |
if (g_policy_delegate && |
!g_policy_delegate->CanExecuteScriptOnPage( |
extension, document_url, tab_id, process_id, error)) { |