Merge "namespace_browser: Do not refresh the details sidebar if selection has not changed."
diff --git a/Makefile b/Makefile
index 3ecf090..42d5cee 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,8 @@
 GO_FILES = $(shell find go -name "*.go")
 VDL_FILES = $(shell find go -name "*.vdl")
 
+default: build
+
 # Creating the bundle JS file.
 public/bundle.js: $(BROWSERIFY_FILES) node_modules src/components/help/content/*.md
 	:;jshint src # lint all src JavaScript files.
@@ -93,7 +95,7 @@
 # Continuously watch for changes to .js, .html or .css files.
 # Rebundles the appropriate bundles when local files change.
 watch:
-	watch -n 1 make
+	watch -n 1 make build
 
 # Continuously reruns the tests as they change.
 watch-test: go/bin
diff --git a/src/components/browse/item-card-list/item-card/index.css b/src/components/browse/item-card-list/item-card/index.css
index 68f5629..ada4671 100644
--- a/src/components/browse/item-card-list/item-card/index.css
+++ b/src/components/browse/item-card-list/item-card/index.css
@@ -1,5 +1 @@
 @import "common-style/card.css";
-
-.item.inaccessible {
-  opacity: 0.5;
-}
diff --git a/src/components/browse/item-card-list/item-card/index.js b/src/components/browse/item-card-list/item-card/index.js
index 3b3c022..a824df7 100644
--- a/src/components/browse/item-card-list/item-card/index.js
+++ b/src/components/browse/item-card-list/item-card/index.js
@@ -37,16 +37,11 @@
   }
 
   // Prepare tooltip and service icon information for the item.
-  var isAccessible = true;
   var itemTooltip = item.objectName;
   var iconCssClass = '.service-type-icon';
   var iconAttributes = {};
 
   if (item.isServer) {
-    isAccessible = item.serverInfo.isAccessible;
-    if (!isAccessible) {
-      itemTooltip += ' - Service seems to be offline or inaccessible';
-    }
     iconAttributes.attributes = {
       title: item.serverInfo.typeInfo.typeName,
       icon: getServiceIcon(item.serverInfo.typeInfo.key)
@@ -63,8 +58,7 @@
 
   // Put the item card's pieces together.
   var itemClassNames = 'item.card' +
-    (selected ? '.selected' : '') +
-    (!isAccessible ? '.inaccessible' : '');
+    (selected ? '.selected' : '');
 
   var cardLabel = (showShortName ? item.mountedName : item.objectName) ||
     '<root>';
diff --git a/src/components/browse/item-details/display-item-details.js b/src/components/browse/item-details/display-item-details.js
index 1f975a5..ee79778 100644
--- a/src/components/browse/item-details/display-item-details.js
+++ b/src/components/browse/item-details/display-item-details.js
@@ -1,5 +1,3 @@
-var mercury = require('mercury');
-
 var methodNameToVarHashKey = require('./methodNameToVarHashKey');
 var methodStart = require('./method-start.js');
 var methodEnd = require('./method-end.js');
@@ -10,6 +8,7 @@
 var bookmarkService = require('../../../services/bookmarks/service');
 var smartService = require('../../../services/smart/service');
 
+
 var log = require('../../../lib/log')(
   'components:browse:item-details:display-item-details'
 );
@@ -33,10 +32,13 @@
 
   lastRequestedName = name;
 
+  state.put('error', null);
+  state.itemName.set(name);
+
   // Whether we have finished loading yet.
   var isLoaded = false;
   // How long to wait before showing loading if things have not loaded yet
-  var SHOW_LOADING_THRESHOLD = 500;
+  var SHOW_LOADING_THRESHOLD = 250;
   setTimeout(function maybeShowLoadingIndicator() {
     if (isLoaded || !isCurrentlySelected()) {
       return;
@@ -44,12 +46,16 @@
     state.showLoadingIndicator.set(true);
   }, SHOW_LOADING_THRESHOLD);
 
-  var resultsPromise = Promise.all([
+  var getItem = Promise.all([
+    //TODO(aghassemi) If isBookmarked fails, we are not showing anything
+    //ideally, we only remove the bookmark related UI and still show the rest.
     bookmarkService.isBookmarked(name),
     namespaceService.getNamespaceItem(name)
   ]);
 
-  resultsPromise.then(function(results) {
+  var isBookmarked;
+  var itemObs;
+  getItem.then(function loadSignature(results) {
     /*
      * Since async call, by the time we are here, a different name
      * might be selected.
@@ -59,6 +65,22 @@
       return;
     }
 
+    isBookmarked = results[0];
+    itemObs = results[1];
+    state.put('item', itemObs);
+    state.isBookmarked.set(isBookmarked);
+
+    if (itemObs().isServer) {
+      return namespaceService.getSignature(name);
+    } else {
+      return null;
+    }
+  }).then(function setStateAndFinishLoading(signatureResult) {
+
+    if (!isCurrentlySelected()) {
+      return;
+    }
+
     // Log the name to the smart service as a potential shortcut, since it was
     // successfully visited.
     smartService.update('learner-shortcut', {
@@ -67,45 +89,37 @@
       log.error('Error while updating shortcut learner', err);
     });
 
-    var isBookmarked = results[0];
-    var itemObs = results[1];
-
     // Indicate we finished loading
     setIsLoaded();
 
-    state.put('item', itemObs);
+    state.put('signature', signatureResult);
 
-    state.isBookmarked.set(isBookmarked);
+    if (!itemObs().isServer || !signatureResult) {
+      return;
+    }
 
-    mercury.watch(itemObs, function(item) {
-      if (!item.isServer) {
-        return;
-      }
+    // Go through each signature method, preparing the state needed for its
+    // form to be rendered and deciding if the method should be recommended.
+    signatureResult.forEach(function(methodData, methodName) {
+      var methodKey = methodNameToVarHashKey(methodName);
+      var form = methodForm();
+      state.methodForm.put(methodKey, form.state);
+      events.methodForm.put(methodKey, form.events);
 
-      // Go through each signature method, preparing the state needed for its
-      // form to be rendered and deciding if the method should be recommended.
-      var signatureResult = item.serverInfo.signature;
-      signatureResult.forEach(function(methodData, methodName) {
-        var methodKey = methodNameToVarHashKey(methodName);
-        var form = methodForm();
-        state.methodForm.put(methodKey, form.state);
-        events.methodForm.put(methodKey, form.events);
+      // Hook up the new form's method start, end, and toast events.
+      form.events.methodStart(
+        methodStart.bind(null, state, methodName)
+      );
+      form.events.methodEnd(
+        methodEnd.bind(null, state, methodName)
+      );
+      form.events.toast = events.toast;
 
-        // Hook up the new form's method start, end, and toast events.
-        form.events.methodStart(
-          methodStart.bind(null, state, methodName)
-        );
-        form.events.methodEnd(
-          methodEnd.bind(null, state, methodName)
-        );
-        form.events.toast = events.toast;
-
-        // Finally, allow the form to gather the info it needs to display.
-        form.events.displayMethodForm({
-          itemName: name,
-          signature: signatureResult,
-          methodName: methodName
-        });
+      // Finally, allow the form to gather the info it needs to display.
+      form.events.displayMethodForm({
+        itemName: name,
+        signature: signatureResult,
+        methodName: methodName
       });
     });
   }).catch(function(err) {
@@ -118,6 +132,7 @@
       type: 'error'
     });
     state.put('item', null);
+    state.put('error', err);
     setIsLoaded();
   });
 
@@ -135,4 +150,4 @@
   function isCurrentlySelected() {
     return (name === lastRequestedName);
   }
-}
\ No newline at end of file
+}
diff --git a/src/components/browse/item-details/index.js b/src/components/browse/item-details/index.js
index f65307e..8019460 100644
--- a/src/components/browse/item-details/index.js
+++ b/src/components/browse/item-details/index.js
@@ -1,12 +1,13 @@
 var mercury = require('mercury');
 var insertCss = require('insert-css');
 
-var methodNameToVarHashKey = require('./methodNameToVarHashKey.js');
+var methodNameToVarHashKey = require('./methodNameToVarHashKey');
 
 var displayItemDetails = require('./display-item-details');
 var bookmark = require('./bookmark');
 
-var methodForm = require('./method-form/index.js');
+var methodForm = require('./method-form/index');
+var ErrorBox = require('../../error/error-box/index');
 
 var css = require('./index.css');
 var h = mercury.h;
@@ -22,13 +23,38 @@
   var state = mercury.varhash({
 
     /*
-     * namespace item to display details for
+     * objectName for the item we are showing details of.
+     * We keep this in addition to item.objectName since item object may not be
+     * present (when in the middle of loading or when failed to load).
+     * Keeping itemName separate allows us to render a header with add/remove
+     * bookmark actions even when item is loading or has failed to load.
+     * @type {string}
+     */
+    itemName: mercury.value(null),
+
+    /*
+     * namespace item to display details for.
      * @see services/namespace/item
      * @type {namespaceitem}
      */
     item: mercury.value(null),
 
     /*
+     * Any fatal error while getting the details.
+     * Note: will be displayed to user.
+     * @type Error
+     */
+    error: mercury.value(null),
+
+    /*
+     * signature for the item.
+     * It's a map with extra information.
+     * @see services/namespace/signature-adapter
+     * @type {signature}
+     */
+    signature: mercury.value(null),
+
+    /*
      * Which tab to display; 0 is for service details
      * TODO(alexfandrianto): Once we have more info to display, add more tabs.
      * We are currently combining service details, methods, and outputs.
@@ -101,13 +127,16 @@
     var detailsContent = renderDetailsContent(state, events);
 
     var methodsContent;
-    if (state.item.isServer && state.item.serverInfo.isAccessible) {
+    if (state.item.isServer) {
       methodsContent = renderMethodsContent(state, events);
     }
-
     tabContent = [detailsContent, methodsContent];
+  } else if (state.error) {
+    var errorTitle = 'Unable to connect to ' + state.itemName;
+    tabContent = ErrorBox.render(errorTitle, state.error.toString());
   }
 
+  var headerContent = renderHeaderContent(state, events);
   return [h('paper-tabs.tabs', {
       attributes: {
         'selected': state.selectedTabIndex,
@@ -125,7 +154,7 @@
         'selected': state.selectedTabIndex
       }
     }, [
-      h('div.tab-content', tabContent),
+      h('div.tab-content', [headerContent, tabContent]),
     ])
   ];
 }
@@ -134,7 +163,6 @@
  * Renders an action bar on top of the details panel page.
  */
 function renderActions(state, events) {
-  var item = state.item;
 
   // Bookmark action
   var isBookmarked = state.isBookmarked;
@@ -153,7 +181,7 @@
       },
       'ev-click': mercury.event(events.bookmark, {
         bookmark: !isBookmarked,
-        name: item.objectName
+        name: state.itemName
       })
     })
   );
