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

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

Issue 1316863010: browser: implement multiple permission requesting (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@request-multiple-content
Patch Set: Cut down on CL size Created 5 years, 3 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 case PermissionType::NUM: 71 case PermissionType::NUM:
72 // This will hit the NOTREACHED below. 72 // This will hit the NOTREACHED below.
73 break; 73 break;
74 } 74 }
75 75
76 NOTREACHED() << "Unknown content setting for permission " 76 NOTREACHED() << "Unknown content setting for permission "
77 << static_cast<int>(permission); 77 << static_cast<int>(permission);
78 return CONTENT_SETTINGS_TYPE_DEFAULT; 78 return CONTENT_SETTINGS_TYPE_DEFAULT;
79 } 79 }
80 80
81 void PermissionRequestResponseCallbackWrapper(
82 const base::Callback<void(PermissionStatus)>& callback,
83 const std::vector<PermissionStatus>& vector) {
84 DCHECK(vector.size() == 1);
85 callback.Run(vector[0]);
86 }
87
81 // Returns whether the permission has a constant PermissionStatus value (i.e. 88 // Returns whether the permission has a constant PermissionStatus value (i.e.
82 // always approved or always denied) 89 // always approved or always denied)
83 // The PermissionTypes for which true is returned should be exactly those which 90 // The PermissionTypes for which true is returned should be exactly those which
84 // return nullptr in PermissionContext::Get since they don't have a context. 91 // return nullptr in PermissionContext::Get since they don't have a context.
85 bool IsConstantPermission(PermissionType type) { 92 bool IsConstantPermission(PermissionType type) {
86 switch (type) { 93 switch (type) {
87 case PermissionType::MIDI: 94 case PermissionType::MIDI:
88 return true; 95 return true;
89 default: 96 default:
90 return false; 97 return false;
(...skipping 16 matching lines...) Expand all
107 } 114 }
108 115
109 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { 116 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) {
110 return ContentSettingToPermissionStatus( 117 return ContentSettingToPermissionStatus(
111 GetContentSettingForConstantPermission(type)); 118 GetContentSettingForConstantPermission(type));
112 } 119 }
113 120
114 } // anonymous namespace 121 } // anonymous namespace
115 122
116 struct PermissionManager::PendingRequest { 123 struct PermissionManager::PendingRequest {
117 PermissionType permission; 124 const GURL requesting_origin;
125 const size_t count;
126 size_t pending;
127 const base::Callback<void(
128 const std::vector<PermissionStatus>&)> callback;
129
130 const std::vector<PermissionType> permissions;
131 std::vector<PermissionStatus> result;
132
133 PendingRequest(const GURL& requesting_origin,
134 const std::vector<PermissionType> permissions,
135 const base::Callback<void(
136 const std::vector<PermissionStatus>&)>& callback)
137 : requesting_origin(requesting_origin),
138 count(permissions.size()),
139 pending(permissions.size()),
140 callback(callback),
141 permissions(permissions),
142 result(permissions.size(), content::PERMISSION_STATUS_DENIED) {
143 }
144
145 // Returns if there are no pending permission requests.
146 bool SetPermission(int index, PermissionStatus status) {
147 PermissionType current_type = permissions[index];
148 for (size_t i = index; i < count; ++i) {
149 if (permissions[i] != current_type)
150 continue;
151 result[i] = status;
152 pending -= 1;
153 }
154 return pending == 0;
155 }
118 }; 156 };
119 157
120 struct PermissionManager::Subscription { 158 struct PermissionManager::Subscription {
121 PermissionType permission; 159 PermissionType permission;
122 GURL requesting_origin; 160 GURL requesting_origin;
123 GURL embedding_origin; 161 GURL embedding_origin;
124 base::Callback<void(PermissionStatus)> callback; 162 base::Callback<void(PermissionStatus)> callback;
125 ContentSetting current_value; 163 ContentSetting current_value;
126 }; 164 };
127 165
128 PermissionManager::PermissionManager(Profile* profile) 166 PermissionManager::PermissionManager(Profile* profile)
129 : profile_(profile), 167 : profile_(profile),
130 weak_ptr_factory_(this) { 168 weak_ptr_factory_(this) {
131 } 169 }
132 170
133 PermissionManager::~PermissionManager() { 171 PermissionManager::~PermissionManager() {
134 if (!subscriptions_.IsEmpty()) 172 if (!subscriptions_.IsEmpty())
135 profile_->GetHostContentSettingsMap()->RemoveObserver(this); 173 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
136 } 174 }
137 175
138 int PermissionManager::RequestPermission( 176 int PermissionManager::RequestPermission(
139 PermissionType permission, 177 PermissionType permission,
140 content::RenderFrameHost* render_frame_host, 178 content::RenderFrameHost* render_frame_host,
141 const GURL& requesting_origin, 179 const GURL& requesting_origin,
142 bool user_gesture, 180 bool user_gesture,
143 const base::Callback<void(PermissionStatus)>& callback) { 181 const base::Callback<void(PermissionStatus)>& callback) {
144 if (IsConstantPermission(permission)) { 182 return RequestPermissionsInternal(
145 callback.Run(GetPermissionStatusForConstantPermission(permission)); 183 std::vector<PermissionType>(1, permission),
146 return -1; 184 render_frame_host,
147 } 185 requesting_origin,
186 user_gesture,
187 base::Bind(&PermissionRequestResponseCallbackWrapper, callback));
188 }
148 189
149 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 190 int PermissionManager::RequestPermissions(
150 if (!context) { 191 const std::vector<PermissionType>& permissions,
151 callback.Run(content::PERMISSION_STATUS_DENIED); 192 content::RenderFrameHost* render_frame_host,
152 return -1; 193 const GURL& requesting_origin,
153 } 194 bool user_gesture,
195 const base::Callback<void(
196 const std::vector<PermissionStatus>&)>& callback) {
197 return RequestPermissionsInternal(
198 permissions,
199 render_frame_host,
200 requesting_origin,
201 user_gesture,
202 callback);
203 }
154 204
205 int PermissionManager::RequestPermissionsInternal(
206 const std::vector<PermissionType>& permissions,
207 content::RenderFrameHost* render_frame_host,
208 const GURL& requesting_origin,
209 bool user_gesture,
210 const base::Callback<void(
211 const std::vector<PermissionStatus>&)>& callback) {
155 content::WebContents* web_contents = 212 content::WebContents* web_contents =
156 content::WebContents::FromRenderFrameHost(render_frame_host); 213 content::WebContents::FromRenderFrameHost(render_frame_host);
157 if (IsPermissionBubbleManagerMissing(web_contents)) {
158 callback.Run(
159 GetPermissionStatus(permission, requesting_origin,
160 web_contents->GetLastCommittedURL().GetOrigin()));
161 return -1;
162 }
163 214
164 PendingRequest* pending_request = new PendingRequest(); 215 int request_id = pending_requests_.Add(new PendingRequest(
165 pending_request->permission = permission; 216 requesting_origin, permissions, callback));
166 int request_id = pending_requests_.Add(pending_request);
167 217
168 int render_process_id = render_frame_host->GetProcess()->GetID(); 218 int render_process_id = render_frame_host->GetProcess()->GetID();
169 int render_frame_id = render_frame_host->GetRoutingID(); 219 int render_frame_id = render_frame_host->GetRoutingID();
170 const PermissionRequestID request(render_process_id, 220 const PermissionRequestID request(render_process_id,
171 render_frame_id, 221 render_frame_id,
172 request_id); 222 request_id);
173 223
174 context->RequestPermission( 224 bool seen_types[static_cast<int>(PermissionType::NUM)] = { false };
175 web_contents, request, requesting_origin, user_gesture, 225 for (size_t i = 0; i < permissions.size(); ++i) {
176 base::Bind(&PermissionManager::OnPermissionRequestResponse, 226 const PermissionType current_type = permissions[i];
177 weak_ptr_factory_.GetWeakPtr(), 227 if (seen_types[static_cast<int>(current_type)])
178 request_id, 228 continue;
179 callback)); 229 seen_types[static_cast<int>(current_type)] = true;
230
231 if (IsConstantPermission(current_type) ||
232 IsPermissionBubbleManagerMissing(web_contents)) {
233 OnPermissionRequestResponseInternal(
234 request_id, i, GetPermissionStatus(current_type, requesting_origin,
235 web_contents->GetLastCommittedURL().GetOrigin()));
236 continue;
237 }
238
239 PermissionContextBase* context =
240 PermissionContext::Get(profile_, current_type);
241 if (!context) {
242 OnPermissionRequestResponseInternal(
243 request_id, i, content::PERMISSION_STATUS_DENIED);
244 continue;
245 }
246
247 context->RequestPermission(
248 content::WebContents::FromRenderFrameHost(render_frame_host),
249 request, requesting_origin, user_gesture,
250 base::Bind(&PermissionManager::OnPermissionRequestResponse,
251 weak_ptr_factory_.GetWeakPtr(), request_id, i));
252 }
180 return request_id; 253 return request_id;
181 } 254 }
182 255
183 void PermissionManager::OnPermissionRequestResponse( 256 void PermissionManager::OnPermissionRequestResponse(
184 int request_id, 257 int request_id,
185 const base::Callback<void(PermissionStatus)>& callback, 258 int request_index,
186 ContentSetting content_setting) { 259 ContentSetting content_setting) {
187 pending_requests_.Remove(request_id); 260 OnPermissionRequestResponseInternal(request_id, request_index,
188 callback.Run(ContentSettingToPermissionStatus(content_setting)); 261 ContentSettingToPermissionStatus(content_setting));
262 }
263
264 void PermissionManager::OnPermissionRequestResponseInternal(
265 int request_id,
266 int request_index,
267 PermissionStatus status) {
268 PendingRequest* pending_request = pending_requests_.Lookup(request_id);
269 bool finished = pending_request->SetPermission(request_index, status);
270 if (finished) {
271 pending_request->callback.Run(pending_request->result);
272 pending_requests_.Remove(request_id);
273 }
189 } 274 }
190 275
191 void PermissionManager::CancelPermissionRequest( 276 void PermissionManager::CancelPermissionRequest(
192 content::RenderFrameHost* render_frame_host, 277 content::RenderFrameHost* render_frame_host,
193 int request_id) { 278 int request_id) {
194 PendingRequest* pending_request = pending_requests_.Lookup(request_id); 279 PendingRequest* pending_request = pending_requests_.Lookup(request_id);
195 if (!pending_request) 280 if (!pending_request)
196 return; 281 return;
197 282
198 PermissionContextBase* context = PermissionContext::Get(
199 profile_, pending_request->permission);
200 pending_requests_.Remove(request_id);
201 if (!context)
202 return;
203
204 content::WebContents* web_contents = 283 content::WebContents* web_contents =
205 content::WebContents::FromRenderFrameHost(render_frame_host); 284 content::WebContents::FromRenderFrameHost(render_frame_host);
206 if (IsPermissionBubbleManagerMissing(web_contents)) 285 if (IsPermissionBubbleManagerMissing(web_contents))
207 return; 286 return;
208 287
209 int render_process_id = render_frame_host->GetProcess()->GetID(); 288 int render_process_id = render_frame_host->GetProcess()->GetID();
210 int render_frame_id = render_frame_host->GetRoutingID(); 289 int render_frame_id = render_frame_host->GetRoutingID();
211 const PermissionRequestID request(render_process_id, 290 const PermissionRequestID request(render_process_id,
212 render_frame_id, 291 render_frame_id,
213 request_id); 292 request_id);
214 293 for (size_t i = 0; i < pending_request->count; ++i) {
215 context->CancelPermissionRequest(web_contents, request); 294 PermissionContextBase* context = PermissionContext::Get(
295 profile_, pending_request->permissions[i]);
296 if (!context)
297 continue;
298 context->CancelPermissionRequest(web_contents, request);
299 }
300 pending_requests_.Remove(request_id);
216 } 301 }
217 302
218 void PermissionManager::ResetPermission(PermissionType permission, 303 void PermissionManager::ResetPermission(PermissionType permission,
219 const GURL& requesting_origin, 304 const GURL& requesting_origin,
220 const GURL& embedding_origin) { 305 const GURL& embedding_origin) {
221 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 306 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
222 if (!context) 307 if (!context)
223 return; 308 return;
224 309
225 context->ResetPermission(requesting_origin.GetOrigin(), 310 context->ResetPermission(requesting_origin.GetOrigin(),
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 // Add the callback to |callbacks| which will be run after the loop to 417 // Add the callback to |callbacks| which will be run after the loop to
333 // prevent re-entrance issues. 418 // prevent re-entrance issues.
334 callbacks.push_back( 419 callbacks.push_back(
335 base::Bind(subscription->callback, 420 base::Bind(subscription->callback,
336 ContentSettingToPermissionStatus(new_value))); 421 ContentSettingToPermissionStatus(new_value)));
337 } 422 }
338 423
339 for (const auto& callback : callbacks) 424 for (const auto& callback : callbacks)
340 callback.Run(); 425 callback.Run();
341 } 426 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698