EME test page application.
[chromium-blink-merge.git] / chrome / browser / extensions / permissions_updater.cc
blobb98bd0cfc09286d544f3af80024d44e6ecccf184
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.
5 #include "chrome/browser/extensions/permissions_updater.h"
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/profiles/profile.h"
13 #include "chrome/common/extensions/api/permissions.h"
14 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_messages.h"
22 #include "extensions/common/permissions/permissions_data.h"
24 using content::RenderProcessHost;
25 using extensions::permissions_api_helpers::PackPermissionSet;
27 namespace extensions {
29 namespace permissions = api::permissions;
31 PermissionsUpdater::PermissionsUpdater(Profile* profile)
32 : profile_(profile) {}
34 PermissionsUpdater::~PermissionsUpdater() {}
36 void PermissionsUpdater::AddPermissions(
37 const Extension* extension, const PermissionSet* permissions) {
38 scoped_refptr<const PermissionSet> existing(
39 extension->GetActivePermissions());
40 scoped_refptr<PermissionSet> total(
41 PermissionSet::CreateUnion(existing.get(), permissions));
42 scoped_refptr<PermissionSet> added(
43 PermissionSet::CreateDifference(total.get(), existing.get()));
45 UpdateActivePermissions(extension, total.get());
47 // Update the granted permissions so we don't auto-disable the extension.
48 GrantActivePermissions(extension);
50 NotifyPermissionsUpdated(ADDED, extension, added.get());
53 void PermissionsUpdater::RemovePermissions(
54 const Extension* extension, const PermissionSet* permissions) {
55 scoped_refptr<const PermissionSet> existing(
56 extension->GetActivePermissions());
57 scoped_refptr<PermissionSet> total(
58 PermissionSet::CreateDifference(existing.get(), permissions));
59 scoped_refptr<PermissionSet> removed(
60 PermissionSet::CreateDifference(existing.get(), total.get()));
62 // We update the active permissions, and not the granted permissions, because
63 // the extension, not the user, removed the permissions. This allows the
64 // extension to add them again without prompting the user.
65 UpdateActivePermissions(extension, total.get());
67 NotifyPermissionsUpdated(REMOVED, extension, removed.get());
70 void PermissionsUpdater::GrantActivePermissions(const Extension* extension) {
71 CHECK(extension);
73 // We only maintain the granted permissions prefs for INTERNAL and LOAD
74 // extensions.
75 if (!Manifest::IsUnpackedLocation(extension->location()) &&
76 extension->location() != Manifest::INTERNAL)
77 return;
79 ExtensionPrefs::Get(profile_)->AddGrantedPermissions(
80 extension->id(), extension->GetActivePermissions().get());
83 void PermissionsUpdater::UpdateActivePermissions(
84 const Extension* extension, const PermissionSet* permissions) {
85 ExtensionPrefs::Get(profile_)->SetActivePermissions(
86 extension->id(), permissions);
87 PermissionsData::SetActivePermissions(extension, permissions);
90 void PermissionsUpdater::DispatchEvent(
91 const std::string& extension_id,
92 const char* event_name,
93 const PermissionSet* changed_permissions) {
94 if (!profile_ || !EventRouter::Get(profile_))
95 return;
97 scoped_ptr<base::ListValue> value(new base::ListValue());
98 scoped_ptr<api::permissions::Permissions> permissions =
99 PackPermissionSet(changed_permissions);
100 value->Append(permissions->ToValue().release());
101 scoped_ptr<Event> event(new Event(event_name, value.Pass()));
102 event->restrict_to_browser_context = profile_;
103 EventRouter::Get(profile_)
104 ->DispatchEventToExtension(extension_id, event.Pass());
107 void PermissionsUpdater::NotifyPermissionsUpdated(
108 EventType event_type,
109 const Extension* extension,
110 const PermissionSet* changed) {
111 if (!changed || changed->IsEmpty())
112 return;
114 UpdatedExtensionPermissionsInfo::Reason reason;
115 const char* event_name = NULL;
117 if (event_type == REMOVED) {
118 reason = UpdatedExtensionPermissionsInfo::REMOVED;
119 event_name = permissions::OnRemoved::kEventName;
120 } else {
121 CHECK_EQ(ADDED, event_type);
122 reason = UpdatedExtensionPermissionsInfo::ADDED;
123 event_name = permissions::OnAdded::kEventName;
126 // Notify other APIs or interested parties.
127 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo(
128 extension, changed, reason);
129 content::NotificationService::current()->Notify(
130 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
131 content::Source<Profile>(profile_),
132 content::Details<UpdatedExtensionPermissionsInfo>(&info));
134 // Send the new permissions to the renderers.
135 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
136 !i.IsAtEnd(); i.Advance()) {
137 RenderProcessHost* host = i.GetCurrentValue();
138 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
139 if (profile_->IsSameProfile(profile)) {
140 ExtensionMsg_UpdatePermissions_Params info;
141 info.reason_id = static_cast<int>(reason);
142 info.extension_id = extension->id();
143 info.apis = changed->apis();
144 info.manifest_permissions = changed->manifest_permissions();
145 info.explicit_hosts = changed->explicit_hosts();
146 info.scriptable_hosts = changed->scriptable_hosts();
147 host->Send(new ExtensionMsg_UpdatePermissions(info));
151 // Trigger the onAdded and onRemoved events in the extension.
152 DispatchEvent(extension->id(), event_name, changed);
155 } // namespace extensions