import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -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/. */
"use strict";
this.EXPORTED_SYMBOLS = [
"FakeCryptoService",
"FakeFilesystemService",
"FakeGUIDService",
"fakeSHA256HMAC",
];
var {utils: Cu} = Components;
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/util.js");
var btoa = Cu.import("resource://gre/modules/Log.jsm").btoa;
this.FakeFilesystemService = function FakeFilesystemService(contents) {
this.fakeContents = contents;
let self = this;
// Save away the unmocked versions of the functions we replace here for tests
// that really want the originals. As this may be called many times per test,
// we must be careful to not replace them with ones we previously replaced.
// (And WTF are we bothering with these mocks in the first place? Is the
// performance of the filesystem *really* such that it outweighs the downside
// of not running our real JSON functions in the tests? Eg, these mocks don't
// always throw exceptions when the real ones do. Anyway...)
for (let name of ["jsonSave", "jsonLoad", "jsonMove", "jsonRemove"]) {
let origName = "_real_" + name;
if (!Utils[origName]) {
Utils[origName] = Utils[name];
}
}
Utils.jsonSave = function jsonSave(filePath, that, obj, callback) {
let json = typeof obj == "function" ? obj.call(that) : obj;
self.fakeContents["weave/" + filePath + ".json"] = JSON.stringify(json);
callback.call(that);
};
Utils.jsonLoad = function jsonLoad(filePath, that, cb) {
let obj;
let json = self.fakeContents["weave/" + filePath + ".json"];
if (json) {
obj = JSON.parse(json);
}
cb.call(that, obj);
};
Utils.jsonMove = function jsonMove(aFrom, aTo, that) {
const fromPath = "weave/" + aFrom + ".json";
self.fakeContents["weave/" + aTo + ".json"] = self.fakeContents[fromPath];
delete self.fakeContents[fromPath];
return Promise.resolve();
};
Utils.jsonRemove = function jsonRemove(filePath, that) {
delete self.fakeContents["weave/" + filePath + ".json"];
return Promise.resolve();
};
};
this.fakeSHA256HMAC = function fakeSHA256HMAC(message) {
message = message.substr(0, 64);
while (message.length < 64) {
message += " ";
}
return message;
}
this.FakeGUIDService = function FakeGUIDService() {
let latestGUID = 0;
Utils.makeGUID = function makeGUID() {
// ensure that this always returns a unique 12 character string
let nextGUID = "fake-guid-" + String(latestGUID++).padStart(2, "0");
return nextGUID.slice(nextGUID.length-12, nextGUID.length);
};
}
/*
* Mock implementation of WeaveCrypto. It does not encrypt or
* decrypt, merely returning the input verbatim.
*/
this.FakeCryptoService = function FakeCryptoService() {
this.counter = 0;
delete Svc.Crypto; // get rid of the getter first
Svc.Crypto = this;
CryptoWrapper.prototype.ciphertextHMAC = function ciphertextHMAC(keyBundle) {
return fakeSHA256HMAC(this.ciphertext);
};
}
FakeCryptoService.prototype = {
encrypt: function encrypt(clearText, symmetricKey, iv) {
return clearText;
},
decrypt: function decrypt(cipherText, symmetricKey, iv) {
return cipherText;
},
generateRandomKey: function generateRandomKey() {
return btoa("fake-symmetric-key-" + this.counter++);
},
generateRandomIV: function generateRandomIV() {
// A base64-encoded IV is 24 characters long
return btoa("fake-fake-fake-random-iv");
},
expandData: function expandData(data, len) {
return data;
},
deriveKeyFromPassphrase: function deriveKeyFromPassphrase(passphrase,
salt, keyLength) {
return "some derived key string composed of bytes";
},
generateRandomBytes: function generateRandomBytes(byteCount) {
return "not-so-random-now-are-we-HA-HA-HA! >:)".slice(byteCount);
}
};

View file

