Labs/F1/Modularity: Difference between revisions

 
(15 intermediate revisions by 2 users not shown)
Line 5: Line 5:
F1 will move towards using Browser Web Modules (WebMod). A WebMod is based on the service-discovery portion of Open Web Apps: a WebMod has a manifest which includes a list of supported services that the browser can hook into. For example, the Facebook WebMod might provide the '''link-send''', '''image-send''', and '''status-update''' services. F1 invokes the Facebook WebMod with action '''link-send''' when the user indicates, via F1, that he wishes to share a link with Facebook friends.
F1 will move towards using Browser Web Modules (WebMod). A WebMod is based on the service-discovery portion of Open Web Apps: a WebMod has a manifest which includes a list of supported services that the browser can hook into. For example, the Facebook WebMod might provide the '''link-send''', '''image-send''', and '''status-update''' services. F1 invokes the Facebook WebMod with action '''link-send''' when the user indicates, via F1, that he wishes to share a link with Facebook friends.


When F1 wishes to access sharing providers, it uses the WebMod framework to instantiate all relevant WebMods, each into its own iframe. F1 calls into the WebMod framework using a JavaScript API, and the WebMod framework communicates with each WebMod over '''postMessage'''. The key difference between a full-blown Open Web App and a WebMod is that the WebMod iframe remains hidden: a WebMod has no UI of its own. A WebMod is effectively a postMessage-based javascript API.
When F1 wishes to access sharing providers, it uses the WebMod framework to instantiate all relevant WebMods, each into its own iframe. F1 calls into the WebMod framework using a JavaScript API, and the WebMod framework communicates with each WebMod over '''postMessage'''. The key difference between a full-blown Open Web App and a WebMod is meant to enhance browser functionality, while an Open Web App exists to provide loosely-coupled functionality to web content. Thus, a WebMod is almost always headless, while an Open Web App almost always presents a UI. A WebMod is effectively a postMessage-based javascript API.


F1 will be a proving ground for WebMods, but also needs to be its own product. Thus, the complete WebMod architecture is described here, with generic pieces and F1-specifics carefully separated.
F1 will be a proving ground for WebMods, but also needs to be its own product. Thus, the complete WebMod architecture is described here, with generic pieces and F1-specifics carefully separated.
For those web products wanting to implement WebMods, we have written the [[Labs/F1/Modularity/WebMod HOWTO]].


== Architecture ==
== Architecture ==
Line 24: Line 26:


* creates an IFRAME and loads the prescribed WebMod URL into it.
* creates an IFRAME and loads the prescribed WebMod URL into it.
* when the WebMod's page is fully loaded and ready, it messages the WMF that it is ready.
* when the WebMod's page is fully loaded and ready, it indicates readiness by sending a message to the WMF.
* WMF and the WebMod engage in user authentication and potentially authorization (more below).
* WMF and the WebMod engage in user authentication and potentially authorization (see below).
* WMF sends additional messages to the WebMod to fulfill the actual feature. The pattern and structure of these messages depend on the specific feature being implemented. For F1, the specifics of the API are defined below.
* WMF sends additional messages to the WebMod to fulfill the actual feature. The pattern and structure of these messages depend on the specific feature being implemented. For F1, the specifics of the API are defined below.


=== User Interface ===
=== User Interface ===
Line 37: Line 38:
=== Authentication ===
=== Authentication ===


F1, or any other WMF feature mediator (e.g. image share), does not get involved in the user's authentication with the WebMod's backend server beyond coordinating the WebMod's UI needs. Specifically:
==== Login ====
 
F1, or any other WMF feature mediator (e.g. image share), does not get involved in the user's authentication with the WebMod's backend server beyond coordinating the WebMod's UI needs. While WMF will attempt to support all reasonable authentication options, it is expected that most services will choose to use whatever auth mechanism they already use for their site, eg, cookies.  For example, logging out of the site using the normal web UI will also log them out of the WebMod, while logging in via the WebMod mechanisms described here will also log them onto the site for the normal web interface.
 
Specifically:
 
* WMF messages the WebMod's IFRAME with a ''getLogin()'' call to obtain its login status, passing in a credentials blob it obtained earlier (or null if no such blob exists.)  The WebMod may return either:
** Information about the currently logged in user.  This information has 2 parts:
*** User information returned in Portable Contacts (PoCo) format.  This includes information such as their display name, username, preferred avatar, etc.
 
  NOTE: It isn't clear PoCo is the correct choice here.  At a minimum we
  probably need fields beyond what PoCo offers (eg, URL to the "my account"
  page, etc) so we at least need to spec them and also spec which of the
  PoCo fields we will actually look for.


