| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/memory/ptr_util.h" |
| 10 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 #include "chrome/browser/background_sync/background_sync_permission_context.h" |
| 11 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 13 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 12 #include "chrome/browser/permissions/permission_context.h" | 14 #include "chrome/browser/media/media_stream_device_permission_context.h" |
| 15 #include "chrome/browser/media/midi_permission_context.h" |
| 16 #include "chrome/browser/notifications/notification_permission_context.h" |
| 13 #include "chrome/browser/permissions/permission_context_base.h" | 17 #include "chrome/browser/permissions/permission_context_base.h" |
| 18 #include "chrome/browser/permissions/permission_manager_factory.h" |
| 14 #include "chrome/browser/permissions/permission_request_id.h" | 19 #include "chrome/browser/permissions/permission_request_id.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/push_messaging/push_messaging_permission_context.h" |
| 22 #include "chrome/browser/storage/durable_storage_permission_context.h" |
| 16 #include "chrome/browser/tab_contents/tab_util.h" | 23 #include "chrome/browser/tab_contents/tab_util.h" |
| 24 #include "chrome/common/features.h" |
| 17 #include "components/content_settings/core/browser/host_content_settings_map.h" | 25 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 18 #include "content/public/browser/permission_type.h" | 26 #include "content/public/browser/permission_type.h" |
| 19 #include "content/public/browser/render_frame_host.h" | 27 #include "content/public/browser/render_frame_host.h" |
| 20 #include "content/public/browser/render_process_host.h" | 28 #include "content/public/browser/render_process_host.h" |
| 21 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 22 | 30 |
| 31 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 32 #include "chrome/browser/media/protected_media_identifier_permission_context.h" |
| 33 #endif |
| 34 |
| 23 #if !defined(OS_ANDROID) | 35 #if !defined(OS_ANDROID) |
| 24 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" | 36 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" |
| 25 #endif | 37 #endif |
| 26 | 38 |
| 39 #if BUILDFLAG(ANDROID_JAVA_UI) |
| 40 #include "chrome/browser/geolocation/geolocation_permission_context_android.h" |
| 41 #else |
| 42 #include "chrome/browser/geolocation/geolocation_permission_context.h" |
| 43 #endif |
| 44 |
| 27 using blink::mojom::PermissionStatus; | 45 using blink::mojom::PermissionStatus; |
| 28 using content::PermissionType; | 46 using content::PermissionType; |
| 29 | 47 |
| 30 namespace { | 48 namespace { |
| 31 | 49 |
| 32 // Helper method to convert ContentSetting to PermissionStatus. | 50 // Helper method to convert ContentSetting to PermissionStatus. |
| 33 PermissionStatus ContentSettingToPermissionStatus(ContentSetting setting) { | 51 PermissionStatus ContentSettingToPermissionStatus(ContentSetting setting) { |
| 34 switch (setting) { | 52 switch (setting) { |
| 35 case CONTENT_SETTING_ALLOW: | 53 case CONTENT_SETTING_ALLOW: |
| 36 case CONTENT_SETTING_SESSION_ONLY: | 54 case CONTENT_SETTING_SESSION_ONLY: |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 } | 110 } |
| 93 | 111 |
| 94 NOTREACHED() << "Unknown content setting for permission " | 112 NOTREACHED() << "Unknown content setting for permission " |
| 95 << static_cast<int>(permission); | 113 << static_cast<int>(permission); |
| 96 return CONTENT_SETTINGS_TYPE_DEFAULT; | 114 return CONTENT_SETTINGS_TYPE_DEFAULT; |
| 97 } | 115 } |
| 98 | 116 |
| 99 // Returns whether the permission has a constant PermissionStatus value (i.e. | 117 // Returns whether the permission has a constant PermissionStatus value (i.e. |
| 100 // always approved or always denied) | 118 // always approved or always denied) |
| 101 // The PermissionTypes for which true is returned should be exactly those which | 119 // The PermissionTypes for which true is returned should be exactly those which |
| 102 // return nullptr in PermissionContext::Get since they don't have a context. | 120 // return nullptr in PermissionManager::GetPermissionContext since they don't |
| 121 // have a context. |
| 103 bool IsConstantPermission(PermissionType type) { | 122 bool IsConstantPermission(PermissionType type) { |
| 104 switch (type) { | 123 switch (type) { |
| 105 case PermissionType::MIDI: | 124 case PermissionType::MIDI: |
| 106 return true; | 125 return true; |
| 107 default: | 126 default: |
| 108 return false; | 127 return false; |
| 109 } | 128 } |
| 110 } | 129 } |
| 111 | 130 |
| 112 void PermissionRequestResponseCallbackWrapper( | 131 void PermissionRequestResponseCallbackWrapper( |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 }; | 207 }; |
| 189 | 208 |
| 190 struct PermissionManager::Subscription { | 209 struct PermissionManager::Subscription { |
| 191 PermissionType permission; | 210 PermissionType permission; |
| 192 GURL requesting_origin; | 211 GURL requesting_origin; |
| 193 GURL embedding_origin; | 212 GURL embedding_origin; |
| 194 base::Callback<void(PermissionStatus)> callback; | 213 base::Callback<void(PermissionStatus)> callback; |
| 195 ContentSetting current_value; | 214 ContentSetting current_value; |
| 196 }; | 215 }; |
| 197 | 216 |
| 217 // static |
| 218 PermissionManager* PermissionManager::Get(Profile* profile) { |
| 219 return PermissionManagerFactory::GetForProfile(profile); |
| 220 } |
| 221 |
| 198 PermissionManager::PermissionManager(Profile* profile) | 222 PermissionManager::PermissionManager(Profile* profile) |
| 199 : profile_(profile), | 223 : profile_(profile), |
| 200 weak_ptr_factory_(this) { | 224 weak_ptr_factory_(this) { |
| 225 permission_contexts_[PermissionType::MIDI_SYSEX] = |
| 226 base::WrapUnique(new MidiPermissionContext(profile)); |
| 227 permission_contexts_[PermissionType::PUSH_MESSAGING] = |
| 228 base::WrapUnique(new PushMessagingPermissionContext(profile)); |
| 229 permission_contexts_[PermissionType::NOTIFICATIONS] = |
| 230 base::WrapUnique(new NotificationPermissionContext(profile)); |
| 231 #if !BUILDFLAG(ANDROID_JAVA_UI) |
| 232 permission_contexts_[PermissionType::GEOLOCATION] = |
| 233 base::WrapUnique(new GeolocationPermissionContext(profile)); |
| 234 #else |
| 235 permission_contexts_[PermissionType::GEOLOCATION] = |
| 236 base::WrapUnique(new GeolocationPermissionContextAndroid(profile)); |
| 237 #endif |
| 238 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 239 permission_contexts_[PermissionType::PROTECTED_MEDIA_IDENTIFIER] = |
| 240 base::WrapUnique(new ProtectedMediaIdentifierPermissionContext(profile)); |
| 241 #endif |
| 242 permission_contexts_[PermissionType::DURABLE_STORAGE] = |
| 243 base::WrapUnique(new DurableStoragePermissionContext(profile)); |
| 244 permission_contexts_[PermissionType::AUDIO_CAPTURE] = |
| 245 base::WrapUnique(new MediaStreamDevicePermissionContext( |
| 246 profile, content::PermissionType::AUDIO_CAPTURE, |
| 247 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)); |
| 248 permission_contexts_[PermissionType::VIDEO_CAPTURE] = |
| 249 base::WrapUnique(new MediaStreamDevicePermissionContext( |
| 250 profile, content::PermissionType::VIDEO_CAPTURE, |
| 251 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)); |
| 252 permission_contexts_[PermissionType::BACKGROUND_SYNC] = |
| 253 base::WrapUnique(new BackgroundSyncPermissionContext(profile)); |
| 201 } | 254 } |
| 202 | 255 |
| 203 PermissionManager::~PermissionManager() { | 256 PermissionManager::~PermissionManager() { |
| 204 if (!subscriptions_.IsEmpty()) | 257 if (!subscriptions_.IsEmpty()) |
| 205 HostContentSettingsMapFactory::GetForProfile(profile_) | 258 HostContentSettingsMapFactory::GetForProfile(profile_) |
| 206 ->RemoveObserver(this); | 259 ->RemoveObserver(this); |
| 207 } | 260 } |
| 208 | 261 |
| 209 int PermissionManager::RequestPermission( | 262 int PermissionManager::RequestPermission( |
| 210 PermissionType permission, | 263 PermissionType permission, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 237 render_frame_host, permissions, callback); | 290 render_frame_host, permissions, callback); |
| 238 int request_id = pending_requests_.Add(pending_request); | 291 int request_id = pending_requests_.Add(pending_request); |
| 239 | 292 |
| 240 const PermissionRequestID request(render_frame_host, request_id); | 293 const PermissionRequestID request(render_frame_host, request_id); |
| 241 | 294 |
| 242 for (size_t i = 0; i < permissions.size(); ++i) { | 295 for (size_t i = 0; i < permissions.size(); ++i) { |
| 243 const PermissionType permission = permissions[i]; | 296 const PermissionType permission = permissions[i]; |
| 244 | 297 |
| 245 if (IsConstantPermission(permission) || | 298 if (IsConstantPermission(permission) || |
| 246 IsPermissionBubbleManagerMissing(web_contents) || | 299 IsPermissionBubbleManagerMissing(web_contents) || |
| 247 !PermissionContext::Get(profile_, permission)) { | 300 !GetPermissionContext(permission)) { |
| 248 OnPermissionsRequestResponseStatus(request_id, i, | 301 OnPermissionsRequestResponseStatus(request_id, i, |
| 249 GetPermissionStatus(permission, requesting_origin, embedding_origin)); | 302 GetPermissionStatus(permission, requesting_origin, embedding_origin)); |
| 250 continue; | 303 continue; |
| 251 } | 304 } |
| 252 | 305 |
| 253 PermissionContextBase* context = PermissionContext::Get( | 306 PermissionContextBase* context = GetPermissionContext(permission); |
| 254 profile_, permission); | |
| 255 context->RequestPermission( | 307 context->RequestPermission( |
| 256 web_contents, request, requesting_origin, | 308 web_contents, request, requesting_origin, |
| 257 base::Bind(&ContentSettingToPermissionStatusCallbackWrapper, | 309 base::Bind(&ContentSettingToPermissionStatusCallbackWrapper, |
| 258 base::Bind(&PermissionManager::OnPermissionsRequestResponseStatus, | 310 base::Bind(&PermissionManager::OnPermissionsRequestResponseStatus, |
| 259 weak_ptr_factory_.GetWeakPtr(), request_id, i))); | 311 weak_ptr_factory_.GetWeakPtr(), request_id, i))); |
| 260 } | 312 } |
| 261 | 313 |
| 262 // The request might have been resolved already. | 314 // The request might have been resolved already. |
| 263 if (!pending_requests_.Lookup(request_id)) | 315 if (!pending_requests_.Lookup(request_id)) |
| 264 return kNoPendingOperation; | 316 return kNoPendingOperation; |
| 265 | 317 |
| 266 return request_id; | 318 return request_id; |
| 267 } | 319 } |
| 268 | 320 |
| 321 std::size_t PermissionManager::PermissionTypeHash::operator()( |
| 322 const content::PermissionType& type) const { |
| 323 return static_cast<size_t>(type); |
| 324 } |
| 325 |
| 326 PermissionContextBase* PermissionManager::GetPermissionContext( |
| 327 PermissionType type) { |
| 328 const auto& it = permission_contexts_.find(type); |
| 329 return it == permission_contexts_.end() ? nullptr : it->second.get(); |
| 330 } |
| 331 |
| 269 void PermissionManager::OnPermissionsRequestResponseStatus( | 332 void PermissionManager::OnPermissionsRequestResponseStatus( |
| 270 int request_id, | 333 int request_id, |
| 271 int permission_id, | 334 int permission_id, |
| 272 PermissionStatus status) { | 335 PermissionStatus status) { |
| 273 PendingRequest* pending_request = pending_requests_.Lookup(request_id); | 336 PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
| 274 pending_request->SetPermissionStatus(permission_id, status); | 337 pending_request->SetPermissionStatus(permission_id, status); |
| 275 | 338 |
| 276 if (!pending_request->IsComplete()) | 339 if (!pending_request->IsComplete()) |
| 277 return; | 340 return; |
| 278 | 341 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 290 DCHECK(web_contents); | 353 DCHECK(web_contents); |
| 291 if (IsPermissionBubbleManagerMissing(web_contents)) { | 354 if (IsPermissionBubbleManagerMissing(web_contents)) { |
| 292 pending_requests_.Remove(request_id); | 355 pending_requests_.Remove(request_id); |
| 293 return; | 356 return; |
| 294 } | 357 } |
| 295 | 358 |
| 296 const PermissionRequestID request(pending_request->render_process_id(), | 359 const PermissionRequestID request(pending_request->render_process_id(), |
| 297 pending_request->render_frame_id(), | 360 pending_request->render_frame_id(), |
| 298 request_id); | 361 request_id); |
| 299 for (PermissionType permission : pending_request->permissions()) { | 362 for (PermissionType permission : pending_request->permissions()) { |
| 300 PermissionContextBase* context = PermissionContext::Get( | 363 PermissionContextBase* context = GetPermissionContext(permission); |
| 301 profile_, permission); | |
| 302 if (!context) | 364 if (!context) |
| 303 continue; | 365 continue; |
| 304 context->CancelPermissionRequest(web_contents, request); | 366 context->CancelPermissionRequest(web_contents, request); |
| 305 } | 367 } |
| 306 pending_requests_.Remove(request_id); | 368 pending_requests_.Remove(request_id); |
| 307 } | 369 } |
| 308 | 370 |
| 309 void PermissionManager::ResetPermission(PermissionType permission, | 371 void PermissionManager::ResetPermission(PermissionType permission, |
| 310 const GURL& requesting_origin, | 372 const GURL& requesting_origin, |
| 311 const GURL& embedding_origin) { | 373 const GURL& embedding_origin) { |
| 312 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 374 PermissionContextBase* context = GetPermissionContext(permission); |
| 313 if (!context) | 375 if (!context) |
| 314 return; | 376 return; |
| 315 | 377 |
| 316 context->ResetPermission(requesting_origin.GetOrigin(), | 378 context->ResetPermission(requesting_origin.GetOrigin(), |
| 317 embedding_origin.GetOrigin()); | 379 embedding_origin.GetOrigin()); |
| 318 } | 380 } |
| 319 | 381 |
| 320 PermissionStatus PermissionManager::GetPermissionStatus( | 382 PermissionStatus PermissionManager::GetPermissionStatus( |
| 321 PermissionType permission, | 383 PermissionType permission, |
| 322 const GURL& requesting_origin, | 384 const GURL& requesting_origin, |
| 323 const GURL& embedding_origin) { | 385 const GURL& embedding_origin) { |
| 324 if (IsConstantPermission(permission)) | 386 if (IsConstantPermission(permission)) |
| 325 return GetPermissionStatusForConstantPermission(permission); | 387 return GetPermissionStatusForConstantPermission(permission); |
| 326 | 388 |
| 327 PermissionContextBase* context = PermissionContext::Get(profile_, permission); | 389 PermissionContextBase* context = GetPermissionContext(permission); |
| 328 if (!context) | 390 if (!context) |
| 329 return PermissionStatus::DENIED; | 391 return PermissionStatus::DENIED; |
| 330 | 392 |
| 331 return ContentSettingToPermissionStatus(context->GetPermissionStatus( | 393 return ContentSettingToPermissionStatus(context->GetPermissionStatus( |
| 332 requesting_origin.GetOrigin(), embedding_origin.GetOrigin())); | 394 requesting_origin.GetOrigin(), embedding_origin.GetOrigin())); |
| 333 } | 395 } |
| 334 | 396 |
| 335 void PermissionManager::RegisterPermissionUsage(PermissionType permission, | 397 void PermissionManager::RegisterPermissionUsage(PermissionType permission, |
| 336 const GURL& requesting_origin, | 398 const GURL& requesting_origin, |
| 337 const GURL& embedding_origin) { | 399 const GURL& embedding_origin) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 357 Subscription* subscription = new Subscription(); | 419 Subscription* subscription = new Subscription(); |
| 358 subscription->permission = permission; | 420 subscription->permission = permission; |
| 359 subscription->requesting_origin = requesting_origin; | 421 subscription->requesting_origin = requesting_origin; |
| 360 subscription->embedding_origin = embedding_origin; | 422 subscription->embedding_origin = embedding_origin; |
| 361 subscription->callback = callback; | 423 subscription->callback = callback; |
| 362 | 424 |
| 363 if (IsConstantPermission(permission)) { | 425 if (IsConstantPermission(permission)) { |
| 364 subscription->current_value = GetContentSettingForConstantPermission( | 426 subscription->current_value = GetContentSettingForConstantPermission( |
| 365 permission); | 427 permission); |
| 366 } else { | 428 } else { |
| 367 subscription->current_value = PermissionContext::Get(profile_, permission) | 429 subscription->current_value = |
| 368 ->GetPermissionStatus(subscription->requesting_origin, | 430 GetPermissionContext(permission) |
| 369 subscription->embedding_origin); | 431 ->GetPermissionStatus(subscription->requesting_origin, |
| 432 subscription->embedding_origin); |
| 370 } | 433 } |
| 371 | 434 |
| 372 return subscriptions_.Add(subscription); | 435 return subscriptions_.Add(subscription); |
| 373 } | 436 } |
| 374 | 437 |
| 375 void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) { | 438 void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) { |
| 376 // Whether |subscription_id| is known will be checked by the Remove() call. | 439 // Whether |subscription_id| is known will be checked by the Remove() call. |
| 377 subscriptions_.Remove(subscription_id); | 440 subscriptions_.Remove(subscription_id); |
| 378 | 441 |
| 379 if (subscriptions_.IsEmpty()) | 442 if (subscriptions_.IsEmpty()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 404 } | 467 } |
| 405 | 468 |
| 406 if (primary_pattern.IsValid() && | 469 if (primary_pattern.IsValid() && |
| 407 !primary_pattern.Matches(subscription->requesting_origin)) | 470 !primary_pattern.Matches(subscription->requesting_origin)) |
| 408 continue; | 471 continue; |
| 409 if (secondary_pattern.IsValid() && | 472 if (secondary_pattern.IsValid() && |
| 410 !secondary_pattern.Matches(subscription->embedding_origin)) | 473 !secondary_pattern.Matches(subscription->embedding_origin)) |
| 411 continue; | 474 continue; |
| 412 | 475 |
| 413 ContentSetting new_value = | 476 ContentSetting new_value = |
| 414 PermissionContext::Get(profile_, subscription->permission) | 477 GetPermissionContext(subscription->permission) |
| 415 ->GetPermissionStatus(subscription->requesting_origin, | 478 ->GetPermissionStatus(subscription->requesting_origin, |
| 416 subscription->embedding_origin); | 479 subscription->embedding_origin); |
| 417 if (subscription->current_value == new_value) | 480 if (subscription->current_value == new_value) |
| 418 continue; | 481 continue; |
| 419 | 482 |
| 420 subscription->current_value = new_value; | 483 subscription->current_value = new_value; |
| 421 | 484 |
| 422 // Add the callback to |callbacks| which will be run after the loop to | 485 // Add the callback to |callbacks| which will be run after the loop to |
| 423 // prevent re-entrance issues. | 486 // prevent re-entrance issues. |
| 424 callbacks.push_back( | 487 callbacks.push_back( |
| 425 base::Bind(subscription->callback, | 488 base::Bind(subscription->callback, |
| 426 ContentSettingToPermissionStatus(new_value))); | 489 ContentSettingToPermissionStatus(new_value))); |
| 427 } | 490 } |
| 428 | 491 |
| 429 for (const auto& callback : callbacks) | 492 for (const auto& callback : callbacks) |
| 430 callback.Run(); | 493 callback.Run(); |
| 431 } | 494 } |
| OLD | NEW |