Index: chrome/common/extensions/extension.cc |
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc |
index a06497ef55f1c4e4233cee33abdde90e174aa86e..b3b0b65e2499f312486f5927d5a64a73943e7fc7 100644 |
--- a/chrome/common/extensions/extension.cc |
+++ b/chrome/common/extensions/extension.cc |
@@ -3388,6 +3388,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_); |
@@ -3410,6 +3411,16 @@ 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_permissions = |
+ runtime_data_.GetTabSpecificHostPermissions(tab_id); |
+ if (tab_permissions && |
+ tab_permissions->MatchesSecurityOrigin(page_url)) { |
+ return true; |
+ } |
+ } |
+ |
// If a script is specified, use its matches. |
if (script) |
return script->MatchesURL(page_url); |
@@ -3472,7 +3483,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; |
@@ -3648,6 +3666,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; |
@@ -3691,6 +3744,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; |
Aaron Boodman
2012/06/08 05:31:30
Consider moving this into a method of URLPatternSe
not at google - send to devlin
2012/06/12 20:40:51
Done.
|
+ 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) { |
Aaron Boodman
2012/06/08 05:31:30
(all.size() - skip) for clarity.
not at google - send to devlin
2012/06/12 20:40:51
ok.
|
+ 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; |
Aaron Boodman
2012/06/08 05:31:30
You aren't saving much by passing an out param bec
not at google - send to devlin
2012/06/12 20:40:51
Done.
|
+ } |
+} |
+ |
+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( |