* WMF asks the WebMod its login status.
*** An optional user-credentials blob which may be stored by the framework.  This blob will never be introspected by the framework (ie, it really is a blob) but will be passed back in subsequent ''getLogin'' calls.
* the WebMod may return either
** A "need-to-login" json object.  This object may contain multiple supported login methods, but in the first version the only supported method will be "dialog", where a service supplied URL is opened in a popup Window.
** a user-information blob, or
* When WMF receives a "need-to-login" message from the WebMod, it uses the "need-to-login" object to initiate the auth process (eg, it opens up a pop-up to the WebMod's preferred login URL)
** a "need-to-login" message.
* The WebMod is then responsible for authenticating the user however it sees fit, in its own HTML content window, likely by prompting for username and password. (That said, OpenID, OAuth, Verified Email, client-side certs, ... can be used at this point.)
* When WMF receives a "need-to-login" message from the WebMod, it opens up a pop-up to the WebMod's preferred login URL.
* Once a user has successfully logged in, the WebMod messages WMF back with an optional opaque ''credentials'' JavaScript object, which WMF stores securely.
* WMF then repeats this process - ie, messages the WebMod IFRAME with a ''getLogin()'' call including the ''credentials'' object it received and stored. The WebMod should, at this point, respond with the user information object (presumably with the same credentials blob it was passed)


=== F1-Specific Features ===
The use of the credentials blob is designed to allow WMA to securely store information on behalf of the WebMod if the WebMod desires.  However, some WebMods may not wish to take advantage of this (eg, they choose to use the existing cookies provided by the service, use localStorage directly, etc), in which case the WebMod is free to ignore this (ie, never return credentials and therefore always have null passed as the credentials object)


==== Service Discovery, Installation and Storage ====
  NOTES:
  It isn't clear the above actually deals with multiple users per service.  Eg,
  How is the UI built to switch users and what API calls does that UI make?


The F1 UI will need to make a distinction between "installed" apps and "discoverable" apps - currently this distinction doesn't really exist as the number of possible apps is assumed to be small.
  Is the added complication of the 'credentials' blob worth while?  Existing
  sites manage to handle auth without a special secure storage helper - why
  can't WebMods just use those existing practices (and update to better
  practices as they become known and rolled out for the site itself)?


The F1 server will be the primary service discovery mechanism.  An end-point will be exposed to list the URL of the manifest for all apps which support our serviceThe service will return both the "internal" apps supported directly by F1 and any other "external" services we know about.  A config file or similar will list those external services, so as (say) facebook supports this sharing directly, we make a simple change to that config file and the facebook hosted app is able to be discovered by F1.
  If the credentials blob is a true blob (ie, may contain binary data) then
  some consideration might need to be given to passing this aroundI suspect
  we want to define this as a simple string, and therefore force the WebMod
  to do its own encoding before passing it back to us.


F1 will allow the user to "install" these discovered applications. Installed apps will be kept in local-storage using the same basic model as OWA itself.  The routines used internally by F1 to enumerate the installed applications should be identical to the OWA counterparts. There will need to be some UI for removing an app, which needs to be different from any UI relating to "disconnect/logout from this app service."  F1 will probably relax the OWA restriction about "only one app per domain" simply so all "internal" F1 apps can be hosted together.
==== Logout ====


==== Other UI and Front-End Issues ====
The WebMod will also expose a ''logout'' method which will be passed the most recent 'credentials' object returned by the service (or null if no such object exists).  This should always succeed and no scope for a UI is provided (ie, the service can not request a logout page be shown).


