| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/browser/permissions/permission_service_impl.h" | 5 #include "content/browser/permissions/permission_service_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "content/public/browser/browser_context.h" | 11 #include "content/public/browser/browser_context.h" |
| 12 #include "content/public/browser/permission_manager.h" | 12 #include "content/public/browser/permission_manager.h" |
| 13 #include "content/public/browser/permission_type.h" | 13 #include "content/public/browser/permission_type.h" |
| 14 | 14 |
| 15 using blink::mojom::PermissionDescriptorPtr; |
| 15 using blink::mojom::PermissionName; | 16 using blink::mojom::PermissionName; |
| 16 using blink::mojom::PermissionStatus; | 17 using blink::mojom::PermissionStatus; |
| 17 | 18 |
| 18 namespace content { | 19 namespace content { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 PermissionType PermissionNameToPermissionType(PermissionName name) { | 23 PermissionType PermissionDescriptorToPermissionType( |
| 23 switch(name) { | 24 const PermissionDescriptorPtr& descriptor) { |
| 25 switch (descriptor->name) { |
| 24 case PermissionName::GEOLOCATION: | 26 case PermissionName::GEOLOCATION: |
| 25 return PermissionType::GEOLOCATION; | 27 return PermissionType::GEOLOCATION; |
| 26 case PermissionName::NOTIFICATIONS: | 28 case PermissionName::NOTIFICATIONS: |
| 27 return PermissionType::NOTIFICATIONS; | 29 return PermissionType::NOTIFICATIONS; |
| 28 case PermissionName::PUSH_NOTIFICATIONS: | 30 case PermissionName::PUSH_NOTIFICATIONS: |
| 29 return PermissionType::PUSH_MESSAGING; | 31 return PermissionType::PUSH_MESSAGING; |
| 30 case PermissionName::MIDI: | 32 case PermissionName::MIDI: { |
| 33 if (descriptor->extension && descriptor->extension->is_midi() && |
| 34 descriptor->extension->get_midi()->sysex) { |
| 35 return PermissionType::MIDI_SYSEX; |
| 36 } |
| 31 return PermissionType::MIDI; | 37 return PermissionType::MIDI; |
| 32 case PermissionName::MIDI_SYSEX: | 38 } |
| 33 return PermissionType::MIDI_SYSEX; | |
| 34 case PermissionName::PROTECTED_MEDIA_IDENTIFIER: | 39 case PermissionName::PROTECTED_MEDIA_IDENTIFIER: |
| 35 return PermissionType::PROTECTED_MEDIA_IDENTIFIER; | 40 return PermissionType::PROTECTED_MEDIA_IDENTIFIER; |
| 36 case PermissionName::DURABLE_STORAGE: | 41 case PermissionName::DURABLE_STORAGE: |
| 37 return PermissionType::DURABLE_STORAGE; | 42 return PermissionType::DURABLE_STORAGE; |
| 38 case PermissionName::AUDIO_CAPTURE: | 43 case PermissionName::AUDIO_CAPTURE: |
| 39 return PermissionType::AUDIO_CAPTURE; | 44 return PermissionType::AUDIO_CAPTURE; |
| 40 case PermissionName::VIDEO_CAPTURE: | 45 case PermissionName::VIDEO_CAPTURE: |
| 41 return PermissionType::VIDEO_CAPTURE; | 46 return PermissionType::VIDEO_CAPTURE; |
| 42 case PermissionName::BACKGROUND_SYNC: | 47 case PermissionName::BACKGROUND_SYNC: |
| 43 return PermissionType::BACKGROUND_SYNC; | 48 return PermissionType::BACKGROUND_SYNC; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 DCHECK(pending_requests_.IsEmpty()); | 104 DCHECK(pending_requests_.IsEmpty()); |
| 100 } | 105 } |
| 101 | 106 |
| 102 void PermissionServiceImpl::OnConnectionError() { | 107 void PermissionServiceImpl::OnConnectionError() { |
| 103 CancelPendingOperations(); | 108 CancelPendingOperations(); |
| 104 context_->ServiceHadConnectionError(this); | 109 context_->ServiceHadConnectionError(this); |
| 105 // After that call, |this| will be deleted. | 110 // After that call, |this| will be deleted. |
| 106 } | 111 } |
| 107 | 112 |
| 108 void PermissionServiceImpl::RequestPermission( | 113 void PermissionServiceImpl::RequestPermission( |
| 109 PermissionName permission, | 114 PermissionDescriptorPtr permission, |
| 110 const url::Origin& origin, | 115 const url::Origin& origin, |
| 111 bool user_gesture, | 116 bool user_gesture, |
| 112 const PermissionStatusCallback& callback) { | 117 const PermissionStatusCallback& callback) { |
| 113 // This condition is valid if the call is coming from a ChildThread instead of | 118 // This condition is valid if the call is coming from a ChildThread instead of |
| 114 // a RenderFrame. Some consumers of the service run in Workers and some in | 119 // a RenderFrame. Some consumers of the service run in Workers and some in |
| 115 // Frames. In the context of a Worker, it is not possible to show a | 120 // Frames. In the context of a Worker, it is not possible to show a |
| 116 // permission prompt because there is no tab. In the context of a Frame, we | 121 // permission prompt because there is no tab. In the context of a Frame, we |
| 117 // can. Even if the call comes from a context where it is not possible to show | 122 // can. Even if the call comes from a context where it is not possible to show |
| 118 // any UI, we want to still return something relevant so the current | 123 // any UI, we want to still return something relevant so the current |
| 119 // permission status is returned. | 124 // permission status is returned. |
| 120 BrowserContext* browser_context = context_->GetBrowserContext(); | 125 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 121 DCHECK(browser_context); | 126 DCHECK(browser_context); |
| 122 if (!context_->render_frame_host() || | 127 if (!context_->render_frame_host() || |
| 123 !browser_context->GetPermissionManager()) { | 128 !browser_context->GetPermissionManager()) { |
| 124 callback.Run(GetPermissionStatusFromName(permission, origin)); | 129 callback.Run(GetPermissionStatus(permission, origin)); |
| 125 return; | 130 return; |
| 126 } | 131 } |
| 127 | 132 |
| 128 int pending_request_id = pending_requests_.Add(new PendingRequest( | 133 int pending_request_id = pending_requests_.Add(new PendingRequest( |
| 129 base::Bind(&PermissionRequestResponseCallbackWrapper, callback), 1)); | 134 base::Bind(&PermissionRequestResponseCallbackWrapper, callback), 1)); |
| 130 int id = browser_context->GetPermissionManager()->RequestPermission( | 135 int id = browser_context->GetPermissionManager()->RequestPermission( |
| 131 PermissionNameToPermissionType(permission), context_->render_frame_host(), | 136 PermissionDescriptorToPermissionType(permission), |
| 132 GURL(origin.Serialize()), user_gesture, | 137 context_->render_frame_host(), GURL(origin.Serialize()), user_gesture, |
| 133 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, | 138 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, |
| 134 weak_factory_.GetWeakPtr(), pending_request_id)); | 139 weak_factory_.GetWeakPtr(), pending_request_id)); |
| 135 | 140 |
| 136 // Check if the request still exists. It might have been removed by the | 141 // Check if the request still exists. It might have been removed by the |
| 137 // callback if it was run synchronously. | 142 // callback if it was run synchronously. |
| 138 PendingRequest* pending_request = pending_requests_.Lookup( | 143 PendingRequest* pending_request = pending_requests_.Lookup( |
| 139 pending_request_id); | 144 pending_request_id); |
| 140 if (!pending_request) | 145 if (!pending_request) |
| 141 return; | 146 return; |
| 142 pending_request->id = id; | 147 pending_request->id = id; |
| 143 } | 148 } |
| 144 | 149 |
| 145 void PermissionServiceImpl::OnRequestPermissionResponse( | 150 void PermissionServiceImpl::OnRequestPermissionResponse( |
| 146 int pending_request_id, | 151 int pending_request_id, |
| 147 PermissionStatus status) { | 152 PermissionStatus status) { |
| 148 OnRequestPermissionsResponse(pending_request_id, | 153 OnRequestPermissionsResponse(pending_request_id, |
| 149 std::vector<PermissionStatus>(1, status)); | 154 std::vector<PermissionStatus>(1, status)); |
| 150 } | 155 } |
| 151 | 156 |
| 152 void PermissionServiceImpl::RequestPermissions( | 157 void PermissionServiceImpl::RequestPermissions( |
| 153 const std::vector<PermissionName>& permissions, | 158 std::vector<PermissionDescriptorPtr> permissions, |
| 154 const url::Origin& origin, | 159 const url::Origin& origin, |
| 155 bool user_gesture, | 160 bool user_gesture, |
| 156 const RequestPermissionsCallback& callback) { | 161 const RequestPermissionsCallback& callback) { |
| 157 // This condition is valid if the call is coming from a ChildThread instead of | 162 // This condition is valid if the call is coming from a ChildThread instead of |
| 158 // a RenderFrame. Some consumers of the service run in Workers and some in | 163 // a RenderFrame. Some consumers of the service run in Workers and some in |
| 159 // Frames. In the context of a Worker, it is not possible to show a | 164 // Frames. In the context of a Worker, it is not possible to show a |
| 160 // permission prompt because there is no tab. In the context of a Frame, we | 165 // permission prompt because there is no tab. In the context of a Frame, we |
| 161 // can. Even if the call comes from a context where it is not possible to show | 166 // can. Even if the call comes from a context where it is not possible to show |
| 162 // any UI, we want to still return something relevant so the current | 167 // any UI, we want to still return something relevant so the current |
| 163 // permission status is returned for each permission. | 168 // permission status is returned for each permission. |
| 164 BrowserContext* browser_context = context_->GetBrowserContext(); | 169 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 165 DCHECK(browser_context); | 170 DCHECK(browser_context); |
| 166 if (!context_->render_frame_host() || | 171 if (!context_->render_frame_host() || |
| 167 !browser_context->GetPermissionManager()) { | 172 !browser_context->GetPermissionManager()) { |
| 168 std::vector<PermissionStatus> result(permissions.size()); | 173 std::vector<PermissionStatus> result(permissions.size()); |
| 169 for (size_t i = 0; i < permissions.size(); ++i) { | 174 for (size_t i = 0; i < permissions.size(); ++i) |
| 170 result[i] = GetPermissionStatusFromName(permissions[i], origin); | 175 result[i] = GetPermissionStatus(permissions[i], origin); |
| 171 } | |
| 172 callback.Run(result); | 176 callback.Run(result); |
| 173 return; | 177 return; |
| 174 } | 178 } |
| 175 | 179 |
| 176 std::vector<PermissionType> types(permissions.size()); | 180 std::vector<PermissionType> types(permissions.size()); |
| 177 for (size_t i = 0; i < types.size(); ++i) | 181 for (size_t i = 0; i < types.size(); ++i) |
| 178 types[i] = PermissionNameToPermissionType(permissions[i]); | 182 types[i] = PermissionDescriptorToPermissionType(permissions[i]); |
| 179 | 183 |
| 180 int pending_request_id = pending_requests_.Add( | 184 int pending_request_id = pending_requests_.Add( |
| 181 new PendingRequest(callback, permissions.size())); | 185 new PendingRequest(callback, permissions.size())); |
| 182 int id = browser_context->GetPermissionManager()->RequestPermissions( | 186 int id = browser_context->GetPermissionManager()->RequestPermissions( |
| 183 types, context_->render_frame_host(), GURL(origin.Serialize()), | 187 types, context_->render_frame_host(), GURL(origin.Serialize()), |
| 184 user_gesture, | 188 user_gesture, |
| 185 base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse, | 189 base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse, |
| 186 weak_factory_.GetWeakPtr(), pending_request_id)); | 190 weak_factory_.GetWeakPtr(), pending_request_id)); |
| 187 | 191 |
| 188 // Check if the request still exists. It may have been removed by the | 192 // Check if the request still exists. It may have been removed by the |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( | 230 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( |
| 227 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); | 231 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); |
| 228 it.GetCurrentValue()->callback.Reset(); | 232 it.GetCurrentValue()->callback.Reset(); |
| 229 permission_manager->UnsubscribePermissionStatusChange( | 233 permission_manager->UnsubscribePermissionStatusChange( |
| 230 it.GetCurrentValue()->id); | 234 it.GetCurrentValue()->id); |
| 231 } | 235 } |
| 232 pending_subscriptions_.Clear(); | 236 pending_subscriptions_.Clear(); |
| 233 } | 237 } |
| 234 | 238 |
| 235 void PermissionServiceImpl::HasPermission( | 239 void PermissionServiceImpl::HasPermission( |
| 236 PermissionName permission, | 240 PermissionDescriptorPtr permission, |
| 237 const url::Origin& origin, | 241 const url::Origin& origin, |
| 238 const PermissionStatusCallback& callback) { | 242 const PermissionStatusCallback& callback) { |
| 239 callback.Run(GetPermissionStatusFromName(permission, origin)); | 243 callback.Run(GetPermissionStatus(permission, origin)); |
| 240 } | 244 } |
| 241 | 245 |
| 242 void PermissionServiceImpl::RevokePermission( | 246 void PermissionServiceImpl::RevokePermission( |
| 243 PermissionName permission, | 247 PermissionDescriptorPtr permission, |
| 244 const url::Origin& origin, | 248 const url::Origin& origin, |
| 245 const PermissionStatusCallback& callback) { | 249 const PermissionStatusCallback& callback) { |
| 246 PermissionType permission_type = PermissionNameToPermissionType(permission); | 250 PermissionType permission_type = |
| 251 PermissionDescriptorToPermissionType(permission); |
| 247 PermissionStatus status = | 252 PermissionStatus status = |
| 248 GetPermissionStatusFromType(permission_type, origin); | 253 GetPermissionStatusFromType(permission_type, origin); |
| 249 | 254 |
| 250 // Resetting the permission should only be possible if the permission is | 255 // Resetting the permission should only be possible if the permission is |
| 251 // already granted. | 256 // already granted. |
| 252 if (status != PermissionStatus::GRANTED) { | 257 if (status != PermissionStatus::GRANTED) { |
| 253 callback.Run(status); | 258 callback.Run(status); |
| 254 return; | 259 return; |
| 255 } | 260 } |
| 256 | 261 |
| 257 ResetPermissionStatus(permission_type, origin); | 262 ResetPermissionStatus(permission_type, origin); |
| 258 | 263 |
| 259 callback.Run(GetPermissionStatusFromType(permission_type, origin)); | 264 callback.Run(GetPermissionStatusFromType(permission_type, origin)); |
| 260 } | 265 } |
| 261 | 266 |
| 262 void PermissionServiceImpl::GetNextPermissionChange( | 267 void PermissionServiceImpl::GetNextPermissionChange( |
| 263 PermissionName permission, | 268 PermissionDescriptorPtr permission, |
| 264 const url::Origin& origin, | 269 const url::Origin& origin, |
| 265 PermissionStatus last_known_status, | 270 PermissionStatus last_known_status, |
| 266 const PermissionStatusCallback& callback) { | 271 const PermissionStatusCallback& callback) { |
| 267 PermissionStatus current_status = | 272 PermissionStatus current_status = GetPermissionStatus(permission, origin); |
| 268 GetPermissionStatusFromName(permission, origin); | |
| 269 if (current_status != last_known_status) { | 273 if (current_status != last_known_status) { |
| 270 callback.Run(current_status); | 274 callback.Run(current_status); |
| 271 return; | 275 return; |
| 272 } | 276 } |
| 273 | 277 |
| 274 BrowserContext* browser_context = context_->GetBrowserContext(); | 278 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 275 DCHECK(browser_context); | 279 DCHECK(browser_context); |
| 276 if (!browser_context->GetPermissionManager()) { | 280 if (!browser_context->GetPermissionManager()) { |
| 277 callback.Run(current_status); | 281 callback.Run(current_status); |
| 278 return; | 282 return; |
| 279 } | 283 } |
| 280 | 284 |
| 281 PermissionType permission_type = PermissionNameToPermissionType(permission); | 285 PermissionType permission_type = |
| 286 PermissionDescriptorToPermissionType(permission); |
| 282 | 287 |
| 283 // We need to pass the id of PendingSubscription in pending_subscriptions_ | 288 // We need to pass the id of PendingSubscription in pending_subscriptions_ |
| 284 // to the callback but SubscribePermissionStatusChange() will also return an | 289 // to the callback but SubscribePermissionStatusChange() will also return an |
| 285 // id which is different. | 290 // id which is different. |
| 286 PendingSubscription* subscription = | 291 PendingSubscription* subscription = |
| 287 new PendingSubscription(permission_type, origin, callback); | 292 new PendingSubscription(permission_type, origin, callback); |
| 288 int pending_subscription_id = pending_subscriptions_.Add(subscription); | 293 int pending_subscription_id = pending_subscriptions_.Add(subscription); |
| 289 | 294 |
| 290 GURL requesting_origin(origin.Serialize()); | 295 GURL requesting_origin(origin.Serialize()); |
| 291 GURL embedding_origin = context_->GetEmbeddingOrigin(); | 296 GURL embedding_origin = context_->GetEmbeddingOrigin(); |
| 292 subscription->id = | 297 subscription->id = |
| 293 browser_context->GetPermissionManager()->SubscribePermissionStatusChange( | 298 browser_context->GetPermissionManager()->SubscribePermissionStatusChange( |
| 294 permission_type, requesting_origin, | 299 permission_type, requesting_origin, |
| 295 // If the embedding_origin is empty, we,ll use the |origin| instead. | 300 // If the embedding_origin is empty, we,ll use the |origin| instead. |
| 296 embedding_origin.is_empty() ? requesting_origin : embedding_origin, | 301 embedding_origin.is_empty() ? requesting_origin : embedding_origin, |
| 297 base::Bind(&PermissionServiceImpl::OnPermissionStatusChanged, | 302 base::Bind(&PermissionServiceImpl::OnPermissionStatusChanged, |
| 298 weak_factory_.GetWeakPtr(), pending_subscription_id)); | 303 weak_factory_.GetWeakPtr(), pending_subscription_id)); |
| 299 } | 304 } |
| 300 | 305 |
| 301 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromName( | 306 PermissionStatus PermissionServiceImpl::GetPermissionStatus( |
| 302 PermissionName permission, | 307 const PermissionDescriptorPtr& permission, |
| 303 const url::Origin& origin) { | 308 const url::Origin& origin) { |
| 304 return GetPermissionStatusFromType(PermissionNameToPermissionType(permission), | 309 return GetPermissionStatusFromType( |
| 305 origin); | 310 PermissionDescriptorToPermissionType(permission), origin); |
| 306 } | 311 } |
| 307 | 312 |
| 308 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType( | 313 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType( |
| 309 PermissionType type, | 314 PermissionType type, |
| 310 const url::Origin& origin) { | 315 const url::Origin& origin) { |
| 311 BrowserContext* browser_context = context_->GetBrowserContext(); | 316 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 312 DCHECK(browser_context); | 317 DCHECK(browser_context); |
| 313 if (!browser_context->GetPermissionManager()) | 318 if (!browser_context->GetPermissionManager()) |
| 314 return PermissionStatus::DENIED; | 319 return PermissionStatus::DENIED; |
| 315 | 320 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 356 |
| 352 PermissionStatusCallback callback = subscription->callback; | 357 PermissionStatusCallback callback = subscription->callback; |
| 353 | 358 |
| 354 subscription->callback.Reset(); | 359 subscription->callback.Reset(); |
| 355 pending_subscriptions_.Remove(pending_subscription_id); | 360 pending_subscriptions_.Remove(pending_subscription_id); |
| 356 | 361 |
| 357 callback.Run(status); | 362 callback.Run(status); |
| 358 } | 363 } |
| 359 | 364 |
| 360 } // namespace content | 365 } // namespace content |
| OLD | NEW |