--- a/browser/base/content/browser-loop.js
+++ b/browser/base/content/browser-loop.js
@@ -8,94 +8,48 @@ let LoopUI;
XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI", "resource:///modules/loop/MozLoopAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoopRooms", "resource:///modules/loop/LoopRooms.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopService", "resource:///modules/loop/MozLoopService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/PanelFrame.jsm");
(function() {
LoopUI = {
- /**
- * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton
- * instance for this window.
- */
get toolbarButton() {
delete this.toolbarButton;
return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window);
},
- /**
- * @var {XULElement} panel Getter for the Loop panel element.
- */
get panel() {
delete this.panel;
return this.panel = document.getElementById("loop-notification-panel");
},
/**
- * @var {XULElement|null} browser Getter for the Loop panel browser element.
- * Will be NULL if the panel hasn't loaded yet.
- */
- get browser() {
- let browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe");
- if (browser) {
- delete this.browser;
- this.browser = browser;
- }
- return browser;
- },
-
- /**
- * @var {String|null} selectedTab Getter for the name of the currently selected
- * tab inside the Loop panel. Will be NULL if
- * the panel hasn't loaded yet.
- */
- get selectedTab() {
- if (!this.browser) {
- return null;
- }
-
- let selectedTab = this.browser.contentDocument.querySelector(".tab-view > .selected");
- return selectedTab && selectedTab.getAttribute("data-tab-name");
- },
-
- /**
* @return {Promise}
*/
promiseDocumentVisible(aDocument) {
if (!aDocument.hidden) {
return Promise.resolve();
}
return new Promise((resolve) => {
aDocument.addEventListener("visibilitychange", function onVisibilityChanged() {
aDocument.removeEventListener("visibilitychange", onVisibilityChanged);
resolve();
});
});
},
- /**
- * Toggle between opening or hiding the Loop panel.
- *
- * @param {DOMEvent} [event] Optional event that triggered the call to this
- * function.
- * @param {String} [tabId] Optional name of the tab to select after the panel
- * has opened. Does nothing when the panel is hidden.
- * @return {Promise}
- */
togglePanel: function(event, tabId = null) {
if (this.panel.state == "open") {
- return new Promise(resolve => {
- this.panel.hidePopup();
- resolve();
- });
+ this.panel.hidePopup();
+ } else {
+ this.openCallPanel(event, tabId);
}
-
- return this.openCallPanel(event, tabId);
},
/**
* Opens the panel for Loop and sizes it appropriately.
*
* @param {event} event The event opening the panel, used to anchor
* the panel to the button which triggers it.
* @param {String} [tabId] Identifier of the tab to select when the panel is
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -733,25 +733,23 @@ function injectLoopAPI(targetWindow) {
});
}
},
/**
* Notifies the UITour module that an event occurred that it might be
* interested in.
*
- * @param {String} subject Subject of the notification
- * @param {mixed} [params] Optional parameters, providing more details to
- * the notification subject
+ * @param {String} subject Subject of the notification
*/
notifyUITour: {
enumerable: true,
writable: true,
- value: function(subject, params) {
- UITour.notify(subject, params);
+ value: function(subject) {
+ UITour.notify(subject);
}
},
/**
* Used to record the screen sharing state for a window so that it can
* be reflected on the toolbar button.
*
* @param {String} windowId The id of the conversation window the state
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -20,34 +20,25 @@ loop.panel = (function(_, mozL10n) {
var ButtonGroup = sharedViews.ButtonGroup;
var ContactsList = loop.contacts.ContactsList;
var ContactDetailsForm = loop.contacts.ContactDetailsForm;
var TabView = React.createClass({displayName: "TabView",
propTypes: {
buttonsHidden: React.PropTypes.array,
// The selectedTab prop is used by the UI showcase.
- selectedTab: React.PropTypes.string,
- mozLoop: React.PropTypes.object
+ selectedTab: React.PropTypes.string
},
getDefaultProps: function() {
return {
buttonsHidden: []
};
},
- shouldComponentUpdate: function(nextProps, nextState) {
- var tabChange = this.state.selectedTab !== nextState.selectedTab;
- if (tabChange) {
- this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
- }
- return tabChange;
- },
-
getInitialState: function() {
// XXX Work around props.selectedTab being undefined initially.
// When we don't need to rely on the pref, this can move back to
// getDefaultProps (bug 1100258).
return {
selectedTab: this.props.selectedTab || "rooms"
};
},
@@ -803,17 +794,17 @@ loop.panel = (function(_, mozL10n) {
hideButtons.push("contacts");
}
return (
React.createElement("div", null,
React.createElement(NotificationListView, {notifications: this.props.notifications,
clearOnDocumentHidden: true}),
React.createElement(TabView, {ref: "tabView", selectedTab: this.props.selectedTab,
- buttonsHidden: hideButtons, mozLoop: this.props.mozLoop},
+ buttonsHidden: hideButtons},
React.createElement(Tab, {name: "rooms"},
React.createElement(RoomList, {dispatcher: this.props.dispatcher,
store: this.props.roomStore,
userDisplayName: this._getUserDisplayName()}),
React.createElement(ToSView, null)
),
React.createElement(Tab, {name: "contacts"},
React.createElement(ContactsList, {selectTab: this.selectTab,
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -20,34 +20,25 @@ loop.panel = (function(_, mozL10n) {
var ButtonGroup = sharedViews.ButtonGroup;
var ContactsList = loop.contacts.ContactsList;
var ContactDetailsForm = loop.contacts.ContactDetailsForm;
var TabView = React.createClass({
propTypes: {
buttonsHidden: React.PropTypes.array,
// The selectedTab prop is used by the UI showcase.
- selectedTab: React.PropTypes.string,
- mozLoop: React.PropTypes.object
+ selectedTab: React.PropTypes.string
},
getDefaultProps: function() {
return {
buttonsHidden: []
};
},
- shouldComponentUpdate: function(nextProps, nextState) {
- var tabChange = this.state.selectedTab !== nextState.selectedTab;
- if (tabChange) {
- this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
- }
- return tabChange;
- },
-
getInitialState: function() {
// XXX Work around props.selectedTab being undefined initially.
// When we don't need to rely on the pref, this can move back to
// getDefaultProps (bug 1100258).
return {
selectedTab: this.props.selectedTab || "rooms"
};
},
@@ -803,17 +794,17 @@ loop.panel = (function(_, mozL10n) {
hideButtons.push("contacts");
}
return (
<div>
<NotificationListView notifications={this.props.notifications}
clearOnDocumentHidden={true} />
<TabView ref="tabView" selectedTab={this.props.selectedTab}
- buttonsHidden={hideButtons} mozLoop={this.props.mozLoop}>
+ buttonsHidden={hideButtons}>
<Tab name="rooms">
<RoomList dispatcher={this.props.dispatcher}
store={this.props.roomStore}
userDisplayName={this._getUserDisplayName()}/>
<ToSView />
</Tab>
<Tab name="contacts">
<ContactsList selectTab={this.selectTab}
--- a/browser/components/loop/test/mochitest/browser_toolbarbutton.js
+++ b/browser/components/loop/test/mochitest/browser_toolbarbutton.js
@@ -6,84 +6,37 @@
*/
"use strict";
Components.utils.import("resource://gre/modules/Promise.jsm", this);
const {LoopRoomsInternal} = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {});
Services.prefs.setBoolPref("loop.gettingStarted.seen", true);
-const fxASampleToken = {
- token_type: "bearer",
- access_token: "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",
- scope: "profile"
-};
-
-const fxASampleProfile = {
- email: "test@example.com",
- uid: "abcd1234"
-};
-
registerCleanupFunction(function*() {
MozLoopService.doNotDisturb = false;
MozLoopServiceInternal.fxAOAuthProfile = null;
yield MozLoopServiceInternal.clearError("testing");
Services.prefs.clearUserPref("loop.gettingStarted.seen");
});
-add_task(function* test_LoopUI_getters() {
- Assert.ok(LoopUI.panel, "LoopUI panel element should be set");
- Assert.strictEqual(LoopUI.browser, null, "Browser element should not be there yet");
- Assert.strictEqual(LoopUI.selectedTab, null, "No tab should be selected yet");
-
- // Load and show the Loop panel for the very first time this session.
- yield loadLoopPanel();
- Assert.ok(LoopUI.browser, "Browser element should be there");
- Assert.strictEqual(LoopUI.selectedTab, "rooms", "Initially the rooms tab should be selected");
-
- // Hide the panel.
- yield LoopUI.togglePanel();
- Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should still be selected");
-
- // Make sure the contacts tab shows up by simulating a login.
- MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken;
- MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
- yield MozLoopServiceInternal.notifyStatusChanged("login");
-
- // Programmatically select the contacts tab.
- yield LoopUI.togglePanel(null, "contacts");
- Assert.strictEqual(LoopUI.selectedTab, "contacts", "Contacts tab should be selected now");
-
- // Switch back to the rooms tab.
- yield LoopUI.openCallPanel(null, "rooms");
- Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should be selected now");
-
- // Hide the panel.
- yield LoopUI.togglePanel();
-
- // Logout to prevent interfering with the tests after this one.
- MozLoopServiceInternal.fxAOAuthTokenData =
- MozLoopServiceInternal.fxAOAuthProfile = null;
- yield MozLoopServiceInternal.notifyStatusChanged();
-});
-
add_task(function* test_doNotDisturb() {
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");
yield MozLoopService.doNotDisturb = false;
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");
- MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken;
- MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
+ MozLoopServiceInternal.fxAOAuthTokenData = {token_type:"bearer",access_token:"1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",scope:"profile"};
+ MozLoopServiceInternal.fxAOAuthProfile = {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");
LoopUI.panel.hidePopup();
yield MozLoopService.doNotDisturb = false;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
MozLoopServiceInternal.fxAOAuthTokenData = null;
@@ -98,30 +51,30 @@ add_task(function* test_error() {
yield MozLoopServiceInternal.clearError("testing");
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");
- MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
+ MozLoopServiceInternal.fxAOAuthProfile = {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");
MozLoopServiceInternal.fxAOAuthProfile = 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");
- MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken;
- MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
+ MozLoopServiceInternal.fxAOAuthTokenData = {token_type:"bearer",access_token:"1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",scope:"profile"};
+ MozLoopServiceInternal.fxAOAuthProfile = {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");
LoopUI.panel.hidePopup();
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -134,33 +134,33 @@ this.UITour = {
["loop", {
allowAdd: true,
query: "#loop-button",
widgetName: "loop-button",
}],
["loop-newRoom", {
infoPanelPosition: "leftcenter topright",
query: (aDocument) => {
- let loopUI = aDocument.defaultView.LoopUI;
- if (loopUI.selectedTab != "rooms") {
+ let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe");
+ if (!loopBrowser) {
return null;
}
// Use the parentElement full-width container of the button so our arrow
// doesn't overlap the panel contents much.
- return loopUI.browser.contentDocument.querySelector(".new-room-button").parentElement;
+ return loopBrowser.contentDocument.querySelector(".new-room-button").parentElement;
},
}],
["loop-roomList", {
infoPanelPosition: "leftcenter topright",
query: (aDocument) => {
- let loopUI = aDocument.defaultView.LoopUI;
- if (loopUI.selectedTab != "rooms") {
+ let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe");
+ if (!loopBrowser) {
return null;
}
- return loopUI.browser.contentDocument.querySelector(".room-list");
+ return loopBrowser.contentDocument.querySelector(".room-list");
},
}],
["loop-selectedRoomButtons", {
infoPanelOffsetY: -20,
infoPanelPosition: "start_after",
query: (aDocument) => {
let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]");
@@ -173,17 +173,17 @@ this.UITour = {
// But anchor on the <browser> in the chatbox so the panel doesn't jump to undefined
// positions when the copy/email buttons disappear e.g. when the feedback form opens or
// somebody else joins the room.
return chatbox.content;
},
}],
["loop-signInUpLink", {
query: (aDocument) => {
- let loopBrowser = aDocument.defaultView.LoopUI.browser;
+ let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe");
if (!loopBrowser) {
return null;
}
return loopBrowser.contentDocument.querySelector(".signin-link");
},
}],
["privateWindow", {query: "#privatebrowsing-button"}],
["quit", {query: "#PanelUI-quit"}],
--- a/browser/components/uitour/test/browser_UITour_loop.js
+++ b/browser/components/uitour/test/browser_UITour_loop.js
@@ -6,17 +6,16 @@
let gTestTab;
let gContentAPI;
let gContentWindow;
let loopButton;
let loopPanel = document.getElementById("loop-notification-panel");
Components.utils.import("resource:///modules/UITour.jsm");
const { LoopRooms } = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {});
-const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
function test() {
UITourTest();
}
function runOffline(fun) {
return (done) => {
Services.io.offline = true;
@@ -177,63 +176,16 @@ let tests = [
yield Promise.all(hiddenPromises);
isnot(infoPanel.state, "open", "Info panel should have automatically hid");
isnot(highlightPanel.state, "open", "Highlight panel should have automatically hid");
done();
}), "Info panel should be anchored to the new room button");
});
});
},
- taskify(function* test_panelTabChangeNotifications() {
- // First make sure the Loop panel looks like we're logged in to have more than
- // just one tab to switch to.
- const fxASampleToken = {
- token_type: "bearer",
- access_token: "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",
- scope: "profile"
- };
- const fxASampleProfile = {
- email: "test@example.com",
- uid: "abcd1234"
- };
- MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken;
- MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
- yield MozLoopServiceInternal.notifyStatusChanged("login");
-
- // Show the Loop menu.
- yield showMenuPromise("loop");
-
- // Listen for and test the notifications that will arrive from now on.
- let tabChangePromise = new Promise(resolve => {
- gContentAPI.observe((event, params) => {
- is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification");
- is(params, "contacts", "Check the tab name param");
-
- gContentAPI.observe((event, params) => {
- is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification");
- is(params, "rooms", "Check the tab name param");
-
- gContentAPI.observe((event, params) => {
- ok(false, "No more notifications should have arrived");
- });
- resolve();
- });
- });
- });
-
- // Switch to the contacts tab.
- yield window.LoopUI.openCallPanel(null, "contacts");
-
- // Logout. The panel tab will switch back to 'rooms'.
- MozLoopServiceInternal.fxAOAuthTokenData =
- MozLoopServiceInternal.fxAOAuthProfile = null;
- yield MozLoopServiceInternal.notifyStatusChanged();
-
- yield tabChangePromise;
- }),
runOffline(function test_notifyLoopChatWindowOpenedClosed(done) {
gContentAPI.observe((event, params) => {
is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification");
gContentAPI.observe((event, params) => {
is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
gContentAPI.observe((event, params) => {
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
gContentAPI.observe((event, params) => {