| 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::InitializeActivePermissions( |
| 88 const Extension* extension) { |
| 89 // If the extension has used the optional permissions API, it will have a |
| 90 // custom set of active permissions defined in the extension prefs. Here, |
| 91 // we update the extension's active permissions based on the prefs. |
| 92 scoped_refptr<PermissionSet> active_permissions = |
| 93 ExtensionPrefs::Get(browser_context_)->GetActivePermissions( |
| 94 extension->id()); |
| 95 if (!active_permissions) |
| 96 return; |
| 97 |
| 98 // We restrict the active permissions to be within the bounds defined in the |
| 99 // extension's manifest. |
| 100 // a) active permissions must be a subset of optional + default permissions |
| 101 // b) active permissions must contains all default permissions |
| 102 scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion( |
| 103 PermissionsParser::GetRequiredPermissions(extension), |
| 104 PermissionsParser::GetOptionalPermissions(extension)); |
| 105 |
| 106 // Make sure the active permissions contain no more than optional + default. |
| 107 scoped_refptr<PermissionSet> adjusted_active = |
| 108 PermissionSet::CreateIntersection(total_permissions, active_permissions); |
| 109 |
| 110 // Make sure the active permissions contain the default permissions. |
| 111 adjusted_active = PermissionSet::CreateUnion( |
| 112 PermissionsParser::GetRequiredPermissions(extension), |
| 113 adjusted_active); |
| 114 |
| 115 SetActivePermissions(extension, adjusted_active); |
| 116 } |
| 117 |
| 118 void PermissionsUpdater::SetActivePermissions( |
| 85 const Extension* extension, const PermissionSet* permissions) { | 119 const Extension* extension, const PermissionSet* permissions) { |
| 86 ExtensionPrefs::Get(profile_)->SetActivePermissions( | 120 ExtensionPrefs::Get(browser_context_)->SetActivePermissions( |
| 87 extension->id(), permissions); | 121 extension->id(), permissions); |
| 88 extension->permissions_data()->SetActivePermissions(permissions); | 122 extension->permissions_data()->SetActivePermissions(permissions); |
| 89 } | 123 } |
| 90 | 124 |
| 91 void PermissionsUpdater::DispatchEvent( | 125 void PermissionsUpdater::DispatchEvent( |
| 92 const std::string& extension_id, | 126 const std::string& extension_id, |
| 93 const char* event_name, | 127 const char* event_name, |
| 94 const PermissionSet* changed_permissions) { | 128 const PermissionSet* changed_permissions) { |
| 95 if (!profile_ || !EventRouter::Get(profile_)) | 129 EventRouter* event_router = EventRouter::Get(browser_context_); |
| 130 if (!event_router) |
| 96 return; | 131 return; |
| 97 | 132 |
| 98 scoped_ptr<base::ListValue> value(new base::ListValue()); | 133 scoped_ptr<base::ListValue> value(new base::ListValue()); |
| 99 scoped_ptr<api::permissions::Permissions> permissions = | 134 scoped_ptr<api::permissions::Permissions> permissions = |
| 100 PackPermissionSet(changed_permissions); | 135 PackPermissionSet(changed_permissions); |
| 101 value->Append(permissions->ToValue().release()); | 136 value->Append(permissions->ToValue().release()); |
| 102 scoped_ptr<Event> event(new Event(event_name, value.Pass())); | 137 scoped_ptr<Event> event(new Event(event_name, value.Pass())); |
| 103 event->restrict_to_browser_context = profile_; | 138 event->restrict_to_browser_context = browser_context_; |
| 104 EventRouter::Get(profile_) | 139 event_router->DispatchEventToExtension(extension_id, event.Pass()); |
| 105 ->DispatchEventToExtension(extension_id, event.Pass()); | |
| 106 } | 140 } |
| 107 | 141 |
| 108 void PermissionsUpdater::NotifyPermissionsUpdated( | 142 void PermissionsUpdater::NotifyPermissionsUpdated( |
| 109 EventType event_type, | 143 EventType event_type, |
| 110 const Extension* extension, | 144 const Extension* extension, |
| 111 const PermissionSet* changed) { | 145 const PermissionSet* changed) { |
| 112 if (!changed || changed->IsEmpty()) | 146 if (!changed || changed->IsEmpty()) |
| 113 return; | 147 return; |
| 114 | 148 |
| 115 UpdatedExtensionPermissionsInfo::Reason reason; | 149 UpdatedExtensionPermissionsInfo::Reason reason; |
| 116 const char* event_name = NULL; | 150 const char* event_name = NULL; |
| 117 | 151 |
| 118 if (event_type == REMOVED) { | 152 if (event_type == REMOVED) { |
| 119 reason = UpdatedExtensionPermissionsInfo::REMOVED; | 153 reason = UpdatedExtensionPermissionsInfo::REMOVED; |
| 120 event_name = permissions::OnRemoved::kEventName; | 154 event_name = permissions::OnRemoved::kEventName; |
| 121 } else { | 155 } else { |
| 122 CHECK_EQ(ADDED, event_type); | 156 CHECK_EQ(ADDED, event_type); |
| 123 reason = UpdatedExtensionPermissionsInfo::ADDED; | 157 reason = UpdatedExtensionPermissionsInfo::ADDED; |
| 124 event_name = permissions::OnAdded::kEventName; | 158 event_name = permissions::OnAdded::kEventName; |
| 125 } | 159 } |
| 126 | 160 |
| 127 // Notify other APIs or interested parties. | 161 // Notify other APIs or interested parties. |
| 128 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( | 162 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( |
| 129 extension, changed, reason); | 163 extension, changed, reason); |
| 164 Profile* profile = Profile::FromBrowserContext(browser_context_); |
| 130 content::NotificationService::current()->Notify( | 165 content::NotificationService::current()->Notify( |
| 131 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, | 166 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, |
| 132 content::Source<Profile>(profile_), | 167 content::Source<Profile>(profile), |
| 133 content::Details<UpdatedExtensionPermissionsInfo>(&info)); | 168 content::Details<UpdatedExtensionPermissionsInfo>(&info)); |
| 134 | 169 |
| 170 ExtensionMsg_UpdatePermissions_Params params; |
| 171 params.reason_id = static_cast<int>(reason); |
| 172 params.extension_id = extension->id(); |
| 173 params.apis = changed->apis(); |
| 174 params.manifest_permissions = changed->manifest_permissions(); |
| 175 params.explicit_hosts = changed->explicit_hosts(); |
| 176 params.scriptable_hosts = changed->scriptable_hosts(); |
| 177 |
| 135 // Send the new permissions to the renderers. | 178 // Send the new permissions to the renderers. |
| 136 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 179 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 137 !i.IsAtEnd(); i.Advance()) { | 180 !i.IsAtEnd(); i.Advance()) { |
| 138 RenderProcessHost* host = i.GetCurrentValue(); | 181 RenderProcessHost* host = i.GetCurrentValue(); |
| 139 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); | 182 if (profile->IsSameProfile( |
| 140 if (profile_->IsSameProfile(profile)) { | 183 Profile::FromBrowserContext(host->GetBrowserContext()))) { |
| 141 ExtensionMsg_UpdatePermissions_Params info; | 184 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 } | 185 } |
| 150 } | 186 } |
| 151 | 187 |
| 152 // Trigger the onAdded and onRemoved events in the extension. | 188 // Trigger the onAdded and onRemoved events in the extension. |
| 153 DispatchEvent(extension->id(), event_name, changed); | 189 DispatchEvent(extension->id(), event_name, changed); |
| 154 } | 190 } |
| 155 | 191 |
| 156 } // namespace extensions | 192 } // namespace extensions |
| OLD | NEW |