| OLD | NEW |
| 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" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 extension->permissions_data() | 53 extension->permissions_data() |
| 54 ->active_permissions() | 54 ->active_permissions() |
| 55 ->ShouldWarnAllHosts(); | 55 ->ShouldWarnAllHosts(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 } // namespace | 58 } // namespace |
| 59 | 59 |
| 60 ActiveScriptController::ActiveScriptController( | 60 ActiveScriptController::ActiveScriptController( |
| 61 content::WebContents* web_contents) | 61 content::WebContents* web_contents) |
| 62 : content::WebContentsObserver(web_contents), | 62 : content::WebContentsObserver(web_contents), |
| 63 browser_context_(web_contents->GetBrowserContext()), |
| 63 enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()), | 64 enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()), |
| 64 extension_registry_observer_(this) { | 65 extension_registry_observer_(this) { |
| 65 CHECK(web_contents); | 66 CHECK(web_contents); |
| 66 extension_registry_observer_.Add( | 67 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
| 67 ExtensionRegistry::Get(web_contents->GetBrowserContext())); | |
| 68 } | 68 } |
| 69 | 69 |
| 70 ActiveScriptController::~ActiveScriptController() { | 70 ActiveScriptController::~ActiveScriptController() { |
| 71 LogUMA(); | 71 LogUMA(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 // static | 74 // static |
| 75 ActiveScriptController* ActiveScriptController::GetForWebContents( | 75 ActiveScriptController* ActiveScriptController::GetForWebContents( |
| 76 content::WebContents* web_contents) { | 76 content::WebContents* web_contents) { |
| 77 if (!web_contents) | 77 if (!web_contents) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 scoped_refptr<PermissionSet> new_permissions = | 123 scoped_refptr<PermissionSet> new_permissions = |
| 124 new PermissionSet(APIPermissionSet(), | 124 new PermissionSet(APIPermissionSet(), |
| 125 ManifestPermissionSet(), | 125 ManifestPermissionSet(), |
| 126 new_explicit_hosts, | 126 new_explicit_hosts, |
| 127 new_scriptable_hosts); | 127 new_scriptable_hosts); |
| 128 | 128 |
| 129 // Update permissions for the session. This adds |new_permissions| to active | 129 // Update permissions for the session. This adds |new_permissions| to active |
| 130 // permissions and granted permissions. | 130 // permissions and granted permissions. |
| 131 // TODO(devlin): Make sure that the permission is removed from | 131 // TODO(devlin): Make sure that the permission is removed from |
| 132 // withheld_permissions if appropriate. | 132 // withheld_permissions if appropriate. |
| 133 PermissionsUpdater(web_contents()->GetBrowserContext()) | 133 PermissionsUpdater(browser_context_).AddPermissions(extension, |
| 134 .AddPermissions(extension, new_permissions.get()); | 134 new_permissions.get()); |
| 135 | 135 |
| 136 // Allow current tab to run injection. | 136 // Allow current tab to run injection. |
| 137 OnClicked(extension); | 137 OnClicked(extension); |
| 138 } | 138 } |
| 139 | 139 |
| 140 void ActiveScriptController::OnClicked(const Extension* extension) { | 140 void ActiveScriptController::OnClicked(const Extension* extension) { |
| 141 DCHECK(ContainsKey(pending_requests_, extension->id())); | 141 DCHECK(ContainsKey(pending_requests_, extension->id())); |
| 142 RunPendingForExtension(extension); | 142 RunPendingForExtension(extension); |
| 143 } | 143 } |
| 144 | 144 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 return PermissionsData::ACCESS_DENIED; | 176 return PermissionsData::ACCESS_DENIED; |
| 177 } | 177 } |
| 178 | 178 |
| 179 void ActiveScriptController::RequestScriptInjection( | 179 void ActiveScriptController::RequestScriptInjection( |
| 180 const Extension* extension, | 180 const Extension* extension, |
| 181 const base::Closure& callback) { | 181 const base::Closure& callback) { |
| 182 CHECK(extension); | 182 CHECK(extension); |
| 183 PendingRequestList& list = pending_requests_[extension->id()]; | 183 PendingRequestList& list = pending_requests_[extension->id()]; |
| 184 list.push_back(callback); | 184 list.push_back(callback); |
| 185 | 185 |
| 186 // If this was the first entry, notify the location bar that there's a new | 186 // If this was the first entry, we need to notify that a new extension wants |
| 187 // icon. | 187 // to run. |
| 188 if (list.size() == 1u) { | 188 if (list.size() == 1u) |
| 189 ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> | 189 NotifyChange(extension); |
| 190 NotifyPageActionsChanged(web_contents()); | |
| 191 } | |
| 192 } | 190 } |
| 193 | 191 |
| 194 void ActiveScriptController::RunPendingForExtension( | 192 void ActiveScriptController::RunPendingForExtension( |
| 195 const Extension* extension) { | 193 const Extension* extension) { |
| 196 DCHECK(extension); | 194 DCHECK(extension); |
| 197 | 195 |
| 198 content::NavigationEntry* visible_entry = | 196 content::NavigationEntry* visible_entry = |
| 199 web_contents()->GetController().GetVisibleEntry(); | 197 web_contents()->GetController().GetVisibleEntry(); |
| 200 // Refuse to run if there's no visible entry, because we have no idea of | 198 // Refuse to run if there's no visible entry, because we have no idea of |
| 201 // determining if it's the proper page. This should rarely, if ever, happen. | 199 // determining if it's the proper page. This should rarely, if ever, happen. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 222 TabHelper::FromWebContents(web_contents())-> | 220 TabHelper::FromWebContents(web_contents())-> |
| 223 active_tab_permission_granter()->GrantIfRequested(extension); | 221 active_tab_permission_granter()->GrantIfRequested(extension); |
| 224 | 222 |
| 225 // Run all pending injections for the given extension. | 223 // Run all pending injections for the given extension. |
| 226 for (PendingRequestList::iterator request = requests.begin(); | 224 for (PendingRequestList::iterator request = requests.begin(); |
| 227 request != requests.end(); | 225 request != requests.end(); |
| 228 ++request) { | 226 ++request) { |
| 229 request->Run(); | 227 request->Run(); |
| 230 } | 228 } |
| 231 | 229 |
| 232 // Inform the location bar that the action is now gone. | 230 // The extension ran, so we need to update the ExtensionActionAPI that we no |
| 233 ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> | 231 // longer want to act. |
| 234 NotifyPageActionsChanged(web_contents()); | 232 NotifyChange(extension); |
| 235 } | 233 } |
| 236 | 234 |
| 237 void ActiveScriptController::OnRequestScriptInjectionPermission( | 235 void ActiveScriptController::OnRequestScriptInjectionPermission( |
| 238 const std::string& extension_id, | 236 const std::string& extension_id, |
| 239 UserScript::InjectionType script_type, | 237 UserScript::InjectionType script_type, |
| 240 int64 request_id) { | 238 int64 request_id) { |
| 241 if (!crx_file::id_util::IdIsValid(extension_id)) { | 239 if (!crx_file::id_util::IdIsValid(extension_id)) { |
| 242 NOTREACHED() << "'" << extension_id << "' is not a valid id."; | 240 NOTREACHED() << "'" << extension_id << "' is not a valid id."; |
| 243 return; | 241 return; |
| 244 } | 242 } |
| 245 | 243 |
| 246 const Extension* extension = | 244 const Extension* extension = |
| 247 ExtensionRegistry::Get(web_contents()->GetBrowserContext()) | 245 ExtensionRegistry::Get(browser_context_) |
| 248 ->enabled_extensions().GetByID(extension_id); | 246 ->enabled_extensions().GetByID(extension_id); |
| 249 // We shouldn't allow extensions which are no longer enabled to run any | 247 // We shouldn't allow extensions which are no longer enabled to run any |
| 250 // scripts. Ignore the request. | 248 // scripts. Ignore the request. |
| 251 if (!extension) | 249 if (!extension) |
| 252 return; | 250 return; |
| 253 | 251 |
| 254 // If the request id is -1, that signals that the content script has already | 252 // If the request id is -1, that signals that the content script has already |
| 255 // ran (because this feature is not enabled). Add the extension to the list of | 253 // ran (because this feature is not enabled). Add the extension to the list of |
| 256 // permitted extensions (for metrics), and return immediately. | 254 // permitted extensions (for metrics), and return immediately. |
| 257 if (request_id == -1) { | 255 if (request_id == -1) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 287 // This only sends the response to the renderer - the process of adding the | 285 // This only sends the response to the renderer - the process of adding the |
| 288 // extension to the list of |permitted_extensions_| is done elsewhere. | 286 // extension to the list of |permitted_extensions_| is done elsewhere. |
| 289 content::RenderViewHost* render_view_host = | 287 content::RenderViewHost* render_view_host = |
| 290 web_contents()->GetRenderViewHost(); | 288 web_contents()->GetRenderViewHost(); |
| 291 if (render_view_host) { | 289 if (render_view_host) { |
| 292 render_view_host->Send(new ExtensionMsg_PermitScriptInjection( | 290 render_view_host->Send(new ExtensionMsg_PermitScriptInjection( |
| 293 render_view_host->GetRoutingID(), request_id)); | 291 render_view_host->GetRoutingID(), request_id)); |
| 294 } | 292 } |
| 295 } | 293 } |
| 296 | 294 |
| 295 void ActiveScriptController::NotifyChange(const Extension* extension) { |
| 296 ExtensionActionAPI* extension_action_api = |
| 297 ExtensionActionAPI::Get(browser_context_); |
| 298 ExtensionAction* extension_action = |
| 299 ExtensionActionManager::Get(browser_context_)-> |
| 300 GetExtensionAction(*extension); |
| 301 // If the extension has an action, we need to notify that it's updated. |
| 302 if (extension_action) { |
| 303 extension_action_api->NotifyChange( |
| 304 extension_action, web_contents(), browser_context_); |
| 305 } |
| 306 |
| 307 // We also notify that page actions may have changed. |
| 308 extension_action_api->NotifyPageActionsChanged(web_contents()); |
| 309 } |
| 310 |
| 297 void ActiveScriptController::LogUMA() const { | 311 void ActiveScriptController::LogUMA() const { |
| 298 UMA_HISTOGRAM_COUNTS_100( | 312 UMA_HISTOGRAM_COUNTS_100( |
| 299 "Extensions.ActiveScriptController.ShownActiveScriptsOnPage", | 313 "Extensions.ActiveScriptController.ShownActiveScriptsOnPage", |
| 300 pending_requests_.size()); | 314 pending_requests_.size()); |
| 301 | 315 |
| 302 // We only log the permitted extensions metric if the feature is enabled, | 316 // We only log the permitted extensions metric if the feature is enabled, |
| 303 // because otherwise the data will be boring (100% allowed). | 317 // because otherwise the data will be boring (100% allowed). |
| 304 if (enabled_) { | 318 if (enabled_) { |
| 305 UMA_HISTOGRAM_COUNTS_100( | 319 UMA_HISTOGRAM_COUNTS_100( |
| 306 "Extensions.ActiveScriptController.PermittedExtensions", | 320 "Extensions.ActiveScriptController.PermittedExtensions", |
| (...skipping 25 matching lines...) Expand all Loading... |
| 332 pending_requests_.clear(); | 346 pending_requests_.clear(); |
| 333 } | 347 } |
| 334 | 348 |
| 335 void ActiveScriptController::OnExtensionUnloaded( | 349 void ActiveScriptController::OnExtensionUnloaded( |
| 336 content::BrowserContext* browser_context, | 350 content::BrowserContext* browser_context, |
| 337 const Extension* extension, | 351 const Extension* extension, |
| 338 UnloadedExtensionInfo::Reason reason) { | 352 UnloadedExtensionInfo::Reason reason) { |
| 339 PendingRequestMap::iterator iter = pending_requests_.find(extension->id()); | 353 PendingRequestMap::iterator iter = pending_requests_.find(extension->id()); |
| 340 if (iter != pending_requests_.end()) { | 354 if (iter != pending_requests_.end()) { |
| 341 pending_requests_.erase(iter); | 355 pending_requests_.erase(iter); |
| 342 ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> | 356 ExtensionActionAPI::Get(browser_context_)-> |
| 343 NotifyPageActionsChanged(web_contents()); | 357 NotifyPageActionsChanged(web_contents()); |
| 344 } | 358 } |
| 345 } | 359 } |
| 346 | 360 |
| 347 } // namespace extensions | 361 } // namespace extensions |
| OLD | NEW |