permissions_updater.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/permissions_updater.h" 6 7#include "base/json/json_writer.h" 8#include "base/memory/ref_counted.h" 9#include "base/values.h" 10#include "chrome/browser/chrome_notification_types.h" 11#include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" 12#include "chrome/browser/extensions/event_router.h" 13#include "chrome/browser/extensions/extension_prefs.h" 14#include "chrome/browser/extensions/extension_system.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/common/extensions/api/permissions.h" 17#include "chrome/common/extensions/extension.h" 18#include "chrome/common/extensions/extension_messages.h" 19#include "chrome/common/extensions/permissions/permissions_data.h" 20#include "content/public/browser/notification_observer.h" 21#include "content/public/browser/notification_registrar.h" 22#include "content/public/browser/notification_service.h" 23#include "content/public/browser/render_process_host.h" 24 25using content::RenderProcessHost; 26using extensions::permissions_api_helpers::PackPermissionSet; 27 28namespace extensions { 29 30namespace permissions = api::permissions; 31 32PermissionsUpdater::PermissionsUpdater(Profile* profile) 33 : profile_(profile) {} 34 35PermissionsUpdater::~PermissionsUpdater() {} 36 37void PermissionsUpdater::AddPermissions( 38 const Extension* extension, const PermissionSet* permissions) { 39 scoped_refptr<const PermissionSet> existing( 40 extension->GetActivePermissions()); 41 scoped_refptr<PermissionSet> total( 42 PermissionSet::CreateUnion(existing.get(), permissions)); 43 scoped_refptr<PermissionSet> added( 44 PermissionSet::CreateDifference(total.get(), existing.get())); 45 46 UpdateActivePermissions(extension, total.get()); 47 48 // Update the granted permissions so we don't auto-disable the extension. 49 GrantActivePermissions(extension); 50 51 NotifyPermissionsUpdated(ADDED, extension, added.get()); 52} 53 54void PermissionsUpdater::RemovePermissions( 55 const Extension* extension, const PermissionSet* permissions) { 56 scoped_refptr<const PermissionSet> existing( 57 extension->GetActivePermissions()); 58 scoped_refptr<PermissionSet> total( 59 PermissionSet::CreateDifference(existing.get(), permissions)); 60 scoped_refptr<PermissionSet> removed( 61 PermissionSet::CreateDifference(existing.get(), total.get())); 62 63 // We update the active permissions, and not the granted permissions, because 64 // the extension, not the user, removed the permissions. This allows the 65 // extension to add them again without prompting the user. 66 UpdateActivePermissions(extension, total.get()); 67 68 NotifyPermissionsUpdated(REMOVED, extension, removed.get()); 69} 70 71void PermissionsUpdater::GrantActivePermissions(const Extension* extension) { 72 CHECK(extension); 73 74 // We only maintain the granted permissions prefs for INTERNAL and LOAD 75 // extensions. 76 if (!Manifest::IsUnpackedLocation(extension->location()) && 77 extension->location() != Manifest::INTERNAL) 78 return; 79 80 ExtensionPrefs::Get(profile_)->AddGrantedPermissions( 81 extension->id(), extension->GetActivePermissions().get()); 82} 83 84void PermissionsUpdater::UpdateActivePermissions( 85 const Extension* extension, const PermissionSet* permissions) { 86 ExtensionPrefs::Get(profile_)->SetActivePermissions( 87 extension->id(), permissions); 88 PermissionsData::SetActivePermissions(extension, permissions); 89} 90 91void PermissionsUpdater::DispatchEvent( 92 const std::string& extension_id, 93 const char* event_name, 94 const PermissionSet* changed_permissions) { 95 if (!profile_ || 96 !ExtensionSystem::Get(profile_)->event_router()) 97 return; 98 99 scoped_ptr<base::ListValue> value(new base::ListValue()); 100 scoped_ptr<api::permissions::Permissions> permissions = 101 PackPermissionSet(changed_permissions); 102 value->Append(permissions->ToValue().release()); 103 scoped_ptr<Event> event(new Event(event_name, value.Pass())); 104 event->restrict_to_profile = profile_; 105 ExtensionSystem::Get(profile_)->event_router()-> 106 DispatchEventToExtension(extension_id, event.Pass()); 107} 108 109void PermissionsUpdater::NotifyPermissionsUpdated( 110 EventType event_type, 111 const Extension* extension, 112 const PermissionSet* changed) { 113 if (!changed || changed->IsEmpty()) 114 return; 115 116 UpdatedExtensionPermissionsInfo::Reason reason; 117 const char* event_name = NULL; 118 119 if (event_type == REMOVED) { 120 reason = UpdatedExtensionPermissionsInfo::REMOVED; 121 event_name = permissions::OnRemoved::kEventName; 122 } else { 123 CHECK_EQ(ADDED, event_type); 124 reason = UpdatedExtensionPermissionsInfo::ADDED; 125 event_name = permissions::OnAdded::kEventName; 126 } 127 128 // Notify other APIs or interested parties. 129 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( 130 extension, changed, reason); 131 content::NotificationService::current()->Notify( 132 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, 133 content::Source<Profile>(profile_), 134 content::Details<UpdatedExtensionPermissionsInfo>(&info)); 135 136 // Send the new permissions to the renderers. 137 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 138 !i.IsAtEnd(); i.Advance()) { 139 RenderProcessHost* host = i.GetCurrentValue(); 140 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 141 if (profile_->IsSameProfile(profile)) 142 host->Send(new ExtensionMsg_UpdatePermissions( 143 static_cast<int>(reason), 144 extension->id(), 145 changed->apis(), 146 changed->explicit_hosts(), 147 changed->scriptable_hosts())); 148 } 149 150 // Trigger the onAdded and onRemoved events in the extension. 151 DispatchEvent(extension->id(), event_name, changed); 152} 153 154} // namespace extensions 155