1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
fuchsia_web / webengine / browser / frame_permission_controller.cc [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia_web/webengine/browser/frame_permission_controller.h"
#include "base/check_op.h"
#include "components/permissions/permission_util.h"
#include "content/public/browser/web_contents.h"
#include "url/origin.h"
using PermissionStatus = blink::mojom::PermissionStatus;
using PermissionType = blink::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/40680523): 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/40680523): 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 == PermissionType::AUDIO_CAPTURE ||
permission == PermissionType::VIDEO_CAPTURE ||
permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER ||
permission == 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(
permissions::PermissionUtil::GetLastCommittedOriginAsURL(
web_contents_->GetPrimaryMainFrame()));
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,
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;
}