p2b: Using ag-data-grid directly from GitHub.
Changing from Serve() to ServeDispatcher() since we have suffixes!

Change-Id: I87d9d48300b1eb0e3c8013edf5cb450831a0611f
diff --git a/Makefile b/Makefile
index 3174b86..3c31a93 100644
--- a/Makefile
+++ b/Makefile
@@ -32,18 +32,13 @@
 	jspm install -y -link npm:vanadium
 
 # Install JSPM and Bower packages as listed in browser/package.json from JSPM and browser/bower.json from bower
-browser/third-party: browser/third-party/npm/vanadium@0.0.1 browser/third-party/ag-data-grid browser/package.json browser/bower.json node_modules
+browser/third-party: browser/third-party/npm/vanadium@0.0.1 browser/package.json browser/bower.json node_modules
 	cd browser && \
 	jspm install -y && \
 	bower prune && \
 	bower install
 	touch browser/third-party
 
-# TODO(aghassemi) Remove when data-grid is published on GitHub and just use bower
-# For now we just copy into third-party
-browser/third-party/ag-data-grid:
-	yes | cp -rf browser/libs/ui-components/data-grid browser/third-party/ag-data-grid
-
 browser/services/v.io/x/p2b/vdl/index.js:
 	v23 run vdl generate --lang=javascript --js-out-dir=browser/services v.io/x/p2b/vdl
 
diff --git a/browser/bower.json b/browser/bower.json
index 177d881..35746d0 100644
--- a/browser/bower.json
+++ b/browser/bower.json
@@ -2,9 +2,10 @@
   "name": "pipe-to-browser",
   "version": "0.0.1",
   "dependencies": {
-    "polymer": "Polymer/polymer#~0.5.4",
-    "core-elements": "Polymer/core-elements#~0.5.4",
-    "paper-elements": "Polymer/paper-elements#~0.5.4"
+    "polymer": "Polymer/polymer#~0.5",
+    "core-elements": "Polymer/core-elements#~0.5",
+    "paper-elements": "Polymer/paper-elements#~0.5",
+    "ag-data-grid": "aghassemi/ag-data-grid#0.0.1"
   },
   "resolutions": {
     "polymer": "^0.5",
diff --git a/browser/config.js b/browser/config.js
index 34f8b87..04f6a21 100644
--- a/browser/config.js
+++ b/browser/config.js
@@ -229,6 +229,11 @@
       "inherits": "npm:inherits@2.0.1",
       "systemjs-json": "github:systemjs/plugin-json@0.1.0"
     },
+    "npm:es6-promise@2.1.1": {
+      "assert": "github:jspm/nodelibs-assert@0.1.0",
+      "process": "github:jspm/nodelibs-process@0.1.1",
+      "util": "github:jspm/nodelibs-util@0.1.0"
+    },
     "npm:es6-shim@0.20.4": {
       "process": "github:jspm/nodelibs-process@0.1.1"
     },
