Skip to content

Commit 51aee8c

Browse files
added asynch calls to message box
1 parent 0585328 commit 51aee8c

1 file changed

Lines changed: 167 additions & 102 deletions

File tree

specs/IFramePermissionRequested.md

Lines changed: 167 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -73,73 +73,92 @@ void RegisterIFramePermissionRequestedHandler()
7373
Callback<ICoreWebView2FramePermissionRequestedEventHandler>(
7474
[this](ICoreWebView2Frame* sender,
7575
ICoreWebView2PermissionRequestedEventArgs* args) -> HRESULT {
76-
COREWEBVIEW2_PERMISSION_KIND kind =
77-
COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION;
78-
BOOL userInitiated = FALSE;
79-
wil::unique_cotaskmem_string uri;
80-
81-
CHECK_FAILURE(args->get_PermissionKind(&kind));
82-
CHECK_FAILURE(args->get_IsUserInitiated(&userInitiated));
83-
CHECK_FAILURE(args->get_Uri(&uri));
84-
85-
auto cachedKey = std::tuple<
86-
std::wstring, COREWEBVIEW2_PERMISSION_KIND, BOOL>(
87-
std::wstring(uri.get()), kind, userInitiated);
88-
89-
auto cachedPermission =
90-
m_cachedPermissions.find(cachedKey);
91-
if (cachedPermission != m_cachedPermissions.end())
92-
{
93-
bool allow = cachedPermission->second;
94-
if (allow)
76+
// We avoid potential reentrancy from running a message loop
77+
// in the permission requested event handler by showing the
78+
// dialog via lambda run asynchronously outside of this event
79+
// handler.
80+
auto showDialog = [this, args] {
81+
COREWEBVIEW2_PERMISSION_KIND kind =
82+
COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION;
83+
BOOL userInitiated = FALSE;
84+
wil::unique_cotaskmem_string uri;
85+
86+
CHECK_FAILURE(args->get_PermissionKind(&kind));
87+
CHECK_FAILURE(args->get_IsUserInitiated(&userInitiated));
88+
CHECK_FAILURE(args->get_Uri(&uri));
89+
90+
auto cachedKey = std::tuple<
91+
std::wstring, COREWEBVIEW2_PERMISSION_KIND, BOOL>(
92+
std::wstring(uri.get()), kind, userInitiated);
93+
94+
auto cachedPermission =
95+
m_cachedPermissions.find(cachedKey);
96+
if (cachedPermission != m_cachedPermissions.end())
9597
{
96-
CHECK_FAILURE(args->put_State(
97-
COREWEBVIEW2_PERMISSION_STATE_ALLOW));
98+
bool allow = cachedPermission->second;
99+
if (allow)
100+
{
101+
CHECK_FAILURE(args->put_State(
102+
COREWEBVIEW2_PERMISSION_STATE_ALLOW));
103+
}
104+
else
105+
{
106+
CHECK_FAILURE(args->put_State(
107+
COREWEBVIEW2_PERMISSION_STATE_DENY));
108+
}
109+
110+
PutHandled(args);
111+
return S_OK;
98112
}
99-
else
113+
114+
std::wstring message =
115+
L"An iframe has requested device permission for ";
116+
message += NameOfPermissionKind(kind);
117+
message += L" to the website at ";
118+
message += uri.get();
119+
message += L"?\n\n";
120+
message += L"Do you want to grant permission?\n";
121+
message +=
122+
(userInitiated
123+
? L"This request came from a user gesture."
124+
: L"This request did not come from a user "
125+
L"gesture.");
126+
127+
int response = MessageBox(
128+
nullptr, message.c_str(), L"Permission Request",
129+
MB_YESNOCANCEL | MB_ICONWARNING);
130+
131+
COREWEBVIEW2_PERMISSION_STATE state =
132+
COREWEBVIEW2_PERMISSION_STATE_DEFAULT;
133+
134+
if (response == IDYES)
135+
{
136+
m_cachedPermissions[cachedKey] = true;
137+
state = COREWEBVIEW2_PERMISSION_STATE_ALLOW;
138+
}
139+
else if (response == IDNO)
100140
{
101-
CHECK_FAILURE(args->put_State(
102-
COREWEBVIEW2_PERMISSION_STATE_DENY));
141+
m_cachedPermissions[cachedKey] = false;
142+
state = COREWEBVIEW2_PERMISSION_STATE_DENY;
103143
}
104144

145+
CHECK_FAILURE(args->put_State(state));
146+
105147
PutHandled(args);
106148
return S_OK;
107-
}
108-
109-
std::wstring message =
110-
L"An iframe has requested device permission for ";
111-
message += NameOfPermissionKind(kind);
112-
message += L" to the website at ";
113-
message += uri.get();
114-
message += L"?\n\n";
115-
message += L"Do you want to grant permission?\n";
116-
message +=
117-
(userInitiated
118-
? L"This request came from a user gesture."
119-
: L"This request did not come from a user "
120-
L"gesture.");
121-
122-
int response = MessageBox(
123-
nullptr, message.c_str(), L"Permission Request",
124-
MB_YESNOCANCEL | MB_ICONWARNING);
125-
126-
COREWEBVIEW2_PERMISSION_STATE state =
127-
COREWEBVIEW2_PERMISSION_STATE_DEFAULT;
128-
129-
if (response == IDYES)
130-
{
131-
m_cachedPermissions[cachedKey] = true;
132-
state = COREWEBVIEW2_PERMISSION_STATE_ALLOW;
133-
}
134-
else if (response == IDNO)
135-
{
136-
m_cachedPermissions[cachedKey] = false;
137-
state = COREWEBVIEW2_PERMISSION_STATE_DENY;
138-
}
139-
140-
CHECK_FAILURE(args->put_State(state));
141-
142-
PutHandled(args);
149+
};
150+
151+
// Obtain a deferral for the event so that the CoreWebView2
152+
// doesn't examine the properties we set on the event args until
153+
// after we call the Complete method asynchronously later.
154+
wil::com_ptr<ICoreWebView2Deferral> deferral;
155+
CHECK_FAILURE(args->GetDeferral(&deferral));
156+
157+
m_appWindow->RunAsync([deferral, showDialog]() {
158+
showDialog();
159+
CHECK_FAILURE(deferral->Complete());
160+
});
161+
143162
return S_OK;
144163
}).Get(),
145164
&m_PermissionRequestedToken));
@@ -201,51 +220,74 @@ void RegisterIFramePermissionRequestedHandler()
201220
{
202221
m_webview.CoreWebView2.FrameCreated += (sender, frameCreatedArgs) =>
203222
{
204-
frameCreatedArgs.Frame.PermissionRequested += (frameSender, permissionArgs) =>
223+
// Checking for runtime support of CoreWebView2Frame.PermissionRequested
224+
try
205225
{
206-
var cachedKey = Tuple.Create(permissionArgs.Uri,
207-
permissionArgs.PermissionKind, permissionArgs.IsUserInitiated);
208-
209-
if (m_cachedPermissions.ContainsKey(cachedKey))
226+
frameCreatedArgs.Frame.PermissionRequested += (frameSender, permissionArgs) =>
210227
{
211-
permissionArgs.State = m_cachedPermissions[cachedKey]
212-
? CoreWebView2PermissionState.Allow
213-
: CoreWebView2PermissionState.Deny;
214-
215-
permissionArgs.Handled = true;
216-
return;
217-
}
218-
219-
string message = "An iframe has requested device permission for ";
220-
message += NameOfPermissionKind(permissionArgs.PermissionKind);
221-
message += " to the website at ";
222-
message += permissionArgs.Uri;
223-
message += "\n\n";
224-
message += "Do you want to grant permission?\n";
225-
message +=
226-
(permissionArgs.IsUserInitiated
227-
? "This request came from a user gesture."
228-
: "This request did not come from a user gesture.");
229-
230-
var selection = MessageBox.Show(message, "iframe PermissionRequest",
231-
MessageBoxButton.YesNoCancel);
232-
if (selection == MessageBoxResult.Yes)
233-
{
234-
permissionArgs.State = CoreWebView2PermissionState.Allow;
235-
m_cachedPermissions[cachedKey] = true;
236-
}
237-
else if (selection == MessageBoxResult.No)
238-
{
239-
permissionArgs.State = CoreWebView2PermissionState.Deny;
240-
m_cachedPermissions[cachedKey] = false;
241-
}
242-
else
243-
{
244-
permissionArgs.State = CoreWebView2PermissionState.Default;
245-
}
228+
// Developer can obtain a deferral for the event so that the CoreWebView2
229+
// doesn't examine the properties we set on the event args until
230+
// after the deferral completes asynchronously.
231+
CoreWebView2Deferral deferral = args.GetDeferral();
232+
233+
// We avoid potential reentrancy from running a message loop
234+
// in the permission requested event handler by showing the
235+
// dialog asynchronously.
236+
System.Threading.SynchronizationContext.Current.Post((_) => {
237+
using (deferral)
238+
{
239+
var cachedKey = Tuple.Create(permissionArgs.Uri,
240+
permissionArgs.PermissionKind, permissionArgs.IsUserInitiated);
241+
242+
if (m_cachedPermissions.ContainsKey(cachedKey))
243+
{
244+
permissionArgs.State = m_cachedPermissions[cachedKey]
245+
? CoreWebView2PermissionState.Allow
246+
: CoreWebView2PermissionState.Deny;
247+
248+
PutHandled(permissionArgs);
249+
return;
250+
}
251+
252+
string message = "An iframe has requested device permission for ";
253+
message += NameOfPermissionKind(permissionArgs.PermissionKind);
254+
message += " to the website at ";
255+
message += permissionArgs.Uri;
256+
message += "\n\n";
257+
message += "Do you want to grant permission?\n";
258+
message +=
259+
(permissionArgs.IsUserInitiated
260+
? "This request came from a user gesture."
261+
: "This request did not come from a user gesture.");
262+
263+
var selection = MessageBox.Show(message, "iframe PermissionRequest",
264+
MessageBoxButton.YesNoCancel);
265+
266+
permissionArgs.State = CoreWebView2PermissionState.Default;
267+
268+
if (selection == MessageBoxResult.Yes)
269+
{
270+
permissionArgs.State = CoreWebView2PermissionState.Allow;
271+
m_cachedPermissions[cachedKey] = true;
272+
}
273+
else if (selection == MessageBoxResult.No)
274+
{
275+
permissionArgs.State = CoreWebView2PermissionState.Deny;
276+
m_cachedPermissions[cachedKey] = false;
277+
}
278+
279+
PutHandled(permissionArgs);
280+
}
281+
}, null);
282+
246283
247-
permissionArgs.Handled = true;
248-
};
284+
};
285+
}
286+
catch (NotImplementedException exception)
287+
{
288+
MessageBox.Show(this, "Frame Permission Requested Failed: " + exception.Message,
289+
"Frame Permission Requested");
290+
}
249291
};
250292
}
251293
@@ -269,6 +311,29 @@ string NameOfPermissionKind(CoreWebView2PermissionKind kind)
269311
return "Unknown resources";
270312
}
271313
}
314+
315+
void PutHandled(CoreWebView2PermissionEventArgs args)
316+
{
317+
// In the case of an iframe requesting permission, the default behavior is
318+
// to first raise the PermissionRequested event off of the CoreWebView2Frame
319+
// and invoke it's handlers, and then raise the event off the CoreWebView2
320+
// and invoke it's handlers. However, If we set Handled to true on the
321+
// CoreWebView2Frame event handler, then we will not raise the
322+
// PermissionRequested event off the CoreWebView2.
323+
try
324+
{
325+
// NotImplementedException could be thrown if underlying runtime did not
326+
// implement Handled. However, we only run this code after checking if
327+
// CoreWebView2Frame.PermissionRequested exists, and both exist together,
328+
// so it would not be a problem.
329+
permissionArgs.Handled = true;
330+
}
331+
catch(NotImplementedException)
332+
{
333+
MessageBox.Show(this, "Put Handled Failed: " + exception.Message,
334+
"Frame Permission Requested Handled");
335+
}
336+
}
272337
```
273338

274339
# API Details

0 commit comments

Comments
 (0)