@@ -161,6 +189,24 @@
   return h('div.icon-group.item-actions', [bookmarkAction]);
 }
 
+
+/*
+ * Renders the header which includes actions and name field.
+ * Header is always displayed, even during loading time or when we fail
+ * to load details for an item.
+ * Note: we should be able to render header without loading signature any
+ * information about the item other than name and whether it is bookmarked.
+ */
+function renderHeaderContent(state, events) {
+  var actions = renderActions(state, events);
+  var headerItems = [
+    actions,
+    renderFieldItem('Name', (state.itemName || '<root>')),
+  ];
+
+  return headerItems;
+}
+
 /*
  * Renders details about the current service object.
  * Note: Currently renders in the same tab as renderMethodsContent.
@@ -176,18 +222,14 @@
     typeName = 'Intermediary Name';
   }
 
-  var actions = renderActions(state, events);
-
   var displayItems = [
-    actions,
-    renderFieldItem('Name', (item.objectName || '<root>')),
     renderFieldItem('Type', typeName, typeDescription)
   ];
 
-  if (item.isServer) {
+  if (item.isServer && state.signature) {
     // Display each service description and show it.
     var serviceDescs = [];
-    var descs = state.item.serverInfo.signature.pkgNameDescriptions;
+    var descs = state.signature.pkgNameDescriptions;
     Object.keys(descs).forEach(function(pkgName) {
       var desc = descs[pkgName];
 
@@ -238,8 +280,8 @@
  * making RPCs to the associated service.
  */
 function renderMethodSignatures(state, events) {
-  var sig = state.item.serverInfo.signature;
-  if (!sig) {
+  var sig = state.signature;
+  if (!sig || sig.size === 0) {
     return h('div', h('span', 'No method signature'));
   }
 
@@ -294,7 +336,7 @@
   var outputTable = h('table', {
     attributes: {
       'summary': 'Table showing the outputs of methods run on' +
-          'the service. The results are shown in reverse order.'
+        'the service. The results are shown in reverse order.'
     }
   }, outputRows);
   return h('div.method-output', outputTable);
@@ -327,4 +369,4 @@
     state.selectedTabIndex.set(data.index);
   });
   events.bookmark(bookmark.bind(null, state, events));