@@ -398,7 +403,6 @@
     },
     "npm:vanadium@0.0.1": {
       "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "bluebird": "npm:bluebird@2.9.8",
       "buffer": "github:jspm/nodelibs-buffer@0.1.0",
       "child_process": "github:jspm/nodelibs-child_process@0.1.0",
       "console": "github:jspm/nodelibs-console@0.1.0",
@@ -407,6 +411,7 @@
       "dgram": "github:jspm/nodelibs-dgram@0.1.0",
       "dns": "github:jspm/nodelibs-dns@0.1.0",
       "domready": "npm:domready@1.0.7",
+      "es6-promise": "npm:es6-promise@2.1.1",
       "es6-shim": "npm:es6-shim@0.20.4",
       "eventemitter2": "npm:eventemitter2@0.4.14",
       "events": "github:jspm/nodelibs-events@0.1.0",
diff --git a/browser/libs/ui-components/data-grid/LICENSE b/browser/libs/ui-components/data-grid/LICENSE
deleted file mode 100644
index 945151c..0000000
--- a/browser/libs/ui-components/data-grid/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Ali Ghassemi
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/README.md b/browser/libs/ui-components/data-grid/README.md
deleted file mode 100644
index 9e468c5..0000000
--- a/browser/libs/ui-components/data-grid/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-#ag-data-grid
-**Experimental Work**
-ag-data-grid is an Web Component to display tabular data.
-It has built-in support for paging, search, filters, sortable columns and custom cell renderer.
-
-ag-data-grid is responsive and can automatically hide columns on smaller screens based
-on a few simple attributes defined by developer such as "importance" of a particular column.
-
-![demo of data grid in action](http://TODO)
-
-##Demo
-[Contacts List Grid Demo](aghassemi.github.io/webcomponents/ag-data-grid/demo.html)
-
-##Install
-```
-bower install aghassemi/ag-data-grid
-```
-##Usage
-
-Please see full API documentation on the [Component Page](aghassemi.github.io/webcomponents/ag-data-grid)
-###Basic
-```
-  <ag-data-grid summary="Displays each person's score"
-    pageSize=5
-    dataSource="{{dataSource}}">
-    <ag-data-grid-column label="Name">
-      <template>
-        {{item.name}}
-      </template>
-    </ag-data-grid-column>
-    <ag-data-grid-column label="Score">
-      <template>
-        {{item.score}}
-       </template>
-    </ag-data-grid-column>
-  </ag-data-grid>
-```
-DataSource attribute expects an object that has a ```fetch(search, sort, filters)``` method.
-Please see documentation on DataSource property for details.
-
-###Full Featured
-Please see ```demo.html``` for a full featured example.
-
-##License
-MIT
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/ag-data-grid.css b/browser/libs/ui-components/data-grid/ag-data-grid.css
deleted file mode 100644
index 995c8c2..0000000
--- a/browser/libs/ui-components/data-grid/ag-data-grid.css
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-table {
-  border-collapse: collapse;
-  table-layout: fixed;
-  width: 100%;
-  border-spacing: 0;
-  margin-top: 15px;
-}
-
-thead tr {
-  border-bottom: solid 1px rgba(0,0,0, .12);
-  padding-bottom: 0.75em;
-}
-
-thead tr th {
-  position: relative;
-  overflow: hidden;
-}
-
-thead tr th:last-child {
-  overflow: visible;
-}
-
-td {
-  overflow: hidden;
-  vertical-align: top;
-}
-
-table tbody tr:nth-child(2) td {
-  padding-top: 15px;
-}
-
-.more-icon {
-  fill: #0a7e07;
-  color: #0a7e07;
-}
-
-paper-action-dialog {
-  width: 80%;
-  max-width: 600px;
-}
-
-.more-dialog-content .heading {
-  font-size: 1.0em;
-  padding-top: 0.2em;
-  padding-bottom: 0.2em;
-  color: #4285f4;
-  border-bottom: 1px solid rgba(0,0,0,0.05);
-  font-weight: normal;
-  text-transform: uppercase;
-  margin: 0;
-}
-
-.more-dialog-content .details {
-  margin-bottom: 1em;
-}
-
-.search-fab {
-  position: absolute;
-  right: -5px;
-  top: 10px;
-  background-color: #03a9f4;
-}
-
-#searchTools {
-  box-shadow: rgba(0, 0, 0, 0.14902) 2px 2px 4px;
-  background-color: #f5f5f5;
-  padding: 1em;
-  padding-bottom: 0;
-}
-
-.result-count {
-  font-size: 0.8em;
-  color: #616161;
-  float: right;
-}
-
-.info-column {
-  text-align: center;
-}
-
-[moreInfoOnly] {
-  display: none;
-}
-
-.more-dialog-content [moreInfoOnly] {
-  display: initial;
-}
-
-.more-dialog-content [gridOnly] {
-  display:none;
-}
-
-.paginator {
-  display: inline-block;
-  border: solid 1px rgba(0, 0, 0, 0.05);
-  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15);
-  color: rgba(0, 0, 0, 0.54);
-  fill: rgba(0, 0, 0, 0.54);
-  margin: 1em;
-  font-size: 0.9em;
-}
-
-.paginator paper-icon-button {
-  vertical-align: middle;
-}
-
-.screen-reader {
-  position: absolute;
-  top: -1000px;
-  left: -1000px;
-  width: 0px !important;
-  height: 0px !important;
-}
diff --git a/browser/libs/ui-components/data-grid/ag-data-grid.html b/browser/libs/ui-components/data-grid/ag-data-grid.html
deleted file mode 100644
index e4dff5d..0000000
--- a/browser/libs/ui-components/data-grid/ag-data-grid.html
+++ /dev/null
@@ -1,468 +0,0 @@
-<!--
-ag-data-grid is an Web Component to display tabular data.
-It has built-in support for paging, search, filters, sortable columns and custom cell renderer.
-
-ag-data-grid is responsive and can automatically hide columns on smaller screens based
-on a few simple attributes defined by developer such as "importance" of a particular column.
-
-Simple usage:
-  ```
-  <ag-data-grid summary="Displays each person's score"
-    pageSize=5
-    dataSource="{{dataSource}}">
-    <ag-data-grid-column label="Name">
-      <template>
-        {{item.name}}
-      </template>
-    </ag-data-grid-column>
-    <ag-data-grid-column label="Score">
-      <template>
-        {{item.score}}
-       </template>
-    </ag-data-grid-column>
-  </ag-data-grid>
-  ```
-
-DataSource attribute expects an object that has a fetch(search, sort, filters) method.
-Please see documentation on DataSource property for details.
-
-Please see the ```demo.html``` for a full featured example.
-
-@element ag-data-grid
-@homepage https://github.com/aghassemi/ag-data-grid
-@status unstable
--->
-<link rel="import" href="../polymer/polymer.html">
-<link rel="import" href="../paper-icon-button/paper-icon-button.html">
-<link rel="import" href="../paper-dialog/paper-dialog.html">
-<link rel="import" href="../paper-dialog/paper-dialog-transition.html">
-<link rel="import" href="../paper-dialog/paper-action-dialog.html">
-<link rel="import" href="../paper-fab/paper-fab.html">
-<link rel="import" href="../core-collapse/core-collapse.html">
-
-<link rel="import" href="column/ag-data-grid-column.html">
-<link rel="import" href="filter/select/item/ag-data-grid-filter-select-item.html">
-<link rel="import" href="filter/select/ag-data-grid-filter-select.html">
-<link rel="import" href="filter/toggle/ag-data-grid-filter-toggle.html">
-<link rel="import" href="search/ag-data-grid-search.html">
-<link rel="import" href="cell/renderer.html">
-<link rel="import" href="column/renderer.html">
-<link rel="import" href="row/renderer.html">
-
-<polymer-element name="ag-data-grid" attributes="summary dataSource defaultSortKey defaultSortAscending pageSize responsiveWidth">
-  <template>
-    <link rel="stylesheet" href="ag-data-grid.css">
-    <div id="templates"></div>
-    <core-collapse id="searchTools">
-      <div class="result-count">Showing {{ dataSourceResult.length }} items of {{totalNumItems}}</div>
-      <div>
-        <content select="[grid-search]"></content>
-      </div>
-      <div>
-        <content select="[grid-filter]"></content>
-      </div>
-    </core-collapse>
-    <table id="table" summary="{{ summary }}" cellpadding="0" cellpadding="0" border="0"  style="visibility:hidden" >
-      <thead>
-        <tr>
-          <th is="ag-data-grid-column-renderer" gridState="{{ gridState }}" data="{{ col.columnData }}" repeat="{{ col in columns }}" template></th>
-          <th style="width:40px">&nbsp;<span class="screen-reader">More info</span>
-            <paper-fab class="search-fab" focused icon="search" on-tap="{{ toggleSearchTools }}"></paper-fab>
-          </th>
-        </tr>
-      </thead>
-      <tbody>
-        <!-- quirk: Shadow Dom breaks parent-child relationships in HTML, this causes issues with
-         elements like table. Ideally we could have had <grid><grid-row><grid-cell> but we can't do
-         that yet since the tr and td rendered by <grid-row> <grid-cell> will be in shadow Dom and isolated.
-         Chromium bug: https://code.google.com/p/chromium/issues/detail?id=374315
-         W3C Spec bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=15616
-         -->
-        <tr is="ag-data-grid-row-renderer" repeat="{{ item in dataSourceResult }}" template>
-          <td is="ag-data-grid-cell-renderer" data="{{ col.columnData }}" repeat="{{ col in columns }}" style="text-align: {{ col.columnData.align }};" template>
-            <template ref="{{ col.cellTemplateId }}" bind></template>
-          </td>
-          <td class="info-column">
-            <paper-icon-button on-click="{{ showMoreInfo }}" class="more-icon" icon="more-vert" title="more info"></paper-icon-button
-            >
-          </td>
-        </tr>
-      </tbody>
-    </table>
-
-    <!-- Pagination -->
-    <template if="{{totalNumPages > 1}}">
-      <div class="paginator">
-        <paper-icon-button title="Previous page" icon="chevron-left"
-        class="{{ {invisible : pageNumber == 1} | tokenList }}" on-click="{{ previousPage }}"></paper-icon-button>
-        <span>Page {{ pageNumber }} of {{ totalNumPages }}</span>
-        <paper-icon-button title="Next page" icon="chevron-right"
-        class="{{ {invisible : onLastPage } | tokenList }}" on-click="{{ nextPage }}"></paper-icon-button>
-      </div>
-    </template>
-
-    <!-- Dialog that displays all columns and their values when more info icon activated -->
-    <paper-action-dialog backdrop layered="false" id="dialog" heading="Details" transition="paper-dialog-transition-bottom">
-      <template id="moreInfoTemplate" bind>
-        <div class="more-dialog-content">
-          <template repeat="{{ item in selectedItems }}">
-            <template repeat="{{ col in columns }}">
-              <h3 class="heading">{{ col.columnData.label }}</h3>
-              <div class="details"><template ref="{{ col.cellTemplateId }}" bind></template></div>
-            </template>
-          </template>
-        </div>
-      </template>
-      <paper-button dismissive>Close</paper-button>
-    </paper-action-dialog>
-
-  </template>
-  <script>
-    Polymer('ag-data-grid', {
-      /**
-       * DataSource is an object that has a fetch(search, sort, filters) method where
-       * search{key<string>} is current search keyword
-       * sort{key<string>, ascending<bool>} current sort key and direction
-       * filter{map{key<string>, values<Array>}} Map of filter keys to currently selected filter values
-       * search, sort and filters are provided by the grid control whenever they are changed by the user.
-       * DataSource is called automatically by the grid when user interacts with the component
-       * Grid does some batching of user actions and only calls fetch when needed in a requestAnimationFrame
-       * Keys provided for sort and filters correspond to keys set in the markup when constructing the grid.
-       * DataSource.fetch() is expected to return an array of filtered sorted results of the items.
-       *
-       * @attribute dataSource
-       * @type Object
-       * @default null
-       */
-      dataSource: null,
-
-      /**
-       * Summary for the grid.
-       * @attribute summary
-       * @type string
-       * @default ''
-       */
-      summary: '',
-
-      /**
-       * Initial sort key
-       * @attribute defaultSortKey
-       * @type string
-       * @default ''
-       */
-      defaultSortKey: '',
-
-      /**
-       * Initial sort direction
-       * @attribute defaultSortAscending
-       * @type boolean
-       * @default false
-       */
-      defaultSortAscending: false,
-
-      /**
-       * Number if items displayed in each page.
-       * @attribute pageSize
-       * @type integer
-       * @default 20
-       */
-      pageSize: 20,
-
-      /**
-       * The minimum width that all columns can fix nicely in it.
-       * When screen is resized to less than this, responsive behaviour kicks in
-       * and starts hiding columns.
-       * @attribute responsiveWidth
-       * @type integer
-       * @default 768
-       */
-      responsiveWidth: 768,
-
-      showMoreInfo: function(e) {
-        var item = e.target.templateInstance.model.item;
-        this.selectedItems = [item];
-        var me = this;
-        setTimeout(function() {
-          me.toggleDialog();
-        });
-      },
-
-      toggleDialog: function() {
-        this.$.dialog.toggle();
-      },
-
-      ready: function() {
-        // private property fields
-        this.columns = [];
-        this.pageNumber = 1;
-        //this.dataSource = null;
-        this.cachedDataSourceResult = [];
-        this.dataSourceResult = [];
-        this.gridState = {
-          sort: {
-            key: '',
-            ascending: false
-          },
-          search: {
-            keyword: ''
-          },
-          filters: {}
-        },
-
-        // set the default sort and direction on the state object
-        this.gridState.sort.key = this.defaultSortKey;
-        this.gridState.sort.ascending = this.defaultSortAscending;
-
-        this.initTemplates(); // loads cell templates
-        this.initGridStateDependents(); //  initialize filters and search
-        this.initGridStateObserver(); // observe changes to grid state by filters
-
-      },
-
-      /*
-       * Called by Polymer when DOM is read.
-       * @private
-       */
-      domReady: function() {
-        this.adjustFlexWidths();
-        this.$.table.style.visibility = 'visible';
-      },
-
-      /*
-       * Called by Polymer when dataSource attribute changes.
-       * @private
-       */
-      dataSourceChanged: function() {
-        this.refresh(true);
-      },
-
-      /*
-       * Sets up an object observer to get any mutations on the grid state object.
-       * Filters or sortable columns can change the state and we like to refresh
-       * when changes happens.
-       * @private
-       */
-      initGridStateObserver: function() {
-        var self = this;
-        for (key in this.gridState) {
-          var observer = new ObjectObserver(this.gridState[key])
-          observer.open(function() {
-            // refresh the grid on any mutations and go back to page one
-            self.refresh(true);
-          });
-        }
-      },
-
-      /*
-       * Copies the cell templates as defined by the user for each column into
-       * the grid so that we can reference them in a loop.
-       * quirk: Need to reference them by Id so a new Id is generated for each one
-       * Ids are scoped in the shadow DOM so no collisions.
-       * @private
-       */
-      initTemplates: function() {
-        var self = this;
-        var columnNodes = this.querySelectorAll('[grid-column]');
-        var totalFlex = 0;
-        for (var i = 0; i < columnNodes.length; i++) {
-          var col = columnNodes[i];
-          var cellTemplate = col.querySelector('template');
-          this.originalContext = cellTemplate.model;
-          var cellTemplateId = "userProvidedCellTemplate" + i;
-          cellTemplate.id = cellTemplateId;
-          this.$.templates.appendChild(cellTemplate);
-          totalFlex += col.flex;
-          col.origFlex = col.flex;
-          this.columns.push({
-            cellTemplateId: cellTemplateId,
-            columnData: col
-          });
-        }
-
-        // add up the total value of flex attribute on each column and add it to data
-        this.columns.forEach(function(c) {
-          c.columnData.totalFlex = totalFlex;
-        });
-
-        // readjust the widths on resize
-        var previousTableWidth = self.$.table.offsetWidth;
-        onResizeHandler = function() {
-          var newWidth = self.$.table.offsetWidth;
-          if (newWidth != previousTableWidth && newWidth > 0) {
-            self.adjustFlexWidths();
-          }
-          previousTableWidth = newWidth;
-        };
-
-        // quirks: since there is no good way to know if width changes, we pull.
-        // window.resize does not cover all resize cases
-        this.resizeInterval = setInterval(onResizeHandler, 50);
-      },
-
-      /*
-       * Called by Polymer when DOM is gone. We need to unbind custom event listeners here.
-       * @private
-       */
-      detached: function() {
-        clearInterval(this.resizeInterval);
-      },
-
-      /*
-       * Provide the grid state to any component that expects it so they can mutate
-       * without the grid needing to know about them at all.
-       * @private
-       */
-      initGridStateDependents: function() {
-        var gridStateDependents = this.querySelectorAll('[expects-grid-state]');
-        for (var i = 0; i < gridStateDependents.length; i++) {
-          gridStateDependents[i].gridState = this.gridState;
-        }
-      },
-
-      /*
-       * Refreshed the grid by fetching the data again and updating the UI in the next render tick
-       * @param {bool} goBackToPageOne Optional parameter indicating that grid should go back
-       * to page 1 after refresh. false by default
-       */
-      refresh: function(goBackToPageOne) {
-        var self = this;
-        requestAnimationFrame(function() {
-          if (goBackToPageOne) {
-            self.pageNumber = 1;
-          }
-          self.updateDataSource();
-        });
-      },
-
-      /*
-       * Performs responsive changes for the grid.
-       * Values of flex, minFlex and priority attributes on the grid column decides
-       * the responsive behavior.
-       * Grid assumes the original total number of columns can fit on a 768px width,
-       * if width of the grid container is less than that, then it starts to reduce
-       * flex values for each columns in reverse priority one by one until it reaches
-       * the minFlex value for all columns.
-       * If it still needs to reduce the width of the table at this point, it starts hiding
-       * columns in reverse priority order.
-       */
-      adjustFlexWidths: function() {
-        var minWidth = this.responsiveWidth;
-        var tableWidth = this.$.table.offsetWidth;
-
-        // reset to original flex values
-        for (var i = 0; i < this.columns.length; i++) {
-          var col = this.columns[i];
-          col.columnData.flex = col.columnData.origFlex;
-        }
-
-        if (tableWidth === 0 || tableWidth >= minWidth) {
-          return;
-        }
-
-        // total of all flex values from all columns
-        var totalFlex = this.columns.reduce( function(prev, col) {
-          return prev + col.columnData.flex;
-        }, 0);
-
-        // number of pixels per flex point
-        var pixelPerFlex = Math.floor(tableWidth / totalFlex);
-        // number of flex points we need to eliminate to same pixelPerFlex as the minWidth case
-        var numFlexToEliminate = Math.ceil((minWidth - tableWidth) / pixelPerFlex);
-
-        // sort from least important to most important
-        var sortedColumnsData = this.columns.map(function(col) {
-          return col.columnData
-        }).sort(function(a, b) {
-          return b.priority - a.priority;
-        });
-
-        // first try to reduce each flex value until we hit min-flex for each column
-        var numElimintedFlex = 0
-        var numIrreducableColumns = 0;
-        var numColumns = sortedColumnsData.length;
-        while (numElimintedFlex < numFlexToEliminate && numIrreducableColumns < numColumns) {
-          for (var i = 0; i < numColumns; i++) {
-            var col = sortedColumnsData[i];
-            if (col.flex > col.minFlex) {
-              col.flex--;
-              numElimintedFlex++;
-            } else {
-              numIrreducableColumns++;
-            }
-          }
-        }
-
-        // if still need to reduce, start eliminating whole columns based on priority
-        // never eliminate the top priority column, hence only iterate to numColumns - 1
-        if (numElimintedFlex < numFlexToEliminate) {
-          for (var i = 0; i < numColumns - 1 && numElimintedFlex < numFlexToEliminate; i++) {
-            var col = sortedColumnsData[i];
-            numElimintedFlex += col.flex;
-            col.flex = 0;
-          }
-        }
-
-        // update the new totalFlex for each column
-        this.columns.forEach(function(c) {
-          c.columnData.totalFlex = totalFlex - numFlexToEliminate;
-        });
-      },
-
-      /*
-       * dataSourceResult is what the UI binds to and integrate over.
-       * Only fetches data if scheduled to do so
-       * @private
-       */
-      updateDataSource: function() {
-        if (!this.dataSource) {
-          return;
-        }
-
-        // fetch the data
-        this.cachedDataSourceResult = this.dataSource.fetch(
-          this.gridState.search,
-          this.gridState.sort,
-          this.gridState.filters
-        );
-
-        // page the data
-        this.totalNumItems = this.cachedDataSourceResult.length;
-        // if there less data than current page number, go back to page 1
-        if (this.totalNumItems < (this.pageNumber - 1) * this.pageSize) {
-          this.pageNumber = 1;
-        }
-        this.totalNumPages = Math.ceil(this.totalNumItems / this.pageSize);
-        this.onLastPage = this.totalNumPages == this.pageNumber;
-
-        // skip and take
-        var startIndex = (this.pageNumber - 1) * this.pageSize;
-        var endIndex = startIndex + this.pageSize;
-        this.cachedDataSourceResult = this.cachedDataSourceResult.slice(startIndex, endIndex);
-
-        this.dataSourceResult = this.cachedDataSourceResult;
-      },
-
-      /*
-       * collapse/show search and filter container.
-       * @private
-       */
-      toggleSearchTools: function() {
-        this.$.searchTools.toggle();
-      },
-
-      nextPage: function() {
-        if (!this.onLastPage) {
-          this.pageNumber++;
-          this.refresh();
-        }
-      },
-
-      previousPage: function() {
-        if (this.pageNumber > 1) {
-          this.pageNumber--;
-          this.refresh();
-        }
-      }
-    });
-  </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/basic-demo.html b/browser/libs/ui-components/data-grid/basic-demo.html
deleted file mode 100644
index 292eb67..0000000
--- a/browser/libs/ui-components/data-grid/basic-demo.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <title></title>
-  <script src="../webcomponentsjs/webcomponents.js"></script>
-  <link rel="import" href="./basic.html">
-</head>
-<body>
-  <link rel="import" href="../polymer/polymer.html">
-  <link rel="import" href="ag-data-grid.html">
-
-  <polymer-element name="basic-demo">
-    <template>
-      <ag-data-grid summary="Displays each person's score"
-        pageSize=5
-        dataSource="{{dataSource}}">
-        <ag-data-grid-column label="Name">
-          <template>
-            {{item.name}}
-          </template>
-        </ag-data-grid-column>
-        <ag-data-grid-column label="Score">
-          <template>
-            {{item.score}}
-           </template>
-        </ag-data-grid-column>
-      </ag-data-grid>
-    </template>
-    <script type="text/javascript">
-      Polymer({
-        dataSource: {
-          fetch: function(search, sort, filters) {
-            return [
-              {name: 'John', score: 70},
-              {name: 'Jane', score: 54},
-              {name: 'Alex', score: 81},
-              {name: 'Hamed', score: 70},
-              {name: 'Milad', score: 88},
-              {name: 'Kaylee', score: 62},
-              {name: 'Maya', score: 92}
-            ];
-          }
-        }
-      });
-    </script>
-  </polymer-element>
-
-  <basic-demo></basic-demo>
-</body>
-</html>
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/bower.json b/browser/libs/ui-components/data-grid/bower.json
deleted file mode 100644
index 42bcfab..0000000
--- a/browser/libs/ui-components/data-grid/bower.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "name": "ag-data-grid",
-  "version": "0.0.1",
-  "description": "Responsive data grid that can host search, filters and supports sortable columns and custom cell renderer",
-  "license": "MIT",
-  "main": "ag-data-grid.html",
-  "private": true,
-  "keywords": [
-    "polymer",
-    "web-components",
-    "data-grid",
-    "data-table"
-  ],
-  "ignore": [
-    "bower_components"
-  ],
-  "dependencies": {
-    "polymer": "Polymer/polymer#master",
-    "core-elements": "Polymer/core-elements#master",
-    "paper-elements": "Polymer/paper-elements#master"
-  }
-}
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/cell/renderer.css b/browser/libs/ui-components/data-grid/cell/renderer.css
deleted file mode 100644
index 01c9b15..0000000
--- a/browser/libs/ui-components/data-grid/cell/renderer.css
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-.cell {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  padding: 0.75em 0.5em;
-}
-
-:host {
-  overflow: hidden;
-}
-
-.no-wrap {
-  white-space: nowrap;
-}
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/cell/renderer.html b/browser/libs/ui-components/data-grid/cell/renderer.html
deleted file mode 100644
index 0ed724a..0000000
--- a/browser/libs/ui-components/data-grid/cell/renderer.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<link rel="import" href="../../polymer/polymer.html">
-<polymer-element name="ag-data-grid-cell-renderer" extends="td" attributes="data">
-  <template>
-    <link rel="stylesheet" href="renderer.css">
-    <div class="cell {{ {'secondary-text': !data.primary, 'no-wrap': !data.wrap} | tokenList }}">
-      <content></content>
-    </div>
-  </template>
-  <script>
-   /*
-    * @private
-    */
-    Polymer('ag-data-grid-cell-renderer', {
-    });
-  </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/column/ag-data-grid-column.html b/browser/libs/ui-components/data-grid/column/ag-data-grid-column.html
deleted file mode 100644
index 547bf2c..0000000
--- a/browser/libs/ui-components/data-grid/column/ag-data-grid-column.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!--
-ag-data-grid-column
-
-Usage:
-ag-data-grid-column defines a column of data and provides the template to render
-the cells for that column.
-a variable named ```item``` is in scope for the cell renderer template that refers
-to the JavaScript object, as defined by the dataSource, being rendered currently.
-  ```
-    <ag-data-grid-column
-      label="Name"
-      key="name"
-      sortable
-      primary
-      wrap
-      minFlex="3"
-      flex="4"
-      priority="3"
-      align="center"/>
-
-      <template>
-         <div>{{ item.name }}</div>
-      </template>
-
-    </ag-data-grid-column>
-  ```
-@element ag-data-grid-column
--->
-<link rel="import" href="../../polymer/polymer.html">
-<polymer-element name="ag-data-grid-column" grid-column attributes="label sortable key primary wrap flex minFlex priority align">
-  <script>
-    Polymer('ag-data-grid-column', {
-      /**
-       * Label text for the column
-       * @attribute label
-       * @type string
-       * @default ''
-       */
-      label: '',
-
-      /**
-       * number specifying how flexible the width of the column is
-       * compared to other columns. For instance for a grid with three columns
-       * flex values of 1, 3, 1. means the middle column needs to be three times
-       * as wide as the other two.
-       * Flex value of 0 means the column should not be displayed.
-       * Flex values for all the columns can add up to any value.
-       * @attribute flex
-       * @type integer
-       * @default 1
-       */
-      flex: 1,
-
-      /**
-       * minimum Flex value that this column can be reduced to by the responsive data grid
-       * Defaults to 1 meaning column can be reduced to 1 flex as available space shrinks.
-       * @attribute minFlex
-       * @type integer
-       * @default 1
-       */
-      minFlex: 1,
-
-      /**
-       * specifies the importance of this column. Responsive grid uses this number
-       * to decide which columns to reduce/hide when available space shrinks.
-       * Lower number means more important.
-       * @attribute priority
-       * @type integer
-       * @default 1
-       */
-      priority: 1,
-
-      /**
-       * whether this column is sortable
-       * @attribute sortable
-       * @type boolean
-       * @default false
-       */
-      sortable: false,
-
-      /**
-       * whether this the primary column of the grid.
-       * Normally there is a single column that other columns are dependents on
-       * @attribute primary
-       * @type boolean
-       * @default false
-       */
-      primary: false,
-
-
-      /**
-       * whether text inside the cells of this columns are allowed to wrap.
-       * @attribute wrap
-       * @type boolean
-       * @default false
-       */
-      wrap: false,
-
-      /**
-       * Key that will be pass as sort.key to fetch() function of your data source.
-       * @attribute key
-       * @type string
-       * @default ''
-       */
-      key: '',
-
-      /**
-       * How the text context of the column is aligned horizontally.
-       * Default to left aligned, can be center, right
-       * @attribute align
-       * @type string
-       * @default 'left'
-       */
-      align: 'left'
-    });
-  </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/column/renderer.css b/browser/libs/ui-components/data-grid/column/renderer.css
deleted file mode 100644
index 955495d..0000000
--- a/browser/libs/ui-components/data-grid/column/renderer.css
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-:host {
-  color: rgba(0,0,0, 0.26);
-  font-weight: normal;
-  text-align: left;
-  white-space: nowrap;
-}
-
-paper-button {
-  width: 100%;
-  text-transform: none;
-}
-
-paper-button.left::shadow .button-content {
-  justify-content: left !important;
-}
-
-paper-button.center::shadow .button-content {
-  justify-content: center !important;
-}
-
-paper-button.right::shadow .button-content {
-  justify-content: right !important;
-}
-
-paper-button[disabled] {
-  background: inherit !important;
-  color: inherit !important;
-}
-
-paper-button[disabled] {
-  background: inherit !important;
-  color: inherit !important;
-}
-
-paper-button::shadow #ripple {
-  color: #0f9d58;
-}
diff --git a/browser/libs/ui-components/data-grid/column/renderer.html b/browser/libs/ui-components/data-grid/column/renderer.html
deleted file mode 100644
index cf1524e..0000000
--- a/browser/libs/ui-components/data-grid/column/renderer.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<link rel="import" href="../../polymer/polymer.html">
-<link rel="import" href="../../paper-button/paper-button.html">
-<polymer-element name="ag-data-grid-column-renderer" extends="th" attributes="data gridState" expects-grid-state>
-  <template>
-    <link rel="stylesheet" href="renderer.css">
-    <paper-button class="{{ data.align }}" disabled?="{{!data.sortable}}" on-tap="{{ updateGridState }}">
-      {{ formattedLabel }}
-    </paper-button>
-  </template>
-  <script>
-   /*
-    * @private
-    */
-    Polymer('ag-data-grid-column-renderer', {
-      'observe': {
-        'data.flex' : 'updateWidth',
-        'data.totalFlex' : 'updateWidth',
-        'gridState.sort.key' : 'formatLabel',
-        'gridState.sort.ascending' : 'formatLabel'
-      },
-
-      formattedLabel: '',
-
-      ready: function() {
-        this.formatLabel();
-      },
-
-      domReady: function() {
-        this.updateWidth();
-      },
-
-      updateWidth: function() {
-        // calculate the width value based on flex and total flex of the whole grid.
-        this.style.width = (this.data.flex / this.data.totalFlex) * 100 + '%';
-      },
-
-      updateGridState:function() {
-        if( !this.data.sortable ) {
-          return;
-        }
-        this.gridState.sort.ascending = !this.gridState.sort.ascending;
-        this.gridState.sort.key = this.data.key;
-      },
-
-      formatLabel: function() {
-        if (!this.data.sortable || this.gridState.sort.key != this.data.key) {
-          this.formattedLabel = this.data.label;
-          return;
-        }
-
-        if (this.gridState.sort.ascending) {
-          this.formattedLabel = this.data.label + ' \u21A5'; // up wedge unicode character
-        } else {
-          this.formattedLabel = this.data.label + ' \u21A7'; // down wedge unicode character
-        }
-      }
-    });
-  </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/demo.html b/browser/libs/ui-components/data-grid/demo.html
deleted file mode 100644
index 9c94baf..0000000
--- a/browser/libs/ui-components/data-grid/demo.html
+++ /dev/null
@@ -1,253 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <title></title>
-  <script src="../webcomponentsjs/webcomponents.js"></script>
-  <link rel="import" href="ag-data-grid.html">
-  <style>
-    body {
-      font-family: sans-serif;
-      font-size: 14pt;
-      color: rgba(0, 0, 0, 0.87);
-    }
-    ::shadow /deep/ .phoneNum, ::shadow /deep/ .email {
-      text-decoration: none;
-      font-size: 0.9em;
-    }
-    ::shadow /deep/ .phoneNum {
-      color: #ff4080;
-    }
-    ::shadow /deep/ .email {
-      color: #5C6BC0;
-    }
-    ::shadow /deep/ .lastName {
-      font-size: 1.2em;
-      text-transform: uppercase;
-      color: rgba(0, 0, 0, 0.54);
-    }
-    ::shadow /deep/ .online {
-      color: #4CAF50;
-    }
-    ::shadow /deep/ .away {
-      color: #FFEB3B;
-    }
-    ::shadow /deep/ .offline {
-      color: #BDBDBD;
-    }
-  </style>
-  </head>
-<body>
-  <ag-data-grid id="contactsGrid"
-    summary="Displays your contacts in a tabular format"
-    pageSize=10
-    responsiveWidth="1200"
-    defaultSortKey="lastName"
-    defaultSortAscending>
-
-    <!-- Search contacts-->
-    <ag-data-grid-search label="Search Contacts"></ag-data-grid-search>
-
-    <!-- Filter for circles -->
-    <ag-data-grid-filter-select multiple key="status" label="Show contacts that are">
-      <ag-data-grid-filter-select-item checked label="Online" value="online"></ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item checked label="Away" value="away"></ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item checked label="Offline" value="offline"></ag-data-grid-filter-select-item>
-    </ag-data-grid-filter-select>
-
-    <!-- Toggle to allow filtering by online mode-->
-    <ag-data-grid-filter-toggle key="withPhone" label="Only show contacts that have a phone number" ></ag-data-grid-filter-toggle>
-
-    <!-- Columns, sorting and cell templates -->
-    <ag-data-grid-column sortable label="First Name" key="firstName"
-      minFlex="3" flex="4" priority="3"/>
-      <template>{{ item.firstName }}</template>
-    </ag-data-grid-column>
-
-    <ag-data-grid-column sortable label="Last Name" key="lastName" minFlex="4" flex="5" priority="1"/>
-      <template>
-        <span class="lastName">
-          {{ item.lastName }}
-        </span>
-      </template>
-    </ag-data-grid-column>
-
-    <ag-data-grid-column label="Phone Number" key="phone"
-      minFlex= "3" flex="4" priority="2" align="center"/>
-      <template if="{{ item.phone !== ''}}">
-        <a class='phoneNum' href="tel://{{item.phone}}">{{ item.phone }}</a>
-      </template>
-    </ag-data-grid-column>
-
-    <ag-data-grid-column label="Email" key="email"
-      minFlex= "6" flex="6" priority="5" align="left"/>
-      <template if="{{ item.email !== ''}}">
-        <a class='email' href="mailto://{{item.email}}">{{ item.email }}</a>
-      </template>
-    </ag-data-grid-column>
-
-    <ag-data-grid-column sortable label="Status" key="status"
-      minFlex="1" flex="3" priority="4" align="center"/>
-      <template>
-        <template if="{{item.status === 'online'}}">
-          <core-icon gridOnly class="online" icon="radio-button-on" alt="{{ item.firstName }} {{ item.lastName }} is online" title="online"></core-icon>
-          <span moreInfoOnly> {{ item.status }} </span>
-        </template>
-        <template if="{{item.status === 'away'}}">
-          <core-icon gridOnly class="away" icon="schedule" alt="{{ item.firstName }} {{ item.lastName }} is away" title="away"></core-icon>
-          <span moreInfoOnly> {{ item.status }} </span>
-        </template>
-        <template if="{{item.status === 'offline'}}">
-          <core-icon gridOnly class="offline" icon="block" alt="{{ item.firstName }} {{ item.lastName }} is offline" title="offline"></core-icon>
-          <span moreInfoOnly> {{ item.status }} </span>
-        </template>
-      </template>
-    </ag-data-grid-column>
-  </ag-data-grid>
-
-  <script type="text/javascript">
-
-// Add the data source to the grid
-window.addEventListener('polymer-ready', function(e) {
-  var grid = document.getElementById('contactsGrid');
-  grid.dataSource = {
-    // This method is expected by the data-grid. It is responsible for
-    // searching, filtering and sorting the data when user takes an action
-    // such as changing the filters or searching.
-    // This is also called on the initial load to populate the grid.
-    fetch: function(search, sort, filters) {
-      return filterAndSortContacts(search, sort, filters);
-    }
-  };
-
-  var contacts = generateContacts(100);
-  function filterAndSortContacts(search, sort, filters) {
-    var filtered = contacts.filter(function(c) {
-      var isMatch = true;
-
-      // Search keyword
-      var keyword = search.keyword;
-      if (keyword) {
-        isMatch = contains(c.firstName, keyword) ||
-          contains(c.lastName, keyword) ||
-          contains(c.phone, keyword);
-      }
-
-      // Status filter
-      var statusFilterValues = filters['status']; // status is the "key" defined on the filter
-      if (statusFilterValues) {
-        isMatch = isMatch && statusFilterValues.indexOf(c.status) > -1;
-      }
-
-      // Only with phone number filter
-      var onlyShowWithPhoeNumber = filters['withPhone']; // withPhone is the "key" defined on the filter
-      if (onlyShowWithPhoeNumber) {
-        isMatch = isMatch && !!c.phone;
-      }
-
-      return isMatch;
-    });
-
-    // Sort
-    return filtered.sort(sorter);
-
-    function sorter(item1, item2) {
-      var key = sort.key;
-      var ascending = sort.ascending;
-      var first = item1[key];
-      var second = item2[key];
-      if (!ascending) {
-        first = item2[key];
-        second = item1[key];
-      }
-
-      var statusPriority = {
-        'online': 3,
-        'away': 2,
-        'offline': 1
-      };
-
-      if (key === 'status') {
-        first = statusPriority[first];
-        second = statusPriority[second];
-        return (first - second);
-      }
-      if (key === 'firstName' || key === 'lastName') {
-        return first.localeCompare(second);
-      }
-    }
-  }
-
-  // Helpers
-  function generateContacts(n) {
-    var firstNames = ['Isabella', 'Sophia', 'Emma', 'Olivia', 'Isabella', 'Mia', 'Ava', 'Lily', 'Zoe', 'Emily', 'Chloe', 'Layla', 'Madison', 'Madelyn', 'Abigail', 'Aubrey', 'Charlotte', 'Amelia', 'Ella', 'Kaylee', 'Avery', 'Aaliyah', 'Hailey', 'Hannah', 'Addison', 'Riley', 'Harper', 'Aria', 'Arianna', 'Mackenzie', 'Lila', 'Evelyn', 'Adalyn', 'Grace', 'Brooklyn', 'Ellie', 'Anna', 'Kaitlyn', 'Isabelle', 'Sophie', 'Scarlett', 'Natalie', 'Leah', 'Sarah', 'Nora', 'Mila', 'Elizabeth', 'Lillian', 'Kylie', 'Audrey', 'Lucy', 'Maya', 'Annabelle', 'Makayla', 'Gabriella']
-    var lastNames = ['McDonald', 'Howard-Kelly', 'Brown', 'Wilson', 'Rodríguez', 'Diaz', 'Jones', 'Anderson', 'Lee', 'Robinson', 'Cooper-Brown', 'Sanchez', 'Campbell', 'Collins-Edwards', 'Campbell-Diaz', 'Parker', 'Cruz', 'Torres-Bell', ];
-    var firstNameCursor = 0;
-    var lastNameCursor = 0;
-
-    var results = [];
-    for (var i = 0; i < n; i++) {
-      var fname = getFirstName();
-      var lname = getLastName();
-      results.push({
-        firstName: fname,
-        lastName: lname,
-        phone: createPhone(),
-        email: fname + '.' + lname + '@example.org',
-        status: getStatus()
-      })
-    }
-
-    return results;
-
-    function rand(min, max) {
-      return Math.floor(Math.random() * (max - min + 1) + min);
-    }
-
-    function getStatus() {
-      var tri = rand(0, 2);
-      if (tri === 0) {
-        return 'online';
-      }
-      if (tri === 1) {
-        return 'away';
-      }
-      if (tri === 2) {
-        return 'offline';
-      }
-    }
-
-    function createPhone() {
-      // not everyone has a phone number
-      if (rand(0, 1) == 1) {
-        return '';
-      }
-      return rand(100, 999) + '-' + rand(100, 999) + '-' + rand(1000, 9999);
-    }
-
-    function getFirstName() {
-      if (firstNameCursor === firstNames.length) {
-        firstNameCursor = 0;
-      }
-      var name = firstNames[firstNameCursor];
-      firstNameCursor++;
-      return name;
-    }
-
-    function getLastName() {
-      if (lastNameCursor === lastNames.length) {
-        lastNameCursor = 0;
-      }
-      var name = lastNames[lastNameCursor];
-      lastNameCursor++;
-      return name;
-    }
-  }
-});
-
-function contains(str, s) {
-  return str.toLowerCase().indexOf(s.toLowerCase()) > -1;
-}
-  </script>
-</body>
-</html>
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/filter/common.css b/browser/libs/ui-components/data-grid/filter/common.css
deleted file mode 100644
index 53802f5..0000000
--- a/browser/libs/ui-components/data-grid/filter/common.css
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-.filter-container {
-  margin-bottom: 1.5em;
-}
-
-.filter-container h3 {
-  margin: 0;
-  margin-bottom: -10px;
-}
-
-.filter-container h3 {
-  font-size: 1em;
-  color: #9e9e9e;
-  font-weight: normal;
-}
diff --git a/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.css b/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.css
deleted file mode 100644
index 7e298c3..0000000
--- a/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.css
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-paper-checkbox, paper-radio-button {
-  padding: 16px 16px 0px 12px !important;
-}
-
-paper-checkbox::shadow #ink[checked] {
-  color: #4285f4;
-}
-
-paper-checkbox::shadow #checkbox.checked {
-  border-color: #4285f4;
-}
-
-paper-radio-button::shadow #ink[checked] {
-  color: #e91e63;
-}
-
-paper-radio-button::shadow #onRadio {
-  background-color: #e91e63;
-}
diff --git a/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.html b/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.html
deleted file mode 100644
index bea4215..0000000
--- a/browser/libs/ui-components/data-grid/filter/select/ag-data-grid-filter-select.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<!--
-ag-data-grid-filter-select renders a select list filter.
-The value(s) of the filter is provided to the ```dataSource's fetch``` function
-as a string value or array of string values in case of multi-selection in the
-filters map. ```filters[key]: <string|string[]>```.
-Values come from value field of child ag-data-grid-filter-select-item elements.
-
-Usage:
-  ```
-    <ag-data-grid-filter-select
-        multiple
-        key="status"
-        label="Show contacts that are">
-
-      <ag-data-grid-filter-select-item
-        checked
-        label="Online"
-        value="online">
-      </ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item
-        checked
-        label="Away"
-        value="away">
-      </ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item
-        checked
-        label="Offline"
-        value="offline">
-      </ag-data-grid-filter-select-item>
-
-    </ag-data-grid-filter-select>
-  ```
-@element ag-data-grid-filter-select
--->
-<link rel="import" href="../../../polymer/polymer.html">
-<link rel="import" href="../../../paper-checkbox/paper-checkbox.html">
-<link rel="import" href="../../../paper-radio-button/paper-radio-button.html">
-<link rel="import" href="../../../paper-radio-group/paper-radio-group.html">
-<polymer-element name="ag-data-grid-filter-select" attributes="multiple key label" grid-filter expects-grid-state>
-  <template>
-    <link rel="stylesheet" href="ag-data-grid-filter-select.css">
-    <link rel="stylesheet" href="../common.css">
-    <content id="content" select="*"></content>
-    <div class="filter-container">
-      <h3>{{label}}</h3>
-      <template if="{{ multiple }}" bind>
-        <core-selector id="multiSelector" multi selectedAttribute="checked" valueattr="value" core-select="{{updateGridState}}" selected="{{ selected }}">
-          <template repeat="{{ item in items }}">
-            <paper-checkbox value="{{ item.value }}" on-change="{{ updateGridState }}" label="{{ item.label }}"></paper-checkbox>
-          </template>
-        </core-selector>
-      </template>
-
-      <template if="{{ !multiple }}" bind>
-        <paper-radio-group id="singleSelector" valueattr="value" selected="{{ selected }}">
-          <template repeat="{{ item in items }}">
-            <paper-radio-button value="{{ item.value }}" on-change="{{ updateGridState }}" label="{{ item.label }}"></paper-radio-button>
-          </template>
-        </paper-radio-group>
-      </template>
-    </div>
-  </template>
-  <script>
-    Polymer('ag-data-grid-filter-select', {
-     /**
-      * Whether multiple items can be selected
-      * @attribute multiple
-      * @type boolean
-      * @default false
-      */
-      multiple: false,
-
-      /**
-       * Key that will be added to filters map passed to the fetch() function of your data
-       * source. value would be a string value or array of string values in case of
-       * multi-selection in the filters map.
-       * @attribute key
-       * @type string
-       * @default ''
-       */
-      key: '',
-
-      ready: function() {
-        // find the selected items from the child nodes
-        this.items = Array.prototype.slice.call(this.$.content.getDistributedNodes());
-        for(var i=0; i < this.items.length; i++){
-          if(this.items[i].checked) {
-            if(this.multiple) {
-              this.selected = this.selected || [];
-              this.selected.push(this.items[i].value);
-            } else {
-              this.selected = this.items[i].value;
-            }
-          }
-        }
-      },
-
-      updateGridState: function() {
-        var me = this;
-        setTimeout(function() {
-          if (me.multiple ) {
-            // quirk: we need to copy the array so change is observed. .slice() does that
-            me.gridState.filters[me.key] = me.$.multiSelector.selected.slice();
-          } else {
-            me.gridState.filters[me.key] = me.$.singleSelector.selected.slice();
-          }
-        });
-      }
-
-    });
-    </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/filter/select/item/ag-data-grid-filter-select-item.html b/browser/libs/ui-components/data-grid/filter/select/item/ag-data-grid-filter-select-item.html
deleted file mode 100644
index 685359f..0000000
--- a/browser/libs/ui-components/data-grid/filter/select/item/ag-data-grid-filter-select-item.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
-ag-data-grid-filter-select-item renders an item inside the select list filter.
-
-Usage:
-  ```
-    <ag-data-grid-filter-select
-        multiple
-        key="status"
-        label="Show contacts that are">
-
-      <ag-data-grid-filter-select-item
-        checked
-        label="Online"
-        value="online">
-      </ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item
-        checked
-        label="Away"
-        value="away">
-      </ag-data-grid-filter-select-item>
-      <ag-data-grid-filter-select-item
-        checked
-        label="Offline"
-        value="offline">
-      </ag-data-grid-filter-select-item>
-
-    </ag-data-grid-filter-select>
-  ```
-@element ag-data-grid-filter-select-item
--->
-<link rel="import" href="../../../../polymer/polymer.html">
-<polymer-element name="ag-data-grid-filter-select-item" attributes="label checked value">
-  <script>
-    Polymer('ag-data-grid-filter-select-item', {
-      /**
-       * Label text for the item
-       * @attribute label
-       * @type string
-       * @default ''
-       */
-      label: '',
-
-      /**
-       * Whether item is checked or not
-       * @attribute checked
-       * @type boolean
-       * @default false
-       */
-      checked: false,
-
-      /**
-       * Value that will available as filters[key] in the fetch() function of your data source.
-       * Where key is the key of the select filter that contains this item
-       * @attribute value
-       * @type string
-       * @default ''
-       */
-      value: ''
-    });
-    </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.css b/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.css
deleted file mode 100644
index 593f05d..0000000
--- a/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-paper-toggle-button {
-  padding: 16px 16px 0px 12px !important;
-}
diff --git a/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.html b/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.html
deleted file mode 100644
index 6509f07..0000000
--- a/browser/libs/ui-components/data-grid/filter/toggle/ag-data-grid-filter-toggle.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!--
-ag-data-grid-filter-toggle renders a boolean filter.
-The value of the filter is provided to the ```dataSource's fetch``` function
-as a value in the filters map. ```filters[key]: <boolean>```
-
-Usage:
-  ```
-    <ag-data-grid-filter-toggle
-      key="withPhone"
-      label="Only show contacts that have a phone number">
-    </ag-data-grid-filter-toggle>
-  ```
-@element ag-data-grid-filter-toggle
--->
-<link rel="import" href="../../../polymer/polymer.html">
-<link rel="import" href="../../../paper-toggle-button/paper-toggle-button.html">
-<polymer-element name="ag-data-grid-filter-toggle" attributes="key checked label" grid-filter expects-grid-state>
-  <template>
-    <link rel="stylesheet" href="ag-data-grid-filter-toggle.css">
-    <link rel="stylesheet" href="../common.css">
-    <div class="filter-container">
-      <h3>{{label}}</h3>
-      <paper-toggle-button id="toggle" on-change="{{ updateGridState }}" checked?="{{ checked }}"></paper-toggle-button>
-    </div>
-  </template>
-  <script>
-    Polymer('ag-data-grid-filter-toggle', {
-      /**
-       * Label text for the toggle filter
-       * @attribute label
-       * @type string
-       * @default ''
-       */
-      label: '',
-
-      /**
-       * Whether toggle is checked or not
-       * @attribute checked
-       * @type boolean
-       * @default false
-       */
-      checked: false,
-
-      /**
-       * Key that will be added to filters map passed to the fetch() function of
-       * your data source with the value of the filter (boolean in this case)
-       * @attribute key
-       * @type string
-       * @default ''
-       */
-      key: '',
-
-      updateGridState: function() {
-        this.gridState.filters[this.key] = this.$.toggle.checked;
-      }
-    });
-    </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/index.html b/browser/libs/ui-components/data-grid/index.html
deleted file mode 100644
index e72029c..0000000
--- a/browser/libs/ui-components/data-grid/index.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-
-  <script src="../webcomponentsjs/webcomponents.js"></script>
-  <link rel="import" href="../core-component-page/core-component-page.html">
-
-</head>
-<body unresolved>
-
-  <core-component-page
-    sources='[
-    "ag-data-grid.html",
-    "column/ag-data-grid-column.html",
-    "filter/select/item/ag-data-grid-filter-select-item.html",
-    "filter/select/ag-data-grid-filter-select.html",
-    "filter/toggle/ag-data-grid-filter-toggle.html",
-    "search/ag-data-grid-search.html"
-    ]'>
-    </core-component-page>
-
-
-</body>
-</html>
\ No newline at end of file
diff --git a/browser/libs/ui-components/data-grid/row/renderer.css b/browser/libs/ui-components/data-grid/row/renderer.css
deleted file mode 100644
index f92b1fc..0000000
--- a/browser/libs/ui-components/data-grid/row/renderer.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
diff --git a/browser/libs/ui-components/data-grid/row/renderer.html b/browser/libs/ui-components/data-grid/row/renderer.html
deleted file mode 100644
index 891de41..0000000
--- a/browser/libs/ui-components/data-grid/row/renderer.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<link rel="import" href="../../polymer/polymer.html">
-<polymer-element name="ag-data-grid-row-renderer" extends="tr">
-  <template>
-    <link rel="stylesheet" href="renderer.css">
-    <content></content>
-  </template>
-  <script>
-   /*
-    * @private
-    */
-    Polymer('ag-data-grid-row-renderer', {
-    });
-  </script>
-</polymer-element>
diff --git a/browser/libs/ui-components/data-grid/search/ag-data-grid-search.css b/browser/libs/ui-components/data-grid/search/ag-data-grid-search.css
deleted file mode 100644
index c18bc27..0000000
--- a/browser/libs/ui-components/data-grid/search/ag-data-grid-search.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Copyright 2015 The Vanadium Authors. All rights reserved. */
-/* Use of this source code is governed by a BSD-style */
-/* license that can be found in the LICENSE file. */
-
-paper-input {
-  width: 50%;
-  color: #9e9e9e;
-}
-
-:host {
-  display: block;
-  margin-bottom: 0.75em
-}
diff --git a/browser/libs/ui-components/data-grid/search/ag-data-grid-search.html b/browser/libs/ui-components/data-grid/search/ag-data-grid-search.html
deleted file mode 100644
index 58267c2..0000000
--- a/browser/libs/ui-components/data-grid/search/ag-data-grid-search.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-ag-data-grid-search renders a search area for the grid.
-The value of the search is provided to the ```dataSource's fetch``` function
-as a ```search { keyword: <string> }``` object.
-
-Usage:
-  ```
-  <ag-data-grid-search label="Search Contacts"></ag-data-grid-search>
-  ```
-@element ag-data-grid-search
--->
-<link rel="import" href="../../polymer/polymer.html">
-<link rel="import" href="../../paper-input/paper-input.html">
-<polymer-element name="ag-data-grid-search" grid-search expects-grid-state attributes="label">
-  <template>
-    <link rel="stylesheet" href="ag-data-grid-search.css">
-    <paper-input committedValue="{{ value }}" id="search" label="{{ label }}"></paper-input>
-  </template>
-  <script>
-    /*
-     * Renders a search box inside the grid components
-     */
-    Polymer('ag-data-grid-search', {
-      /**
-       * Label text for search box.
-       * @attribute label
-       * @type string
-       */
-      label: '',
-      valueChanged: function() {
-        this.gridState.search.keyword = this.value;
-      }
-    });
-  </script>
-</polymer-element>
diff --git a/browser/services/pipe-to-browser-server.js b/browser/services/pipe-to-browser-server.js
index 51d1928..22c90c1 100644
--- a/browser/services/pipe-to-browser-server.js
+++ b/browser/services/pipe-to-browser-server.js
@@ -12,6 +12,7 @@
 import { ByteObjectStreamAdapter } from 'libs/utils/byte-object-stream-adapter'
 import { StreamByteCounter } from 'libs/utils/stream-byte-counter'
 import { StreamCopy } from 'libs/utils/stream-copy'
