From 3bd56e31c6d103b814828e38ead061bd06d65780 Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Wed, 22 Nov 2017 15:57:23 -0800 Subject: [PATCH 01/46] Bug 1381645 - Restrict access to WebVR to HTTPS only sites r=daoshengmu,smaug MozReview-Commit-ID: BsqUzSH55nN --HG-- extra : rebase_source : 054eca4ee6fb28c32534aa46d925beb49670899b --- dom/webidl/Navigator.webidl | 4 ++-- dom/webidl/VRDisplay.webidl | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index d9af6d027115..46b97771c1dc 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -217,10 +217,10 @@ partial interface Navigator { }; partial interface Navigator { - [Throws, Pref="dom.vr.enabled"] + [SecureContext, Throws, Pref="dom.vr.enabled"] Promise> getVRDisplays(); // TODO: Use FrozenArray once available. (Bug 1236777) - [Frozen, Cached, Pure, Pref="dom.vr.enabled"] + [SecureContext, Frozen, Cached, Pure, Pref="dom.vr.enabled"] readonly attribute sequence activeVRDisplays; [ChromeOnly, Pref="dom.vr.enabled"] readonly attribute boolean isWebVRContentDetected; diff --git a/dom/webidl/VRDisplay.webidl b/dom/webidl/VRDisplay.webidl index 43bcd3e00ebc..c75fb9a6de5c 100644 --- a/dom/webidl/VRDisplay.webidl +++ b/dom/webidl/VRDisplay.webidl @@ -9,6 +9,7 @@ enum VREye { }; [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRFieldOfView { readonly attribute double upDegrees; @@ -49,6 +50,7 @@ dictionary VRLayer { * These are expected to be static per-device/per-user. */ [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRDisplayCapabilities { /** @@ -90,6 +92,7 @@ interface VRDisplayCapabilities { * that support room-scale experiences. */ [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRStageParameters { /** @@ -115,6 +118,7 @@ interface VRStageParameters { }; [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRPose { @@ -136,6 +140,7 @@ interface VRPose [Constructor, Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRFrameData { readonly attribute DOMHighResTimeStamp timestamp; @@ -158,6 +163,7 @@ interface VRSubmitFrameResult { }; [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VREyeParameters { /** @@ -181,6 +187,7 @@ interface VREyeParameters { }; [Pref="dom.vr.enabled", + SecureContext, HeaderFile="mozilla/dom/VRDisplay.h"] interface VRDisplay : EventTarget { /** From 6613a4b93e55b207a984f580ed9d073070392b5b Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Fri, 15 Dec 2017 10:22:11 -0600 Subject: [PATCH 02/46] Bug 1381645 - Part 2: Move VR tests to secure context r=daoshengmu MozReview-Commit-ID: CTDnXHBuaLU --HG-- extra : rebase_source : a5be58d0cf10c2b4d7cbda95174793439af3fc5b --- dom/vr/test/mochitest/mochitest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/vr/test/mochitest/mochitest.ini b/dom/vr/test/mochitest/mochitest.ini index c5b82e719e6d..cdd6ee4e02a9 100644 --- a/dom/vr/test/mochitest/mochitest.ini +++ b/dom/vr/test/mochitest/mochitest.ini @@ -1,5 +1,6 @@ # Please confirm there is no other VR display connected. Otherwise, VRPuppetDisplay can't be attached. [DEFAULT] +scheme = https support-files = VRSimulationDriver.js requestPresent.js From 6ec807f80ddc37ad5c038ed6e5b7115ee1d6d175 Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Mon, 18 Dec 2017 13:09:52 -0800 Subject: [PATCH 03/46] Bug 1381645 - Part 3: Update test_interfaces.js to expect WebVR interfaces to be enabled only in secure contexts r=bz MozReview-Commit-ID: 3jyxWRi8BIv --HG-- extra : rebase_source : 87f00b098a52207749ca0400a53d904520a0eb0a --- dom/tests/mochitest/general/test_interfaces.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index f5fa0a3b9f36..6fa4c17816af 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -1181,21 +1181,21 @@ var interfaceNamesInGlobalScope = // IMPORTANT: Do not change this list without review from a DOM peer! {name: "VideoStreamTrack", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRDisplay", insecureContext: true, releaseNonWindows: false}, + {name: "VRDisplay", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRDisplayCapabilities", insecureContext: true, releaseNonWindows: false}, + {name: "VRDisplayCapabilities", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRDisplayEvent", insecureContext: true, releaseNonWindows: false}, + {name: "VRDisplayEvent", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VREyeParameters", insecureContext: true, releaseNonWindows: false}, + {name: "VREyeParameters", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRFieldOfView", insecureContext: true, releaseNonWindows: false}, + {name: "VRFieldOfView", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRFrameData", insecureContext: true, releaseNonWindows: false}, + {name: "VRFrameData", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRPose", insecureContext: true, releaseNonWindows: false}, + {name: "VRPose", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "VRStageParameters", insecureContext: true, releaseNonWindows: false}, + {name: "VRStageParameters", releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "VTTCue", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! From c6289726c77732c6310fa01568581c213d51936c Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Wed, 24 Jan 2018 14:18:47 -0800 Subject: [PATCH 04/46] Bug 1381645 - Part 4: Update web-platform tests expectation data for WebVR r=jgraham The testing/web-platform/tests/webvr/idlharness.html web-platform test is reporting failures due to the webvr interfaces being available only on secure contexts. A PR has been added to the upstream web-platform-tests repo in GitHub to make webvr/idlharness.html run in a secure context. Once this change has landed and been pulled down, we can update the expectation data to expect these tests to pass once again. MozReview-Commit-ID: Gar9MHUFEHr --HG-- extra : rebase_source : 2776b52c02abaa2522f992739d5c8febbe368b5d --- .../meta/webvr/idlharness.html.ini | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) diff --git a/testing/web-platform/meta/webvr/idlharness.html.ini b/testing/web-platform/meta/webvr/idlharness.html.ini index f784e49ab6da..926c1fcf9500 100644 --- a/testing/web-platform/meta/webvr/idlharness.html.ini +++ b/testing/web-platform/meta/webvr/idlharness.html.ini @@ -11,3 +11,207 @@ [HTMLIFrameElement interface: attribute allowvr] expected: FAIL + [Navigator interface: operation getVRDisplays()] + expected: FAIL + + [Navigator interface: attribute activeVRDisplays] + expected: FAIL + + [VRDisplay interface: existence and properties of interface object] + expected: FAIL + + [VRDisplay interface object length] + expected: FAIL + + [VRDisplay interface object name] + expected: FAIL + + [VRDisplay interface: existence and properties of interface prototype object] + expected: FAIL + + [VRDisplay interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VRDisplay interface: attribute isPresenting] + expected: FAIL + + [VRDisplay interface: attribute capabilities] + expected: FAIL + + [VRDisplay interface: attribute stageParameters] + expected: FAIL + + [VRDisplay interface: operation getEyeParameters(VREye)] + expected: FAIL + + [VRDisplay interface: attribute displayId] + expected: FAIL + + [VRDisplay interface: attribute displayName] + expected: FAIL + + [VRDisplay interface: operation getFrameData(VRFrameData)] + expected: FAIL + + [VRDisplay interface: attribute depthNear] + expected: FAIL + + [VRDisplay interface: attribute depthFar] + expected: FAIL + + [VRDisplay interface: operation requestAnimationFrame(FrameRequestCallback)] + expected: FAIL + + [VRDisplay interface: operation cancelAnimationFrame(long)] + expected: FAIL + + [VRDisplay interface: operation requestPresent([object Object\])] + expected: FAIL + + [VRDisplay interface: operation exitPresent()] + expected: FAIL + + [VRDisplay interface: operation getLayers()] + expected: FAIL + + [VRDisplay interface: operation submitFrame()] + expected: FAIL + + [VRDisplayCapabilities interface: existence and properties of interface object] + expected: FAIL + + [VRDisplayCapabilities interface object length] + expected: FAIL + + [VRDisplayCapabilities interface object name] + expected: FAIL + + [VRDisplayCapabilities interface: existence and properties of interface prototype object] + expected: FAIL + + [VRDisplayCapabilities interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VRDisplayCapabilities interface: attribute hasPosition] + expected: FAIL + + [VRDisplayCapabilities interface: attribute hasExternalDisplay] + expected: FAIL + + [VRDisplayCapabilities interface: attribute canPresent] + expected: FAIL + + [VRDisplayCapabilities interface: attribute maxLayers] + expected: FAIL + + [VRPose interface: existence and properties of interface object] + expected: FAIL + + [VRPose interface object length] + expected: FAIL + + [VRPose interface object name] + expected: FAIL + + [VRPose interface: existence and properties of interface prototype object] + expected: FAIL + + [VRPose interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VRPose interface: attribute position] + expected: FAIL + + [VRPose interface: attribute linearVelocity] + expected: FAIL + + [VRPose interface: attribute linearAcceleration] + expected: FAIL + + [VRPose interface: attribute orientation] + expected: FAIL + + [VRPose interface: attribute angularVelocity] + expected: FAIL + + [VRPose interface: attribute angularAcceleration] + expected: FAIL + + [VRFrameData interface: existence and properties of interface object] + expected: FAIL + + [VRFrameData interface object length] + expected: FAIL + + [VRFrameData interface object name] + expected: FAIL + + [VRFrameData interface: existence and properties of interface prototype object] + expected: FAIL + + [VRFrameData interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VRFrameData interface: attribute leftProjectionMatrix] + expected: FAIL + + [VRFrameData interface: attribute leftViewMatrix] + expected: FAIL + + [VRFrameData interface: attribute rightProjectionMatrix] + expected: FAIL + + [VRFrameData interface: attribute rightViewMatrix] + expected: FAIL + + [VRFrameData interface: attribute pose] + expected: FAIL + + [VREyeParameters interface: existence and properties of interface object] + expected: FAIL + + [VREyeParameters interface object length] + expected: FAIL + + [VREyeParameters interface object name] + expected: FAIL + + [VREyeParameters interface: existence and properties of interface prototype object] + expected: FAIL + + [VREyeParameters interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VREyeParameters interface: attribute offset] + expected: FAIL + + [VREyeParameters interface: attribute renderWidth] + expected: FAIL + + [VREyeParameters interface: attribute renderHeight] + expected: FAIL + + [VRStageParameters interface: existence and properties of interface object] + expected: FAIL + + [VRStageParameters interface object length] + expected: FAIL + + [VRStageParameters interface object name] + expected: FAIL + + [VRStageParameters interface: existence and properties of interface prototype object] + expected: FAIL + + [VRStageParameters interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [VRStageParameters interface: attribute sittingToStandingTransform] + expected: FAIL + + [VRStageParameters interface: attribute sizeX] + expected: FAIL + + [VRStageParameters interface: attribute sizeZ] + expected: FAIL + From 6321345295810d4d9c1bd8de0de6d87d722d54b8 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Tue, 9 Jan 2018 19:22:33 -0500 Subject: [PATCH 05/46] Bug 1429250 - Avoid repeated traversals of toFetch in _processIncoming. r=eoger,kitcambridge MozReview-Commit-ID: N1Zr8iT7da --HG-- extra : rebase_source : ddaa51704c93985219d15b31aec7ff7e19b2832f --- services/sync/modules-testing/rotaryengine.js | 4 +- services/sync/modules/bookmark_repair.js | 8 ++- services/sync/modules/engines.js | 43 +++++++++----- services/sync/modules/util.js | 52 ++++++++++++++++- .../sync/tests/unit/test_bookmark_engine.js | 2 +- .../sync/tests/unit/test_history_engine.js | 13 +++-- services/sync/tests/unit/test_syncengine.js | 56 +++++++++++-------- .../sync/tests/unit/test_syncengine_sync.js | 56 ++++++++++--------- services/sync/tests/unit/test_telemetry.js | 2 +- tools/lint/eslint/modules.json | 2 +- 10 files changed, 158 insertions(+), 80 deletions(-) diff --git a/services/sync/modules-testing/rotaryengine.js b/services/sync/modules-testing/rotaryengine.js index 9faf4243bd97..77fd60a74ca7 100644 --- a/services/sync/modules-testing/rotaryengine.js +++ b/services/sync/modules-testing/rotaryengine.js @@ -100,8 +100,8 @@ RotaryTracker.prototype = { this.RotaryEngine = function RotaryEngine(service) { SyncEngine.call(this, "Rotary", service); // Ensure that the engine starts with a clean slate. - this.toFetch = []; - this.previousFailed = []; + this.toFetch = new SerializableSet(); + this.previousFailed = new SerializableSet(); }; RotaryEngine.prototype = { __proto__: SyncEngine.prototype, diff --git a/services/sync/modules/bookmark_repair.js b/services/sync/modules/bookmark_repair.js index 0d79d99e09b7..7a03315abf47 100644 --- a/services/sync/modules/bookmark_repair.js +++ b/services/sync/modules/bookmark_repair.js @@ -194,9 +194,11 @@ class BookmarkRepairRequestor extends CollectionRepairRequestor { for (let id of validationInfo.problems.serverMissing) { engine.addForWeakUpload(id); } - let toFetch = engine.toFetch.concat(validationInfo.problems.clientMissing, - validationInfo.problems.serverDeleted); - engine.toFetch = Array.from(new Set(toFetch)); + engine.toFetch = Utils.setAddAll( + Utils.setAddAll(engine.toFetch, + validationInfo.problems.clientMissing), + validationInfo.problems.serverDeleted + ); return true; } diff --git a/services/sync/modules/engines.js b/services/sync/modules/engines.js index 447f07b1ce3c..390f04955ab1 100644 --- a/services/sync/modules/engines.js +++ b/services/sync/modules/engines.js @@ -842,6 +842,9 @@ SyncEngine.prototype = { if (!json.ids) { json.ids = []; } + // The set serializes the same way as an array, but offers more efficient + // methods of manipulation. + json.ids = new SerializableSet(json.ids); return json; }, @@ -911,6 +914,9 @@ SyncEngine.prototype = { }, set toFetch(ids) { + if (ids.constructor.name != "SerializableSet") { + throw new Error("Bug: Attempted to set toFetch to something that isn't a SerializableSet"); + } this._toFetchStorage.data = { ids }; this._toFetchStorage.saveSoon(); }, @@ -919,7 +925,12 @@ SyncEngine.prototype = { this._previousFailedStorage.ensureDataReady(); return this._previousFailedStorage.data.ids; }, + set previousFailed(ids) { + if (ids.constructor.name != "SerializableSet") { + throw new Error( + "Bug: Attempted to set previousFailed to something that isn't a SerializableSet"); + } this._previousFailedStorage.data = { ids }; this._previousFailedStorage.saveSoon(); }, @@ -1100,7 +1111,7 @@ SyncEngine.prototype = { // reconciled => number of items that were reconciled. let count = {applied: 0, failed: 0, newFailed: 0, reconciled: 0}; let recordsToApply = []; - let failedInCurrentSync = []; + let failedInCurrentSync = new SerializableSet(); let oldestModified = this.lastModified; let downloadedIDs = new Set(); @@ -1124,7 +1135,7 @@ SyncEngine.prototype = { let { shouldApply, error } = await this._maybeReconcile(record); if (error) { - failedInCurrentSync.push(record.id); + failedInCurrentSync.add(record.id); count.failed++; continue; } @@ -1136,7 +1147,7 @@ SyncEngine.prototype = { } let failedToApply = await this._applyRecords(recordsToApply); - failedInCurrentSync.push(...failedToApply); + Utils.setAddAll(failedInCurrentSync, failedToApply); // `applied` is a bit of a misnomer: it counts records that *should* be // applied, so it also includes records that we tried to apply and failed. @@ -1165,7 +1176,7 @@ SyncEngine.prototype = { // that in case the Sync server doesn't support `older` (bug 1316110). let remainingIDs = guids.obj.filter(id => !downloadedIDs.has(id)); if (remainingIDs.length > 0) { - this.toFetch = Utils.arrayUnion(this.toFetch, remainingIDs); + this.toFetch = Utils.setAddAll(this.toFetch, remainingIDs); } } @@ -1180,8 +1191,9 @@ SyncEngine.prototype = { // download limit, to prevent a large backlog for one engine from blocking // the others. We'll keep processing the backlog on subsequent engine syncs. let failedInPreviousSync = this.previousFailed; - let idsToBackfill = Utils.arrayUnion(this.toFetch.slice(0, downloadLimit), - failedInPreviousSync); + let idsToBackfill = Array.from( + Utils.setAddAll(Utils.subsetOfSize(this.toFetch, downloadLimit), + failedInPreviousSync)); // Note that we intentionally overwrite the previously failed list here. // Records that fail to decrypt or apply in two consecutive syncs are likely @@ -1230,20 +1242,21 @@ SyncEngine.prototype = { count.failed += failedToApply.length; count.applied += backfilledRecordsToApply.length; - this.toFetch = Utils.arraySub(this.toFetch, ids); - this.previousFailed = Utils.arrayUnion(this.previousFailed, failedInBackfill); + this.toFetch = Utils.setDeleteAll(this.toFetch, ids); + this.previousFailed = Utils.setAddAll(this.previousFailed, failedInBackfill); if (this.lastSync < this.lastModified) { this.lastSync = this.lastModified; } } - count.newFailed = this.previousFailed.reduce((count, engine) => { - if (failedInPreviousSync.indexOf(engine) == -1) { - count++; + count.newFailed = 0; + for (let item of this.previousFailed) { + if (!failedInPreviousSync.has(item)) { + ++count.newFailed; } - return count; - }, 0); + } + count.succeeded = Math.max(0, count.applied - count.failed); this._log.info(["Records:", count.applied, "applied,", @@ -1811,8 +1824,8 @@ SyncEngine.prototype = { async _resetClient() { this.resetLastSync(); - this.previousFailed = []; - this.toFetch = []; + this.previousFailed = new SerializableSet(); + this.toFetch = new SerializableSet(); this._needWeakUpload.clear(); }, diff --git a/services/sync/modules/util.js b/services/sync/modules/util.js index 920991aee69e..304da82e1e31 100644 --- a/services/sync/modules/util.js +++ b/services/sync/modules/util.js @@ -2,7 +2,7 @@ * 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/. */ -this.EXPORTED_SYMBOLS = ["Utils", "Svc"]; +this.EXPORTED_SYMBOLS = ["Utils", "Svc", "SerializableSet"]; var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; @@ -524,6 +524,47 @@ this.Utils = { return foo.concat(Utils.arraySub(bar, foo)); }, + /** + * Add all the items in `items` to the provided Set in-place. + * + * @return The provided set. + */ + setAddAll(set, items) { + for (let item of items) { + set.add(item); + } + return set; + }, + + /** + * Delete every items in `items` to the provided Set in-place. + * + * @return The provided set. + */ + setDeleteAll(set, items) { + for (let item of items) { + set.delete(item); + } + return set; + }, + + /** + * Take the first `size` items from the Set `items`. + * + * @return A Set of size at most `size` + */ + subsetOfSize(items, size) { + let result = new Set(); + let count = 0; + for (let item of items) { + if (count++ == size) { + return result; + } + result.add(item); + } + return result; + }, + bind2: function Async_bind2(object, method) { return function innerBind() { return method.apply(object, arguments); }; }, @@ -703,6 +744,15 @@ this.Utils = { } }; +/** + * A subclass of Set that serializes as an Array when passed to JSON.stringify. + */ +class SerializableSet extends Set { + toJSON() { + return Array.from(this); + } +} + XPCOMUtils.defineLazyGetter(Utils, "_utf8Converter", function() { let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index ef9f5ed559ab..8621a8bfeefa 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -170,7 +170,7 @@ add_task(async function test_processIncoming_error_orderChildren() { // Make the 10 minutes old so it will only be synced in the toFetch phase. bogus_record.modified = Date.now() / 1000 - 60 * 10; engine.lastSync = Date.now() / 1000 - 60; - engine.toFetch = [BOGUS_GUID]; + engine.toFetch = new SerializableSet([BOGUS_GUID]); let error; try { diff --git a/services/sync/tests/unit/test_history_engine.js b/services/sync/tests/unit/test_history_engine.js index 67ebe516ecef..2547f0c656d1 100644 --- a/services/sync/tests/unit/test_history_engine.js +++ b/services/sync/tests/unit/test_history_engine.js @@ -69,7 +69,7 @@ add_task(async function test_history_download_limit() { let ping = await sync_engine_and_validate_telem(engine, false); deepEqual(ping.engines[0].incoming, { applied: 5 }); - let backlogAfterFirstSync = engine.toFetch.slice(0); + let backlogAfterFirstSync = Array.from(engine.toFetch).sort(); deepEqual(backlogAfterFirstSync, ["place0000000", "place0000001", "place0000002", "place0000003", "place0000004", "place0000005", "place0000006", "place0000007", "place0000008", "place0000009"]); @@ -84,7 +84,7 @@ add_task(async function test_history_download_limit() { // After the second sync, our backlog still contains the same GUIDs: we // weren't able to make progress on fetching them, since our // `guidFetchBatchSize` is 0. - let backlogAfterSecondSync = engine.toFetch.slice(0); + let backlogAfterSecondSync = Array.from(engine.toFetch).sort(); deepEqual(backlogAfterFirstSync, backlogAfterSecondSync); // Now add a newer record to the server. @@ -105,7 +105,7 @@ add_task(async function test_history_download_limit() { deepEqual(ping.engines[0].incoming, { applied: 1 }); // Our backlog should remain the same. - let backlogAfterThirdSync = engine.toFetch.slice(0); + let backlogAfterThirdSync = Array.from(engine.toFetch).sort(); deepEqual(backlogAfterSecondSync, backlogAfterThirdSync); equal(engine.lastSync, lastSync + 20); @@ -118,15 +118,16 @@ add_task(async function test_history_download_limit() { ping = await sync_engine_and_validate_telem(engine, false); deepEqual(ping.engines[0].incoming, { applied: 5 }); - deepEqual(engine.toFetch, ["place0000005", "place0000006", "place0000007", - "place0000008", "place0000009"]); + deepEqual( + Array.from(engine.toFetch).sort(), + ["place0000005", "place0000006", "place0000007", "place0000008", "place0000009"]); // Sync again to clear out the backlog. engine.lastModified = collection.modified; ping = await sync_engine_and_validate_telem(engine, false); deepEqual(ping.engines[0].incoming, { applied: 5 }); - deepEqual(engine.toFetch, []); + deepEqual(Array.from(engine.toFetch), []); await PlacesTestUtils.clearHistory(); }); diff --git a/services/sync/tests/unit/test_syncengine.js b/services/sync/tests/unit/test_syncengine.js index baf2665acb48..f92e5650180a 100644 --- a/services/sync/tests/unit/test_syncengine.js +++ b/services/sync/tests/unit/test_syncengine.js @@ -12,6 +12,16 @@ async function makeSteamEngine() { return engine; } +function guidSetOfSize(length) { + return new SerializableSet( + Array.from({ length }, () => Utils.makeGUID())); +} + +function assertSetsEqual(a, b) { + // Assert.deepEqual doesn't understand Set. + Assert.deepEqual(Array.from(a).sort(), Array.from(b).sort()); +} + async function testSteamEngineStorage(test) { try { let setupEngine = await makeSteamEngine(); @@ -113,10 +123,10 @@ add_task(async function test_toFetch() { const filename = "weave/toFetch/steam.json"; await testSteamEngineStorage({ - toFetch: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], + toFetch: guidSetOfSize(3), setup(engine) { // Ensure pristine environment - Assert.equal(engine.toFetch.length, 0); + Assert.equal(engine.toFetch.size, 0); // Write file to disk engine.toFetch = this.toFetch; @@ -124,13 +134,13 @@ add_task(async function test_toFetch() { }, check(engine) { // toFetch is written asynchronously - Assert.deepEqual(engine.toFetch, this.toFetch); + assertSetsEqual(engine.toFetch, this.toFetch); }, }); await testSteamEngineStorage({ - toFetch: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], - toFetch2: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], + toFetch: guidSetOfSize(4), + toFetch2: guidSetOfSize(5), setup(engine) { // Make sure it work for consecutive writes before the callback is executed. engine.toFetch = this.toFetch; @@ -140,12 +150,12 @@ add_task(async function test_toFetch() { Assert.equal(engine.toFetch, this.toFetch2); }, check(engine) { - Assert.deepEqual(engine.toFetch, this.toFetch2); + assertSetsEqual(engine.toFetch, this.toFetch2); }, }); await testSteamEngineStorage({ - toFetch: [Utils.makeGUID(), Utils.makeGUID()], + toFetch: guidSetOfSize(2), async beforeCheck() { let toFetchPath = OS.Path.join(OS.Constants.Path.profileDir, filename); let bytes = new TextEncoder().encode(JSON.stringify(this.toFetch)); @@ -154,7 +164,7 @@ add_task(async function test_toFetch() { }, check(engine) { // Read file from disk - Assert.deepEqual(engine.toFetch, this.toFetch); + assertSetsEqual(engine.toFetch, this.toFetch); }, }); }); @@ -165,10 +175,10 @@ add_task(async function test_previousFailed() { const filename = "weave/failed/steam.json"; await testSteamEngineStorage({ - previousFailed: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], + previousFailed: guidSetOfSize(3), setup(engine) { // Ensure pristine environment - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.previousFailed.size, 0); // Write file to disk engine.previousFailed = this.previousFailed; @@ -176,13 +186,13 @@ add_task(async function test_previousFailed() { }, check(engine) { // previousFailed is written asynchronously - Assert.deepEqual(engine.previousFailed, this.previousFailed); + assertSetsEqual(engine.previousFailed, this.previousFailed); }, }); await testSteamEngineStorage({ - previousFailed: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], - previousFailed2: [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()], + previousFailed: guidSetOfSize(4), + previousFailed2: guidSetOfSize(5), setup(engine) { // Make sure it work for consecutive writes before the callback is executed. engine.previousFailed = this.previousFailed; @@ -192,12 +202,12 @@ add_task(async function test_previousFailed() { Assert.equal(engine.previousFailed, this.previousFailed2); }, check(engine) { - Assert.deepEqual(engine.previousFailed, this.previousFailed2); + assertSetsEqual(engine.previousFailed, this.previousFailed2); }, }); await testSteamEngineStorage({ - previousFailed: [Utils.makeGUID(), Utils.makeGUID()], + previousFailed: guidSetOfSize(2), async beforeCheck() { let previousFailedPath = OS.Path.join(OS.Constants.Path.profileDir, filename); @@ -207,7 +217,7 @@ add_task(async function test_previousFailed() { }, check(engine) { // Read file from disk - Assert.deepEqual(engine.previousFailed, this.previousFailed); + assertSetsEqual(engine.previousFailed, this.previousFailed); }, }); }); @@ -220,18 +230,18 @@ add_task(async function test_resetClient() { // Ensure pristine environment Assert.equal(Svc.Prefs.get("steam.lastSync"), undefined); Assert.equal(Svc.Prefs.get("steam.lastSyncLocal"), undefined); - Assert.equal(engine.toFetch.length, 0); + Assert.equal(engine.toFetch.size, 0); engine.lastSync = 123.45; engine.lastSyncLocal = 67890; - engine.toFetch = [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()]; - engine.previousFailed = [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()]; + engine.toFetch = guidSetOfSize(4); + engine.previousFailed = guidSetOfSize(3); await engine.resetClient(); Assert.equal(engine.lastSync, 0); Assert.equal(engine.lastSyncLocal, 0); - Assert.equal(engine.toFetch.length, 0); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.toFetch.size, 0); + Assert.equal(engine.previousFailed.size, 0); } finally { Svc.Prefs.resetBranch(""); } @@ -252,13 +262,13 @@ add_task(async function test_wipeServer() { try { // Some data to reset. engine.lastSync = 123.45; - engine.toFetch = [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()]; + engine.toFetch = guidSetOfSize(3), _("Wipe server data and reset client."); await engine.wipeServer(); Assert.equal(steamCollection.payload, undefined); Assert.equal(engine.lastSync, 0); - Assert.equal(engine.toFetch.length, 0); + Assert.equal(engine.toFetch.size, 0); } finally { steamServer.stop(do_test_finished); diff --git a/services/sync/tests/unit/test_syncengine_sync.js b/services/sync/tests/unit/test_syncengine_sync.js index a30d8512e52f..3788f19bfbd2 100644 --- a/services/sync/tests/unit/test_syncengine_sync.js +++ b/services/sync/tests/unit/test_syncengine_sync.js @@ -627,8 +627,8 @@ add_task(async function test_processIncoming_resume_toFetch() { // Time travel 10 seconds into the future but still download the above WBOs. let engine = makeRotaryEngine(); engine.lastSync = LASTSYNC; - engine.toFetch = ["flying", "scotsman"]; - engine.previousFailed = ["failed0", "failed1", "failed2"]; + engine.toFetch = new SerializableSet(["flying", "scotsman"]); + engine.previousFailed = new SerializableSet(["failed0", "failed1", "failed2"]); let server = sync_httpd_setup({ "/1.1/foo/storage/rotary": collection.handler() @@ -657,7 +657,7 @@ add_task(async function test_processIncoming_resume_toFetch() { Assert.equal(engine._store.items.failed0, "Record No. 0"); Assert.equal(engine._store.items.failed1, "Record No. 1"); Assert.equal(engine._store.items.failed2, "Record No. 2"); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.previousFailed.size, 0); } finally { await cleanAndGo(engine, server); } @@ -703,8 +703,8 @@ add_task(async function test_processIncoming_notify_count() { try { // Confirm initial environment. Assert.equal(engine.lastSync, 0); - Assert.equal(engine.toFetch.length, 0); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.toFetch.size, 0); + Assert.equal(engine.previousFailed.size, 0); do_check_empty(engine._store.items); let called = 0; @@ -722,8 +722,8 @@ add_task(async function test_processIncoming_notify_count() { // Confirm failures. do_check_attribute_count(engine._store.items, 12); - Assert.deepEqual(engine.previousFailed, ["record-no-00", "record-no-05", - "record-no-10"]); + Assert.deepEqual(Array.from(engine.previousFailed).sort(), + ["record-no-00", "record-no-05", "record-no-10"].sort()); // There are newly failed records and they are reported. Assert.equal(called, 1); @@ -737,7 +737,7 @@ add_task(async function test_processIncoming_notify_count() { // Confirming removed failures. do_check_attribute_count(engine._store.items, 14); - Assert.deepEqual(engine.previousFailed, ["record-no-00"]); + Assert.deepEqual(Array.from(engine.previousFailed), ["record-no-00"]); Assert.equal(called, 2); Assert.equal(counts.failed, 1); @@ -792,12 +792,12 @@ add_task(async function test_processIncoming_previousFailed() { try { // Confirm initial environment. Assert.equal(engine.lastSync, 0); - Assert.equal(engine.toFetch.length, 0); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.toFetch.size, 0); + Assert.equal(engine.previousFailed.size, 0); do_check_empty(engine._store.items); // Initial failed items in previousFailed to be reset. - let previousFailed = [Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()]; + let previousFailed = new SerializableSet([Utils.makeGUID(), Utils.makeGUID(), Utils.makeGUID()]); engine.previousFailed = previousFailed; Assert.equal(engine.previousFailed, previousFailed); @@ -807,9 +807,10 @@ add_task(async function test_processIncoming_previousFailed() { // Expected result: 4 sync batches with 2 failures each => 8 failures do_check_attribute_count(engine._store.items, 6); - Assert.deepEqual(engine.previousFailed, ["record-no-00", "record-no-01", - "record-no-04", "record-no-05", "record-no-08", "record-no-09", - "record-no-12", "record-no-13"]); + Assert.deepEqual( + Array.from(engine.previousFailed).sort(), + ["record-no-00", "record-no-01", "record-no-04", "record-no-05", + "record-no-08", "record-no-09", "record-no-12", "record-no-13"].sort()); // Sync again with the same failed items (records 0, 1, 8, 9). await engine._processIncoming(); @@ -817,8 +818,9 @@ add_task(async function test_processIncoming_previousFailed() { // A second sync with the same failed items should not add the same items again. // Items that did not fail a second time should no longer be in previousFailed. do_check_attribute_count(engine._store.items, 10); - Assert.deepEqual(engine.previousFailed, ["record-no-00", "record-no-01", - "record-no-08", "record-no-09"]); + Assert.deepEqual( + Array.from(engine.previousFailed).sort(), + ["record-no-00", "record-no-01", "record-no-08", "record-no-09"].sort()); // Refetched items that didn't fail the second time are in engine._store.items. Assert.equal(engine._store.items["record-no-04"], "Record No. 4"); @@ -900,8 +902,8 @@ add_task(async function test_processIncoming_failed_records() { // Confirm initial environment Assert.equal(engine.lastSync, 0); - Assert.equal(engine.toFetch.length, 0); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.toFetch.size, 0); + Assert.equal(engine.previousFailed.size, 0); do_check_empty(engine._store.items); let observerSubject; @@ -920,8 +922,8 @@ add_task(async function test_processIncoming_failed_records() { NUMBER_OF_RECORDS - BOGUS_RECORDS.length); // Ensure that the bogus records will be fetched again on the next sync. - Assert.equal(engine.previousFailed.length, BOGUS_RECORDS.length); - Assert.deepEqual(engine.previousFailed.sort(), BOGUS_RECORDS.sort()); + Assert.equal(engine.previousFailed.size, BOGUS_RECORDS.length); + Assert.deepEqual(Array.from(engine.previousFailed).sort(), BOGUS_RECORDS.sort()); // Ensure the observer was notified Assert.equal(observerData, engine.name); @@ -999,8 +1001,8 @@ add_task(async function test_processIncoming_decrypt_failed() { try { // Confirm initial state - Assert.equal(engine.toFetch.length, 0); - Assert.equal(engine.previousFailed.length, 0); + Assert.equal(engine.toFetch.size, 0); + Assert.equal(engine.previousFailed.size, 0); let observerSubject; let observerData; @@ -1016,11 +1018,11 @@ add_task(async function test_processIncoming_decrypt_failed() { Assert.equal(ping.engines[0].incoming.failed, 4); Assert.equal(ping.engines[0].incoming.newFailed, 4); - Assert.equal(engine.previousFailed.length, 4); - Assert.equal(engine.previousFailed[0], "nojson"); - Assert.equal(engine.previousFailed[1], "nojson2"); - Assert.equal(engine.previousFailed[2], "nodecrypt"); - Assert.equal(engine.previousFailed[3], "nodecrypt2"); + Assert.equal(engine.previousFailed.size, 4); + Assert.ok(engine.previousFailed.has("nojson")); + Assert.ok(engine.previousFailed.has("nojson2")); + Assert.ok(engine.previousFailed.has("nodecrypt")); + Assert.ok(engine.previousFailed.has("nodecrypt2")); // Ensure the observer was notified Assert.equal(observerData, engine.name); diff --git a/services/sync/tests/unit/test_telemetry.js b/services/sync/tests/unit/test_telemetry.js index 82f0e0f827d2..d5720c18b81c 100644 --- a/services/sync/tests/unit/test_telemetry.js +++ b/services/sync/tests/unit/test_telemetry.js @@ -122,7 +122,7 @@ add_task(async function test_processIncoming_error() { // Make the 10 minutes old so it will only be synced in the toFetch phase. bogus_record.modified = Date.now() / 1000 - 60 * 10; engine.lastSync = Date.now() / 1000 - 60; - engine.toFetch = [BOGUS_GUID]; + engine.toFetch = new SerializableSet([BOGUS_GUID]); let error, pingPayload, fullPing; try { diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json index 71aedc68d180..f3454136d5f3 100644 --- a/tools/lint/eslint/modules.json +++ b/tools/lint/eslint/modules.json @@ -208,7 +208,7 @@ "Traversal.jsm": ["TraversalRules", "TraversalHelper"], "UpdateTelemetry.jsm": ["AUSTLMY"], "UpdateTopLevelContentWindowIDHelper.jsm": ["trackBrowserWindow"], - "util.js": ["getChromeWindow", "Utils", "Svc"], + "util.js": ["getChromeWindow", "Utils", "Svc", "SerializableSet"], "utils.js": ["btoa", "encryptPayload", "makeIdentityConfig", "makeFxAccountsInternalMock", "configureFxAccountIdentity", "configureIdentity", "SyncTestingInfrastructure", "waitForZeroTimer", "Promise", "MockFxaStorageManager", "AccountState", "sumHistogram", "CommonUtils", "CryptoUtils", "TestingUtils", "promiseZeroTimer", "promiseNamedTimer", "getLoginTelemetryScalar", "syncTestLogging"], "Utils.jsm": ["Utils", "Logger", "PivotContext", "PrefCache"], "VariablesView.jsm": ["VariablesView", "escapeHTML"], From cf332b3975180c59f52f09afb1cb8af1c34228f3 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 26 Jan 2018 12:58:50 -0600 Subject: [PATCH 06/46] servo: Merge #18726 - Add script to automate pulling changes from upstream WPT (from jdm:automate-wpt-sync); r=asajeffrey I want to make automated WPT syncing happen this quarter. This script should allow us to run a nightly job on the builder that grabs the latest changes from upstream runs our testsuite, updates the expected test results, then open a PR with the changes. It still requires saltfs changes to allow it to actually run, but I don't see any harm in getting it reviewed and merged before everything is ready. Source-Repo: https://github.com/servo/servo Source-Revision: ce17959f7c5f817bc5739c6693c93cafb1855f4f --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 21ffe7b18cf46b8811793fa78c685973c238f7b9 --- servo/etc/ci/buildbot_steps.yml | 3 + servo/etc/ci/update-wpt-checkout | 186 +++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100755 servo/etc/ci/update-wpt-checkout diff --git a/servo/etc/ci/buildbot_steps.yml b/servo/etc/ci/buildbot_steps.yml index 3c6d7ca67355..df86cee287e1 100644 --- a/servo/etc/ci/buildbot_steps.yml +++ b/servo/etc/ci/buildbot_steps.yml @@ -72,6 +72,9 @@ mac-nightly: - env PKG_CONFIG_PATH=/usr/local/opt/zlib/lib/pkgconfig ./mach build --release - ./mach package --release - ./mach upload-nightly mac + - ./etc/ci/update-wpt-checkout fetch-and-update-expectations + - ./etc/ci/update-wpt-checkout open-pr + - ./etc/ci/update-wpt-checkout cleanup linux-rel-intermittent: - ./mach clean-nightlies --keep 3 --force diff --git a/servo/etc/ci/update-wpt-checkout b/servo/etc/ci/update-wpt-checkout new file mode 100755 index 000000000000..6203d4641917 --- /dev/null +++ b/servo/etc/ci/update-wpt-checkout @@ -0,0 +1,186 @@ +#!/usr/bin/env bash + +# 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/. + +set -o errexit +set -o nounset +set -o pipefail + +REMOTE_NAME=sync-fork +LOG_FILE=test-wpt.log +CURRENT_DATE=$(date +"%d-%m-%Y") +BRANCH_NAME="wpt_update_${CURRENT_DATE}" + +export GIT_AUTHOR_NAME="WPT Sync Bot" +export GIT_AUTHOR_EMAIL="josh+wptsync@joshmatthews.net" + +# Retrieve the HEAD commit and extract its hash +function latest_git_commit() { + git log -1 --oneline | cut -f 1 -d ' ' +} + +# Create a new branch for this sync, pull down all changes from the upstream +# web-platform-tests repository, and commit the changes. +function unsafe_pull_from_upstream() { + git checkout -b "${1}" || return 1 + + OLD_COMMIT=$(latest_git_commit) + + # Fetch all changes from upstream WPT and automatically transpose them + # into a single servo commit. + ./mach update-wpt --sync --no-upstream --patch || return 2 + + # If there was no new commit created, there are no changes that need syncing. + # Skip the remaining steps. + if [[ "$(latest_git_commit)" == "${OLD_COMMIT}" ]]; then + return 255 + fi + + # Update the manifest to include the new changes. + ./mach update-manifest || return 3 + + # Amend the existing commit with the new changes from updating the manifest. + git commit -a --amend --no-edit || return 4 +} + +# Remove all local traces of this sync operation. +function cleanup() { + git remote rm "${REMOTE_NAME}" || true + git reset --hard || true + git checkout master || true + git branch -D "${BRANCH_NAME}" || true + ./mach update-wpt --abort || true +} + +# Build Servo and run the full WPT testsuite, saving the results to a log file. +function unsafe_run_tests() { + # Run the full testsuite and record the new test results. + ./mach test-wpt --release --processes 24 --log-raw "${1}" \ + --always-succeed || return 1 +} + +# Using an existing log file, update the expected test results and amend the +# last commit with the new results. +function unsafe_update_metadata() { + ./mach update-wpt "${1}" || return 1 + # Ignore any metadata changes to files that weren't modified by this sync. + git checkout -- tests/wpt/mozilla/meta || return 2 + # Ensure any new directories or ini files are included in these changes. + git add tests/wpt/metadata || return 3 + # Merge all changes with the existing commit. + git commit -a --amend --no-edit || return 4 +} + +# Push the branch to a remote branch, then open a PR for the branch +# against servo/servo. +function unsafe_open_pull_request() { + WPT_SYNC_USER=servo-wpt-sync + + # If the branch doesn't exist, we'll silently exit. This deals with the + # case where an earlier step either failed or discovered that syncing + # is unnecessary. + git checkout "${BRANCH_NAME}" || return 0 + + if [[ -z "${WPT_SYNC_TOKEN+set}" ]]; then + echo "Github auth token missing from WPT_SYNC_TOKEN." + return 1 + fi + + # Push the changes to a remote branch owned by the bot. + AUTH="${WPT_SYNC_USER}:${WPT_SYNC_TOKEN}" + UPSTREAM="https://${AUTH}@github.com/${WPT_SYNC_USER}/servo.git" + git remote add "${REMOTE_NAME}" "${UPSTREAM}" || return 2 + git push -f "${REMOTE_NAME}" "${BRANCH_NAME}" || return 3 + + # Prepare the pull request metadata. + BODY="Automated downstream sync of changes from upstream as of " + BODY+="${CURRENT_DATE}.\n" + BODY+="[no-wpt-sync]" + cat <prdata.json || return 4 +{ + "title": "Sync WPT with upstream (${CURRENT_DATE})", + "head": "${WPT_SYNC_USER}:${BRANCH_NAME}", + "base": "master", + "body": "${BODY}", + "maintainer_can_modify": true +} +EOF + + # Open a pull request using the new branch. + curl -H "Authorization: token ${WPT_SYNC_TOKEN}" \ + -H "Content-Type: application/json" \ + --data @prdata.json \ + https://api.github.com/repos/servo/servo/pulls || return 4 +} + +function pull_from_upstream() { + unsafe_pull_from_upstream "${1}" || { code="${?}"; cleanup; return "${code}"; } +} + +function run_tests() { + unsafe_run_tests "${1}" || { code="${?}"; cleanup; return "${code}"; } +} + +function update_metadata() { + unsafe_update_metadata "${1}" || { code="${?}"; cleanup; return "${code}"; } +} + +function open_pull_request() { + unsafe_open_pull_request || { code="${?}"; cleanup; return "${code}"; } +} + +SCRIPT_NAME="${0}" + +function update_test_results() { + run_tests "${LOG_FILE}" + update_metadata "${LOG_FILE}" +} + +function fetch_upstream_changes() { + pull_from_upstream "${BRANCH_NAME}" +} + +function usage() { + echo "usage: ${SCRIPT_NAME} [cmd]" + echo " commands:" + echo " - fetch-upstream-changes: create a branch with the latest changes from upstream" + echo " - update-test-results: run the tests, update the expected test results, and commit the changes" + echo " - fetch-and-update-expectations: combines fetch-upstream-changes and update-test-results" + echo " - open-pr: open a pull request with the latest changes" + echo " - cleanup: cleanup all traces of an in-progress sync and checkout the master branch" + exit 1 +} + +function main() { + if [[ "${1}" == "fetch-upstream-changes" ]] || [[ "${1}" == "fetch-and-update-expectations" ]]; then + code="" + fetch_upstream_changes || code="${?}" + if [[ "${code}" == "255" ]]; then + echo "No changes to sync." + return 0 + fi + fi + + if [[ "${1}" == "update-test-results" ]] || [[ "${1}" == "fetch-and-update-expectations" ]]; then + update_test_results + + elif [[ "${1}" == "open-pr" ]]; then + open_pull_request + + elif [[ "${1}" == "cleanup" ]]; then + cleanup + + else + usage + fi +} + +if [[ "$#" != 1 ]]; then + usage +fi + +# Ensure we clean up after ourselves if this script is interrupted. +trap 'cleanup' SIGINT SIGTERM +main "${1}" From 78404351388d8ddb2319389d8120380319f7f0bd Mon Sep 17 00:00:00 2001 From: David Keeler Date: Fri, 19 Jan 2018 13:09:22 -0800 Subject: [PATCH 07/46] bug 1431791 - remove "Others" tab from certificate manager r=jaws,mgoodwin MozReview-Commit-ID: HUPkIAMhNEX --HG-- extra : rebase_source : a737297d8cb8800b03532d62b39e85711d6f0663 --- .../preferences/in-content/privacy.xul | 2 - .../en-US/chrome/pippki/certManager.dtd | 2 - .../en-US/chrome/pippki/pippki.properties | 3 -- .../pki/resources/content/OrphanOverlay.xul | 47 ------------------- .../pki/resources/content/certManager.js | 32 ------------- .../pki/resources/content/certManager.xul | 3 -- .../pki/resources/content/deletecert.js | 5 -- security/manager/pki/resources/jar.mn | 1 - security/manager/ssl/nsCertTree.cpp | 8 ---- .../browser/browser_deleteCert_ui.js | 10 ---- 10 files changed, 113 deletions(-) delete mode 100644 security/manager/pki/resources/content/OrphanOverlay.xul diff --git a/browser/components/preferences/in-content/privacy.xul b/browser/components/preferences/in-content/privacy.xul index ec37e90060c7..4396861d12cc 100644 --- a/browser/components/preferences/in-content/privacy.xul +++ b/browser/components/preferences/in-content/privacy.xul @@ -672,12 +672,10 @@ &certmgr.tab.others2; &certmgr.tab.websites3; &certmgr.tab.ca; - &certmgr.tab.orphan2; &certmgr.mine2; &certmgr.others2; &certmgr.websites3; &certmgr.cas2; - &certmgr.orphans2; &certmgr.certname; &certmgr.tokenname; &certmgr.view2.label; diff --git a/security/manager/locales/en-US/chrome/pippki/certManager.dtd b/security/manager/locales/en-US/chrome/pippki/certManager.dtd index e6318e1ce096..2133f3047688 100644 --- a/security/manager/locales/en-US/chrome/pippki/certManager.dtd +++ b/security/manager/locales/en-US/chrome/pippki/certManager.dtd @@ -8,13 +8,11 @@ - - diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 163384651067..ed3b867ed260 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -32,9 +32,6 @@ deleteEmailCertConfirm=Are you sure you want to delete these people’s e-mail c deleteEmailCertImpactDesc=If you delete a person’s e-mail certificate, you will no longer be able to send encrypted e-mail to that person. deleteEmailCertTitle=Delete E-Mail Certificates -deleteOrphanCertConfirm=Are you sure you want to delete these certificates? -deleteOrphanCertTitle=Delete Certificates - # PKCS#12 file dialogs chooseP12RestoreFileDialog2=Certificate File to Import chooseP12BackupFileDialog=File Name to Backup diff --git a/security/manager/pki/resources/content/OrphanOverlay.xul b/security/manager/pki/resources/content/OrphanOverlay.xul deleted file mode 100644 index c267d0f7bef6..000000000000 --- a/security/manager/pki/resources/content/OrphanOverlay.xul +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - &certmgr.orphans2; - - - - - - - - - - - - - -