diff --git a/browser/components/loop/LoopCalls.jsm b/browser/components/loop/LoopCalls.jsm index fb9c1f77d89..5e1a63a69e7 100644 --- a/browser/components/loop/LoopCalls.jsm +++ b/browser/components/loop/LoopCalls.jsm @@ -203,7 +203,7 @@ let LoopCallsInternal = { // Make the call to get the GUEST session regardless of whether the FXA // request fails. - if (channelID == LoopCalls.channelIDs.FxA && MozLoopService.userProfile) { + if (channelID == MozLoopService.channelIDs.callsFxA && MozLoopService.userProfile) { this._getCalls(LOOP_SESSION_TYPE.FXA, version); } else { this._getCalls(LOOP_SESSION_TYPE.GUEST, version); @@ -320,12 +320,6 @@ Object.freeze(LoopCallsInternal); * Public API */ this.LoopCalls = { - // Channel ids that will be registered with the PushServer for notifications - channelIDs: { - FxA: "25389583-921f-4169-a426-a4673658944b", - Guest: "801f754b-686b-43ec-bd83-1419bbf58388", - }, - /** * Callback from MozLoopPushHandler - A push notification has been received from * the server. diff --git a/browser/components/loop/LoopRooms.jsm b/browser/components/loop/LoopRooms.jsm index fad9d1bbce2..c4a1cf023f0 100644 --- a/browser/components/loop/LoopRooms.jsm +++ b/browser/components/loop/LoopRooms.jsm @@ -5,21 +5,166 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; +Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); -this.EXPORTED_SYMBOLS = ["LoopRooms"]; +XPCOMUtils.defineLazyModuleGetter(this, "MozLoopService", + "resource:///modules/loop/MozLoopService.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "LOOP_SESSION_TYPE", + "resource:///modules/loop/MozLoopService.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", + "resource:///modules/loop/MozLoopPushHandler.jsm"); -/** - * Public Loop Rooms API - */ -this.LoopRooms = Object.freeze({ -// Channel ids that will be registered with the PushServer for notifications - channelIDs: { - FxA: "6add272a-d316-477c-8335-f00f73dfde71", - Guest: "19d3f799-a8f3-4328-9822-b7cd02765832", +// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref. +XPCOMUtils.defineLazyGetter(this, "log", () => { + let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI; + let consoleOptions = { + maxLogLevel: Services.prefs.getCharPref(PREF_LOG_LEVEL).toLowerCase(), + prefix: "Loop", + }; + return new ConsoleAPI(consoleOptions); +}); + +this.EXPORTED_SYMBOLS = ["LoopRooms", "roomsPushNotification"]; + +let gRoomsListFetched = false; +let gRooms = new Map(); + + /** + * Callback used to indicate changes to rooms data on the LoopServer. + * + * @param {Object} version Version number assigned to this change set. + * @param {Object} channelID Notification channel identifier. + * + */ +const roomsPushNotification = function(version, channelID) { + return LoopRoomsInternal.onNotification(version, channelID); + }; + +let LoopRoomsInternal = { + getAll: function(callback) { + Task.spawn(function*() { + yield MozLoopService.register(); + + if (gRoomsListFetched) { + callback(null, [...gRooms.values()]); + return; + } + // Fetch the rooms from the server. + let sessionType = MozLoopService.userProfile ? LOOP_SESSION_TYPE.FXA : + LOOP_SESSION_TYPE.GUEST; + let rooms = yield this.requestRoomList(sessionType); + // Add each room to our in-memory Map using a locally unique + // identifier. + for (let room of rooms) { + let id = MozLoopService.generateLocalID(); + room.localRoomID = id; + // Next, request the detailed information for each room. + // If the request fails the room data will not be added to the map. + try { + let details = yield this.requestRoomDetails(room.roomToken, sessionType); + for (let attr in details) { + room[attr] = details[attr] + } + gRooms.set(id, room); + } + catch (error) {log.warn("failed GETing room details for roomToken = " + room.roomToken + ": ", error)} + } + callback(null, [...gRooms.values()]); + return; + }.bind(this)).catch((error) => {log.error("getAll error:", error); + callback(error)}); + return; }, + getRoomData: function(roomID, callback) { + if (gRooms.has(roomID)) { + callback(null, gRooms.get(roomID)); + } else { + callback(new Error("Room data not found or not fetched yet for room with ID " + roomID)); + } + return; + }, + + /** + * Request list of all rooms associated with this account. + * + * @param {String} sessionType Indicates which hawkRequest endpoint to use. + * + * @returns {Promise} room list + */ + requestRoomList: function(sessionType) { + return MozLoopService.hawkRequest(sessionType, "/rooms", "GET") + .then(response => { + let roomsList = JSON.parse(response.body); + if (!Array.isArray(roomsList)) { + // Force a reject in the returned promise. + // To be caught by the caller using the returned Promise. + throw new Error("Missing array of rooms in response."); + } + return roomsList; + }); + }, + + /** + * Request information about a specific room from the server. + * + * @param {Object} token Room identifier returned from the LoopServer. + * @param {String} sessionType Indicates which hawkRequest endpoint to use. + * + * @returns {Promise} room details + */ + requestRoomDetails: function(token, sessionType) { + return MozLoopService.hawkRequest(sessionType, "/rooms/" + token, "GET") + .then(response => JSON.parse(response.body)); + }, + + /** + * Callback used to indicate changes to rooms data on the LoopServer. + * + * @param {Object} version Version number assigned to this change set. + * @param {Object} channelID Notification channel identifier. + * + */ onNotification: function(version, channelID) { return; }, -}); +}; +Object.freeze(LoopRoomsInternal); + +/** + * The LoopRooms class. + * + * Each method that is a member of this class requires the last argument to be a + * callback Function. MozLoopAPI will cause things to break if this invariant is + * violated. You'll notice this as well in the documentation for each method. + */ +this.LoopRooms = { + /** + * Fetch a list of rooms that the currently registered user is a member of. + * + * @param {Function} callback Function that will be invoked once the operation + * finished. The first argument passed will be an + * `Error` object or `null`. The second argument will + * be the list of rooms, if it was fetched successfully. + */ + getAll: function(callback) { + return LoopRoomsInternal.getAll(callback); + }, + + /** + * Return the current stored version of the data for the indicated room. + * + * @param {String} roomID Local room identifier + * @param {Function} callback Function that will be invoked once the operation + * finished. The first argument passed will be an + * `Error` object or `null`. The second argument will + * be the list of rooms, if it was fetched successfully. + */ + getRoomData: function(roomID, callback) { + return LoopRoomsInternal.getRoomData(roomID, callback); + }, +}; +Object.freeze(LoopRooms); + diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index ef355247553..71a799ba524 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -11,6 +11,8 @@ Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource:///modules/loop/LoopCalls.jsm"); Cu.import("resource:///modules/loop/MozLoopService.jsm"); +Cu.import("resource:///modules/loop/LoopRooms.jsm"); +Cu.import("resource:///modules/loop/LoopContacts.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "LoopContacts", "resource:///modules/loop/LoopContacts.jsm"); @@ -124,6 +126,7 @@ function injectLoopAPI(targetWindow) { let ringerStopper; let appVersionInfo; let contactsAPI; + let roomsAPI; let api = { /** @@ -245,6 +248,21 @@ function injectLoopAPI(targetWindow) { } }, + /** + * Returns the rooms API. + * + * @returns {Object} The rooms API object + */ + rooms: { + enumerable: true, + get: function() { + if (roomsAPI) { + return roomsAPI; + } + return roomsAPI = injectObjectAPI(LoopRooms, targetWindow); + } + }, + /** * Import a list of (new) contacts from an external data source. * diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index 79d4c07dd6c..15f55665117 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -71,6 +71,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "LoopCalls", XPCOMUtils.defineLazyModuleGetter(this, "LoopRooms", "resource:///modules/loop/LoopRooms.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "roomsPushNotification", + "resource:///modules/loop/LoopRooms.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", "resource:///modules/loop/MozLoopPushHandler.jsm"); @@ -342,17 +345,18 @@ let MozLoopServiceInternal = { let options = mockWebSocket ? {mockWebSocket: mockWebSocket} : {}; gPushHandler.initialize(options); - let callsRegGuest = registerForNotification(LoopCalls.channelIDs.Guest, + let callsRegGuest = registerForNotification(MozLoopService.channelIDs.callsGuest, LoopCalls.onNotification); - - let roomsRegGuest = registerForNotification(LoopRooms.channelIDs.Guest, - LoopRooms.onNotification); - - let callsRegFxA = registerForNotification(LoopCalls.channelIDs.FxA, + + let roomsRegGuest = registerForNotification(MozLoopService.channelIDs.roomsGuest, + roomsPushNotification); + + let callsRegFxA = registerForNotification(MozLoopService.channelIDs.callsFxA, LoopCalls.onNotification); + + let roomsRegFxA = registerForNotification(MozLoopService.channelIDs.roomsFxA, + roomsPushNotification); - let roomsRegFxA = registerForNotification(LoopRooms.channelIDs.FxA, - LoopRooms.onNotification); Promise.all([callsRegGuest, roomsRegGuest, callsRegFxA, roomsRegFxA]) .then((pushUrls) => { return this.registerWithLoopServer(LOOP_SESSION_TYPE.GUEST, @@ -880,8 +884,8 @@ let gInitializeTimerFunc = (deferredInitialization, mockPushHandler, mockWebSock let registeredPromise = MozLoopServiceInternal.registerWithLoopServer( LOOP_SESSION_TYPE.FXA, { - calls: gPushHandler.registeredChannels[LoopCalls.channelIDs.FxA], - rooms: gPushHandler.registeredChannels[LoopRooms.channelIDs.FxA] + calls: gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA], + rooms: gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA] }); registeredPromise.then(() => { deferredInitialization.resolve("initialized to logged-in status"); @@ -905,6 +909,17 @@ let gInitializeTimerFunc = (deferredInitialization, mockPushHandler, mockWebSock this.MozLoopService = { _DNSService: gDNSService, + get channelIDs() { + // Channel ids that will be registered with the PushServer for notifications + return { + callsFxA: "25389583-921f-4169-a426-a4673658944b", + callsGuest: "801f754b-686b-43ec-bd83-1419bbf58388", + roomsFxA: "6add272a-d316-477c-8335-f00f73dfde71", + roomsGuest: "19d3f799-a8f3-4328-9822-b7cd02765832", + }; + }, + + set initializeTimerFunc(value) { gInitializeTimerFunc = value; }, @@ -1127,6 +1142,21 @@ this.MozLoopService = { return uuidgen.generateUUID().toString(); }, + /** + * Returns a new non-global id + * + * @param {Function} notUnique [optional] This function will be + * applied to test the generated id for uniqueness + * in the callers domain. + */ + generateLocalID: function(notUnique = ((id) => {return false})) { + do { + var id = Date.now().toString(36) + Math.floor((Math.random() * 4096)).toString(16); + } + while (notUnique(id)); + return id; + }, + /** * Retrieves MozLoopService "do not disturb" value. * @@ -1265,8 +1295,8 @@ this.MozLoopService = { return tokenData; }).then(tokenData => { return gRegisteredDeferred.promise.then(Task.async(function*() { - let callsUrl = gPushHandler.registeredChannels[LoopCalls.channelIDs.FxA], - roomsUrl = gPushHandler.registeredChannels[LoopRooms.channelIDs.FxA]; + let callsUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA], + roomsUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA]; if (callsUrl && roomsUrl) { yield MozLoopServiceInternal.registerWithLoopServer( LOOP_SESSION_TYPE.FXA, {calls: callsUrl, rooms: roomsUrl}); @@ -1314,8 +1344,8 @@ this.MozLoopService = { log.debug("logOutFromFxA"); let callsPushUrl, roomsPushUrl; if (gPushHandler) { - callsPushUrl = gPushHandler.registeredChannels[LoopCalls.channelIDs.FxA]; - roomsPushUrl = gPushHandler.registeredChannels[LoopRooms.channelIDs.FxA]; + callsPushUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA]; + roomsPushUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA]; } try { if (callsPushUrl) { diff --git a/browser/components/loop/test/mochitest/browser_fxa_login.js b/browser/components/loop/test/mochitest/browser_fxa_login.js index a2e137a243c..a0d66c9d34c 100644 --- a/browser/components/loop/test/mochitest/browser_fxa_login.js +++ b/browser/components/loop/test/mochitest/browser_fxa_login.js @@ -256,8 +256,8 @@ add_task(function* basicAuthorizationAndRegistration() { // 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. - mockPushHandler.registeredChannels[LoopCalls.channelIDs.FxA] = "https://localhost/pushUrl/fxa-calls"; - mockPushHandler.registeredChannels[LoopRooms.channelIDs.FxA] = "https://localhost/pushUrl/fxa-rooms"; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = "https://localhost/pushUrl/fxa-calls"; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA] = "https://localhost/pushUrl/fxa-rooms"; statusChangedPromise = promiseObserverNotified("loop-status-changed"); yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true}); @@ -333,8 +333,8 @@ add_task(function* loginWithParams401() { add_task(function* logoutWithIncorrectPushURL() { yield resetFxA(); let pushURL = "http://www.example.com/"; - mockPushHandler.registeredChannels[LoopCalls.channelIDs.FxA] = pushURL; - mockPushHandler.registeredChannels[LoopRooms.channelIDs.FxA] = pushURL; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = pushURL; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA] = pushURL; // Create a fake FxA hawk session token const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA); @@ -343,7 +343,7 @@ add_task(function* logoutWithIncorrectPushURL() { yield MozLoopServiceInternal.registerWithLoopServer(LOOP_SESSION_TYPE.FXA, {calls: pushURL}); let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL); ise(registrationResponse.response.simplePushURLs.calls, pushURL, "Check registered push URL"); - mockPushHandler.registeredChannels[LoopCalls.channelIDs.FxA] = "http://www.example.com/invalid"; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = "http://www.example.com/invalid"; let caught = false; yield MozLoopService.logOutFromFxA().catch((error) => { caught = true; @@ -357,7 +357,7 @@ add_task(function* logoutWithIncorrectPushURL() { add_task(function* logoutWithNoPushURL() { yield resetFxA(); let pushURL = "http://www.example.com/"; - mockPushHandler.registeredChannels[LoopCalls.channelIDs.FxA] = pushURL; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = pushURL; // Create a fake FxA hawk session token const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA); @@ -366,8 +366,8 @@ add_task(function* logoutWithNoPushURL() { yield MozLoopServiceInternal.registerWithLoopServer(LOOP_SESSION_TYPE.FXA, {calls: pushURL}); let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL); ise(registrationResponse.response.simplePushURLs.calls, pushURL, "Check registered push URL"); - mockPushHandler.registeredChannels[LoopCalls.channelIDs.FxA] = null; - mockPushHandler.registeredChannels[LoopRooms.channelIDs.FxA] = null; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = null; + mockPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA] = null; yield MozLoopService.logOutFromFxA(); checkLoggedOutState(); registrationResponse = yield promiseOAuthGetRegistration(BASE_URL); diff --git a/browser/components/loop/test/xpcshell/head.js b/browser/components/loop/test/xpcshell/head.js index d51f2638b2d..6490c03d427 100644 --- a/browser/components/loop/test/xpcshell/head.js +++ b/browser/components/loop/test/xpcshell/head.js @@ -10,6 +10,7 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource:///modules/loop/MozLoopService.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource:///modules/loop/LoopCalls.jsm"); +Cu.import("resource:///modules/loop/LoopRooms.jsm"); const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", diff --git a/browser/components/loop/test/xpcshell/test_loopservice_busy.js b/browser/components/loop/test/xpcshell/test_loopservice_busy.js index 9d331a5090d..604422e6b85 100644 --- a/browser/components/loop/test/xpcshell/test_loopservice_busy.js +++ b/browser/components/loop/test/xpcshell/test_loopservice_busy.js @@ -35,7 +35,7 @@ add_test(function test_busy_2guest_calls() { opened++; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); waitForCondition(() => {return actionReceived && opened > 0}).then(() => { do_check_true(opened === 1, "should open only one chat window"); @@ -58,8 +58,8 @@ add_test(function test_busy_1fxa_1guest_calls() { opened++; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.FxA); - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); waitForCondition(() => {return actionReceived && opened > 0}).then(() => { do_check_true(opened === 1, "should open only one chat window"); @@ -82,7 +82,7 @@ add_test(function test_busy_2fxa_calls() { opened++; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.FxA); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA); waitForCondition(() => {return actionReceived && opened > 0}).then(() => { do_check_true(opened === 1, "should open only one chat window"); @@ -105,8 +105,8 @@ add_test(function test_busy_1guest_1fxa_calls() { opened++; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); - mockPushHandler.notify(1, LoopCalls.channelIDs.FxA); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA); waitForCondition(() => {return actionReceived && opened > 0}).then(() => { do_check_true(opened === 1, "should open only one chat window"); diff --git a/browser/components/loop/test/xpcshell/test_loopservice_dnd.js b/browser/components/loop/test/xpcshell/test_loopservice_dnd.js index f8783355342..8479736713e 100644 --- a/browser/components/loop/test/xpcshell/test_loopservice_dnd.js +++ b/browser/components/loop/test/xpcshell/test_loopservice_dnd.js @@ -37,7 +37,7 @@ add_test(function test_do_not_disturb_disabled_should_open_chat_window() { opened = true; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); waitForCondition(function() opened).then(() => { run_next_test(); @@ -56,7 +56,7 @@ add_test(function test_do_not_disturb_enabled_shouldnt_open_chat_window() { opened = true; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); do_timeout(500, function() { do_check_false(opened, "should not open a chat window"); diff --git a/browser/components/loop/test/xpcshell/test_loopservice_notification.js b/browser/components/loop/test/xpcshell/test_loopservice_notification.js index 07d6148551b..25795a231f1 100644 --- a/browser/components/loop/test/xpcshell/test_loopservice_notification.js +++ b/browser/components/loop/test/xpcshell/test_loopservice_notification.js @@ -16,7 +16,7 @@ add_test(function test_openChatWindow_on_notification() { opened = true; }; - mockPushHandler.notify(1, LoopCalls.channelIDs.Guest); + mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest); waitForCondition(function() opened).then(() => { do_check_true(opened, "should open a chat window"); diff --git a/browser/components/loop/test/xpcshell/test_rooms_getdata.js b/browser/components/loop/test/xpcshell/test_rooms_getdata.js new file mode 100644 index 00000000000..5c806e16db2 --- /dev/null +++ b/browser/components/loop/test/xpcshell/test_rooms_getdata.js @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Cu.import("resource://services-common/utils.js"); + +XPCOMUtils.defineLazyModuleGetter(this, "Chat", + "resource:///modules/Chat.jsm"); +let hasTheseProps = function(a, b) { + for (let prop in a) { + if (a[prop] != b[prop]) { + do_print("hasTheseProps fail: prop = " + prop); + return false; + } + } + return true; +} + +let openChatOrig = Chat.open; + +add_test(function test_getAllRooms() { + + let roomList = [ + { roomToken: "_nxD4V4FflQ", + roomName: "First Room Name", + roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ", + maxSize: 2, + currSize: 0, + ctime: 1405517546 }, + { roomToken: "QzBbvGmIZWU", + roomName: "Second Room Name", + roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU", + maxSize: 2, + currSize: 0, + ctime: 140551741 }, + { roomToken: "3jKS_Els9IU", + roomName: "Third Room Name", + roomUrl: "http://localhost:3000/rooms/3jKS_Els9IU", + maxSize: 3, + clientMaxSize: 2, + currSize: 1, + ctime: 1405518241 } + ] + + let roomDetail = { + roomName: "First Room Name", + roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ", + roomOwner: "Alexis", + maxSize: 2, + clientMaxSize: 2, + creationTime: 1405517546, + expiresAt: 1405534180, + participants: [ + { displayName: "Alexis", account: "alexis@example.com", roomConnectionId: "2a1787a6-4a73-43b5-ae3e-906ec1e763cb" }, + { displayName: "Adam", roomConnectionId: "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7" } + ] + } + + loopServer.registerPathHandler("/rooms", (request, response) => { + response.setStatusLine(null, 200, "OK"); + response.write(JSON.stringify(roomList)); + response.processAsync(); + response.finish(); + }); + + let returnRoomDetails = function(response, roomName) { + roomDetail.roomName = roomName; + response.setStatusLine(null, 200, "OK"); + response.write(JSON.stringify(roomDetail)); + response.processAsync(); + response.finish(); + } + + loopServer.registerPathHandler("/rooms/_nxD4V4FflQ", (request, response) => { + returnRoomDetails(response, "First Room Name"); + }); + + loopServer.registerPathHandler("/rooms/QzBbvGmIZWU", (request, response) => { + returnRoomDetails(response, "Second Room Name"); + }); + + loopServer.registerPathHandler("/rooms/3jKS_Els9IU", (request, response) => { + returnRoomDetails(response, "Third Room Name"); + }); + + MozLoopService.register(mockPushHandler).then(() => { + + LoopRooms.getAll((error, rooms) => { + do_check_false(error); + do_check_true(rooms); + do_check_eq(rooms.length, 3); + do_check_eq(rooms[0].roomName, "First Room Name"); + do_check_eq(rooms[1].roomName, "Second Room Name"); + do_check_eq(rooms[2].roomName, "Third Room Name"); + + let room = rooms[0]; + do_check_true(room.localRoomID); + do_check_true(hasTheseProps(roomList[0], room)); + delete roomDetail.roomName; + delete room.participants; + delete roomDetail.participants; + do_check_true(hasTheseProps(roomDetail, room)); + + LoopRooms.getRoomData(room.localRoomID, (error, roomData) => { + do_check_false(error); + do_check_true(hasTheseProps(room, roomData)); + + run_next_test(); + }); + }); + }); +}); + +function run_test() +{ + setupFakeLoopServer(); + mockPushHandler.registrationPushURL = kEndPointUrl; + + loopServer.registerPathHandler("/registration", (request, response) => { + response.setStatusLine(null, 200, "OK"); + response.processAsync(); + response.finish(); + }); + + do_register_cleanup(function() { + // Revert original Chat.open implementation + Chat.open = openChatOrig; + }); + + run_next_test(); +} diff --git a/browser/components/loop/test/xpcshell/xpcshell.ini b/browser/components/loop/test/xpcshell/xpcshell.ini index 9c2b25c5328..b2a765dc521 100644 --- a/browser/components/loop/test/xpcshell/xpcshell.ini +++ b/browser/components/loop/test/xpcshell/xpcshell.ini @@ -21,3 +21,4 @@ skip-if = toolkit == 'gonk' [test_loopservice_token_send.js] [test_loopservice_token_validation.js] [test_loopservice_busy.js] +[test_rooms_getdata.js]