-}
+}
\ No newline at end of file
diff --git a/src/components/browse/item-details/method-end.js b/src/components/browse/item-details/method-end.js
index b9171c6..03e8112 100644
--- a/src/components/browse/item-details/method-end.js
+++ b/src/components/browse/item-details/method-end.js
@@ -22,7 +22,7 @@
     return;
   }
 
-  var sig = state.item().serverInfo.signature;
+  var sig = state.signature;
 
   // Otherwise, we'll have to learn from the results and draw them, if possible.
   var numInArgs = sig.get(method).inArgs.length;
@@ -76,7 +76,7 @@
  * Learn from the method inputs to be able to suggest them in the future.
  */
 function learnMethodInput(state, method, args) {
-  var sig = state.item().serverInfo.signature;
+  var sig = state.signature;
   args.forEach(function(value, i) {
     var argName = sig.get(method).inArgs[i].name;
     var input = {
@@ -97,7 +97,7 @@
  * Learn from this invocation to be able to suggest them in the future.
  */
 function learnMethodInvocation(state, method, args) {
-  var sig = state.item().serverInfo.signature;
+  var sig = state.signature;
   var input = {
     methodName: method,
     signature: sig,
diff --git a/src/components/browse/items/visualize-view/index.js b/src/components/browse/items/visualize-view/index.js
index 370ed28..ae097f6 100644
--- a/src/components/browse/items/visualize-view/index.js
+++ b/src/components/browse/items/visualize-view/index.js
@@ -25,8 +25,7 @@
 }
 
 // Maximum number of levels that are automatically shown
-// TODO(aghassemi) Switch to globbing <namespace>/... instead
-var MAX_AUTO_LOAD_DEPTH = 3;
+var MAX_AUTO_LOAD_DEPTH = 5;
 
 function TreeWidget(browseState, browseEvents) {
   this.browseState = browseState;
@@ -161,8 +160,7 @@
           label: item.mountedName,
           level: node.level + 1,
           shape: shape,
-          color: color,
-          isGlobbable: item.isGlobbable
+          color: color
         };
       });
       var newEdges = nodesToAdd.map(function(item) {
@@ -174,9 +172,6 @@
       });
       newNodes.forEach(function(item) {
         // recurse if within the MAX_AUTO_LOAD_DEPTH
-        if (!item.isGlobbable) {
-          return;
-        }
         if (item.level - self.rootNode.level < MAX_AUTO_LOAD_DEPTH) {
           self.loadSubNodes(item);
         } else {
diff --git a/src/components/common-style/defaults.css b/src/components/common-style/defaults.css
index f9195a9..74c71f6 100644
--- a/src/components/common-style/defaults.css
+++ b/src/components/common-style/defaults.css
@@ -91,4 +91,4 @@
  */
 .margin-left-xxsmall {
   margin-left: var(--size-space-xxsmall);
-}
\ No newline at end of file
+}
diff --git a/src/components/error/error-box/index.css b/src/components/error/error-box/index.css
new file mode 100644
index 0000000..9979e67
--- /dev/null
+++ b/src/components/error/error-box/index.css
@@ -0,0 +1,28 @@
+@import "common-style/sizes.css";
+@import "common-style/theme.css";
+
+.error-box-title {
+  display: flex;
+  width: 100%;
+  font-size: var(--size-font-xlarge);
+  color: var(--color-text-secondary);
+}
+
+.error-box-details {
+  width: 100%;
+  font-size: var(--size-font-xsmall);
+  color: var(--color-text-hint);
+  padding: var(--size-space-xxsmall);
+  padding-top: var(--size-space-large);
+}
+
+.error-box {
+  overflow: hidden;
+  word-break: break-word
+}
+
+.error-box-icon {
+  padding-right: var(--size-space-xxsmall);
+  margin-left: -var(--size-space-xxsmall);
+  color: var(--color-error);
+}
\ No newline at end of file
diff --git a/src/components/error/error-box/index.js b/src/components/error/error-box/index.js
new file mode 100644
index 0000000..67064e3
--- /dev/null
+++ b/src/components/error/error-box/index.js
@@ -0,0 +1,30 @@
+var mercury = require('mercury');
+var insertCss = require('insert-css');
+
+var css = require('./index.css');
+
+var h = mercury.h;
+
+module.exports.render = render;
+
+/*
+ * Renders an error in a box with details section
+ * @param message {string} errTitle short error title
+ * @param details {string} details Error details
+ */
+function render(errTitle, details) {
+  insertCss(css);
+
+  var titleView = h('div.error-box-title', [
+    h('core-icon.error-box-icon', {
+      attributes: {
+        icon: 'error'
+      }
+    }),
+    h('span', errTitle)
+  ]);
+
+  var detailsView = h('div.error-box-details', h('span', details));
+
+  return h('div.error-box', [titleView, detailsView]);
+}
\ No newline at end of file
diff --git a/src/components/error/index.css b/src/components/error/index.css
new file mode 100644
index 0000000..c5bfab0
--- /dev/null
+++ b/src/components/error/index.css
@@ -0,0 +1,5 @@
+@import "common-style/sizes.css";
+
+.error-page {
+  padding: var(--size-space-normal);
+}
\ No newline at end of file
diff --git a/src/components/error/index.js b/src/components/error/index.js
index b7544f9..03bcf99 100644
--- a/src/components/error/index.js
+++ b/src/components/error/index.js
@@ -1,4 +1,10 @@
 var mercury = require('mercury');
+var insertCss = require('insert-css');
+
+var ErrorBox = require('./error-box/index');
+
+var css = require('./index.css');
+
 var h = mercury.h;
 
 module.exports = create;
@@ -23,8 +29,8 @@
 }
 
 function render(state) {
-  // TODO(aghassemi)
-  return [
-    h('p', state.message)
-  ];
+  insertCss(css);
+
+  var errorTitle = 'Something went wrong :(';
+  return h('div.error-page', ErrorBox.render(errorTitle, state.message));
 }
\ No newline at end of file
diff --git a/src/components/main-content/index.js b/src/components/main-content/index.js
index acc5c03..f86411a 100644
--- a/src/components/main-content/index.js
+++ b/src/components/main-content/index.js
@@ -1,8 +1,10 @@
 var mercury = require('mercury');
 var insertCss = require('insert-css');
+
 var Browse = require('../browse/index');
 var Help = require('../help/index');
 var ErrorPage = require('../error/index');
+
 var css = require('./index.css');
 
 var h = mercury.h;
diff --git a/src/components/user-account/index.css b/src/components/user-account/index.css
new file mode 100644
index 0000000..7ca09fe
--- /dev/null
+++ b/src/components/user-account/index.css
@@ -0,0 +1,10 @@
+@import "common-style/theme.css";
+@import "common-style/sizes.css";
+
+.account-name {
+  position: absolute;
+  right: var(--size-space-xxsmall);
+  top: var(--size-space-xxsmall);
+  color: var(--color-text-secondary);
+  font-size: var(--size-font-xsmall);
+}
\ No newline at end of file
diff --git a/src/components/user-account/index.js b/src/components/user-account/index.js
index 24e8cfc..587b98a 100644
--- a/src/components/user-account/index.js
+++ b/src/components/user-account/index.js
@@ -1,7 +1,14 @@
 var mercury = require('mercury');
+var insertCss = require('insert-css');
+
 var namespaceService = require('../../services/namespace/service');
 
+var css = require('./index.css');
+
+var h = mercury.h;
+
 module.exports = create;
+module.exports.render = render;
 
 /*
  * User Account
@@ -24,3 +31,16 @@
     state: state
   };
 }
+
+function render(state) {
+  insertCss(css);
+
+  return h('core-tooltip.account-name', {
+      attributes: {
+        'label': 'You are logged in as:',
+        'position': 'bottom'
+      }
+    },
+    h('span', state.accountName)
+  );
+}
\ No newline at end of file
diff --git a/src/components/viewport/index.css b/src/components/viewport/index.css
index 69ade76..de96220 100644
--- a/src/components/viewport/index.css
+++ b/src/components/viewport/index.css
@@ -27,14 +27,6 @@
   color: var(--color-white);
 }
 
-.account-name {
-  position: absolute;
-  right: var(--size-space-xxsmall);
-  top: var(--size-space-xxsmall);
-  color: var(--color-text-secondary);
-  font-size: var(--size-font-xsmall);
-}
-
 /*
  * Wrap the paper-toast in a fixed div. This allows us to show multiple toasts.
  */
diff --git a/src/components/viewport/index.js b/src/components/viewport/index.js
index fcd1d1d..30b18f8 100644
--- a/src/components/viewport/index.js
+++ b/src/components/viewport/index.js
@@ -4,6 +4,7 @@
 var Sidebar = require('../sidebar/index');
 var MainContent = require('../main-content/index');
 var ReportBug = require('../bug-report/index');
+var UserAccount = require('../user-account/index');
 
 var css = require('./index.css');
 
@@ -125,15 +126,8 @@
       'ev-click': mercury.event(events.viewport.openSidebar)
     }),
     h('h2.title', state.viewport.title),
-    MainContent.renderHeader(state,events),
-    h('core-tooltip.account-name', {
-      attributes: {
-        'label': 'You are logged in as:',
-        'position': 'left'
-      }
-    },
-      h('span', state.userAccount.accountName)
-    )
+    MainContent.renderHeader(state, events),
+    UserAccount.render(state.userAccount)
   ]);
 }
 
