15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/permissions_updater.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/extensions/extension_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/permissions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h" 236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/common/manifest_handlers/permissions_parser.h" 246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/url_pattern.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/url_pattern_set.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderProcessHost; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::permissions_api_helpers::PackPermissionSet; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace permissions = api::permissions; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Returns a set of single origin permissions from |permissions| that match 396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// |bounds|. This is necessary for two reasons: 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// a) single origin active permissions can get filtered out in 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// GetBoundedActivePermissions because they are not recognized as a subset 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// of all-host permissions 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// b) active permissions that do not match any manifest permissions can 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// exist if a manifest permission is dropped 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)URLPatternSet FilterSingleOriginPermissions(const URLPatternSet& permissions, 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const URLPatternSet& bounds) { 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLPatternSet single_origin_permissions; 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (URLPatternSet::const_iterator iter = permissions.begin(); 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) iter != permissions.end(); 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ++iter) { 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (iter->MatchesSingleOrigin() && 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bounds.MatchesURL(GURL(iter->GetAsString()))) { 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) single_origin_permissions.AddPattern(*iter); 546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return single_origin_permissions; 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns a PermissionSet that has the active permissions of the extension, 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// bounded to its current manifest. 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_refptr<const PermissionSet> GetBoundedActivePermissions( 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const Extension* extension, 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const scoped_refptr<const PermissionSet>& active_permissions) { 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the extension has used the optional permissions API, it will have a 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // custom set of active permissions defined in the extension prefs. Here, 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // we update the extension's active permissions based on the prefs. 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!active_permissions.get()) 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return extension->permissions_data()->active_permissions(); 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> required_permissions = 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PermissionsParser::GetRequiredPermissions(extension); 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We restrict the active permissions to be within the bounds defined in the 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // extension's manifest. 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // a) active permissions must be a subset of optional + default permissions 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // b) active permissions must contains all default permissions 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion( 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci required_permissions.get(), 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PermissionsParser::GetOptionalPermissions(extension).get()); 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Make sure the active permissions contain no more than optional + default. 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<PermissionSet> adjusted_active = 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PermissionSet::CreateIntersection(total_permissions.get(), 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_permissions.get()); 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Make sure the active permissions contain the default permissions. 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adjusted_active = PermissionSet::CreateUnion(required_permissions.get(), 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adjusted_active.get()); 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return adjusted_active; 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Divvy up the |url patterns| between those we grant and those we do not. If 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// |withhold_permissions| is false (because the requisite feature is not 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// enabled), no permissions are withheld. 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SegregateUrlPermissions(const URLPatternSet& url_patterns, 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool withhold_permissions, 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet* granted, 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet* withheld) { 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (URLPatternSet::const_iterator iter = url_patterns.begin(); 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != url_patterns.end(); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter) { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (withhold_permissions && iter->ImpliesAllHosts()) 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld->AddPattern(*iter); 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch granted->AddPattern(*iter); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context) 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : browser_context_(browser_context), init_flag_(INIT_FLAG_NONE) { 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context, 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci InitFlag init_flag) 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : browser_context_(browser_context), init_flag_(init_flag) { 1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PermissionsUpdater::~PermissionsUpdater() {} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionsUpdater::AddPermissions( 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, const PermissionSet* permissions) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<const PermissionSet> existing( 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_data()->active_permissions()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<PermissionSet> total( 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PermissionSet::CreateUnion(existing.get(), permissions)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<PermissionSet> added( 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PermissionSet::CreateDifference(total.get(), existing.get())); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetPermissions(extension, total, NULL); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the granted permissions so we don't auto-disable the extension. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GrantActivePermissions(extension); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyPermissionsUpdated(ADDED, extension, added.get()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionsUpdater::RemovePermissions( 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, const PermissionSet* permissions) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<const PermissionSet> existing( 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_data()->active_permissions()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<PermissionSet> total( 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PermissionSet::CreateDifference(existing.get(), permissions)); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<PermissionSet> removed( 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PermissionSet::CreateDifference(existing.get(), total.get())); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We update the active permissions, and not the granted permissions, because 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extension, not the user, removed the permissions. This allows the 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension to add them again without prompting the user. 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetPermissions(extension, total, NULL); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyPermissionsUpdated(REMOVED, extension, removed.get()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PermissionsUpdater::GrantActivePermissions(const Extension* extension) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(extension); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only maintain the granted permissions prefs for INTERNAL and LOAD 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extensions. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Manifest::IsUnpackedLocation(extension->location()) && 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->location() != Manifest::INTERNAL) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ExtensionPrefs::Get(browser_context_)->AddGrantedPermissions( 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->id(), 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_data()->active_permissions().get()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PermissionsUpdater::InitializePermissions(const Extension* extension) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<const PermissionSet> active_permissions(NULL); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<const PermissionSet> bounded_active(NULL); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If |extension| is a transient dummy extension, we do not want to look for 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it in preferences. 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (init_flag_ & INIT_FLAG_TRANSIENT) { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bounded_active = active_permissions = 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension->permissions_data()->active_permissions(); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_permissions = ExtensionPrefs::Get(browser_context_) 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->GetActivePermissions(extension->id()); 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bounded_active = GetBoundedActivePermissions(extension, active_permissions); 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Withhold permissions if the switch applies to this extension. 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Non-transient extensions also must not have the preference to allow 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scripting on all urls. 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool should_withhold_permissions = 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci util::ScriptsMayRequireActionForExtension(extension); 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((init_flag_ & INIT_FLAG_TRANSIENT) == 0) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci should_withhold_permissions &= 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !util::AllowedScriptingOnAllUrls(extension->id(), browser_context_); 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet granted_explicit_hosts; 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet withheld_explicit_hosts; 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SegregateUrlPermissions(bounded_active->explicit_hosts(), 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch should_withhold_permissions, 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &granted_explicit_hosts, 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &withheld_explicit_hosts); 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet granted_scriptable_hosts; 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet withheld_scriptable_hosts; 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SegregateUrlPermissions(bounded_active->scriptable_hosts(), 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch should_withhold_permissions, 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &granted_scriptable_hosts, 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &withheld_scriptable_hosts); 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // After withholding permissions, add back any origins to the active set that 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // may have been lost during the set operations that would have dropped them. 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // For example, the union of <all_urls> and "example.com" is <all_urls>, so 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // we may lose "example.com". However, "example.com" is important once 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // <all_urls> is stripped during withholding. 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (active_permissions.get()) { 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) granted_explicit_hosts.AddPatterns( 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FilterSingleOriginPermissions(active_permissions->explicit_hosts(), 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bounded_active->explicit_hosts())); 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) granted_scriptable_hosts.AddPatterns( 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FilterSingleOriginPermissions(active_permissions->scriptable_hosts(), 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bounded_active->scriptable_hosts())); 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bounded_active = new PermissionSet(bounded_active->apis(), 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bounded_active->manifest_permissions(), 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch granted_explicit_hosts, 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch granted_scriptable_hosts); 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> withheld = 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new PermissionSet(APIPermissionSet(), 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ManifestPermissionSet(), 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld_explicit_hosts, 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld_scriptable_hosts); 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetPermissions(extension, bounded_active, withheld); 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 2356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PermissionsUpdater::WithholdImpliedAllHosts(const Extension* extension) { 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> active = 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data()->active_permissions(); 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> withheld = 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data()->withheld_permissions(); 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet withheld_scriptable = withheld->scriptable_hosts(); 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet active_scriptable; 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SegregateUrlPermissions(active->scriptable_hosts(), 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true, // withhold permissions 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &active_scriptable, 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &withheld_scriptable); 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet withheld_explicit = withheld->explicit_hosts(); 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet active_explicit; 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SegregateUrlPermissions(active->explicit_hosts(), 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true, // withhold permissions 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &active_explicit, 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &withheld_explicit); 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetPermissions(extension, 257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new PermissionSet(active->apis(), 258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch active->manifest_permissions(), 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch active_explicit, 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch active_scriptable), 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new PermissionSet(withheld->apis(), 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld->manifest_permissions(), 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld_explicit, 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld_scriptable)); 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(rdevlin.cronin) We should notify the observers/renderer. 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 2676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PermissionsUpdater::GrantWithheldImpliedAllHosts( 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension) { 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> active = 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data()->active_permissions(); 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> withheld = 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data()->withheld_permissions(); 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Move the all-hosts permission from withheld to active. 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We can cheat a bit here since we know that the only host permission we 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // withhold is allhosts (or something similar enough to it), so we can just 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // grant all withheld host permissions. 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet explicit_hosts; 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet::CreateUnion( 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch active->explicit_hosts(), withheld->explicit_hosts(), &explicit_hosts); 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet scriptable_hosts; 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLPatternSet::CreateUnion(active->scriptable_hosts(), 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld->scriptable_hosts(), 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &scriptable_hosts); 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Since we only withhold host permissions (so far), we know that withheld 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // permissions will be empty. 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetPermissions(extension, 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new PermissionSet(active->apis(), 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch active->manifest_permissions(), 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch explicit_hosts, 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scriptable_hosts), 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new PermissionSet()); 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(rdevlin.cronin) We should notify the observers/renderer. 2966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 2976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PermissionsUpdater::SetPermissions( 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension, 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const scoped_refptr<const PermissionSet>& active, 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<const PermissionSet> withheld) { 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch withheld = withheld.get() ? withheld 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : extension->permissions_data()->withheld_permissions(); 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->permissions_data()->SetPermissions(active, withheld); 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((init_flag_ & INIT_FLAG_TRANSIENT) == 0) { 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionPrefs::Get(browser_context_) 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->SetActivePermissions(extension->id(), active.get()); 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionsUpdater::DispatchEvent( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* event_name, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PermissionSet* changed_permissions) { 3156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EventRouter* event_router = EventRouter::Get(browser_context_); 3166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!event_router) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> value(new base::ListValue()); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<api::permissions::Permissions> permissions = 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PackPermissionSet(changed_permissions); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->Append(permissions->ToValue().release()); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Event> event(new Event(event_name, value.Pass())); 3246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) event->restrict_to_browser_context = browser_context_; 3256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) event_router->DispatchEventToExtension(extension_id, event.Pass()); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionsUpdater::NotifyPermissionsUpdated( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventType event_type, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PermissionSet* changed) { 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK((init_flag_ & INIT_FLAG_TRANSIENT) == 0); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!changed || changed->IsEmpty()) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatedExtensionPermissionsInfo::Reason reason; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* event_name = NULL; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_type == REMOVED) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = UpdatedExtensionPermissionsInfo::REMOVED; 3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) event_name = permissions::OnRemoved::kEventName; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(ADDED, event_type); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = UpdatedExtensionPermissionsInfo::ADDED; 3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) event_name = permissions::OnAdded::kEventName; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify other APIs or interested parties. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension, changed, reason); 3516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(browser_context_); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, 3546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) content::Source<Profile>(profile), 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<UpdatedExtensionPermissionsInfo>(&info)); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ExtensionMsg_UpdatePermissions_Params params; 3586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) params.extension_id = extension->id(); 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch params.active_permissions = ExtensionMsg_PermissionSetStruct( 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *extension->permissions_data()->active_permissions()); 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch params.withheld_permissions = ExtensionMsg_PermissionSetStruct( 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *extension->permissions_data()->withheld_permissions()); 3636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the new permissions to the renderers. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderProcessHost* host = i.GetCurrentValue(); 3686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (profile->IsSameProfile( 3696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Profile::FromBrowserContext(host->GetBrowserContext()))) { 3706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) host->Send(new ExtensionMsg_UpdatePermissions(params)); 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Trigger the onAdded and onRemoved events in the extension. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DispatchEvent(extension->id(), event_name, changed); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 379