Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / permissions_updater.cc
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/profiles/profile.h"
13 #include "chrome/common/extensions/api/permissions.h"
14 #include "chrome/common/extensions/extension_messages.h"
15 #include "content/public/browser/notification_observer.h"
16 #include "content/public/browser/notification_registrar.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_prefs.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/permissions/permissions_data.h"
24
25 using content::RenderProcessHost;
26 using extensions::permissions_api_helpers::PackPermissionSet;
27
28 namespace extensions {
29
30 namespace permissions = api::permissions;
31
32 PermissionsUpdater::PermissionsUpdater(Profile* profile)
33     : profile_(profile) {}
34
35 PermissionsUpdater::~PermissionsUpdater() {}
36
37 void 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
54 void 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
71 void 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
84 void 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
91 void 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_browser_context = profile_;
105   ExtensionSystem::Get(profile_)->event_router()->
106       DispatchEventToExtension(extension_id, event.Pass());
107 }
108
109 void 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       ExtensionMsg_UpdatePermissions_Params info;
143       info.reason_id = static_cast<int>(reason);
144       info.extension_id = extension->id();
145       info.apis = changed->apis();
146       info.manifest_permissions = changed->manifest_permissions();
147       info.explicit_hosts = changed->explicit_hosts();
148       info.scriptable_hosts = changed->scriptable_hosts();
149       host->Send(new ExtensionMsg_UpdatePermissions(info));
150     }
151   }
152
153   // Trigger the onAdded and onRemoved events in the extension.
154   DispatchEvent(extension->id(), event_name, changed);
155 }
156
157 }  // namespace extensions