1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// Use of this source code is governed by a BSD-style license that can be 3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project// found in the LICENSE file. 4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "chrome/browser/extensions/active_tab_permission_granter.h" 6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "chrome/browser/extensions/active_script_controller.h" 8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "chrome/browser/profiles/profile.h" 9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "content/public/browser/navigation_details.h" 10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "content/public/browser/navigation_entry.h" 11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "content/public/browser/web_contents.h" 12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/browser/extension_registry.h" 13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/common/extension_messages.h" 14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/common/feature_switch.h" 15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/common/permissions/permission_set.h" 16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/common/permissions/permissions_data.h" 17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "extensions/common/user_script.h" 18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "url/gurl.h" 19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectusing content::RenderProcessHost; 21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectusing content::WebContentsObserver; 22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectnamespace extensions { 24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectActiveTabPermissionGranter::ActiveTabPermissionGranter( 26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project content::WebContents* web_contents, 27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int tab_id, 28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project Profile* profile) 29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project : WebContentsObserver(web_contents), 30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project tab_id_(tab_id), 31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project extension_registry_observer_(this) { 32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project extension_registry_observer_.Add(ExtensionRegistry::Get(profile)); 33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectActiveTabPermissionGranter::~ActiveTabPermissionGranter() {} 36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) { 38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (granted_extensions_.Contains(extension->id())) 39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return; 40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project APIPermissionSet new_apis; 42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project URLPatternSet new_hosts; 43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const PermissionsData* permissions_data = extension->permissions_data(); 45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // If the extension requested all-hosts but has had it withheld, we grant it 47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // active tab-style permissions, even if it doesn't have the activeTab 48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // permission in the manifest. 49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (permissions_data->HasAPIPermission(APIPermission::kActiveTab) || 50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project permissions_data->HasWithheldImpliedAllHosts()) { 51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), 52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project web_contents()->GetVisibleURL().GetOrigin()); 53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new_apis.insert(APIPermission::kTab); 54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (permissions_data->HasAPIPermission(APIPermission::kTabCapture)) 57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new_apis.insert(APIPermission::kTabCaptureForTab); 58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!new_apis.empty() || !new_hosts.is_empty()) { 60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project granted_extensions_.Insert(extension); 61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project scoped_refptr<const PermissionSet> new_permissions = 62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new PermissionSet(new_apis, ManifestPermissionSet(), 63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new_hosts, URLPatternSet()); 64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project permissions_data->UpdateTabSpecificPermissions(tab_id_, new_permissions); 65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const content::NavigationEntry* navigation_entry = 66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project web_contents()->GetController().GetVisibleEntry(); 67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (navigation_entry) { 68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project Send(new ExtensionMsg_UpdateTabSpecificPermissions( 69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project navigation_entry->GetURL(), 70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project tab_id_, 71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project extension->id(), 72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project new_hosts)); 73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // If more things ever need to know about this, we should consider making 74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // an observer class. 75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // It's important that this comes after the IPC is sent to the renderer, 76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // so that any tasks executing in the renderer occur after it has the 77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // updated permissions. 78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ActiveScriptController::GetForWebContents(web_contents()) 79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ->OnActiveTabPermissionGranted(extension); 80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ActiveTabPermissionGranter::DidNavigateMainFrame( 85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const content::LoadCommittedDetails& details, 86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const content::FrameNavigateParams& params) { 87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (details.is_in_page) 88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return; 89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project DCHECK(details.is_main_frame); // important: sub-frames don't get granted! 90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // Only clear the granted permissions for cross-origin navigations. 92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // 93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // See http://crbug.com/404243 for why. Currently we only differentiate 94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // between same-origin and cross-origin navigations when the 95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // script-require-action flag is on. It's not clear it's good for general 96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // activeTab consumption (we likely need to build some UI around it first). 97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // However, the scripts-require-action feature is all-but unusable without 98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // this behaviour. 99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (FeatureSwitch::scripts_require_action()->IsEnabled()) { 100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const content::NavigationEntry* navigation_entry = 101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project web_contents()->GetController().GetVisibleEntry(); 102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!navigation_entry || (navigation_entry->GetURL().GetOrigin() != 103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project details.previous_url.GetOrigin())) { 104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ClearActiveExtensionsAndNotify(); 105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else { 107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ClearActiveExtensionsAndNotify(); 108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ActiveTabPermissionGranter::WebContentsDestroyed() { 112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ClearActiveExtensionsAndNotify(); 113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ActiveTabPermissionGranter::OnExtensionUnloaded( 116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project content::BrowserContext* browser_context, 117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const Extension* extension, 118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project UnloadedExtensionInfo::Reason reason) { 119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // Note: don't need to clear the permissions (nor tell the renderer about it) 120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project // because it's being unloaded anyway. 121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project granted_extensions_.Remove(extension->id()); 122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() { 125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (granted_extensions_.is_empty()) 126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return; 127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project std::vector<std::string> extension_ids; 129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for (ExtensionSet::const_iterator it = granted_extensions_.begin(); 131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project it != granted_extensions_.end(); ++it) { 132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project it->get()->permissions_data()->ClearTabSpecificPermissions(tab_id_); 133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project extension_ids.push_back((*it)->id()); 134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project Send(new ExtensionMsg_ClearTabSpecificPermissions(tab_id_, extension_ids)); 137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project granted_extensions_.Clear(); 138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} // namespace extensions 141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project