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/browser/permissions/permission_pending_multiple_request.h" |
| 9 #include "content/browser/permissions/permission_pending_single_request.h" |
8 #include "content/public/browser/browser_context.h" | 10 #include "content/public/browser/browser_context.h" |
9 #include "content/public/browser/permission_manager.h" | 11 #include "content/public/browser/permission_manager.h" |
10 #include "content/public/browser/permission_type.h" | 12 #include "content/public/browser/permission_type.h" |
11 | 13 |
12 namespace content { | 14 namespace content { |
13 | 15 |
14 namespace { | 16 namespace { |
15 | 17 |
16 PermissionType PermissionNameToPermissionType(PermissionName name) { | 18 PermissionType PermissionNameToPermissionType(PermissionName name) { |
17 switch(name) { | 19 switch(name) { |
18 case PERMISSION_NAME_GEOLOCATION: | 20 case PERMISSION_NAME_GEOLOCATION: |
19 return PermissionType::GEOLOCATION; | 21 return PermissionType::GEOLOCATION; |
20 case PERMISSION_NAME_NOTIFICATIONS: | 22 case PERMISSION_NAME_NOTIFICATIONS: |
21 return PermissionType::NOTIFICATIONS; | 23 return PermissionType::NOTIFICATIONS; |
22 case PERMISSION_NAME_PUSH_NOTIFICATIONS: | 24 case PERMISSION_NAME_PUSH_NOTIFICATIONS: |
23 return PermissionType::PUSH_MESSAGING; | 25 return PermissionType::PUSH_MESSAGING; |
24 case PERMISSION_NAME_MIDI_SYSEX: | 26 case PERMISSION_NAME_MIDI_SYSEX: |
25 return PermissionType::MIDI_SYSEX; | 27 return PermissionType::MIDI_SYSEX; |
26 case PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER: | 28 case PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER: |
27 return PermissionType::PROTECTED_MEDIA_IDENTIFIER; | 29 return PermissionType::PROTECTED_MEDIA_IDENTIFIER; |
28 } | 30 } |
29 | 31 |
30 NOTREACHED(); | 32 NOTREACHED(); |
31 return PermissionType::NUM; | 33 return PermissionType::NUM; |
32 } | 34 } |
33 | 35 |
34 } // anonymous namespace | 36 } // anonymous namespace |
35 | 37 |
36 PermissionServiceImpl::PendingRequest::PendingRequest( | |
37 PermissionType permission, | |
38 const GURL& origin, | |
39 const PermissionStatusCallback& callback) | |
40 : permission(permission), | |
41 origin(origin), | |
42 callback(callback) { | |
43 } | |
44 | |
45 PermissionServiceImpl::PendingRequest::~PendingRequest() { | |
46 if (!callback.is_null()) | |
47 callback.Run(PERMISSION_STATUS_ASK); | |
48 } | |
49 | |
50 PermissionServiceImpl::PendingSubscription::PendingSubscription( | 38 PermissionServiceImpl::PendingSubscription::PendingSubscription( |
51 PermissionType permission, | 39 PermissionType permission, |
52 const GURL& origin, | 40 const GURL& origin, |
53 const PermissionStatusCallback& callback) | 41 const PermissionStatusCallback& callback) |
54 : id(-1), | 42 : id(-1), |
55 permission(permission), | 43 permission(permission), |
56 origin(origin), | 44 origin(origin), |
57 callback(callback) { | 45 callback(callback) { |
58 } | 46 } |
59 | 47 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 } | 90 } |
103 | 91 |
104 BrowserContext* browser_context = context_->GetBrowserContext(); | 92 BrowserContext* browser_context = context_->GetBrowserContext(); |
105 DCHECK(browser_context); | 93 DCHECK(browser_context); |
106 if (!browser_context->GetPermissionManager()) { | 94 if (!browser_context->GetPermissionManager()) { |
107 callback.Run(content::PERMISSION_STATUS_DENIED); | 95 callback.Run(content::PERMISSION_STATUS_DENIED); |
108 return; | 96 return; |
109 } | 97 } |
110 | 98 |
111 PermissionType permission_type = PermissionNameToPermissionType(permission); | 99 PermissionType permission_type = PermissionNameToPermissionType(permission); |
112 int request_id = pending_requests_.Add( | 100 |
113 new PendingRequest(permission_type, GURL(origin), callback)); | 101 PermissionPendingSingleRequest* request = |
| 102 new PermissionPendingSingleRequest( |
| 103 permission_type, GURL(origin), callback); |
| 104 int request_id = pending_requests_.Add(request); |
114 | 105 |
115 browser_context->GetPermissionManager()->RequestPermission( | 106 browser_context->GetPermissionManager()->RequestPermission( |
116 permission_type, | 107 permission_type, |
117 context_->render_frame_host(), | 108 context_->render_frame_host(), |
118 request_id, | 109 request_id, |
119 GURL(origin), | 110 GURL(origin), |
120 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) | 111 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) |
121 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, | 112 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse, |
122 weak_factory_.GetWeakPtr(), | 113 weak_factory_.GetWeakPtr(), |
123 request_id)); | 114 request_id, |
| 115 request)); |
| 116 } |
| 117 |
| 118 void PermissionServiceImpl::RequestPermissions( |
| 119 mojo::Array<PermissionName> permissions, |
| 120 const mojo::String& origin, |
| 121 bool user_gesture, |
| 122 const PermissionsStatusCallback& callback) { |
| 123 if (permissions.is_null()) { |
| 124 callback.Run(mojo::Array<PermissionStatus>()); |
| 125 return; |
| 126 } |
| 127 |
| 128 // This condition is valid if the call is coming from a ChildThread instead of |
| 129 // a RenderFrame. Some consumers of the service run in Workers and some in |
| 130 // Frames. In the context of a Worker, it is not possible to show a |
| 131 // permission prompt because there is no tab. In the context of a Frame, we |
| 132 // can. Even if the call comes from a context where it is not possible to show |
| 133 // any UI, we want to still return something relevant so the current |
| 134 // permission status is returned for each permission. |
| 135 if (!context_->render_frame_host()) { |
| 136 mojo::Array<PermissionStatus> result(permissions.size()); |
| 137 for (size_t i = 0; i < permissions.size(); ++i) { |
| 138 result[i] = GetPermissionStatusFromName(permissions[i], GURL(origin)); |
| 139 } |
| 140 callback.Run(result.Pass()); |
| 141 return; |
| 142 } |
| 143 |
| 144 BrowserContext* browser_context = context_->GetBrowserContext(); |
| 145 DCHECK(browser_context); |
| 146 if (!browser_context->GetPermissionManager()) { |
| 147 mojo::Array<PermissionStatus> result(permissions.size()); |
| 148 for (size_t i = 0; i < permissions.size(); ++i) { |
| 149 result[i] = PERMISSION_STATUS_DENIED; |
| 150 } |
| 151 callback.Run(result.Pass()); |
| 152 return; |
| 153 } |
| 154 |
| 155 std::vector<PermissionType> permission_types; |
| 156 permission_types.reserve(permissions.size()); |
| 157 for (size_t i = 0; i < permissions.size(); ++i) { |
| 158 permission_types.push_back( |
| 159 PermissionNameToPermissionType(permissions[i])); |
| 160 } |
| 161 PermissionPendingMultipleRequest* request = |
| 162 new PermissionPendingMultipleRequest(callback, permissions.size()); |
| 163 int request_id = pending_requests_.Add(request); |
| 164 |
| 165 browser_context->GetPermissionManager()->RequestPermissions( |
| 166 permission_types, |
| 167 context_->render_frame_host(), |
| 168 request_id, |
| 169 GURL(origin), |
| 170 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770) |
| 171 base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse, |
| 172 weak_factory_.GetWeakPtr(), |
| 173 request_id, |
| 174 request)); |
124 } | 175 } |
125 | 176 |
126 void PermissionServiceImpl::OnRequestPermissionResponse( | 177 void PermissionServiceImpl::OnRequestPermissionResponse( |
127 int request_id, | 178 int request_id, |
| 179 PermissionPendingSingleRequest* request, |
128 PermissionStatus status) { | 180 PermissionStatus status) { |
129 PendingRequest* request = pending_requests_.Lookup(request_id); | |
130 PermissionStatusCallback callback(request->callback); | 181 PermissionStatusCallback callback(request->callback); |
131 request->callback.reset(); | 182 request->callback.reset(); |
132 pending_requests_.Remove(request_id); | 183 pending_requests_.Remove(request_id); |
| 184 |
133 callback.Run(status); | 185 callback.Run(status); |
134 } | 186 } |
135 | 187 |
| 188 void PermissionServiceImpl::OnRequestPermissionsResponse( |
| 189 int request_id, |
| 190 PermissionPendingMultipleRequest* request, |
| 191 const std::vector<PermissionStatus>& status) { |
| 192 PermissionsStatusCallback callback(request->callback); |
| 193 request->callback.reset(); |
| 194 pending_requests_.Remove(request_id); |
| 195 |
| 196 mojo::Array<PermissionStatus> status_array(status.size()); |
| 197 for (size_t i = 0; i < status.size(); i++) { |
| 198 status_array[i] = status[i]; |
| 199 } |
| 200 callback.Run(status_array.Pass()); |
| 201 } |
| 202 |
136 void PermissionServiceImpl::CancelPendingOperations() { | 203 void PermissionServiceImpl::CancelPendingOperations() { |
137 DCHECK(context_->render_frame_host()); | 204 DCHECK(context_->render_frame_host()); |
138 DCHECK(context_->GetBrowserContext()); | 205 DCHECK(context_->GetBrowserContext()); |
139 | 206 |
140 PermissionManager* permission_manager = | 207 PermissionManager* permission_manager = |
141 context_->GetBrowserContext()->GetPermissionManager(); | 208 context_->GetBrowserContext()->GetPermissionManager(); |
142 if (!permission_manager) | 209 if (!permission_manager) |
143 return; | 210 return; |
144 | 211 |
145 // Cancel pending requests. | 212 // Cancel pending requests. |
146 for (RequestsMap::Iterator<PendingRequest> it(&pending_requests_); | 213 for (RequestsMap::Iterator<PermissionPendingRequest> it(&pending_requests_); |
147 !it.IsAtEnd(); it.Advance()) { | 214 !it.IsAtEnd(); it.Advance()) { |
148 permission_manager->CancelPermissionRequest( | 215 it.GetCurrentValue()->Cancel(permission_manager, |
149 it.GetCurrentValue()->permission, | 216 context_->render_frame_host(), |
150 context_->render_frame_host(), | 217 it.GetCurrentKey()); |
151 it.GetCurrentKey(), | |
152 it.GetCurrentValue()->origin); | |
153 } | 218 } |
154 pending_requests_.Clear(); | 219 pending_requests_.Clear(); |
155 | 220 |
156 // Cancel pending subscriptions. | 221 // Cancel pending subscriptions. |
157 for (SubscriptionsMap::Iterator<PendingSubscription> | 222 for (SubscriptionsMap::Iterator<PendingSubscription> |
158 it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) { | 223 it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) { |
159 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( | 224 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType( |
160 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); | 225 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin)); |
161 it.GetCurrentValue()->callback.reset(); | 226 it.GetCurrentValue()->callback.reset(); |
162 permission_manager->UnsubscribePermissionStatusChange( | 227 permission_manager->UnsubscribePermissionStatusChange( |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 | 346 |
282 PermissionStatusCallback callback = subscription->callback; | 347 PermissionStatusCallback callback = subscription->callback; |
283 | 348 |
284 subscription->callback.reset(); | 349 subscription->callback.reset(); |
285 pending_subscriptions_.Remove(pending_subscription_id); | 350 pending_subscriptions_.Remove(pending_subscription_id); |
286 | 351 |
287 callback.Run(status); | 352 callback.Run(status); |
288 } | 353 } |
289 | 354 |
290 } // namespace content | 355 } // namespace content |
OLD | NEW |