diff --git a/lib/browserid/views.js b/lib/browserid/views.js
index 1fc696fb6c90cd63d222e648afaec5f9364efeb9..ae9f3ecf22f8fd4f09e52c22880cdea5ce437568 100644
--- a/lib/browserid/views.js
+++ b/lib/browserid/views.js
@@ -173,7 +173,7 @@ exports.setup = function(app) {
   } else {
     // this is stage or production, explicitly disable all resources under /test
     app.get(/^\/test/, function(req, res) {
-      httputils.notFound("Cannot " + req.method + " " + req.url);
+      httputils.notFound(res, "Cannot " + req.method + " " + req.url);
     });
   }
 
diff --git a/lib/wsapi/stage_user.js b/lib/wsapi/stage_user.js
index ff1dd24bf03c10cee69671ba8ef0b80786c56db3..909d4d3dbb101daed1808699bd6b162028149fe3 100644
--- a/lib/wsapi/stage_user.js
+++ b/lib/wsapi/stage_user.js
@@ -59,7 +59,7 @@ exports.process = function(req, res) {
       if (err) {
         if (err.indexOf('exceeded') != -1) {
           logger.warn("max load hit, failing on auth request with 503: " + err);
-          return httputils.serviceUnavailable("server is too busy");
+          return httputils.serviceUnavailable(res, "server is too busy");
         }
         logger.error("can't bcrypt: " + err);
         return res.json({ success: false });
diff --git a/resources/static/dialog/css/popup.css b/resources/static/dialog/css/popup.css
index 8a655b7def5fd70a18016314e84683171402ec65..c55543e572188e2ce35d2a14b4f0102f31cd295b 100644
--- a/resources/static/dialog/css/popup.css
+++ b/resources/static/dialog/css/popup.css
@@ -51,9 +51,6 @@ header {
      * overflow the dialog box.
      */
     *padding: 10px 0;
-    /*
-    font-weight: bold;
-    */
     border-bottom: 1px solid #c7c6c1;
 
     /*-ms-filter through zoom: 1 are fixes for IE6 and IE7 so they show the header
@@ -74,6 +71,8 @@ header {
   background: url("/i/persona-logo-transparent.png") 0 0 no-repeat;
   text-indent: -9999px;
   display: inline-block;
+  *display: block;
+  zoom: 1;
 }
 
 footer {
@@ -153,10 +152,10 @@ section > .contents {
     /* Fix for IE6 not displaying the unsupported dialog correctly. IE6 by
      * default sets the height and width of the element to 0 meaning nothing
      * shows up on the screen.
-     * Note, these are magic numbers that depend on the width and height of the
+     * Note, height is a magic number that depend on the height of the
      * dialog.  The height also depends on the height of the header and footer.
      */
-    _width: 682px;
+    _width: 100%;
     _height: 250px;
 }
 
@@ -441,3 +440,7 @@ a.emphasize:active {
   min-width: 4em;
 }
 
+.unsupported, .cookies_disabled {
+  text-align: center;
+}
+
diff --git a/resources/static/shared/network.js b/resources/static/shared/network.js
index ed2cc792620a933b3ecee39784c11dd95e4a0eae..752ce427df57ff8903fea6a742ccd7b795b97703 100644
--- a/resources/static/shared/network.js
+++ b/resources/static/shared/network.js
@@ -94,6 +94,10 @@ BrowserID.Network = (function() {
       // Any time the context info changes, we want to know about it.
       mediator.subscribe('context_info', onContextChange);
 
+      // BEGIN TEST API
+      this.cookiesEnabledOverride = config && config.cookiesEnabledOverride;
+      // END TEST API
+
       clearContext();
     },
 
@@ -677,6 +681,12 @@ BrowserID.Network = (function() {
           enabled = false;
         }
 
+        // BEGIN TESTING API
+        if (typeof Network.cookiesEnabledOverride === "boolean") {
+          enabled = Network.cookiesEnabledOverride;
+        }
+        // END TESTING API
+
         complete(onComplete, enabled);
       }, onFailure);
     },
diff --git a/resources/static/shared/user.js b/resources/static/shared/user.js
index 1679488400632061aab85e12603afc5b273393ac..0695c836c9d1b045c3b35415067205c4415eb69b 100644
--- a/resources/static/shared/user.js
+++ b/resources/static/shared/user.js
@@ -679,6 +679,7 @@ BrowserID.User = (function() {
         if(cookiesEnabled) {
           network.checkAuth(function(authenticated) {
             setAuthenticationStatus(authenticated);
+            if (!authenticated) authenticated = false;
             complete(onComplete, authenticated);
           }, onFailure);
         }
@@ -692,12 +693,13 @@ BrowserID.User = (function() {
      * Check whether the current user is authenticated.  If authenticated, sync
      * identities.
      * @method checkAuthenticationAndSync
-     * @param {function} [onComplete] - Called on sync completion.
+     * @param {function} [onComplete] - Called on sync completion with one
+     * boolean parameter, authenticated.  authenticated will be true if user
+     * is authenticated, false otw.
      * @param {function} [onFailure] - Called on error.
      */
     checkAuthenticationAndSync: function(onComplete, onFailure) {
-      network.checkAuth(function(authenticated) {
-        setAuthenticationStatus(authenticated);
+      User.checkAuthentication(function(authenticated) {
         if (authenticated) {
           User.syncEmails(function() {
             onComplete && onComplete(authenticated);
@@ -1053,7 +1055,7 @@ BrowserID.User = (function() {
      * Get an assertion for the current domain if the user is signed into it
      * @method getPersistentSigninAssertion
      * @param {function} onComplete - called on completion.  Called with an
-     * assertion if successful, null otw.
+     * an email and assertion if successful, null otw.
      * @param {function} onFailure - called on XHR failure.
      */
     getSilentAssertion: function(siteSpecifiedEmail, onComplete, onFailure) {
@@ -1065,7 +1067,7 @@ BrowserID.User = (function() {
       //      so if we rely on localstorage only and check authentication status
       //      only when we know a network request will be required, we very well
       //      might have fewer race conditions and do fewer network requests.
-      User.checkAuthentication(function(authenticated) {
+      User.checkAuthenticationAndSync(function(authenticated) {
         if (authenticated) {
           var loggedInEmail = storage.getLoggedIn(origin);
           if (loggedInEmail !== siteSpecifiedEmail) {
diff --git a/resources/static/test/cases/shared/network.js b/resources/static/test/cases/shared/network.js
index ef310d932c20905bea77f4aca7dbe8e263c7ca85..4ce7680923dd3d0f03d8c57f771d69d461ae7e53 100644
--- a/resources/static/test/cases/shared/network.js
+++ b/resources/static/test/cases/shared/network.js
@@ -20,7 +20,6 @@
   module("shared/network", {
     setup: function() {
       testHelpers.setup();
-      network.init();
     },
     teardown: function() {
       testHelpers.teardown();
@@ -593,12 +592,28 @@
   });
 
   asyncTest("cookiesEnabled with cookies enabled - return true status", function() {
+    network.init({ cookiesEnabledOverride: true });
     network.cookiesEnabled(function(status) {
       equal(status, true, "cookies are enabled, correct status");
       start();
     }, testHelpers.unexpectedXHRFailure);
   });
 
+  asyncTest("cookiesEnabled with cookies disabled - return true status", function() {
+    network.init({ cookiesEnabledOverride: false });
+    network.cookiesEnabled(function(status) {
+      equal(status, false, "cookies are disabled, correct status");
+      start();
+    }, testHelpers.unexpectedXHRFailure);
+  });
+
+  asyncTest("cookiesEnabled with browser defined cookie status - wait and see", function() {
+    network.cookiesEnabled(function(status) {
+      equal(status, true, "hopefully cookies are enabled, correct status");
+      start();
+    }, testHelpers.unexpectedXHRFailure);
+  });
+
   asyncTest("cookiesEnabled with onComplete exception thrown - should not call onComplete a second time", function() {
     // Since we are manually throwing an exception, it must be caught
     // below.
diff --git a/resources/static/test/cases/shared/user.js b/resources/static/test/cases/shared/user.js
index c44fe0cd719b806924b091a621d1f2a0e0af5cfa..a07a5febb04c5527c7a5ff9980d62b994828bf96 100644
--- a/resources/static/test/cases/shared/user.js
+++ b/resources/static/test/cases/shared/user.js
@@ -14,6 +14,8 @@ var jwcrypto = require("./lib/jwcrypto");
       testHelpers = bid.TestHelpers,
       testOrigin = testHelpers.testOrigin,
       failureCheck = testHelpers.failureCheck,
+      testUndefined = testHelpers.testUndefined,
+      testNotUndefined = testHelpers.testNotUndefined,
       provisioning = bid.Mocks.Provisioning,
       TEST_EMAIL = "testuser@testuser.com";
 
@@ -512,24 +514,40 @@ var jwcrypto = require("./lib/jwcrypto");
 
 
   asyncTest("checkAuthentication with valid authentication", function() {
+    storage.addSecondaryEmail(TEST_EMAIL);
     xhr.setContextInfo("auth_level", "primary");
+
     lib.checkAuthentication(function(authenticated) {
       equal(authenticated, "primary", "We are authenticated!");
+      testNotUndefined(storage.getEmail(TEST_EMAIL), "localStorage is not cleared");
       start();
     });
   });
 
 
 
-  asyncTest("checkAuthentication with invalid authentication", function() {
+  asyncTest("checkAuthentication with invalid authentication - localStorage cleared", function() {
+    storage.addSecondaryEmail(TEST_EMAIL);
     xhr.setContextInfo("auth_level", undefined);
+
     lib.checkAuthentication(function(authenticated) {
-      equal(authenticated, undefined, "We are not authenticated!");
+      equal(authenticated, false, "We are not authenticated!");
+      testUndefined(storage.getEmail(TEST_EMAIL), "localStorage was cleared");
       start();
     });
   });
 
 
+  asyncTest("checkAuthentication with cookies disabled - localStorage is not cleared, user can enable their cookies and try again", function() {
+    storage.addSecondaryEmail(TEST_EMAIL);
+    network.init({ cookiesEnabledOverride: false });
+
+    lib.checkAuthentication(function(authenticated) {
+      equal(authenticated, false, "We are not authenticated!");
+      testNotUndefined(storage.getEmail(TEST_EMAIL), "localStorage is not cleared");
+      start();
+    });
+  });
 
   asyncTest("checkAuthentication with XHR failure", function() {
     xhr.useResult("contextAjaxError");
@@ -548,12 +566,24 @@ var jwcrypto = require("./lib/jwcrypto");
   });
 
 
-
-  asyncTest("checkAuthenticationAndSync with invalid authentication", function() {
+  asyncTest("checkAuthenticationAndSync with invalid authentication - localStorage cleared", function() {
+    storage.addSecondaryEmail(TEST_EMAIL);
     xhr.setContextInfo("auth_level", undefined);
 
     lib.checkAuthenticationAndSync(function onComplete(authenticated) {
-      equal(authenticated, undefined, "We are not authenticated!");
+      equal(authenticated, false, "We are not authenticated!");
+      testUndefined(storage.getEmail(TEST_EMAIL), "localStorage was cleared");
+      start();
+    }, testHelpers.unexpectedXHRFailure);
+  });
+
+  asyncTest("checkAuthenticationAndSync with cookies disabled - localStorage not cleared, user can enable their cookies and try again", function() {
+    storage.addSecondaryEmail(TEST_EMAIL);
+    network.init({ cookiesEnabledOverride: false });
+
+    lib.checkAuthenticationAndSync(function onComplete(authenticated) {
+      equal(authenticated, false, "We are not authenticated!");
+      testNotUndefined(storage.getEmail(TEST_EMAIL), "localStorage is not cleared");
       start();
     }, testHelpers.unexpectedXHRFailure);
   });
@@ -942,6 +972,34 @@ var jwcrypto = require("./lib/jwcrypto");
   });
 
 
+  asyncTest("getSilentAssertion with logged in user, emails match - user already logged in, call callback with email and null assertion", function() {
+    var LOGGED_IN_EMAIL = TEST_EMAIL;
+    xhr.setContextInfo("auth_level", "password");
+
+    lib.syncEmailKeypair(LOGGED_IN_EMAIL, function() {
+      storage.setLoggedIn(lib.getOrigin(), LOGGED_IN_EMAIL);
+      lib.getSilentAssertion(LOGGED_IN_EMAIL, function(email, assertion) {
+        equal(email, LOGGED_IN_EMAIL, "correct email");
+        strictEqual(assertion, null, "correct assertion");
+        start();
+      }, testHelpers.unexpectedXHRFailure);
+    }, testHelpers.unexpectedXHRFailure);
+  });
+
+  asyncTest("getSilentAssertion with logged in user, request email different from logged in email, valid cert for logged in email - logged in user needs assertion - call callback with email and assertion.", function() {
+    xhr.setContextInfo("auth_level", "password");
+    var LOGGED_IN_EMAIL = TEST_EMAIL;
+    var REQUESTED_EMAIL = "requested@testuser.com";
+
+    lib.syncEmailKeypair(LOGGED_IN_EMAIL, function() {
+      storage.setLoggedIn(lib.getOrigin(), LOGGED_IN_EMAIL);
+      lib.getSilentAssertion(REQUESTED_EMAIL, function(email, assertion) {
+        equal(email, LOGGED_IN_EMAIL, "correct email");
+        testAssertion(assertion, start);
+      }, testHelpers.unexpectedXHRFailure);
+    }, testHelpers.unexpectedXHRFailure);
+  });
+
   asyncTest("logoutUser", function(onSuccess) {
     lib.authenticate(TEST_EMAIL, "testuser", function(authenticated) {
       lib.syncEmails(function() {
diff --git a/resources/static/test/testHelpers/helpers.js b/resources/static/test/testHelpers/helpers.js
index 2c77f42019d666b16005680e32cd1afc4aab1bc6..c309deeb16f250d20aa848d01b1d5d5b0f0e3b90 100644
--- a/resources/static/test/testHelpers/helpers.js
+++ b/resources/static/test/testHelpers/helpers.js
@@ -68,7 +68,7 @@ BrowserID.TestHelpers = (function() {
       transport.setContextInfo("cookies_enabled", true);
       transport.useResult("valid");
 
-      network.init();
+      network.init({ forceCookieStatus: undefined });
       clearStorage();
 
       $("body").stop().show();
@@ -223,6 +223,14 @@ BrowserID.TestHelpers = (function() {
     testHasClass: function(selector, className, msg) {
       ok($(selector).hasClass(className),
           selector + " has className " + className + " - " + msg);
+    },
+
+    testUndefined: function(toTest, msg) {
+      equal(typeof toTest, "undefined", msg || "object is undefined");
+    },
+
+    testNotUndefined: function(toTest, msg) {
+      notEqual(typeof toTest, "undefined", msg || "object is defined");
     }
 
   };
diff --git a/resources/views/layout.ejs b/resources/views/layout.ejs
index 8c8d01cd0879b4067b1bd866bfd4a1bb6b1a2723..1373793786f965237d79b2ee474adae56e4bbe05 100644
--- a/resources/views/layout.ejs
+++ b/resources/views/layout.ejs
@@ -16,7 +16,7 @@
     <%- cachify_css('/production/ie8_main.css') %>
   <![endif]-->
   <%- cachify_js(util.format('/production/%s/browserid.js', locale)) %>
-  <title><%= format(gettext("Mozilla Person: %s"), [title]) %></title>
+  <title><%= format(gettext("Mozilla Persona: %s"), [title]) %></title>
 </head>
 <body class="loading">
 <a href="#" id="showDevelopment">&nbsp;</a>
diff --git a/resources/views/signin.ejs b/resources/views/signin.ejs
index e9fa2170922d4c83219ab6451ff7d02e25c9f407..a0ed5a5fc8300f55d29493db7f345dd0bf23f23e 100644
--- a/resources/views/signin.ejs
+++ b/resources/views/signin.ejs
@@ -42,7 +42,7 @@
                     </div>
 
                     <div id="cannot_authenticate" class="tooltip" for="password">
-                      The account cannot be logged in with this username and password.')
+                      The account cannot be logged in with this username and password.
 
                 </li>
             </ul>