Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / content / browser / permissions / permission_service_impl.cc
blob795c93b471f24bd7970086f75932463501b7e01f
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
3 // found in the LICENSE file.
5 #include "content/browser/permissions/permission_service_impl.h"
7 #include "base/bind.h"
8 #include "content/public/browser/browser_context.h"
9 #include "content/public/browser/permission_manager.h"
10 #include "content/public/browser/permission_type.h"
12 namespace content {
14 namespace {
16 PermissionType PermissionNameToPermissionType(PermissionName name) {
17 switch(name) {
18 case PERMISSION_NAME_GEOLOCATION:
19 return PermissionType::GEOLOCATION;
20 case PERMISSION_NAME_NOTIFICATIONS:
21 return PermissionType::NOTIFICATIONS;
22 case PERMISSION_NAME_PUSH_NOTIFICATIONS:
23 return PermissionType::PUSH_MESSAGING;
24 case PERMISSION_NAME_MIDI_SYSEX:
25 return PermissionType::MIDI_SYSEX;
26 case PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER:
27 return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
30 NOTREACHED();
31 return PermissionType::NUM;
34 } // anonymous namespace
36 PermissionServiceImpl::PendingRequest::PendingRequest(
37 PermissionType permission,
38 const GURL& origin,
39 const PermissionStatusCallback& callback)
40 : permission(permission),
41 origin(origin),
42 callback(callback) {
45 PermissionServiceImpl::PendingRequest::~PendingRequest() {
46 if (!callback.is_null())
47 callback.Run(PERMISSION_STATUS_ASK);
50 PermissionServiceImpl::PendingSubscription::PendingSubscription(
51 PermissionType permission,
52 const GURL& origin,
53 const PermissionStatusCallback& callback)
54 : id(-1),
55 permission(permission),
56 origin(origin),
57 callback(callback) {
60 PermissionServiceImpl::PendingSubscription::~PendingSubscription() {
61 if (!callback.is_null())
62 callback.Run(PERMISSION_STATUS_ASK);
65 PermissionServiceImpl::PermissionServiceImpl(
66 PermissionServiceContext* context,
67 mojo::InterfaceRequest<PermissionService> request)
68 : context_(context),
69 binding_(this, request.Pass()),
70 weak_factory_(this) {
71 binding_.set_connection_error_handler(
72 base::Bind(&PermissionServiceImpl::OnConnectionError,
73 base::Unretained(this)));
76 PermissionServiceImpl::~PermissionServiceImpl() {
77 DCHECK(pending_requests_.IsEmpty());
80 void PermissionServiceImpl::OnConnectionError() {
81 context_->ServiceHadConnectionError(this);
82 // After that call, |this| will be deleted.
85 void PermissionServiceImpl::RequestPermission(
86 PermissionName permission,
87 const mojo::String& origin,
88 bool user_gesture,
89 const PermissionStatusCallback& callback) {
90 // This condition is valid if the call is coming from a ChildThread instead of
91 // a RenderFrame. Some consumers of the service run in Workers and some in
92 // Frames. In the context of a Worker, it is not possible to show a
93 // permission prompt because there is no tab. In the context of a Frame, we
94 // can. Even if the call comes from a context where it is not possible to show
95 // any UI, we want to still return something relevant so the current
96 // permission status is returned.
97 if (!context_->render_frame_host()) {
98 // There is no way to show a UI so the call will simply return the current
99 // permission.
100 HasPermission(permission, origin, callback);
101 return;
104 BrowserContext* browser_context = context_->GetBrowserContext();
105 DCHECK(browser_context);
106 if (!browser_context->GetPermissionManager()) {
107 callback.Run(content::PERMISSION_STATUS_DENIED);
108 return;
111 PermissionType permission_type = PermissionNameToPermissionType(permission);
112 int request_id = pending_requests_.Add(
113 new PendingRequest(permission_type, GURL(origin), callback));
115 browser_context->GetPermissionManager()->RequestPermission(
116 permission_type,
117 context_->render_frame_host(),
118 request_id,
119 GURL(origin),
120 user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770)
121 base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse,
122 weak_factory_.GetWeakPtr(),
123 request_id));
126 void PermissionServiceImpl::OnRequestPermissionResponse(
127 int request_id,
128 PermissionStatus status) {
129 PendingRequest* request = pending_requests_.Lookup(request_id);
130 PermissionStatusCallback callback(request->callback);
131 request->callback.reset();
132 pending_requests_.Remove(request_id);
133 callback.Run(status);
136 void PermissionServiceImpl::CancelPendingOperations() {
137 DCHECK(context_->render_frame_host());
138 DCHECK(context_->GetBrowserContext());
140 PermissionManager* permission_manager =
141 context_->GetBrowserContext()->GetPermissionManager();
142 if (!permission_manager)
143 return;
145 // Cancel pending requests.
146 for (RequestsMap::Iterator<PendingRequest> it(&pending_requests_);
147 !it.IsAtEnd(); it.Advance()) {
148 permission_manager->CancelPermissionRequest(
149 it.GetCurrentValue()->permission,
150 context_->render_frame_host(),
151 it.GetCurrentKey(),
152 it.GetCurrentValue()->origin);
154 pending_requests_.Clear();
156 // Cancel pending subscriptions.
157 for (SubscriptionsMap::Iterator<PendingSubscription>
158 it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) {
159 it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType(
160 it.GetCurrentValue()->permission, it.GetCurrentValue()->origin));
161 it.GetCurrentValue()->callback.reset();
162 permission_manager->UnsubscribePermissionStatusChange(
163 it.GetCurrentValue()->id);
165 pending_subscriptions_.Clear();
168 void PermissionServiceImpl::HasPermission(
169 PermissionName permission,
170 const mojo::String& origin,
171 const PermissionStatusCallback& callback) {
172 callback.Run(GetPermissionStatusFromName(permission, GURL(origin)));
175 void PermissionServiceImpl::RevokePermission(
176 PermissionName permission,
177 const mojo::String& origin,
178 const PermissionStatusCallback& callback) {
179 GURL origin_url(origin);
180 PermissionType permission_type = PermissionNameToPermissionType(permission);
181 PermissionStatus status = GetPermissionStatusFromType(permission_type,
182 origin_url);
184 // Resetting the permission should only be possible if the permission is
185 // already granted.
186 if (status != PERMISSION_STATUS_GRANTED) {
187 callback.Run(status);
188 return;
191 ResetPermissionStatus(permission_type, origin_url);
193 callback.Run(GetPermissionStatusFromType(permission_type, origin_url));
196 void PermissionServiceImpl::GetNextPermissionChange(
197 PermissionName permission,
198 const mojo::String& mojo_origin,
199 PermissionStatus last_known_status,
200 const PermissionStatusCallback& callback) {
201 GURL origin(mojo_origin);
202 PermissionStatus current_status =
203 GetPermissionStatusFromName(permission, origin);
204 if (current_status != last_known_status) {
205 callback.Run(current_status);
206 return;
209 BrowserContext* browser_context = context_->GetBrowserContext();
210 DCHECK(browser_context);
211 if (!browser_context->GetPermissionManager()) {
212 callback.Run(current_status);
213 return;
216 PermissionType permission_type = PermissionNameToPermissionType(permission);
218 // We need to pass the id of PendingSubscription in pending_subscriptions_
219 // to the callback but SubscribePermissionStatusChange() will also return an
220 // id which is different.
221 PendingSubscription* subscription =
222 new PendingSubscription(permission_type, origin, callback);
223 int pending_subscription_id = pending_subscriptions_.Add(subscription);
225 GURL embedding_origin = context_->GetEmbeddingOrigin();
226 subscription->id =
227 browser_context->GetPermissionManager()->SubscribePermissionStatusChange(
228 permission_type,
229 origin,
230 // If the embedding_origin is empty, we,ll use the |origin| instead.
231 embedding_origin.is_empty() ? origin : embedding_origin,
232 base::Bind(&PermissionServiceImpl::OnPermissionStatusChanged,
233 weak_factory_.GetWeakPtr(),
234 pending_subscription_id));
237 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromName(
238 PermissionName permission, const GURL& origin) {
239 return GetPermissionStatusFromType(PermissionNameToPermissionType(permission),
240 origin);
243 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
244 PermissionType type, const GURL& origin) {
245 BrowserContext* browser_context = context_->GetBrowserContext();
246 DCHECK(browser_context);
247 if (!browser_context->GetPermissionManager())
248 return PERMISSION_STATUS_DENIED;
250 // If the embedding_origin is empty we'll use |origin| instead.
251 GURL embedding_origin = context_->GetEmbeddingOrigin();
252 return browser_context->GetPermissionManager()->GetPermissionStatus(
253 type, origin, embedding_origin.is_empty() ? origin : embedding_origin);
256 void PermissionServiceImpl::ResetPermissionStatus(PermissionType type,
257 const GURL& origin) {
258 BrowserContext* browser_context = context_->GetBrowserContext();
259 DCHECK(browser_context);
260 if (!browser_context->GetPermissionManager())
261 return;
263 // If the embedding_origin is empty we'll use |origin| instead.
264 GURL embedding_origin = context_->GetEmbeddingOrigin();
265 browser_context->GetPermissionManager()->ResetPermission(
266 type, origin, embedding_origin.is_empty() ? origin : embedding_origin);
269 void PermissionServiceImpl::OnPermissionStatusChanged(
270 int pending_subscription_id,
271 PermissionStatus status) {
272 PendingSubscription* subscription =
273 pending_subscriptions_.Lookup(pending_subscription_id);
275 BrowserContext* browser_context = context_->GetBrowserContext();
276 DCHECK(browser_context);
277 if (browser_context->GetPermissionManager()) {
278 browser_context->GetPermissionManager()->UnsubscribePermissionStatusChange(
279 subscription->id);
282 PermissionStatusCallback callback = subscription->callback;
284 subscription->callback.reset();
285 pending_subscriptions_.Remove(pending_subscription_id);
287 callback.Run(status);
290 } // namespace content