Data Providers & Viewers

From FirebugWiki
Revision as of 11:36, 23 November 2013 by Sebastianz (Talk | contribs) (Corrected spelling and added links)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This page covers the concept of data providers and viewers that is used in Firebug to populate various UI widgets.


Data providers are objects that mediate data access through a unified interface. Providers are usually consumed by UI related objects such as Views (or Viewers) that use them to populate their content with data. The provider is only an adapter, it is neither storing nor caching data.

A similar and related pattern is called Document-View.


  • View: responsible for data rendering (display)
  • Document: represents the data source (e.g. a database or cache)

Drawback of this simple concept is that the View needs to know the interface of the Document, which makes it harder to switch to another data source with different API. An improvement of the previous concept is incorporating a Provider that is implemented for a specific Document (i.e. data source) and provides the data through a common interface that is known to all Viewers.


  • Provider: provides data through unified interface

This also means that any viewer can use the same provider to connect to a data source without any specific knowledge about it. This way the implementation of viewers can be always generic and is only dependent on the generic data provider interface.


Here is how a Provider interface looks like:

var Provider =
    hasChildren: function(object) { return this.getChildren().length > 0; },
    getChildren: function(object) { return []; },
    getLabel: function(object, col) { return ""; },
    getValue: function(object, col) { return null; },
  • hasChildren: used mostly by tree-style viewers that needs to know whether a twisty (+/- icons) should be displayed for specific item or not; It's implementation can be simple, as you can see in the code or optimized for various scenarios.
  • getChildren: returns a list of child objects for the given object
  • getLabel: returns a label for the given object; The label will be directly displayed within the UI (e.g. in a drop down list). The col argument can be used by UI widgets supporting tabular data display (several labels for given object/row).
  • getValue returns a value for the given object

Asynchronous Data Providers[edit]

One of the challenges for consuming data is support for asynchronous access. Firebug needs this, too, since data is often requested through RDP (remote debugging protocol) that uses TCP/IP and JSON based packets to deliver data from a remote server asynchronously.


  • The getChildren() method can return a Promise instead of a direct list of children. The promise is resolved asynchronously as soon as data is available.

The basic pattern is extended with support for Promise. It's up to the viewer whether it supports the promise (the asynchronous update callback) or not. The dashed arrow depicts the way how a promise object can be resolved. The promise object usually comes from the data source and is passed through the provider to the view. When it's being resolved the provider might be interested in the update callback, too. (use case?)

A working prototype (a web application) showing asynchronously populated tree is available:


A Decorator is supposed to modify the visual style of items in UI widgets. For instance, a decorator can append a prefix to an existing label or a badge to an existing icon. The styling should be always related to one item in particular widget. Decorators should help to avoid the cases where a new widget is derived from an existing widget just because of visual differences. This often leads to big hierarchies (or even parallel hierarchies) of objects with little differences.

var Decorator =
    getType: function(object) { return ""; },
  • getType should return a CSS class name that is applied on the visual element associated with the given object.

TODO: the exact interface of the Decorator object is yet to be specified.

The decorator pattern is not yet implemented in Firebug, but there is a comment inside the 'firebug/debugger/watch/watchPanel' module that suggests it.

Firebug Implementation[edit]

Let's see what objects are available within the Firebug framework.


  • DomTree is a widget implemented on top of Domplate (Firebug's UI template engine) that represents a tree-style viewer.
  • Provider represents a provider. Firebug has a hierarchy of providers (see below).
  • Context is an object that represents a document within the framework. It's created for every page for which Firebug is activated. It collects all data related to the current page. Firebug extensions can inject new custom data, too.



  • ClientProvider is basic provider knowing how to deal with Grip objects. A grip is a JSON value that refers to a specific JavaScript value in the debuggee (can be fetched asynchronously over TCP/IP from the server side).
  • DomProvider Used to provider data for the DOM panel (and DOM side panel). The provider knows how to get grips (JS objects) locally (breaking RDP for good reasons at the present).
  • WatchProvider is used in the Watch Side Panel. It appends logic that deals with stack frames, scope chains and user expressions.



  • DomTree is a generic UI widget displaying tree-like structures. It knows how to get data through the Provider interface and how to consume asynchronous data through Promise.
  • DomBaseTree appends specific features like long string expansion, asynchronous tree population (to avoid UI freeze in case of big data) and presentation state persistence (to restore tree state after refresh).
  • WatchTree appends visual support for user watch expressions. For instance, there is a new input field (new Domplate template) for creating a new watch expression.
  • DomPanelTree is used in the main DOM Panel and appends support for breakpoints. There is a breakpoint column that allows to create DOM breakpoints for existing DOM properties.