| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "content/public/browser/browser_context.h" | 8 #include "content/public/browser/browser_context.h" |
| 9 #include "content/public/browser/permission_manager.h" | 9 #include "content/public/browser/permission_manager.h" |
| 10 #include "content/public/browser/permission_type.h" | 10 #include "content/public/browser/permission_type.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 case PERMISSION_NAME_AUDIO_CAPTURE: | 32 case PERMISSION_NAME_AUDIO_CAPTURE: |
| 33 return PermissionType::AUDIO_CAPTURE; | 33 return PermissionType::AUDIO_CAPTURE; |
| 34 case PERMISSION_NAME_VIDEO_CAPTURE: | 34 case PERMISSION_NAME_VIDEO_CAPTURE: |
| 35 return PermissionType::VIDEO_CAPTURE; | 35 return PermissionType::VIDEO_CAPTURE; |
| 36 } | 36 } |
| 37 | 37 |
| 38 NOTREACHED(); | 38 NOTREACHED(); |
| 39 return PermissionType::NUM; | 39 return PermissionType::NUM; |
| 40 } | 40 } |
| 41 | 41 |
| 42 // This function allows the usage of the the multiple request map |
| 43 // with single requests. |
| 44 void PermissionRequestResponseCallbackWrapper( |
| 45 const mojo::Callback<void(PermissionStatus)>& callback, |
| 46 const mojo::Array<PermissionStatus>& vector) { |
| 47 DCHECK_EQ(1ul, vector.size()); |
| 48 callback.Run(vector[0]); |
| 49 } |
| 50 |
| 42 } // anonymous namespace | 51 } // anonymous namespace |
| 43 | 52 |
| 44 PermissionServiceImpl::PendingRequest::PendingRequest( | 53 PermissionServiceImpl::PendingRequest::PendingRequest( |
| 45 PermissionType permission, | 54 const PermissionsStatusCallback& callback, |
| 46 const GURL& origin, | 55 int request_count) |
| 47 const PermissionStatusCallback& callback) | 56 : callback(callback), |
| 48 : id(PermissionManager::kNoPendingOperation), | 57 request_count(request_count) { |
| 49 permission(permission), | |
| 50 origin(origin), | |
| 51 callback(callback) { | |
| 52 } | 58 } |
| 53 | 59 |
| 54 PermissionServiceImpl::PendingRequest::~PendingRequest() { | 60 PermissionServiceImpl::PendingRequest::~PendingRequest() { |
| 55 if (!callback.is_null()) | 61 if (!callback.is_null()) { |
| 56 callback.Run(PERMISSION_STATUS_ASK); | 62 mojo::Array<PermissionStatus> result = |
| 63 mojo::Array<PermissionStatus>::New(request_count); |
| 64 for (int i = 0; i < request_count; ++i) |
| 65 result[i] = PERMISSION_STATUS_DENIED; |
| 66 callback.Run(result.Pass()); |
| 67 } |
| 57 } | 68 } |
| 58 | 69 |
| 59 PermissionServiceImpl::PendingSubscription::PendingSubscription( | 70 PermissionServiceImpl::PendingSubscription::PendingSubscription( |
| 60 PermissionType permission, | 71 PermissionType permission, |
| 61 const GURL& origin, | 72 const GURL& origin, |
| 62 const PermissionStatusCallback& callback) | 73 const PermissionStatusCallback& callback) |
| 63 : id(-1), | 74 : id(-1), |
| 64 permission(permission), | 75 permission(permission), |
| 65 origin(origin), | 76 origin(origin), |
| 66 callback(callback) { | 77 callback(callback) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 96 const mojo::String& origin, | 107 const mojo::String& origin, |
| 97 bool user_gesture, | 108 bool user_gesture, |
| 98 const PermissionStatusCallback& callback) { | 109 const PermissionStatusCallback& callback) { |
| 99 // This condition is valid if the call is coming from a ChildThread instead of | 110 // This condition is valid if the call is coming from a ChildThread instead of |
| 100 // a RenderFrame. Some consumers of the service run in Workers and some in | 111 // a RenderFrame. Some consumers of the service run in Workers and some in |
| 101 // Frames. In the context of a Worker, it is not possible to show a | 112 // Frames. In the context of a Worker, it is not possible to show a |
| 102 // permission prompt because there is no tab. In the context of a Frame, we | 113 // permission prompt because there is no tab. In the context of a Frame, we |
| 103 // can. Even if the call comes from a context where it is not possible to show | 114 // can. Even if the call comes from a context where it is not possible to show |
| 104 // any UI, we want to still return something relevant so the current | 115 // any UI, we want to still return something relevant so the current |
| 105 // permission status is returned. | 116 // permission status is returned. |
| 106 if (!context_->render_frame_host()) { | 117 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 107 // There is no way to show a UI so the call will simply return the current | 118 DCHECK(browser_context); |
| 108 // permission. | 119 if (!context_->render_frame_host() || |
| 109 HasPermission(permission, origin, callback); | 120 !browser_context->GetPermissionManager()) { |
| 121 callback.Run(GetPermissionStatusFromName(permission, GURL(origin))); |
| 110 return; | 122 return; |
| 111 } | 123 } |
| 112 | 124 |
| 113 BrowserContext* browser_context = context_->GetBrowserContext(); | 125 int pending_request_id = pending_requests_.Add(new PendingRequest( |
| 114 DCHECK(browser_context); | 126 base::Bind(&PermissionRequestResponseCallbackWrapper, callback), 1)); |
| 115 if (!browser_context->GetPermissionManager()) { | |
| 116 callback.Run(content::PERMISSION_STATUS_DENIED); | |
| 117 return; | |
| 118 } | |
| 119 | |
| 120 PermissionType permission_type = PermissionNameToPermissionType(permission); | |
| 121 int pending_request_id = pending_requests_.Add( | |
| 122 new PendingRequest(permission_type, GURL(origin), callback)); | |
| 123 | |
| 124 int id = browser_context->GetPermissionManager()->RequestPermission( | 127 int id = browser_context->GetPermissionManager()->RequestPermission( |
| 125 permission_type, | 128 PermissionNameToPermissionType(permission), |
| 126 context_->render_frame_host(), | 129 context_->render_frame_host(), |
| 127 GURL(origin), | 130 GURL(origin), |
| 128 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) | 131 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) |
| 129 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, | 132 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, |
| 130 weak_factory_.GetWeakPtr(), | 133 weak_factory_.GetWeakPtr(), |
| 131 pending_request_id)); | 134 pending_request_id)); |
| 132 | 135 |
| 133 // Check if the request still exists. It might have been removed by the | 136 // Check if the request still exists. It might have been removed by the |
| 134 // callback if it was run synchronously. | 137 // callback if it was run synchronously. |
| 135 PendingRequest* pending_request = pending_requests_.Lookup( | 138 PendingRequest* pending_request = pending_requests_.Lookup( |
| 136 pending_request_id); | 139 pending_request_id); |
| 137 if (!pending_request) | 140 if (!pending_request) |
| 138 return; | 141 return; |
| 139 pending_request->id = id; | 142 pending_request->id = id; |
| 140 } | 143 } |
| 141 | 144 |
| 145 void PermissionServiceImpl::OnRequestPermissionResponse( |
| 146 int pending_request_id, |
| 147 PermissionStatus status) { |
| 148 OnRequestPermissionsResponse(pending_request_id, |
| 149 std::vector<PermissionStatus>(1, status)); |
| 150 } |
| 151 |
| 142 void PermissionServiceImpl::RequestPermissions( | 152 void PermissionServiceImpl::RequestPermissions( |
| 143 mojo::Array<PermissionName> permissions, | 153 mojo::Array<PermissionName> permissions, |
| 144 const mojo::String& origin, | 154 const mojo::String& origin, |
| 145 bool user_gesture, | 155 bool user_gesture, |
| 146 const PermissionsStatusCallback& callback) { | 156 const PermissionsStatusCallback& callback) { |
| 147 // TODO(lalitm,mlamouri): this is returning the current permission statuses | 157 if (permissions.is_null()) { |
| 148 // in order for the call to successfully return. It will be changed later. | 158 callback.Run(mojo::Array<PermissionStatus>()); |
| 149 // See https://crbug.com/516626 | 159 return; |
| 150 mojo::Array<PermissionStatus> result(permissions.size()); | 160 } |
| 151 for (size_t i = 0; i < permissions.size(); ++i) | 161 |
| 152 result[i] = GetPermissionStatusFromName(permissions[i], GURL(origin)); | 162 // This condition is valid if the call is coming from a ChildThread instead of |
| 153 callback.Run(result.Pass()); | 163 // a RenderFrame. Some consumers of the service run in Workers and some in |
| 164 // Frames. In the context of a Worker, it is not possible to show a |
| 165 // permission prompt because there is no tab. In the context of a Frame, we |
| 166 // can. Even if the call comes from a context where it is not possible to show |
| 167 // any UI, we want to still return something relevant so the current |
| 168 // permission status is returned for each permission. |
| 169 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 170 DCHECK(browser_context); |
| 171 if (!context_->render_frame_host() || |
| 172 !browser_context->GetPermissionManager()) { |
| 173 mojo::Array<PermissionStatus> result(permissions.size()); |
| 174 for (size_t i = 0; i < permissions.size(); ++i) |
| 175 result[i] = GetPermissionStatusFromName(permissions[i], GURL(origin)); |
| 176 callback.Run(result.Pass()); |
| 177 return; |
| 178 } |
| 179 |
| 180 std::vector<PermissionType> types(permissions.size()); |
| 181 for (size_t i = 0; i < types.size(); ++i) |
| 182 types[i] = PermissionNameToPermissionType(permissions[i]); |
| 183 |
| 184 int pending_request_id = pending_requests_.Add( |
| 185 new PendingRequest(callback, permissions.size())); |
| 186 int id = browser_context->GetPermissionManager()->RequestPermissions( |
| 187 types, |
| 188 context_->render_frame_host(), |
| 189 GURL(origin), |
| 190 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) |
| 191 base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse, |
| 192 weak_factory_.GetWeakPtr(), |
| 193 pending_request_id)); |
| 194 |
| 195 // Check if the request still exists. It may have been removed by the |
| 196 // the response callback. |
| 197 PendingRequest* pending_request = pending_requests_.Lookup( |
| 198 pending_request_id); |
| 199 if (!pending_request) |
| 200 return; |
| 201 pending_request->id = id; |
| 154 } | 202 } |
| 155 | 203 |
| 156 void PermissionServiceImpl::OnRequestPermissionResponse( | 204 void PermissionServiceImpl::OnRequestPermissionsResponse( |
| 157 int request_id, | 205 int pending_request_id, |
| 158 PermissionStatus status) { | 206 const std::vector<PermissionStatus>& result) { |
| 159 PendingRequest* request = pending_requests_.Lookup(request_id); | 207 PendingRequest* request = pending_requests_.Lookup(pending_request_id); |
| 160 PermissionStatusCallback callback(request->callback); | 208 PermissionsStatusCallback callback(request->callback); |
| 161 request->callback.reset(); | 209 request->callback.reset(); |
| 162 pending_requests_.Remove(request_id); | 210 pending_requests_.Remove(pending_request_id); |
| 163 callback.Run(status); | 211 callback.Run(mojo::Array<PermissionStatus>::From(result)); |
| 164 } | 212 } |
| 165 | 213 |
| 166 void PermissionServiceImpl::CancelPendingOperations() { | 214 void PermissionServiceImpl::CancelPendingOperations() { |
| 167 DCHECK(context_->render_frame_host()); | |
| 168 DCHECK(context_->GetBrowserContext()); | 215 DCHECK(context_->GetBrowserContext()); |
| 169 | 216 |
| 170 PermissionManager* permission_manager = | 217 PermissionManager* permission_manager = |
| 171 context_->GetBrowserContext()->GetPermissionManager(); | 218 context_->GetBrowserContext()->GetPermissionManager(); |
| 172 if (!permission_manager) | 219 if (!permission_manager) |
| 173 return; | 220 return; |
| 174 | 221 |
| 175 // Cancel pending requests. | 222 // Cancel pending requests. |
| 176 for (RequestsMap::Iterator<PendingRequest> it(&pending_requests_); | 223 for (RequestsMap::Iterator<PendingRequest> it(&pending_requests_); |
| 177 !it.IsAtEnd(); it.Advance()) { | 224 !it.IsAtEnd(); it.Advance()) { |
| 178 permission_manager->CancelPermissionRequest( | 225 permission_manager->CancelPermissionRequest( |
| 179 it.GetCurrentValue()->permission, | 226 it.GetCurrentValue()->id); |
| 180 context_->render_frame_host(), | |
| 181 it.GetCurrentKey(), | |
| 182 it.GetCurrentValue()->origin); | |
| 183 } | 227 } |
| 184 pending_requests_.Clear(); | 228 pending_requests_.Clear(); |
| 185 | 229 |
| 186 // Cancel pending subscriptions. | 230 // Cancel pending subscriptions. |
| 187 for (SubscriptionsMap::Iterator<PendingSubscription> | 231 for (SubscriptionsMap::Iterator<PendingSubscription> |
| 188 it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) { | 232 it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) { |
| 189 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( | 233 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( |
| 190 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); | 234 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); |
| 191 it.GetCurrentValue()->callback.reset(); | 235 it.GetCurrentValue()->callback.reset(); |
| 192 permission_manager->UnsubscribePermissionStatusChange( | 236 permission_manager->UnsubscribePermissionStatusChange( |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 | 355 |
| 312 PermissionStatusCallback callback = subscription->callback; | 356 PermissionStatusCallback callback = subscription->callback; |
| 313 | 357 |
| 314 subscription->callback.reset(); | 358 subscription->callback.reset(); |
| 315 pending_subscriptions_.Remove(pending_subscription_id); | 359 pending_subscriptions_.Remove(pending_subscription_id); |
| 316 | 360 |
| 317 callback.Run(status); | 361 callback.Run(status); |
| 318 } | 362 } |
| 319 | 363 |
| 320 } // namespace content | 364 } // namespace content |
| OLD | NEW |