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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/active_script_controller.h" 5 #include "chrome/browser/extensions/active_script_controller.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
7 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
8 #include "base/stl_util.h" 10 #include "base/stl_util.h"
9 #include "chrome/browser/extensions/extension_action.h" 11 #include "chrome/browser/extensions/extension_action.h"
10 #include "chrome/browser/extensions/location_bar_controller.h" 12 #include "chrome/browser/extensions/location_bar_controller.h"
11 #include "chrome/browser/extensions/tab_helper.h" 13 #include "chrome/browser/extensions/tab_helper.h"
12 #include "chrome/common/extensions/api/extension_action/action_info.h" 14 #include "chrome/common/extensions/api/extension_action/action_info.h"
13 #include "content/public/browser/navigation_controller.h" 15 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/navigation_entry.h" 16 #include "content/public/browser/navigation_entry.h"
17 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h" 18 #include "content/public/browser/web_contents.h"
16 #include "extensions/browser/extension_registry.h" 19 #include "extensions/browser/extension_registry.h"
17 #include "extensions/common/extension.h" 20 #include "extensions/common/extension.h"
18 #include "extensions/common/extension_messages.h" 21 #include "extensions/common/extension_messages.h"
19 #include "extensions/common/extension_set.h" 22 #include "extensions/common/extension_set.h"
20 #include "extensions/common/feature_switch.h" 23 #include "extensions/common/feature_switch.h"
21 #include "extensions/common/permissions/permissions_data.h" 24 #include "extensions/common/permissions/permissions_data.h"
22 #include "ipc/ipc_message_macros.h" 25 #include "ipc/ipc_message_macros.h"
23 26
24 namespace extensions { 27 namespace extensions {
25 28
26 ActiveScriptController::ActiveScriptController( 29 ActiveScriptController::ActiveScriptController(
27 content::WebContents* web_contents) 30 content::WebContents* web_contents)
28 : content::WebContentsObserver(web_contents), 31 : content::WebContentsObserver(web_contents),
29 enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()) { 32 enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()),
33 extension_registry_(NULL) {
34 CHECK(web_contents);
35 extension_registry_ =
36 ExtensionRegistry::Get(web_contents->GetBrowserContext());
30 } 37 }
31 38
32 ActiveScriptController::~ActiveScriptController() { 39 ActiveScriptController::~ActiveScriptController() {
33 LogUMA(); 40 LogUMA();
34 } 41 }
35 42
36 // static 43 // static
37 ActiveScriptController* ActiveScriptController::GetForWebContents( 44 ActiveScriptController* ActiveScriptController::GetForWebContents(
38 content::WebContents* web_contents) { 45 content::WebContents* web_contents) {
39 if (!web_contents) 46 if (!web_contents)
40 return NULL; 47 return NULL;
41 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); 48 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
42 if (!tab_helper) 49 if (!tab_helper)
43 return NULL; 50 return NULL;
44 LocationBarController* location_bar_controller = 51 LocationBarController* location_bar_controller =
45 tab_helper->location_bar_controller(); 52 tab_helper->location_bar_controller();
46 // This should never be NULL. 53 // This should never be NULL.
47 DCHECK(location_bar_controller); 54 DCHECK(location_bar_controller);
48 return location_bar_controller->active_script_controller(); 55 return location_bar_controller->active_script_controller();
49 } 56 }
50 57
51 void ActiveScriptController::NotifyScriptExecuting( 58 void ActiveScriptController::GetPermissionForInjection(
52 const std::string& extension_id, int page_id) { 59 const std::string& extension_id,
60 int page_id,
61 scoped_ptr<const base::Closure> callback) {
53 content::NavigationEntry* visible_entry = 62 content::NavigationEntry* visible_entry =
54 web_contents()->GetController().GetVisibleEntry(); 63 web_contents()->GetController().GetVisibleEntry();
55 if (!visible_entry || 64 if (!visible_entry || visible_entry->GetPageID() != page_id)
56 extensions_executing_scripts_.count(extension_id) ||
57 visible_entry->GetPageID() != page_id) {
58 return; 65 return;
59 }
60 66
61 const Extension* extension = 67 const Extension* extension =
62 ExtensionRegistry::Get(web_contents()->GetBrowserContext()) 68 extension_registry_->enabled_extensions().GetByID(extension_id);
not at google - send to devlin 2014/05/15 00:12:36 storing extension_registry_ seems a little inconve
Devlin 2014/05/15 17:45:59 Yeah, you're right. I used to use it more, but I
63 ->enabled_extensions().GetByID(extension_id); 69 if (!extension)
64 if (extension && 70 return;
65 PermissionsData::RequiresActionForScriptExecution(extension)) { 71
66 extensions_executing_scripts_.insert(extension_id); 72 AddOrProcessRequest(extension, callback.Pass());
67 LocationBarController::NotifyChange(web_contents());
68 }
69 } 73 }
70 74
71 void ActiveScriptController::OnAdInjectionDetected( 75 void ActiveScriptController::OnAdInjectionDetected(
72 const std::vector<std::string> ad_injectors) { 76 const std::vector<std::string> ad_injectors) {
73 size_t num_preventable_ad_injectors = 77 size_t num_preventable_ad_injectors =
74 base::STLSetIntersection<std::set<std::string> >( 78 base::STLSetIntersection<std::set<std::string> >(
75 ad_injectors, extensions_executing_scripts_).size(); 79 ad_injectors, requesting_extensions_).size();
not at google - send to devlin 2014/05/15 00:12:36 we should also measure how many were run
Devlin 2014/05/15 17:45:59 Done.
76 80
77 UMA_HISTOGRAM_COUNTS_100( 81 UMA_HISTOGRAM_COUNTS_100(
78 "Extensions.ActiveScriptController.PreventableAdInjectors", 82 "Extensions.ActiveScriptController.PreventableAdInjectors",
79 num_preventable_ad_injectors); 83 num_preventable_ad_injectors);
80 UMA_HISTOGRAM_COUNTS_100( 84 UMA_HISTOGRAM_COUNTS_100(
81 "Extensions.ActiveScriptController.PreventableAdInjectors", 85 "Extensions.ActiveScriptController.PreventableAdInjectors",
82 ad_injectors.size() - num_preventable_ad_injectors); 86 ad_injectors.size() - num_preventable_ad_injectors);
83 } 87 }
84 88
85 ExtensionAction* ActiveScriptController::GetActionForExtension( 89 ExtensionAction* ActiveScriptController::GetActionForExtension(
86 const Extension* extension) { 90 const Extension* extension) {
87 if (!enabled_ || extensions_executing_scripts_.count(extension->id()) == 0) 91 if (!enabled_ || pending_requests_.count(extension->id()) == 0)
88 return NULL; // No action for this extension. 92 return NULL; // No action for this extension.
89 93
90 ActiveScriptMap::iterator existing = 94 ActiveScriptMap::iterator existing =
91 active_script_actions_.find(extension->id()); 95 active_script_actions_.find(extension->id());
92 if (existing != active_script_actions_.end()) 96 if (existing != active_script_actions_.end())
93 return existing->second.get(); 97 return existing->second.get();
94 98
95 linked_ptr<ExtensionAction> action(new ExtensionAction( 99 linked_ptr<ExtensionAction> action(new ExtensionAction(
96 extension->id(), ActionInfo::TYPE_PAGE, ActionInfo())); 100 extension->id(), ActionInfo::TYPE_PAGE, ActionInfo()));
97 action->SetTitle(ExtensionAction::kDefaultTabId, extension->name()); 101 action->SetTitle(ExtensionAction::kDefaultTabId, extension->name());
98 action->SetIsVisible(ExtensionAction::kDefaultTabId, true); 102 action->SetIsVisible(ExtensionAction::kDefaultTabId, true);
99 103
100 const ActionInfo* action_info = ActionInfo::GetPageActionInfo(extension); 104 const ActionInfo* action_info = ActionInfo::GetPageActionInfo(extension);
101 if (!action_info) 105 if (!action_info)
102 action_info = ActionInfo::GetBrowserActionInfo(extension); 106 action_info = ActionInfo::GetBrowserActionInfo(extension);
103 107
104 if (action_info && !action_info->default_icon.empty()) { 108 if (action_info && !action_info->default_icon.empty()) {
105 action->set_default_icon( 109 action->set_default_icon(
106 make_scoped_ptr(new ExtensionIconSet(action_info->default_icon))); 110 make_scoped_ptr(new ExtensionIconSet(action_info->default_icon)));
107 } 111 }
108 112
109 active_script_actions_[extension->id()] = action; 113 active_script_actions_[extension->id()] = action;
110 return action.get(); 114 return action.get();
111 } 115 }
112 116
113 LocationBarController::Action ActiveScriptController::OnClicked( 117 LocationBarController::Action ActiveScriptController::OnClicked(
114 const Extension* extension) { 118 const Extension* extension) {
115 DCHECK(extensions_executing_scripts_.count(extension->id()) > 0); 119 DCHECK(extension);
120 PendingRequestMap::iterator iter =
121 pending_requests_.find(extension->id());
122 DCHECK(iter != pending_requests_.end());
123
124 // Run all pending injections for the given extension.
125 PendingRequestList& list = iter->second;
126 for (PendingRequestList::iterator request = list.begin();
127 request != list.end();
128 ++request) {
129 (*request)->Run();
130 }
131 pending_requests_.erase(extension->id());
132
133 // Inform the location bar that the action is now gone.
134 LocationBarController::NotifyChange(web_contents());
135
116 return LocationBarController::ACTION_NONE; 136 return LocationBarController::ACTION_NONE;
117 } 137 }
118 138
119 void ActiveScriptController::OnNavigated() { 139 void ActiveScriptController::OnNavigated() {
120 LogUMA(); 140 LogUMA();
121 extensions_executing_scripts_.clear(); 141 requesting_extensions_.clear();
142 pending_requests_.clear();
143 }
144
145 void ActiveScriptController::OnNotifyExtensionScriptExecution(
146 const std::string& extension_id,
147 int page_id) {
148 if (!Extension::IdIsValid(extension_id)) {
149 NOTREACHED() << "'" << extension_id << "' is not a valid id.";
150 return;
151 }
152
153 GetPermissionForInjection(
154 extension_id,
155 page_id,
156 scoped_ptr<const base::Closure>(
157 new base::Closure(base::Bind(&base::DoNothing))));
not at google - send to devlin 2014/05/15 00:12:36 fwiw you might be able to use make_scoped_ptr() he
Devlin 2014/05/15 17:45:59 Nope, compile error. Tried it. But moot anyway.
158 }
159
160 void ActiveScriptController::AddOrProcessRequest(
161 const Extension* extension,
162 scoped_ptr<const base::Closure> request) {
163 // If the extension does not require permissions, run it immediately.
164 if (!PermissionsData::RequiresActionForScriptExecution(extension)) {
165 request->Run();
166 return;
167 }
168
not at google - send to devlin 2014/05/15 00:12:36 if our permissions infrastructure is working we al
Devlin 2014/05/15 17:45:59 Done.
169 // Track the extension as having requested permission.
170 requesting_extensions_.insert(extension->id());
171
172 // If the feature is not enabled, run the script.
173 if (!enabled_) {
174 request->Run();
175 return;
176 }
177
178 PendingRequestList* list = &pending_requests_[extension->id()];
179 list->push_back(make_linked_ptr(request.release()));
180
181 // If this was the first entry, notify the location bar that there's a new
182 // icon.
183 if (list->size() == 1u)
184 LocationBarController::NotifyChange(web_contents());
185
not at google - send to devlin 2014/05/15 00:12:36 no blank line
Devlin 2014/05/15 17:45:59 Done.
122 } 186 }
123 187
124 bool ActiveScriptController::OnMessageReceived(const IPC::Message& message) { 188 bool ActiveScriptController::OnMessageReceived(const IPC::Message& message) {
125 bool handled = true; 189 bool handled = true;
126 IPC_BEGIN_MESSAGE_MAP(ActiveScriptController, message) 190 IPC_BEGIN_MESSAGE_MAP(ActiveScriptController, message)
127 IPC_MESSAGE_HANDLER(ExtensionHostMsg_NotifyExtensionScriptExecution, 191 IPC_MESSAGE_HANDLER(ExtensionHostMsg_NotifyExtensionScriptExecution,
128 OnNotifyExtensionScriptExecution) 192 OnNotifyExtensionScriptExecution)
129 IPC_MESSAGE_UNHANDLED(handled = false) 193 IPC_MESSAGE_UNHANDLED(handled = false)
130 IPC_END_MESSAGE_MAP() 194 IPC_END_MESSAGE_MAP()
131 return handled; 195 return handled;
132 } 196 }
133 197
134 void ActiveScriptController::OnNotifyExtensionScriptExecution(
135 const std::string& extension_id,
136 int page_id) {
137 if (!Extension::IdIsValid(extension_id)) {
138 NOTREACHED() << "'" << extension_id << "' is not a valid id.";
139 return;
140 }
141 NotifyScriptExecuting(extension_id, page_id);
142 }
143
144 void ActiveScriptController::LogUMA() const { 198 void ActiveScriptController::LogUMA() const {
145 UMA_HISTOGRAM_COUNTS_100( 199 UMA_HISTOGRAM_COUNTS_100(
146 "Extensions.ActiveScriptController.ShownActiveScriptsOnPage", 200 "Extensions.ActiveScriptController.ShownActiveScriptsOnPage",
147 extensions_executing_scripts_.size()); 201 pending_requests_.size());
148 } 202 }
149 203
150 } // namespace extensions 204 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698