0

[fuchsia] Grant web permissions to Frame contents regardless of origin.

Temporarily allow the default permissions granted to each Frame to be
configured by passing a wildcard origin to SetPermissionState().

Bug: b/170198665, 1136994
Change-Id: I653622a5bbe8d8f7d08bc4f1c0fa6da94dc207cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2452633
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: David Dorwin <ddorwin@chromium.org>
Auto-Submit: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817118}
This commit is contained in:
Wez
2020-10-14 18:31:33 +00:00
committed by Commit Bot
parent 22b2cdc0fa
commit 0c5037ad7c
4 changed files with 115 additions and 45 deletions

@ -894,14 +894,6 @@ void FrameImpl::SetPermissionState(
return;
}
auto web_origin = ParseAndValidateWebOrigin(web_origin_string);
if (!web_origin) {
LOG(ERROR) << "SetPermissionState() called with invalid web_origin: "
<< web_origin_string;
CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
return;
}
content::PermissionType type =
FidlPermissionTypeToContentPermissionType(fidl_permission.type());
@ -910,6 +902,23 @@ void FrameImpl::SetPermissionState(
? blink::mojom::PermissionStatus::GRANTED
: blink::mojom::PermissionStatus::DENIED;
// TODO(crbug.com/1136994): Remove this once the PermissionManager API is
// available.
if (web_origin_string == "*" &&
type == content::PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
permission_controller_.SetDefaultPermissionState(type, state);
return;
}
// Handle per-origin permissions specifications.
auto web_origin = ParseAndValidateWebOrigin(web_origin_string);
if (!web_origin) {
LOG(ERROR) << "SetPermissionState() called with invalid web_origin: "
<< web_origin_string;
CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
return;
}
permission_controller_.SetPermissionState(type, web_origin.value(), state);
}

