Backed out changeset b0573ebe7b3a / bug 1151862 for incorrectly including two different bugs in one commit.

This commit is contained in:
Mark Banner 2015-05-06 12:37:23 +01:00
Родитель 5928e07946
Коммит 284a13a8d7
8 изменённых файлов: 14 добавлений и 622 удалений

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

@ -7,13 +7,11 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
return new EventEmitter();
@ -21,9 +19,6 @@ XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() {
return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties');
});
XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache",
"resource:///modules/loop/LoopRoomsCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
"resource:///modules/loop/utils.js", "utils");
XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
@ -46,8 +41,6 @@ const roomsPushNotification = function(version, channelID) {
let gDirty = true;
// Global variable that keeps track of the currently used account.
let gCurrentUser = null;
// Global variable that keeps track of the room cache.
let gRoomsCache = null;
/**
* Extend a `target` object with the properties defined in `source`.
@ -130,13 +123,6 @@ let LoopRoomsInternal = {
*/
rooms: new Map(),
get roomsCache() {
if (!gRoomsCache) {
gRoomsCache = new LoopRoomsCache();
}
return gRoomsCache;
},
/**
* @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'.
*/
@ -289,40 +275,12 @@ let LoopRoomsInternal = {
throw new Error("Missing wrappedKey");
}
let savedRoomKey = yield this.roomsCache.getKey(this.sessionType, roomData.roomToken);
let fallback = false;
let key;
try {
key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);
} catch (error) {
// If we don't have a key saved, then we can't do anything.
if (!savedRoomKey) {
throw error;
}
// We failed to decrypt the room key, so has our FxA key changed?
// If so, we fall-back to the saved room key.
key = savedRoomKey;
fallback = true;
}
// Bug 1152761 will cause us to additionally store keys locally. We'll
// need to add some code for recovery in case decryption fails.
let key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);
let decryptedData = yield loopCrypto.decryptBytes(key, roomData.context.value);
if (fallback) {
// Fallback decryption succeeded, so we need to re-encrypt the room key and
// save the data back again.
// XXX Bug 1152764 will implement this or make it a separate bug.
} else if (!savedRoomKey || key != savedRoomKey) {
// Decryption succeeded, but we don't have the right key saved.
try {
yield this.roomsCache.setKey(this.sessionType, roomData.roomToken, key);
}
catch (error) {
MozLoopService.log.error("Failed to save room key:", error);
}
}
roomData.roomKey = key;
roomData.decryptedContext = JSON.parse(decryptedData);
@ -379,7 +337,7 @@ let LoopRoomsInternal = {
this.saveAndNotifyUpdate(roomData, isUpdate);
} catch (error) {
MozLoopService.log.error("Failed to decrypt room data: ", error);
MozLoopService.log.error("Failed to decrypt room data: " + error);
// Do what we can to save the room data.
room.decryptedContext = {};
this.saveAndNotifyUpdate(room, isUpdate);
@ -532,9 +490,6 @@ let LoopRoomsInternal = {
this.setGuestCreatedRoom(true);
}
// Now we've got the room token, we can save the key to disk.
yield this.roomsCache.setKey(this.sessionType, room.roomToken, room.roomKey);
eventEmitter.emit("add", room);
callback(null, room);
}.bind(this)).catch(callback);
@ -745,10 +700,6 @@ let LoopRoomsInternal = {
sendData = {
roomName: newRoomName
};
} else {
// This might be an upgrade to encrypted rename, so store the key
// just in case.
yield this.roomsCache.setKey(this.sessionType, all.roomToken, all.roomKey);
}
let response = yield MozLoopService.hawkRequest(this.sessionType,
@ -776,12 +727,8 @@ let LoopRoomsInternal = {
return;
}
let oldDirty = gDirty;
gDirty = true;
// If we were already dirty, then get the full set of rooms. For example,
// we'd already be dirty if we had started up but not got the list of rooms
// yet.
this.getAll(oldDirty ? null : version, () => {});
this.getAll(version, () => {});
},
/**

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

@ -1,159 +0,0 @@
/* 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/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {MozLoopService, LOOP_SESSION_TYPE} =
Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
this.EXPORTED_SYMBOLS = ["LoopRoomsCache"];
const LOOP_ROOMS_CACHE_FILENAME = "loopRoomsCache.json";
/**
* RoomsCache is a cache for saving simple rooms data to the disk in case we
* need it for back-up purposes, e.g. recording room keys for FxA if the user
* changes their password.
*
* The format of the data is:
*
* {
* <sessionType>: {
* <roomToken>: {
* "key": <roomKey>
* }
* }
* }
*
* It is intended to try and keep the data forward and backwards compatible in
* a reasonable manner, hence why the structure is more complex than it needs
* to be to store tokens and keys.
*
* @param {Object} options The options for the RoomsCache, containing:
* - {String} baseDir The base directory in which to save the file.
* - {String} filename The filename for the cache file.
*/
function LoopRoomsCache(options) {
options = options || {};
this.baseDir = options.baseDir || OS.Constants.Path.profileDir;
this.path = OS.Path.join(
this.baseDir,
options.filename || LOOP_ROOMS_CACHE_FILENAME
);
this._cache = null;
}
LoopRoomsCache.prototype = {
/**
* Updates the local copy of the cache and saves it to disk.
*
* @param {Object} contents An object to be saved in json format.
* @return {Promise} A promise that is resolved once the save is complete.
*/
_setCache: function(contents) {
this._cache = contents;
return OS.File.makeDir(this.baseDir, {ignoreExisting: true}).then(() => {
return CommonUtils.writeJSON(contents, this.path);
});
},
/**
* Returns the local copy of the cache if there is one, otherwise it reads
* it from the disk.
*
* @return {Promise} A promise that is resolved once the read is complete.
*/
_getCache: Task.async(function* () {
if (this._cache) {
return this._cache;
}
try {
return (this._cache = yield CommonUtils.readJSON(this.path));
} catch(error) {
// This is really complex due to OSFile's error handling, see bug 1160109.
if ((OS.Constants.libc && error.unixErrno != OS.Constants.libc.ENOENT) ||
(OS.Constants.Win && error.winLastError != OS.Constants.Win.ERROR_FILE_NOT_FOUND)) {
MozLoopService.log.debug("Error reading the cache:", error);
}
return (this._cache = {});
}
}),
/**
* Function for testability purposes. Clears the cache.
*
* @return {Promise} A promise that is resolved once the clear is complete.
*/
clear: function() {
this._cache = null;
return OS.File.remove(this.path);
},
/**
* Gets a room key from the cache.
*
* @param {LOOP_SESSION_TYPE} sessionType The session type for the room.
* @param {String} roomToken The token for the room.
* @return {Promise} A promise that is resolved when the data has been read
* with the value of the key, or null if it isn't present.
*/
getKey: Task.async(function* (sessionType, roomToken) {
if (sessionType != LOOP_SESSION_TYPE.FXA) {
return null;
}
let sessionData = (yield this._getCache())[sessionType];
if (!sessionData || !sessionData[roomToken]) {
return null;
}
return sessionData[roomToken].key;
}),
/**
* Stores a room key into the cache. Note, if the key has not changed,
* the store will not be re-written.
*
* @param {LOOP_SESSION_TYPE} sessionType The session type for the room.
* @param {String} roomToken The token for the room.
* @param {String} roomKey The encryption key for the room.
* @return {Promise} A promise that is resolved when the data has been stored.
*/
setKey: Task.async(function* (sessionType, roomToken, roomKey) {
if (sessionType != LOOP_SESSION_TYPE.FXA) {
return;
}
let cache = yield this._getCache();
// Create these objects if they don't exist.
// We aim to do this creation and setting of the room key in a
// forwards-compatible way so that if new fields are added to rooms later
// then we don't mess them up (if there's no keys).
if (!cache[sessionType]) {
cache[sessionType] = {};
}
if (!cache[sessionType][roomToken]) {
cache[sessionType][roomToken] = {};
}
// Only save it if there's no key, or it is different.
if (!cache[sessionType][roomToken].key ||
cache[sessionType][roomToken].key != roomKey) {
cache[sessionType][roomToken].key = roomKey;
return yield this._setCache(cache);
}
})
};

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

