зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1403276 - Dedupe sync devices with the same fxaDeviceId by picking the one with the newer last modified date r=eoger
MozReview-Commit-ID: 3Lq7vuPpF6 --HG-- extra : rebase_source : f16c5fe0d29551ab829ba8f0c8c92e78109ace07
This commit is contained in:
Родитель
2b7d843720
Коммит
da5797466a
|
@ -310,10 +310,27 @@ ClientEngine.prototype = {
|
|||
async updateKnownStaleClients() {
|
||||
this._log.debug("Updating the known stale clients");
|
||||
await this._refreshKnownStaleClients();
|
||||
for (let client of Object.values(this._store._remoteClients)) {
|
||||
if (client.fxaDeviceId && this._knownStaleFxADeviceIds.includes(client.fxaDeviceId)) {
|
||||
let localFxADeviceId = await fxAccounts.getDeviceId();
|
||||
// Process newer records first, so that if we hit a record with a device ID
|
||||
// we've seen before, we can mark it stale immediately.
|
||||
let clientList = Object.values(this._store._remoteClients).sort((a, b) =>
|
||||
b.serverLastModified - a.serverLastModified);
|
||||
let seenDeviceIds = new Set([localFxADeviceId]);
|
||||
for (let client of clientList) {
|
||||
// Clients might not have an `fxaDeviceId` if they fail the FxA
|
||||
// registration process.
|
||||
if (!client.fxaDeviceId) {
|
||||
continue;
|
||||
}
|
||||
if (this._knownStaleFxADeviceIds.includes(client.fxaDeviceId)) {
|
||||
this._log.info(`Hiding stale client ${client.id} - in known stale clients list`);
|
||||
client.stale = true;
|
||||
} else if (seenDeviceIds.has(client.fxaDeviceId)) {
|
||||
this._log.info(`Hiding stale client ${client.id}` +
|
||||
` - duplicate device id ${client.fxaDeviceId}`);
|
||||
client.stale = true;
|
||||
} else {
|
||||
seenDeviceIds.add(client.fxaDeviceId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -369,6 +386,7 @@ ClientEngine.prototype = {
|
|||
await this._removeRemoteClient(id);
|
||||
}
|
||||
}
|
||||
let localFxADeviceId = await fxAccounts.getDeviceId();
|
||||
// Bug 1264498: Mobile clients don't remove themselves from the clients
|
||||
// collection when the user disconnects Sync, so we mark as stale clients
|
||||
// with the same name that haven't synced in over a week.
|
||||
|
@ -376,7 +394,10 @@ ClientEngine.prototype = {
|
|||
// bug 1287687)
|
||||
delete this._incomingClients[this.localID];
|
||||
let names = new Set([this.localName]);
|
||||
for (let [id, serverLastModified] of Object.entries(this._incomingClients)) {
|
||||
let seenDeviceIds = new Set([localFxADeviceId]);
|
||||
let idToLastModifiedList = Object.entries(this._incomingClients)
|
||||
.sort((a, b) => b[1] - a[1]);
|
||||
for (let [id, serverLastModified] of idToLastModifiedList) {
|
||||
let record = this._store._remoteClients[id];
|
||||
// stash the server last-modified time on the record.
|
||||
record.serverLastModified = serverLastModified;
|
||||
|
@ -385,6 +406,9 @@ ClientEngine.prototype = {
|
|||
record.stale = true;
|
||||
}
|
||||
if (!names.has(record.name)) {
|
||||
if (record.fxaDeviceId) {
|
||||
seenDeviceIds.add(record.fxaDeviceId);
|
||||
}
|
||||
names.add(record.name);
|
||||
continue;
|
||||
}
|
||||
|
@ -392,6 +416,14 @@ ClientEngine.prototype = {
|
|||
if (remoteAge > STALE_CLIENT_REMOTE_AGE) {
|
||||
this._log.info(`Hiding stale client ${id} with age ${remoteAge}`);
|
||||
record.stale = true;
|
||||
continue;
|
||||
}
|
||||
if (record.fxaDeviceId && seenDeviceIds.has(record.fxaDeviceId)) {
|
||||
this._log.info(`Hiding stale client ${record.id}` +
|
||||
` - duplicate device id ${record.fxaDeviceId}`);
|
||||
record.stale = true;
|
||||
} else if (record.fxaDeviceId) {
|
||||
seenDeviceIds.add(record.fxaDeviceId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
|
|
@ -870,6 +870,68 @@ add_task(async function test_clients_not_in_fxa_list() {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
add_task(async function test_dupe_device_ids() {
|
||||
_("Ensure that we mark devices with duplicate fxaDeviceIds but older lastModified as stale.");
|
||||
|
||||
await engine._store.wipe();
|
||||
await generateNewKeys(Service.collectionKeys);
|
||||
|
||||
let server = await serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let remoteId = Utils.makeGUID();
|
||||
let remoteId2 = Utils.makeGUID();
|
||||
let remoteDeviceId = Utils.makeGUID();
|
||||
|
||||
_("Create remote client records");
|
||||
server.insertWBO("foo", "clients", new ServerWBO(remoteId, encryptPayload({
|
||||
id: remoteId,
|
||||
name: "Remote client",
|
||||
type: "desktop",
|
||||
commands: [],
|
||||
version: "48",
|
||||
fxaDeviceId: remoteDeviceId,
|
||||
protocols: ["1.5"],
|
||||
}), Date.now() / 1000 - 30000));
|
||||
server.insertWBO("foo", "clients", new ServerWBO(remoteId2, encryptPayload({
|
||||
id: remoteId2,
|
||||
name: "Remote client",
|
||||
type: "desktop",
|
||||
commands: [],
|
||||
version: "48",
|
||||
fxaDeviceId: remoteDeviceId,
|
||||
protocols: ["1.5"],
|
||||
}), Date.now() / 1000));
|
||||
|
||||
let fxAccounts = engine.fxAccounts;
|
||||
engine.fxAccounts = {
|
||||
notifyDevices() { return Promise.resolve(true); },
|
||||
getDeviceId() { return fxAccounts.getDeviceId(); },
|
||||
getDeviceList() { return Promise.resolve([{ id: remoteDeviceId }]); }
|
||||
};
|
||||
|
||||
try {
|
||||
_("Syncing.");
|
||||
await syncClientsEngine(server);
|
||||
|
||||
ok(engine._store._remoteClients[remoteId].stale);
|
||||
ok(!engine._store._remoteClients[remoteId2].stale);
|
||||
|
||||
} finally {
|
||||
engine.fxAccounts = fxAccounts;
|
||||
await cleanup();
|
||||
|
||||
try {
|
||||
let collection = server.getCollection("foo", "clients");
|
||||
collection.remove(remoteId);
|
||||
} finally {
|
||||
await promiseStopServer(server);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
add_task(async function test_send_uri_to_client_for_display() {
|
||||
_("Ensure sendURIToClientForDisplay() sends command properly.");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче