Merge "js/core: Add WebDriver library for UI Testing"
diff --git a/Makefile b/Makefile
index 744a171..b15a55e 100644
--- a/Makefile
+++ b/Makefile
@@ -238,7 +238,7 @@
 	@$(VGO) build -o $(GOBIN)/servicerunner -a -tags wspr v.io/x/ref/cmd/servicerunner
 	@$(VGO) build -o $(GOBIN)/principal v.io/x/ref/cmd/principal
 	@$(VGO) build -o $(GOBIN)/test_serviced v.io/x/js.core/test_service/test_serviced
-	@$(VGO) build -o $(GOBIN)/stressd v.io/x/ref/profiles/internal/rpc/stress/stressd
+	@$(VGO) build -o $(GOBIN)/stressd v.io/x/ref/runtime/internal/rpc/stress/stressd
 
 lint: node_modules
 ifdef NOLINT
diff --git a/extension/manifest.json b/extension/manifest.json
index a75c079..89c0449 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -1,6 +1,6 @@
 {
   "name": "Vanadium Extension",
-  "version": "0.1.6",
+  "version": "0.1.7",
   "description": "Access and create Vanadium services from JavaScript.",
   "manifest_version": 2,
   "icons": {
diff --git a/extension/src/background/addcaveats.js b/extension/src/background/addcaveats.js
index 1852579..7059519 100644
--- a/extension/src/background/addcaveats.js
+++ b/extension/src/background/addcaveats.js
@@ -56,10 +56,8 @@
   var backgroundPort = chrome.runtime.connect();
   backgroundPort.postMessage({
     type: 'assocAccount:finish',
-    requestId: parseInt(params.requestId),
     origin: params.origin,
     caveats: caveats,
-    authState: params.authState,
     cancel: cancel
   });
   backgroundPort.disconnect();
diff --git a/extension/src/background/auth-handler.js b/extension/src/background/auth-handler.js
index 848e7eb..90b3815 100644
--- a/extension/src/background/auth-handler.js
+++ b/extension/src/background/auth-handler.js
@@ -7,7 +7,6 @@
  */
 
 var getOrigin = require('./util').getOrigin;
-var random = require('../../../src/lib/random');
 
 module.exports = AuthHandler;
 
@@ -18,9 +17,6 @@
 
   this._channel = channel;
 
-  // Auth request id, incremented on each auth request.
-  this._lastRequestId = 0;
-
   // Map from origins to the Vanadium app ports of tabs with active requests.
   // This keeps track of existing auth tabs for an origin so new ones are not
   // started.
@@ -126,22 +122,29 @@
 
 // Pop up a new tab asking the user to chose their caveats.
 AuthHandler.prototype.getCaveats = function(account, origin, appPort) {
+  // Store the account name on the appPort.
+  appPort.account = account;
+
   var outstandingAuthRequests = this._outstandingAuthRequests;
+  var caveatTabOrigins = this._caveatTabOrigins;
   if (origin in this._outstandingAuthRequests) {
     outstandingAuthRequests[origin].push(appPort);
+
+    // Switch to the corresponding open caveat tab.
+    for (var tabId in caveatTabOrigins) {
+      if (caveatTabOrigins[tabId] === origin) {
+        var tabIdAsNumber = +tabId;
+        chrome.tabs.update(tabIdAsNumber, {active: true});
+        break;
+      }
+    }
+
     return;
   }
-
-  this._lastRequestId++;
-  var requestId = this._lastRequestId;
-
-  // Store the account name, random salt, and timestamp on the port.
-  appPort.account = account;
-  appPort.authState = random.hex();
+  outstandingAuthRequests[origin] = [appPort];
 
   // Get  currently active tab in the window.
   var windowId = appPort.sender.tab.windowId;
-  var caveatTabOrigins = this._caveatTabOrigins;
   chrome.tabs.query({active: true, windowId: windowId}, function(tabs) {
     // Store the current tab id so we can switch back to it after the addcaveats
     // tab is removed.  Note that the currently active tab might not be the same
@@ -151,11 +154,9 @@
     }
 
     chrome.tabs.create({
-      url: chrome.extension.getURL('html/addcaveats.html') + '?requestId=' +
-        requestId + '&origin=' + encodeURIComponent(origin) +
-        '&authState=' + appPort.authState
+      url: chrome.extension.getURL('html/addcaveats.html') + '?origin=' +
+        encodeURIComponent(origin)
     }, function(tab) {
-      outstandingAuthRequests[origin] = [appPort];
       caveatTabOrigins[tab.id] = origin;
     });
   });
@@ -281,11 +282,6 @@
           new Error('Invalid origin.'));
     }
 