@ -0,0 +1,58 @@
"use strict";
this.EXPORTED_SYMBOLS = [
"initializeIdentityWithTokenServerResponse",
];
var {utils: Cu} = Components;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/main.js");
Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://services-common/tokenserverclient.js");
Cu.import("resource://testing-common/services/common/logging.js");
Cu.import("resource://testing-common/services/sync/utils.js");
// Create a new browserid_identity object and initialize it with a
// mocked TokenServerClient which always receives the specified response.
this.initializeIdentityWithTokenServerResponse = function(response) {
// First create a mock "request" object that well' hack into the token server.
// A log for it
let requestLog = Log.repository.getLogger("testing.mock-rest");
if (!requestLog.appenders.length) { // might as well see what it says :)
requestLog.addAppender(new Log.DumpAppender());
requestLog.level = Log.Level.Trace;
}
// A mock request object.
function MockRESTRequest(url) {};
MockRESTRequest.prototype = {
_log: requestLog,
setHeader: function() {},
get: function(callback) {
this.response = response;
callback.call(this);
}
}
// The mocked TokenServer client which will get the response.
function MockTSC() { }
MockTSC.prototype = new TokenServerClient();
MockTSC.prototype.constructor = MockTSC;
MockTSC.prototype.newRESTRequest = function(url) {
return new MockRESTRequest(url);
}
// Arrange for the same observerPrefix as browserid_identity uses.
MockTSC.prototype.observerPrefix = "weave:service";
// tie it all together.
Weave.Status.__authManager = Weave.Service.identity = new BrowserIDManager();
Weave.Service._clusterManager = Weave.Service.identity.createClusterManager(Weave.Service);
let browseridManager = Weave.Service.identity;
// a sanity check
if (!(browseridManager instanceof BrowserIDManager)) {
throw new Error("sync isn't configured for browserid_identity");
}
let mockTSC = new MockTSC()
configureFxAccountIdentity(browseridManager);
browseridManager._tokenServerClient = mockTSC;
}

View file

@ -0,0 +1,124 @@
/* 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";
this.EXPORTED_SYMBOLS = [
"RotaryEngine",
"RotaryRecord",
"RotaryStore",
"RotaryTracker",
];
var {utils: Cu} = Components;
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/util.js");
/*
* A fake engine implementation.
* This is used all over the place.
*
* Complete with record, store, and tracker implementations.
*/
this.RotaryRecord = function RotaryRecord(collection, id) {
CryptoWrapper.call(this, collection, id);
}
RotaryRecord.prototype = {
__proto__: CryptoWrapper.prototype
};
Utils.deferGetSet(RotaryRecord, "cleartext", ["denomination"]);
this.RotaryStore = function RotaryStore(name, engine) {
Store.call(this, name, engine);
this.items = {};
}
RotaryStore.prototype = {
__proto__: Store.prototype,
create: function create(record) {
this.items[record.id] = record.denomination;
},
remove: function remove(record) {
delete this.items[record.id];
},
update: function update(record) {
this.items[record.id] = record.denomination;
},
itemExists: function itemExists(id) {
return (id in this.items);
},
createRecord: function createRecord(id, collection) {
let record = new RotaryRecord(collection, id);
if (!(id in this.items)) {
record.deleted = true;
return record;
}
record.denomination = this.items[id] || "Data for new record: " + id;
return record;
},
changeItemID: function changeItemID(oldID, newID) {
if (oldID in this.items) {
this.items[newID] = this.items[oldID];
}
delete this.items[oldID];
},
getAllIDs: function getAllIDs() {
let ids = {};
for (let id in this.items) {
ids[id] = true;
}
return ids;
},
wipe: function wipe() {
this.items = {};
}
};
this.RotaryTracker = function RotaryTracker(name, engine) {
Tracker.call(this, name, engine);
}
RotaryTracker.prototype = {
__proto__: Tracker.prototype
};
this.RotaryEngine = function RotaryEngine(service) {
SyncEngine.call(this, "Rotary", service);
// Ensure that the engine starts with a clean slate.
this.toFetch = [];
this.previousFailed = [];
}
RotaryEngine.prototype = {
__proto__: SyncEngine.prototype,
_storeObj: RotaryStore,
_trackerObj: RotaryTracker,
_recordObj: RotaryRecord,
_findDupe: function _findDupe(item) {
// This is a semaphore used for testing proper reconciling on dupe
// detection.
if (item.id == "DUPE_INCOMING") {
return "DUPE_LOCAL";
}
for (let [id, value] of Object.entries(this._store.items)) {
if (item.denomination == value) {
return id;
}
}
}
};

View file