diff --git a/src/services/namespace/item.js b/src/services/namespace/item.js
index 8d50dbb..dfc7127 100644
--- a/src/services/namespace/item.js
+++ b/src/services/namespace/item.js
@@ -34,23 +34,16 @@
 }
 
 /*
- * Creates an observable struct representing information about a server such as
- * type information, signature, etc...
+ * Creates an observable struct representing type information about a server.
  *
  * @param {mercury.struct} obj.typeInfo. Struct representing the type of the
  * server. ServerTypeInfo includes key, name, description, icon, etc..
  * @see #createServerTypeInfo method for details on typeInfo.
- * @param {object} obj.signature object representing the method signature of the
- * server.
- * @param {boolean} obj.isAccessible Whether the server instance is online and
- * accessible by the user.
  * @return {mercury.struct}
  */
 function createServerInfo(obj) {
   return mercury.struct({
     typeInfo: obj.typeInfo,
-    signature: mercury.value(obj.signature),
-    isAccessible: mercury.value(obj.isAccessible)
   });
 }
 
diff --git a/src/services/namespace/service.js b/src/services/namespace/service.js
index 0408f82..b9ea31b 100644
--- a/src/services/namespace/service.js
+++ b/src/services/namespace/service.js
@@ -21,6 +21,11 @@
   util: namespaceUtil,
 };
 