-    if (msg.authState !== appPort.authState) {
-      return sendErrorToContentScript('auth', appPort,
-          new Error('Port not authorized.'));
-    }
-
     if (!appPort.account) {
       return sendErrorToContentScript('auth', appPort,
           new Error('No port.account.'));
diff --git a/extension/src/content/index.js b/extension/src/content/index.js
index cf9ae18..09d32ef 100644
--- a/extension/src/content/index.js
+++ b/extension/src/content/index.js
@@ -10,8 +10,15 @@
 // Port to communicate with background js.
 // One content script runs per iframe / tabs so there may be multiple ports
 // per page.
-// TODO(bprosnitz) Change this to lazily connect.
-var backgroundPort = chrome.runtime.connect();
+var _backgroundPort;
+function getBackgroundPort() {
+  // Lazily connect to background port.
+  if (!_backgroundPort) {
+    _backgroundPort = chrome.runtime.connect();
+    _backgroundPort.onMessage.addListener(backgroundPageMessageForwarder);
+  }
+  return _backgroundPort;
+}
 
 // We generate and send different instanceIds to the background page than those
 // coming from the web app. This prevents the web app from intentionally
@@ -69,7 +76,7 @@
   }
 
   try {
-    backgroundPort.postMessage({
+    getBackgroundPort().postMessage({
       type: this.event,
       body: body
     });
@@ -80,7 +87,7 @@
 });
 
 // Forward any messages from the background page to the webApp.
-backgroundPort.onMessage.addListener(function(msg) {
+function backgroundPageMessageForwarder(msg) {
   debug('content script received message of type', msg.type,
     'from background script:', msg.body);
 
@@ -100,6 +107,6 @@
   }
 
   pageEventProxy.send(msg.type, msg);
-});
+}
 
 debug('content script loaded');
diff --git a/go/src/v.io/x/js.core/test_service/cache.vdl.go b/go/src/v.io/x/js.core/test_service/cache.vdl.go
index 0c96986..ac84325 100644
--- a/go/src/v.io/x/js.core/test_service/cache.vdl.go
+++ b/go/src/v.io/x/js.core/test_service/cache.vdl.go
@@ -20,7 +20,7 @@
 type KeyPageResult [10]string
 
 func (KeyPageResult) __VDLReflect(struct {
-	Name string "v.io/x/js.core/test_service.KeyPageResult"
+	Name string `vdl:"v.io/x/js.core/test_service.KeyPageResult"`
 }) {
 }
 
@@ -31,7 +31,7 @@
 }
 
 func (KeyValuePair) __VDLReflect(struct {
-	Name string "v.io/x/js.core/test_service.KeyValuePair"
+	Name string `vdl:"v.io/x/js.core/test_service.KeyValuePair"`
 }) {
 }
 
diff --git a/go/src/v.io/x/js.core/test_service/invoke_method_caveat_id.vdl.go b/go/src/v.io/x/js.core/test_service/invoke_method_caveat_id.vdl.go
index f6c9379..a283878 100644
--- a/go/src/v.io/x/js.core/test_service/invoke_method_caveat_id.vdl.go
+++ b/go/src/v.io/x/js.core/test_service/invoke_method_caveat_id.vdl.go
@@ -25,7 +25,7 @@
 }
 
 func (TestCaveatData) __VDLReflect(struct {
-	Name string "v.io/x/js.core/test_service.TestCaveatData"
+	Name string `vdl:"v.io/x/js.core/test_service.TestCaveatData"`
 }) {
 }
 
diff --git a/go/src/v.io/x/js.core/test_service/test_serviced/main.go b/go/src/v.io/x/js.core/test_service/test_serviced/main.go
index c10108a..ec964e8 100644
--- a/go/src/v.io/x/js.core/test_service/test_serviced/main.go
+++ b/go/src/v.io/x/js.core/test_service/test_serviced/main.go
@@ -11,7 +11,7 @@
 
 	"v.io/v23"
 	"v.io/x/ref/lib/signals"
-	_ "v.io/x/ref/profiles"
+	_ "v.io/x/ref/runtime/factories/generic"
 )
 
 func main() {
diff --git a/go/src/v.io/x/js.core/test_service/test_serviced/test_serviced.go b/go/src/v.io/x/js.core/test_service/test_serviced/test_serviced.go
index 6158ed2..092ae64 100644
--- a/go/src/v.io/x/js.core/test_service/test_serviced/test_serviced.go
+++ b/go/src/v.io/x/js.core/test_service/test_serviced/test_serviced.go
@@ -14,7 +14,7 @@
 	"v.io/v23/rpc"
 	"v.io/v23/security"
 	"v.io/x/js.core/test_service"
-	_ "v.io/x/ref/profiles"
+	_ "v.io/x/ref/runtime/factories/generic"
 )
 
 // openAuthorizer allows RPCs from all clients.
