Bug 1047181 - Change the Loop toolbar button when FxA sign in completes. r=MattN

--HG--
extra : rebase_source : e0821ac3fdb8e5840ef241f24c4d9e675388dbf3
This commit is contained in:
Jared Wein 2014-09-18 16:14:44 -04:00
Родитель 43a1089bce
Коммит 497dd662ca
5 изменённых файлов: 101 добавлений и 10 удалений

Просмотреть файл

@ -32,6 +32,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel
}, true); }, true);
}; };
// Used to clear the temporary "login" state from the button.
Services.obs.notifyObservers(null, "loop-status-changed", null);
PanelFrame.showPopup(window, event.target, "loop", null, PanelFrame.showPopup(window, event.target, "loop", null,
"about:looppanel", null, callback); "about:looppanel", null, callback);
}, },
@ -69,13 +72,25 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel
if (topic != "loop-status-changed") { if (topic != "loop-status-changed") {
return; return;
} }
this.updateToolbarState(); this.updateToolbarState(data);
}, },
updateToolbarState: function() { /**
* Updates the toolbar/menu-button state to reflect Loop status.
*
* @param {string} [aReason] Some states are only shown if
* a related reason is provided.
*
* aReason="login": Used after a login is completed
* successfully. This is used so the state can be
* temporarily shown until the next state change.
*/
updateToolbarState: function(aReason = null) {
let state = ""; let state = "";
if (MozLoopService.errors.size) { if (MozLoopService.errors.size) {
state = "error"; state = "error";
} else if (aReason == "login" && MozLoopService.userProfile) {
state = "active";
} else if (MozLoopService.doNotDisturb) { } else if (MozLoopService.doNotDisturb) {
state = "disabled"; state = "disabled";
} }

Просмотреть файл

@ -160,8 +160,8 @@ let MozLoopServiceInternal = {
this.notifyStatusChanged(); this.notifyStatusChanged();
}, },
notifyStatusChanged: function() { notifyStatusChanged: function(aReason = null) {
Services.obs.notifyObservers(null, "loop-status-changed", null); Services.obs.notifyObservers(null, "loop-status-changed", aReason);
}, },
/** /**
@ -1024,7 +1024,7 @@ this.MozLoopService = {
}); });
client.fetchProfile().then(result => { client.fetchProfile().then(result => {
gFxAOAuthProfile = result; gFxAOAuthProfile = result;
MozLoopServiceInternal.notifyStatusChanged(); MozLoopServiceInternal.notifyStatusChanged("login");
}, error => { }, error => {
console.error("Failed to retrieve profile", error); console.error("Failed to retrieve profile", error);
gFxAOAuthProfile = null; gFxAOAuthProfile = null;

Просмотреть файл

@ -219,20 +219,27 @@ add_task(function* basicAuthorizationAndRegistration() {
info("registering"); info("registering");
mockPushHandler.pushUrl = "https://localhost/pushUrl/guest"; mockPushHandler.pushUrl = "https://localhost/pushUrl/guest";
// Notification observed due to the error being cleared upon successful registration.
let statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield MozLoopService.register(mockPushHandler); yield MozLoopService.register(mockPushHandler);
yield statusChangedPromise;
// Normally the same pushUrl would be registered but we change it in the test // Normally the same pushUrl would be registered but we change it in the test
// to be able to check for success on the second registration. // to be able to check for success on the second registration.
mockPushHandler.pushUrl = "https://localhost/pushUrl/fxa"; mockPushHandler.pushUrl = "https://localhost/pushUrl/fxa";
statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true}); yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
yield statusChangedPromise;
let loopDoc = document.getElementById("loop").contentDocument; let loopDoc = document.getElementById("loop").contentDocument;
let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0]; let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0];
is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel when not logged in"); 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"); is(MozLoopService.userProfile, null, "profile should be null before log-in");
let loopButton = document.getElementById("loop-call-button");
is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in");
let tokenData = yield MozLoopService.logInToFxA(); let tokenData = yield MozLoopService.logInToFxA();
yield promiseObserverNotified("loop-status-changed"); yield promiseObserverNotified("loop-status-changed", "login");
ise(tokenData.access_token, "code1_access_token", "Check access_token"); ise(tokenData.access_token, "code1_access_token", "Check access_token");
ise(tokenData.scope, "profile", "Check scope"); ise(tokenData.scope, "profile", "Check scope");
ise(tokenData.token_type, "bearer", "Check token_type"); ise(tokenData.token_type, "bearer", "Check token_type");
@ -240,9 +247,18 @@ add_task(function* basicAuthorizationAndRegistration() {
is(MozLoopService.userProfile.email, "test@example.com", "email should exist in the profile data"); 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(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(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");
let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL); let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa", "Check registered push URL"); ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa", "Check registered push URL");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
yield statusChangedPromise;
is(loopButton.getAttribute("state"), "", "state of loop button should return to empty after panel is opened");
loopPanel.hidePopup();
}); });
add_task(function* loginWithParams401() { add_task(function* loginWithParams401() {

Просмотреть файл

@ -9,19 +9,69 @@
registerCleanupFunction(function*() { registerCleanupFunction(function*() {
MozLoopService.doNotDisturb = false; MozLoopService.doNotDisturb = false;
setInternalLoopGlobal("gFxAOAuthProfile", null);
yield MozLoopServiceInternal.clearError("testing"); yield MozLoopServiceInternal.clearError("testing");
}); });
add_task(function* test_doNotDisturb() { add_task(function* test_doNotDisturb() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopService.doNotDisturb = true; yield MozLoopService.doNotDisturb = true;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state"); Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
yield MozLoopService.doNotDisturb = false; yield MozLoopService.doNotDisturb = false;
Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is not in disabled state"); Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is not in disabled state");
}); });
add_task(function* test_doNotDisturb_with_login() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopService.doNotDisturb = true;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
yield MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
yield loadLoopPanel();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state after opening panel");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
yield MozLoopService.doNotDisturb = false;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", null);
yield MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});
add_task(function* test_error() { add_task(function* test_error() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopServiceInternal.setError("testing", {}); yield MozLoopServiceInternal.setError("testing", {});
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state"); Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
yield MozLoopServiceInternal.clearError("testing"); yield MozLoopServiceInternal.clearError("testing");
Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is not in error state"); Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is not in error state");
}); });
add_task(function* test_error_with_login() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopServiceInternal.setError("testing", {});
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
yield MozLoopServiceInternal.clearError("testing");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", null);
MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});
add_task(function* test_active() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
yield MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
yield loadLoopPanel();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state after opening panel");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
setInternalLoopGlobal("gFxAOAuthProfile", null);
MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});

Просмотреть файл

@ -46,7 +46,11 @@ function promiseGetMozLoopAPI() {
// life of the application. // life of the application.
registerCleanupFunction(function() { registerCleanupFunction(function() {
loopPanel.hidePopup(); loopPanel.hidePopup();
loopPanel.removeChild(document.getElementById(btn.getAttribute("notificationFrameId"))); let frameId = btn.getAttribute("notificationFrameId");
let frame = document.getElementById(frameId);
if (frame) {
loopPanel.removeChild(frame);
}
}); });
return deferred.promise; return deferred.promise;
@ -110,6 +114,11 @@ function resetFxA() {
Services.prefs.clearUserPref(fxASessionPref); Services.prefs.clearUserPref(fxASessionPref);
} }
function setInternalLoopGlobal(aName, aValue) {
let global = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
global[aName] = aValue;
}
function promiseDeletedOAuthParams(baseURL) { function promiseDeletedOAuthParams(baseURL) {
let deferred = Promise.defer(); let deferred = Promise.defer();
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
@ -122,12 +131,13 @@ function promiseDeletedOAuthParams(baseURL) {
return deferred.promise; return deferred.promise;
} }
function promiseObserverNotified(aTopic) { function promiseObserverNotified(aTopic, aExpectedData = null) {
let deferred = Promise.defer(); let deferred = Promise.defer();
Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) { Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) {
Services.obs.removeObserver(onNotification, aTopic); Services.obs.removeObserver(onNotification, aTopic);
deferred.resolve({subject: aSubject, data: aData}); is(aData, aExpectedData, "observer data should match expected data")
}, aTopic, false); deferred.resolve({subject: aSubject, data: aData});
}, aTopic, false);
return deferred.promise; return deferred.promise;
} }