1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/active_script_controller.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind_helpers.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/histogram.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/stl_util.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/active_tab_permission_granter.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/extensions/permissions_updater.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/extensions/api/extension_action/action_info.h" 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/navigation_details.h" 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/navigation_entry.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/web_contents.h" 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension.h" 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension_messages.h" 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension_set.h" 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/feature_switch.h" 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/manifest.h" 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ipc/ipc_message_macros.h" 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace extensions { 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns true if the extension should be regarded as a "permitted" extension 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// for the case of metrics. We need this because we only actually withhold 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// permissions if the switch is enabled, but want to record metrics in all 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// cases. 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// "ExtensionWouldHaveHadHostPermissionsWithheldIfSwitchWasOn()" would be 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// more accurate, but too long. 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ShouldRecordExtension(const Extension* extension) { 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return extension->ShouldDisplayInExtensionSettings() && 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !Manifest::IsPolicyLocation(extension->location()) && 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !Manifest::IsComponentLocation(extension->location()) && 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !PermissionsData::CanExecuteScriptEverywhere(extension) && 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data() 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ->active_permissions() 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ->ShouldWarnAllHosts(); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ActiveScriptController::ActiveScriptController( 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebContents* web_contents) 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : content::WebContentsObserver(web_contents), 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()), 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_registry_observer_(this) { 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(web_contents); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_registry_observer_.Add( 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionRegistry::Get(web_contents->GetBrowserContext())); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ActiveScriptController::~ActiveScriptController() { 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LogUMA(); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ActiveScriptController* ActiveScriptController::GetForWebContents( 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebContents* web_contents) { 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!web_contents) 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return tab_helper ? tab_helper->active_script_controller() : NULL; 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ActiveScriptController::OnActiveTabPermissionGranted( 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RunPendingForExtension(extension); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ActiveScriptController::OnAdInjectionDetected( 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::set<std::string>& ad_injectors) { 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We're only interested in data if there are ad injectors detected. 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ad_injectors.empty()) 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t num_preventable_ad_injectors = 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::STLSetIntersection<std::set<std::string> >( 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ad_injectors, permitted_extensions_).size(); 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Extensions.ActiveScriptController.PreventableAdInjectors", 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_preventable_ad_injectors); 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Extensions.ActiveScriptController.UnpreventableAdInjectors", 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ad_injectors.size() - num_preventable_ad_injectors); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ActiveScriptController::AlwaysRunOnVisibleOrigin( 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const Extension* extension) { 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GURL& url = web_contents()->GetVisibleURL(); 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLPatternSet new_explicit_hosts; 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLPatternSet new_scriptable_hosts; 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_refptr<const PermissionSet> withheld_permissions = 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) extension->permissions_data()->withheld_permissions(); 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (withheld_permissions->explicit_hosts().MatchesURL(url)) { 1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new_explicit_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), 1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url.GetOrigin()); 1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (withheld_permissions->scriptable_hosts().MatchesURL(url)) { 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new_scriptable_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url.GetOrigin()); 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_refptr<PermissionSet> new_permissions = 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new PermissionSet(APIPermissionSet(), 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ManifestPermissionSet(), 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new_explicit_hosts, 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new_scriptable_hosts); 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Update permissions for the session. This adds |new_permissions| to active 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // permissions and granted permissions. 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // TODO(devlin): Make sure that the permission is removed from 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // withheld_permissions if appropriate. 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PermissionsUpdater(web_contents()->GetBrowserContext()) 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .AddPermissions(extension, new_permissions.get()); 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Allow current tab to run injection. 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnClicked(extension); 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ActiveScriptController::OnClicked(const Extension* extension) { 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(ContainsKey(pending_requests_, extension->id())); 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RunPendingForExtension(extension); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActiveScriptController::WantsToRun(const Extension* extension) { 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return enabled_ && pending_requests_.count(extension->id()) > 0; 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 149116680a4aac90f2aa7413d9095a592090648e557Ben MurdochPermissionsData::AccessType 150116680a4aac90f2aa7413d9095a592090648e557Ben MurdochActiveScriptController::RequiresUserConsentForScriptInjection( 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension, 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UserScript::InjectionType type) { 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(extension); 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the feature is not enabled, we automatically allow all extensions to 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // run scripts. 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!enabled_) 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch permitted_extensions_.insert(extension->id()); 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Allow the extension if it's been explicitly granted permission. 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (permitted_extensions_.count(extension->id()) > 0) 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return PermissionsData::ACCESS_ALLOWED; 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL url = web_contents()->GetVisibleURL(); 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int tab_id = SessionTabHelper::IdForTab(web_contents()); 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (type) { 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case UserScript::CONTENT_SCRIPT: 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return extension->permissions_data()->GetContentScriptAccess( 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension, url, url, tab_id, -1, NULL); 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case UserScript::PROGRAMMATIC_SCRIPT: 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return extension->permissions_data()->GetPageAccess( 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension, url, url, tab_id, -1, NULL); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NOTREACHED(); 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return PermissionsData::ACCESS_DENIED; 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ActiveScriptController::RequestScriptInjection( 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension, 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::Closure& callback) { 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(extension); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PendingRequestList& list = pending_requests_[extension->id()]; 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch list.push_back(callback); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If this was the first entry, notify the location bar that there's a new 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // icon. 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (list.size() == 1u) { 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyPageActionsChanged(web_contents()); 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ActiveScriptController::RunPendingForExtension( 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(extension); 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NavigationEntry* visible_entry = 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) web_contents()->GetController().GetVisibleEntry(); 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Refuse to run if there's no visible entry, because we have no idea of 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // determining if it's the proper page. This should rarely, if ever, happen. 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!visible_entry) 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We add this to the list of permitted extensions and erase pending entries 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // *before* running them to guard against the crazy case where running the 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // callbacks adds more entries. 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) permitted_extensions_.insert(extension->id()); 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PendingRequestMap::iterator iter = pending_requests_.find(extension->id()); 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (iter == pending_requests_.end()) 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PendingRequestList requests; 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter->second.swap(requests); 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_requests_.erase(extension->id()); 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Clicking to run the extension counts as granting it permission to run on 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the given tab. 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The extension may already have active tab at this point, but granting 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // it twice is essentially a no-op. 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TabHelper::FromWebContents(web_contents())-> 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) active_tab_permission_granter()->GrantIfRequested(extension); 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Run all pending injections for the given extension. 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (PendingRequestList::iterator request = requests.begin(); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) request != requests.end(); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++request) { 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request->Run(); 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Inform the location bar that the action is now gone. 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyPageActionsChanged(web_contents()); 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ActiveScriptController::OnRequestScriptInjectionPermission( 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& extension_id, 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UserScript::InjectionType script_type, 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int64 request_id) { 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!crx_file::id_util::IdIsValid(extension_id)) { 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED() << "'" << extension_id << "' is not a valid id."; 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension = 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionRegistry::Get(web_contents()->GetBrowserContext()) 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ->enabled_extensions().GetByID(extension_id); 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We shouldn't allow extensions which are no longer enabled to run any 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // scripts. Ignore the request. 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!extension) 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If the request id is -1, that signals that the content script has already 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ran (because this feature is not enabled). Add the extension to the list of 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // permitted extensions (for metrics), and return immediately. 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (request_id == -1) { 258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ShouldRecordExtension(extension)) { 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!enabled_); 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch permitted_extensions_.insert(extension->id()); 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (RequiresUserConsentForScriptInjection(extension, script_type)) { 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case PermissionsData::ACCESS_ALLOWED: 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PermitScriptInjection(request_id); 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case PermissionsData::ACCESS_WITHHELD: 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This base::Unretained() is safe, because the callback is only invoked 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // by this object. 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RequestScriptInjection( 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension, 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&ActiveScriptController::PermitScriptInjection, 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(this), 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request_id)); 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case PermissionsData::ACCESS_DENIED: 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We should usually only get a "deny access" if the page changed (as the 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // renderer wouldn't have requested permission if the answer was always 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // "no"). Just let the request fizzle and die. 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ActiveScriptController::PermitScriptInjection(int64 request_id) { 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This only sends the response to the renderer - the process of adding the 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // extension to the list of |permitted_extensions_| is done elsewhere. 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::RenderViewHost* render_view_host = 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) web_contents()->GetRenderViewHost(); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (render_view_host) { 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch render_view_host->Send(new ExtensionMsg_PermitScriptInjection( 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch render_view_host->GetRoutingID(), request_id)); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ActiveScriptController::LogUMA() const { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Extensions.ActiveScriptController.ShownActiveScriptsOnPage", 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_requests_.size()); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We only log the permitted extensions metric if the feature is enabled, 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // because otherwise the data will be boring (100% allowed). 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (enabled_) { 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Extensions.ActiveScriptController.PermittedExtensions", 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) permitted_extensions_.size()); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Extensions.ActiveScriptController.DeniedExtensions", 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_requests_.size()); 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActiveScriptController::OnMessageReceived(const IPC::Message& message) { 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool handled = true; 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_BEGIN_MESSAGE_MAP(ActiveScriptController, message) 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestScriptInjectionPermission, 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnRequestScriptInjectionPermission) 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_UNHANDLED(handled = false) 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_END_MESSAGE_MAP() 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return handled; 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ActiveScriptController::DidNavigateMainFrame( 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const content::LoadCommittedDetails& details, 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const content::FrameNavigateParams& params) { 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (details.is_in_page) 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogUMA(); 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci permitted_extensions_.clear(); 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_requests_.clear(); 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ActiveScriptController::OnExtensionUnloaded( 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::BrowserContext* browser_context, 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension, 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UnloadedExtensionInfo::Reason reason) { 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PendingRequestMap::iterator iter = pending_requests_.find(extension->id()); 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (iter != pending_requests_.end()) { 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_requests_.erase(iter); 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionActionAPI::Get(web_contents()->GetBrowserContext())-> 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyPageActionsChanged(web_contents()); 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace extensions 348