OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/permissions_updater.h" | 5 #include "chrome/browser/extensions/permissions_updater.h" |
6 | 6 |
7 #include "base/json/json_writer.h" | 7 #include "base/json/json_writer.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/values.h" | 9 #include "base/values.h" |
10 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
11 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" | 11 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" |
12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/common/extensions/api/permissions.h" | 13 #include "chrome/common/extensions/api/permissions.h" |
14 #include "content/public/browser/notification_observer.h" | 14 #include "content/public/browser/notification_observer.h" |
15 #include "content/public/browser/notification_registrar.h" | 15 #include "content/public/browser/notification_registrar.h" |
16 #include "content/public/browser/notification_service.h" | 16 #include "content/public/browser/notification_service.h" |
17 #include "content/public/browser/render_process_host.h" | 17 #include "content/public/browser/render_process_host.h" |
18 #include "extensions/browser/event_router.h" | 18 #include "extensions/browser/event_router.h" |
19 #include "extensions/browser/extension_prefs.h" | 19 #include "extensions/browser/extension_prefs.h" |
20 #include "extensions/common/extension.h" | 20 #include "extensions/common/extension.h" |
21 #include "extensions/common/extension_messages.h" | 21 #include "extensions/common/extension_messages.h" |
| 22 #include "extensions/common/manifest_handlers/permissions_parser.h" |
| 23 #include "extensions/common/permissions/permission_set.h" |
22 #include "extensions/common/permissions/permissions_data.h" | 24 #include "extensions/common/permissions/permissions_data.h" |
23 | 25 |
24 using content::RenderProcessHost; | 26 using content::RenderProcessHost; |
25 using extensions::permissions_api_helpers::PackPermissionSet; | 27 using extensions::permissions_api_helpers::PackPermissionSet; |
26 | 28 |
27 namespace extensions { | 29 namespace extensions { |
28 | 30 |
29 namespace permissions = api::permissions; | 31 namespace permissions = api::permissions; |
30 | 32 |
31 PermissionsUpdater::PermissionsUpdater(Profile* profile) | 33 PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context) |
32 : profile_(profile) {} | 34 : browser_context_(browser_context) { |
| 35 } |
33 | 36 |
34 PermissionsUpdater::~PermissionsUpdater() {} | 37 PermissionsUpdater::~PermissionsUpdater() {} |
35 | 38 |
36 void PermissionsUpdater::AddPermissions( | 39 void PermissionsUpdater::AddPermissions( |
37 const Extension* extension, const PermissionSet* permissions) { | 40 const Extension* extension, const PermissionSet* permissions) { |
38 scoped_refptr<const PermissionSet> existing( | 41 scoped_refptr<const PermissionSet> existing( |
39 extension->permissions_data()->active_permissions()); | 42 extension->permissions_data()->active_permissions()); |
40 scoped_refptr<PermissionSet> total( | 43 scoped_refptr<PermissionSet> total( |
41 PermissionSet::CreateUnion(existing.get(), permissions)); | 44 PermissionSet::CreateUnion(existing.get(), permissions)); |
42 scoped_refptr<PermissionSet> added( | 45 scoped_refptr<PermissionSet> added( |
43 PermissionSet::CreateDifference(total.get(), existing.get())); | 46 PermissionSet::CreateDifference(total.get(), existing.get())); |
44 | 47 |
45 UpdateActivePermissions(extension, total.get()); | 48 SetActivePermissions(extension, total.get()); |
46 | 49 |
47 // Update the granted permissions so we don't auto-disable the extension. | 50 // Update the granted permissions so we don't auto-disable the extension. |
48 GrantActivePermissions(extension); | 51 GrantActivePermissions(extension); |
49 | 52 |
50 NotifyPermissionsUpdated(ADDED, extension, added.get()); | 53 NotifyPermissionsUpdated(ADDED, extension, added.get()); |
51 } | 54 } |
52 | 55 |
53 void PermissionsUpdater::RemovePermissions( | 56 void PermissionsUpdater::RemovePermissions( |
54 const Extension* extension, const PermissionSet* permissions) { | 57 const Extension* extension, const PermissionSet* permissions) { |
55 scoped_refptr<const PermissionSet> existing( | 58 scoped_refptr<const PermissionSet> existing( |
56 extension->permissions_data()->active_permissions()); | 59 extension->permissions_data()->active_permissions()); |
57 scoped_refptr<PermissionSet> total( | 60 scoped_refptr<PermissionSet> total( |
58 PermissionSet::CreateDifference(existing.get(), permissions)); | 61 PermissionSet::CreateDifference(existing.get(), permissions)); |
59 scoped_refptr<PermissionSet> removed( | 62 scoped_refptr<PermissionSet> removed( |
60 PermissionSet::CreateDifference(existing.get(), total.get())); | 63 PermissionSet::CreateDifference(existing.get(), total.get())); |
61 | 64 |
62 // We update the active permissions, and not the granted permissions, because | 65 // We update the active permissions, and not the granted permissions, because |
63 // the extension, not the user, removed the permissions. This allows the | 66 // the extension, not the user, removed the permissions. This allows the |
64 // extension to add them again without prompting the user. | 67 // extension to add them again without prompting the user. |
65 UpdateActivePermissions(extension, total.get()); | 68 SetActivePermissions(extension, total.get()); |
66 | 69 |
67 NotifyPermissionsUpdated(REMOVED, extension, removed.get()); | 70 NotifyPermissionsUpdated(REMOVED, extension, removed.get()); |
68 } | 71 } |
69 | 72 |
70 void PermissionsUpdater::GrantActivePermissions(const Extension* extension) { | 73 void PermissionsUpdater::GrantActivePermissions(const Extension* extension) { |
71 CHECK(extension); | 74 CHECK(extension); |
72 | 75 |
73 // We only maintain the granted permissions prefs for INTERNAL and LOAD | 76 // We only maintain the granted permissions prefs for INTERNAL and LOAD |
74 // extensions. | 77 // extensions. |
75 if (!Manifest::IsUnpackedLocation(extension->location()) && | 78 if (!Manifest::IsUnpackedLocation(extension->location()) && |
76 extension->location() != Manifest::INTERNAL) | 79 extension->location() != Manifest::INTERNAL) |
77 return; | 80 return; |
78 | 81 |
79 ExtensionPrefs::Get(profile_)->AddGrantedPermissions( | 82 ExtensionPrefs::Get(browser_context_)->AddGrantedPermissions( |
80 extension->id(), | 83 extension->id(), |
81 extension->permissions_data()->active_permissions().get()); | 84 extension->permissions_data()->active_permissions().get()); |
82 } | 85 } |
83 | 86 |
84 void PermissionsUpdater::UpdateActivePermissions( | 87 void PermissionsUpdater::UpdateActivePermissions(const Extension* extension) { |
| 88 // If the extension has used the optional permissions API, it will have a |
| 89 // custom set of active permissions defined in the extension prefs. Here, |
| 90 // we update the extension's active permissions based on the prefs. |
| 91 scoped_refptr<PermissionSet> active_permissions = |
| 92 ExtensionPrefs::Get(browser_context_)->GetActivePermissions( |
| 93 extension->id()); |
| 94 if (!active_permissions) |
| 95 return; |
| 96 |
| 97 // We restrict the active permissions to be within the bounds defined in the |
| 98 // extension's manifest. |
| 99 // a) active permissions must be a subset of optional + default permissions |
| 100 // b) active permissions must contains all default permissions |
| 101 scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion( |
| 102 PermissionsParser::GetRequiredPermissions(extension), |
| 103 PermissionsParser::GetOptionalPermissions(extension)); |
| 104 |
| 105 // Make sure the active permissions contain no more than optional + default. |
| 106 scoped_refptr<PermissionSet> adjusted_active = |
| 107 PermissionSet::CreateIntersection(total_permissions, active_permissions); |
| 108 |
| 109 // Make sure the active permissions contain the default permissions. |
| 110 adjusted_active = PermissionSet::CreateUnion( |
| 111 PermissionsParser::GetRequiredPermissions(extension), |
| 112 adjusted_active); |
| 113 |
| 114 SetActivePermissions(extension, adjusted_active); |
| 115 } |
| 116 |
| 117 void PermissionsUpdater::SetActivePermissions( |
85 const Extension* extension, const PermissionSet* permissions) { | 118 const Extension* extension, const PermissionSet* permissions) { |
86 ExtensionPrefs::Get(profile_)->SetActivePermissions( | 119 ExtensionPrefs::Get(browser_context_)->SetActivePermissions( |
87 extension->id(), permissions); | 120 extension->id(), permissions); |
88 extension->permissions_data()->SetActivePermissions(permissions); | 121 extension->permissions_data()->SetActivePermissions(permissions); |
89 } | 122 } |
90 | 123 |
91 void PermissionsUpdater::DispatchEvent( | 124 void PermissionsUpdater::DispatchEvent( |
92 const std::string& extension_id, | 125 const std::string& extension_id, |
93 const char* event_name, | 126 const char* event_name, |
94 const PermissionSet* changed_permissions) { | 127 const PermissionSet* changed_permissions) { |
95 if (!profile_ || !EventRouter::Get(profile_)) | 128 EventRouter* event_router = EventRouter::Get(browser_context_); |
| 129 if (!event_router) |
96 return; | 130 return; |
97 | 131 |
98 scoped_ptr<base::ListValue> value(new base::ListValue()); | 132 scoped_ptr<base::ListValue> value(new base::ListValue()); |
99 scoped_ptr<api::permissions::Permissions> permissions = | 133 scoped_ptr<api::permissions::Permissions> permissions = |
100 PackPermissionSet(changed_permissions); | 134 PackPermissionSet(changed_permissions); |
101 value->Append(permissions->ToValue().release()); | 135 value->Append(permissions->ToValue().release()); |
102 scoped_ptr<Event> event(new Event(event_name, value.Pass())); | 136 scoped_ptr<Event> event(new Event(event_name, value.Pass())); |
103 event->restrict_to_browser_context = profile_; | 137 event->restrict_to_browser_context = browser_context_; |
104 EventRouter::Get(profile_) | 138 event_router->DispatchEventToExtension(extension_id, event.Pass()); |
105 ->DispatchEventToExtension(extension_id, event.Pass()); | |
106 } | 139 } |
107 | 140 |
108 void PermissionsUpdater::NotifyPermissionsUpdated( | 141 void PermissionsUpdater::NotifyPermissionsUpdated( |
109 EventType event_type, | 142 EventType event_type, |
110 const Extension* extension, | 143 const Extension* extension, |
111 const PermissionSet* changed) { | 144 const PermissionSet* changed) { |
112 if (!changed || changed->IsEmpty()) | 145 if (!changed || changed->IsEmpty()) |
113 return; | 146 return; |
114 | 147 |
115 UpdatedExtensionPermissionsInfo::Reason reason; | 148 UpdatedExtensionPermissionsInfo::Reason reason; |
116 const char* event_name = NULL; | 149 const char* event_name = NULL; |
117 | 150 |
118 if (event_type == REMOVED) { | 151 if (event_type == REMOVED) { |
119 reason = UpdatedExtensionPermissionsInfo::REMOVED; | 152 reason = UpdatedExtensionPermissionsInfo::REMOVED; |
120 event_name = permissions::OnRemoved::kEventName; | 153 event_name = permissions::OnRemoved::kEventName; |
121 } else { | 154 } else { |
122 CHECK_EQ(ADDED, event_type); | 155 CHECK_EQ(ADDED, event_type); |
123 reason = UpdatedExtensionPermissionsInfo::ADDED; | 156 reason = UpdatedExtensionPermissionsInfo::ADDED; |
124 event_name = permissions::OnAdded::kEventName; | 157 event_name = permissions::OnAdded::kEventName; |
125 } | 158 } |
126 | 159 |
127 // Notify other APIs or interested parties. | 160 // Notify other APIs or interested parties. |
128 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( | 161 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( |
129 extension, changed, reason); | 162 extension, changed, reason); |
| 163 Profile* profile = Profile::FromBrowserContext(browser_context_); |
130 content::NotificationService::current()->Notify( | 164 content::NotificationService::current()->Notify( |
131 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, | 165 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, |
132 content::Source<Profile>(profile_), | 166 content::Source<Profile>(profile), |
133 content::Details<UpdatedExtensionPermissionsInfo>(&info)); | 167 content::Details<UpdatedExtensionPermissionsInfo>(&info)); |
134 | 168 |
| 169 ExtensionMsg_UpdatePermissions_Params params; |
| 170 params.reason_id = static_cast<int>(reason); |
| 171 params.extension_id = extension->id(); |
| 172 params.apis = changed->apis(); |
| 173 params.manifest_permissions = changed->manifest_permissions(); |
| 174 params.explicit_hosts = changed->explicit_hosts(); |
| 175 params.scriptable_hosts = changed->scriptable_hosts(); |
| 176 |
135 // Send the new permissions to the renderers. | 177 // Send the new permissions to the renderers. |
136 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 178 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
137 !i.IsAtEnd(); i.Advance()) { | 179 !i.IsAtEnd(); i.Advance()) { |
138 RenderProcessHost* host = i.GetCurrentValue(); | 180 RenderProcessHost* host = i.GetCurrentValue(); |
139 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); | 181 if (profile->IsSameProfile( |
140 if (profile_->IsSameProfile(profile)) { | 182 Profile::FromBrowserContext(host->GetBrowserContext()))) { |
141 ExtensionMsg_UpdatePermissions_Params info; | 183 host->Send(new ExtensionMsg_UpdatePermissions(params)); |
142 info.reason_id = static_cast<int>(reason); | |
143 info.extension_id = extension->id(); | |
144 info.apis = changed->apis(); | |
145 info.manifest_permissions = changed->manifest_permissions(); | |
146 info.explicit_hosts = changed->explicit_hosts(); | |
147 info.scriptable_hosts = changed->scriptable_hosts(); | |
148 host->Send(new ExtensionMsg_UpdatePermissions(info)); | |
149 } | 184 } |
150 } | 185 } |
151 | 186 |
152 // Trigger the onAdded and onRemoved events in the extension. | 187 // Trigger the onAdded and onRemoved events in the extension. |
153 DispatchEvent(extension->id(), event_name, changed); | 188 DispatchEvent(extension->id(), event_name, changed); |
154 } | 189 } |
155 | 190 |
156 } // namespace extensions | 191 } // namespace extensions |
OLD | NEW |