WebAPI/BrowserAPI: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(44 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
|-
|reload || P2 || {{bug|741717}} || NOT STARTED
|-
|-
|goBack || P2 || || NOT STARTED
|stop || P1 || {{bug|709759}} || {{implemented|}}
|-
|-
|goForward || P2 || || NOT STARTED
|reload || P2 || {{bug|741717}} || {{implemented|}}
|-
|-
|canGoBack || P2 || {{bug|741755}} || NOT STARTED
|go{Back,Forward}, canGo{Back,Forward} || P2 || {{bug|741755}} || {{implemented|}}
|-
|-
|canGoForward || P2 || {{bug|741755}} || NOT STARTED
|getScreenshot || P1 || {{bug|753595}} || {{implemented|}}
|-
|-
|getThumbnail || P1 || || NOT STARTED
|getContentDimensions || || {{bug|757859}} || {{implemented|}}
|-
|-
|getFavicon || P2 || || NOT STARTED
|setVisible || || {{bug|702880}}, {{bug|762939}} || {{implemented|}}
|}
|}


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


{| 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 || || IN PROGRESS
|Process separation || P1 || {{bug|714861}} || {{implemented|}}
|-
|Framebusting protection || P1 || {{bug|771273}} || {{implemented|}}
|-
|Touch pan & zoom || P1 || {{bug|745136}} || {{implemented|}}
|-
|<meta name="viewport"> tags || P2 || {{bug|746502}} || {{implemented|}}
|-
|-
|Framebusting protection || P1 || || IN PROGRESS (implemented but needs improvement)
|target=_blank/_top || P2 || {{bug|769254}} || {{implemented|}}
|-
|-
|Touch pan & zoom || P1 || || IN PROGRESS
|Permissions prompts || P1 || || {{implemented|}}
|-
|-
|Viewport || P2 || || NOT STARTED
|Clear private data || P1 || || {{implemented|}}
|-
|-
|Hyperlink targets || P2 || || NOT STARTED
|Turn cookies on/off || || || '''not started'''
|-
|-
|Context menu || P1 || || NOT STARTED
|<select> popups || P1 || {{bug|759511}} || {{implemented|}}
|}
|}


== Example implementation ==


== Attributes ==
This is a minimal implementation of a browser. When it's complete, it will
 
exercise the full surface area of the API.
'''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.
 
 
'''getThumbnail(callback)'''
 
: Generates a thumbnail of the content currently displayed in the browser element. The thumbnail 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.
 
'''getFavicon(callback)'''
 
: Gets the favicon associated with the content currently loaded inside the browser element. The favicon should be returned to the callback as a binary blob (or alternatively just a URL pointing to the file) in addition to the URL of the page it corresponds to. This could be used by a browser app to save icons for use in history, boomkarks or tab switching. We may not need this feature if we have an iconchange event.
 
== 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?
 
== 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.
 
'''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'''
''This code is completely untested at the moment.''


: Should support viewport meta tags to allow web sites to define how they want to be displayed on screens with different pixel densities.
=== HTML ===


'''Hyperlink targets'''
  &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;


: Open <a target="_top"> and <a target="_blank"> in a new window.
=== JS ===


'''Context menu'''
  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 providing a context menu ("open in new tab" etc.), e.g. with a long press.
== 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

Latest revision as of 23:49, 1 October 2014

Browser Element & API

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-api).

This is similar to the XUL browser element.

Roadmap

Summary

Note: Please find the current document on MDN https://developer.mozilla.org/en-US/docs/WebAPI/Browser
Attributes
Name Priority Bug Status
src P1 [IMPLEMENTED]
Methods
Name Priority Bug Status
go not started
stop P1 bug 709759 [IMPLEMENTED]
reload P2 bug 741717 [IMPLEMENTED]
go{Back,Forward}, canGo{Back,Forward} P2 bug 741755 [IMPLEMENTED]
getScreenshot P1 bug 753595 [IMPLEMENTED]
getContentDimensions bug 757859 [IMPLEMENTED]
setVisible bug 702880, bug 762939 [IMPLEMENTED]
Events
Name Priority Bug Status
loadstart P1 [IMPLEMENTED]
loadend P1 [IMPLEMENTED]
loadprogress not started
locationchange P1 [IMPLEMENTED]
titlechange P1 [IMPLEMENTED]
iconchange P1 bug 719461 [IMPLEMENTED]
alert/prompt/confirm P1 bug 741587 [IMPLEMENTED]
open P1 bug 742944 [IMPLEMENTED]
close P1 bug 757182 [IMPLEMENTED]
securitychange P1 bug 763694 [IMPLEMENTED]
contextmenu P1 bug 756371 [IMPLEMENTED]
error bug 768842 [IMPLEMENTED]
error:fatal bug 766437 [IMPLEMENTED]
scroll P1 bug 770847 [IMPLEMENTED]
Other Related Features (not all necessarily part of Browser API)
Name Priority Bug Status
Process separation P1 bug 714861 [IMPLEMENTED]
Framebusting protection P1 bug 771273 [IMPLEMENTED]
Touch pan & zoom P1 bug 745136 [IMPLEMENTED]
<meta name="viewport"> tags P2 bug 746502 [IMPLEMENTED]
target=_blank/_top P2 bug 769254 [IMPLEMENTED]
Permissions prompts P1 [IMPLEMENTED]
Clear private data P1 [IMPLEMENTED]
Turn cookies on/off not started
<select> popups P1 bug 759511 [IMPLEMENTED]

Example implementation

This is a minimal implementation of a browser. When it's complete, it will exercise the full surface area of the API.

This code is completely untested at the moment.

HTML

 <div><span id='location-bar'></span> <button onclick='go_button_clicked()'>Go</button></div>
 <div id='load-status'></div>
 <div id='security-status'></div>
 <img id='favicon'>
 <div id='title'></div>
 <iframe mozbrowser id='browser'></iframe>

JS

 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

Draft Specification

Other browser vendors have implementations of a similar API (e.g. Chrome). An early draft proposal for a standardised <webview> element and associated API can be found here. Please provide feedback in the issue tracker here.