diff --git a/src/gen-vdl/v.io/v23/security/access/index.js b/src/gen-vdl/v.io/v23/security/access/index.js
index 9503e22..84afd30 100644
--- a/src/gen-vdl/v.io/v23/security/access/index.js
+++ b/src/gen-vdl/v.io/v23/security/access/index.js
@@ -95,6 +95,19 @@
 ]);
 
 
+module.exports.UnenforceablePatternsError = makeError('v.io/v23/security/access.UnenforceablePatterns', actions.NO_RETRY, {
+  'en': '{1:}{2:} AccessList contains the following invalid or unrecognized patterns in the In list: {3}',
+}, [
+  _type1,
+]);
+
+
+module.exports.InvalidOpenAccessListError = makeError('v.io/v23/security/access.InvalidOpenAccessList', actions.NO_RETRY, {
+  'en': '{1:}{2:} AccessList with the pattern ... in its In list must have no other patterns in the In or NotIn lists',
+}, [
+]);
+
+
 
 
 // Services:
diff --git a/src/rpc/server.js b/src/rpc/server.js
index 4d77944..ca75941 100644
--- a/src/rpc/server.js
+++ b/src/rpc/server.js
@@ -57,6 +57,9 @@
   this.serverOption = serverOption || new ServerOption();
 }
 
+// TODO(aghassemi) the serviceObject example needs to point to a "Guides" page
+// on the website when we have it. https://github.com/vanadium/issues/issues/444
+/* jshint ignore:start */
 /**
  * ServeOptions is a set of options that are passed to the
  * [serve]{@link module:vanadium.rpc~Server#serve}.
@@ -70,13 +73,6 @@
  * <p>Serve associates object with name by publishing the address
  * of this server with the mount table under the supplied name and using
  * authorizer to authorize access to it.</p>
- *
- * <p>To serve names of the form "mymedia/*" make the calls:</p>
- * <pre>
- * serve("mymedia", serviceObject, { // optional authorizer
- *   authorizer: serviceAuthorizer
- * });
- * </pre>
  * <p>If name is an empty string, no attempt will made to publish that
  * name to a mount table. It is an error to call
  * {@link module:vanadium.rpc~Server#serve|serve}
@@ -84,6 +80,55 @@
  * or {@link module:vanadium.rpc~Server.serve|serve} has already been called.
  * To serve the same object under multiple names,
  * {@link module:vanadium.rpc~Server#addName|addName} can be used.</p>
+ * <p>To serve names of the form "mymedia/*" make the calls:</p>
+ * <pre>
+ * serve("mymedia", serviceObject, {
+ *   authorizer: serviceAuthorizer // optional authorizer
+ * });
+ * </pre>
+ * <p>
+ * serviceObject is simply a JavaScript object that implements service methods.
+ * </p>
+ * <p>
+ * <pre>
+ * var serviceObject = new MyService();
+ * function MyService() {}
+ * </pre>
+ * <p>
+ * Each service method must take [ctx]{@link module:vanadium.context.Context}
+ * and [serverCall]{@link module:vanadium.rpc~ServerCall} as the
+ * first two parameters.
+ * </p>
+ * <p>
+ * The output arguments can be given in several forms - through direct return,
+ * return of a promise or calling a callback that is optionally the
+ * last parameter.
+ * </p>
+ * <pre>
+ * // Sync method that echoes the input text immediately.
+ * MyService.prototype.echo = function(ctx, serverCall, text) {
+ *   return 'Echo: ' + text;
+ * };
+ * </pre>
+ * <pre>
+ * // Async method that echoes the input text after 1 second, using Promises.
+ * MyService.prototype.delayedEcho = function(ctx, serverCall, text) {
+ *   return new Promise(function(resolve, reject) {
+ *     setTimeout(function() {
+ *       resolve('Echo: ' + text);
+ *     }, 1000);
+ *   });
+ * };
+ *</pre>
+ *<pre>
+ * // Async method that echoes the input text after 1 second, using Callbacks.
+ * MyService.prototype.delayedEcho = function(ctx, serverCall, text, callback) {
+ *   setTimeout(function() {
+ *     // first argument to the callback is error, second argument is results
+ *     callback(null, 'Echo: ' + text);
+ *   }, 1000);
+ * };
+ *</pre>
  *
  * @public
  * @param {string} name Name to serve under.
@@ -94,6 +139,7 @@
  * will be called on completion.
  * @return {Promise<void>} Promise to be called when serve completes or fails.
  */