@ -20,7 +20,6 @@ EXTRA_JS_MODULES.loop += [
'modules/LoopCalls.jsm',
'modules/LoopContacts.jsm',
'modules/LoopRooms.jsm',
'modules/LoopRoomsCache.jsm',
'modules/LoopStorage.jsm',
'modules/MozLoopAPI.jsm',
'modules/MozLoopPushHandler.jsm',

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

@ -5,9 +5,6 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
// Initialize this before the imports, as some of them need it.
do_get_profile();
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Http.jsm");
@ -16,9 +13,7 @@ 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");
Cu.import("resource://gre/modules/osfile.jsm");
const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
const { LoopRoomsInternal } = Cu.import("resource:///modules/loop/LoopRooms.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
"resource:///modules/loop/MozLoopPushHandler.jsm");
@ -216,10 +211,3 @@ MockWebSocketChannel.prototype = {
this.listener.onServerClose(this.context, err || -1);
},
};
const extend = function(target, source) {
for (let key of Object.getOwnPropertyNames(source)) {
target[key] = source[key];
}
return target;
};

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

@ -182,6 +182,13 @@ const kCreateRoomData = {
const kChannelGuest = MozLoopService.channelIDs.roomsGuest;
const kChannelFxA = MozLoopService.channelIDs.roomsFxA;
const extend = function(target, source) {
for (let key of Object.getOwnPropertyNames(source)) {
target[key] = source[key];
}
return target;
};
const normalizeRoom = function(room) {
let newRoom = extend({}, room);
let name = newRoom.decryptedContext.roomName;

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

@ -1,269 +0,0 @@
/* 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/. */
"use strict";
Cu.import("resource://services-common/utils.js");
const { LOOP_ROOMS_CACHE_FILENAME } = Cu.import("resource:///modules/loop/LoopRoomsCache.jsm", {});
const kContextEnabledPref = "loop.contextInConverations.enabled";
const kFxAKey = "uGIs-kGbYt1hBBwjyW7MLQ";
// Rooms details as responded by the server.
const kRoomsResponses = new Map([
["_nxD4V4FflQ", {
// Encrypted with roomKey "FliIGLUolW-xkKZVWstqKw".
// roomKey is wrapped with kFxAKey.
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
roomToken: "_nxD4V4FflQ",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ"
}],
["QzBbvGmIZWU", {
context: {
wrappedKey: "AFu7WwFNjhWR5J6L8ks7S6H/1ktYVEw3yt1eIIWVaMabZaB3vh5612/FNzua4oS2oCM=",
value: "sqj+xRNEty8K3Q1gSMd5bIUYKu34JfiO2+LIMlJrOetFIbJdBoQ+U8JZNaTFl6Qp3RULZ41x0zeSBSk=",
alg: "AES-GCM"
},
roomToken: "QzBbvGmIZWU",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU"
}]
]);
const kExpectedRooms = new Map([
["_nxD4V4FflQ", {
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
decryptedContext: {
roomName: "First Room Name"
},
roomKey: "FliIGLUolW-xkKZVWstqKw",
roomToken: "_nxD4V4FflQ",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ#FliIGLUolW-xkKZVWstqKw"
}],
["QzBbvGmIZWU", {
context: {
wrappedKey: "AFu7WwFNjhWR5J6L8ks7S6H/1ktYVEw3yt1eIIWVaMabZaB3vh5612/FNzua4oS2oCM=",
value: "sqj+xRNEty8K3Q1gSMd5bIUYKu34JfiO2+LIMlJrOetFIbJdBoQ+U8JZNaTFl6Qp3RULZ41x0zeSBSk=",
alg: "AES-GCM"
},
decryptedContext: {
roomName: "Loopy Discussion",
},
roomKey: "h2H8Sa9QxLCTTiXNmJVtRA",
roomToken: "QzBbvGmIZWU",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU"
}]
]);
const kCreateRoomProps = {
decryptedContext: {
roomName: "Say Hello",
},
roomOwner: "Gavin",
maxSize: 2
};
const kCreateRoomData = {
roomToken: "Vo2BFQqIaAM",
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
expiresAt: 1405534180
};
function getCachePath() {
return OS.Path.join(OS.Constants.Path.profileDir, LOOP_ROOMS_CACHE_FILENAME);
}
function readRoomsCache() {
return CommonUtils.readJSON(getCachePath());
}
function saveRoomsCache(contents) {
delete LoopRoomsInternal.roomsCache._cache;
return CommonUtils.writeJSON(contents, getCachePath());
}
function clearRoomsCache() {
return LoopRoomsInternal.roomsCache.clear();
}
// This is a cut-down version of the one in test_looprooms.js.
add_task(function* setup_server() {
loopServer.registerPathHandler("/registration", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms", (req, res) => {
res.setStatusLine(null, 200, "OK");
if (req.method == "POST") {
Assert.ok(req.bodyInputStream, "POST request should have a payload");
let body = CommonUtils.readBytesFromInputStream(req.bodyInputStream);
let data = JSON.parse(body);
Assert.ok(!("decryptedContext" in data), "should not have any decrypted data");
Assert.ok("context" in data, "should have context");
res.write(JSON.stringify(kCreateRoomData));
} else {
res.write(JSON.stringify([...kRoomsResponses.values()]));
}
res.processAsync();
res.finish();
});
function returnRoomDetails(res, roomName) {
roomDetail.roomName = roomName;
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(roomDetail));
res.processAsync();
res.finish();
}
function getJSONData(body) {
return JSON.parse(CommonUtils.readBytesFromInputStream(body));
}
// Add a request handler for each room in the list.
[...kRoomsResponses.values()].forEach(function(room) {
loopServer.registerPathHandler("/rooms/" + encodeURIComponent(room.roomToken), (req, res) => {
if (req.method == "POST") {
let data = getJSONData(req.bodyInputStream);
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(data));
res.processAsync();
res.finish();
} else if (req.method == "PATCH") {
let data = getJSONData(req.bodyInputStream);
Assert.ok("context" in data, "should have encrypted context");
// We return a fake encrypted name here as the context is
// encrypted.
returnRoomDetails(res, "fakeEncrypted");
} else {
res.setStatusLine(null, 200, "OK");
res.write(JSON.stringify(room));
res.processAsync();
res.finish();
}
});
});
loopServer.registerPathHandler("/rooms/error401", (req, res) => {
res.setStatusLine(null, 401, "Not Found");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms/errorMalformed", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.write("{\"some\": \"Syntax Error!\"}}}}}}");
res.processAsync();
res.finish();
});
mockPushHandler.registrationPushURL = kEndPointUrl;
yield MozLoopService.promiseRegisteredWithServers();
});
// Test if getting rooms saves unknown keys correctly.
add_task(function* test_get_rooms_saves_unknown_keys() {
let rooms = yield LoopRooms.promise("getAll");
// Check that we've saved the encryption keys correctly.
let roomsCache = yield readRoomsCache();
for (let room of [...kExpectedRooms.values()]) {
if (room.context.wrappedKey) {
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][room.roomToken].key, room.roomKey);
}
}
yield clearRoomsCache();
});
// Test that when we get a room it updates the saved key if it is different.
add_task(function* test_get_rooms_saves_different_keys() {
let roomsCache = {};
roomsCache[LOOP_SESSION_TYPE.FXA] = {
QzBbvGmIZWU: {key: "fakeKey"}
};
yield saveRoomsCache(roomsCache);
const kRoomToken = "QzBbvGmIZWU";
let room = yield LoopRooms.promise("get", kRoomToken);
// Check that we've saved the encryption keys correctly.
roomsCache = yield readRoomsCache();
Assert.notEqual(roomsCache[LOOP_SESSION_TYPE.FXA][kRoomToken].key, "fakeKey");
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][kRoomToken].key, room.roomKey);
yield clearRoomsCache();
});
// Test that if roomKey decryption fails, the saved key is used for decryption.
add_task(function* test_get_rooms_uses_saved_key() {
const kRoomToken = "_nxD4V4FflQ";
const kExpected = kExpectedRooms.get(kRoomToken);
let roomsCache = {};
roomsCache[LOOP_SESSION_TYPE.FXA] = {
"_nxD4V4FflQ": {key: kExpected.roomKey}
};
yield saveRoomsCache(roomsCache);
// Change the encryption key for FxA, so that decoding the room key will break.
Services.prefs.setCharPref("loop.key.fxa", "invalidKey");
let room = yield LoopRooms.promise("get", kRoomToken);
Assert.deepEqual(room, kExpected);
Services.prefs.setCharPref("loop.key.fxa", kFxAKey);
yield clearRoomsCache();
});
// Test that when a room is created the new key is saved.
add_task(function* test_create_room_saves_key() {
let room = yield LoopRooms.promise("create", kCreateRoomProps);
let roomsCache = yield readRoomsCache();
Assert.equal(roomsCache[LOOP_SESSION_TYPE.FXA][room.roomToken].key, room.roomKey);
yield clearRoomsCache();
});
function run_test() {
setupFakeLoopServer();
Services.prefs.setCharPref("loop.key.fxa", kFxAKey);
Services.prefs.setBoolPref(kContextEnabledPref, true);
// Pretend we're signed into FxA.
MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
MozLoopServiceInternal.fxAOAuthProfile = { email: "fake@invalid.com" };
do_register_cleanup(function () {
Services.prefs.clearUserPref(kContextEnabledPref);
Services.prefs.clearUserPref("loop.key.fxa");
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.fxAOAuthProfile = null;
});
run_next_test();
}

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

