Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding protocol handlers #972

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
999f9a9
adds protocol_handlers member
diekus Apr 15, 2021
da610bd
Update index.mhtml (adds protocol_handlers)
diekus Apr 26, 2021
8664c01
update index.htmlo
diekus Apr 26, 2021
228e2e6
Update index.html
diekus Apr 26, 2021
e1b678f
Update index.html
diekus May 7, 2021
81bdeda
Update index.html
diekus May 7, 2021
2c023ef
Update index.html
diekus May 7, 2021
2ace6ea
Merge branch 'gh-pages' into adding-protocol-handlers
aarongustafson May 13, 2021
61780a4
updates to protocol_handlers
diekus May 17, 2021
8b698d5
Merge branch 'adding-protocol-handlers' of https://github.com/w3c/man…
diekus May 17, 2021
9314353
Update index.html
diekus May 17, 2021
264ab23
Update index.html
diekus May 18, 2021
b011275
Update index.html
diekus May 18, 2021
1dcffe3
Update index.html
diekus May 18, 2021
0d4f273
Update index.html
diekus May 24, 2021
f0945d4
Update index.html
diekus May 24, 2021
003c2b1
Update index.html
diekus May 24, 2021
34d479b
Update index.html
diekus May 24, 2021
d440080
Update index.html
diekus May 24, 2021
94811fb
Update index.html
diekus May 24, 2021
f145884
Update index.html
diekus May 25, 2021
18c9046
Update index.html
diekus Jun 7, 2021
ea5cb7b
Merge branch 'gh-pages' into adding-protocol-handlers
diekus Jun 7, 2021
2573589
Update index.html
diekus Jun 15, 2021
3998cfa
Merge branch 'gh-pages' into adding-protocol-handlers
marcoscaceres Jun 23, 2021
8308ae2
Merge branch 'gh-pages' into adding-protocol-handlers
marcoscaceres Jun 30, 2021
2b4ba13
Run tidy
diekus Jul 5, 2021
c034185
run tidy
diekus Jul 5, 2021
40f8a13
Merge branch 'gh-pages' into adding-protocol-handlers
diekus Jul 12, 2021
73f3812
Update index.html
diekus Jul 13, 2021
ec620b6
Merge branch 'gh-pages' into adding-protocol-handlers
marcoscaceres Jul 20, 2021
6de904e
Fixes index.html
diekus Aug 2, 2021
ee2674a
Merge branch 'gh-pages' into adding-protocol-handlers
diekus Aug 2, 2021
b8c938a
Merge branch 'main' into adding-protocol-handlers
marcoscaceres Apr 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 184 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ <h2>
</li>
<li>[=manifest/prefer_related_applications=]
</li>
<li>[=manifest/protocol_handlers=]
</li>
<li>[=manifest/related_applications=]
</li>
<li>[=manifest/scope=]
Expand Down Expand Up @@ -1004,6 +1006,95 @@ <h3>
conventions or limitations of the host operating system.
</p>
</section>
<section>
<h3>
`protocol_handlers` member
</h3>
<p>
The [=manifest's=] <code><dfn data-dfn-for="manifest">protocol_handlers</dfn></code> member is an <a>array</a>
of <a>protocol handler description</a>s that allows a web application to
handle URL protocols.
</p>
<p class="example">
Protocol handlers could, for instance, be used for web app
communication where one app directly invokes another and passes data
via custom protocol links.
</p>
<p>
How protocol handlers are presented, and how many of them are shown
to the user, is at the discretion of the user agent and/or operating
system.
</p>
<p>To <dfn>process the `protocol_handlers` member</dfn>, given [=object=] |json:JSON|, |manifest:ordered map|, and |manifest URL:URL|:</p>
diekus marked this conversation as resolved.
Show resolved Hide resolved
<ol>
<li>Let <var>processedProtocolHandlers</var> be a new [=list=].
</li>
diekus marked this conversation as resolved.
Show resolved Hide resolved
<li>[=list/For each=] <var>protocol_handler</var> (<a>protocol handler description</a>):
<ol>
<li>If |protocol_handler|["protocol"] or
<var>protocol_handler</var>["url"] is undefined, [=iteration/continue=].
</li>
<li>Let (<dfn>normalizedProtocol</dfn>, <dfn>normalizedUrl</dfn>) be the result of running <a data-cite="HTML/system-state#normalize-protocol-handler-parameters">normalize protocol handler parameters</a> with <var>protocol_handler</var>["protocol"], <var>protocol_handler</var>["url"] using <var>manifest URL</var> as the base URL, and [=this=]'s relevant [=environment settings object=]. If the result is failure, [=iteration/continue=].</li>
diekus marked this conversation as resolved.
Show resolved Hide resolved
diekus marked this conversation as resolved.
Show resolved Hide resolved
</li>
<li>If [=normalizedUrl=] is not
[=manifest/within scope=] of <var>manifest URL</var>, [=iteration/continue=].
</li>
<li>If [=normalizedUrl=] already exists in <var>
processedProtocolHandlers</var>, [=iteration/continue=].
</li>
<li>
[=List/Append=] |protocol_handler| to
<var>processedProtocolHandlers</var>.
</li>
</ol>
</li>
<li>
[=list/For each=] |processedProtocolHandlers|, [=register a protocol handler=].
</li>
</ol>
<p>
A user agent SHOULD ask users for permission before registering a
<a>protocol handler description</a> <var>protocol_handler</var>s as the
default handler for a protocol with the host operating system. A user
agent MAY truncate the list of <a>protocol handler description</a>
<var>protocol_handlers</var> presented in order to remain consistent
with the conventions or limitations of the host operating system.
</p>
<aside class="example">
<p>
In the following example, the developer has included two
<a>protocol handler description</a> <var>protocol_handler</var>s. Assuming
the the manifest's URL is
<samp>https://example.com/manifest.webmanifest</samp>:
</p>
<ul>
<li>The first protocol handler would register to handle "web+music"
URLs (e.g.: web+music://#1234). When activated, the user agent
would instantiate a new <a>top-level browsing context</a> and
navigate to
<samp>https://example.com/play?songId=web+music://%231234</samp>.
</li>
<li>The second protocol handler would be ignored, as the protocol
provided does not start with "web+" and is not part of the
[=safelist=].
</li>
</ul>
<pre class="example json">
{
"protocol_handlers": [
{
"protocol": "web+music",
"url": "/play?songId=%s"
},
{
"protocol": "store",
"url": "/buy?songId=%s"
marcoscaceres marked this conversation as resolved.
Show resolved Hide resolved
}
]
}
</pre>
</aside>
</section>
<section>
<h2>
Manifest life-cycle
Expand Down Expand Up @@ -1099,8 +1190,11 @@ <h3>
|manifest|, |manifest URL|, and "icons".
</li>
<li>[=Process the `orientation` member=] passing |json|,
|manifest|.
</li>
|manifest|.
</li>
<li>[=Process the `protocol_handlers` member=] passing |json|,
|manifest|, and |manifest URL|.
</li>
<li>[=Process the `related_applications` member=] passing |json|
and |manifest|.
</li>
Expand Down Expand Up @@ -1759,6 +1853,94 @@ <h2>
</ol>
</section>
</section>
<section>
<h2>
ProtocolHandler items
</h2>
<p>
Each <dfn>protocol handler description</dfn> is an [=object=] that
represents a protocol that the web application wants to handle. It has
the following members:
</p>
<ul>
<li>[=`protocol`=]
</li>
<li>[=`url`=]
</li>
</ul>
<p>
A user agent SHOULD use these values to register the web application as
a handler with the operating system. When the user activates a protocol
handler URL, the user agent SHOULD run <a>handling a protocol
launch</a>.
</p>
<p class="note">
diekus marked this conversation as resolved.
Show resolved Hide resolved
[[HTML]]'s {{NavigatorContentUtils/registerProtocolHandler()}} allows web sites
to register themselves as possible handlers for particular protocols.
What constitutes valid <code>protocol</code> and <code>url</code>
values for <a>protocol handler description</a>s is defined in that API. Also
note that the [[HTML]] API uses [=url/scheme=]
where we use <code>protocol</code> but the same restrictions apply.
</p>
<section>
<h3>
`protocol` member
</h3>
<p>
The <dfn>protocol</dfn> member of a <a>protocol handler description</a> is a
<a>string</a> that represents the protocol to be handled, such as
`mailto` or `web+auth`.
</p>
<p>
The <a>protocol</a> member of a <a>protocol handler description</a> is
equivalent to {{NavigatorContentUtils/registerProtocolHandler()}}'s
|scheme| argument defined in [[HTML]].
</p>
</section>
<section>
<h3>
`url` member
</h3>
<p>
The <dfn>url</dfn> member of a <a>protocol handler description</a> is the
<a>URL</a> [=manifest/within scope=] of the application that opens
when the associated protocol is activated.
</p>
<p>
The <a>url</a> member of a <a>protocol handler description</a> is equivalent
to {{NavigatorContentUtils/registerProtocolHandler()}}'s
<code>url</code> argument defined in [[HTML]].
</p>
</section>
<section>
<h3>
<dfn>Handling a protocol launch</dfn>
</h3>
<p>
When a <a>protocol handler description</a> <var>protocol_handler</var> having
[=manifest=] <var>manifest</var> is invoked, it goes through the same
steps used to [=invoke a protocol handler=] defined in [=HTML=],
where the user agent SHOULD navigate to [=url=] and the appropriate
browsing context is set to a new top level browsing context.
</p>
</section>
<section>
<h3>
Privacy and Security considerations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this should go here. There's a main P&S section at the end of the document that collects all of these (this would be the only section to have it's own P&S subsection, other than Installable Web Apps, and that is probably a mistake too -- note that it is duplicated text from the end of the document).

However, I think P&S should only have non-normative discussion; a MUST requirement shouldn't be in it. So I would move this MUST requirement above to Handling a protocol launch. Then explain why it is so in the P&S section.

</h3>
<p>
Privacy concerns for custom scheme handling are detailed in the
Security and privacy section of
{{NavigatorContentUtils/registerProtocolHandler()}}.
</p>
<p>
The user agent MUST ask for permission when using a protocol
handler for the first time. This feature requires user interaction
and a script cannot communicate with another application on its
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems odd (not the asking for permission part - but this doesn't feel like it's wired up properly)...

Using HTML+JS as an example, can you show me what would this look like in practice? If it's to do with "permissions", then I suspect we need some kind of Permissions Policy or Permissions API thing here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hola Marcos, so the way this would work is that these registrations happen upon installation of the Web App. There is a prompt, and it is similar to the one that appears when registration is invoked from the .registerProtocolHandler(). In this case, where the registration happens from the manifest, the prompt appears the first time the protocol handler is invoked for a Web app. (It was a requirement from security/privacy folks).

image

Copy link
Member

@marcoscaceres marcoscaceres May 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, where the registration happens from the manifest, the prompt appears the first time the protocol handler is invoked for a Web app.

Sorry, I'm still having a hard time following. Can you walk me through the set up end-to-end?

How do I "invoke a protocol handler"? Do I click on a link on some website (appears to be the case from the HTML spec)?

I'm also confused about this in the HTML spec:

navigator.registerProtocolHandler('web+soup', 'soup?url=%s')

If I can register protocol handlers to do the same thing in HTML using JS, why do we need them in the manifest again? Does this just duplicate the functionality? Or does this work differently or provide some additional functionality that I'm not getting?

Sorry for the dumb questions. I'm just trying to understand.

Copy link
Member Author

@diekus diekus May 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hola again Marcos! Not sure which dumb questions you are referring to, they all seem important to be clear for me!

The difference between navigator.registerProtocolHandler() and having a protocol_handlers member in the manifest file is is mostly where/when is the scheme registration and invocation happening. Let me explain a bit further:

  • navigator.registerProtocolHandler(): once it is called it will immediately try to register the scheme and show the prompt displayed above. This is handy if I want to register a scheme anytime from HTML/JS. Handy AF.
  • protocol_handlers member in the manifest file: this will register a/several scheme(s) when a Web application is being installed. (register the installed Web app as a possible handler for that scheme). Here a noteworthy difference is that the prompt itself would appear once a user in a website on the browser invokes one of the registered schemes. For example, I installed the BatmanPWA and when I am browsing online I click on a 'web+batman://' link and then the prompt appears in the browser asking if the user wants to use that (registered) PWA. This happens the first time a user invokes a specific scheme. Very convenient indeed.

So in summary, it is a matter of where the registration happens, as it is more convenient for a user to decide whether they want to use an installed Web app when they run into a link that would require it instead of getting N prompts when trying to install a Web app (where N = number of valid items in the protocol_handlers member in the manifest).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the automatic unregistration that happens when a user uninstalls a webapp, which is nice :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protocol_handlers member in the manifest file: this will register a/several scheme(s) when a Web application is being installed.

Ok, but isn't this in violation of the web's security/permission model? I.e., we only really allow things to be request permission at use time, not en mass at install time.

Consider, we've previously rejected similar proposals whereby one would do:

  features: ["geolocation", "camera", "something else"]

This feels very similar.

Here a noteworthy difference is that the prompt itself would appear once a user in a website on the browser invokes one of the registered schemes. For example, I installed the BatmanPWA and when I am browsing online I click on a 'web+batman://' link and then the prompt appears in the browser asking if the user wants to use that (registered) PWA. This happens the first time a user invokes a specific scheme. Very convenient indeed.

This is concerning though. If I install BatmanPWA, it could do:

   protocol_handlers: [
       /// ...1000 protocols here... MUAHAHAH! 
       /// Appear to handle everything, and show up everywhere!
    ]

@dmurph:

There is also the automatic unregistration that happens when a user uninstalls a webapp, which is nice :)

