Index: chrome/browser/permissions/permission_manager.cc |
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc |
index ff670c218d814c63055b102e700079476397b1e5..15168b41848bc9eef7800868a4d28f46777bd8c3 100644 |
--- a/chrome/browser/permissions/permission_manager.cc |
+++ b/chrome/browser/permissions/permission_manager.cc |
@@ -93,6 +93,13 @@ bool IsConstantPermission(PermissionType type) { |
} |
} |
+void PermissionRequestResponseCallbackWrapper( |
+ const base::Callback<void(PermissionStatus)>& callback, |
+ const std::vector<PermissionStatus>& vector) { |
+ DCHECK(vector.size() == 1); |
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: DCHECK_EQ()
Lalit Maganti
2015/09/24 09:24:11
Done.
|
+ callback.Run(vector[0]); |
+} |
+ |
// Function used for handling permission types which do not change their |
// value i.e. they are always approved or always denied etc. |
// CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. |
@@ -116,9 +123,56 @@ PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { |
} // anonymous namespace |
struct PermissionManager::PendingRequest { |
- PermissionType permission; |
+ PendingRequest(content::RenderFrameHost* render_frame_host, |
+ const GURL& requesting_origin, |
+ const std::vector<PermissionType> types, |
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)>& callback) |
+ : render_process_id(render_frame_host->GetProcess()->GetID()), |
+ render_frame_id(render_frame_host->GetRoutingID()), |
+ requesting_origin(requesting_origin), |
+ pending(types.size()), |
+ callback(callback), |
+ permissions(types), |
+ result(permissions.size(), content::PERMISSION_STATUS_DENIED) { |
+ // TODO(miguelg, peter) This special case for should go away once |
+ // push -> notifications mapping goes away/is changed. |
+ bool push_seen = false; |
+ for (const PermissionType& type : permissions) { |
+ if (type == PermissionType::PUSH_MESSAGING) |
+ push_seen = true; |
+ } |
+ if (!push_seen) |
+ return; |
+ for (size_t i = 0; i < permissions.size(); ++i) { |
+ if (permissions[i] == PermissionType::NOTIFICATIONS) |
+ permissions[i] = PermissionType::PUSH_MESSAGING; |
+ } |
+ } |
+ |
+ // Returns if there are no further pending sub-requests. |
+ bool SetPermission(int index, PermissionStatus status) { |
+ PermissionType current = permissions[index]; |
+ for (size_t i = index; i < permissions.size(); ++i) { |
+ if (permissions[i] == current) { |
+ result[i] = status; |
+ pending -= 1; |
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: --pending;
Lalit Maganti
2015/09/24 09:24:11
All changed.
|
+ } |
+ } |
+ if (pending == 0) |
+ callback.Run(result); |
+ return pending == 0; |
+ } |
+ |
int render_process_id; |
int render_frame_id; |
+ const GURL requesting_origin; |
+ size_t pending; |
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: pending_results?
Lalit Maganti
2015/09/24 09:24:11
Gone.
|
+ const base::Callback<void( |
+ const std::vector<PermissionStatus>&)> callback; |
+ |
+ std::vector<PermissionType> permissions; |
+ std::vector<PermissionStatus> result; |
}; |
struct PermissionManager::Subscription { |
@@ -146,54 +200,74 @@ int PermissionManager::RequestPermission( |
const GURL& requesting_origin, |
bool user_gesture, |
const base::Callback<void(PermissionStatus)>& callback) { |
- if (IsConstantPermission(permission)) { |
- callback.Run(GetPermissionStatusForConstantPermission(permission)); |
- return kNoPendingRequestOrSubscription; |
- } |
- |
- PermissionContextBase* context = PermissionContext::Get(profile_, permission); |
- if (!context) { |
- callback.Run(content::PERMISSION_STATUS_DENIED); |
- return kNoPendingRequestOrSubscription; |
- } |
+ return RequestPermissions( |
+ std::vector<PermissionType>(1, permission), |
+ render_frame_host, |
+ requesting_origin, |
+ user_gesture, |
+ base::Bind(&PermissionRequestResponseCallbackWrapper, callback)); |
+} |
+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) { |
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 kNoPendingRequestOrSubscription; |
- } |
- |
- int render_process_id = render_frame_host->GetProcess()->GetID(); |
- int render_frame_id = render_frame_host->GetRoutingID(); |
- |
- PendingRequest* pending_request = new PendingRequest(); |
- pending_request->render_process_id = render_process_id; |
- pending_request->render_frame_id = render_frame_id; |
- pending_request->permission = permission; |
+ GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); |
+ PendingRequest* pending_request = new PendingRequest( |
+ render_frame_host, requesting_origin, permissions, callback); |
int request_id = pending_requests_.Add(pending_request); |
- const PermissionRequestID request(render_process_id, |
- render_frame_id, |
- request_id); |
+ const PermissionRequestID request(render_frame_host, request_id); |
+ |
+ std::set<PermissionType> seen_permissions; |
+ for (size_t i = 0; i < permissions.size(); ++i) { |
+ // It is important that the pending request be used here as it can change |
+ // the PermissionType from the vector that was passed in. |
+ // TODO(peter, miguelg) Remove this when push and notifcations are unified. |
+ const PermissionType permission = pending_request->permissions[i]; |
+ if (seen_permissions.find(permission) != seen_permissions.end()) |
+ continue; |
+ seen_permissions.insert(permission); |
+ |
+ if (IsConstantPermission(permission) || |
+ IsPermissionBubbleManagerMissing(web_contents) || |
+ !PermissionContext::Get(profile_, permission)) { |
+ OnPermissionsRequestResponseStatus(request_id, i, |
+ GetPermissionStatus( |
+ permission, requesting_origin, embedding_origin)); |
+ continue; |
+ } |
- context->RequestPermission( |
- web_contents, request, requesting_origin, user_gesture, |
- base::Bind(&PermissionManager::OnPermissionRequestResponse, |
- weak_ptr_factory_.GetWeakPtr(), |
- request_id, |
- callback)); |
+ PermissionContextBase* context = PermissionContext::Get( |
+ profile_, permission); |
+ context->RequestPermission( |
+ web_contents, request, requesting_origin, user_gesture, |
+ base::Bind(&PermissionManager::OnPermissionsRequestResponse, |
+ weak_ptr_factory_.GetWeakPtr(), request_id, i)); |
+ } |
return request_id; |
} |
-void PermissionManager::OnPermissionRequestResponse( |
+void PermissionManager::OnPermissionsRequestResponse( |
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)); |
+ OnPermissionsRequestResponseStatus(request_id, request_index, |
+ ContentSettingToPermissionStatus(content_setting)); |
+} |
+ |
+void PermissionManager::OnPermissionsRequestResponseStatus( |
+ int request_id, |
+ int request_index, |
+ PermissionStatus status) { |
+ PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
+ if (pending_request->SetPermission(request_index, status)) |
+ pending_requests_.Remove(request_id); |
} |
void PermissionManager::CancelPermissionRequest(int request_id) { |
@@ -201,11 +275,6 @@ void PermissionManager::CancelPermissionRequest(int request_id) { |
if (!pending_request) |
return; |
- PermissionContextBase* context = PermissionContext::Get( |
- profile_, pending_request->permission); |
- if (!context) |
- return; |
- |
content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
pending_request->render_process_id, pending_request->render_frame_id); |
DCHECK(web_contents); |
@@ -217,7 +286,18 @@ void PermissionManager::CancelPermissionRequest(int request_id) { |
const PermissionRequestID request(pending_request->render_process_id, |
pending_request->render_frame_id, |
request_id); |
- context->CancelPermissionRequest(web_contents, request); |
+ std::set<PermissionType> seen_permissions; |
+ for (const PermissionType& permission : pending_request->permissions) { |
+ if (seen_permissions.find(permission) != seen_permissions.end()) |
+ continue; |
+ seen_permissions.insert(permission); |
+ |
+ PermissionContextBase* context = PermissionContext::Get( |
+ profile_, permission); |
+ if (!context) |
+ continue; |
+ context->CancelPermissionRequest(web_contents, request); |
+ } |
pending_requests_.Remove(request_id); |
} |