@ -1,119 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://services-common/utils.js");
Cu.import("resource:///modules/loop/LoopRooms.jsm");
Cu.import("resource:///modules/Chat.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
const kGuestKey = "uGIs-kGbYt1hBBwjyW7MLQ";
const kChannelGuest = MozLoopService.channelIDs.roomsGuest;
const kRoomsResponses = new Map([
["_nxD4V4FflQ", {
roomToken: "_nxD4V4FflQ",
// Encrypted with roomKey "FliIGLUolW-xkKZVWstqKw".
// roomKey is wrapped with kGuestKey.
context: {
wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
alg: "AES-GCM"
},
roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
maxSize: 2,
ctime: 1405517546,
participants: [{
displayName: "Alexis",
account: "alexis@example.com",
roomConnectionId: "2a1787a6-4a73-43b5-ae3e-906ec1e763cb"
}, {
displayName: "Adam",
roomConnectionId: "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7"
}]
}],
["QzBbvGmIZWU", {
roomToken: "QzBbvGmIZWU",
roomName: "Second Room Name",
roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU",
maxSize: 2,
ctime: 140551741
}],
]);
let gRoomsAdded = [];
let gRoomsUpdated = [];
const onRoomAdded = function(e, room) {
gRoomsAdded.push(room);
};
const onRoomUpdated = function(e, room) {
gRoomsUpdated.push(room);
};
let gQueryString = null;
add_task(function* setup_server() {
loopServer.registerPathHandler("/registration", (req, res) => {
res.setStatusLine(null, 200, "OK");
res.processAsync();
res.finish();
});
loopServer.registerPathHandler("/rooms", (req, res) => {
gQueryString = req.queryString;
res.setStatusLine(null, 200, "OK");
// For this simple test, always send all rooms, even though this wouldn't
// happen normally.
res.write(JSON.stringify([...kRoomsResponses.values()]));
res.processAsync();
res.finish();
});
mockPushHandler.registrationPushURL = kEndPointUrl;
yield MozLoopService.promiseRegisteredWithServers();
});
// Test if notifying from push correctly gets all rooms the first time.
add_task(function* test_notification_firstTime() {
roomsPushNotification("1", kChannelGuest);
// Wait for the notification to complete before we getAll, otherwise
// the getAll may cover up what we're testing.
yield waitForCondition(() => gRoomsAdded.length === 2);
let rooms = yield LoopRooms.promise("getAll");
Assert.equal(rooms.length, 2);
Assert.equal(gQueryString, "", "Query string should not be set.");
});
// Test if notifying from push correctly only gets the specific room the second time.
add_task(function* test_notification_firstTime() {
roomsPushNotification("2", kChannelGuest);
yield waitForCondition(() => gRoomsUpdated.length === 2);
let rooms = yield LoopRooms.promise("getAll");
Assert.equal(rooms.length, 2);
Assert.equal(gQueryString, "version=2", "Query string should be set.");
});
function run_test() {
setupFakeLoopServer();
Services.prefs.setCharPref("loop.key", kGuestKey);
LoopRooms.on("add", onRoomAdded);
LoopRooms.on("update", onRoomUpdated);
do_register_cleanup(function () {
Services.prefs.clearUserPref("loop.key");
LoopRooms.off("add", onRoomAdded);
LoopRooms.off("update", onRoomUpdated);
});
run_next_test();
}

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

@ -7,8 +7,6 @@ skip-if = toolkit == 'gonk'
[test_loopapi_hawk_request.js]
[test_looppush_initialize.js]
[test_looprooms.js]
[test_looprooms_encryption_in_fxa.js]
[test_looprooms_first_notification.js]
[test_loopservice_directcall.js]
[test_loopservice_dnd.js]
[test_loopservice_encryptionkey.js]