blob: 5cd674e8fadddf7d9f4200d522ccc37401c86dbf [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia/engine/browser/frame_permission_controller.h"
#include "base/check_op.h"
#include "content/public/browser/web_contents.h"
#include "url/origin.h"
using PermissionStatus = blink::mojom::PermissionStatus;
using PermissionType = content::PermissionType;
namespace {
size_t GetPermissionIndex(PermissionType type) {
size_t index = static_cast<size_t>(type);
DCHECK_LT(index, static_cast<size_t>(PermissionType::NUM));
return index;
}
constexpr PermissionStatus kDefaultPerOriginStatus = PermissionStatus::ASK;
// Converts from |url|'s actual origin to the "canonical origin" that should
// be used for the purpose of requesting permissions.
const url::Origin& GetCanonicalOrigin(PermissionType permission,
const url::Origin& requesting_origin,
const url::Origin& embedding_origin) {
// Logic in this function should match the logic in
// permissions::PermissionManager::GetCanonicalOrigin(). Currently it always
// returns embedding origin, which is correct for all permissions supported by
// WebEngine (AUDIO_CAPTURE, VIDEO_CAPTURE, PROTECTED_MEDIA_IDENTIFIER,
// DURABLE_STORAGE).
//
// TODO(crbug.com/1063094): Update this function when other permissions are
// added.
return embedding_origin;
}
} // namespace
FramePermissionController::PermissionSet::PermissionSet(
PermissionStatus initial_state) {
for (auto& permission : permission_states) {
permission = initial_state;
}
}
FramePermissionController::PermissionSet::PermissionSet(
const PermissionSet& other) = default;
FramePermissionController::PermissionSet&
FramePermissionController::PermissionSet::operator=(
const PermissionSet& other) = default;
FramePermissionController::FramePermissionController(
content::WebContents* web_contents)
: web_contents_(web_contents) {}
FramePermissionController::~FramePermissionController() = default;
void FramePermissionController::SetPermissionState(PermissionType permission,
const url::Origin& origin,
PermissionStatus state) {
// Currently only the following permissions are supported by WebEngine. Others
// may not be handled correctly by this class.
//
// TODO(crbug.com/1063094): This check is necessary mainly because
// GetCanonicalOrigin() may not work correctly for other permission. See
// comemnts in GetCanonicalOrigin(). Remove it once that issue is resolved.
DCHECK(permission == content::PermissionType::AUDIO_CAPTURE ||
permission == content::PermissionType::VIDEO_CAPTURE ||
permission == content::PermissionType::PROTECTED_MEDIA_IDENTIFIER ||
permission == content::PermissionType::DURABLE_STORAGE);
auto it = per_origin_permissions_.find(origin);
if (it == per_origin_permissions_.end()) {
// Don't create a PermissionSet for |origin| if |state| is set to the
// per-origin default, since that would have no effect.
if (state == kDefaultPerOriginStatus)
return;
it = per_origin_permissions_
.insert(
std::make_pair(origin, PermissionSet(kDefaultPerOriginStatus)))
.first;
}
it->second.permission_states[GetPermissionIndex(permission)] = state;
}
void FramePermissionController::SetDefaultPermissionState(
PermissionType permission,
PermissionStatus state) {
DCHECK(state != PermissionStatus::ASK);
default_permissions_.permission_states[GetPermissionIndex(permission)] =
state;
}
PermissionStatus FramePermissionController::GetPermissionState(
PermissionType permission,
const url::Origin& requesting_origin) {
url::Origin embedding_origin =
url::Origin::Create(web_contents_->GetLastCommittedURL());
const url::Origin& canonical_origin =
GetCanonicalOrigin(permission, requesting_origin, embedding_origin);
PermissionSet effective = GetEffectivePermissionsForOrigin(canonical_origin);
return effective.permission_states[GetPermissionIndex(permission)];
}
void FramePermissionController::RequestPermissions(
const std::vector<PermissionType>& permissions,
const url::Origin& requesting_origin,
bool user_gesture,
base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback) {
std::vector<PermissionStatus> result;
result.reserve(permissions.size());
for (auto& permission : permissions) {
result.push_back(GetPermissionState(permission, requesting_origin));
}
std::move(callback).Run(result);
}
FramePermissionController::PermissionSet
FramePermissionController::GetEffectivePermissionsForOrigin(
const url::Origin& origin) {
PermissionSet result = default_permissions_;
auto it = per_origin_permissions_.find(origin);
if (it != per_origin_permissions_.end()) {
// Apply per-origin GRANTED and DENIED states. Permissions with the ASK
// state defer to the defaults.
for (size_t i = 0; i < it->second.permission_states.size(); ++i) {
if (it->second.permission_states[i] != kDefaultPerOriginStatus)
result.permission_states[i] = it->second.permission_states[i];
}
}
return result;
}