mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
368f1bcefd
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a3e4614c7fb0a6ffa8c748bf5d49b34612c9d6d4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a3e4614c7fb0a6ffa8c748bf5d49b34612c9d6d4"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "5686a4726b2c90d5bd20cf96f8e97038cbe3f083",
|
||||
"revision": "5f064a62ce5ee63c6f75ff3422a7472bec71f7bf",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a3e4614c7fb0a6ffa8c748bf5d49b34612c9d6d4"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e429d970c160e580e19e61ad8ff5612de159f00"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cfde14a9fc87659963092a6b9d7898a8c23ec74"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -71,6 +71,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "roomsPushNotification",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
|
||||
"resource:///modules/loop/MozLoopPushHandler.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
||||
"resource:///modules/UITour.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
@ -810,6 +813,11 @@ let MozLoopServiceInternal = {
|
||||
chatbox.removeEventListener("DOMContentLoaded", loaded, true);
|
||||
|
||||
let window = chatbox.contentWindow;
|
||||
|
||||
window.addEventListener("unload", function onUnloadChat(evt) {
|
||||
UITour.notify("Loop:ChatWindowClosed");
|
||||
});
|
||||
|
||||
injectLoopAPI(window);
|
||||
|
||||
let ourID = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@ -850,6 +858,8 @@ let MozLoopServiceInternal = {
|
||||
|
||||
let pc_static = new window.mozRTCPeerConnectionStatic();
|
||||
pc_static.registerPeerConnectionLifecycleCallback(onPCLifecycleChange);
|
||||
|
||||
UITour.notify("Loop:ChatWindowOpened");
|
||||
}.bind(this), true);
|
||||
};
|
||||
|
||||
|
@ -52,12 +52,16 @@ function submit() {
|
||||
// Show the "connecting" screen
|
||||
document.body.classList.add("connecting");
|
||||
|
||||
// Save the host/port values
|
||||
let host = document.getElementById("host").value;
|
||||
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
|
||||
|
||||
let port = document.getElementById("port").value;
|
||||
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
|
||||
|
||||
// Save the host/port values
|
||||
try {
|
||||
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
|
||||
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
|
||||
} catch(e) {
|
||||
// Fails in e10s mode, but not a critical feature.
|
||||
}
|
||||
|
||||
// Initiate the connection
|
||||
let transport;
|
||||
|
@ -88,12 +88,12 @@ browser.jar:
|
||||
content/browser/devtools/ui-profile.js (profiler/ui-profile.js)
|
||||
#ifdef MOZ_DEVTOOLS_PERFTOOLS
|
||||
content/browser/devtools/performance.xul (performance/performance.xul)
|
||||
content/browser/devtools/performance/controller.js (performance/controller.js)
|
||||
content/browser/devtools/performance/views/main.js (performance/views/main.js)
|
||||
content/browser/devtools/performance/performance-controller.js (performance/performance-controller.js)
|
||||
content/browser/devtools/performance/performance-view.js (performance/performance-view.js)
|
||||
content/browser/devtools/performance/views/overview.js (performance/views/overview.js)
|
||||
content/browser/devtools/performance/views/details.js (performance/views/details.js)
|
||||
content/browser/devtools/performance/views/call-tree.js (performance/views/call-tree.js)
|
||||
content/browser/devtools/performance/views/waterfall.js (performance/views/waterfall.js)
|
||||
content/browser/devtools/performance/views/details-call-tree.js (performance/views/details-call-tree.js)
|
||||
content/browser/devtools/performance/views/details-waterfall.js (performance/views/details-waterfall.js)
|
||||
#endif
|
||||
content/browser/devtools/responsivedesign/resize-commands.js (responsivedesign/resize-commands.js)
|
||||
content/browser/devtools/commandline.css (commandline/commandline.css)
|
||||
|
@ -108,7 +108,7 @@ PerformanceActorsConnection.prototype = {
|
||||
if (this._target.chrome) {
|
||||
this._profiler = this._target.form.profilerActor;
|
||||
}
|
||||
// Or when we are debugging content processes, we already have the tab
|
||||
// When we are debugging content processes, we already have the tab
|
||||
// specific one. Use it immediately.
|
||||
else if (this._target.form && this._target.form.profilerActor) {
|
||||
this._profiler = this._target.form.profilerActor;
|
||||
|
@ -7,22 +7,19 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
let require = devtools.require;
|
||||
devtools.lazyRequireGetter(this, "Services");
|
||||
devtools.lazyRequireGetter(this, "promise");
|
||||
devtools.lazyRequireGetter(this, "EventEmitter",
|
||||
"devtools/toolkit/event-emitter");
|
||||
devtools.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/toolkit/DevToolsUtils");
|
||||
devtools.lazyRequireGetter(this, "FramerateFront",
|
||||
"devtools/server/actors/framerate", true);
|
||||
devtools.lazyRequireGetter(this, "L10N",
|
||||
"devtools/profiler/global", true);
|
||||
devtools.lazyImporter(this, "LineGraphWidget",
|
||||
"resource:///modules/devtools/Graphs.jsm");
|
||||
devtools.lazyRequireGetter(this, "FramerateFront",
|
||||
"devtools/server/actors/framerate", true);
|
||||
devtools.lazyRequireGetter(this, "Waterfall",
|
||||
"devtools/timeline/waterfall", true);
|
||||
devtools.lazyRequireGetter(this, "MarkerDetails",
|
||||
@ -32,6 +29,9 @@ devtools.lazyRequireGetter(this, "CallView",
|
||||
devtools.lazyRequireGetter(this, "ThreadNode",
|
||||
"devtools/profiler/tree-model", true);
|
||||
|
||||
devtools.lazyImporter(this, "LineGraphWidget",
|
||||
"resource:///modules/devtools/Graphs.jsm");
|
||||
|
||||
// Events emitted by the `PerformanceController`
|
||||
const EVENTS = {
|
||||
// When a recording is started or stopped via the controller
|
||||
@ -154,10 +154,11 @@ let PerformanceController = {
|
||||
*/
|
||||
stopRecording: Task.async(function *() {
|
||||
let results = yield gFront.stopRecording();
|
||||
// If `endTime` is not yielded from timeline actor (< Fx36),
|
||||
// fake an endTime
|
||||
|
||||
// If `endTime` is not yielded from timeline actor (< Fx36), fake an endTime.
|
||||
if (!results.endTime) {
|
||||
this._endTime = results.endTime = this._startTime + (performance.now() - this._localStartTime);
|
||||
results.endTime = this._startTime + (performance.now() - this._localStartTime);
|
||||
this._endTime = results.endTime;
|
||||
}
|
||||
|
||||
this.emit(EVENTS.RECORDING_STOPPED, results);
|
@ -14,12 +14,12 @@
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://browser/content/devtools/theme-switching.js"/>
|
||||
<script type="application/javascript" src="performance/controller.js"/>
|
||||
<script type="application/javascript" src="performance/views/main.js"/>
|
||||
<script type="application/javascript" src="performance/performance-controller.js"/>
|
||||
<script type="application/javascript" src="performance/performance-view.js"/>
|
||||
<script type="application/javascript" src="performance/views/overview.js"/>
|
||||
<script type="application/javascript" src="performance/views/details.js"/>
|
||||
<script type="application/javascript" src="performance/views/call-tree.js"/>
|
||||
<script type="application/javascript" src="performance/views/waterfall.js"/>
|
||||
<script type="application/javascript" src="performance/views/details-call-tree.js"/>
|
||||
<script type="application/javascript" src="performance/views/details-waterfall.js"/>
|
||||
|
||||
<vbox class="theme-body" flex="1">
|
||||
<toolbar id="performance-toolbar" class="devtools-toolbar">
|
||||
|
@ -4,7 +4,7 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Waterfall view controlled by DetailsView.
|
||||
* Waterfall view containing the timeline markers, controlled by DetailsView.
|
||||
*/
|
||||
let WaterfallView = {
|
||||
_startTime: 0,
|
@ -6,7 +6,7 @@
|
||||
const DEFAULT_DETAILS_SUBVIEW = "waterfall";
|
||||
|
||||
/**
|
||||
* Details view containing profiler call tree. Manages
|
||||
* Details view containing profiler call tree and markers waterfall. Manages
|
||||
* subviews and toggles visibility between them.
|
||||
*/
|
||||
let DetailsView = {
|
||||
|
@ -27,6 +27,7 @@ support-files =
|
||||
[browser_graphs-09a.js]
|
||||
[browser_graphs-09b.js]
|
||||
[browser_graphs-09c.js]
|
||||
[browser_graphs-09d.js]
|
||||
[browser_graphs-10a.js]
|
||||
[browser_graphs-10b.js]
|
||||
[browser_graphs-11a.js]
|
||||
|
41
browser/devtools/shared/test/browser_graphs-09d.js
Normal file
41
browser/devtools/shared/test/browser_graphs-09d.js
Normal file
@ -0,0 +1,41 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that line graphs hide the 'max' tooltip when the distance between
|
||||
// the 'min' and 'max' tooltip is too small.
|
||||
|
||||
const TEST_DATA = [{ delta: 100, value: 60 }, { delta: 200, value: 59.9 }];
|
||||
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
|
||||
let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
|
||||
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
|
||||
|
||||
let test = Task.async(function*() {
|
||||
yield promiseTab("about:blank");
|
||||
yield performTest();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
|
||||
function* performTest() {
|
||||
let [host, win, doc] = yield createHost();
|
||||
let graph = new LineGraphWidget(doc.body, "fps");
|
||||
|
||||
yield testGraph(graph);
|
||||
|
||||
graph.destroy();
|
||||
host.destroy();
|
||||
}
|
||||
|
||||
function* testGraph(graph) {
|
||||
yield graph.setDataWhenReady(TEST_DATA);
|
||||
|
||||
is(graph._gutter.hidden, false,
|
||||
"The gutter should not be hidden.");
|
||||
is(graph._maxTooltip.hidden, true,
|
||||
"The max tooltip should be hidden.");
|
||||
is(graph._avgTooltip.hidden, false,
|
||||
"The avg tooltip should not be hidden.");
|
||||
is(graph._minTooltip.hidden, false,
|
||||
"The min tooltip should not be hidden.");
|
||||
}
|
@ -46,6 +46,7 @@ const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4; // px
|
||||
const LINE_GRAPH_DAMPEN_VALUES = 0.85;
|
||||
const LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS = 400; // 20 px
|
||||
const LINE_GRAPH_TOOLTIP_SAFE_BOUNDS = 8; // px
|
||||
const LINE_GRAPH_MIN_MAX_TOOLTIP_DISTANCE = 14; // px
|
||||
|
||||
const LINE_GRAPH_BACKGROUND_COLOR = "#0088cc";
|
||||
const LINE_GRAPH_STROKE_WIDTH = 1; // px
|
||||
@ -1358,12 +1359,16 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
||||
let safeTop = LINE_GRAPH_TOOLTIP_SAFE_BOUNDS;
|
||||
let safeBottom = bottom - LINE_GRAPH_TOOLTIP_SAFE_BOUNDS;
|
||||
|
||||
this._maxTooltip.style.top = (this.withFixedTooltipPositions
|
||||
? safeTop : clamp(maxPosY, safeTop, safeBottom)) + "px";
|
||||
this._avgTooltip.style.top = (this.withFixedTooltipPositions
|
||||
? safeTop : clamp(avgPosY, safeTop, safeBottom)) + "px";
|
||||
this._minTooltip.style.top = (this.withFixedTooltipPositions
|
||||
? safeBottom : clamp(minPosY, safeTop, safeBottom)) + "px";
|
||||
let maxTooltipTop = (this.withFixedTooltipPositions
|
||||
? safeTop : clamp(maxPosY, safeTop, safeBottom));
|
||||
let avgTooltipTop = (this.withFixedTooltipPositions
|
||||
? safeTop : clamp(avgPosY, safeTop, safeBottom));
|
||||
let minTooltipTop = (this.withFixedTooltipPositions
|
||||
? safeBottom : clamp(minPosY, safeTop, safeBottom));
|
||||
|
||||
this._maxTooltip.style.top = maxTooltipTop + "px";
|
||||
this._avgTooltip.style.top = avgTooltipTop + "px";
|
||||
this._minTooltip.style.top = minTooltipTop + "px";
|
||||
|
||||
this._maxGutterLine.style.top = maxPosY + "px";
|
||||
this._avgGutterLine.style.top = avgPosY + "px";
|
||||
@ -1373,11 +1378,13 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
||||
this._avgTooltip.setAttribute("with-arrows", this.withTooltipArrows);
|
||||
this._minTooltip.setAttribute("with-arrows", this.withTooltipArrows);
|
||||
|
||||
this._gutter.hidden = !this.withTooltipArrows;
|
||||
this._maxTooltip.hidden = !totalTicks;
|
||||
let distanceMinMax = Math.abs(maxTooltipTop - minTooltipTop);
|
||||
this._maxTooltip.hidden = !totalTicks || distanceMinMax < LINE_GRAPH_MIN_MAX_TOOLTIP_DISTANCE;
|
||||
this._avgTooltip.hidden = !totalTicks;
|
||||
this._minTooltip.hidden = !totalTicks;
|
||||
|
||||
this._gutter.hidden = !this.withTooltipArrows;
|
||||
|
||||
return canvas;
|
||||
},
|
||||
|
||||
@ -1415,6 +1422,7 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
||||
tooltip.className = "line-graph-widget-tooltip";
|
||||
tooltip.setAttribute("type", type);
|
||||
tooltip.setAttribute("arrow", arrow);
|
||||
tooltip.setAttribute("hidden", true);
|
||||
|
||||
let infoNode = this._document.createElementNS(HTML_NS, "span");
|
||||
infoNode.textContent = info;
|
||||
|
@ -88,8 +88,8 @@ MarkerDetails.prototype = {
|
||||
let hbox = this._document.createElement("hbox");
|
||||
let labelName = this._document.createElement("label");
|
||||
let labelValue = this._document.createElement("label");
|
||||
labelName.className = "marker-details-labelname";
|
||||
labelValue.className = "marker-details-labelvalue";
|
||||
labelName.className = "plain marker-details-labelname";
|
||||
labelValue.className = "plain marker-details-labelvalue";
|
||||
labelName.setAttribute("value", L10N.getStr(l10nName));
|
||||
labelValue.setAttribute("value", value);
|
||||
hbox.appendChild(labelName);
|
||||
|
@ -208,7 +208,7 @@ functionality specific to firefox. -->
|
||||
<!ENTITY oldSecurityProtocol.title "Unable to Connect Securely">
|
||||
<!-- LOCALIZATION NOTE (oldSecurityProtocol.longDesc) - Do not translate the
|
||||
<span id='hostname'></span>. -->
|
||||
<!ENTITY oldSecurityProtocol.longDesc "Firefox cannot guarantee the safety of your data on <span id='hostname'></span> because it uses SSLv3, a broken security protocol.">
|
||||
<!ENTITY oldSecurityProtocol.longDesc2 "&brandShortName; cannot guarantee the safety of your data on <span id='hostname'></span> because it uses SSLv3, a broken security protocol.">
|
||||
<!-- LOCALIZATION NOTE (oldSecurityProtocol.advancedInfo) - Do not translate
|
||||
the <span id='errorcode'></span>. -->
|
||||
<!ENTITY oldSecurityProtocol.advancedInfo "Advanced info: <span id='errorcode'></span>">
|
||||
|
@ -10,6 +10,7 @@ let loopButton;
|
||||
let loopPanel = document.getElementById("loop-notification-panel");
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
const { LoopRooms } = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {});
|
||||
|
||||
function test() {
|
||||
UITourTest();
|
||||
@ -85,6 +86,20 @@ let tests = [
|
||||
});
|
||||
});
|
||||
},
|
||||
function test_notifyLoopChatWindowOpenedClosed(done) {
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
ok(false, "No more notifications should have arrived");
|
||||
});
|
||||
done();
|
||||
});
|
||||
document.querySelector("#pinnedchats > chatbox").close();
|
||||
});
|
||||
LoopRooms.open("fakeTourRoom");
|
||||
},
|
||||
];
|
||||
|
||||
function checkLoopPanelIsHidden() {
|
||||
|
@ -46,14 +46,6 @@
|
||||
|
||||
/* Profile call tree */
|
||||
|
||||
.theme-dark .call-tree-headers-container {
|
||||
border-top: 1px solid #000;
|
||||
}
|
||||
|
||||
.theme-light .call-tree-headers-container {
|
||||
border-top: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.call-tree-cells-container {
|
||||
/* Hack: force hardware acceleration */
|
||||
transform: translateZ(1px);
|
||||
@ -391,7 +383,9 @@
|
||||
}
|
||||
|
||||
#waterfall-details {
|
||||
padding-top: 28px;
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
padding-top: 8vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@ -403,6 +397,16 @@
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.marker-details-start,
|
||||
.marker-details-end,
|
||||
.marker-details-duration {
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.marker-details-labelname {
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
.marker-details-type {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
|
@ -175,8 +175,10 @@
|
||||
border-color: initial!important;
|
||||
}
|
||||
|
||||
#timeline-waterfall-details {
|
||||
padding-top: 28px;
|
||||
#waterfall-details {
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
padding-top: 8vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@ -188,6 +190,16 @@
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.marker-details-start,
|
||||
.marker-details-end,
|
||||
.marker-details-duration {
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.marker-details-labelname {
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
.marker-details-type {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
|
@ -1001,6 +1001,7 @@ public class LocalBrowserDB {
|
||||
new String[] { faviconURL },
|
||||
null);
|
||||
|
||||
boolean shouldDelete = false;
|
||||
byte[] b = null;
|
||||
try {
|
||||
if (!c.moveToFirst()) {
|
||||
@ -1008,11 +1009,28 @@ public class LocalBrowserDB {
|
||||
}
|
||||
|
||||
final int faviconIndex = c.getColumnIndexOrThrow(Favicons.DATA);
|
||||
b = c.getBlob(faviconIndex);
|
||||
try {
|
||||
b = c.getBlob(faviconIndex);
|
||||
} catch (IllegalStateException e) {
|
||||
// This happens when the blob is more than 1MB: Bug 1106347.
|
||||
// Delete that row.
|
||||
shouldDelete = true;
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
|
||||
if (shouldDelete) {
|
||||
try {
|
||||
Log.d(LOGTAG, "Deleting invalid favicon.");
|
||||
cr.delete(mFaviconsUriWithProfile,
|
||||
Favicons.URL + " = ?",
|
||||
new String[] { faviconURL });
|
||||
} catch (Exception e) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
if (b == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="300dp"
|
||||
android:minWidth="250dp"
|
||||
android:minHeight="40dp"
|
||||
android:label="@string/search_widget_name"
|
||||
android:widgetCategory="home_screen|keyguard"
|
||||
|
@ -1140,4 +1140,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1426079773398000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1426331544664000);
|
||||
|
@ -53,6 +53,7 @@ co.search.yahoo.com: did not receive HSTS header
|
||||
code.facebook.com: did not receive HSTS header
|
||||
code.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
codereview.chromium.org: did not receive HSTS header (error ignored - included regardless)
|
||||
console.python.org: did not receive HSTS header
|
||||
coursella.com: did not receive HSTS header
|
||||
cr.search.yahoo.com: did not receive HSTS header
|
||||
crate.io: did not receive HSTS header
|
||||
@ -62,6 +63,7 @@ crypto.is: did not receive HSTS header
|
||||
csawctf.poly.edu: did not receive HSTS header
|
||||
ct.search.yahoo.com: did not receive HSTS header
|
||||
cyanogenmod.xxx: could not connect to host
|
||||
cybershambles.com: could not connect to host
|
||||
daylightcompany.com: did not receive HSTS header
|
||||
de.search.yahoo.com: did not receive HSTS header
|
||||
decibelios.li: did not receive HSTS header
|
||||
@ -77,6 +79,7 @@ drive.google.com: did not receive HSTS header (error ignored - included regardle
|
||||
dropcam.com: did not receive HSTS header
|
||||
ed.gs: did not receive HSTS header
|
||||
edmodo.com: did not receive HSTS header
|
||||
eldietista.es: did not receive HSTS header
|
||||
email.lookout.com: could not connect to host
|
||||
en-maktoob.search.yahoo.com: did not receive HSTS header
|
||||
encrypted.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
@ -91,7 +94,6 @@ fi.search.yahoo.com: did not receive HSTS header
|
||||
filedir.com: did not receive HSTS header
|
||||
fixingdns.com: did not receive HSTS header
|
||||
fj.search.yahoo.com: did not receive HSTS header
|
||||
fm83.nl: did not receive HSTS header
|
||||
fr.search.yahoo.com: did not receive HSTS header
|
||||
gamesdepartment.co.uk: did not receive HSTS header
|
||||
get.zenpayroll.com: did not receive HSTS header
|
||||
@ -106,7 +108,7 @@ googleplex.com: could not connect to host (error ignored - included regardless)
|
||||
goto.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
gparent.org: did not receive HSTS header
|
||||
gr.search.yahoo.com: did not receive HSTS header
|
||||
grandmascookieblog.com: did not receive HSTS header
|
||||
grandmascookieblog.com: could not connect to host
|
||||
greplin.com: could not connect to host
|
||||
groups.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
hackerone-user-content.com: could not connect to host
|
||||
@ -117,8 +119,10 @@ hn.search.yahoo.com: did not receive HSTS header
|
||||
hoerbuecher-und-hoerspiele.de: did not receive HSTS header
|
||||
honeytracks.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134" data: no]
|
||||
horosho.in: did not receive HSTS header
|
||||
horseboners.xxx: could not connect to host
|
||||
hostedtalkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
howrandom.org: could not connect to host
|
||||
hstspreload.appspot.com: did not receive HSTS header
|
||||
hu.search.yahoo.com: did not receive HSTS header
|
||||
id.search.yahoo.com: did not receive HSTS header
|
||||
ie.search.yahoo.com: did not receive HSTS header
|
||||
@ -131,6 +135,8 @@ irccloud.com: did not receive HSTS header
|
||||
it.search.yahoo.com: did not receive HSTS header
|
||||
itriskltd.com: did not receive HSTS header
|
||||
jottit.com: could not connect to host
|
||||
jwilsson.com: could not connect to host
|
||||
jwilsson.me: could not connect to host
|
||||
keymaster.lookout.com: did not receive HSTS header
|
||||
kiwiirc.com: max-age too low: 5256000
|
||||
klaxn.com: could not connect to host
|
||||
@ -175,6 +181,7 @@ mx.search.yahoo.com: did not receive HSTS header
|
||||
my.alfresco.com: did not receive HSTS header
|
||||
mydigipass.com: did not receive HSTS header
|
||||
mykolab.com: did not receive HSTS header
|
||||
myplaceonline.com: could not connect to host
|
||||
neonisi.com: could not connect to host
|
||||
netzpolitik.org: did not receive HSTS header
|
||||
nexth.de: could not connect to host
|
||||
@ -221,8 +228,8 @@ ro.search.yahoo.com: did not receive HSTS header
|
||||
ru.search.yahoo.com: did not receive HSTS header
|
||||
rw.search.yahoo.com: did not receive HSTS header
|
||||
sah3.net: could not connect to host
|
||||
salserocafe.com: could not connect to host
|
||||
saturngames.co.uk: could not connect to host
|
||||
schreiber-netzwerk.eu: max-age too low: 0
|
||||
script.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
se.search.yahoo.com: did not receive HSTS header
|
||||
search.yahoo.com: did not receive HSTS header
|
||||
@ -254,7 +261,6 @@ stocktrade.de: could not connect to host
|
||||
sunshinepress.org: could not connect to host
|
||||
surfeasy.com: did not receive HSTS header
|
||||
sv.search.yahoo.com: did not receive HSTS header
|
||||
sylaps.com: did not receive HSTS header
|
||||
t.facebook.com: did not receive HSTS header
|
||||
tablet.facebook.com: did not receive HSTS header
|
||||
talk.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
@ -276,6 +282,8 @@ uprotect.it: could not connect to host
|
||||
uy.search.yahoo.com: did not receive HSTS header
|
||||
uz.search.yahoo.com: did not receive HSTS header
|
||||
ve.search.yahoo.com: did not receive HSTS header
|
||||
viennan.net: did not receive HSTS header
|
||||
visionless.me: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134" data: no]
|
||||
vn.search.yahoo.com: did not receive HSTS header
|
||||
wallet.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
webmail.mayfirst.org: did not receive HSTS header
|
||||
|
@ -8,7 +8,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1428145748415000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1428750739923000);
|
||||
|
||||
class nsSTSPreload
|
||||
{
|
||||
@ -40,10 +40,12 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "alexsexton.com", true },
|
||||
{ "alexyang.me", true },
|
||||
{ "alpha.irccloud.com", false },
|
||||
{ "anadoluefessporkulubu.org", true },
|
||||
{ "andreasbreitenlohner.de", true },
|
||||
{ "anetaben.nl", true },
|
||||
{ "angularjs.org", true },
|
||||
{ "animurecs.com", true },
|
||||
{ "ankarakart.com.tr", true },
|
||||
{ "annahmeschluss.de", true },
|
||||
{ "annevankesteren.com", true },
|
||||
{ "annevankesteren.nl", true },
|
||||
@ -91,10 +93,13 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "beneathvt.com", true },
|
||||
{ "benjamins.com", true },
|
||||
{ "best-wedding-quotes.com", true },
|
||||
{ "bgneuesheim.de", true },
|
||||
{ "bhatia.at", true },
|
||||
{ "big-andy.co.uk", true },
|
||||
{ "bigbrownpromotions.com.au", true },
|
||||
{ "bitbucket.org", false },
|
||||
{ "bitfactory.ws", true },
|
||||
{ "bitmex.com", true },
|
||||
{ "bitmon.net", true },
|
||||
{ "bjornjohansen.no", true },
|
||||
{ "bl4ckb0x.com", true },
|
||||
@ -104,16 +109,19 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "bl4ckb0x.org", true },
|
||||
{ "blacklane.com", true },
|
||||
{ "blessnet.jp", true },
|
||||
{ "blockchain.info", true },
|
||||
{ "blocksatz-medien.de", true },
|
||||
{ "blog.cyveillance.com", true },
|
||||
{ "blog.gparent.org", true },
|
||||
{ "blog.linode.com", false },
|
||||
{ "blog.torproject.org", false },
|
||||
{ "blubbablasen.de", true },
|
||||
{ "bodo-wolff.de", true },
|
||||
{ "bohramt.de", true },
|
||||
{ "bonigo.de", true },
|
||||
{ "bookingapp.nl", true },
|
||||
{ "boxcryptor.com", true },
|
||||
{ "brage.info", true },
|
||||
{ "brunosouza.org", true },
|
||||
{ "buddhistische-weisheiten.org", true },
|
||||
{ "bugzil.la", true },
|
||||
@ -133,6 +141,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "celltek-server.de", false },
|
||||
{ "certible.com", true },
|
||||
{ "certly.io", true },
|
||||
{ "chahub.com", true },
|
||||
{ "chainmonitor.com", true },
|
||||
{ "check.torproject.org", false },
|
||||
{ "checkout.google.com", true },
|
||||
@ -164,6 +173,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "conformal.com", true },
|
||||
{ "conrad-kostecki.de", true },
|
||||
{ "controlcenter.gigahost.dk", true },
|
||||
{ "cor-ser.es", true },
|
||||
{ "cotonea.de", true },
|
||||
{ "crm.onlime.ch", false },
|
||||
{ "crowdjuris.com", true },
|
||||
@ -182,6 +192,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "cyphertite.com", true },
|
||||
{ "czbix.com", true },
|
||||
{ "daphne.informatik.uni-freiburg.de", true },
|
||||
{ "darchoods.net", false },
|
||||
{ "data-abundance.com", true },
|
||||
{ "data.qld.gov.au", false },
|
||||
{ "datenkeks.de", true },
|
||||
@ -207,13 +218,14 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "dlc.viasinc.com", true },
|
||||
{ "dm.lookout.com", false },
|
||||
{ "dm.mylookout.com", false },
|
||||
{ "doc.python.org", true },
|
||||
{ "docs.google.com", true },
|
||||
{ "docs.python.org", true },
|
||||
{ "domains.google.com", true },
|
||||
{ "domaris.de", true },
|
||||
{ "donmez.ws", false },
|
||||
{ "drive.google.com", true },
|
||||
{ "dropbox.com", false },
|
||||
{ "dropbox.com", true },
|
||||
{ "dzlibs.io", true },
|
||||
{ "easysimplecrm.com", false },
|
||||
{ "ebanking.indovinabank.com.vn", false },
|
||||
@ -221,7 +233,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "edit.yahoo.com", false },
|
||||
{ "edyou.eu", true },
|
||||
{ "eff.org", true },
|
||||
{ "eldietista.es", true },
|
||||
{ "electronic-ignition-system.com", true },
|
||||
{ "elnutricionista.es", true },
|
||||
{ "emailprivacytester.com", true },
|
||||
{ "encircleapp.com", true },
|
||||
@ -240,10 +252,12 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "evstatus.com", true },
|
||||
{ "explodie.org", true },
|
||||
{ "f-droid.org", true },
|
||||
{ "fabhub.io", true },
|
||||
{ "fabianfischer.de", true },
|
||||
{ "factor.cc", false },
|
||||
{ "fairbill.com", true },
|
||||
{ "fakturoid.cz", true },
|
||||
{ "fant.dk", true },
|
||||
{ "faq.lookout.com", false },
|
||||
{ "fastcomcorp.net", true },
|
||||
{ "fedorapeople.org", true },
|
||||
@ -258,6 +272,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "fleximus.org", false },
|
||||
{ "floobits.com", true },
|
||||
{ "flynn.io", true },
|
||||
{ "fm83.nl", true },
|
||||
{ "forewordreviews.com", true },
|
||||
{ "forodeespanol.com", true },
|
||||
{ "forum.linode.com", false },
|
||||
@ -314,8 +329,10 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "helichat.de", true },
|
||||
{ "help.simpletax.ca", false },
|
||||
{ "helpium.de", true },
|
||||
{ "henriknoerr.com", true },
|
||||
{ "hex2013.com", true },
|
||||
{ "hexony.com", true },
|
||||
{ "hg.python.org", true },
|
||||
{ "history.google.com", true },
|
||||
{ "honeybadger.io", false },
|
||||
{ "horseboners.xxx", true },
|
||||
@ -337,8 +354,10 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "ideaweb.de", true },
|
||||
{ "ihrlotto.de", true },
|
||||
{ "ilikerainbows.co.uk", true },
|
||||
{ "imaginary.ca", true },
|
||||
{ "imouto.my", true },
|
||||
{ "in.xero.com", false },
|
||||
{ "inb4.us", true },
|
||||
{ "inbox.google.com", true },
|
||||
{ "inkbunny.net", true },
|
||||
{ "inleaked.com", true },
|
||||
@ -392,6 +411,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "konklone.com", true },
|
||||
{ "koop-bremen.de", true },
|
||||
{ "koordinate.net", true },
|
||||
{ "kosho.org", true },
|
||||
{ "kpebetka.net", true },
|
||||
{ "kraken.io", true },
|
||||
{ "kura.io", true },
|
||||
@ -404,6 +424,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "leonardcamacho.me", true },
|
||||
{ "library.linode.com", false },
|
||||
{ "liebel.org", true },
|
||||
{ "lighting-centres.co.uk", true },
|
||||
{ "limpid.nl", true },
|
||||
{ "lingolia.com", true },
|
||||
{ "linode.com", false },
|
||||
@ -439,6 +460,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "mandala-ausmalbilder.de", true },
|
||||
{ "market.android.com", true },
|
||||
{ "markusueberallassetmanagement.de", true },
|
||||
{ "marshut.net", true },
|
||||
{ "matatall.com", true },
|
||||
{ "mathiasbynens.be", true },
|
||||
{ "matteomarescotti.it", true },
|
||||
@ -446,6 +468,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "mbp.banking.co.at", false },
|
||||
{ "md5file.com", true },
|
||||
{ "mdfnet.se", true },
|
||||
{ "meamod.com", true },
|
||||
{ "mediacru.sh", true },
|
||||
{ "medium.com", true },
|
||||
{ "meetfinch.com", true },
|
||||
@ -472,6 +495,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "mothereff.in", true },
|
||||
{ "mountainmusicpromotions.com", true },
|
||||
{ "mountainroseherbs.com", true },
|
||||
{ "movelaria.com.br", true },
|
||||
{ "movlib.org", true },
|
||||
{ "mqas.net", true },
|
||||
{ "msc-seereisen.net", true },
|
||||
@ -479,6 +503,8 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "mudcrab.us", true },
|
||||
{ "munich-rage.de", true },
|
||||
{ "musicgamegalaxy.de", true },
|
||||
{ "mutantmonkey.in", true },
|
||||
{ "mutantmonkey.info", true },
|
||||
{ "mutantmonkey.sexy", true },
|
||||
{ "mwe.st", true },
|
||||
{ "my.onlime.ch", false },
|
||||
@ -487,10 +513,12 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "mygadgetguardian.lookout.com", false },
|
||||
{ "mykreuzfahrt.de", true },
|
||||
{ "mylookout.com", false },
|
||||
{ "myni.io", true },
|
||||
{ "mynigma.org", true },
|
||||
{ "myplaceonline.com", true },
|
||||
{ "myvirtualserver.com", true },
|
||||
{ "nachsenden.info", true },
|
||||
{ "nameid.org", true },
|
||||
{ "nectarleaf.com", true },
|
||||
{ "neftaly.com", true },
|
||||
{ "neg9.org", false },
|
||||
@ -499,8 +527,10 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "netzbit.de", true },
|
||||
{ "newstarnootropics.com", true },
|
||||
{ "ng-security.com", true },
|
||||
{ "nginxnudes.com", true },
|
||||
{ "nmctest.net", true },
|
||||
{ "nos-oignons.net", true },
|
||||
{ "nouvelle-vague-saint-cast.fr", true },
|
||||
{ "npw.net", true },
|
||||
{ "nu3.at", true },
|
||||
{ "nu3.ch", true },
|
||||
@ -519,6 +549,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "onedrive.com", true },
|
||||
{ "onedrive.live.com", false },
|
||||
{ "onsitemassageco.com", true },
|
||||
{ "opendesk.cc", true },
|
||||
{ "oplop.appspot.com", true },
|
||||
{ "opsmate.com", false },
|
||||
{ "optimus.io", true },
|
||||
@ -555,6 +586,8 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "paypal.com", false },
|
||||
{ "pdf.yt", true },
|
||||
{ "peercraft.com", true },
|
||||
{ "pestici.de", true },
|
||||
{ "petrolplus.ru", true },
|
||||
{ "phoenixlogan.com", true },
|
||||
{ "picksin.club", true },
|
||||
{ "pierre-schmitz.com", true },
|
||||
@ -572,6 +605,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "projektzentrisch.de", true },
|
||||
{ "propagandism.org", true },
|
||||
{ "prowhisky.de", true },
|
||||
{ "proximato.com", true },
|
||||
{ "pubkey.is", true },
|
||||
{ "publications.qld.gov.au", false },
|
||||
{ "pult.co", false },
|
||||
@ -608,8 +642,10 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "salserocafe.com", true },
|
||||
{ "samizdat.cz", true },
|
||||
{ "sandbox.mydigipass.com", false },
|
||||
{ "savetheinternet.eu", true },
|
||||
{ "schachburg.de", true },
|
||||
{ "schokokeks.org", false },
|
||||
{ "schreiber-netzwerk.eu", true },
|
||||
{ "schwarzer.it", true },
|
||||
{ "sciencex.com", true },
|
||||
{ "scotthelme.co.uk", true },
|
||||
@ -633,10 +669,12 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "shodan.io", true },
|
||||
{ "shohruh.uz", false },
|
||||
{ "shopontarget.com", true },
|
||||
{ "shortdiary.me", true },
|
||||
{ "silentcircle.com", false },
|
||||
{ "simbolo.co.uk", false },
|
||||
{ "simple.com", false },
|
||||
{ "simpletax.ca", false },
|
||||
{ "simplia.cz", true },
|
||||
{ "simplystudio.com", true },
|
||||
{ "siraweb.org", true },
|
||||
{ "siriad.com", true },
|
||||
@ -680,15 +718,19 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "support.mayfirst.org", false },
|
||||
{ "surkatty.org", true },
|
||||
{ "swehack.org", true },
|
||||
{ "sylaps.com", true },
|
||||
{ "sysctl.se", true },
|
||||
{ "syss.de", true },
|
||||
{ "tadigitalstore.com", true },
|
||||
{ "tageau.com", true },
|
||||
{ "talk.google.com", true },
|
||||
{ "talkgadget.google.com", true },
|
||||
{ "tapka.cz", true },
|
||||
{ "tatort-fanpage.de", true },
|
||||
{ "tauchkater.de", true },
|
||||
{ "taxsquirrel.com", true },
|
||||
{ "techhipster.net", true },
|
||||
{ "tegelsensanitaironline.nl", true },
|
||||
{ "tekshrek.com", true },
|
||||
{ "tent.io", true },
|
||||
{ "testsuite.org", true },
|
||||
@ -739,26 +781,30 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "tunebitfm.de", true },
|
||||
{ "twentymilliseconds.com", true },
|
||||
{ "twitter.com", false },
|
||||
{ "typingrevolution.com", true },
|
||||
{ "ub3rk1tten.com", true },
|
||||
{ "ubertt.org", true },
|
||||
{ "ukdefencejournal.org.uk", true },
|
||||
{ "ukhas.net", true },
|
||||
{ "ukrainians.ch", true },
|
||||
{ "unison.com", true },
|
||||
{ "unterfrankenclan.de", true },
|
||||
{ "uptrends.com", true },
|
||||
{ "usaa.com", false },
|
||||
{ "uzstyle.com", false },
|
||||
{ "vaddder.com", true },
|
||||
{ "vhost.co.id", true },
|
||||
{ "viasinc.com", false },
|
||||
{ "viennan.net", true },
|
||||
{ "vmoagents.com", false },
|
||||
{ "vocaloid.my", true },
|
||||
{ "vortexhobbies.com", true },
|
||||
{ "vpnzoom.com", true },
|
||||
{ "vrobert.fr", false },
|
||||
{ "w-spotlight.appspot.com", true },
|
||||
{ "wallet.google.com", true },
|
||||
{ "warrencreative.com", false },
|
||||
{ "watsonhall.uk", true },
|
||||
{ "wbg-vs.de", true },
|
||||
{ "webandmore.de", false },
|
||||
{ "webandwords.com.au", true },
|
||||
{ "webcollect.org.uk", true },
|
||||
|
@ -72,6 +72,11 @@ WeaveService.prototype = {
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
ensureLoaded: function () {
|
||||
// If we are loaded and not using FxA, load the migration module.
|
||||
if (!this.fxAccountsEnabled) {
|
||||
Cu.import("resource://services-sync/FxaMigrator.jsm");
|
||||
}
|
||||
|
||||
Components.utils.import("resource://services-sync/main.js");
|
||||
|
||||
// Side-effect of accessing the service is that it is instantiated.
|
||||
|
382
services/sync/modules/FxaMigrator.jsm
Normal file
382
services/sync/modules/FxaMigrator.jsm
Normal file
@ -0,0 +1,382 @@
|
||||
/* 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, results: Cr, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
|
||||
"resource://gre/modules/FxAccounts.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "WeaveService", function() {
|
||||
return Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
|
||||
"resource://services-sync/main.js");
|
||||
|
||||
// FxAccountsCommon.js doesn't use a "namespace", so create one here.
|
||||
let fxAccountsCommon = {};
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
|
||||
|
||||
// We send this notification whenever the migration state changes.
|
||||
const OBSERVER_STATE_CHANGE_TOPIC = "fxa-migration:state-changed";
|
||||
// We also send the state notification when we *receive* this. This allows
|
||||
// consumers to avoid loading this module until it receives a notification
|
||||
// from us (which may never happen if there's no migration to do)
|
||||
const OBSERVER_STATE_REQUEST_TOPIC = "fxa-migration:state-request";
|
||||
|
||||
const OBSERVER_TOPICS = [
|
||||
"xpcom-shutdown",
|
||||
"weave:service:sync:start",
|
||||
"weave:service:sync:finish",
|
||||
"weave:service:sync:error",
|
||||
"weave:eol",
|
||||
OBSERVER_STATE_REQUEST_TOPIC,
|
||||
fxAccountsCommon.ONLOGIN_NOTIFICATION,
|
||||
fxAccountsCommon.ONLOGOUT_NOTIFICATION,
|
||||
fxAccountsCommon.ONVERIFIED_NOTIFICATION,
|
||||
];
|
||||
|
||||
// A list of preference names we write to the migration sentinel. We only
|
||||
// write ones that have a user-set value.
|
||||
const FXA_SENTINEL_PREFS = [
|
||||
"identity.fxaccounts.auth.uri",
|
||||
"identity.fxaccounts.remote.force_auth.uri",
|
||||
"identity.fxaccounts.remote.signup.uri",
|
||||
"identity.fxaccounts.remote.signin.uri",
|
||||
"identity.fxaccounts.settings.uri",
|
||||
"services.sync.tokenServerURI",
|
||||
];
|
||||
|
||||
function Migrator() {
|
||||
// Leave the log-level as Debug - Sync will setup log appenders such that
|
||||
// these messages generally will not be seen unless other log related
|
||||
// prefs are set.
|
||||
this.level = Log.Level.Debug;
|
||||
|
||||
this._nextUserStatePromise = Promise.resolve();
|
||||
|
||||
for (let topic of OBSERVER_TOPICS) {
|
||||
Services.obs.addObserver(this, topic, false);
|
||||
}
|
||||
// ._state is an optimization so we avoid sending redundant observer
|
||||
// notifications when the state hasn't actually changed.
|
||||
this._state = null;
|
||||
}
|
||||
|
||||
Migrator.prototype = {
|
||||
log: Log.repository.getLogger("Sync.SyncMigration"),
|
||||
|
||||
// What user action is necessary to push the migration forward?
|
||||
// A |null| state means there is nothing to do. Note that a null state implies
|
||||
// either. (a) no migration is necessary or (b) that the migrator module is
|
||||
// waiting for something outside of the user's control - eg, sync to complete,
|
||||
// the migration sentinel to be uploaded, etc. In most cases the wait will be
|
||||
// short, but edge cases (eg, no network, sync bugs that prevent it stopping
|
||||
// until shutdown) may require a significantly longer wait.
|
||||
STATE_USER_FXA: "waiting for user to be signed in to FxA",
|
||||
STATE_USER_FXA_VERIFIED: "waiting for a verified FxA user",
|
||||
|
||||
finalize() {
|
||||
for (let topic of OBSERVER_TOPICS) {
|
||||
Services.obs.removeObserver(this, topic);
|
||||
}
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
this.log.debug("observed " + topic);
|
||||
switch (topic) {
|
||||
case "xpcom-shutdown":
|
||||
this.finalize();
|
||||
break;
|
||||
|
||||
case OBSERVER_STATE_REQUEST_TOPIC:
|
||||
// someone has requested the state - send it.
|
||||
this._queueCurrentUserState(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
// some other observer that may affect our state has fired, so update.
|
||||
this._queueCurrentUserState().then(
|
||||
() => this.log.debug("update state from observer " + topic + " complete")
|
||||
).catch(err => {
|
||||
let msg = "Failed to handle topic " + topic + ": " + err;
|
||||
Cu.reportError(msg);
|
||||
this.log.error(msg);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Try and move to a state where we are blocked on a user action.
|
||||
// This needs to be restartable, and the states may, in edge-cases, end
|
||||
// up going backwards (eg, user logs out while we are waiting to be told
|
||||
// about verification)
|
||||
// This is called by our observer notifications - so if there is already
|
||||
// a promise in-flight, it's possible we will miss something important - so
|
||||
// we wait for the in-flight one to complete then fire another (ie, this
|
||||
// is effectively a queue of promises)
|
||||
_queueCurrentUserState(forceObserver = false) {
|
||||
return this._nextUserStatePromise = this._nextUserStatePromise.then(
|
||||
() => this._promiseCurrentUserState(forceObserver),
|
||||
err => {
|
||||
let msg = "Failed to determine the current user state: " + err;
|
||||
Cu.reportError(msg);
|
||||
this.log.error(msg);
|
||||
return this._promiseCurrentUserState(forceObserver)
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_promiseCurrentUserState: Task.async(function* (forceObserver) {
|
||||
this.log.trace("starting _promiseCurrentUserState");
|
||||
let update = newState => {
|
||||
this.log.info("Migration state: '${state}' => '${newState}'",
|
||||
{state: this._state, newState: newState});
|
||||
if (forceObserver || newState !== this._state) {
|
||||
this._state = newState;
|
||||
Services.obs.notifyObservers(null, OBSERVER_STATE_CHANGE_TOPIC, newState);
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
// If we have no sync user, or are already using an FxA account we must
|
||||
// be done.
|
||||
if (WeaveService.fxAccountsEnabled) {
|
||||
// should not be necessary, but if we somehow ended up with FxA enabled
|
||||
// and sync blocked it would be bad - so better safe than sorry.
|
||||
this._unblockSync();
|
||||
return update(null);
|
||||
}
|
||||
|
||||
// so we need to migrate - let's see how far along we are.
|
||||
// If sync isn't in EOL mode, then we are still waiting for the server
|
||||
// to offer the migration process - so no user action necessary.
|
||||
let isEOL = false;
|
||||
try {
|
||||
isEOL = !!Services.prefs.getCharPref("services.sync.errorhandler.alert.mode");
|
||||
} catch (e) {}
|
||||
|
||||
if (!isEOL) {
|
||||
return update(null);
|
||||
}
|
||||
|
||||
// So we are in EOL mode - have we a user?
|
||||
let fxauser = yield fxAccounts.getSignedInUser();
|
||||
if (!fxauser) {
|
||||
return update(this.STATE_USER_FXA);
|
||||
}
|
||||
if (!fxauser.verified) {
|
||||
return update(this.STATE_USER_FXA_VERIFIED);
|
||||
}
|
||||
|
||||
// So we just have housekeeping to do - we aren't blocked on a user, so
|
||||
// reflect that.
|
||||
this.log.info("No next user state - doing some housekeeping");
|
||||
update(null);
|
||||
|
||||
// We need to disable sync from automatically starting,
|
||||
// and if we are currently syncing wait for it to complete.
|
||||
this._blockSync();
|
||||
|
||||
// Are we currently syncing?
|
||||
if (Weave.Service._locked) {
|
||||
// our observers will kick us further along when complete.
|
||||
this.log.info("waiting for sync to complete")
|
||||
return null;
|
||||
}
|
||||
|
||||
// Write the migration sentinel if necessary.
|
||||
yield this._setMigrationSentinelIfNecessary();
|
||||
|
||||
// Must be ready to perform the actual migration.
|
||||
this.log.info("Performing final sync migration steps");
|
||||
// Do the actual migration.
|
||||
let startOverComplete = new Promise((resolve, reject) => {
|
||||
let observe;
|
||||
Services.obs.addObserver(observe = () => {
|
||||
this.log.info("observed that startOver is complete");
|
||||
Services.obs.removeObserver(observe, "weave:service:start-over:finish");
|
||||
resolve();
|
||||
}, "weave:service:start-over:finish", false);
|
||||
});
|
||||
|
||||
Weave.Service.startOver();
|
||||
// need to wait for an observer.
|
||||
yield startOverComplete;
|
||||
// observer fired, now kick things off with the FxA user.
|
||||
this.log.info("scheduling initial FxA sync.");
|
||||
this._unblockSync();
|
||||
Weave.Service.scheduler.scheduleNextSync(0);
|
||||
return null;
|
||||
}),
|
||||
|
||||
/* Return an object with the preferences we care about */
|
||||
_getSentinelPrefs() {
|
||||
let result = {};
|
||||
for (let pref of FXA_SENTINEL_PREFS) {
|
||||
if (Services.prefs.prefHasUserValue(pref)) {
|
||||
result[pref] = Services.prefs.getCharPref(pref);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/* Apply any preferences we've obtained from the sentinel */
|
||||
_applySentinelPrefs(savedPrefs) {
|
||||
for (let pref of FXA_SENTINEL_PREFS) {
|
||||
if (savedPrefs[pref]) {
|
||||
Services.prefs.setCharPref(pref, savedPrefs[pref]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Ask sync to upload the migration sentinel */
|
||||
_setSyncMigrationSentinel: Task.async(function* () {
|
||||
yield WeaveService.whenLoaded();
|
||||
let signedInUser = yield fxAccounts.getSignedInUser();
|
||||
let sentinel = {
|
||||
email: signedInUser.email,
|
||||
uid: signedInUser.uid,
|
||||
verified: signedInUser.verified,
|
||||
prefs: this._getSentinelPrefs(),
|
||||
};
|
||||
if (Weave.Service.setFxaMigrationSentinel) {
|
||||
yield Weave.Service.setFxaMigrationSentinel(sentinel);
|
||||
} else {
|
||||
this.log.warn("Waiting on bug 1017433; no sync sentinel");
|
||||
}
|
||||
}),
|
||||
|
||||
/* Ask sync to upload the migration sentinal if we (or any other linked device)
|
||||
haven't previously written one.
|
||||
*/
|
||||
_setMigrationSentinelIfNecessary: Task.async(function* () {
|
||||
if (!(yield this._getSyncMigrationSentinel())) {
|
||||
this.log.info("writing the migration sentinel");
|
||||
yield this._setSyncMigrationSentinel();
|
||||
}
|
||||
}),
|
||||
|
||||
/* Ask sync to return a migration sentinel if one exists, otherwise return null */
|
||||
_getSyncMigrationSentinel: Task.async(function* () {
|
||||
yield WeaveService.whenLoaded();
|
||||
if (!Weave.Service.getFxaMigrationSentinel) {
|
||||
this.log.warn("Waiting on bug 1017433; no sync sentinel");
|
||||
return null;
|
||||
}
|
||||
let sentinel = yield Weave.Service.getFxaMigrationSentinel();
|
||||
this.log.debug("got migration sentinel ${}", sentinel);
|
||||
return sentinel;
|
||||
}),
|
||||
|
||||
_getDefaultAccountName: Task.async(function* (sentinel) {
|
||||
// Requires looking to see if other devices have written a migration
|
||||
// sentinel (eg, see _haveSynchedMigrationSentinel), and if not, see if
|
||||
// the legacy account name appears to be a valid email address (via the
|
||||
// services.sync.account pref), otherwise return null.
|
||||
// NOTE: Sync does all this synchronously via nested event loops, but we
|
||||
// expose a promise to make future migration to an async-sync easier.
|
||||
if (sentinel && sentinel.email) {
|
||||
this.log.info("defaultAccountName found via sentinel: ${}", sentinel.email);
|
||||
return sentinel.email;
|
||||
}
|
||||
// No previous migrations, so check the existing account name.
|
||||
let account = Weave.Service.identity.account;
|
||||
if (account && account.contains("@")) {
|
||||
this.log.info("defaultAccountName found via legacy account name: {}", account);
|
||||
return account;
|
||||
}
|
||||
this.log.info("defaultAccountName could not find an account");
|
||||
return null;
|
||||
}),
|
||||
|
||||
// Prevent sync from automatically starting
|
||||
_blockSync() {
|
||||
if (Weave.Service.scheduler.blockSync) {
|
||||
Weave.Service.scheduler.blockSync();
|
||||
} else {
|
||||
this.log.warn("Waiting on bug 1019408; sync not blocked");
|
||||
}
|
||||
},
|
||||
|
||||
_unblockSync() {
|
||||
if (Weave.Service.scheduler.unblockSync) {
|
||||
Weave.Service.scheduler.unblockSync();
|
||||
} else {
|
||||
this.log.warn("Waiting on bug 1019408; sync not unblocked");
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Some helpers for the UI to try and move to the next state.
|
||||
*/
|
||||
|
||||
// Open a UI for the user to create a Firefox Account. This should only be
|
||||
// called while we are in the STATE_USER_FXA state. When the user completes
|
||||
// the creation we'll see an ONLOGIN_NOTIFICATION notification from FxA and
|
||||
// we'll move to either the STATE_USER_FXA_VERIFIED state or we'll just
|
||||
// complete the migration if they login as an already verified user.
|
||||
createFxAccount: Task.async(function* (win) {
|
||||
// warn if we aren't in the expected state - but go ahead anyway!
|
||||
if (this._state != this.STATE_USER_FXA) {
|
||||
this.log.warn("createFxAccount called in an unexpected state: ${}", this._state);
|
||||
}
|
||||
// We need to obtain the sentinel and apply any prefs that might be
|
||||
// specified *before* attempting to setup FxA as the prefs might
|
||||
// specify custom servers etc.
|
||||
let sentinel = yield this._getSyncMigrationSentinel();
|
||||
if (sentinel && sentinel.prefs) {
|
||||
this._applySentinelPrefs(sentinel.prefs);
|
||||
}
|
||||
// If we already have a sentinel then we assume the user has previously
|
||||
// created the specified account, so just ask to sign-in.
|
||||
let action = sentinel ? "signin" : "signup";
|
||||
// See if we can find a default account name to use.
|
||||
let email = yield this._getDefaultAccountName(sentinel);
|
||||
let tail = email ? "&email=" + encodeURIComponent(email) : "";
|
||||
win.switchToTabHavingURI("about:accounts?" + action + tail, true,
|
||||
{ignoreFragment: true, replaceQueryString: true});
|
||||
// An FxA observer will fire when the user completes this, which will
|
||||
// cause us to move to the next "user blocked" state and notify via our
|
||||
// observer notification.
|
||||
}),
|
||||
|
||||
// Ask the FxA servers to re-send a verification mail for the currently
|
||||
// logged in user. This should only be called while we are in the
|
||||
// STATE_USER_FXA_VERIFIED state. When the user clicks on the link in
|
||||
// the mail we should see an ONVERIFIED_NOTIFICATION which will cause us
|
||||
// to complete the migration.
|
||||
resendVerificationMail: Task.async(function * () {
|
||||
// warn if we aren't in the expected state - but go ahead anyway!
|
||||
if (this._state != this.STATE_USER_FXA_VERIFIED) {
|
||||
this.log.warn("createFxAccount called in an unexpected state: ${}", this._state);
|
||||
}
|
||||
return fxAccounts.resendVerificationEmail();
|
||||
}),
|
||||
|
||||
// "forget" about the current Firefox account. This should only be called
|
||||
// while we are in the STATE_USER_FXA_VERIFIED state. After this we will
|
||||
// see an ONLOGOUT_NOTIFICATION, which will cause the migrator to return back
|
||||
// to the STATE_USER_FXA state, from where they can choose a different account.
|
||||
forgetFxAccount: Task.async(function * () {
|
||||
// warn if we aren't in the expected state - but go ahead anyway!
|
||||
if (this._state != this.STATE_USER_FXA_VERIFIED) {
|
||||
this.log.warn("createFxAccount called in an unexpected state: ${}", this._state);
|
||||
}
|
||||
return fxAccounts.signOut();
|
||||
}),
|
||||
|
||||
}
|
||||
|
||||
// We expose a singleton
|
||||
this.EXPORTED_SYMBOLS = ["fxaMigrator"];
|
||||
let fxaMigrator = new Migrator();
|
@ -20,6 +20,7 @@ EXTRA_JS_MODULES['services-sync'] += [
|
||||
'modules/addonutils.js',
|
||||
'modules/browserid_identity.js',
|
||||
'modules/engines.js',
|
||||
'modules/FxaMigrator.jsm',
|
||||
'modules/healthreport.jsm',
|
||||
'modules/identity.js',
|
||||
'modules/jpakeclient.js',
|
||||
|
@ -514,8 +514,11 @@ let SyncServerCallback = {
|
||||
*
|
||||
* Allows the test to inspect the request. Hooks should be careful not to
|
||||
* modify or change state of the request or they may impact future processing.
|
||||
* The response is also passed so the callback can set headers etc - but care
|
||||
* must be taken to not screw with the response body or headers that may
|
||||
* conflict with normal operation of this server.
|
||||
*/
|
||||
onRequest: function onRequest(request) {},
|
||||
onRequest: function onRequest(request, response) {},
|
||||
};
|
||||
|
||||
/**
|
||||
@ -796,7 +799,7 @@ SyncServer.prototype = {
|
||||
this._log.debug("SyncServer: Handling request: " + req.method + " " + req.path);
|
||||
|
||||
if (this.callback.onRequest) {
|
||||
this.callback.onRequest(req);
|
||||
this.callback.onRequest(req, resp);
|
||||
}
|
||||
|
||||
let parts = this.pathRE.exec(req.path);
|
||||
|
270
services/sync/tests/unit/test_fxa_migration.js
Normal file
270
services/sync/tests/unit/test_fxa_migration.js
Normal file
@ -0,0 +1,270 @@
|
||||
// Test the FxAMigration module
|
||||
Cu.import("resource://services-sync/FxaMigrator.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
Cu.import("resource://services-sync/browserid_identity.js");
|
||||
|
||||
// Set our username pref early so sync initializes with the legacy provider.
|
||||
Services.prefs.setCharPref("services.sync.username", "foo");
|
||||
// And ensure all debug messages end up being printed.
|
||||
Services.prefs.setCharPref("services.sync.log.appender.dump", "Debug");
|
||||
|
||||
// Now import sync
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// And reset the username.
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
|
||||
Cu.import("resource://testing-common/services/sync/utils.js");
|
||||
Cu.import("resource://testing-common/services/common/logging.js");
|
||||
Cu.import("resource://testing-common/services/sync/rotaryengine.js");
|
||||
|
||||
const FXA_USERNAME = "someone@somewhere";
|
||||
|
||||
// Utilities
|
||||
function promiseOneObserver(topic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let observer = function(subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
resolve(data);
|
||||
}
|
||||
Services.obs.addObserver(observer, topic, false);
|
||||
});
|
||||
}
|
||||
|
||||
function promiseStopServer(server) {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Helpers
|
||||
function configureLegacySync() {
|
||||
let engine = new RotaryEngine(Service);
|
||||
engine.enabled = true;
|
||||
Svc.Prefs.set("registerEngines", engine.name);
|
||||
Svc.Prefs.set("log.logger.engine.rotary", "Trace");
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {rotary: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
crypto: {},
|
||||
rotary: {}
|
||||
};
|
||||
|
||||
const USER = "foo";
|
||||
const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea";
|
||||
|
||||
setBasicCredentials(USER, "password", PASSPHRASE);
|
||||
|
||||
let onRequest = function(request, response) {
|
||||
// ideally we'd only do this while a legacy user is configured, but WTH.
|
||||
response.setHeader("x-weave-alert", JSON.stringify({code: "soft-eol"}));
|
||||
}
|
||||
let server = new SyncServer({onRequest: onRequest});
|
||||
server.registerUser(USER, "password");
|
||||
server.createContents(USER, contents);
|
||||
server.start();
|
||||
|
||||
Service.serverURL = server.baseURI;
|
||||
Service.clusterURL = server.baseURI;
|
||||
Service.identity.username = USER;
|
||||
Service._updateCachedURLs();
|
||||
|
||||
Service.engineManager._engines[engine.name] = engine;
|
||||
|
||||
return [engine, server];
|
||||
}
|
||||
|
||||
function configureFxa() {
|
||||
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost");
|
||||
}
|
||||
|
||||
add_task(function *testMigration() {
|
||||
configureFxa();
|
||||
|
||||
// when we do a .startOver we want the new provider.
|
||||
let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity");
|
||||
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", false);
|
||||
do_register_cleanup(() => {
|
||||
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", oldValue)
|
||||
});
|
||||
|
||||
// No sync user - that should report no user-action necessary.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null,
|
||||
"no user state when complete");
|
||||
|
||||
// Arrange for a legacy sync user and manually bump the migrator
|
||||
let [engine, server] = configureLegacySync();
|
||||
|
||||
// monkey-patch the migration sentinel code so we know it was called.
|
||||
let haveStartedSentinel = false;
|
||||
// (This is waiting on bug 1017433)
|
||||
/**
|
||||
let origSetFxaMigrationSentinel = Service.setFxaMigrationSentinel;
|
||||
let promiseSentinelWritten = new Promise((resolve, reject) => {
|
||||
Service.setFxaMigrationSentinel = function(arg) {
|
||||
haveStartedSentinel = true;
|
||||
return origSetFxaMigrationSentinel.call(Service, arg).then(result => {
|
||||
Service.setFxaMigrationSentinel = origSetFxaMigrationSentinel;
|
||||
resolve(result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
});
|
||||
**/
|
||||
// We are now configured for legacy sync, but we aren't in an EOL state yet,
|
||||
// so should still be not waiting for a user.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null,
|
||||
"no user state before server EOL");
|
||||
|
||||
// Start a sync - this will cause an EOL notification which the migrator's
|
||||
// observer will notice.
|
||||
let promise = promiseOneObserver("fxa-migration:state-changed");
|
||||
_("Starting sync");
|
||||
Service.sync();
|
||||
_("Finished sync");
|
||||
|
||||
// We should have seen the observer, so be waiting for an FxA user.
|
||||
Assert.equal((yield promise), fxaMigrator.STATE_USER_FXA, "now waiting for FxA.")
|
||||
|
||||
// Re-calling our user-state promise should also reflect the same state.
|
||||
Assert.equal((yield fxaMigrator._queueCurrentUserState()),
|
||||
fxaMigrator.STATE_USER_FXA,
|
||||
"still waiting for FxA.");
|
||||
|
||||
// arrange for an unverified FxA user.
|
||||
let config = makeIdentityConfig({username: FXA_USERNAME});
|
||||
let fxa = new FxAccounts({});
|
||||
config.fxaccount.user.email = config.username;
|
||||
delete config.fxaccount.user.verified;
|
||||
// *sob* - shouldn't need this boilerplate
|
||||
fxa.internal.currentAccountState.getCertificate = function(data, keyPair, mustBeValidUntil) {
|
||||
this.cert = {
|
||||
validUntil: fxa.internal.now() + CERT_LIFETIME,
|
||||
cert: "certificate",
|
||||
};
|
||||
return Promise.resolve(this.cert.cert);
|
||||
};
|
||||
|
||||
// As soon as we set the FxA user the observers should fire and magically
|
||||
// transition.
|
||||
promise = promiseOneObserver("fxa-migration:state-changed");
|
||||
fxAccounts.setSignedInUser(config.fxaccount.user);
|
||||
|
||||
Assert.equal((yield promise),
|
||||
fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"now waiting for verification");
|
||||
|
||||
// should have seen the user set, so state should automatically update.
|
||||
Assert.equal((yield fxaMigrator._queueCurrentUserState()),
|
||||
fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"now waiting for verification");
|
||||
|
||||
// Before we verify the user, fire off a sync that calls us back during
|
||||
// the sync and before it completes - this way we can ensure we do the right
|
||||
// thing in terms of blocking sync and waiting for it to complete.
|
||||
|
||||
let wasWaiting = false;
|
||||
// This is a PITA as sync is pseudo-blocking.
|
||||
engine._syncFinish = function () {
|
||||
// We aren't in a generator here, so use a helper to block on promises.
|
||||
function getState() {
|
||||
let cb = Async.makeSpinningCallback();
|
||||
fxaMigrator._queueCurrentUserState().then(state => cb(null, state));
|
||||
return cb.wait();
|
||||
}
|
||||
// should still be waiting for verification.
|
||||
Assert.equal(getState(), fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"still waiting for verification");
|
||||
|
||||
// arrange for the user to be verified. The fxAccount's mock story is
|
||||
// broken, so go behind its back.
|
||||
config.fxaccount.user.verified = true;
|
||||
fxAccounts.setSignedInUser(config.fxaccount.user);
|
||||
Services.obs.notifyObservers(null, ONVERIFIED_NOTIFICATION, null);
|
||||
|
||||
// spinningly wait for the migrator to catch up - sync is running so
|
||||
// we should be in a 'null' user-state as there is no user-action
|
||||
// necessary.
|
||||
let cb = Async.makeSpinningCallback();
|
||||
promiseOneObserver("fxa-migration:state-changed").then(state => cb(null, state));
|
||||
Assert.equal(cb.wait(), null, "no user action necessary while sync completes.");
|
||||
|
||||
// We must not have started writing the sentinel yet.
|
||||
Assert.ok(!haveStartedSentinel, "haven't written a sentinel yet");
|
||||
|
||||
// sync should be blocked from continuing
|
||||
// (This is waiting on bug 1019408)
|
||||
/**
|
||||
Assert.ok(Service.scheduler.isBlocked, "sync is blocked.")
|
||||
**/
|
||||
|
||||
wasWaiting = true;
|
||||
throw ex;
|
||||
};
|
||||
|
||||
_("Starting sync");
|
||||
Service.sync();
|
||||
_("Finished sync");
|
||||
|
||||
// mock sync so we can ensure the final sync is scheduled with the FxA user.
|
||||
// (letting a "normal" sync complete is a PITA without mocking huge amounts
|
||||
// of FxA infra)
|
||||
let promiseFinalSync = new Promise((resolve, reject) => {
|
||||
let oldSync = Service.sync;
|
||||
Service.sync = function() {
|
||||
Service.sync = oldSync;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
Assert.ok(wasWaiting, "everything was good while sync was running.")
|
||||
|
||||
// The migration is now going to run to completion.
|
||||
// sync should still be "blocked"
|
||||
// (This is waiting on bug 1019408)
|
||||
/**
|
||||
Assert.ok(Service.scheduler.isBlocked, "sync is blocked.");
|
||||
**/
|
||||
|
||||
// We should see the migration sentinel written and it should return true.
|
||||
// (This is waiting on bug 1017433)
|
||||
/**
|
||||
Assert.ok((yield promiseSentinelWritten), "wrote the sentinel");
|
||||
**/
|
||||
|
||||
// And we should see a new sync start
|
||||
yield promiseFinalSync;
|
||||
|
||||
// and we should be configured for FxA
|
||||
let WeaveService = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
Assert.ok(WeaveService.fxAccountsEnabled, "FxA is enabled");
|
||||
Assert.ok(Service.identity instanceof BrowserIDManager,
|
||||
"sync is configured with the browserid_identity provider.");
|
||||
Assert.equal(Service.identity.username, config.username, "correct user configured")
|
||||
Assert.ok(!Service.scheduler.isBlocked, "sync is not blocked.")
|
||||
// and the user state should remain null.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()),
|
||||
null,
|
||||
"still no user action necessary");
|
||||
|
||||
// aaaand, we are done - clean up.
|
||||
yield promiseStopServer(server);
|
||||
});
|
||||
|
||||
|
||||
function run_test() {
|
||||
initTestLogging();
|
||||
do_register_cleanup(() => {
|
||||
fxaMigrator.finalize();
|
||||
Svc.Prefs.resetBranch("");
|
||||
});
|
||||
run_next_test();
|
||||
}
|
@ -172,3 +172,6 @@ skip-if = debug
|
||||
skip-if = ! healthreport
|
||||
|
||||
[test_warn_on_truncated_response.js]
|
||||
|
||||
# FxA migration
|
||||
[test_fxa_migration.js]
|
||||
|
Loading…
Reference in New Issue
Block a user