@ -0,0 +1,350 @@
/* 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";
this.EXPORTED_SYMBOLS = [
"btoa", // It comes from a module import.
"encryptPayload",
"isConfiguredWithLegacyIdentity",
"ensureLegacyIdentityManager",
"setBasicCredentials",
"makeIdentityConfig",
"makeFxAccountsInternalMock",
"configureFxAccountIdentity",
"configureIdentity",
"SyncTestingInfrastructure",
"waitForZeroTimer",
"Promise", // from a module import
"add_identity_test",
"MockFxaStorageManager",
"AccountState", // from a module import
"sumHistogram",
];
var {utils: Cu} = Components;
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-crypto/utils.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://testing-common/services/common/logging.js");
Cu.import("resource://testing-common/services/sync/fakeservices.js");
Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://gre/modules/FxAccountsClient.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Services.jsm");
// and grab non-exported stuff via a backstage pass.
const {AccountState} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
// A mock "storage manager" for FxAccounts that doesn't actually write anywhere.
function MockFxaStorageManager() {
}
MockFxaStorageManager.prototype = {
promiseInitialized: Promise.resolve(),
initialize(accountData) {
this.accountData = accountData;
},
finalize() {
return Promise.resolve();
},
getAccountData() {
return Promise.resolve(this.accountData);
},
updateAccountData(updatedFields) {
for (let [name, value] of Object.entries(updatedFields)) {
if (value == null) {
delete this.accountData[name];
} else {
this.accountData[name] = value;
}
}
return Promise.resolve();
},
deleteAccountData() {
this.accountData = null;
return Promise.resolve();
}
}
/**
* First wait >100ms (nsITimers can take up to that much time to fire, so
* we can account for the timer in delayedAutoconnect) and then two event
* loop ticks (to account for the Utils.nextTick() in autoConnect).
*/
this.waitForZeroTimer = function waitForZeroTimer(callback) {
let ticks = 2;
function wait() {
if (ticks) {
ticks -= 1;
CommonUtils.nextTick(wait);
return;
}
callback();
}
CommonUtils.namedTimer(wait, 150, {}, "timer");
}
/**
* Return true if Sync is configured with the "legacy" identity provider.
*/
this.isConfiguredWithLegacyIdentity = function() {
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
// We can't use instanceof as BrowserIDManager (the "other" identity) inherits
// from IdentityManager so that would return true - so check the prototype.
return Object.getPrototypeOf(ns.Service.identity) === IdentityManager.prototype;
}
/**
* Ensure Sync is configured with the "legacy" identity provider.
*/
this.ensureLegacyIdentityManager = function() {
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
Status.__authManager = ns.Service.identity = new IdentityManager();
ns.Service._clusterManager = ns.Service.identity.createClusterManager(ns.Service);
}
this.setBasicCredentials =
function setBasicCredentials(username, password, syncKey) {
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
let auth = ns.Service.identity;
auth.username = username;
auth.basicPassword = password;
auth.syncKey = syncKey;
}
// Return an identity configuration suitable for testing with our identity
// providers. |overrides| can specify overrides for any default values.
this.makeIdentityConfig = function(overrides) {
// first setup the defaults.
let result = {
// Username used in both fxaccount and sync identity configs.
username: "foo",
// fxaccount specific credentials.
fxaccount: {
user: {
assertion: 'assertion',
email: 'email',
kA: 'kA',
kB: 'kB',
sessionToken: 'sessionToken',
uid: "a".repeat(32),
verified: true,
},
token: {
endpoint: null,
duration: 300,
id: "id",
key: "key",
hashed_fxa_uid: "f".repeat(32), // used during telemetry validation
// uid will be set to the username.
}
},
sync: {
// username will come from the top-level username
password: "whatever",
syncKey: "abcdeabcdeabcdeabcdeabcdea",
}
};
// Now handle any specified overrides.
if (overrides) {
if (overrides.username) {
result.username = overrides.username;
}
if (overrides.sync) {
// TODO: allow just some attributes to be specified
result.sync = overrides.sync;
}
if (overrides.fxaccount) {
// TODO: allow just some attributes to be specified
result.fxaccount = overrides.fxaccount;
}
}
return result;
}
this.makeFxAccountsInternalMock = function(config) {
return {
newAccountState(credentials) {
// We only expect this to be called with null indicating the (mock)
// storage should be read.
if (credentials) {
throw new Error("Not expecting to have credentials passed");
}
let storageManager = new MockFxaStorageManager();
storageManager.initialize(config.fxaccount.user);
let accountState = new AccountState(storageManager);
return accountState;
},
_getAssertion(audience) {
return Promise.resolve("assertion");
},
};
};
// Configure an instance of an FxAccount identity provider with the specified
// config (or the default config if not specified).
this.configureFxAccountIdentity = function(authService,
config = makeIdentityConfig(),
fxaInternal = makeFxAccountsInternalMock(config)) {
// until we get better test infrastructure for bid_identity, we set the
// signedin user's "email" to the username, simply as many tests rely on this.
config.fxaccount.user.email = config.username;
let fxa = new FxAccounts(fxaInternal);
let MockFxAccountsClient = function() {
FxAccountsClient.apply(this);
};
MockFxAccountsClient.prototype = {
__proto__: FxAccountsClient.prototype,
accountStatus() {
return Promise.resolve(true);
}
};
let mockFxAClient = new MockFxAccountsClient();
fxa.internal._fxAccountsClient = mockFxAClient;
let mockTSC = { // TokenServerClient
getTokenFromBrowserIDAssertion: function(uri, assertion, cb) {
config.fxaccount.token.uid = config.username;
cb(null, config.fxaccount.token);
},
};
authService._fxaService = fxa;
authService._tokenServerClient = mockTSC;
// Set the "account" of the browserId manager to be the "email" of the
// logged in user of the mockFXA service.
authService._signedInUser = config.fxaccount.user;
authService._account = config.fxaccount.user.email;
}
this.configureIdentity = function(identityOverrides) {
let config = makeIdentityConfig(identityOverrides);
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
if (ns.Service.identity instanceof BrowserIDManager) {
// do the FxAccounts thang...
configureFxAccountIdentity(ns.Service.identity, config);
return ns.Service.identity.initializeWithCurrentIdentity().then(() => {
// need to wait until this identity manager is readyToAuthenticate.
return ns.Service.identity.whenReadyToAuthenticate.promise;
});
}
// old style identity provider.
setBasicCredentials(config.username, config.sync.password, config.sync.syncKey);
let deferred = Promise.defer();
deferred.resolve();
return deferred.promise;
}
this.SyncTestingInfrastructure = function (server, username, password, syncKey) {
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
ensureLegacyIdentityManager();
let config = makeIdentityConfig();
// XXX - hacks for the sync identity provider.
if (username)
config.username = username;
if (password)
config.sync.password = password;
if (syncKey)
config.sync.syncKey = syncKey;
let cb = Async.makeSpinningCallback();
configureIdentity(config).then(cb, cb);
cb.wait();
let i = server.identity;
let uri = i.primaryScheme + "://" + i.primaryHost + ":" +
i.primaryPort + "/";
ns.Service.serverURL = uri;
ns.Service.clusterURL = uri;
this.logStats = initTestLogging();
this.fakeFilesystem = new FakeFilesystemService({});
this.fakeGUIDService = new FakeGUIDService();
this.fakeCryptoService = new FakeCryptoService();
}
/**
* Turn WBO cleartext into fake "encrypted" payload as it goes over the wire.
*/
this.encryptPayload = function encryptPayload(cleartext) {
if (typeof cleartext == "object") {
cleartext = JSON.stringify(cleartext);
}
return {
ciphertext: cleartext, // ciphertext == cleartext with fake crypto
IV: "irrelevant",
hmac: fakeSHA256HMAC(cleartext, CryptoUtils.makeHMACKey("")),
};
}
// This helper can be used instead of 'add_test' or 'add_task' to run the
// specified test function twice - once with the old-style sync identity
// manager and once with the new-style BrowserID identity manager, to ensure
// it works in both cases.
//
// * The test itself should be passed as 'test' - ie, test code will generally
// pass |this|.
// * The test function is a regular test function - although note that it must
// be a generator - async operations should yield them, and run_next_test
// mustn't be called.
this.add_identity_test = function(test, testFunction) {
function note(what) {
let msg = "running test " + testFunction.name + " with " + what + " identity manager";
test.do_print(msg);
}
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
// one task for the "old" identity manager.
test.add_task(function* () {
note("sync");
let oldIdentity = Status._authManager;
ensureLegacyIdentityManager();
yield testFunction();
Status.__authManager = ns.Service.identity = oldIdentity;
});
// another task for the FxAccounts identity manager.
test.add_task(function* () {
note("FxAccounts");
let oldIdentity = Status._authManager;
Status.__authManager = ns.Service.identity = new BrowserIDManager();
yield testFunction();
Status.__authManager = ns.Service.identity = oldIdentity;
});
}
this.sumHistogram = function(name, options = {}) {
let histogram = options.key ? Services.telemetry.getKeyedHistogramById(name) :
Services.telemetry.getHistogramById(name);
let snapshot = histogram.snapshot(options.key);
let sum = -Infinity;
if (snapshot) {
sum = snapshot.sum;
}
histogram.clear();
return sum;
}