Backed out changeset d94ef5bca70e (bug 1152761) for xpcshell failures.

This commit is contained in:
Ryan VanderMeulen 2015-04-30 14:18:34 -04:00
Родитель 2cb72a414d
Коммит 330f835697
7 изменённых файлов: 14 добавлений и 496 удалений

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

@ -7,13 +7,11 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.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", {}); const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "Promise", XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm"); "resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://services-common/utils.js"); "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() { XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
return new EventEmitter(); return new EventEmitter();
@ -21,11 +19,8 @@ XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() { XPCOMUtils.defineLazyGetter(this, "gLoopBundle", function() {
return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties'); return Services.strings.createBundle('chrome://browser/locale/loop/loop.properties');
}); });
XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache",
"resource:///modules/loop/LoopRoomsCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
"resource:///modules/loop/utils.js", "utils"); "resource:///modules/loop/utils.js", "utils")
XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
"resource:///modules/loop/crypto.js", "LoopCrypto"); "resource:///modules/loop/crypto.js", "LoopCrypto");
@ -46,8 +41,6 @@ const roomsPushNotification = function(version, channelID) {
let gDirty = true; let gDirty = true;
// Global variable that keeps track of the currently used account. // Global variable that keeps track of the currently used account.
let gCurrentUser = null; 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`. * Extend a `target` object with the properties defined in `source`.
@ -130,13 +123,6 @@ let LoopRoomsInternal = {
*/ */
rooms: new Map(), 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'. * @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'.
*/ */
@ -294,40 +280,12 @@ let LoopRoomsInternal = {
throw new Error("Missing wrappedKey"); throw new Error("Missing wrappedKey");
} }
let savedRoomKey = yield this.roomsCache.getKey(this.sessionType, roomData.roomToken); // Bug 1152761 will cause us to additionally store keys locally. We'll
let fallback = false; // need to add some code for recovery in case decryption fails.
let key; let key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);
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;
}
let decryptedData = yield loopCrypto.decryptBytes(key, roomData.context.value); 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.roomKey = key;
roomData.decryptedContext = JSON.parse(decryptedData); roomData.decryptedContext = JSON.parse(decryptedData);
@ -384,7 +342,7 @@ let LoopRoomsInternal = {
this.saveAndNotifyUpdate(roomData, isUpdate); this.saveAndNotifyUpdate(roomData, isUpdate);
} catch (error) { } 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. // Do what we can to save the room data.
room.decryptedContext = {}; room.decryptedContext = {};
this.saveAndNotifyUpdate(room, isUpdate); this.saveAndNotifyUpdate(room, isUpdate);
@ -537,9 +495,6 @@ let LoopRoomsInternal = {
this.setGuestCreatedRoom(true); 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); eventEmitter.emit("add", room);
callback(null, room); callback(null, room);
}.bind(this)).catch(callback); }.bind(this)).catch(callback);
@ -749,10 +704,6 @@ let LoopRoomsInternal = {
sendData = { sendData = {
roomName: newRoomName 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, let response = yield MozLoopService.hawkRequest(this.sessionType,

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

@ -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/LoopCalls.jsm',
'modules/LoopContacts.jsm', 'modules/LoopContacts.jsm',
'modules/LoopRooms.jsm', 'modules/LoopRooms.jsm',
'modules/LoopRoomsCache.jsm',
'modules/LoopStorage.jsm', 'modules/LoopStorage.jsm',
'modules/MozLoopAPI.jsm', 'modules/MozLoopAPI.jsm',
'modules/MozLoopPushHandler.jsm', 'modules/MozLoopPushHandler.jsm',

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

@ -3,9 +3,6 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; 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/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Http.jsm"); Cu.import("resource://gre/modules/Http.jsm");
@ -14,9 +11,7 @@ Cu.import("resource:///modules/loop/MozLoopService.jsm");
Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource:///modules/loop/LoopCalls.jsm"); Cu.import("resource:///modules/loop/LoopCalls.jsm");
Cu.import("resource:///modules/loop/LoopRooms.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 { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
const { LoopRoomsInternal } = Cu.import("resource:///modules/loop/LoopRooms.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
"resource:///modules/loop/MozLoopPushHandler.jsm"); "resource:///modules/loop/MozLoopPushHandler.jsm");
@ -214,10 +209,3 @@ MockWebSocketChannel.prototype = {
this.listener.onServerClose(this.context, err || -1); 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 kChannelGuest = MozLoopService.channelIDs.roomsGuest;
const kChannelFxA = MozLoopService.channelIDs.roomsFxA; 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) { const normalizeRoom = function(room) {
let newRoom = extend({}, room); let newRoom = extend({}, room);
let name = newRoom.decryptedContext.roomName; let name = newRoom.decryptedContext.roomName;

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

@ -1,267 +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/. */
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();
}

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

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