Agree, that's nice. But it does presume some tight integration at the OS level with the browser. IIRC (and this was long ago), Firefox couldn't support such things because it could only put a shortcut icon on the home screen, but it had no way of getting notified if a user had deleted the shortcut.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hola Marcos,

protocol_handlers member in the manifest file: this will register a/several scheme(s) when a Web application is being installed.

Ok, but isn't this in violation of the web's security/permission model? I.e., we only really allow things to be request permission at use time, not en mass at install time.

It is as you are saying, the permission request happens when the user is using the protocol for the first time. We think the consent dialog on this first use is a good compromise between asking for permission for every protocol that an app wants to register and the security concerns of registering the protocols.

Consider, we've previously rejected similar proposals whereby one would do:

  features: ["geolocation", "camera", "something else"]

This feels very similar.

Here a noteworthy difference is that the prompt itself would appear once a user in a website on the browser invokes one of the registered schemes. For example, I installed the BatmanPWA and when I am browsing online I click on a 'web+batman://' link and then the prompt appears in the browser asking if the user wants to use that (registered) PWA. This happens the first time a user invokes a specific scheme. Very convenient indeed.

This is concerning though. If I install BatmanPWA, it could do:

   protocol_handlers: [
       /// ...1000 protocols here... MUAHAHAH! 
       /// Appear to handle everything, and show up everywhere!
    ]

The list of safe-listed protocols is rather small and they're very likely to have multiple handlers already defined among browser, native and installed web apps, which makes it unlikely that an app can take over everything. Would setting an arbitrary limit to the number of protocols that can be registered help?

@dmurph:

There is also the automatic unregistration that happens when a user uninstalls a webapp, which is nice :)

Agree, that's nice. But it does presume some tight integration at the OS level with the browser. IIRC (and this was long ago), Firefox couldn't support such things because it could only put a shortcut icon on the home screen, but it had no way of getting notified if a user had deleted the shortcut.

own.
</p>
</section>
</section>
<section>
<h2>
External application resource
Expand Down