Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/permissions/permission_manager.h" | 5 #include "chrome/browser/permissions/permission_manager.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 8 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 9 #include "chrome/browser/permissions/permission_context.h" | 9 #include "chrome/browser/permissions/permission_context.h" |
| 10 #include "chrome/browser/permissions/permission_context_base.h" | 10 #include "chrome/browser/permissions/permission_context_base.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 // return nullptr in PermissionContext::Get since they don't have a context. | 86 // return nullptr in PermissionContext::Get since they don't have a context. |
| 87 bool IsConstantPermission(PermissionType type) { | 87 bool IsConstantPermission(PermissionType type) { |
| 88 switch (type) { | 88 switch (type) { |
| 89 case PermissionType::MIDI: | 89 case PermissionType::MIDI: |
| 90 return true; | 90 return true; |
| 91 default: | 91 default: |
| 92 return false; | 92 return false; |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 void PermissionRequestResponseCallbackWrapper( | |
| 97 const base::Callback<void(PermissionStatus)>& callback, | |
| 98 const std::vector<PermissionStatus>& vector) { | |
| 99 DCHECK(vector.size() == 1); | |
|
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: DCHECK_EQ()
Lalit Maganti
2015/09/24 09:24:11
Done.
| |
| 100 callback.Run(vector[0]); | |
| 101 } | |
| 102 | |
| 96 // Function used for handling permission types which do not change their | 103 // Function used for handling permission types which do not change their |
| 97 // value i.e. they are always approved or always denied etc. | 104 // value i.e. they are always approved or always denied etc. |
| 98 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. | 105 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. |
| 99 // This function should only be called when IsConstantPermission has returned | 106 // This function should only be called when IsConstantPermission has returned |
| 100 // true for the PermissionType. | 107 // true for the PermissionType. |
| 101 ContentSetting GetContentSettingForConstantPermission(PermissionType type) { | 108 ContentSetting GetContentSettingForConstantPermission(PermissionType type) { |
| 102 DCHECK(IsConstantPermission(type)); | 109 DCHECK(IsConstantPermission(type)); |
| 103 switch (type) { | 110 switch (type) { |
| 104 case PermissionType::MIDI: | 111 case PermissionType::MIDI: |
| 105 return CONTENT_SETTING_ALLOW; | 112 return CONTENT_SETTING_ALLOW; |
| 106 default: | 113 default: |
| 107 return CONTENT_SETTING_DEFAULT; | 114 return CONTENT_SETTING_DEFAULT; |
| 108 } | 115 } |
| 109 } | 116 } |
| 110 | 117 |
| 111 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { | 118 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { |
| 112 return ContentSettingToPermissionStatus( | 119 return ContentSettingToPermissionStatus( |
| 113 GetContentSettingForConstantPermission(type)); | 120 GetContentSettingForConstantPermission(type)); |
| 114 } | 121 } |
| 115 | 122 |
| 116 } // anonymous namespace | 123 } // anonymous namespace |
| 117 | 124 |
| 118 struct PermissionManager::PendingRequest { | 125 struct PermissionManager::PendingRequest { |
| 119 PermissionType permission; | 126 PendingRequest(content::RenderFrameHost* render_frame_host, |
| 127 const GURL& requesting_origin, | |
| 128 const std::vector<PermissionType> types, | |
| 129 const base::Callback<void( | |
| 130 const std::vector<PermissionStatus>&)>& callback) | |
| 131 : render_process_id(render_frame_host->GetProcess()->GetID()), | |
| 132 render_frame_id(render_frame_host->GetRoutingID()), | |
| 133 requesting_origin(requesting_origin), | |
| 134 pending(types.size()), | |
| 135 callback(callback), | |
| 136 permissions(types), | |
| 137 result(permissions.size(), content::PERMISSION_STATUS_DENIED) { | |
| 138 // TODO(miguelg, peter) This special case for should go away once | |
| 139 // push -> notifications mapping goes away/is changed. | |
| 140 bool push_seen = false; | |
| 141 for (const PermissionType& type : permissions) { | |
| 142 if (type == PermissionType::PUSH_MESSAGING) | |
| 143 push_seen = true; | |
| 144 } | |
| 145 if (!push_seen) | |
| 146 return; | |
| 147 for (size_t i = 0; i < permissions.size(); ++i) { | |
| 148 if (permissions[i] == PermissionType::NOTIFICATIONS) | |
| 149 permissions[i] = PermissionType::PUSH_MESSAGING; | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 // Returns if there are no further pending sub-requests. | |
| 154 bool SetPermission(int index, PermissionStatus status) { | |
| 155 PermissionType current = permissions[index]; | |
| 156 for (size_t i = index; i < permissions.size(); ++i) { | |
| 157 if (permissions[i] == current) { | |
| 158 result[i] = status; | |
| 159 pending -= 1; | |
|
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: --pending;
Lalit Maganti
2015/09/24 09:24:11
All changed.
| |
| 160 } | |
| 161 } | |
| 162 if (pending == 0) | |
| 163 callback.Run(result); | |
| 164 return pending == 0; | |
| 165 } | |
| 166 | |
| 120 int render_process_id; | 167 int render_process_id; |
| 121 int render_frame_id; | 168 int render_frame_id; |
| 169 const GURL requesting_origin; | |
| 170 size_t pending; | |
|
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: pending_results?
Lalit Maganti
2015/09/24 09:24:11
Gone.
| |
| 171 const base::Callback<void( | |
| 172 const std::vector<PermissionStatus>&)> callback; | |
| 173 | |
| 174 std::vector<PermissionType> permissions; | |
| 175 std::vector<PermissionStatus> result; | |
| 122 }; | 176 }; |
| 123 | 177 |
| 124 struct PermissionManager::Subscription { | 178 struct PermissionManager::Subscription { |
| 125 PermissionType permission; | 179 PermissionType permission; |
| 126 GURL requesting_origin; | 180 GURL requesting_origin; |
| 127 GURL embedding_origin; | 181 GURL embedding_origin; |
| 128 base::Callback<void(PermissionStatus)> callback; | 182 base::Callback<void(PermissionStatus)> callback; |
| 129 ContentSetting current_value; | 183 ContentSetting current_value; |
| 130 }; | 184 }; |
| 131 | 185 |
| 132 PermissionManager::PermissionManager(Profile* profile) | 186 PermissionManager::PermissionManager(Profile* profile) |
| 133 : profile_(profile), | 187 : profile_(profile), |
| 134 weak_ptr_factory_(this) { | 188 weak_ptr_factory_(this) { |
| 135 } | 189 } |
| 136 | 190 |
| 137 PermissionManager::~PermissionManager() { | 191 PermissionManager::~PermissionManager() { |
| 138 if (!subscriptions_.IsEmpty()) | 192 if (!subscriptions_.IsEmpty()) |
| 139 HostContentSettingsMapFactory::GetForProfile(profile_) | 193 HostContentSettingsMapFactory::GetForProfile(profile_) |
| 140 ->RemoveObserver(this); | 194 ->RemoveObserver(this); |
| 141 } | 195 } |
| 142 | 196 |
| 143 int PermissionManager::RequestPermission( | 197 int PermissionManager::RequestPermission( |
| 144 PermissionType permission, | 198 PermissionType permission, |
| 145 content::RenderFrameHost* render_frame_host, | 199 content::RenderFrameHost* render_frame_host, |
| 146 const GURL& requesting_origin, | 200 const GURL& requesting_origin, |
| 147 bool user_gesture, | 201 bool user_gesture, |
| 148 const base::Callback<void(PermissionStatus)>& callback) { | 202 const base::Callback<void(PermissionStatus)>& callback) { |
| 149 if (IsConstantPermission(permission)) { | 203 return RequestPermissions( |
| 150 callback.Run(GetPermissionStatusForConstantPermission(permission)); | 204 std::vector<PermissionType>(1, permission), |
| 151 return kNoPendingRequestOrSubscription; | 205 render_frame_host, |
| 152 } | 206 requesting_origin, |
| 207 user_gesture, | |
| 208 base::Bind(&PermissionRequestResponseCallbackWrapper, callback)); | |
| 209 } | |
| 153 | 210 |
| 154 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 211 int PermissionManager::RequestPermissions( |
| 155 if (!context) { | 212 const std::vector<PermissionType>& permissions, |
| 156 callback.Run(content::PERMISSION_STATUS_DENIED); | 213 content::RenderFrameHost* render_frame_host, |
| 157 return kNoPendingRequestOrSubscription; | 214 const GURL& requesting_origin, |
| 158 } | 215 bool user_gesture, |
| 159 | 216 const base::Callback<void( |
| 217 const std::vector<PermissionStatus>&)>& callback) { | |
| 160 content::WebContents* web_contents = | 218 content::WebContents* web_contents = |
| 161 content::WebContents::FromRenderFrameHost(render_frame_host); | 219 content::WebContents::FromRenderFrameHost(render_frame_host); |
| 162 if (IsPermissionBubbleManagerMissing(web_contents)) { | 220 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); |
| 163 callback.Run( | 221 |
| 164 GetPermissionStatus(permission, requesting_origin, | 222 PendingRequest* pending_request = new PendingRequest( |
| 165 web_contents->GetLastCommittedURL().GetOrigin())); | 223 render_frame_host, requesting_origin, permissions, callback); |
| 166 return kNoPendingRequestOrSubscription; | 224 int request_id = pending_requests_.Add(pending_request); |
| 225 const PermissionRequestID request(render_frame_host, request_id); | |
| 226 | |
| 227 std::set<PermissionType> seen_permissions; | |
| 228 for (size_t i = 0; i < permissions.size(); ++i) { | |
| 229 // It is important that the pending request be used here as it can change | |
| 230 // the PermissionType from the vector that was passed in. | |
| 231 // TODO(peter, miguelg) Remove this when push and notifcations are unified. | |
| 232 const PermissionType permission = pending_request->permissions[i]; | |
| 233 if (seen_permissions.find(permission) != seen_permissions.end()) | |
| 234 continue; | |
| 235 seen_permissions.insert(permission); | |
| 236 | |
| 237 if (IsConstantPermission(permission) || | |
| 238 IsPermissionBubbleManagerMissing(web_contents) || | |
| 239 !PermissionContext::Get(profile_, permission)) { | |
| 240 OnPermissionsRequestResponseStatus(request_id, i, | |
| 241 GetPermissionStatus( | |
| 242 permission, requesting_origin, embedding_origin)); | |
| 243 continue; | |
| 244 } | |
| 245 | |
| 246 PermissionContextBase* context = PermissionContext::Get( | |
| 247 profile_, permission); | |
| 248 context->RequestPermission( | |
| 249 web_contents, request, requesting_origin, user_gesture, | |
| 250 base::Bind(&PermissionManager::OnPermissionsRequestResponse, | |
| 251 weak_ptr_factory_.GetWeakPtr(), request_id, i)); | |
| 167 } | 252 } |
| 168 | |
| 169 int render_process_id = render_frame_host->GetProcess()->GetID(); | |
| 170 int render_frame_id = render_frame_host->GetRoutingID(); | |
| 171 | |
| 172 PendingRequest* pending_request = new PendingRequest(); | |
| 173 pending_request->render_process_id = render_process_id; | |
| 174 pending_request->render_frame_id = render_frame_id; | |
| 175 pending_request->permission = permission; | |
| 176 | |
| 177 int request_id = pending_requests_.Add(pending_request); | |
| 178 const PermissionRequestID request(render_process_id, | |
| 179 render_frame_id, | |
| 180 request_id); | |
| 181 | |
| 182 context->RequestPermission( | |
| 183 web_contents, request, requesting_origin, user_gesture, | |
| 184 base::Bind(&PermissionManager::OnPermissionRequestResponse, | |
| 185 weak_ptr_factory_.GetWeakPtr(), | |
| 186 request_id, | |
| 187 callback)); | |
| 188 return request_id; | 253 return request_id; |
| 189 } | 254 } |
| 190 | 255 |
| 191 void PermissionManager::OnPermissionRequestResponse( | 256 void PermissionManager::OnPermissionsRequestResponse( |
| 192 int request_id, | 257 int request_id, |
| 193 const base::Callback<void(PermissionStatus)>& callback, | 258 int request_index, |
| 194 ContentSetting content_setting) { | 259 ContentSetting content_setting) { |
| 195 pending_requests_.Remove(request_id); | 260 OnPermissionsRequestResponseStatus(request_id, request_index, |
| 196 callback.Run(ContentSettingToPermissionStatus(content_setting)); | 261 ContentSettingToPermissionStatus(content_setting)); |
| 262 } | |
| 263 | |
| 264 void PermissionManager::OnPermissionsRequestResponseStatus( | |
| 265 int request_id, | |
| 266 int request_index, | |
| 267 PermissionStatus status) { | |
| 268 PendingRequest* pending_request = pending_requests_.Lookup(request_id); | |
| 269 if (pending_request->SetPermission(request_index, status)) | |
| 270 pending_requests_.Remove(request_id); | |
| 197 } | 271 } |
| 198 | 272 |
| 199 void PermissionManager::CancelPermissionRequest(int request_id) { | 273 void PermissionManager::CancelPermissionRequest(int request_id) { |
| 200 PendingRequest* pending_request = pending_requests_.Lookup(request_id); | 274 PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
| 201 if (!pending_request) | 275 if (!pending_request) |
| 202 return; | 276 return; |
| 203 | 277 |
| 204 PermissionContextBase* context = PermissionContext::Get( | |
| 205 profile_, pending_request->permission); | |
| 206 if (!context) | |
| 207 return; | |
| 208 | |
| 209 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( | 278 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
| 210 pending_request->render_process_id, pending_request->render_frame_id); | 279 pending_request->render_process_id, pending_request->render_frame_id); |
| 211 DCHECK(web_contents); | 280 DCHECK(web_contents); |
| 212 if (IsPermissionBubbleManagerMissing(web_contents)) { | 281 if (IsPermissionBubbleManagerMissing(web_contents)) { |
| 213 pending_requests_.Remove(request_id); | 282 pending_requests_.Remove(request_id); |
| 214 return; | 283 return; |
| 215 } | 284 } |
| 216 | 285 |
| 217 const PermissionRequestID request(pending_request->render_process_id, | 286 const PermissionRequestID request(pending_request->render_process_id, |
| 218 pending_request->render_frame_id, | 287 pending_request->render_frame_id, |
| 219 request_id); | 288 request_id); |
| 220 context->CancelPermissionRequest(web_contents, request); | 289 std::set<PermissionType> seen_permissions; |
| 290 for (const PermissionType& permission : pending_request->permissions) { | |
| 291 if (seen_permissions.find(permission) != seen_permissions.end()) | |
| 292 continue; | |
| 293 seen_permissions.insert(permission); | |
| 294 | |
| 295 PermissionContextBase* context = PermissionContext::Get( | |
| 296 profile_, permission); | |
| 297 if (!context) | |
| 298 continue; | |
| 299 context->CancelPermissionRequest(web_contents, request); | |
| 300 } | |
| 221 pending_requests_.Remove(request_id); | 301 pending_requests_.Remove(request_id); |
| 222 } | 302 } |
| 223 | 303 |
| 224 void PermissionManager::ResetPermission(PermissionType permission, | 304 void PermissionManager::ResetPermission(PermissionType permission, |
| 225 const GURL& requesting_origin, | 305 const GURL& requesting_origin, |
| 226 const GURL& embedding_origin) { | 306 const GURL& embedding_origin) { |
| 227 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 307 PermissionContextBase* context = PermissionContext::Get(profile_, permission); |
| 228 if (!context) | 308 if (!context) |
| 229 return; | 309 return; |
| 230 | 310 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 // Add the callback to |callbacks| which will be run after the loop to | 419 // Add the callback to |callbacks| which will be run after the loop to |
| 340 // prevent re-entrance issues. | 420 // prevent re-entrance issues. |
| 341 callbacks.push_back( | 421 callbacks.push_back( |
| 342 base::Bind(subscription->callback, | 422 base::Bind(subscription->callback, |
| 343 ContentSettingToPermissionStatus(new_value))); | 423 ContentSettingToPermissionStatus(new_value))); |
| 344 } | 424 } |
| 345 | 425 |
| 346 for (const auto& callback : callbacks) | 426 for (const auto& callback : callbacks) |
| 347 callback.Run(); | 427 callback.Run(); |
| 348 } | 428 } |
| OLD | NEW |