WebAPI/BrowserAPI: Difference between revisions

no edit summary
No edit summary
No edit summary
 
(37 intermediate revisions by 5 users not shown)
Line 1: Line 1:
= Browser Element & API =
= Browser Element & API =


This is a proposal for Browser API and a new HTML element called "<browser>", which is similar to an iframe but allows the implementation of a fully featured web browser as a web app.
This is a proposal for a Browser API and a new HTML element called "<browser>" or "<webview>", which is similar to an iframe but allows the implementation of a fully featured web browser as a web app.


This feature is being tracked by the meta-bug {{bug|693515}} (alias browser-as-webapp).
This feature is being tracked by the meta-bug {{bug|693515}} (alias browser-api).


This is similar to the [https://developer.mozilla.org/en/XUL/browser XUL browser element].
This is similar to the [https://developer.mozilla.org/en/XUL/browser XUL browser element].
== Roadmap ==
* P1
** {{In progress|}} Nested OOP {{bug|nested-oop}}
** State/Session restore {{bug|1033999}}
** Navigation scope
*** User stories: {{bug|996039}}, {{bug|972320}}, {{bug|1023803}}
*** Reference: https://github.com/w3c/manifest/issues/114
** {{In progress|}} Hardware key events {{bug|989198}}
** Fine-grained visilibity API {{bug|1034001}} (e.g. <code>setVisible(bool)</code> -> <code>setVisible({state: bool, rendering: bool, normalpriority: bool })</code>)
* P2
** <iframe mozbrowser> to <webview> {{bug|738172}}
** Rewrite some browser API using C++
* P3
** Dialog API (http auth, alert, etc)
** OOM Priority API
* P4
** Clean up existing functions
** Password management
** Freeze process
* P5
** Metadata API
* Related
** {{In progress|}} {{Pl|WebAPI/WidgetAPI|WidgetAPI|}} embed-widgets permission and mozwidget attribute {{bug|1005818}}


== Summary ==
== Summary ==
New HTML tag name "<browser>" {{bug|738172}}


{| border="1"
{{Note|Please find the current document on MDN https://developer.mozilla.org/en-US/docs/WebAPI/Browser}}
 
{| class="wikitable"
|+Attributes
|+Attributes
|-
|-
! Name !! Priority !! Bug !! Status
! Name !! Priority !! Bug !! Status
|-
|-
|src || P1 || || IMPLEMENTED
|src || P1 || || {{implemented|}}
|}
|}


{| border="1"
{| class="wikitable"
|+ Methods
|+ Methods
|-
|-
! Name !! Priority !! Bug !! Status
! Name !! Priority !! Bug !! Status
|-
|-
|go || P2 || || NOT STARTED
|go || || || '''not started'''
|-
|-
|stop || P1 || {{bug|709759}} || NOT STARTED
|stop || P1 || {{bug|709759}} || {{implemented|}}
|-
|-
|reload || P2 || {{bug|741717}} || NOT STARTED
|reload || P2 || {{bug|741717}} || {{implemented|}}
|-
|-
|goBack || P2 || || NOT STARTED
|go{Back,Forward}, canGo{Back,Forward} || P2 || {{bug|741755}} || {{implemented|}}
|-
|-
|goForward || P2 || || NOT STARTED
|getScreenshot || P1 || {{bug|753595}} || {{implemented|}}
|-
|-
|canGoBack || P2 || {{bug|741755}} || NOT STARTED
|getContentDimensions || || {{bug|757859}} || {{implemented|}}
|-
|-
|canGoForward || P2 || {{bug|741755}} || NOT STARTED
|setVisible || || {{bug|702880}}, {{bug|762939}} || {{implemented|}}
|-
|getScreenshot || P1 || || IN PROGRESS
|-
|getHeight || || {{bug|757859}} || NOT STARTED
|-
|getWidth || || {{bug|757859}} || NOT STARTED
|}
|}


{| border="1"
{| class="wikitable"
|+Events
|+Events
|-
|-
! Name !! Priority !! Bug !!Status
! Name !! Priority !! Bug !!Status
|-
|-
|loadstart || P1 || || IMPLEMENTED
|loadstart || P1 || || {{implemented|}}
|-
|loadend || P1 || || {{implemented|}}
|-
|-
|loadend || P1 || || IMPLEMENTED
|loadprogress || || || '''not started'''
|-
|-
|loadprogress || P3 || || NOT STARTED
|locationchange || P1 || || {{implemented|}}
|-
|-
|locationchange || P1 || || IMPLEMENTED
|titlechange || P1 || || {{implemented|}}
|-
|-
|titlechange || P1 || || IMPLEMENTED
|iconchange || P1 || {{bug|719461}} || {{implemented|}}
|-
|-
|iconchange || P1 || {{bug|719461}} || IMPLEMENTED
|alert/prompt/confirm || P1 || {{bug|741587}} || {{implemented|}}
|-
|-
|alert || P1 || {{bug|741587}} || IN PROGRESS
|open || P1 || {{bug|742944}} || {{implemented|}}
|-
|-
|confirm || P1 || {{bug|741587}} || IN PROGRESS
|close || P1 || {{bug|757182}} || {{implemented|}}
|-
|-
|prompt || P1 || {{bug|741587}} || IN PROGRESS
|securitychange || P1 || {{bug|763694}} || {{implemented|}}
|-
|-
|open || P1 || {{bug|742944}} || IN PROGRESS
|contextmenu || P1 || {{bug|756371}} || {{implemented|}}
|-
|-
|close || P1 || {{bug|742944}} || IN PROGRESS
|error || || {{bug|768842}} || {{implemented|}}
|-
|-
|securitychange || P1 || || NOT STARTED
|error:fatal || || {{bug|766437}} || {{implemented|}}
|-
|-
|resize || || {{bug|757859}} || NOT STARTED
|scroll || P1 || {{bug|770847}} || {{implemented|}}
|}
|}


{| border="1"
{| class="wikitable"
|+Other Features
|+Other Related Features (not all necessarily part of Browser API)
|-
|-
! Name !! Priority !! Bug !! Status
! Name !! Priority !! Bug !! Status
|-
|-
|Process separation || P1 || {{bug|714861}} || IMPLEMENTED
|Process separation || P1 || {{bug|714861}} || {{implemented|}}
|-
|-
|Framebusting protection || P1 || || IN PROGRESS (implemented but needs improvement)
|Framebusting protection || P1 || {{bug|771273}} || {{implemented|}}
|-
|-
|Touch pan & zoom || P1 || || IN PROGRESS
|Touch pan & zoom || P1 || {{bug|745136}} || {{implemented|}}
|-
|-
|Viewport || P2 || || NOT STARTED
|<meta name="viewport"> tags || P2 || {{bug|746502}} || {{implemented|}}
|-
|-
|Hyperlink targets || P2 || || NOT STARTED
|target=_blank/_top || P2 || {{bug|769254}} || {{implemented|}}
|-
|-
|Context menu || P1 || || IN PROGRESS
|Permissions prompts || P1 || || {{implemented|}}
|-
|-
|Permissions prompts || P1 || || NOT STARTED
|Clear private data || P1 || || {{implemented|}}
|-
|-
|Clear private data || P1 || || NOT STARTED
|Turn cookies on/off || || || '''not started'''
|-
|-
|Turn cookies on/off || P1 || || NOT STARTED
|<select> popups || P1 || {{bug|759511}} || {{implemented|}}
|}
|}


== Attributes ==
== Example implementation ==
 
'''src'''
 
: The URI of the content to appear in the element.
 
== Methods ==
'''go(URI)'''
 
: Navigate to the URI provided.
 
'''stop()'''
 
: Stop the content from loading. Used by a stop button in a browser app.
 
'''reload()'''
 
: Reload the content in the browser. Used by a refresh button in a browser app. We may in future need other versions of this method (e.g. to bypass the browser cache and do a hard reload).
 
'''goBack()'''
 
: Navigates back one step in the session history. Could have success/failure reported in a callback but this isn't essential. Used by a back button in a browser app.
 
'''goForward()'''
 
: Navigates forward one step in the session history. Could have success/failure reported in a callback but this isn't essential. Used by a forward button in a browser app.
 
'''canGoBack(callback)'''
 
: Tells the app whether there is a history item in the session history to navigate back to. Should return a boolean true or false in a callback. Used by a browser app to decide whether to display a back button.
 
 
'''canGoForward(callback)'''
 
: Tells the app whether there is a history item in the session history to navigate forward to. Should return a boolean true or false in a callback. Used by a browser app to decide whether to display a forward button.
 
 
'''getScreenshot(callback)'''
 
: Generates a screenshot of the content currently displayed in the browser element. The screenshot should be returned to the callback as a binary blob, in addition to the URL it corresponds to. This could be used by a browser app to save visual bookmark or history information or as visual information to help in switching between tabs.
 
'''getWidth(callback)'''
 
: Gets the width of the current browser content, returned as an integer in the provided callback.
 
'''getHeight(callback)'''
 
: Gets the height of the current browser content, returned as an integer in the provided callback.
 
== Events ==
Events which are fired by a browser element.
 
'''loadstart'''
 
: Indicates that the element started loading content. Used by a browser app to show a loading indicator.
 
'''loadend'''
 
: Indicates that the element finished loading content. Used by a browser app to hide a loading indicator.
 
'''loadprogress'''
 
: Provides an estimate of the percentage of a page loaded. This is tricky but is better for browser apps to provide a determinate rather than indeterminate progress indicator.
 
'''locationchange'''
 
: Indicates that the URI changed, the URI is included as a string in the event payload.
 
'''titlechange'''
 
: Indicates that the title of the page changed, the title is included as a string in the event payload.
 
'''iconchange'''
 
: Indicates the favicon URL of the page changed, the URL of the favicon is included as a string in the event payload.
 
'''alert'''
 
: Indicates that the content requested an alert dialog to be displayed. Used by a browser app to display alerts.
 
'''confirm'''
 
: Indicates that the content requested a confirmation dialog to be displayed. Used by a browser app to display confirmation dialogs.
 
'''prompt'''
 
: Indicates that the content requested a prompt dialog to be displayed. Used by a browser app to display prompt dialogs.
 
'''open'''
 
: Indicates that the content requested a new window to be opened. Used by a browser app to open a new window/tab.
 
'''close'''
 
: Indicates that the content requested the current window to be closed. Used by a browser app to close a window/tab.
 
'''securitychange'''
 
: Indicates that the security status (secure or not) of a web page changed. Not sure how this should work, should we provide all the security details (e.g. SSL or not, certificate) in the event payload or add a getSecurityInfo() method for this?
 
'''resize'''
 
: Indicates that the browser was resized. Not sure what data should be included in the event payload.
 
== Other Features ==
'''Process separation'''
 
: Each browser element should be capable of running in its own system process.
 
'''Framebusting protection'''
 
: A browser element should ignore X-Frame-Options HTTP headers and act as a window.top boundary in order to prevent web sites from frame-busting. We already have a pref to disable X-Frame-Options system-wide but we need a way to just disable this for <browser> elements.
 
'''Touch pan & zoom'''
 
: Users of touch-based devices should be able to zoom with pinch to zoom, zoom in on an element by double-tapping it and pan around the page by dragging their finger across the screen.
 
'''Viewport'''
 
: Should support viewport meta tags to allow web sites to define how they want to be displayed on screens with different pixel densities.
 
'''Hyperlink targets'''
 
: Open <a target="_top"> and <a target="_blank"> in a new window.
 
'''Context menu'''


: Some method of providing a context menu ("open in new tab" etc.), e.g. with a long press.
This is a minimal implementation of a browser. When it's complete, it will
exercise the full surface area of the API.


'''Permissions prompts'''
''This code is completely untested at the moment.''


: Some method of showing/wrapping permissions prompts for e.g. geolocation and indexedDB
=== HTML ===


'''Clear private data'''
  &lt;div&gt;&lt;span id='location-bar'&gt;&lt;/span&gt; &lt;button onclick='go_button_clicked()'&gt;Go&lt;/button&gt;&lt;/div&gt;
  &lt;div id='load-status'&gt;&lt;/div&gt;
  &lt;div id='security-status'&gt;&lt;/div&gt;
  &lt;img id='favicon'&gt;
  &lt;div id='title'&gt;&lt;/div&gt;
  &lt;iframe mozbrowser id='browser'&gt;&lt;/iframe&gt;


: Some method of clearing private data, specifically for one app. Not sure if this should be part of the browser API, or another API. This should include the ability to clear cookies & cache for one particular app. Download history, saved form data, saved passwords and offline website data (indexedDB, localStorage, appcache etc.) may also need to be cleared in future.
=== JS ===


'''Turn cookies on/off'''
  function $(id) {
    return document.getElementById(id);
  }
 
  let iframe = $('browser');
 
  iframe.addEventListener('mozbrowserloadstart', function(e) {
    $('load-status').innerText = 'loading...';
  });
 
  iframe.addEventListener('mozbrowserloadend', function(e) {
    $('load-status').innerText = 'done loading';
  });
 
  iframe.addEventListener('mozbrowserlocationchange', function(e) {
    $('location-bar').innerText = e.detail;
  });
 
  iframe.addEventListener('mozbrowsertitlechange', function(e) {
    $('title').innerText = e.detail;
  });
 
  iframe.addEventListener('mozbrowsericonchange', function(e) {
    $('favicon').src = e.detail;
  });
 
  iframe.addEventListener('mozbrowsersecuritychange', function(e) {
    // 'secure', 'insecure', or 'broken'.  'broken' indicates mixed content.
    $('security-status').innerText = e.detail.state;
   
    // There's also e.detail.extendedValidation (boolean), but this will be
    // false until bug 764496 is fixed.
  });
 
  iframe.addEventListener('mozbrowsercontextmenu', function(e) {
    // TODO
  });
 
  iframe.addEventListener('mozbrowsererror', function(e) {
    switch (e.detail.type) {
    case 'other':
      // Something has gone wrong -- we're probably displaying a Gecko error
      // page, e.g. "no network connection" or "invalid SSL cert".  You
      // probably don't need to do anything here.
      break;
    case 'fatal':
      // The tab crashed.  Not implemented yet; see bug 766437.
      break;
    }
  });
 
  iframe.addEventListener('mozbrowserkeyevent', function(e) {
    // TODO.  You probably don't care about this event.
  });
 
  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
    // TODO
  });
 
  iframe.addEventListener('mozbrowseropenwindow', function(e) {
    // TODO
  });
 
  iframe.addEventListener('mozbrowserclose', function() {
    // This is really only meaningful for popup windows.
    document.body.removeChild(iframe);
  });
 
  function go_button_clicked() {
    iframe.src = $('location-bar').value;
  }
 
  // TODO:
  //  * getCanGoBack
  //  * getCanGoForward
  //  * goBack
  //  * goForward
  //  * setVisible
  //  * getScreenshot


: Some method of turning cookies on and off specifically for one app. Not sure if this should be part of the browser API or some other API.
== Draft Specification ==


== Other Comments ==
Other browser vendors have implementations of a similar API (e.g. [https://developer.chrome.com/apps/tags/webview Chrome]). An early draft proposal for a standardised <webview> element and associated API can be found [http://benfrancis.github.io/webview/ here]. Please provide feedback in the issue tracker [https://github.com/benfrancis/webview/issues here].


Other features that could be required in the future:
[[Category:Web APIs]]
* Find in page
* Download manager
* View source
Confirmed users
1,340

edits