frame_permission_controller.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "fuchsia_web/webengine/browser/frame_permission_controller.h"
  5. #include "base/check_op.h"
  6. #include "components/permissions/permission_util.h"
  7. #include "content/public/browser/web_contents.h"
  8. #include "url/origin.h"
  9. using PermissionStatus = blink::mojom::PermissionStatus;
  10. using PermissionType = blink::PermissionType;
  11. namespace {
  12. size_t GetPermissionIndex(PermissionType type) {
  13. size_t index = static_cast<size_t>(type);
  14. DCHECK_LT(index, static_cast<size_t>(PermissionType::NUM));
  15. return index;
  16. }
  17. constexpr PermissionStatus kDefaultPerOriginStatus = PermissionStatus::ASK;
  18. // Converts from |url|'s actual origin to the "canonical origin" that should
  19. // be used for the purpose of requesting permissions.
  20. const url::Origin& GetCanonicalOrigin(PermissionType permission,
  21. const url::Origin& requesting_origin,
  22. const url::Origin& embedding_origin) {
  23. // Logic in this function should match the logic in
  24. // permissions::PermissionManager::GetCanonicalOrigin(). Currently it always
  25. // returns embedding origin, which is correct for all permissions supported by
  26. // WebEngine (AUDIO_CAPTURE, VIDEO_CAPTURE, PROTECTED_MEDIA_IDENTIFIER,
  27. // DURABLE_STORAGE).
  28. //
  29. // TODO(crbug.com/1063094): Update this function when other permissions are
  30. // added.
  31. return embedding_origin;
  32. }
  33. } // namespace
  34. FramePermissionController::PermissionSet::PermissionSet(
  35. PermissionStatus initial_state) {
  36. for (auto& permission : permission_states) {
  37. permission = initial_state;
  38. }
  39. }
  40. FramePermissionController::PermissionSet::PermissionSet(
  41. const PermissionSet& other) = default;
  42. FramePermissionController::PermissionSet&
  43. FramePermissionController::PermissionSet::operator=(
  44. const PermissionSet& other) = default;
  45. FramePermissionController::FramePermissionController(
  46. content::WebContents* web_contents)
  47. : web_contents_(web_contents) {}
  48. FramePermissionController::~FramePermissionController() = default;
  49. void FramePermissionController::SetPermissionState(PermissionType permission,
  50. const url::Origin& origin,
  51. PermissionStatus state) {
  52. // Currently only the following permissions are supported by WebEngine. Others
  53. // may not be handled correctly by this class.
  54. //
  55. // TODO(crbug.com/1063094): This check is necessary mainly because
  56. // GetCanonicalOrigin() may not work correctly for other permission. See
  57. // comemnts in GetCanonicalOrigin(). Remove it once that issue is resolved.
  58. DCHECK(permission == PermissionType::AUDIO_CAPTURE ||
  59. permission == PermissionType::VIDEO_CAPTURE ||
  60. permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER ||
  61. permission == PermissionType::DURABLE_STORAGE);
  62. auto it = per_origin_permissions_.find(origin);
  63. if (it == per_origin_permissions_.end()) {
  64. // Don't create a PermissionSet for |origin| if |state| is set to the
  65. // per-origin default, since that would have no effect.
  66. if (state == kDefaultPerOriginStatus)
  67. return;
  68. it = per_origin_permissions_
  69. .insert(
  70. std::make_pair(origin, PermissionSet(kDefaultPerOriginStatus)))
  71. .first;
  72. }
  73. it->second.permission_states[GetPermissionIndex(permission)] = state;
  74. }
  75. void FramePermissionController::SetDefaultPermissionState(
  76. PermissionType permission,
  77. PermissionStatus state) {
  78. DCHECK(state != PermissionStatus::ASK);
  79. default_permissions_.permission_states[GetPermissionIndex(permission)] =
  80. state;
  81. }
  82. PermissionStatus FramePermissionController::GetPermissionState(
  83. PermissionType permission,
  84. const url::Origin& requesting_origin) {
  85. url::Origin embedding_origin = url::Origin::Create(
  86. permissions::PermissionUtil::GetLastCommittedOriginAsURL(
  87. web_contents_->GetPrimaryMainFrame()));
  88. const url::Origin& canonical_origin =
  89. GetCanonicalOrigin(permission, requesting_origin, embedding_origin);
  90. PermissionSet effective = GetEffectivePermissionsForOrigin(canonical_origin);
  91. return effective.permission_states[GetPermissionIndex(permission)];
  92. }
  93. void FramePermissionController::RequestPermissions(
  94. const std::vector<PermissionType>& permissions,
  95. const url::Origin& requesting_origin,
  96. bool user_gesture,
  97. base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback) {
  98. std::vector<PermissionStatus> result;
  99. result.reserve(permissions.size());
  100. for (auto& permission : permissions) {
  101. result.push_back(GetPermissionState(permission, requesting_origin));
  102. }
  103. std::move(callback).Run(result);
  104. }
  105. FramePermissionController::PermissionSet
  106. FramePermissionController::GetEffectivePermissionsForOrigin(
  107. const url::Origin& origin) {
  108. PermissionSet result = default_permissions_;
  109. auto it = per_origin_permissions_.find(origin);
  110. if (it != per_origin_permissions_.end()) {
  111. // Apply per-origin GRANTED and DENIED states. Permissions with the ASK
  112. // state defer to the defaults.
  113. for (size_t i = 0; i < it->second.permission_states.size(); ++i) {
  114. if (it->second.permission_states[i] != kDefaultPerOriginStatus)
  115. result.permission_states[i] = it->second.permission_states[i];
  116. }
  117. }
  118. return result;
  119. }