Bug 1595601: Add documentation for the external handler service. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D52578

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dave Townsend 2019-11-12 19:45:26 +00:00
parent 1945617175
commit 9c2cda9a81
6 changed files with 137 additions and 0 deletions

View File

@ -12,6 +12,7 @@ categories:
- modules/libpref
- remote
- services/common/services
- uriloader
build_doc:
- mach
- tools/try

10
uriloader/docs/index.rst Normal file
View File

@ -0,0 +1,10 @@
File Handling
=============
This covers how files requested for display are loaded.
.. toctree::
:maxdepth: 2
uriloader
exthandler/docs/index

View File

@ -0,0 +1,46 @@
.. _uri_loader_service:
URI Loader Service
==================
As its name might suggest the URI loader service is responsible for loading URIs
but it is also responsible for deciding how to handle that content, whether to
display it as part of a DOM window or hand it off to something else.
It is generally used when loading content for display to the user, normally from
``nsDocShell`` for display as a webpage or ``nsObjectLoadingContent`` for display inside
a webpage's ``<object>`` tag. The normal entrypoint is throught ``nsIURILoader::OpenURI``.
The URI loader starts the load and registers an ``nsDocumentOpenInfo`` as a stream
listener for the content. Once headers have been received `DispatchContent <https://searchfox.org/mozilla-central/search?q=nsDocumentOpenInfo%3A%3ADispatchContent&path=>`_
then decides what to do with the content as it may need to be handled by something
other than the caller. It uses a few criteria to decide this including:
* Content-Type header.
* Content-Disposition header.
* Load flags.
Part of this handling may include running the content through a registered stream
converter to convert the content type from one to another. This is done through
the `stream converter service <https://searchfox.org/mozilla-central/source/netwerk/streamconv>`_.
When this happens a new ``nsDocumentOpenInfo`` is created to handle the new content
in the same way as the current content.
The rough flow goes as follows (though note that this can vary depending on the
flags passed to the loader service):
1. The caller may provide an ``nsIURIContentListener`` which can offer to handle
the content type or a content type that we can convert the original type to).
If so the load is passed off to the listener.
2. Global instances of ``nsIURIContentListener`` can be registered with the URI
loader service so these are consulted in the same way.
3. Global instances of ``nsIURIContentListener`` can be registered in the category
manager so these are consulted in the same way.
4. Global instances of ``nsIContentHandler`` can be registered. If one agrees to
handle the content then the load is handed over to it.
5. We attempt to convert the content to a different type.
6. The load is handed over to the :ref:`External Helper App Service <external_helper_app_service>`.
For the most part the process ends at step 1 because nsDocShell passes a ``nsDSURIContentListener``
for the ``nsIURIContentListener`` consulted first and it accepts most of the
`web content types <https://searchfox.org/mozilla-central/search?q=CONTENTDLF_CATEGORIES&redirect=false>`_.

View File

@ -0,0 +1,76 @@
.. _external_helper_app_service:
External Helper App Service
===========================
The external helper app service is responsible for deciding how to handle an
attempt to load come content that cannot be loaded by the browser itself.
Part of this involves using the Handler Service which manages the users
preferences for what to do by default with different content.
When a Link is Clicked
----------------------
When a link in a page is clicked (or a form submitted) ``nsDocShell`` tests
whether the target protocol can be loaded by the browser itself, this is based
on the preferences under ``network.protocol-handler``. When the browser cannot
load the protocol it calls into ``nsExternalHelperAppService::LoadURI``.
Some validation checks are performed but ultimateley we look for a registered
protocol handler. First the OS is queried for an app registration for the
protocol and then the handler server is asked to fill in any user settings from
the internal database. If there were no settings from the handler service then
some defaults are applied in ``nsExternalHelperAppService::SetProtocolHandlerDefaults``.
If there is a default handler app chosen and the settings say to use it without
asking then that happens. If not a dialog s shown asking the user what they
want to do.
During a Load
-------------
When content is already being loaded the :ref:`URI Loader Service <uri_loader_service>`
determines whether the browser can handle the content or not. If not it calls
into the external helper app server through ``nsExternalHelperAppService::DoContent``.
The content type of the loading content is retrieved from the channel. A file
extension is also generated using the Content-Disposition header or if the load
is not a HTTP POST request the file extension is generated from the requested URL.
We then query the MIME Service for an nsIMIMEInfo to find information about
apps that can handle the content type or file extension based on OS and user
settings, :ref:`see below <mime_service>` for further details. The result is
used to create a ``nsExternalAppHandler`` which is then used as a stream listener
for the content.
The MIME info object contains settings that control whether to prompt the user
before doing anything and what the default action should be. If we need to ask
the user then a dialog is shown offering to let users cancel the load, save the
content to disk or send it to a registered application handler.
Assuming the load isn't canceled the content is streamed to disk using a background
file saver with a target ``nsITransfer``. The ``nsITransfer`` is responsible for
showing the download in the UI.
If the user opted to open the file with an application then once the transfer is
complete then ``nsIMIMEInfo::LaunchWithFile`` is used to
`launch the application <https://searchfox.org/mozilla-central/search?q=nsIMIMEInfo%3A%3ALaunchWithFile&path=>`_.
.. _mime_service:
MIME Service
------------
The MIME service is responsible for getting an ``nsIMIMEInfo`` object for a
content type or file extension:
1. Fills out an ``nsIMIMEInfo`` based on OS provided information. This is platform
specific but should try to find the default application registered to handle
the content.
2. Ask the handler service to fill out the ``nsIMIMEInfo`` with information held
in browser settings. This will not overwrite a any application found from
the OS.
3. If one has not been found already then try to find a type description from
a `lookup table <https://searchfox.org/mozilla-central/search?q=extraMimeEntries[]&path=>`_
or just by appending " File" to the file extension.

View File

@ -4,6 +4,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SPHINX_TREES['docs'] = 'docs'
TEST_DIRS += ['tests']
XPIDL_SOURCES += [

View File

@ -4,6 +4,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SPHINX_TREES['/uriloader'] = 'docs'
with Files('**'):
BUG_COMPONENT = ('Firefox', 'File Handling')