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

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

Issue 1419083002: Permissions: browser/ side implementation of multiple permissions request. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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/content_settings/host_content_settings_map_factory.h" 8 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
9 #include "chrome/browser/permissions/permission_context.h" 9 #include "chrome/browser/permissions/permission_context.h"
10 #include "chrome/browser/permissions/permission_context_base.h" 10 #include "chrome/browser/permissions/permission_context_base.h"
(...skipping 28 matching lines...) Expand all
39 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: 39 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
40 case CONTENT_SETTING_DEFAULT: 40 case CONTENT_SETTING_DEFAULT:
41 case CONTENT_SETTING_NUM_SETTINGS: 41 case CONTENT_SETTING_NUM_SETTINGS:
42 break; 42 break;
43 } 43 }
44 44
45 NOTREACHED(); 45 NOTREACHED();
46 return content::PERMISSION_STATUS_DENIED; 46 return content::PERMISSION_STATUS_DENIED;
47 } 47 }
48 48
49 // Wrap a callback taking a PermissionStatus to pass it as a callback taking a
50 // ContentSetting.
51 void ContentSettingToPermissionStatusCallbackWrapper(
52 const base::Callback<void(PermissionStatus)>& callback,
53 ContentSetting setting) {
54 callback.Run(ContentSettingToPermissionStatus(setting));
55 }
56
49 // Helper method to convert PermissionType to ContentSettingType. 57 // Helper method to convert PermissionType to ContentSettingType.
50 ContentSettingsType PermissionTypeToContentSetting(PermissionType permission) { 58 ContentSettingsType PermissionTypeToContentSetting(PermissionType permission) {
51 switch (permission) { 59 switch (permission) {
52 case PermissionType::MIDI_SYSEX: 60 case PermissionType::MIDI_SYSEX:
53 return CONTENT_SETTINGS_TYPE_MIDI_SYSEX; 61 return CONTENT_SETTINGS_TYPE_MIDI_SYSEX;
54 case PermissionType::PUSH_MESSAGING: 62 case PermissionType::PUSH_MESSAGING:
55 return CONTENT_SETTINGS_TYPE_PUSH_MESSAGING; 63 return CONTENT_SETTINGS_TYPE_PUSH_MESSAGING;
56 case PermissionType::NOTIFICATIONS: 64 case PermissionType::NOTIFICATIONS:
57 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS; 65 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
58 case PermissionType::GEOLOCATION: 66 case PermissionType::GEOLOCATION:
(...skipping 30 matching lines...) Expand all
89 // return nullptr in PermissionContext::Get since they don't have a context. 97 // return nullptr in PermissionContext::Get since they don't have a context.
90 bool IsConstantPermission(PermissionType type) { 98 bool IsConstantPermission(PermissionType type) {
91 switch (type) { 99 switch (type) {
92 case PermissionType::MIDI: 100 case PermissionType::MIDI:
93 return true; 101 return true;
94 default: 102 default:
95 return false; 103 return false;
96 } 104 }
97 } 105 }
98 106
107 void PermissionRequestResponseCallbackWrapper(
108 const base::Callback<void(PermissionStatus)>& callback,
109 const std::vector<PermissionStatus>& vector) {
110 DCHECK_EQ(vector.size(), 1ul);
111 callback.Run(vector[0]);
112 }
113
99 // Function used for handling permission types which do not change their 114 // Function used for handling permission types which do not change their
100 // value i.e. they are always approved or always denied etc. 115 // value i.e. they are always approved or always denied etc.
101 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. 116 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling.
102 // This function should only be called when IsConstantPermission has returned 117 // This function should only be called when IsConstantPermission has returned
103 // true for the PermissionType. 118 // true for the PermissionType.
104 ContentSetting GetContentSettingForConstantPermission(PermissionType type) { 119 ContentSetting GetContentSettingForConstantPermission(PermissionType type) {
105 DCHECK(IsConstantPermission(type)); 120 DCHECK(IsConstantPermission(type));
106 switch (type) { 121 switch (type) {
107 case PermissionType::MIDI: 122 case PermissionType::MIDI:
108 return CONTENT_SETTING_ALLOW; 123 return CONTENT_SETTING_ALLOW;
109 default: 124 default:
110 return CONTENT_SETTING_DEFAULT; 125 return CONTENT_SETTING_DEFAULT;
111 } 126 }
112 } 127 }
113 128
114 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { 129 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) {
115 return ContentSettingToPermissionStatus( 130 return ContentSettingToPermissionStatus(
116 GetContentSettingForConstantPermission(type)); 131 GetContentSettingForConstantPermission(type));
117 } 132 }
118 133
119 } // anonymous namespace 134 } // anonymous namespace
120 135
121 struct PermissionManager::PendingRequest { 136 class PermissionManager::PendingRequest {
122 PendingRequest(PermissionType permission, 137 public:
123 content::RenderFrameHost* render_frame_host) 138 PendingRequest(content::RenderFrameHost* render_frame_host,
124 : permission(permission), 139 const std::vector<PermissionType> permissions,
125 render_process_id(render_frame_host->GetProcess()->GetID()), 140 const base::Callback<void(
126 render_frame_id(render_frame_host->GetRoutingID()) { 141 const std::vector<PermissionStatus>&)>& callback)
142 : render_process_id_(render_frame_host->GetProcess()->GetID()),
143 render_frame_id_(render_frame_host->GetRoutingID()),
144 callback_(callback),
145 permissions_(permissions),
146 results_(permissions.size(), content::PERMISSION_STATUS_DENIED),
147 remaining_results_(permissions.size()) {
127 } 148 }
128 149
129 PermissionType permission; 150 void SetPermissionStatus(int permission_id, PermissionStatus status) {
130 int render_process_id; 151 DCHECK(!IsComplete());
131 int render_frame_id; 152
153 results_[permission_id] = status;
154 --remaining_results_;
155 }
156
157 bool IsComplete() const {
158 return remaining_results_ == 0;
159 }
160
161 int render_process_id() const { return render_process_id_; }
162 int render_frame_id() const { return render_frame_id_; }
163
164 const base::Callback<void(const std::vector<PermissionStatus>&)>
165 callback() const {
166 return callback_;
167 }
168
169 std::vector<PermissionType> permissions() const {
170 return permissions_;
171 }
172
173 std::vector<PermissionStatus> results() const {
174 return results_;
175 }
176
177 private:
178 int render_process_id_;
179 int render_frame_id_;
180 const base::Callback<void(const std::vector<PermissionStatus>&)> callback_;
181 std::vector<PermissionType> permissions_;
182 std::vector<PermissionStatus> results_;
183 size_t remaining_results_;
132 }; 184 };
133 185
134 struct PermissionManager::Subscription { 186 struct PermissionManager::Subscription {
135 PermissionType permission; 187 PermissionType permission;
136 GURL requesting_origin; 188 GURL requesting_origin;
137 GURL embedding_origin; 189 GURL embedding_origin;
138 base::Callback<void(PermissionStatus)> callback; 190 base::Callback<void(PermissionStatus)> callback;
139 ContentSetting current_value; 191 ContentSetting current_value;
140 }; 192 };
141 193
142 PermissionManager::PermissionManager(Profile* profile) 194 PermissionManager::PermissionManager(Profile* profile)
143 : profile_(profile), 195 : profile_(profile),
144 weak_ptr_factory_(this) { 196 weak_ptr_factory_(this) {
145 } 197 }
146 198
147 PermissionManager::~PermissionManager() { 199 PermissionManager::~PermissionManager() {
148 if (!subscriptions_.IsEmpty()) 200 if (!subscriptions_.IsEmpty())
149 HostContentSettingsMapFactory::GetForProfile(profile_) 201 HostContentSettingsMapFactory::GetForProfile(profile_)
150 ->RemoveObserver(this); 202 ->RemoveObserver(this);
151 } 203 }
152 204
153 int PermissionManager::RequestPermission( 205 int PermissionManager::RequestPermission(
154 PermissionType permission, 206 PermissionType permission,
155 content::RenderFrameHost* render_frame_host, 207 content::RenderFrameHost* render_frame_host,
156 const GURL& requesting_origin, 208 const GURL& requesting_origin,
157 bool user_gesture, 209 bool user_gesture,
158 const base::Callback<void(PermissionStatus)>& callback) { 210 const base::Callback<void(PermissionStatus)>& callback) {
159 if (IsConstantPermission(permission)) { 211 return RequestPermissions(
160 callback.Run(GetPermissionStatusForConstantPermission(permission)); 212 std::vector<PermissionType>(1, permission),
161 return kNoPendingOperation; 213 render_frame_host,
162 } 214 requesting_origin,
215 user_gesture,
216 base::Bind(&PermissionRequestResponseCallbackWrapper, callback));
217 }
163 218
164 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 219 int PermissionManager::RequestPermissions(
165 if (!context) { 220 const std::vector<PermissionType>& permissions,
166 callback.Run(content::PERMISSION_STATUS_DENIED); 221 content::RenderFrameHost* render_frame_host,
222 const GURL& requesting_origin,
223 bool user_gesture,
224 const base::Callback<void(
225 const std::vector<PermissionStatus>&)>& callback) {
226 if (permissions.empty()) {
227 callback.Run(std::vector<PermissionStatus>());
167 return kNoPendingOperation; 228 return kNoPendingOperation;
168 } 229 }
169 230
170 content::WebContents* web_contents = 231 content::WebContents* web_contents =
171 content::WebContents::FromRenderFrameHost(render_frame_host); 232 content::WebContents::FromRenderFrameHost(render_frame_host);
172 if (IsPermissionBubbleManagerMissing(web_contents)) { 233 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
173 callback.Run( 234
174 GetPermissionStatus(permission, requesting_origin, 235 PendingRequest* pending_request = new PendingRequest(
175 web_contents->GetLastCommittedURL().GetOrigin())); 236 render_frame_host, permissions, callback);
176 return kNoPendingOperation; 237 int request_id = pending_requests_.Add(pending_request);
238
239 const PermissionRequestID request(render_frame_host, request_id);
240
241 for (size_t i = 0; i < permissions.size(); ++i) {
242 const PermissionType permission = permissions[i];
243
244 if (IsConstantPermission(permission) ||
245 IsPermissionBubbleManagerMissing(web_contents) ||
246 !PermissionContext::Get(profile_, permission)) {
247 OnPermissionsRequestResponseStatus(request_id, i,
248 GetPermissionStatus(permission, requesting_origin, embedding_origin));
249 continue;
250 }
251
252 PermissionContextBase* context = PermissionContext::Get(
253 profile_, permission);
254 context->RequestPermission(
255 web_contents, request, requesting_origin, user_gesture,
256 base::Bind(&ContentSettingToPermissionStatusCallbackWrapper,
257 base::Bind(&PermissionManager::OnPermissionsRequestResponseStatus,
258 weak_ptr_factory_.GetWeakPtr(), request_id, i)));
177 } 259 }
178 260
179 PendingRequest* pending_request = new PendingRequest( 261 // The request might have been resolved already.
180 permission, render_frame_host); 262 if (!pending_requests_.Lookup(request_id))
181 int request_id = pending_requests_.Add(pending_request); 263 return kNoPendingOperation;
182 const PermissionRequestID request(pending_request->render_process_id,
183 pending_request->render_frame_id,
184 request_id);
185 264
186 context->RequestPermission(
187 web_contents, request, requesting_origin, user_gesture,
188 base::Bind(&PermissionManager::OnPermissionRequestResponse,
189 weak_ptr_factory_.GetWeakPtr(),
190 request_id,
191 callback));
192 return request_id; 265 return request_id;
193 } 266 }
194 267
195 void PermissionManager::OnPermissionRequestResponse( 268 void PermissionManager::OnPermissionsRequestResponseStatus(
196 int request_id, 269 int request_id,
197 const base::Callback<void(PermissionStatus)>& callback, 270 int permission_id,
198 ContentSetting content_setting) { 271 PermissionStatus status) {
272 PendingRequest* pending_request = pending_requests_.Lookup(request_id);
273 pending_request->SetPermissionStatus(permission_id, status);
274
275 if (!pending_request->IsComplete())
276 return;
277
278 pending_request->callback().Run(pending_request->results());
199 pending_requests_.Remove(request_id); 279 pending_requests_.Remove(request_id);
200 callback.Run(ContentSettingToPermissionStatus(content_setting));
201 } 280 }
202 281
203 void PermissionManager::CancelPermissionRequest(int request_id) { 282 void PermissionManager::CancelPermissionRequest(int request_id) {
204 PendingRequest* pending_request = pending_requests_.Lookup(request_id); 283 PendingRequest* pending_request = pending_requests_.Lookup(request_id);
205 if (!pending_request) 284 if (!pending_request)
206 return; 285 return;
207 286
208 PermissionContextBase* context = PermissionContext::Get(
209 profile_, pending_request->permission);
210 if (!context)
211 return;
212
213 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( 287 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID(
214 pending_request->render_process_id, pending_request->render_frame_id); 288 pending_request->render_process_id(), pending_request->render_frame_id());
215 DCHECK(web_contents); 289 DCHECK(web_contents);
216 if (IsPermissionBubbleManagerMissing(web_contents)) { 290 if (IsPermissionBubbleManagerMissing(web_contents)) {
217 pending_requests_.Remove(request_id); 291 pending_requests_.Remove(request_id);
218 return; 292 return;
219 } 293 }
220 294
221 const PermissionRequestID request(pending_request->render_process_id, 295 const PermissionRequestID request(pending_request->render_process_id(),
222 pending_request->render_frame_id, 296 pending_request->render_frame_id(),
223 request_id); 297 request_id);
224 context->CancelPermissionRequest(web_contents, request); 298 for (PermissionType permission : pending_request->permissions()) {
299 PermissionContextBase* context = PermissionContext::Get(
300 profile_, permission);
301 if (!context)
302 continue;
303 context->CancelPermissionRequest(web_contents, request);
304 }
225 pending_requests_.Remove(request_id); 305 pending_requests_.Remove(request_id);
226 } 306 }
227 307
228 void PermissionManager::ResetPermission(PermissionType permission, 308 void PermissionManager::ResetPermission(PermissionType permission,
229 const GURL& requesting_origin, 309 const GURL& requesting_origin,
230 const GURL& embedding_origin) { 310 const GURL& embedding_origin) {
231 PermissionContextBase* context = PermissionContext::Get(profile_, permission); 311 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
232 if (!context) 312 if (!context)
233 return; 313 return;
234 314
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 // Add the callback to |callbacks| which will be run after the loop to 421 // Add the callback to |callbacks| which will be run after the loop to
342 // prevent re-entrance issues. 422 // prevent re-entrance issues.
343 callbacks.push_back( 423 callbacks.push_back(
344 base::Bind(subscription->callback, 424 base::Bind(subscription->callback,
345 ContentSettingToPermissionStatus(new_value))); 425 ContentSettingToPermissionStatus(new_value)));
346 } 426 }
347 427
348 for (const auto& callback : callbacks) 428 for (const auto& callback : callbacks)
349 callback.Run(); 429 callback.Run();
350 } 430 }
OLDNEW
« no previous file with comments | « chrome/browser/permissions/permission_manager.h ('k') | chrome/browser/permissions/permission_request_id.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698