+//TODO(aghassemi) What's a good timeout? It should be shorter than this.
+//Can we use ML to dynamically change the timeout?
+//Should this be a user settings?
+var RPC_TIMEOUT = 30 * 1000;
+
 /*
  * Lazy getter and initializer for Veyron runtime
  */
@@ -58,7 +63,7 @@
  * the changes.
  *
  * The observable result has an events property which is an EventEmitter
- * and emits 'end', 'streamError' and 'itemError' events.
+ * and emits 'end' and 'streamError' events.
  *
  * @param {string} pattern Glob pattern
  * @return {Promise.<mercury.array>} Promise of an observable array
@@ -95,35 +100,29 @@
     }).then(function updateResult(globStream) {
       var itemPromises = [];
 
-      globStream.on('data', function createItem(result) {
+      globStream.on('data', function createItem(globResult) {
         // Create an item as glob results come in and add the item to result
-        var createItemPromise = createNamespaceItem(result)
-          .then(function(item) {
-            // TODO(aghassemi) namespace glob can return duplicate results, this
-            // temporary fix keeps the one that's a server. Is this correct?
-            // If a name can be more than one thing, UI needs change too.
-            var existingItem = globItemsObservArr.filter(function(curItem) {
-              return curItem().objectName === item().objectName;
-            }).get(0);
-            if (existingItem) {
-              // override the old one if new item is a server
-              if (item().isServer) {
-                var index = globItemsObservArr.indexOf(existingItem);
-                globItemsObservArr.put(index, item);
-              }
-            } else {
-              globItemsObservArr.push(item);
-            }
-          }).catch(function(err) {
-            globCache.del(cacheKey);
-            immutableResult.events.emit('itemError', {
-              name: result.name,
-              error: err
-            });
-            log.error('Failed to create item for "' + result.name + '"', err);
-          });
+        var result = createNamespaceItem(globResult);
+        var item = result.item;
+        var onFinishPromise = result.onFinish;
 
-        itemPromises.push(createItemPromise);
+        // TODO(aghassemi) namespace glob can return duplicate results, this
+        // temporary fix keeps the one that's a server. Is this correct?
+        // If a name can be more than one thing, UI needs change too.
+        var existingItem = globItemsObservArr.filter(function(curItem) {
+          return curItem().objectName === item().objectName;
+        }).get(0);
+        if (existingItem) {
+          // override the old one if new item is a server
+          if (item().isServer) {
+            var index = globItemsObservArr.indexOf(existingItem);
+            globItemsObservArr.put(index, item);
+          }
+        } else {
+          globItemsObservArr.push(item);
+        }
+
+        itemPromises.push(onFinishPromise);
       });
 
       globStream.on('end', function() {
@@ -169,9 +168,6 @@
       resultsObs.events.on('streamError', function(err) {
         reject(err);
       });
-      resultsObs.events.on('itemError', function(err) {
-        reject(err);
-      });
       resultsObs.events.on('end', function() {
         var results = resultsObs();
         if (results.length === 0) {
@@ -239,7 +235,7 @@
     return Promise.resolve(cacheHit);
   }
   return getRuntime().then(function invokeSignatureMethod(rt) {
-    var ctx = veyron.context.Context();
+    var ctx = veyron.context.Context().withTimeout(RPC_TIMEOUT);
     var client = rt.newClient();
     return client.signature(ctx, objectName);
   }).then(function cacheAndReturnSignature(signatures) {
@@ -306,11 +302,11 @@
  */
 function makeRPC(name, methodName, args) {
   return getRuntime().then(function bindToName(rt) {
-    var ctx = veyron.context.Context();
+    var ctx = veyron.context.Context().withTimeout(RPC_TIMEOUT);
     return rt.bindTo(ctx, name);
   }).then(function callMethod(service) {
     log.debug('Calling', methodName, 'on', name, 'with', args);
-    var ctx = veyron.context.Context();
+    var ctx = veyron.context.Context().withTimeout(RPC_TIMEOUT);
     args.unshift(ctx);
     return service[methodName].apply(null, args);
   }).then(function returnResult(result) {
@@ -325,60 +321,62 @@
  * "bar/baz/foo"
  * @param {MountEntry} mountEntry The mount entry from glob results.
  * @param {Array<string>} List of server addresses this name points to, if any.
- * @return {mercury.struct}
+ * @return item: {mercury.struct} onFinish: {Promise<bool>} Promise indicating
+ * we have loaded all the information including the async ones for the item.
  */
 function createNamespaceItem(mountEntry) {
 
   var name = mountEntry.name;
+
   // mounted name relative to parent
   var mountedName = namespaceUtil.basename(name);
   var servers = mountEntry.servers;
 
-  // Find out if the object referenced by name is globbable and get
-  // server related information about it.
+  // get server related information.
   var isServer = servers.length > 0;
-  return Promise.all([
-    (!isServer ? Promise.resolve(true) : isGlobbable(name)),
-    (isServer ? getServerInfo(name, mountEntry) : Promise.resolve(null))
-  ]).then(function(results) {
-    return itemFactory.createItem({
-      objectName: name,
-      mountedName: mountedName,
-      isGlobbable: results[0],
-      isServer: isServer,
-      serverInfo: results[1]
-    });
+  var serverInfo = null;
+  if (isServer) {
+    serverInfo = getServerInfo(name, mountEntry);
+  }
+
+  var item = itemFactory.createItem({
+    objectName: name,
+    mountedName: mountedName,
+    isGlobbable: false,
+    isServer: isServer,
+    serverInfo: serverInfo
   });
+
+  // find out if the object referenced by name is globbable asynchronously and
+  // update the state when it comes back
+  var onFinishPromise = isGlobbable(name).then(function(isGlobbable) {
+    item.isGlobbable.set(isGlobbable);
+    return true;
+  }).catch(function() {
+    return true;
+  });
+
+  return {
+    item: item,
+    onFinish: onFinishPromise
+  };
 }
 
 /*
  * Creates an observable struct representing information about a server such as
- * type information, signature, etc...
+ * type information
  * @see item.js for details.
  * @param {string} objectName Object name to get serverInfo for.
  * @param {MountEntry} mountEntry mount entry to item to get serverInfo for.
  * @return {mercury.struct}
  */
 function getServerInfo(objectName, mountEntry) {
-  var signature;
-  var isAccessible;
-  return getSignature(objectName).then(function gotSignature(sig) {
-    signature = sig;
-    isAccessible = true;
-    return getServerTypeInfo(sig, mountEntry);
-  }, function failedToGetSignature(err) {
-    signature = adaptSignature([]);
-    //TODO(aghassemi): We should at least be able to tell if inaccessible
-    //because not authorized vs other reasons.
-    isAccessible = false;
-    return createUnknownServiceTypeInfo();
-  }).then(function(serverTypeInfo) {
-    return itemFactory.createServerInfo({
-      typeInfo: serverTypeInfo,
-      signature: signature,
-      isAccessible: isAccessible
-    });
+  var typeInfo = getServerTypeInfo(mountEntry);
+  var serverInfo = itemFactory.createServerInfo({
+    typeInfo: typeInfo
   });
+
+  return serverInfo;
 }
 
 /*
@@ -387,11 +385,10 @@
  * would have information such as a key, human readable name and description for
  * the type of server.
  * @see item.js for details.
- * @param {Signature} signature signature to get serverTypeInfo for.
  * @param {MountEntry} mountEntry mount entry to get serverTypeInfo for.
  * @return {mercury.struct}
  */
-function getServerTypeInfo(signature, mountEntry) {
+function getServerTypeInfo(mountEntry) {
   // Currently we only support detecting mounttables which is
   // based on a "MT" flag that comes from the Glob API. Mounttables are special
   // in a sense that we fundamentally "know" they are a mounttable.
@@ -418,4 +415,4 @@
     typeName: 'Service',
     description: null
   });
-}
+}
\ No newline at end of file
diff --git a/test/integration/services/namespace/service.js b/test/integration/services/namespace/service.js
index eadb332..57ef3c4 100644
--- a/test/integration/services/namespace/service.js
+++ b/test/integration/services/namespace/service.js
@@ -363,8 +363,6 @@
   } else if(vals.isGlobbable === false) {
     assertIsNotGlobbable(t, item);
   }
-  assertHasSignature(t, item);
-  assertIsAccessible(t, item);
 
   if (vals.type === 'unknown') {
     assertUnknownServiceTypeInfo(t, item);
@@ -410,14 +408,6 @@
   t.equal(item.isGlobbable, false, item.mountedName + ': is not globbable');
 }
 
-function assertHasSignature(t, item) {
-  t.ok(item.serverInfo.signature, item.mountedName + ': has a signature');
-}
-
-function assertIsAccessible(t, item) {
-  t.ok(item.serverInfo.isAccessible, item.mountedName + ': is accessible');
-}
-
 function assertIsImmutable(t, observable) {
   t.ok(observable.set === undefined, 'is immutable');
 }