@ -7,7 +7,7 @@
#include "base/check_op.h"
#include "url/origin.h"
using PermissionState = blink::mojom::PermissionStatus;
using PermissionStatus = blink::mojom::PermissionStatus;
using PermissionType = content::PermissionType;
namespace {
@ -18,59 +18,90 @@ size_t GetPermissionIndex(PermissionType type) {
return index;
}
constexpr PermissionStatus kDefaultPerOriginStatus = PermissionStatus::ASK;
} // namespace
FramePermissionController::PermissionSet::PermissionSet() {
for (auto& permission : permission_state) {
permission = PermissionState::DENIED;
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() = default;
FramePermissionController::~FramePermissionController() = default;
void FramePermissionController::SetPermissionState(PermissionType permission,
const url::Origin& origin,
PermissionState state) {
PermissionStatus state) {
auto it = per_origin_permissions_.find(origin);
if (it == per_origin_permissions_.end()) {
// All permissions are denied by default.
if (state == PermissionState::DENIED)
// 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()))
it = per_origin_permissions_
.insert(
std::make_pair(origin, PermissionSet(kDefaultPerOriginStatus)))
.first;
}
it->second.permission_state[GetPermissionIndex(permission)] = state;
it->second.permission_states[GetPermissionIndex(permission)] = state;
}
PermissionState FramePermissionController::GetPermissionState(
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& origin) {
auto it = per_origin_permissions_.find(origin);
if (it == per_origin_permissions_.end()) {
return PermissionState::DENIED;
}
return it->second.permission_state[GetPermissionIndex(permission)];
PermissionSet effective = GetEffectivePermissionsForOrigin(origin);
return effective.permission_states[GetPermissionIndex(permission)];
}
void FramePermissionController::RequestPermissions(
const std::vector<PermissionType>& permissions,
const url::Origin& origin,
bool user_gesture,
base::OnceCallback<void(const std::vector<PermissionState>&)> callback) {
std::vector<PermissionState> result;
base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback) {
std::vector<PermissionStatus> result;
result.reserve(permissions.size());
auto it = per_origin_permissions_.find(origin);
if (it == per_origin_permissions_.end()) {
result.resize(permissions.size(), PermissionState::DENIED);
} else {
result.reserve(permissions.size());
for (auto& permission : permissions) {
result.push_back(
it->second.permission_state[GetPermissionIndex(permission)]);
}
PermissionSet effective = GetEffectivePermissionsForOrigin(origin);
for (auto& permission : permissions) {
result.push_back(
effective.permission_states[GetPermissionIndex(permission)]);
}
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;
}

@ -5,10 +5,11 @@
#ifndef FUCHSIA_ENGINE_BROWSER_FRAME_PERMISSION_CONTROLLER_H_
#define FUCHSIA_ENGINE_BROWSER_FRAME_PERMISSION_CONTROLLER_H_
#include <map>
#include <array>
#include <vector>
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "content/public/browser/permission_type.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
@ -31,6 +32,14 @@ class FramePermissionController {
const url::Origin& origin,
blink::mojom::PermissionStatus state);
// Sets the default |state| for the specified |permission|. Setting |state| to
// ASK causes the |default_permissions_| state to be used for |permission| for
// this origin.
// TODO(crbug.com/1063094): Allow ASK to be the default state, to indicate
// that the user should be prompted.
void SetDefaultPermissionState(content::PermissionType permission,
blink::mojom::PermissionStatus state);
// Returns current permission state of the specified |permission| and
// |origin|.
blink::mojom::PermissionStatus GetPermissionState(
@ -41,8 +50,8 @@ class FramePermissionController {
// is resolved, the |callback| is called with a list of status values, one for
// each value in |permissions|, in the same order.
//
// TODO(crbug.com/922833): Current implementation doesn't actually prompt the
// user: all permissions in the PROMPT state are denied silently. Define
// TODO(crbug.com/1063094): Current implementation doesn't actually prompt the
// user: all permissions in the ASK state are denied silently. Define
// fuchsia.web.PermissionManager protocol and use it to request permissions.
void RequestPermissions(
const std::vector<content::PermissionType>& permissions,
@ -53,13 +62,26 @@ class FramePermissionController {
private:
struct PermissionSet {
PermissionSet();
// Initializes all permissions with |initial_state|.
explicit PermissionSet(blink::mojom::PermissionStatus initial_state);
blink::mojom::PermissionStatus
permission_state[static_cast<int>(content::PermissionType::NUM)];
PermissionSet(const PermissionSet& other);
PermissionSet& operator=(const PermissionSet& other);
std::array<blink::mojom::PermissionStatus,
static_cast<int>(content::PermissionType::NUM)>
permission_states;
};
std::map<url::Origin, PermissionSet> per_origin_permissions_;
// Returns the effective PermissionStatus for |origin|. If the per-|origin|
// state is ASK, or there are no specific permissions set for |origin|, then
// the default permission status takes effect. This means that it is not
// currently possible to set a default of GRANTED/DENIED, and to override that
// to ASK for specific origins.
PermissionSet GetEffectivePermissionsForOrigin(const url::Origin& origin);
base::flat_map<url::Origin, PermissionSet> per_origin_permissions_;
PermissionSet default_permissions_{blink::mojom::PermissionStatus::DENIED};
};
#endif // FUCHSIA_ENGINE_BROWSER_FRAME_PERMISSION_CONTROLLER_H_
#endif // FUCHSIA_ENGINE_BROWSER_FRAME_PERMISSION_CONTROLLER_H_

@ -136,14 +136,22 @@ void CastComponent::StartComponent() {
application_controller_ = std::make_unique<ApplicationControllerImpl>(
frame(), application_context_.get());
// Pass application permissions to the frame.
// Apply application-specific web permissions to the fuchsia.web.Frame.
if (application_config_.has_permissions()) {
std::string origin = GURL(application_config_.web_url()).GetOrigin().spec();
// TODO(crbug.com/1136994): Replace this with the PermissionManager API
// when available.
const std::string origin =
GURL(application_config_.web_url()).GetOrigin().spec();
for (auto& permission : application_config_.permissions()) {
fuchsia::web::PermissionDescriptor permission_clone;
zx_status_t status = permission.Clone(&permission_clone);
ZX_DCHECK(status == ZX_OK, status);
frame()->SetPermissionState(std::move(permission_clone), origin,
const bool all_origins =
permission_clone.has_type() &&
(permission_clone.type() ==
fuchsia::web::PermissionType::PROTECTED_MEDIA_IDENTIFIER);
frame()->SetPermissionState(std::move(permission_clone),
all_origins ? "*" : origin,
fuchsia::web::PermissionState::GRANTED);
}
}