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/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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |