author | Matthew Noorenberghe <mozilla@noorenberghe.ca> |
Tue, 20 Jan 2015 16:12:30 -0800 | |
changeset 224870 | 01cc2ba4cb590ec07948469ba2e45813ea0f1438 |
parent 224796 | 9a389eb9609fcc133a7c9a41a755afaadf02783c |
child 224871 | 83fa0bab1486dc615d514bfe75e227d680be25da |
push id | 54370 |
push user | cbook@mozilla.com |
push date | Wed, 21 Jan 2015 13:32:49 +0000 |
treeherder | mozilla-inbound@bd7d13e5875c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | pkerr |
bugs | 1098629 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -255,16 +255,17 @@ let MozLoopServiceInternal = { * error of a type will be saved at a time. This value may be used to * determine user-facing (aka. friendly) strings. * @param {Object} error an object describing the error in the format from Hawk errors * @param {Function} [actionCallback] an object describing the label and callback function for error * bar's button e.g. to retry. */ setError: function(errorType, error, actionCallback = null) { log.debug("setError", errorType, error); + log.trace(); let messageString, detailsString, detailsButtonLabelString, detailsButtonCallback; const NETWORK_ERRORS = [ Cr.NS_ERROR_CONNECTION_REFUSED, Cr.NS_ERROR_NET_INTERRUPT, Cr.NS_ERROR_NET_RESET, Cr.NS_ERROR_NET_TIMEOUT, Cr.NS_ERROR_OFFLINE, Cr.NS_ERROR_PROXY_CONNECTION_REFUSED, @@ -295,25 +296,34 @@ let MozLoopServiceInternal = { messageString = "service_not_available"; detailsString = "try_again_later"; detailsButtonLabelString = "retry_button"; } else { messageString = "generic_failure_title"; } error.friendlyMessage = this.localizedStrings.get(messageString); - error.friendlyDetails = detailsString ? - this.localizedStrings.get(detailsString) : - null; + + // Default to the generic "retry_button" text even though the button won't be shown if + // error.friendlyDetails is null. error.friendlyDetailsButtonLabel = detailsButtonLabelString ? this.localizedStrings.get(detailsButtonLabelString) : - null; + this.localizedStrings.get("retry_button"); error.friendlyDetailsButtonCallback = actionCallback || detailsButtonCallback || null; + if (detailsString) { + error.friendlyDetails = this.localizedStrings.get(detailsString); + } else if (error.friendlyDetailsButtonCallback) { + // If we have a retry callback but no details use the generic try again string. + error.friendlyDetails = this.localizedStrings.get("generic_failure_no_reason2"); + } else { + error.friendlyDetails = null; + } + gErrors.set(errorType, error); this.notifyStatusChanged(); }, clearError: function(errorType) { if (gErrors.has(errorType)) { gErrors.delete(errorType); this.notifyStatusChanged(); @@ -1214,17 +1224,18 @@ this.MozLoopService = { return; } log.debug("MozLoopService: Initializing with already logged-in account"); MozLoopServiceInternal.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA).then(() => { deferredInitialization.resolve("initialized to logged-in status"); }, error => { log.debug("MozLoopService: error logging in using cached auth token"); - MozLoopServiceInternal.setError("login", error); + let retryFunc = () => MozLoopServiceInternal.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA); + MozLoopServiceInternal.setError("login", error, retryFunc); deferredInitialization.reject("error logging in using cached auth token"); }); yield completedPromise; }), /** * Opens the chat window * @@ -1416,37 +1427,27 @@ this.MozLoopService = { MozLoopServiceInternal.fxAOAuthTokenData = tokenData; return tokenData; }).then(tokenData => { return MozLoopServiceInternal.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA).then(() => { MozLoopServiceInternal.clearError("login"); MozLoopServiceInternal.clearError("profile"); return MozLoopServiceInternal.fxAOAuthTokenData; }); - }).then(tokenData => { - let client = new FxAccountsProfileClient({ - serverURL: gFxAOAuthClient.parameters.profile_uri, - token: tokenData.access_token - }); - client.fetchProfile().then(result => { - MozLoopServiceInternal.fxAOAuthProfile = result; - }, error => { - log.error("Failed to retrieve profile", error); - this.setError("profile", error); - MozLoopServiceInternal.fxAOAuthProfile = null; - MozLoopServiceInternal.notifyStatusChanged(); - }); + }).then(Task.async(function* fetchProfile(tokenData) { + yield MozLoopService.fetchFxAProfile(tokenData); return tokenData; - }).catch(error => { + })).catch(error => { MozLoopServiceInternal.fxAOAuthTokenData = null; MozLoopServiceInternal.fxAOAuthProfile = null; MozLoopServiceInternal.deferredRegistrations.delete(LOOP_SESSION_TYPE.FXA); throw error; }).catch((error) => { - MozLoopServiceInternal.setError("login", error); + MozLoopServiceInternal.setError("login", error, + () => MozLoopService.logInToFxA()); // Re-throw for testing throw error; }); }, /** * Logs the user out from FxA. * @@ -1480,16 +1481,40 @@ this.MozLoopService = { // clearError calls notifyStatusChanged so should be done last when the // state is clean. MozLoopServiceInternal.clearError("registration"); MozLoopServiceInternal.clearError("login"); MozLoopServiceInternal.clearError("profile"); } }), + /** + * Fetch/update the FxA Profile for the logged in user. + * + * @return {Promise} resolving if the profile information was succesfully retrieved + * rejecting if the profile information couldn't be retrieved. + * A profile error is registered. + **/ + fetchFxAProfile: function() { + log.debug("fetchFxAProfile"); + let client = new FxAccountsProfileClient({ + serverURL: gFxAOAuthClient.parameters.profile_uri, + token: MozLoopServiceInternal.fxAOAuthTokenData.access_token + }); + return client.fetchProfile().then(result => { + MozLoopServiceInternal.fxAOAuthProfile = result; + MozLoopServiceInternal.clearError("profile"); + }, error => { + log.error("Failed to retrieve profile", error, this.fetchFxAProfile.bind(this)); + MozLoopServiceInternal.setError("profile", error); + MozLoopServiceInternal.fxAOAuthProfile = null; + MozLoopServiceInternal.notifyStatusChanged(); + }); + }, + openFxASettings: Task.async(function() { try { let fxAOAuthClient = yield MozLoopServiceInternal.promiseFxAOAuthClient(); if (!fxAOAuthClient) { log.error("Could not get the OAuth client"); return; } let url = new URL("/settings", fxAOAuthClient.parameters.content_uri);
--- a/browser/components/loop/test/mochitest/browser_fxa_login.js +++ b/browser/components/loop/test/mochitest/browser_fxa_login.js @@ -291,18 +291,19 @@ add_task(function* basicAuthorizationAnd let loopDoc = document.getElementById("loop-panel-iframe").contentDocument; let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0]; is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel when not logged in"); is(MozLoopService.userProfile, null, "profile should be null before log-in"); let loopButton = document.getElementById("loop-button"); is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in"); info("Login"); + statusChangedPromise = promiseObserverNotified("loop-status-changed", "login"); let tokenData = yield MozLoopService.logInToFxA(); - yield promiseObserverNotified("loop-status-changed", "login"); + yield statusChangedPromise; ise(tokenData.access_token, "code1_access_token", "Check access_token"); ise(tokenData.scope, "profile", "Check scope"); ise(tokenData.token_type, "bearer", "Check token_type"); is(MozLoopService.userProfile.email, "test@example.com", "email should exist in the profile data"); is(MozLoopService.userProfile.uid, "1234abcd", "uid should exist in the profile data"); is(visibleEmail.textContent, "test@example.com", "the email should be correct on the panel"); is(loopButton.getAttribute("state"), "active", "state of loop button should be active when logged in");
--- a/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js +++ b/browser/components/loop/test/xpcshell/test_loopservice_hawk_errors.js @@ -69,17 +69,16 @@ add_task(function* guest_401() { "FxA session token should NOT have been cleared"); Assert.strictEqual(MozLoopService.errors.size, 1, "Should be one error"); let err = MozLoopService.errors.get("registration"); Assert.strictEqual(err.code, 401); Assert.strictEqual(err.friendlyMessage, getLoopString("session_expired_error_description")); Assert.equal(err.friendlyDetails, null); - Assert.equal(err.friendlyDetailsButtonLabel, null); }); }); add_task(cleanup_between_tests); add_task(function* fxa_401() { Services.prefs.setCharPref("loop.hawk-session-token", "guest"); Services.prefs.setCharPref("loop.hawk-session-token.fxa", "fxa"); @@ -110,17 +109,16 @@ add_task(function* error_404() { (error) => { MozLoopServiceInternal.setError("testing", error); Assert.strictEqual(MozLoopService.errors.size, 1, "Should be one error"); let err = MozLoopService.errors.get("testing"); Assert.strictEqual(err.code, 404); Assert.strictEqual(err.friendlyMessage, getLoopString("generic_failure_title")); Assert.equal(err.friendlyDetails, null); - Assert.equal(err.friendlyDetailsButtonLabel, null); }); }); add_task(cleanup_between_tests); add_task(function* error_500() { yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/500", "GET").then( () => Assert.ok(false, "Should have rejected"), @@ -144,17 +142,16 @@ add_task(function* profile_500() { (error) => { MozLoopServiceInternal.setError("profile", error); Assert.strictEqual(MozLoopService.errors.size, 1, "Should be one error"); let err = MozLoopService.errors.get("profile"); Assert.strictEqual(err.code, 500); Assert.strictEqual(err.friendlyMessage, getLoopString("problem_accessing_account")); Assert.equal(err.friendlyDetails, null); - Assert.equal(err.friendlyDetailsButtonLabel, null); }); }); add_task(cleanup_between_tests); add_task(function* error_503() { yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/503", "GET").then( () => Assert.ok(false, "Should have rejected"),
--- a/browser/components/loop/test/xpcshell/test_loopservice_restart.js +++ b/browser/components/loop/test/xpcshell/test_loopservice_restart.js @@ -72,16 +72,19 @@ add_task(function test_initialize_with_i (error) => { Assert.equal(MozLoopServiceInternal.pushHandler.registrationPushURL, kEndPointUrl, "Push URL should match"); Assert.equal(Services.prefs.getCharPref(LOOP_FXA_TOKEN_PREF), "", "FXA pref should be cleared if token was invalid"); Assert.equal(Services.prefs.getCharPref(LOOP_FXA_PROFILE_PREF), "", "FXA profile pref should be cleared if token was invalid"); Assert.ok(MozLoopServiceInternal.errors.has("login"), "Initialization error should have been reported to UI"); + Assert.ok(MozLoopServiceInternal.errors.has("login")); + Assert.ok(MozLoopServiceInternal.errors.get("login").friendlyDetailsButtonCallback, + "Check that there is a retry callback"); }); }); add_task(function test_initialize_with_fxa_token() { Services.prefs.setCharPref(LOOP_FXA_PROFILE_PREF, FAKE_FXA_PROFILE); Services.prefs.setCharPref(LOOP_FXA_TOKEN_PREF, FAKE_FXA_TOKEN_DATA); MozLoopService.errors.clear();
--- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -257,16 +257,17 @@ user_pref("dom.mozApps.debug", true); // Enable apps customizations user_pref("dom.apps.customization.enabled", true); // Don't fetch or send directory tiles data from real servers user_pref("browser.newtabpage.directory.source", 'data:application/json,{"testing":1}'); user_pref("browser.newtabpage.directory.ping", ""); // Enable Loop +user_pref("loop.debug.loglevel", "All"); user_pref("loop.enabled", true); user_pref("loop.throttled", false); user_pref("loop.oauth.google.URL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action="); user_pref("loop.oauth.google.getContactsURL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action=contacts"); user_pref("loop.oauth.google.getGroupsURL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action=groups"); user_pref("loop.server", "http://%(server)s/browser/browser/components/loop/test/mochitest/loop_fxa.sjs?"); user_pref("loop.CSP","default-src 'self' about: file: chrome: data: wss://* http://* https://*");