Index: chrome/common/extensions/extension.cc |
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc |
index 54e056617ede1fb55352371f612050bdb4ffb5de..d1b88a6f1a6dd746883589b7a5af8f9888d2e272 100644 |
--- a/chrome/common/extensions/extension.cc |
+++ b/chrome/common/extensions/extension.cc |
@@ -3320,6 +3320,7 @@ bool Extension::HasMultipleUISurfaces() const { |
} |
bool Extension::CanExecuteScriptOnPage(const GURL& page_url, |
+ int tab_id, |
const UserScript* script, |
std::string* error) const { |
base::AutoLock auto_lock(runtime_data_lock_); |
@@ -3342,6 +3343,14 @@ bool Extension::CanExecuteScriptOnPage(const GURL& page_url, |
!CanExecuteScriptEverywhere()) |
return false; |
+ // If a tab ID is specified, try the tab-specific permissions. |
+ if (tab_id >= 0) { |
+ const URLPatternSet* tab = |
Aaron Boodman
2012/06/06 01:03:13
nit: tab_permissions?
not at google - send to devlin
2012/06/06 07:38:40
But then it won't fit on 1 line!
|
+ runtime_data_.GetTabSpecificHostPermissions(tab_id); |
+ if (tab && tab->MatchesSecurityOrigin(page_url)) |
+ return true; |
+ } |
+ |
// If a script is specified, use its matches. |
if (script) |
return script->MatchesURL(page_url); |
@@ -3404,7 +3413,14 @@ bool Extension::CanExecuteScriptEverywhere() const { |
} |
bool Extension::CanCaptureVisiblePage(const GURL& page_url, |
+ int tab_id, |
std::string *error) const { |
+ if (tab_id >= 0) { |
+ const URLPatternSet* tab = GetTabSpecificHostPermissions(tab_id); |
+ if (tab && tab->MatchesSecurityOrigin(page_url)) |
+ return true; |
+ } |
+ |
if (HasHostPermission(page_url) || page_url.GetOrigin() == url()) |
return true; |
@@ -3580,6 +3596,41 @@ ExtensionAction* Extension::GetScriptBadge() const { |
return script_badge_.get(); |
} |
+const URLPatternSet* Extension::GetTabSpecificHostPermissions( |
+ int tab_id) const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ return runtime_data_.GetTabSpecificHostPermissions(tab_id); |
+} |
+ |
+void Extension::SetTabSpecificHostPermissions( |
+ int tab_id, |
+ const URLPatternSet& permissions) const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ runtime_data_.SetTabSpecificHostPermissions(tab_id, permissions); |
+} |
+ |
+void Extension::ClearTabSpecificHostPermissions(int tab_id) const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ runtime_data_.ClearTabSpecificHostPermissions(tab_id); |
+} |
+ |
+const URLPatternSet* Extension::GetActiveHostPermissionsForAllTabs() const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ return runtime_data_.GetActiveHostPermissionsForAllTabs(); |
+} |
+ |
+void Extension::GetAllTabSpecificHostPermissions( |
+ std::map<int, URLPatternSet>* out) const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ runtime_data_.GetAllTabSpecificHostPermissions(out); |
+} |
+ |
+void Extension::SetAllTabSpecificHostPermissions( |
+ const std::map<int, URLPatternSet>& origins) const { |
+ base::AutoLock auto_lock(runtime_data_lock_); |
+ runtime_data_.SetAllTabSpecificHostPermissions(origins); |
+} |
+ |
bool Extension::CheckPlatformAppFeatures(std::string* utf8_error) { |
if (!is_platform_app()) |
return true; |
@@ -3623,6 +3674,93 @@ scoped_refptr<const ExtensionPermissionSet> |
void Extension::RuntimeData::SetActivePermissions( |
const ExtensionPermissionSet* active) { |
active_permissions_ = active; |
+ active_host_permissions_for_all_tabs_.reset(); |
+} |
+ |
+const URLPatternSet* |
+ Extension::RuntimeData::GetTabSpecificHostPermissions(int tab_id) const { |
+ CHECK_GE(tab_id, 0); |
+ TabHostPermissionsMap::const_iterator it = |
+ tab_specific_host_permissions_.find(tab_id); |
+ return (it != tab_specific_host_permissions_.end()) ? it->second.get() : NULL; |
+} |
+ |
+void Extension::RuntimeData::SetTabSpecificHostPermissions( |
+ int tab_id, |
+ const URLPatternSet& hosts) { |
+ CHECK_GE(tab_id, 0); |
+ tab_specific_host_permissions_[tab_id] = |
+ make_linked_ptr(new URLPatternSet(hosts)); |
+ |
+ // If we're tracking the active host permissions for all tabs, update it. |
+ if (active_host_permissions_for_all_tabs_.get()) { |
+ scoped_ptr<URLPatternSet> updated(new URLPatternSet()); |
+ URLPatternSet::CreateUnion(*active_host_permissions_for_all_tabs_, |
+ hosts, |
+ updated.get()); |
+ active_host_permissions_for_all_tabs_ = updated.Pass(); |
+ } |
+} |
+ |
+void Extension::RuntimeData::ClearTabSpecificHostPermissions(int tab_id) { |
+ CHECK_GE(tab_id, 0); |
+ tab_specific_host_permissions_.erase(tab_id); |
+ active_host_permissions_for_all_tabs_.reset(); |
+} |
+ |
+const URLPatternSet* |
+ Extension::RuntimeData::GetActiveHostPermissionsForAllTabs() const { |
+ if (active_host_permissions_for_all_tabs_.get()) |
+ return active_host_permissions_for_all_tabs_.get(); |
+ |
+ if (tab_specific_host_permissions_.empty()) |
+ return &active_permissions_->explicit_hosts(); |
+ |
+ // Compute and cache the union of all tab specific permissions. The union |
+ // operation for ExtensionPermissionSet is O(n), so the naive union |
+ // implementation would be O(n^2). Try to be smarter and do it in O(nlog(n)). |
+ std::vector<linked_ptr<const URLPatternSet> > all; |
+ for (TabHostPermissionsMap::const_iterator it = |
+ tab_specific_host_permissions_.begin(); |
+ it != tab_specific_host_permissions_.end(); ++it) { |
+ all.push_back(it->second); |
+ } |
+ |
+ for (size_t skip = 1; skip < all.size(); skip *= 2) { |
+ for (size_t i = 0; i < all.size() - skip; i += skip) { |
+ URLPatternSet* u = new URLPatternSet(); |
+ URLPatternSet::CreateUnion(*all[i], *all[i + skip], u); |
+ all[i] = make_linked_ptr(u); |
+ } |
+ } |
+ |
+ active_host_permissions_for_all_tabs_.reset(new URLPatternSet()); |
+ URLPatternSet::CreateUnion( |
+ *all[0], |
+ active_permissions_->explicit_hosts(), |
+ active_host_permissions_for_all_tabs_.get()); |
+ return active_host_permissions_for_all_tabs_.get(); |
+} |
+ |
+void Extension::RuntimeData::GetAllTabSpecificHostPermissions( |
+ std::map<int, URLPatternSet>* out) const { |
+ for (TabHostPermissionsMap::const_iterator it = |
+ tab_specific_host_permissions_.begin(); |
+ it != tab_specific_host_permissions_.end(); ++it) { |
+ (*out)[it->first] = *it->second; |
+ } |
+} |
+ |
+void Extension::RuntimeData::SetAllTabSpecificHostPermissions( |
+ const std::map<int, URLPatternSet>& in) { |
+ tab_specific_host_permissions_.clear(); |
+ active_host_permissions_for_all_tabs_.reset(); |
+ |
+ for (std::map<int, URLPatternSet>::const_iterator it = in.begin(); |
+ it != in.end(); ++it) { |
+ tab_specific_host_permissions_[it->first].reset( |
+ new URLPatternSet(it->second)); |
+ } |
} |
UnloadedExtensionInfo::UnloadedExtensionInfo( |