Skip to content

Commit 9df00f8

Browse files
author
Maura Winstanley
committed
Add Launching Registered Protocols spec
1 parent bd570e5 commit 9df00f8

1 file changed

Lines changed: 241 additions & 0 deletions

File tree

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# Background
2+
3+
We are exposing an event that will fire when an attempt to launch a registered protocol is made. This event will fire when this attempt is made and the host will be given the option to cancel the launch, handle the popup dialog to hide the dialog, as well as revoke permissions that have been previously given to the origin launching the protocol.
4+
5+
# Description
6+
7+
This event will fire before the registered protocol launch occurs. Currently a popup dialog is displayed in which the user can click `Open` or `Cancel`. If the request is made from a trustworthy origin a checkmark box will be displayed that will allow the user to check to always allow this registered protocol from this origin. This event will allow the host to programatically cancel the event, suppress the popup dialog, and revoke permissions given in the past to always allow the protocol from the origin.
8+
9+
There are two events associated with the registered protocol launch - one for the main frame, and one for non-main frame(s). In this case in which the launch request is made from a non-main frame, the frame will raise a `LaunchingRegisteredProtocol` event as well as `CoreWebView2.FrameLaunchingRegisteredProtocol` event.
10+
# Examples
11+
12+
## Win32 C++
13+
14+
```cpp
15+
16+
CHECK_FAILURE(m_webView->add_LaunchingRegisteredProtocol(
17+
Callback<ICoreWebView2LaunchingRegisteredProtocolEventHandler>(
18+
[this](
19+
ICoreWebView2* sender,
20+
ICoreWebView2LaunchingRegisteredProtocolEventArgs* args) {
21+
wil::unique_cotaskmem_string uri;
22+
CHECK_FAILURE(args->get_Uri(&uri));
23+
if (wcscmp(uri.get(), L"calculator://") == 0)
24+
{
25+
CHECK_FAILURE(args->put_Handled(TRUE));
26+
// If this matches our desired protocol, then suppress the
27+
// popup dialog.
28+
}
29+
else
30+
{
31+
CHECK_FAILURE(args->put_Handled(FALSE));
32+
// Otherwise allow the popup dialog, and allow the user to decide
33+
// whether or not to allow the external app to launch.
34+
}
35+
return S_OK;
36+
})
37+
.Get(),
38+
&m_launchingRegisteredProtocolToken));
39+
40+
CHECK_FAILURE(frame->add_LaunchingRegisteredProtocol(
41+
Callback<ICoreWebView2FrameLaunchingRegisteredProtocolEventHandler>(
42+
[this](
43+
ICoreWebView2Frame* sender,
44+
ICoreWebView2LaunchingRegisteredProtocolEventArgs* args) {
45+
wil::unique_cotaskmem_string uri;
46+
CHECK_FAILURE(args->get_Uri(&uri));
47+
if (wcscmp(uri.get(), L"calculator://") == 0)
48+
{
49+
// If this matches our desired protocol, then suppress the
50+
// popup dialog.
51+
CHECK_FAILURE(args->put_Handled(TRUE));
52+
}
53+
else
54+
{
55+
// Otherwise revoke permissions previously granted to this protocol
56+
// from this origin. This will trigger the dialog to appear to allow the user
57+
// to confirm the protocol launch.
58+
CHECK_FAILURE(args->put_RevokeProtocolPermissionsPerOrigin(TRUE));
59+
}
60+
return S_OK;
61+
})
62+
.Get(),
63+
&m_frameLaunchingRegisteredProtocolToken));
64+
65+
```
66+
67+
## .NET and WinRT
68+
69+
```c #
70+
71+
void WebView_LaunchingRegisteredProtocol(object target, CoreWebView2LaunchingRegisteredProtocolEventArgs e)
72+
{
73+
if (e.Uri == "calculator:///")
74+
{
75+
// If this matches our desired protocol, then suppress the popup dialog.
76+
e.Handled = true;
77+
}
78+
else
79+
{
80+
// Otherwise allow the popup dialog, and allow the user to decide
81+
// whether or not to allow the registered protocol to launch.
82+
e.Handled = false;
83+
}
84+
webView.CoreWebView2.FrameCreated += (sender, args) =>
85+
{
86+
// Apply the same logic as above to non-main frame raising the event.
87+
args.Frame.LaunchingRegisteredProtocol += (frameSender, LaunchingRegisteredProtocolArgs) =>
88+
{
89+
if (LaunchingRegisteredProtocolArgs.Uri == "calculator:///")
90+
{
91+
// If this matches our desired protocol, then suppress the popup dialog.
92+
e.Handled = true;
93+
}
94+
else
95+
{
96+
// Otherwise revoke permissions previously granted to this protocol
97+
// from this origin. This will trigger the dialog to appear to allow the user
98+
// to confirm the protocol launch.
99+
e.RevokeProtocolPermissionsPerOrigin = true;
100+
}
101+
};
102+
};
103+
}
104+
105+
```
106+
107+
# API Notes
108+
109+
See [API Details](#api-details) section below for API reference.
110+
111+
# API Details
112+
113+
## Win32 C++
114+
115+
```IDL
116+
/// This is the ICoreWebView2Frame3 interface.
117+
[uuid(fe1d3718-fe8d-48ab-8594-9e3fff6755ac), object, pointer_default(unique)]
118+
interface ICoreWebView2Frame3 : IUnknown {
119+
/// Add an event handler for the `FrameRegisteredProtocol` event.
120+
/// A frame will raise a `LaunchingRegisteredProtocol` event and
121+
/// a `CoreWebView2.FrameLaunchingRegisteredProtocol` event. All of the
122+
/// `FrameLaunchingRegisteredProtocol` event handlers for the current
123+
/// frame will be run before the `LaunchingRegisteredProtocol` event handlers.
124+
/// All of the event handlers share a common `LaunchingRegisteredProtocolEventArgs`
125+
/// object. Whichever event handler is last to change the
126+
/// `LaunchingRegisteredProtocolEventArgs.Cancel` property will
127+
/// decide if the frame launch registered protocol request will be cancelled.
128+
/// Whichever event handler is last to change the
129+
/// `LaunchingRegisteredProtocolEventArgs.Handled` property will decide if
130+
/// the frame external protocol dialog will be suppressed.
131+
/// Whichever event handler is last to change the
132+
/// `LaunchingRegisteredProtocolEventArgs.RevokeProtocolPermissionsPerOrigin`
133+
/// property will determine if the permissions for that origin per protocol
134+
/// will be revoked.
135+
136+
HRESULT add_LaunchingRegisteredProtocol(
137+
[in] ICoreWebView2FrameLaunchingRegisteredProtocolEventHandler* eventHandler,
138+
[out] EventRegistrationToken* token);
139+
140+
/// Remove an event handler previously added with `add_LaunchingRegisteredProtocol`.
141+
HRESULT remove_LaunchingRegisteredProtocol(
142+
[in] EventRegistrationToken token);
143+
}
144+
145+
/// Receives `LaunchingRegisteredProtocol` events for main frame.
146+
[uuid(e5fea648-79c9-47aa-8314-f471fe627649), object, pointer_default(unique)]
147+
interface ICoreWebView2LaunchingRegisteredProtocolEventHandler: IUnknown {
148+
/// Provides the event args for the corresponding event.
149+
HRESULT Invoke(
150+
[in] ICoreWebView2* sender,
151+
[in] ICoreWebView2LaunchingRegisteredProtocolEventArgs* args);
152+
}
153+
154+
/// Receives `LaunchingRegisteredProtocol` events for non-main frame.
155+
[uuid(a898c12c-f949-474c-913b-428770cfc177), object, pointer_default(unique)]
156+
interface ICoreWebView2FrameLaunchingRegisteredProtocolEventHandler: IUnknown {
157+
/// Provides the event args for the corresponding event.
158+
HRESULT Invoke(
159+
[in] ICoreWebView2Frame* sender,
160+
[in] ICoreWebView2LaunchingRegisteredProtocolEventArgs* args);
161+
}
162+
163+
/// Event args for `LaunchingRegisteredProtocol` event.
164+
[uuid(fc43b557-9713-4a67-af8d-a76ef3a206e8), object, pointer_default(unique)]
165+
interface ICoreWebView2LaunchingRegisteredProtocolEventArgs: IUnknown {
166+
/// The uri of the requested app protocol.
167+
168+
[propget] HRESULT Uri([out, retval] LPWSTR* uri);
169+
170+
/// The host may set this flag to cancel the external app launch. If set to
171+
/// `TRUE`, the external app will not be launched, but the
172+
/// `NavigationCompleted` event will still fire. If cancelled, the external
173+
/// protocol dialog is not displayed regardless of the `Handled` property.
174+
175+
[propget] HRESULT Cancel([out, retval] BOOL* cancel);
176+
177+
/// Sets the `Cancel` property.
178+
179+
[propput] HRESULT Cancel([in] BOOL cancel);
180+
181+
/// The host may set this flag to `TRUE` to hide the default external
182+
/// protocol dialog for this navigation if it is a registered app protocol.
183+
/// The external app protocol request will continue as normal if it is not
184+
/// cancelled, although there will be no default UI shown. By default the
185+
/// value is `FALSE` and the default external protocol dialog is shown.
186+
187+
[propget] HRESULT Handled([out, retval] BOOL* handled);
188+
189+
/// Sets the `Handled` property.
190+
191+
[propput] HRESULT Handled([in] BOOL handled);
192+
193+
/// The host may set this flag to `TRUE` to revoke previous permissions given
194+
/// to this protocol/origin. In the case in which the registered protocol
195+
/// launch is being requested from a trustworthy origin, the dialog
196+
/// prompt (if not handled) will display a checkbox that gives the user the option to
197+
/// always allow this origin to open links of this type in the associated app.
198+
/// Once checked by the user, this protocol for this origin will be launched automatically
199+
/// without displaying the dialog prompt.
200+
/// If the `Cancel` property is set to `TRUE` while this property is set to
201+
/// `TRUE` the registered protocol will not be launched in this instance. If `Handled` is set
202+
/// to `TRUE` the dialog prompt will still be disabled regardless of this property, but the
203+
/// permissions will be revoked in the future if this property is set to `TRUE`.
204+
205+
[propget] HRESULT RevokeProtocolPermissionsPerOrigin(
206+
[out, retval] BOOL* revokeProtocolPermissionsPerOrigin);
207+
208+
/// Sets the `RevokeProtocolPermissionsPerOrigin` property.
209+
[propput] HRESULT RevokeProtocolPermissionsPerOrigin([in] BOOL revokeProtocolPermissionsPerOrigin);
210+
}
211+
212+
```
213+
## .NET and WinRT
214+
215+
```c#
216+
namespace Microsoft.Web.WebView2.Core
217+
{
218+
runtimeclass CoreWebView2LaunchingRegisteredProtocolEventArgs;
219+
220+
runtimeclass CoreWebView2LaunchingRegisteredProtocolEventArgs
221+
{
222+
// CoreWebView2LaunchingRegisteredProtocolEventArgs members
223+
String Uri { get; };
224+
Boolean Cancel { get; set; };
225+
Boolean Handled {get; set; };
226+
Boolean RevokeProtocolPermissionsPerOrigin {get; set; };
227+
}
228+
229+
runtimeclass CoreWebView2
230+
{
231+
// CoreWebView2
232+
event Windows.Foundation.TypedEventHandler<CoreWebView2, CoreWebView2LaunchingRegisteredProtocolEventArgs> LaunchingRegisteredProtocolEventArgs;
233+
}
234+
235+
runtimeclass CoreWebView2Frame
236+
{
237+
//CoreWebView2Frame
238+
event Windows.Foundation.TypedEventHandler<CoreWebView2Frame, CoreWebView2LaunchingRegisteredProtocolEventArgs> LaunchingRegisteredProtocolEventArgs;
239+
}
240+
}
241+
```

0 commit comments

Comments
 (0)