blob: 215b2ec7f0f91a34a062b9f894ef6020885d95e8 [file] [log] [blame]
[email protected]c333e792012-01-06 16:57:391// 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"
[email protected]76aeb1772012-01-20 22:14:1610#include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h"
[email protected]c333e792012-01-06 16:57:3911#include "chrome/browser/extensions/extension_event_router.h"
[email protected]c333e792012-01-06 16:57:3912#include "chrome/browser/extensions/extension_prefs.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/profiles/profile.h"
[email protected]15f08dd2012-01-27 07:29:4815#include "chrome/common/extensions/api/permissions.h"
[email protected]c333e792012-01-06 16:57:3916#include "chrome/common/chrome_notification_types.h"
17#include "chrome/common/extensions/extension.h"
18#include "chrome/common/extensions/extension_messages.h"
19#include "chrome/common/extensions/extension_permission_set.h"
20#include "content/public/browser/notification_service.h"
21#include "content/public/browser/render_process_host.h"
22
23using content::RenderProcessHost;
[email protected]15f08dd2012-01-27 07:29:4824using extensions::permissions_api_helpers::PackPermissionSet;
[email protected]c333e792012-01-06 16:57:3925
26namespace extensions {
27
28namespace {
29
30const char kOnAdded[] = "permissions.onAdded";
31const char kOnRemoved[] = "permissions.onRemoved";
32
33}
34
35PermissionsUpdater::PermissionsUpdater(Profile* profile)
36 : profile_(profile) {}
37
38PermissionsUpdater::~PermissionsUpdater() {}
39
40void PermissionsUpdater::AddPermissions(
41 const Extension* extension, const ExtensionPermissionSet* permissions) {
42 scoped_refptr<const ExtensionPermissionSet> existing(
43 extension->GetActivePermissions());
44 scoped_refptr<ExtensionPermissionSet> total(
45 ExtensionPermissionSet::CreateUnion(existing, permissions));
46 scoped_refptr<ExtensionPermissionSet> added(
47 ExtensionPermissionSet::CreateDifference(total.get(), existing));
48
49 UpdateActivePermissions(extension, total.get());
50
51 // Update the granted permissions so we don't auto-disable the extension.
52 GrantActivePermissions(extension);
53
54 NotifyPermissionsUpdated(ADDED, extension, added.get());
55}
56
57void PermissionsUpdater::RemovePermissions(
58 const Extension* extension, const ExtensionPermissionSet* permissions) {
59 scoped_refptr<const ExtensionPermissionSet> existing(
60 extension->GetActivePermissions());
61 scoped_refptr<ExtensionPermissionSet> total(
62 ExtensionPermissionSet::CreateDifference(existing, permissions));
63 scoped_refptr<ExtensionPermissionSet> removed(
64 ExtensionPermissionSet::CreateDifference(existing, total.get()));
65
66 // We update the active permissions, and not the granted permissions, because
67 // the extension, not the user, removed the permissions. This allows the
68 // extension to add them again without prompting the user.
69 UpdateActivePermissions(extension, total.get());
70
71 NotifyPermissionsUpdated(REMOVED, extension, removed.get());
72}
73
74void PermissionsUpdater::GrantActivePermissions(const Extension* extension) {
75 CHECK(extension);
76
[email protected]c24fb292012-02-01 22:52:1177 // We only maintain the granted permissions prefs for INTERNAL and LOAD
78 // extensions.
79 if (extension->location() != Extension::LOAD &&
80 extension->location() != Extension::INTERNAL)
[email protected]c333e792012-01-06 16:57:3981 return;
82
83 GetExtensionPrefs()->AddGrantedPermissions(
84 extension->id(), extension->GetActivePermissions());
85}
86
87void PermissionsUpdater::UpdateActivePermissions(
88 const Extension* extension, const ExtensionPermissionSet* permissions) {
89 GetExtensionPrefs()->SetActivePermissions(extension->id(), permissions);
90 extension->SetActivePermissions(permissions);
91}
92
93void PermissionsUpdater::DispatchEvent(
94 const std::string& extension_id,
95 const char* event_name,
96 const ExtensionPermissionSet* changed_permissions) {
97 if (!profile_ || !profile_->GetExtensionEventRouter())
98 return;
99
100 ListValue value;
[email protected]15f08dd2012-01-27 07:29:48101 scoped_ptr<api::permissions::Permissions> permissions =
102 PackPermissionSet(changed_permissions);
103 value.Append(permissions->ToValue());
[email protected]c333e792012-01-06 16:57:39104 std::string json_value;
105 base::JSONWriter::Write(&value, false, &json_value);
106 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
107 extension_id, event_name, json_value, profile_, GURL());
108}
109
110void PermissionsUpdater::NotifyPermissionsUpdated(
111 EventType event_type,
112 const Extension* extension,
113 const ExtensionPermissionSet* changed) {
114 if (!changed || changed->IsEmpty())
115 return;
116
117 UpdatedExtensionPermissionsInfo::Reason reason;
118 const char* event_name = NULL;
119
120 if (event_type == REMOVED) {
121 reason = UpdatedExtensionPermissionsInfo::REMOVED;
122 event_name = kOnRemoved;
123 } else {
124 CHECK_EQ(ADDED, event_type);
125 reason = UpdatedExtensionPermissionsInfo::ADDED;
126 event_name = kOnAdded;
127 }
128
129 // Notify other APIs or interested parties.
130 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo(
131 extension, changed, reason);
132 content::NotificationService::current()->Notify(
133 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
134 content::Source<Profile>(profile_),
135 content::Details<UpdatedExtensionPermissionsInfo>(&info));
136
137 // Send the new permissions to the renderers.
138 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
139 !i.IsAtEnd(); i.Advance()) {
140 RenderProcessHost* host = i.GetCurrentValue();
141 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
142 if (profile_->IsSameProfile(profile))
143 host->Send(new ExtensionMsg_UpdatePermissions(
144 static_cast<int>(reason),
145 extension->id(),
146 changed->apis(),
147 changed->explicit_hosts(),
148 changed->scriptable_hosts()));
149 }
150
151 // Trigger the onAdded and onRemoved events in the extension.
152 DispatchEvent(extension->id(), event_name, changed);
153}
154
155ExtensionPrefs* PermissionsUpdater::GetExtensionPrefs() {
156 return profile_->GetExtensionService()->extension_prefs();
157}
158
159} // namespace extensions