+/* jshint ignore:end */
 Server.prototype.serve = function(name, serviceObject, options, cb) {
   if (typeof options === 'function') {
     cb = options;
diff --git a/src/security/access/accesslist-extensions.js b/src/security/access/accesslist-extensions.js
new file mode 100644
index 0000000..d1ff744
--- /dev/null
+++ b/src/security/access/accesslist-extensions.js
@@ -0,0 +1,38 @@
+// 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.
+
+/*
+ * Extends the vdl generated AccessList by adding additional methods.
+ * @fileoverview
+ */
+
+var blessingMatches = require('./blessing-matching');
+var AccessList = require('../../gen-vdl/v.io/v23/security/access').AccessList;
+
+/**
+ * Returns true iff the AccessList grants access to a principal that
+ * presents blessings.
+ * (i.e., if at least one of the blessings matches the AccessList).
+ * @param {string[]} blessings Presented blessing names.
+ * @return {boolean}
+ * @name includes
+ * @method
+ * @memberof module:vanadium.security.access.AccessList.prototype
+ */
+ AccessList.prototype.includes = function(blessings) {
+  var accessList = this;
+
+  // Remove the blessing that are blacklisted.
+  var unblacklistedNames = blessings.filter(function(blessing) {
+    return accessList.notIn.every(function(pattern) {
+      return !blessingMatches(blessing, pattern);
+    });
+  });
+  // Check the remaining blessing for a match in the white list.
+  return unblacklistedNames.some(function(blessing) {
+    return accessList.in.some(function(pattern) {
+      return blessingMatches(blessing, pattern);
+    });
+  });
+ };
\ No newline at end of file
diff --git a/src/security/access/index.js b/src/security/access/index.js
index 6964eb8..d5fafda 100644
--- a/src/security/access/index.js
+++ b/src/security/access/index.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Require the extensions files.
+require('./accesslist-extensions');
+
 var extend = require('xtend');
 /* jshint ignore:start */
 /**
diff --git a/src/security/access/permissions-authorizer.js b/src/security/access/permissions-authorizer.js
index 6c4e1c4..c2a03ad 100644
--- a/src/security/access/permissions-authorizer.js
+++ b/src/security/access/permissions-authorizer.js
@@ -5,7 +5,6 @@
  * @fileoverview The Permissions authorizer
  * @private
  */
-var blessingMatches = require('./blessing-matching');
 var unwrap = require('../../vdl/type-util').unwrap;
 var makeError = require('../../verror/make-errors');
 var actions = require('../../verror/actions');
@@ -66,27 +65,9 @@
 
     var key = unwrap(tags[0]);
     var lists = permissions.get(key);
-    if (!lists || !canAccess(call.remoteBlessingStrings, lists.in,
-                                lists.notIn)) {
+    if (!lists || !lists.includes(call.remoteBlessingStrings)) {
       throw new NoPermissionsError(ctx, call.remoteBlessingStrings, [], key);
     }
     return;
   };
-}
-
-// Returns whether name passed in has permission for the passed in
-// label.
-function canAccess(names, inSet, notInSet) {
-  // Remove the names that are blacklisted.
-  var unblacklistedNames = names.filter(function(name) {
-    return notInSet.every(function(pattern) {
-      return !blessingMatches(name, pattern);
-    });
-  });
-  // Check the remaining names for a match in the white list.
-  return unblacklistedNames.some(function(name) {
-    return inSet.some(function(pattern) {
-      return blessingMatches(name, pattern);
-    });
-  });
-}
+}
\ No newline at end of file
diff --git a/test/integration/test-namespace.js b/test/integration/test-namespace.js
index a2cbccb..ee56a42 100644
--- a/test/integration/test-namespace.js
+++ b/test/integration/test-namespace.js
@@ -176,7 +176,7 @@
       runtime = rt;
       var namespace = rt.namespace();
       // Note: Glob will always timeout after 30s
-      // see v.io/x/ref/profiles/internal/naming/namespace/parallelstartcall.go
+      // see v.io/x/ref/runtime/internal/naming/namespace/parallelstartcall.go
       // This means we'll get a timeout error on the glob stream before
       // timeouts.long expires.
       var rpc = namespace.glob(rt.getContext(),