Bug 1595601: Add documentation for the external handler service. r=Gijs
☠☠ backed out by 74b609eab5c2 ☠ ☠
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 12 Nov 2019 17:10:07 +0000
changeset 501600 d1ea0724b6caa33111426ec69a7e288cfde79dee
parent 501599 3b21c6bc1e1c58fefc34c71ad370fe903c42613f
child 501601 46948e618953a6cb0d7aa931ea94c4d64789dbdb
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1595601
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1595601: Add documentation for the external handler service. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D52578
tools/docs/config.yml
uriloader/docs/index.rst
uriloader/docs/uriloader.rst
uriloader/exthandler/docs/index.rst
uriloader/exthandler/moz.build
uriloader/moz.build
--- a/tools/docs/config.yml
+++ b/tools/docs/config.yml
@@ -7,16 +7,17 @@ categories:
         - browser
         - dom
         - gfx
         - toolkit
         - dom/bindings/webidl
         - modules/libpref
         - remote
         - services/common/services
+        - uriloader
     build_doc:
         - mach
         - tools/try
         - build/buildsystem
         - taskcluster
     testing_doc:
         - testing/marionette
         - testing/geckodriver
new file mode 100644
--- /dev/null
+++ b/uriloader/docs/index.rst
@@ -0,0 +1,10 @@
+File Handling
+=============
+
+This covers how files requested for display are loaded.
+
+.. toctree::
+   :maxdepth: 2
+
+   uriloader
+   exthandler/docs/index
new file mode 100644
--- /dev/null
+++ b/uriloader/docs/uriloader.rst
@@ -0,0 +1,45 @@
+.. _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 ``nsIURIContentListener``s can be registered with the URI loader service
+   so these are consulted in the same way.
+3. Global ``nsIURIContentListener`s can be registered in the category manager
+   so these are consulted in the same way.
+4. Global ``nsIContentHandler``s can be registered. If one agrees to hande 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>`_.
new file mode 100644
--- /dev/null
+++ b/uriloader/exthandler/docs/index.rst
@@ -0,0 +1,74 @@
+.. _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.
--- a/uriloader/exthandler/moz.build
+++ b/uriloader/exthandler/moz.build
@@ -1,14 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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 += [
     'nsCExternalHandlerService.idl',
     'nsIContentDispatchChooser.idl',
     'nsIExternalHelperAppService.idl',
     'nsIExternalProtocolService.idl',
     'nsIExternalURLHandlerService.idl',
--- a/uriloader/moz.build
+++ b/uriloader/moz.build
@@ -1,14 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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')
 
 DIRS += [
     'base',
     'exthandler',
     'prefetch',
 ]