Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: chrome/browser/permissions/permission_manager.cc

Issue 1260193009: renderer: implement multiple permission requesting (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@permissions-request-multiple
Patch Set: Rebase on top of other change Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/permissions/permission_context.h" 8 #include "chrome/browser/permissions/permission_context.h"
9 #include "chrome/browser/permissions/permission_context_base.h" 9 #include "chrome/browser/permissions/permission_context_base.h"
10 #include "chrome/browser/permissions/permission_request_id.h" 10 #include "chrome/browser/permissions/permission_request_id.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 case PermissionType::NUM: 66 case PermissionType::NUM:
67 // This will hit the NOTREACHED below. 67 // This will hit the NOTREACHED below.
68 break; 68 break;
69 } 69 }
70 70
71 NOTREACHED() << "Unknown content setting for permission " 71 NOTREACHED() << "Unknown content setting for permission "
72 << static_cast<int>(permission); 72 << static_cast<int>(permission);
73 return CONTENT_SETTINGS_TYPE_DEFAULT; 73 return CONTENT_SETTINGS_TYPE_DEFAULT;
74 } 74 }
75 75
76 // Helper method that wraps a callback a void(PermissionStatus) 76 void PermissionRequestResponseCallbackWrapper(
77 // callback into a void(ContentSetting) callback.
78 void PermissionStatusCallbackWrapper(
79 const base::Callback<void(PermissionStatus)>& callback, 77 const base::Callback<void(PermissionStatus)>& callback,
80 ContentSetting content_setting) { 78 const std::vector<PermissionStatus>& vector) {
81 callback.Run(ContentSettingToPermissionStatus(content_setting)); 79 DCHECK(vector.size() == 1);
80 callback.Run(vector[0]);
82 } 81 }
83 82
84 // Returns whether the permission has a constant PermissionStatus value (i.e. 83 // Returns whether the permission has a constant PermissionStatus value (i.e.
85 // always approved or always denied) 84 // always approved or always denied)
86 // The PermissionTypes for which true is returned should be exactly those which 85 // The PermissionTypes for which true is returned should be exactly those which
87 // 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.
88 bool IsConstantPermission(PermissionType type) { 87 bool IsConstantPermission(PermissionType type) {
89 switch (type) { 88 switch (type) {
90 case PermissionType::MIDI: 89 case PermissionType::MIDI:
91 return true; 90 return true;
(...skipping 17 matching lines...) Expand all
109 } 108 }
110 } 109 }
111 110
112 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { 111 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) {
113 return ContentSettingToPermissionStatus( 112 return ContentSettingToPermissionStatus(
114 GetContentSettingForConstantPermission(type)); 113 GetContentSettingForConstantPermission(type));
115 } 114 }
116 115
117 } // anonymous namespace 116 } // anonymous namespace
118 117
118 struct PermissionManager::PendingResponse {
119 PermissionType type;
120 PermissionStatus status;
121
122 PendingResponse(PermissionType type, PermissionStatus status)
123 : type(type), status(status) {
124 }
125 };
126
127 struct PermissionManager::PendingResponses {
128 GURL requesting_origin;
129 size_t count;
130 size_t pending;
131 std::vector<PendingResponse> responses;
132 };
133
119 struct PermissionManager::Subscription { 134 struct PermissionManager::Subscription {
120 PermissionType permission; 135 PermissionType permission;
121 GURL requesting_origin; 136 GURL requesting_origin;
122 GURL embedding_origin; 137 GURL embedding_origin;
123 base::Callback<void(PermissionStatus)> callback; 138 base::Callback<void(PermissionStatus)> callback;
124 ContentSetting current_value; 139 ContentSetting current_value;
125 }; 140 };
126 141
127 PermissionManager::PermissionManager(Profile* profile) 142 PermissionManager::PermissionManager(Profile* profile)
128 : profile_(profile) { 143 : profile_(profile),
144 weak_ptr_factory_(this) {
129 } 145 }
130 146
131 PermissionManager::~PermissionManager() { 147 PermissionManager::~PermissionManager() {
132 if (!subscriptions_.IsEmpty()) 148 if (!subscriptions_.IsEmpty())
133 profile_->GetHostContentSettingsMap()->RemoveObserver(this); 149 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
134 } 150 }
135 151
136 void PermissionManager::RequestPermission( 152 void PermissionManager::RequestPermission(
137 PermissionType permission, 153 PermissionType permission,
138 content::RenderFrameHost* render_frame_host, 154 content::RenderFrameHost* render_frame_host,
139 int request_id, 155 int request_id,
140 const GURL& requesting_origin, 156 const GURL& requesting_origin,
141 bool user_gesture, 157 bool user_gesture,
142 const base::Callback<void(PermissionStatus)>& callback) { 158 const RequestCallback& callback) {
143 if (IsConstantPermission(permission)) { 159 RequestPermissionInternal(
144 callback.Run(GetPermissionStatusForConstantPermission(permission)); 160 std::vector<PermissionType>(1, permission),
145 return; 161 render_frame_host,
146 } 162 request_id,
163 requesting_origin,
164 user_gesture,
165 base::Bind(&PermissionRequestResponseCallbackWrapper, callback));
166 }
147 167
148 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 168 void PermissionManager::RequestPermission(
149 if (!context) { 169 const std::vector<PermissionType>& permissions,
150 callback.Run(content::PERMISSION_STATUS_DENIED); 170 content::RenderFrameHost* render_frame_host,
151 return; 171 int request_id,
152 } 172 const GURL& requesting_origin,
173 bool user_gesture,
174 const BatchRequestCallback& callback) {
175 RequestPermissionInternal(permissions, render_frame_host, request_id,
176 requesting_origin, user_gesture, callback);
177 }
153 178
179 void PermissionManager::RequestPermissionInternal(
180 const std::vector<PermissionType>& permissions,
181 content::RenderFrameHost* render_frame_host,
182 int request_id,
183 const GURL& requesting_origin,
184 bool user_gesture,
185 const BatchRequestCallback& callback) {
154 int render_process_id = render_frame_host->GetProcess()->GetID(); 186 int render_process_id = render_frame_host->GetProcess()->GetID();
155 int render_frame_id = render_frame_host->GetRoutingID(); 187 int render_frame_id = render_frame_host->GetRoutingID();
156 const PermissionRequestID request(render_process_id, 188 const PermissionRequestID request(render_process_id,
157 render_frame_id, 189 render_frame_id,
158 request_id, 190 request_id,
159 requesting_origin); 191 requesting_origin);
160 192
161 context->RequestPermission( 193 // Pass complete control of the scoped pointer to the map.
162 content::WebContents::FromRenderFrameHost(render_frame_host), 194 // Locally we will use the raw pointer and the response will be removed from
163 request, requesting_origin, user_gesture, 195 // the map once all the responses return.
164 base::Bind(&PermissionStatusCallbackWrapper, 196 scoped_ptr<PendingResponses> scoped_response(new PendingResponses());
165 callback)); 197 PendingResponses* pending_responses = scoped_response.get();
198 pending_responses_.add(request_id, scoped_response.Pass());
199
200 pending_responses->requesting_origin = requesting_origin;
201 pending_responses->count = permissions.size();
202 pending_responses->pending = permissions.size();
203
204 for (size_t i = 0; i < permissions.size(); ++i) {
205 pending_responses->responses.emplace_back(
206 permissions[i],
207 content::PERMISSION_STATUS_DENIED);
208 }
209
210 // The pending responses should all be added to the vector before running
211 // this loop so duplicate permissions are handled properly.
212 bool seen_types[static_cast<int>(PermissionType::NUM)] = { false };
213 for (size_t i = 0; i < permissions.size(); ++i) {
214 const PermissionType current_type = permissions[i];
215 const int current_type_index = static_cast<int>(current_type);
216 if (seen_types[current_type_index])
217 continue;
218 seen_types[current_type_index] = true;
219
220 if (IsConstantPermission(current_type)) {
221 OnRequestResponse(callback, request, pending_responses, i,
222 GetContentSettingForConstantPermission(current_type));
223 continue;
224 }
225
226 PermissionContextBase* context =
227 PermissionContext::Get(profile_, current_type);
228 if (!context) {
229 OnRequestResponse(callback, request, pending_responses, i,
230 CONTENT_SETTING_BLOCK);
231 continue;
232 }
233 context->RequestPermission(
234 content::WebContents::FromRenderFrameHost(render_frame_host),
235 request, requesting_origin, user_gesture,
236 base::Bind(&PermissionManager::OnRequestResponse,
237 weak_ptr_factory_.GetWeakPtr(),
238 callback,
239 request,
240 pending_responses,
241 i));
242 }
243 }
244
245 void PermissionManager::OnRequestResponse(const BatchRequestCallback& callback,
246 const PermissionRequestID request,
247 PendingResponses* pending_responses,
248 int index,
249 ContentSetting content_setting) {
250 PendingResponse& response = pending_responses->responses[index];
251 response.status = ContentSettingToPermissionStatus(content_setting);
252
253 for (size_t i = index + 1; i < pending_responses->responses.size(); ++i) {
254 if (pending_responses->responses[i].type == response.type) {
255 pending_responses->responses[i].status = response.status;
256 --pending_responses->pending;
257 }
258 }
259
260 if (pending_responses->pending == 1) {
261 std::vector<PermissionStatus> status;
262 for (auto response : pending_responses->responses)
263 status.push_back(response.status);
264 pending_responses_.erase(request.request_id());
265 callback.Run(status);
266 }
166 } 267 }
167 268
168 void PermissionManager::CancelPermissionRequest( 269 void PermissionManager::CancelPermissionRequest(
169 PermissionType permission,
170 content::RenderFrameHost* render_frame_host, 270 content::RenderFrameHost* render_frame_host,
171 int request_id, 271 int request_id) {
172 const GURL& requesting_origin) { 272 PendingResponses* pending_responses =
173 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 273 pending_responses_.get(request_id);
174 if (!context)
175 return;
176 274
177 int render_process_id = render_frame_host->GetProcess()->GetID(); 275 int render_process_id = render_frame_host->GetProcess()->GetID();
178 int render_frame_id = render_frame_host->GetRoutingID(); 276 int render_frame_id = render_frame_host->GetRoutingID();
179 const PermissionRequestID request(render_process_id, 277 const PermissionRequestID request(render_process_id,
180 render_frame_id, 278 render_frame_id,
181 request_id, 279 request_id,
182 requesting_origin); 280 pending_responses->requesting_origin);
183 281
184 context->CancelPermissionRequest( 282 for (size_t i = 0; i < pending_responses->count; ++i) {
185 content::WebContents::FromRenderFrameHost(render_frame_host), request); 283 PermissionType type = pending_responses->responses[i].type;
284 PermissionContextBase* context = PermissionContext::Get(profile_, type);
285 if (!context) continue;
286
287 context->CancelPermissionRequest(
288 content::WebContents::FromRenderFrameHost(render_frame_host), request);
289 }
290 pending_responses_.erase(request_id);
186 } 291 }
187 292
188 void PermissionManager::ResetPermission(PermissionType permission, 293 void PermissionManager::ResetPermission(PermissionType permission,
189 const GURL& requesting_origin, 294 const GURL& requesting_origin,
190 const GURL& embedding_origin) { 295 const GURL& embedding_origin) {
191 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 296 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
192 if (!context) 297 if (!context)
193 return; 298 return;
194 299
195 context->ResetPermission(requesting_origin.GetOrigin(), 300 context->ResetPermission(requesting_origin.GetOrigin(),
(...skipping 27 matching lines...) Expand all
223 profile_->GetHostContentSettingsMap()->UpdateLastUsage( 328 profile_->GetHostContentSettingsMap()->UpdateLastUsage(
224 requesting_origin, 329 requesting_origin,
225 embedding_origin, 330 embedding_origin,
226 PermissionTypeToContentSetting(permission)); 331 PermissionTypeToContentSetting(permission));
227 } 332 }
228 333
229 int PermissionManager::SubscribePermissionStatusChange( 334 int PermissionManager::SubscribePermissionStatusChange(
230 PermissionType permission, 335 PermissionType permission,
231 const GURL& requesting_origin, 336 const GURL& requesting_origin,
232 const GURL& embedding_origin, 337 const GURL& embedding_origin,
233 const base::Callback<void(PermissionStatus)>& callback) { 338 const RequestCallback& callback) {
234 if (subscriptions_.IsEmpty()) 339 if (subscriptions_.IsEmpty())
235 profile_->GetHostContentSettingsMap()->AddObserver(this); 340 profile_->GetHostContentSettingsMap()->AddObserver(this);
236 341
237 Subscription* subscription = new Subscription(); 342 Subscription* subscription = new Subscription();
238 subscription->permission = permission; 343 subscription->permission = permission;
239 subscription->requesting_origin = requesting_origin; 344 subscription->requesting_origin = requesting_origin;
240 subscription->embedding_origin = embedding_origin; 345 subscription->embedding_origin = embedding_origin;
241 subscription->callback = callback; 346 subscription->callback = callback;
242 347
243 if (IsConstantPermission(permission)) { 348 if (IsConstantPermission(permission)) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 // Add the callback to |callbacks| which will be run after the loop to 399 // Add the callback to |callbacks| which will be run after the loop to
295 // prevent re-entrance issues. 400 // prevent re-entrance issues.
296 callbacks.push_back( 401 callbacks.push_back(
297 base::Bind(subscription->callback, 402 base::Bind(subscription->callback,
298 ContentSettingToPermissionStatus(new_value))); 403 ContentSettingToPermissionStatus(new_value)));
299 } 404 }
300 405
301 for (const auto& callback : callbacks) 406 for (const auto& callback : callbacks)
302 callback.Run(); 407 callback.Run();
303 } 408 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698