Skip to content

Commit e7c6b10

Browse files
added spec file
1 parent 79f85a8 commit e7c6b10

1 file changed

Lines changed: 221 additions & 0 deletions

File tree

specs/IFramePermissionRequested.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Background
2+
3+
4+
# Description
5+
6+
7+
# Examples
8+
## C++: Regestering IFrame Permission Requested Handler
9+
10+
``` cpp
11+
wil::com_ptr<ICoreWebView2> m_webview;
12+
13+
EventRegistrationToken m_frameCreatedToken = {};
14+
EventRegistrationToken m_permissionRequestedToken = {};
15+
16+
void RegisterIFramePermissionRequestedHandler()
17+
{
18+
webview4 = m_webview.try_query<ICoreWebView2_4>();
19+
if (webview4)
20+
{
21+
CHECK_FAILURE(webview4->add_FrameCreated(
22+
Callback<ICoreWebView2FrameCreatedEventHandler>(
23+
[this](ICoreWebView2* sender, ICoreWebView2FrameCreatedEventArgs* args) -> HRESULT {
24+
wil::com_ptr<ICoreWebView2Frame> webviewFrame;
25+
CHECK_FAILURE(args->get_Frame(&webviewFrame));
26+
27+
auto webviewFrame2 = webviewFrame.try_query<ICoreWebView2Frame2>();
28+
if (webviewFrame2)
29+
{
30+
CHECK_FAILURE(webviewFrame2->add_PermissionRequested(
31+
Callback<ICoreWebView2FramePermissionRequestedEventHandler>(
32+
[this](ICoreWebView2Frame* sender,
33+
ICoreWebView2PermissionRequestedEventArgs* args) -> HRESULT {
34+
COREWEBVIEW2_PERMISSION_KIND kind =
35+
COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION;
36+
BOOL userInitiated = FALSE;
37+
wil::unique_cotaskmem_string uri;
38+
39+
CHECK_FAILURE(args->get_PermissionKind(&kind));
40+
CHECK_FAILURE(args->get_IsUserInitiated(&userInitiated));
41+
CHECK_FAILURE(args->get_Uri(&uri));
42+
43+
auto cached_key = std::tuple<
44+
std::wstring, COREWEBVIEW2_PERMISSION_KIND, BOOL>(
45+
std::wstring(uri.get()), kind, userInitiated);
46+
47+
auto cached_permission =
48+
m_cached_permissions.find(cached_key);
49+
if (cached_permission != m_cached_permissions.end())
50+
{
51+
bool allow = cached_permission->second;
52+
if (allow)
53+
{
54+
CHECK_FAILURE(args->put_State(
55+
COREWEBVIEW2_PERMISSION_STATE_ALLOW));
56+
}
57+
else
58+
{
59+
CHECK_FAILURE(args->put_State(
60+
COREWEBVIEW2_PERMISSION_STATE_DENY));
61+
}
62+
63+
PutHandled(args);
64+
return S_OK;
65+
}
66+
67+
std::wstring message =
68+
L"An iframe has requested device permission for ";
69+
message += SettingsComponent::NameOfPermissionKind(kind);
70+
message += L" to the website at ";
71+
message += uri.get();
72+
message += L"?\n\n";
73+
message += L"Do you want to grant permission?\n";
74+
message +=
75+
(userInitiated
76+
? L"This request came from a user gesture."
77+
: L"This request did not come from a user "
78+
L"gesture.");
79+
80+
int response = MessageBox(
81+
nullptr, message.c_str(), L"Permission Request",
82+
MB_YESNOCANCEL | MB_ICONWARNING);
83+
84+
85+
COREWEBVIEW2_PERMISSION_STATE state =
86+
COREWEBVIEW2_PERMISSION_STATE_DEFAULT;
87+
88+
if (response == IDYES)
89+
{
90+
m_cached_permissions[cached_key] = true;
91+
state = COREWEBVIEW2_PERMISSION_STATE_ALLOW;
92+
}
93+
else if (response == IDNO)
94+
{
95+
m_cached_permissions[cached_key] = false;
96+
state = COREWEBVIEW2_PERMISSION_STATE_DENY;
97+
}
98+
99+
CHECK_FAILURE(args->put_State(state));
100+
101+
PutHandled(args);
102+
return S_OK;
103+
}).Get(),
104+
&m_PermissionRequestedToken));
105+
}
106+
107+
return S_OK;
108+
}).Get(),
109+
&m_FrameCreatedToken));
110+
}
111+
}
112+
113+
static PCWSTR NameOfPermissionKind(COREWEBVIEW2_PERMISSION_KIND kind)
114+
{
115+
switch (kind)
116+
{
117+
case COREWEBVIEW2_PERMISSION_KIND_MICROPHONE:
118+
return L"Microphone";
119+
case COREWEBVIEW2_PERMISSION_KIND_CAMERA:
120+
return L"Camera";
121+
case COREWEBVIEW2_PERMISSION_KIND_GEOLOCATION:
122+
return L"Geolocation";
123+
case COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS:
124+
return L"Notifications";
125+
case COREWEBVIEW2_PERMISSION_KIND_OTHER_SENSORS:
126+
return L"Generic Sensors";
127+
case COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ:
128+
return L"Clipboard Read";
129+
default:
130+
return L"Unknown resources";
131+
}
132+
}
133+
134+
static void PutHandled(ICoreWebView2PermissionRequestedEventArgs* args)
135+
{
136+
// In the case of an iframe requesting permission, the default behavior is
137+
// to first raise the PermissionRequested event off of the CoreWebView2Frame
138+
// and invoke it's handlers, and then raise the event off the CoreWebView2
139+
// and invoke it's handlers. However, If we set Handled to true on the
140+
// CoreWebView2Frame event handler, then we will not raise the
141+
// PermissionRequested event off the CoreWebView2.
142+
wil::com_ptr<ICoreWebView2PermissionRequestedEventArgs2> args2;
143+
CHECK_FAILURE(args->QueryInterface(IID_PPV_ARGS(&args2)));
144+
if (args2) {
145+
CHECK_FAILURE(args2->put_Handled(true));
146+
}
147+
}
148+
```
149+
150+
## C#: TBD
151+
```c#
152+
153+
```
154+
155+
# API Details
156+
## C++
157+
```
158+
interface ICoreWebView2Frame2;
159+
interface ICoreWebView2FramePermissionRequestedEventHandler;
160+
interface ICoreWebView2FramePermissionRequestedEventArgs2;
161+
162+
/// This is an extension of the ICoreWebView2Frame interface.
163+
[uuid(3ed01620-13fc-4c2c-9eb9-62fccd689093), object, pointer_default(unique)]
164+
interface ICoreWebView2Frame2 : ICoreWebView2Frame {
165+
/// Add an event handler for the `PermissionRequested` event.
166+
/// `PermissionRequested` is raised when content in an iframe requests
167+
/// permission to access some priveleged resources.
168+
///
169+
/// This relates to the `PermissionRequested` event on the `CoreWebView2`.
170+
/// Both these events will be raised in the case of an iframe requesting
171+
/// permission. The `CoreWebView2Frame`'s event handlers will be invoked
172+
/// before the event handlers on the `CoreWebView2`. If the `Handled` property
173+
/// of the `PermissionRequestedEventArgs` is set to TRUE within the
174+
/// `CoreWebView2Frame` event handler, then the event will not be
175+
/// raised on the `CoreWebView2`, and it's event handlers will not be invoked.
176+
///
177+
/// In the case of nested iframes, the 'PermissionRequested' event will
178+
/// be raised from the top level iframe.
179+
///
180+
/// If a deferral is not taken on the event args, the subsequent scripts are
181+
/// blocked until the event handler returns. If a deferral is taken, the
182+
/// scripts are blocked until the deferral is completed.
183+
///
184+
/// \snippet ScenarioIFrameDevicePermission.cpp PermissionRequested
185+
HRESULT add_PermissionRequested(
186+
[in] ICoreWebView2FramePermissionRequestedEventHandler* handler,
187+
[out] EventRegistrationToken* token);
188+
189+
/// Remove an event handler previously added with `add_PermissionRequested`
190+
HRESULT remove_PermissionRequested(
191+
[in] EventRegistrationToken token);
192+
}
193+
194+
/// Receives `PermissionRequested` events.
195+
[uuid(603ea097-c805-43fb-aa35-80949c1e4b26), object, pointer_default(unique)]
196+
interface ICoreWebView2FramePermissionRequestedEventHandler : IUnknown {
197+
/// Provides the event args for the corresponding event.
198+
HRESULT Invoke(
199+
[in] ICoreWebView2Frame* sender,
200+
[in] ICoreWebView2PermissionRequestedEventArgs* args);
201+
}
202+
203+
/// This is a continuation of the `ICoreWebView2PermissionRequestedEventArgs` interface.
204+
[uuid(d52ce9b5-c603-4c33-9887-c06c77b54b3c), object, pointer_default(unique)]
205+
interface ICoreWebView2PermissionRequestedEventArgs2: ICoreWebView2PermissionRequestedEventArgs {
206+
/// By default, both the `PermissionRequested` event handlers on the
207+
/// `CoreWebView2Frame' and the `CoreWebView2` will be invoked, with the
208+
/// `CoreWebView2Frame' event handlers invoked first. The host may
209+
/// set this flag to `TRUE` within the `CoreWebView2Frame' event handlers
210+
/// to prevent the remaining `CoreWebView2` event handlers from being invoked.
211+
[propget] HRESULT Handled([out, retval] BOOL* handled);
212+
213+
/// Sets the `Handled` property.
214+
[propput] HRESULT Handled([in] BOOL handled);
215+
}
216+
```
217+
218+
## C#
219+
```c#
220+
221+
```

0 commit comments

Comments
 (0)