The main F1 panel and related code will need to be revamped in a couple of ways: each installed app will get an invisible iframe and all UI config information will be obtained using postMessage with that iframeie, the F1 UI will not be able to keep a global list of "services" as it does now, but dynamically build that list by querying each of the apps.  Additionally, any service specific UI (both the service specific templates currently applied to F1 and the few hard-coding of service behaviour in the javascript) will need to be removed and implemented using data obtained via the postMessage channelThis means F1 probably doubles the number of iframes in use - one invisible one for each app (pointing at the app's domain), and one visible one for each app (holding dynamically built F1 content.)
After calling the logout method, WMF will delete the credentials blobThus, if the WebMod implemented authorization such that only the credentials blob is used, the logout method could be a no-opIf the WebMod implemented auth by way of cookies or by direct use of localStorage, it could simply delete the relevant cookie/storage.


Each existing F1 service will need to be broken into its own "app" and all send and auth related functionality etc implemented in each app rather than "globally".  This can probably be done simply by having each app load the same javascript module (ie, share the implementation even though it exists in different apps).  The F1 server end-points for sharing probably do not need to change.
==== Backchannel ====


The login process above indicates the WebMod's login page must message WMF on successful login.  The following considerations apply here:
* How is this defined and how is the WebMod expected to implement it?  Will a simple postMessage to window.opener be sufficient?  How would the receiving origin be specified?
* What if (eg) Twitter wants to reuse it's regular login page for this rather than a specific page for WebMods.  Would they find it reasonable to change their default page to perform this action?  If anyone felt there are security concerns in the default page doing it, wouldn't such concerns exist in the WebMod version of the page anyway?  Is there any reasonable way we could notice the login in the absence of such a notification?
  TODO: The backchannel stuff above needs thought, particularly in the added
  overheads it may force on such pages - eg, login pages may not want to
  include the jschannels library.


== F1 WebMod APIs ==
== F1 WebMod APIs ==
Line 69: Line 101:


== Implementation Plan ==
== Implementation Plan ==
How will F1 manage WebMods? Over time, this management will move from F1-specific to OWA-generic.


=== Version 1 --  Hard-Wired WebMods ===
=== Version 1 --  Hard-Wired WebMods ===


The primary goals of this stage are to:
In the first release, all F1 WebMods are hard-wired. Users are not able to add sharing providers, nor can they view a dashboard of WebMods. The modularity of the system is hidden from user view. F1 is self-contained, with no code dependence on Open Web Apps (the framework for WebMods). The list of available WebMods is update-able via F1 software updates.


* provide a long-term solution for the long-tail of F1 services in the shortest possible timeframe.
The implementation of each Webmod is ideally done by corresponding partners, each responsible for their WebMod. That said, if needed, we can implement the WebMods on our own and use OAuth to bridge the API calls. We may need chrome-level permissions to allow WebMods to make OAuth calls directly from Firefox.
* provide an auth mechanism which is both flexible and in the direct control of the service itself (eg, avoids the need for Mozilla infrastructure to store oauth tokens to any 3rd party).
* help refine and prove certain aspects of the OWA design, including the HOWA concept.


In this stage, F1 will use an "app-like" model but will not depend on the OWA extension being installed or even the spec being finalized. Thus there will be no standard way of installing, managing or discovering apps - F1 will take special, possibly temporary, action for these.
The focus of this version is the definition and refinement of the F1-specific link-sharing WebMod API, both in parameterizing the UI and in sending the shared link and associated message. We should ensure that our generalization matches existing major providers, and ideally a few non-major ones.


Each supported service will be implemented as a "headless open web app" - this will be true for "external" apps hosted directly by the vendors (eg, if we can convince google/twitter to host their app) and for "internal" apps hosted by F1 (ie, for all the existing services F1 supports where the vendor is not yet on-board).
=== Version 2 -- Installable WebMods ===


F1 will need to define the postMessage javascript API, implement it for the "internal" services and advocate for it to "external" services (hopefully overlapping, so the externals can offer feedback on the API).  F1 must be implemented using just this API - the F1 UI must not have any special UI behaviour hard-coded for facebook etc - everything must be able to be expressed via the API.
In the second version, modularity begins to be exposed to the user. Long-tail providers can advertise a manifest which triggers a Firefox "install App" dialog, which adds a new WebMod, which is then available to F1 if that WebMod advertises the appropriate link-sharing feature. Firefox also displays a dashboard of Apps, where the user can disable existing WebMods.


In addition to the constraints above, all work must be done with an eye towards the OWA-enabled world in Stage 2. Or to put it another way, if we can't see a clear path to Stage 2, we don't really need bother working within the constraints of HOWAs in the first place.
By this point, the manifest specification and the link-sharing API definition should be quite stable. F1 continues to be independent, with OWA functionality built-in.


=== Stage 2: Using Open Web Apps directly ===
=== Version 3 -- WebMods built on OWA Library ===


The primary goals here are:
Eventually, once Open Web Apps are ready for prime-time, the OWA functionality takes over the WebMod and App management, the dashboard, and the WebMod/App Framework that mediates communication with WebMods. F1 then focuses on purely link sharing (and potentially other types of sharing by then).


* to use the Open Web Apps specification for all "app" management - including discovery and installation of new services.
If OWA functionality progresses sufficiently quickly, we will attempt to merge Versions 2 and 3 so that users are not faced with separate dashboards of apps, one for F1 and one for OWA.
* To reuse as much of the OWA UI as possible (eg, the door-hanger) to both ensure a consistent app UX and to reduce duplicated code between F1 and OWA.
* Allow OWA to be the primary mechanism for new vendors supporting the service and the discovery of that new support.


This will depend on 2 things largely out of our control: a final spec and release of Open Web Apps, and significant uptake of this model by 3rd party external services.
=== Version 4 -- WebMods with UI for Trusted Providers ===


At the end of this stage, F1 will look as if it had been designed and implemented *after* the HOWA spec was finalized.  Eventually F1 will not host any "internal" services and the backend can be retired.
Some trusted providers will be provided with screen real estate in the F1 dashboard. Plans for this version need to be fleshed out a bit more, and additional API calls may be necessary to fully offload the message entry and customization to the new UI provided by the WebMod.
668

edits