+import { get as getPipeViewer } from 'pipe-viewers/manager'
 import vanadium from 'vanadium'
 import vdl from 'services/v.io/x/p2b/vdl/index'
 
@@ -110,6 +111,22 @@
   }
 
   var p2b = new Service();
+  var dispatcher = function(suffix) {
+    // Ensure we can handle the suffix
+    return getPipeViewer(suffix).then(() => {
+      var defaultAuthorizer = null;
+      return {
+        service: p2b,
+        // TODO(aghassemi) For now we only allow p2b to talk to instances running
+        // under the default authorizer
+        authorizer: defaultAuthorizer
+      };
+    }).catch(() => {
+      return Promise.reject(
+        new Error(suffix + " plugin does not exist.")
+      );
+    });
+  }
 
   state.publishing = true;
 
@@ -120,12 +137,7 @@
     var nsPrefix = runtime.accountName.replace('dev.v.io/root/', '');
     var serviceName = vanadium.naming.join(nsPrefix, 'p2b', name);
 
-    // TODO(aghassemi) For now we only allow p2b to talk to instances running
-    // under the default authorizer
-    var defaultAuthorizer = null;
-    var options = {authorizer: defaultAuthorizer};
-
-    return server.serve(serviceName, p2b, options).then(() => {
+    return server.serveDispatcher(serviceName, dispatcher).then(() => {
       log.debug('published!');
 
       state.published = true;