Index: chrome/browser/permissions/permission_manager.cc |
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc |
index 2422d1b170b59ff58ed59115b00421499874be8f..cc3e01d883b7c0a9dc3fe3a199c7d06783c0c38c 100644 |
--- a/chrome/browser/permissions/permission_manager.cc |
+++ b/chrome/browser/permissions/permission_manager.cc |
@@ -78,6 +78,13 @@ ContentSettingsType PermissionTypeToContentSetting(PermissionType permission) { |
return CONTENT_SETTINGS_TYPE_DEFAULT; |
} |
+void PermissionRequestResponseCallbackWrapper( |
+ const base::Callback<void(PermissionStatus)>& callback, |
+ const std::vector<PermissionStatus>& vector) { |
+ DCHECK(vector.size() == 1); |
+ callback.Run(vector[0]); |
+} |
+ |
// Returns whether the permission has a constant PermissionStatus value (i.e. |
// always approved or always denied) |
// The PermissionTypes for which true is returned should be exactly those which |
@@ -114,7 +121,38 @@ PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { |
} // anonymous namespace |
struct PermissionManager::PendingRequest { |
- PermissionType permission; |
+ const GURL requesting_origin; |
+ const size_t count; |
+ size_t pending; |
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)> callback; |
+ |
+ const std::vector<PermissionType> permissions; |
+ std::vector<PermissionStatus> result; |
+ |
+ PendingRequest(const GURL& requesting_origin, |
+ const std::vector<PermissionType> permissions, |
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)>& callback) |
+ : requesting_origin(requesting_origin), |
+ count(permissions.size()), |
+ pending(permissions.size()), |
+ callback(callback), |
+ permissions(permissions), |
+ result(permissions.size(), content::PERMISSION_STATUS_DENIED) { |
+ } |
+ |
+ // Returns if there are no pending permission requests. |
+ bool SetPermission(int index, PermissionStatus status) { |
+ PermissionType current_type = permissions[index]; |
+ for (size_t i = index; i < count; ++i) { |
+ if (permissions[i] != current_type) |
+ continue; |
+ result[i] = status; |
+ pending -= 1; |
+ } |
+ return pending == 0; |
+ } |
}; |
struct PermissionManager::Subscription { |
@@ -141,29 +179,41 @@ int PermissionManager::RequestPermission( |
const GURL& requesting_origin, |
bool user_gesture, |
const base::Callback<void(PermissionStatus)>& callback) { |
- if (IsConstantPermission(permission)) { |
- callback.Run(GetPermissionStatusForConstantPermission(permission)); |
- return -1; |
- } |
+ return RequestPermissionsInternal( |
+ std::vector<PermissionType>(1, permission), |
+ render_frame_host, |
+ requesting_origin, |
+ user_gesture, |
+ base::Bind(&PermissionRequestResponseCallbackWrapper, callback)); |
+} |
- PermissionContextBase* context = PermissionContext::Get(profile_, permission); |
- if (!context) { |
- callback.Run(content::PERMISSION_STATUS_DENIED); |
- return -1; |
- } |
+int PermissionManager::RequestPermissions( |
+ const std::vector<PermissionType>& permissions, |
+ content::RenderFrameHost* render_frame_host, |
+ const GURL& requesting_origin, |
+ bool user_gesture, |
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)>& callback) { |
+ return RequestPermissionsInternal( |
+ permissions, |
+ render_frame_host, |
+ requesting_origin, |
+ user_gesture, |
+ callback); |
+} |
+int PermissionManager::RequestPermissionsInternal( |
+ const std::vector<PermissionType>& permissions, |
+ content::RenderFrameHost* render_frame_host, |
+ const GURL& requesting_origin, |
+ bool user_gesture, |
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)>& callback) { |
content::WebContents* web_contents = |
content::WebContents::FromRenderFrameHost(render_frame_host); |
- if (IsPermissionBubbleManagerMissing(web_contents)) { |
- callback.Run( |
- GetPermissionStatus(permission, requesting_origin, |
- web_contents->GetLastCommittedURL().GetOrigin())); |
- return -1; |
- } |
- PendingRequest* pending_request = new PendingRequest(); |
- pending_request->permission = permission; |
- int request_id = pending_requests_.Add(pending_request); |
+ int request_id = pending_requests_.Add(new PendingRequest( |
+ requesting_origin, permissions, callback)); |
int render_process_id = render_frame_host->GetProcess()->GetID(); |
int render_frame_id = render_frame_host->GetRoutingID(); |
@@ -171,21 +221,56 @@ int PermissionManager::RequestPermission( |
render_frame_id, |
request_id); |
- context->RequestPermission( |
- web_contents, request, requesting_origin, user_gesture, |
- base::Bind(&PermissionManager::OnPermissionRequestResponse, |
- weak_ptr_factory_.GetWeakPtr(), |
- request_id, |
- callback)); |
+ bool seen_types[static_cast<int>(PermissionType::NUM)] = { false }; |
+ for (size_t i = 0; i < permissions.size(); ++i) { |
+ const PermissionType current_type = permissions[i]; |
+ if (seen_types[static_cast<int>(current_type)]) |
+ continue; |
+ seen_types[static_cast<int>(current_type)] = true; |
+ |
+ if (IsConstantPermission(current_type) || |
+ IsPermissionBubbleManagerMissing(web_contents)) { |
+ OnPermissionRequestResponseInternal( |
+ request_id, i, GetPermissionStatus(current_type, requesting_origin, |
+ web_contents->GetLastCommittedURL().GetOrigin())); |
+ continue; |
+ } |
+ |
+ PermissionContextBase* context = |
+ PermissionContext::Get(profile_, current_type); |
+ if (!context) { |
+ OnPermissionRequestResponseInternal( |
+ request_id, i, content::PERMISSION_STATUS_DENIED); |
+ continue; |
+ } |
+ |
+ context->RequestPermission( |
+ content::WebContents::FromRenderFrameHost(render_frame_host), |
+ request, requesting_origin, user_gesture, |
+ base::Bind(&PermissionManager::OnPermissionRequestResponse, |
+ weak_ptr_factory_.GetWeakPtr(), request_id, i)); |
+ } |
return request_id; |
} |
void PermissionManager::OnPermissionRequestResponse( |
int request_id, |
- const base::Callback<void(PermissionStatus)>& callback, |
+ int request_index, |
ContentSetting content_setting) { |
- pending_requests_.Remove(request_id); |
- callback.Run(ContentSettingToPermissionStatus(content_setting)); |
+ OnPermissionRequestResponseInternal(request_id, request_index, |
+ ContentSettingToPermissionStatus(content_setting)); |
+} |
+ |
+void PermissionManager::OnPermissionRequestResponseInternal( |
+ int request_id, |
+ int request_index, |
+ PermissionStatus status) { |
+ PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
+ bool finished = pending_request->SetPermission(request_index, status); |
+ if (finished) { |
+ pending_request->callback.Run(pending_request->result); |
+ pending_requests_.Remove(request_id); |
+ } |
} |
void PermissionManager::CancelPermissionRequest( |
@@ -195,12 +280,6 @@ void PermissionManager::CancelPermissionRequest( |
if (!pending_request) |
return; |
- PermissionContextBase* context = PermissionContext::Get( |
- profile_, pending_request->permission); |
- pending_requests_.Remove(request_id); |
- if (!context) |
- return; |
- |
content::WebContents* web_contents = |
content::WebContents::FromRenderFrameHost(render_frame_host); |
if (IsPermissionBubbleManagerMissing(web_contents)) |
@@ -211,8 +290,14 @@ void PermissionManager::CancelPermissionRequest( |
const PermissionRequestID request(render_process_id, |
render_frame_id, |
request_id); |
- |
- context->CancelPermissionRequest(web_contents, request); |
+ for (size_t i = 0; i < pending_request->count; ++i) { |
+ PermissionContextBase* context = PermissionContext::Get( |
+ profile_, pending_request->permissions[i]); |
+ if (!context) |
+ continue; |
+ context->CancelPermissionRequest(web_contents, request); |
+ } |
+ pending_requests_.Remove(request_id); |
} |
void PermissionManager::ResetPermission(PermissionType permission, |