OLD | NEW |
---|---|
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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 // 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. |
87 bool IsConstantPermission(PermissionType type) { | 87 bool IsConstantPermission(PermissionType type) { |
88 switch (type) { | 88 switch (type) { |
89 case PermissionType::MIDI: | 89 case PermissionType::MIDI: |
90 return true; | 90 return true; |
91 default: | 91 default: |
92 return false; | 92 return false; |
93 } | 93 } |
94 } | 94 } |
95 | 95 |
96 void PermissionRequestResponseCallbackWrapper( | |
97 const base::Callback<void(PermissionStatus)>& callback, | |
98 const std::vector<PermissionStatus>& vector) { | |
99 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.
| |
100 callback.Run(vector[0]); | |
101 } | |
102 | |
96 // Function used for handling permission types which do not change their | 103 // Function used for handling permission types which do not change their |
97 // value i.e. they are always approved or always denied etc. | 104 // value i.e. they are always approved or always denied etc. |
98 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. | 105 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling. |
99 // This function should only be called when IsConstantPermission has returned | 106 // This function should only be called when IsConstantPermission has returned |
100 // true for the PermissionType. | 107 // true for the PermissionType. |
101 ContentSetting GetContentSettingForConstantPermission(PermissionType type) { | 108 ContentSetting GetContentSettingForConstantPermission(PermissionType type) { |
102 DCHECK(IsConstantPermission(type)); | 109 DCHECK(IsConstantPermission(type)); |
103 switch (type) { | 110 switch (type) { |
104 case PermissionType::MIDI: | 111 case PermissionType::MIDI: |
105 return CONTENT_SETTING_ALLOW; | 112 return CONTENT_SETTING_ALLOW; |
106 default: | 113 default: |
107 return CONTENT_SETTING_DEFAULT; | 114 return CONTENT_SETTING_DEFAULT; |
108 } | 115 } |
109 } | 116 } |
110 | 117 |
111 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { | 118 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) { |
112 return ContentSettingToPermissionStatus( | 119 return ContentSettingToPermissionStatus( |
113 GetContentSettingForConstantPermission(type)); | 120 GetContentSettingForConstantPermission(type)); |
114 } | 121 } |
115 | 122 |
116 } // anonymous namespace | 123 } // anonymous namespace |
117 | 124 |
118 struct PermissionManager::PendingRequest { | 125 struct PermissionManager::PendingRequest { |
119 PermissionType permission; | 126 PendingRequest(content::RenderFrameHost* render_frame_host, |
127 const GURL& requesting_origin, | |
128 const std::vector<PermissionType> types, | |
129 const base::Callback<void( | |
130 const std::vector<PermissionStatus>&)>& callback) | |
131 : render_process_id(render_frame_host->GetProcess()->GetID()), | |
132 render_frame_id(render_frame_host->GetRoutingID()), | |
133 requesting_origin(requesting_origin), | |
134 pending(types.size()), | |
135 callback(callback), | |
136 permissions(types), | |
137 result(permissions.size(), content::PERMISSION_STATUS_DENIED) { | |
138 // TODO(miguelg, peter) This special case for should go away once | |
139 // push -> notifications mapping goes away/is changed. | |
140 bool push_seen = false; | |
141 for (const PermissionType& type : permissions) { | |
142 if (type == PermissionType::PUSH_MESSAGING) | |
143 push_seen = true; | |
144 } | |
145 if (!push_seen) | |
146 return; | |
147 for (size_t i = 0; i < permissions.size(); ++i) { | |
148 if (permissions[i] == PermissionType::NOTIFICATIONS) | |
149 permissions[i] = PermissionType::PUSH_MESSAGING; | |
150 } | |
151 } | |
152 | |
153 // Returns if there are no further pending sub-requests. | |
154 bool SetPermission(int index, PermissionStatus status) { | |
155 PermissionType current = permissions[index]; | |
156 for (size_t i = index; i < permissions.size(); ++i) { | |
157 if (permissions[i] == current) { | |
158 result[i] = status; | |
159 pending -= 1; | |
mlamouri (slow - plz ping)
2015/09/23 16:37:37
nit: --pending;
Lalit Maganti
2015/09/24 09:24:11
All changed.
| |
160 } | |
161 } | |
162 if (pending == 0) | |
163 callback.Run(result); | |
164 return pending == 0; | |
165 } | |
166 | |
120 int render_process_id; | 167 int render_process_id; |
121 int render_frame_id; | 168 int render_frame_id; |
169 const GURL requesting_origin; | |
170 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.
| |
171 const base::Callback<void( | |
172 const std::vector<PermissionStatus>&)> callback; | |
173 | |
174 std::vector<PermissionType> permissions; | |
175 std::vector<PermissionStatus> result; | |
122 }; | 176 }; |
123 | 177 |
124 struct PermissionManager::Subscription { | 178 struct PermissionManager::Subscription { |
125 PermissionType permission; | 179 PermissionType permission; |
126 GURL requesting_origin; | 180 GURL requesting_origin; |
127 GURL embedding_origin; | 181 GURL embedding_origin; |
128 base::Callback<void(PermissionStatus)> callback; | 182 base::Callback<void(PermissionStatus)> callback; |
129 ContentSetting current_value; | 183 ContentSetting current_value; |
130 }; | 184 }; |
131 | 185 |
132 PermissionManager::PermissionManager(Profile* profile) | 186 PermissionManager::PermissionManager(Profile* profile) |
133 : profile_(profile), | 187 : profile_(profile), |
134 weak_ptr_factory_(this) { | 188 weak_ptr_factory_(this) { |
135 } | 189 } |
136 | 190 |
137 PermissionManager::~PermissionManager() { | 191 PermissionManager::~PermissionManager() { |
138 if (!subscriptions_.IsEmpty()) | 192 if (!subscriptions_.IsEmpty()) |
139 HostContentSettingsMapFactory::GetForProfile(profile_) | 193 HostContentSettingsMapFactory::GetForProfile(profile_) |
140 ->RemoveObserver(this); | 194 ->RemoveObserver(this); |
141 } | 195 } |
142 | 196 |
143 int PermissionManager::RequestPermission( | 197 int PermissionManager::RequestPermission( |
144 PermissionType permission, | 198 PermissionType permission, |
145 content::RenderFrameHost* render_frame_host, | 199 content::RenderFrameHost* render_frame_host, |
146 const GURL& requesting_origin, | 200 const GURL& requesting_origin, |
147 bool user_gesture, | 201 bool user_gesture, |
148 const base::Callback<void(PermissionStatus)>& callback) { | 202 const base::Callback<void(PermissionStatus)>& callback) { |
149 if (IsConstantPermission(permission)) { | 203 return RequestPermissions( |
150 callback.Run(GetPermissionStatusForConstantPermission(permission)); | 204 std::vector<PermissionType>(1, permission), |
151 return kNoPendingRequestOrSubscription; | 205 render_frame_host, |
152 } | 206 requesting_origin, |
207 user_gesture, | |
208 base::Bind(&PermissionRequestResponseCallbackWrapper, callback)); | |
209 } | |
153 | 210 |
154 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 211 int PermissionManager::RequestPermissions( |
155 if (!context) { | 212 const std::vector<PermissionType>& permissions, |
156 callback.Run(content::PERMISSION_STATUS_DENIED); | 213 content::RenderFrameHost* render_frame_host, |
157 return kNoPendingRequestOrSubscription; | 214 const GURL& requesting_origin, |
158 } | 215 bool user_gesture, |
159 | 216 const base::Callback<void( |
217 const std::vector<PermissionStatus>&)>& callback) { | |
160 content::WebContents* web_contents = | 218 content::WebContents* web_contents = |
161 content::WebContents::FromRenderFrameHost(render_frame_host); | 219 content::WebContents::FromRenderFrameHost(render_frame_host); |
162 if (IsPermissionBubbleManagerMissing(web_contents)) { | 220 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); |
163 callback.Run( | 221 |
164 GetPermissionStatus(permission, requesting_origin, | 222 PendingRequest* pending_request = new PendingRequest( |
165 web_contents->GetLastCommittedURL().GetOrigin())); | 223 render_frame_host, requesting_origin, permissions, callback); |
166 return kNoPendingRequestOrSubscription; | 224 int request_id = pending_requests_.Add(pending_request); |
225 const PermissionRequestID request(render_frame_host, request_id); | |
226 | |
227 std::set<PermissionType> seen_permissions; | |
228 for (size_t i = 0; i < permissions.size(); ++i) { | |
229 // It is important that the pending request be used here as it can change | |
230 // the PermissionType from the vector that was passed in. | |
231 // TODO(peter, miguelg) Remove this when push and notifcations are unified. | |
232 const PermissionType permission = pending_request->permissions[i]; | |
233 if (seen_permissions.find(permission) != seen_permissions.end()) | |
234 continue; | |
235 seen_permissions.insert(permission); | |
236 | |
237 if (IsConstantPermission(permission) || | |
238 IsPermissionBubbleManagerMissing(web_contents) || | |
239 !PermissionContext::Get(profile_, permission)) { | |
240 OnPermissionsRequestResponseStatus(request_id, i, | |
241 GetPermissionStatus( | |
242 permission, requesting_origin, embedding_origin)); | |
243 continue; | |
244 } | |
245 | |
246 PermissionContextBase* context = PermissionContext::Get( | |
247 profile_, permission); | |
248 context->RequestPermission( | |
249 web_contents, request, requesting_origin, user_gesture, | |
250 base::Bind(&PermissionManager::OnPermissionsRequestResponse, | |
251 weak_ptr_factory_.GetWeakPtr(), request_id, i)); | |
167 } | 252 } |
168 | |
169 int render_process_id = render_frame_host->GetProcess()->GetID(); | |
170 int render_frame_id = render_frame_host->GetRoutingID(); | |
171 | |
172 PendingRequest* pending_request = new PendingRequest(); | |
173 pending_request->render_process_id = render_process_id; | |
174 pending_request->render_frame_id = render_frame_id; | |
175 pending_request->permission = permission; | |
176 | |
177 int request_id = pending_requests_.Add(pending_request); | |
178 const PermissionRequestID request(render_process_id, | |
179 render_frame_id, | |
180 request_id); | |
181 | |
182 context->RequestPermission( | |
183 web_contents, request, requesting_origin, user_gesture, | |
184 base::Bind(&PermissionManager::OnPermissionRequestResponse, | |
185 weak_ptr_factory_.GetWeakPtr(), | |
186 request_id, | |
187 callback)); | |
188 return request_id; | 253 return request_id; |
189 } | 254 } |
190 | 255 |
191 void PermissionManager::OnPermissionRequestResponse( | 256 void PermissionManager::OnPermissionsRequestResponse( |
192 int request_id, | 257 int request_id, |
193 const base::Callback<void(PermissionStatus)>& callback, | 258 int request_index, |
194 ContentSetting content_setting) { | 259 ContentSetting content_setting) { |
195 pending_requests_.Remove(request_id); | 260 OnPermissionsRequestResponseStatus(request_id, request_index, |
196 callback.Run(ContentSettingToPermissionStatus(content_setting)); | 261 ContentSettingToPermissionStatus(content_setting)); |
262 } | |
263 | |
264 void PermissionManager::OnPermissionsRequestResponseStatus( | |
265 int request_id, | |
266 int request_index, | |
267 PermissionStatus status) { | |
268 PendingRequest* pending_request = pending_requests_.Lookup(request_id); | |
269 if (pending_request->SetPermission(request_index, status)) | |
270 pending_requests_.Remove(request_id); | |
197 } | 271 } |
198 | 272 |
199 void PermissionManager::CancelPermissionRequest(int request_id) { | 273 void PermissionManager::CancelPermissionRequest(int request_id) { |
200 PendingRequest* pending_request = pending_requests_.Lookup(request_id); | 274 PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
201 if (!pending_request) | 275 if (!pending_request) |
202 return; | 276 return; |
203 | 277 |
204 PermissionContextBase* context = PermissionContext::Get( | |
205 profile_, pending_request->permission); | |
206 if (!context) | |
207 return; | |
208 | |
209 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( | 278 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
210 pending_request->render_process_id, pending_request->render_frame_id); | 279 pending_request->render_process_id, pending_request->render_frame_id); |
211 DCHECK(web_contents); | 280 DCHECK(web_contents); |
212 if (IsPermissionBubbleManagerMissing(web_contents)) { | 281 if (IsPermissionBubbleManagerMissing(web_contents)) { |
213 pending_requests_.Remove(request_id); | 282 pending_requests_.Remove(request_id); |
214 return; | 283 return; |
215 } | 284 } |
216 | 285 |
217 const PermissionRequestID request(pending_request->render_process_id, | 286 const PermissionRequestID request(pending_request->render_process_id, |
218 pending_request->render_frame_id, | 287 pending_request->render_frame_id, |
219 request_id); | 288 request_id); |
220 context->CancelPermissionRequest(web_contents, request); | 289 std::set<PermissionType> seen_permissions; |
290 for (const PermissionType& permission : pending_request->permissions) { | |
291 if (seen_permissions.find(permission) != seen_permissions.end()) | |
292 continue; | |
293 seen_permissions.insert(permission); | |
294 | |
295 PermissionContextBase* context = PermissionContext::Get( | |
296 profile_, permission); | |
297 if (!context) | |
298 continue; | |
299 context->CancelPermissionRequest(web_contents, request); | |
300 } | |
221 pending_requests_.Remove(request_id); | 301 pending_requests_.Remove(request_id); |
222 } | 302 } |
223 | 303 |
224 void PermissionManager::ResetPermission(PermissionType permission, | 304 void PermissionManager::ResetPermission(PermissionType permission, |
225 const GURL& requesting_origin, | 305 const GURL& requesting_origin, |
226 const GURL& embedding_origin) { | 306 const GURL& embedding_origin) { |
227 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 307 PermissionContextBase* context = PermissionContext::Get(profile_, permission); |
228 if (!context) | 308 if (!context) |
229 return; | 309 return; |
230 | 310 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 // Add the callback to |callbacks| which will be run after the loop to | 419 // Add the callback to |callbacks| which will be run after the loop to |
340 // prevent re-entrance issues. | 420 // prevent re-entrance issues. |
341 callbacks.push_back( | 421 callbacks.push_back( |
342 base::Bind(subscription->callback, | 422 base::Bind(subscription->callback, |
343 ContentSettingToPermissionStatus(new_value))); | 423 ContentSettingToPermissionStatus(new_value))); |
344 } | 424 } |
345 | 425 |
346 for (const auto& callback : callbacks) | 426 for (const auto& callback : callbacks) |
347 callback.Run(); | 427 callback.Run(); |
348 } | 428 } |
OLD | NEW |