Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(520)

Unified Diff: chrome/browser/extensions/active_script_controller.cc

Issue 286003004: Block tabs.executeScript() from executing until user grants permission (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/active_script_controller.cc
diff --git a/chrome/browser/extensions/active_script_controller.cc b/chrome/browser/extensions/active_script_controller.cc
index 36209aff27729a13b0aa4b29b2aaf815cfed78b6..bc6829bc3cdd4c3af627dfc4693bb820f40c6181 100644
--- a/chrome/browser/extensions/active_script_controller.cc
+++ b/chrome/browser/extensions/active_script_controller.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/extensions/active_script_controller.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "chrome/browser/extensions/extension_action.h"
@@ -12,6 +15,7 @@
#include "chrome/common/extensions/api/extension_action/action_info.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
@@ -27,6 +31,7 @@ ActiveScriptController::ActiveScriptController(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()) {
+ CHECK(web_contents);
}
ActiveScriptController::~ActiveScriptController() {
@@ -48,31 +53,40 @@ ActiveScriptController* ActiveScriptController::GetForWebContents(
return location_bar_controller->active_script_controller();
}
-void ActiveScriptController::NotifyScriptExecuting(
- const std::string& extension_id, int page_id) {
+void ActiveScriptController::InjectScriptIfHasPermission(
+ const std::string& extension_id,
+ int page_id,
+ const base::Closure& callback) {
content::NavigationEntry* visible_entry =
web_contents()->GetController().GetVisibleEntry();
- if (!visible_entry ||
- extensions_executing_scripts_.count(extension_id) ||
- visible_entry->GetPageID() != page_id) {
+ if (!visible_entry || visible_entry->GetPageID() != page_id)
return;
- }
const Extension* extension =
ExtensionRegistry::Get(web_contents()->GetBrowserContext())
->enabled_extensions().GetByID(extension_id);
- if (extension &&
- PermissionsData::RequiresActionForScriptExecution(extension)) {
- extensions_executing_scripts_.insert(extension_id);
- LocationBarController::NotifyChange(web_contents());
- }
+ if (!extension)
+ return;
+
+ AddOrProcessRequest(extension, callback);
}
void ActiveScriptController::OnAdInjectionDetected(
const std::vector<std::string> ad_injectors) {
size_t num_preventable_ad_injectors =
base::STLSetIntersection<std::set<std::string> >(
- ad_injectors, extensions_executing_scripts_).size();
+ ad_injectors, permitted_extensions_).size();
not at google - send to devlin 2014/05/15 22:21:44 if the feature isn't enabled then *every* extensio
Devlin 2014/05/15 23:52:35 Yep, definitely a bug there with the permitted. I
+
+ // We only log the permitted extensions metric if the feature is enabled,
+ // because otherwise the data will be boring (100% allowed).
not at google - send to devlin 2014/05/15 22:21:44 I would have expected 0%
Devlin 2014/05/15 23:52:35 Well, we implicitly allow script injection when it
+ if (enabled_) {
+ UMA_HISTOGRAM_COUNTS_100(
+ "Extensions.ActiveScriptController.PermittedExtensions",
+ permitted_extensions_.size());
+ UMA_HISTOGRAM_COUNTS_100(
+ "Extensions.ActiveScriptController.DeniedExtensions",
+ pending_requests_.size());
+ }
UMA_HISTOGRAM_COUNTS_100(
"Extensions.ActiveScriptController.PreventableAdInjectors",
@@ -84,7 +98,7 @@ void ActiveScriptController::OnAdInjectionDetected(
ExtensionAction* ActiveScriptController::GetActionForExtension(
const Extension* extension) {
- if (!enabled_ || extensions_executing_scripts_.count(extension->id()) == 0)
+ if (!enabled_ || pending_requests_.count(extension->id()) == 0)
return NULL; // No action for this extension.
ActiveScriptMap::iterator existing =
@@ -112,13 +126,72 @@ ExtensionAction* ActiveScriptController::GetActionForExtension(
LocationBarController::Action ActiveScriptController::OnClicked(
const Extension* extension) {
- DCHECK(extensions_executing_scripts_.count(extension->id()) > 0);
+ DCHECK(extension);
+ PendingRequestMap::iterator iter =
+ pending_requests_.find(extension->id());
+ DCHECK(iter != pending_requests_.end());
+
+ // Run all pending injections for the given extension.
+ PendingRequestList& list = iter->second;
+ for (PendingRequestList::iterator request = list.begin();
+ request != list.end();
+ ++request) {
+ request->Run();
+ }
+
+ // Remove the extension's pending request entry, and indicate that it is
+ // allowed to run on the current page.
+ pending_requests_.erase(extension->id());
+ permitted_extensions_.insert(extension->id());
not at google - send to devlin 2014/05/15 22:21:44 this code (lines 134...145) has the potential, in
Devlin 2014/05/15 23:52:35 That would indeed be _crazy_ circumstances. But w
+
not at google - send to devlin 2014/05/15 22:21:44 also, TODO grant active-tab-esque permission.
Devlin 2014/05/15 23:52:35 Done.
+ // Inform the location bar that the action is now gone.
not at google - send to devlin 2014/05/15 22:21:44 something to consider in future (just occurred to
Devlin 2014/05/15 23:52:35 Ooh, that sounds like fun...
+ LocationBarController::NotifyChange(web_contents());
+
return LocationBarController::ACTION_NONE;
}
void ActiveScriptController::OnNavigated() {
LogUMA();
- extensions_executing_scripts_.clear();
+ permitted_extensions_.clear();
+ pending_requests_.clear();
+}
+
+void ActiveScriptController::OnNotifyExtensionScriptExecution(
+ const std::string& extension_id,
+ int page_id) {
+ if (!Extension::IdIsValid(extension_id)) {
+ NOTREACHED() << "'" << extension_id << "' is not a valid id.";
+ return;
+ }
+
+ InjectScriptIfHasPermission(
+ extension_id,
+ page_id,
+ base::Closure(base::Bind(&base::DoNothing)));
+}
+
+void ActiveScriptController::AddOrProcessRequest(
+ const Extension* extension,
+ const base::Closure& request) {
+ // If the feature is not enabled, we automatically allow all extensions to
+ // run scripts.
not at google - send to devlin 2014/05/15 22:21:44 how did this get above the RequiresActionForScript
Devlin 2014/05/15 23:52:35 Whoops, good point. Let's fix that... Done.
+ if (!enabled_)
+ permitted_extensions_.insert(extension->id());
+
+ // If the extension does not require permissions, run it immediately.
not at google - send to devlin 2014/05/15 22:21:44 TODO take into account tab-specific permissions
Devlin 2014/05/15 23:52:35 Done. (added comment in .h above permitted_extensi
+ if (!PermissionsData::RequiresActionForScriptExecution(extension) ||
+ permitted_extensions_.count(extension->id())) {
+ request.Run();
+ return;
+ }
+
+ PendingRequestList* list = &pending_requests_[extension->id()];
not at google - send to devlin 2014/05/15 22:21:44 nit: why not just PendingRequestList& list?
Devlin 2014/05/15 23:52:35 Only 'cuz I never see non-const & in chrome. But,
not at google - send to devlin 2014/05/16 00:08:32 indeed.
+ list->push_back(request);
+
+ // If this was the first entry, notify the location bar that there's a new
+ // icon.
+ if (list->size() == 1u)
+ LocationBarController::NotifyChange(web_contents());
}
bool ActiveScriptController::OnMessageReceived(const IPC::Message& message) {
@@ -131,20 +204,10 @@ bool ActiveScriptController::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void ActiveScriptController::OnNotifyExtensionScriptExecution(
- const std::string& extension_id,
- int page_id) {
- if (!Extension::IdIsValid(extension_id)) {
- NOTREACHED() << "'" << extension_id << "' is not a valid id.";
- return;
- }
- NotifyScriptExecuting(extension_id, page_id);
-}
-
void ActiveScriptController::LogUMA() const {
UMA_HISTOGRAM_COUNTS_100(
"Extensions.ActiveScriptController.ShownActiveScriptsOnPage",
- extensions_executing_scripts_.size());
+ pending_requests_.size());
}
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698