зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound.
This commit is contained in:
Коммит
ee0e94e991
|
@ -1294,6 +1294,8 @@ class UrlbarInput {
|
|||
_on_input() {
|
||||
let value = this.textValue;
|
||||
this.valueIsTyped = true;
|
||||
let valueIsPasted = this._valueIsPasted;
|
||||
this._valueIsPasted = false;
|
||||
this._untrimmedValue = value;
|
||||
this.window.gBrowser.userTypedValue = value;
|
||||
|
||||
|
@ -1351,7 +1353,7 @@ class UrlbarInput {
|
|||
return;
|
||||
}
|
||||
|
||||
let allowAutofill =
|
||||
let allowAutofill = !valueIsPasted &&
|
||||
this._maybeAutofillOnInput(value, deletedAutofilledSubstring);
|
||||
|
||||
this.startQuery({
|
||||
|
@ -1417,7 +1419,7 @@ class UrlbarInput {
|
|||
if (!originalPasteData) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._valueIsPasted = true;
|
||||
let oldValue = this.inputField.value;
|
||||
let oldStart = oldValue.substring(0, this.selectionStart);
|
||||
// If there is already non-whitespace content in the URL bar
|
||||
|
|
|
@ -27,6 +27,7 @@ skip-if = os != "mac" # Mac only feature
|
|||
[browser_autoFill_canonize.js]
|
||||
[browser_autoFill_caretNotAtEnd.js]
|
||||
[browser_autoFill_firstResult.js]
|
||||
[browser_autoFill_paste.js]
|
||||
[browser_autoFill_placeholder.js]
|
||||
[browser_autoFill_preserve.js]
|
||||
[browser_autoFill_trimURLs.js]
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This test checks we don't autofill on paste.
|
||||
|
||||
"use strict";
|
||||
|
||||
async function paste(str) {
|
||||
await SimpleTest.promiseClipboardChange(str, () => {
|
||||
Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper)
|
||||
.copyString(str);
|
||||
});
|
||||
gURLBar.select();
|
||||
document.commandDispatcher.getControllerForCommand("cmd_paste")
|
||||
.doCommand("cmd_paste");
|
||||
}
|
||||
|
||||
add_task(async function test() {
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
await PlacesUtils.history.clear();
|
||||
await PlacesTestUtils.addVisits([
|
||||
"http://example.com/",
|
||||
]);
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.history.clear();
|
||||
});
|
||||
|
||||
// Search for "e". It should autofill to example.com/.
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
waitForFocus,
|
||||
value: "e",
|
||||
fireInputEvent: true,
|
||||
});
|
||||
let details = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
|
||||
Assert.ok(details.autofill);
|
||||
Assert.equal(gURLBar.value, "example.com/");
|
||||
Assert.equal(gURLBar.selectionStart, "e".length);
|
||||
Assert.equal(gURLBar.selectionEnd, "example.com/".length);
|
||||
|
||||
// Now paste.
|
||||
await paste("ex");
|
||||
|
||||
// Nothing should have been autofilled.
|
||||
await UrlbarTestUtils.promiseSearchComplete(window);
|
||||
details = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
|
||||
Assert.ok(!details.autofill);
|
||||
Assert.equal(gURLBar.value, "ex");
|
||||
Assert.equal(gURLBar.selectionStart, "ex".length);
|
||||
Assert.equal(gURLBar.selectionEnd, "ex".length);
|
||||
});
|
|
@ -57,11 +57,12 @@
|
|||
border.
|
||||
*/
|
||||
#navigator-toolbox::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
-moz-appearance: toolbox;
|
||||
height: 1px;
|
||||
/* use inset box-shadow instead of border because -moz-appearance hides the border */
|
||||
border: none;
|
||||
box-shadow: inset 0 -1px var(--chrome-content-separator-color);
|
||||
margin-top: -1px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs {
|
||||
|
|
|
@ -39,13 +39,11 @@
|
|||
|
||||
/* Toolbar / content area border */
|
||||
|
||||
#navigator-toolbox::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
#navigator-toolbox {
|
||||
border-bottom: 1px solid var(--chrome-content-separator-color);
|
||||
}
|
||||
|
||||
:root[customizing] #navigator-toolbox::after {
|
||||
:root[customizing] #navigator-toolbox {
|
||||
border-bottom-style: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,18 @@
|
|||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #navigator-toolbox::after {
|
||||
#navigator-toolbox::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
border-bottom: 1px solid var(--chrome-content-separator-color);
|
||||
}
|
||||
|
||||
#navigator-toolbox,
|
||||
:root[customizing] #navigator-toolbox::after {
|
||||
border-bottom-style: none;
|
||||
}
|
||||
|
||||
:root[sizemode=normal] #navigator-toolbox::after {
|
||||
box-shadow: 1px 0 0 @glassShadowColor@, -1px 0 0 @glassShadowColor@;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
|
|
|
@ -959,6 +959,14 @@ netmonitor.context.copyAsCurl=Copy as cURL
|
|||
# for the Copy as cURL menu item displayed in the context menu for a request
|
||||
netmonitor.context.copyAsCurl.accesskey=C
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.copyAsFetch): This is the label displayed
|
||||
# on the context menu that copies the selected request as a fetch request.
|
||||
netmonitor.context.copyAsFetch=Copy as Fetch
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.copyAsFetch.accesskey): This is the access key
|
||||
# for the Copy as fetch menu item displayed in the context menu for a request
|
||||
netmonitor.context.copyAsFetch.accesskey=F
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.copyRequestHeaders): This is the label displayed
|
||||
# on the context menu that copies the selected item's request headers
|
||||
netmonitor.context.copyRequestHeaders=Copy Request Headers
|
||||
|
@ -991,6 +999,14 @@ netmonitor.context.copyImageAsDataUri=Copy Image as Data URI
|
|||
# for the Copy Image As Data URI menu item displayed in the context menu for a request
|
||||
netmonitor.context.copyImageAsDataUri.accesskey=I
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.useAsFetch): This is the label displayed
|
||||
# on the context menu that copies the selected request as a fetch command.
|
||||
netmonitor.context.useAsFetch=Use as Fetch in Console
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.useAsFetch.accesskey): This is the access key
|
||||
# for the Copy as fetch menu item displayed in the context menu for a request
|
||||
netmonitor.context.useAsFetch.accesskey=F
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.saveImageAs): This is the label displayed
|
||||
# on the context menu that save the Image
|
||||
netmonitor.context.saveImageAs=Save Image As
|
||||
|
|
|
@ -90,6 +90,15 @@ class RequestListContextMenu {
|
|||
this.copyAsCurl(id, url, method, httpVersion, requestHeaders, requestPostData),
|
||||
});
|
||||
|
||||
copySubmenu.push({
|
||||
id: "request-list-context-copy-as-fetch",
|
||||
label: L10N.getStr("netmonitor.context.copyAsFetch"),
|
||||
accesskey: L10N.getStr("netmonitor.context.copyAsFetch.accesskey"),
|
||||
visible: !!selectedRequest,
|
||||
click: () =>
|
||||
this.copyAsFetch(id, url, method, requestHeaders, requestPostData),
|
||||
});
|
||||
|
||||
copySubmenu.push({
|
||||
type: "separator",
|
||||
visible: copySubmenu.slice(0, 4).some((subMenu) => subMenu.visible),
|
||||
|
@ -231,6 +240,19 @@ class RequestListContextMenu {
|
|||
click: () => openStatistics(true),
|
||||
});
|
||||
|
||||
menu.push({
|
||||
type: "separator",
|
||||
});
|
||||
|
||||
menu.push({
|
||||
id: "request-list-context-use-as-fetch",
|
||||
label: L10N.getStr("netmonitor.context.useAsFetch"),
|
||||
accesskey: L10N.getStr("netmonitor.context.useAsFetch.accesskey"),
|
||||
visible: !!selectedRequest,
|
||||
click: () =>
|
||||
this.useAsFetch(id, url, method, requestHeaders, requestPostData),
|
||||
});
|
||||
|
||||
showMenu(menu, {
|
||||
screenX: event.screenX,
|
||||
screenY: event.screenY,
|
||||
|
@ -324,6 +346,107 @@ class RequestListContextMenu {
|
|||
copyString(Curl.generateCommand(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate fetch string
|
||||
*/
|
||||
async generateFetchString(id, url, method, requestHeaders, requestPostData) {
|
||||
requestHeaders = requestHeaders ||
|
||||
await this.props.connector.requestData(id, "requestHeaders");
|
||||
|
||||
requestPostData = requestPostData ||
|
||||
await this.props.connector.requestData(id, "requestPostData");
|
||||
|
||||
// https://fetch.spec.whatwg.org/#forbidden-header-name
|
||||
const forbiddenHeaders = {
|
||||
"accept-charset": 1,
|
||||
"accept-encoding": 1,
|
||||
"access-control-request-headers": 1,
|
||||
"access-control-request-method": 1,
|
||||
"connection": 1,
|
||||
"content-length": 1,
|
||||
"cookie": 1,
|
||||
"cookie2": 1,
|
||||
"date": 1,
|
||||
"dnt": 1,
|
||||
"expect": 1,
|
||||
"host": 1,
|
||||
"keep-alive": 1,
|
||||
"origin": 1,
|
||||
"referer": 1,
|
||||
"te": 1,
|
||||
"trailer": 1,
|
||||
"transfer-encoding": 1,
|
||||
"upgrade": 1,
|
||||
"via": 1,
|
||||
};
|
||||
const credentialHeaders = {"cookie": 1, "authorization": 1};
|
||||
|
||||
const headers = {};
|
||||
for (const {name, value} of requestHeaders.headers) {
|
||||
if (!forbiddenHeaders[name.toLowerCase()]) {
|
||||
headers[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const referrerHeader = requestHeaders.headers.find(
|
||||
({ name }) => name.toLowerCase() === "referer"
|
||||
);
|
||||
|
||||
const referrerPolicy = requestHeaders.headers.find(
|
||||
({ name }) => name.toLowerCase() === "referrer-policy"
|
||||
);
|
||||
|
||||
const referrer = referrerHeader ? referrerHeader.value : undefined;
|
||||
const credentials = requestHeaders.headers.some(
|
||||
({name}) => credentialHeaders[name.toLowerCase()]
|
||||
) ? "include" : "omit";
|
||||
|
||||
const fetchOptions = {
|
||||
credentials,
|
||||
headers,
|
||||
referrer,
|
||||
referrerPolicy,
|
||||
body: requestPostData.postData.text,
|
||||
method: method,
|
||||
mode: "cors",
|
||||
};
|
||||
|
||||
const options = JSON.stringify(fetchOptions, null, 4);
|
||||
const fetchString = `await fetch("${url}", ${options});`;
|
||||
return fetchString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the currently selected item as fetch request.
|
||||
*/
|
||||
async copyAsFetch(id, url, method, requestHeaders, requestPostData) {
|
||||
const fetchString = await this.generateFetchString(
|
||||
id,
|
||||
url,
|
||||
method,
|
||||
requestHeaders,
|
||||
requestPostData
|
||||
);
|
||||
copyString(fetchString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open split console and fill it with fetch command for selected item
|
||||
*/
|
||||
async useAsFetch(id, url, method, requestHeaders, requestPostData) {
|
||||
const fetchString = await this.generateFetchString(
|
||||
id,
|
||||
url,
|
||||
method,
|
||||
requestHeaders,
|
||||
requestPostData
|
||||
);
|
||||
const toolbox = gDevTools.getToolbox(this.props.connector.getTabTarget());
|
||||
await toolbox.openSplitConsole();
|
||||
const { hud } = await toolbox.getPanel("webconsole");
|
||||
hud.setInputValue(fetchString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the raw request headers from the currently selected item.
|
||||
*/
|
||||
|
|
|
@ -116,6 +116,9 @@ subsuite = clipboard
|
|||
skip-if = (verify && debug && os == 'win')
|
||||
[browser_net_copy_as_curl.js]
|
||||
subsuite = clipboard
|
||||
[browser_net_copy_as_fetch.js]
|
||||
subsuite = clipboard
|
||||
[browser_net_use_as_fetch.js]
|
||||
[browser_net_cors_requests.js]
|
||||
[browser_net_cyrillic-01.js]
|
||||
[browser_net_cyrillic-02.js]
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests if Copy as Fetch works.
|
||||
*/
|
||||
|
||||
add_task(async function() {
|
||||
const { tab, monitor } = await initNetMonitor(CURL_URL);
|
||||
info("Starting test... ");
|
||||
|
||||
// GET request, no cookies (first request)
|
||||
await performRequest("GET");
|
||||
await testClipboardContent(`await fetch("http://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", {
|
||||
"credentials": "omit",
|
||||
"headers": {
|
||||
"User-Agent": "${navigator.userAgent}",
|
||||
"Accept": "*/*",
|
||||
"Accept-Language": "en-US",
|
||||
"X-Custom-Header-1": "Custom value",
|
||||
"X-Custom-Header-2": "8.8.8.8",
|
||||
"X-Custom-Header-3": "Mon, 3 Mar 2014 11:11:11 GMT",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"referrer": "http://example.com/browser/devtools/client/netmonitor/test/html_copy-as-curl.html",
|
||||
"method": "GET",
|
||||
"mode": "cors"
|
||||
});`);
|
||||
|
||||
await teardown(monitor);
|
||||
|
||||
async function performRequest(method, payload) {
|
||||
const waitRequest = waitForNetworkEvents(monitor, 1);
|
||||
await ContentTask.spawn(tab.linkedBrowser, {
|
||||
url: SIMPLE_SJS,
|
||||
method_: method,
|
||||
payload_: payload,
|
||||
}, async function({url, method_, payload_}) {
|
||||
content.wrappedJSObject.performRequest(url, method_, payload_);
|
||||
});
|
||||
await waitRequest;
|
||||
}
|
||||
|
||||
async function testClipboardContent(expectedResult) {
|
||||
const { document } = monitor.panelWin;
|
||||
|
||||
const items = document.querySelectorAll(".request-list-item");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
|
||||
EventUtils.sendMouseEvent({ type: "contextmenu" },
|
||||
document.querySelectorAll(".request-list-item")[0]);
|
||||
|
||||
/* Ensure that the copy as fetch option is always visible */
|
||||
const copyAsFetchNode = monitor.panelWin.parent.document
|
||||
.querySelector("#request-list-context-copy-as-fetch");
|
||||
is(!!copyAsFetchNode, true,
|
||||
"The \"Copy as Fetch\" context menu item should not be hidden.");
|
||||
|
||||
await waitForClipboardPromise(function setup() {
|
||||
copyAsFetchNode.click();
|
||||
}, function validate(result) {
|
||||
if (typeof result !== "string") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return expectedResult === result;
|
||||
});
|
||||
|
||||
info("Clipboard contains a fetch command for item " + (items.length - 1));
|
||||
}
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests if Use as Fetch works.
|
||||
*/
|
||||
|
||||
add_task(async function() {
|
||||
const { tab, monitor, toolbox } = await initNetMonitor(CURL_URL);
|
||||
info("Starting test... ");
|
||||
|
||||
// GET request, no cookies (first request)
|
||||
await performRequest("GET");
|
||||
await testConsoleInput(`await fetch("http://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", {
|
||||
"credentials": "omit",
|
||||
"headers": {
|
||||
"User-Agent": "${navigator.userAgent}",
|
||||
"Accept": "*/*",
|
||||
"Accept-Language": "en-US",
|
||||
"X-Custom-Header-1": "Custom value",
|
||||
"X-Custom-Header-2": "8.8.8.8",
|
||||
"X-Custom-Header-3": "Mon, 3 Mar 2014 11:11:11 GMT",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"referrer": "http://example.com/browser/devtools/client/netmonitor/test/html_copy-as-curl.html",
|
||||
"method": "GET",
|
||||
"mode": "cors"
|
||||
});`);
|
||||
|
||||
await teardown(monitor);
|
||||
|
||||
async function performRequest(method, payload) {
|
||||
const waitRequest = waitForNetworkEvents(monitor, 1);
|
||||
await ContentTask.spawn(tab.linkedBrowser, {
|
||||
url: SIMPLE_SJS,
|
||||
method_: method,
|
||||
payload_: payload,
|
||||
}, async function({url, method_, payload_}) {
|
||||
content.wrappedJSObject.performRequest(url, method_, payload_);
|
||||
});
|
||||
await waitRequest;
|
||||
}
|
||||
|
||||
async function testConsoleInput(expectedResult) {
|
||||
const { document } = monitor.panelWin;
|
||||
|
||||
const items = document.querySelectorAll(".request-list-item");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
|
||||
EventUtils.sendMouseEvent({ type: "contextmenu" },
|
||||
document.querySelectorAll(".request-list-item")[0]);
|
||||
|
||||
/* Ensure that the use as fetch option is always visible */
|
||||
const useAsFetchNode = monitor.panelWin.parent.document
|
||||
.querySelector("#request-list-context-use-as-fetch");
|
||||
is(!!useAsFetchNode, true,
|
||||
"The \"Use as Fetch\" context menu item should not be hidden.");
|
||||
|
||||
useAsFetchNode.click();
|
||||
await toolbox.once("split-console");
|
||||
const hud = toolbox.getPanel("webconsole").hud;
|
||||
await hud.jsterm.once("set-input-value");
|
||||
|
||||
is(hud.getInputValue(), expectedResult,
|
||||
"Console input contains fetch request for item " + (items.length - 1));
|
||||
}
|
||||
});
|
|
@ -419,8 +419,9 @@ AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver,
|
|||
mDriver(aDriver),
|
||||
mOperation(aOperation),
|
||||
mShutdownGrip(aDriver->GraphImpl()) {
|
||||
NS_WARNING_ASSERTION(mDriver->mAudioStream || aOperation == INIT,
|
||||
"No audio stream!");
|
||||
NS_WARNING_ASSERTION(
|
||||
mDriver->mAudioStream || aOperation == AsyncCubebOperation::INIT,
|
||||
"No audio stream!");
|
||||
}
|
||||
|
||||
AsyncCubebTask::~AsyncCubebTask() {}
|
||||
|
@ -441,6 +442,22 @@ AsyncCubebTask::Run() {
|
|||
mDriver->CompleteAudioContextOperations(mOperation);
|
||||
break;
|
||||
}
|
||||
case AsyncCubebOperation::START: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::START driver=%p",
|
||||
mDriver->GraphImpl(), mDriver.get()));
|
||||
if (!mDriver->StartStream()) {
|
||||
LOG(LogLevel::Warning,
|
||||
("%p: AsyncCubebOperation couldn't start the driver=%p.",
|
||||
mDriver->GraphImpl(), mDriver.get()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AsyncCubebOperation::STOP: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::STOP driver=%p",
|
||||
mDriver->GraphImpl(), mDriver.get()));
|
||||
mDriver->Stop();
|
||||
break;
|
||||
}
|
||||
case AsyncCubebOperation::SHUTDOWN: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::SHUTDOWN driver=%p",
|
||||
mDriver->GraphImpl(), mDriver.get()));
|
||||
|
@ -713,6 +730,7 @@ void AudioCallbackDriver::Stop() {
|
|||
if (cubeb_stream_stop(mAudioStream) != CUBEB_OK) {
|
||||
NS_WARNING("Could not stop cubeb stream for MSG.");
|
||||
}
|
||||
mStarted = false;
|
||||
}
|
||||
|
||||
void AudioCallbackDriver::Revive() {
|
||||
|
@ -728,9 +746,16 @@ void AudioCallbackDriver::Revive() {
|
|||
LOG(LogLevel::Debug,
|
||||
("Starting audio threads for MediaStreamGraph %p from a new thread.",
|
||||
mGraphImpl.get()));
|
||||
RefPtr<AsyncCubebTask> initEvent =
|
||||
new AsyncCubebTask(this, AsyncCubebOperation::INIT);
|
||||
initEvent->Dispatch();
|
||||
if (IsStarted()) {
|
||||
RefPtr<AsyncCubebTask> stopEvent =
|
||||
new AsyncCubebTask(this, AsyncCubebOperation::STOP);
|
||||
// This dispatches to a thread pool with a maximum of one thread thus it
|
||||
// is guaranteed to be executed before the start event, right below.
|
||||
stopEvent->Dispatch();
|
||||
}
|
||||
RefPtr<AsyncCubebTask> startEvent =
|
||||
new AsyncCubebTask(this, AsyncCubebOperation::START);
|
||||
startEvent->Dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ struct StreamAndPromiseForOperation {
|
|||
dom::AudioContextOperationFlags mFlags;
|
||||
};
|
||||
|
||||
enum AsyncCubebOperation { INIT, SHUTDOWN };
|
||||
enum class AsyncCubebOperation { INIT, START, STOP, SHUTDOWN };
|
||||
enum class AudioInputType { Unknown, Voice };
|
||||
|
||||
/**
|
||||
|
|
|
@ -761,14 +761,7 @@ void MediaStreamGraphImpl::OpenAudioInputImpl(CubebUtils::AudioDeviceID aID,
|
|||
|
||||
nsresult MediaStreamGraphImpl::OpenAudioInput(CubebUtils::AudioDeviceID aID,
|
||||
AudioDataListener* aListener) {
|
||||
// So, so, so annoying. Can't AppendMessage except on Mainthread
|
||||
if (!NS_IsMainThread()) {
|
||||
RefPtr<nsIRunnable> runnable =
|
||||
WrapRunnable(this, &MediaStreamGraphImpl::OpenAudioInput, aID,
|
||||
RefPtr<AudioDataListener>(aListener));
|
||||
mAbstractMainThread->Dispatch(runnable.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(MediaStreamGraphImpl* aGraph, CubebUtils::AudioDeviceID aID,
|
||||
|
@ -845,14 +838,7 @@ void MediaStreamGraphImpl::CloseAudioInputImpl(
|
|||
|
||||
void MediaStreamGraphImpl::CloseAudioInput(
|
||||
Maybe<CubebUtils::AudioDeviceID>& aID, AudioDataListener* aListener) {
|
||||
// So, so, so annoying. Can't AppendMessage except on Mainthread
|
||||
if (!NS_IsMainThread()) {
|
||||
RefPtr<nsIRunnable> runnable =
|
||||
WrapRunnable(this, &MediaStreamGraphImpl::CloseAudioInput, aID,
|
||||
RefPtr<AudioDataListener>(aListener));
|
||||
mAbstractMainThread->Dispatch(runnable.forget());
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(MediaStreamGraphImpl* aGraph, Maybe<CubebUtils::AudioDeviceID>& aID,
|
||||
|
@ -2421,25 +2407,32 @@ SourceMediaStream::SourceMediaStream()
|
|||
|
||||
nsresult SourceMediaStream::OpenAudioInput(CubebUtils::AudioDeviceID aID,
|
||||
AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(GraphImpl());
|
||||
MOZ_ASSERT(!mInputListener);
|
||||
mInputListener = aListener;
|
||||
return GraphImpl()->OpenAudioInput(aID, aListener);
|
||||
}
|
||||
|
||||
void SourceMediaStream::CloseAudioInput(Maybe<CubebUtils::AudioDeviceID>& aID,
|
||||
AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(mInputListener == aListener);
|
||||
// Destroy() may have run already and cleared this
|
||||
if (GraphImpl() && mInputListener) {
|
||||
GraphImpl()->CloseAudioInput(aID, aListener);
|
||||
void SourceMediaStream::CloseAudioInput(Maybe<CubebUtils::AudioDeviceID>& aID) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(GraphImpl());
|
||||
if (!mInputListener) {
|
||||
return;
|
||||
}
|
||||
GraphImpl()->CloseAudioInput(aID, mInputListener);
|
||||
mInputListener = nullptr;
|
||||
}
|
||||
|
||||
void SourceMediaStream::DestroyImpl() {
|
||||
void SourceMediaStream::Destroy() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Maybe<CubebUtils::AudioDeviceID> id = Nothing();
|
||||
CloseAudioInput(id, mInputListener);
|
||||
CloseAudioInput(id);
|
||||
|
||||
MediaStream::Destroy();
|
||||
}
|
||||
|
||||
void SourceMediaStream::DestroyImpl() {
|
||||
GraphImpl()->AssertOnGraphThreadOrNotRunning();
|
||||
for (int32_t i = mConsumers.Length() - 1; i >= 0; --i) {
|
||||
// Disconnect before we come under mMutex's lock since it can call back
|
||||
|
|
|
@ -655,14 +655,14 @@ class SourceMediaStream : public MediaStream {
|
|||
|
||||
// Users of audio inputs go through the stream so it can track when the
|
||||
// last stream referencing an input goes away, so it can close the cubeb
|
||||
// input. Also note: callable on any thread (though it bounces through
|
||||
// MainThread to set the command if needed).
|
||||
// input. Main thread only.
|
||||
nsresult OpenAudioInput(CubebUtils::AudioDeviceID aID,
|
||||
AudioDataListener* aListener);
|
||||
// Note: also implied when Destroy() happens
|
||||
void CloseAudioInput(Maybe<CubebUtils::AudioDeviceID>& aID,
|
||||
AudioDataListener* aListener);
|
||||
// Main thread only.
|
||||
void CloseAudioInput(Maybe<CubebUtils::AudioDeviceID>& aID);
|
||||
|
||||
// Main thread only.
|
||||
void Destroy() override;
|
||||
// MediaStreamGraph thread only
|
||||
void DestroyImpl() override;
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ nsresult MediaEngineWebRTCMicrophoneSource::Stop() {
|
|||
that->mInputProcessing, StartStopMessage::Stop));
|
||||
CubebUtils::AudioDeviceID deviceID = that->mDeviceInfo->DeviceID();
|
||||
Maybe<CubebUtils::AudioDeviceID> id = Some(deviceID);
|
||||
stream->CloseAudioInput(id, that->mInputProcessing);
|
||||
stream->CloseAudioInput(id);
|
||||
}));
|
||||
|
||||
MOZ_ASSERT(mState == kStarted, "Should be started when stopping");
|
||||
|
|
|
@ -212,7 +212,7 @@ pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla
|
|||
/* preferences for the Get Add-ons pane */
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/android/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
|
||||
pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/android/");
|
||||
pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/firefox/collections/4757633/mob/");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/api/v3/addons/search/?guid=%IDS%&lang=%LOCALE%");
|
||||
pref("extensions.getAddons.compatOverides.url", "https://services.addons.mozilla.org/api/v3/addons/compat-override/?guid=%IDS%&lang=%LOCALE%");
|
||||
pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=android&type=language&appversion=%VERSION%");
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const {EventDispatcher} = ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
|
||||
const AMO_ICON = "chrome://browser/skin/images/amo-logo.png";
|
||||
const UPDATE_INDICATOR = "chrome://browser/skin/images/extension-update.svg";
|
||||
|
@ -261,13 +262,34 @@ var Addons = {
|
|||
let title = document.createElement("div");
|
||||
title.id = "browse-title";
|
||||
title.className = "title";
|
||||
title.textContent = gStringBundle.GetStringFromName("addons.browseAll");
|
||||
title.textContent = this._getAmoTitle();
|
||||
inner.appendChild(title);
|
||||
|
||||
outer.appendChild(inner);
|
||||
return outer;
|
||||
},
|
||||
|
||||
// Ensure we get a localized string by using the previous title as a fallback
|
||||
// if the new one has not yet been translated.
|
||||
_getAmoTitle: function _getAmoTitle() {
|
||||
const initialTitleUS = "Browse all Firefox Add-ons";
|
||||
const updatedTitleUS = "Browse Firefox’s Recommended Extensions";
|
||||
const initialTitleLocalized = gStringBundle.GetStringFromName("addons.browseAll");
|
||||
const updatedTitleLocalized = gStringBundle.GetStringFromName("addons.browseRecommended");
|
||||
let title = initialTitleLocalized;
|
||||
|
||||
const titleWasLocalized = updatedTitleLocalized !== updatedTitleUS;
|
||||
const localeIsDefaultUS = updatedTitleLocalized === updatedTitleUS &&
|
||||
initialTitleLocalized === initialTitleUS;
|
||||
|
||||
if (titleWasLocalized || localeIsDefaultUS) {
|
||||
title = updatedTitleLocalized;
|
||||
}
|
||||
|
||||
EventDispatcher.instance.dispatch("about:addons", {amoTitle: title} );
|
||||
return title;
|
||||
},
|
||||
|
||||
_createItemForAddon: function _createItemForAddon(aAddon) {
|
||||
let opType = this._getOpTypeForOperations(aAddon.pendingOperations);
|
||||
let hasUpdate = this._addonHasUpdate(aAddon);
|
||||
|
|
|
@ -8,6 +8,8 @@ addonType.locale=Locale
|
|||
|
||||
addonStatus.uninstalled=%S will be uninstalled after restart.
|
||||
|
||||
# Will keep both strings and at runtime will fallback on the old one if the new one is not yet localized
|
||||
addons.browseAll=Browse all Firefox Add-ons
|
||||
addons.browseRecommended=Browse Firefox’s Recommended Extensions
|
||||
|
||||
addon.options=Options
|
||||
addon.options=Options
|
||||
|
|
|
@ -34,6 +34,9 @@ public class StringHelper {
|
|||
// About pages' titles
|
||||
public final String ABOUT_HOME_TITLE = "";
|
||||
|
||||
// To be kept in sync with 'addons.browseRecommended' from 'aboutAddons.properties'
|
||||
public final String ABOUT_ADDONS_AMO_TITLE = "Browse Firefox’s Recommended Extensions";
|
||||
|
||||
// Context Menu item strings
|
||||
public final String CONTEXT_MENU_BOOKMARK_LINK = "Bookmark Link";
|
||||
public final String CONTEXT_MENU_OPEN_LINK_IN_NEW_TAB = "Open Link in New Tab";
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.tests;
|
|||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.Actions;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
|
@ -21,7 +22,9 @@ public class testAddonManager extends PixelTest {
|
|||
public void testAddonManager() {
|
||||
Actions.EventExpecter tabEventExpecter;
|
||||
Actions.EventExpecter contentEventExpecter;
|
||||
Actions.EventExpecter amoTitleExpecter;
|
||||
final String aboutAddonsURL = mStringHelper.ABOUT_ADDONS_URL;
|
||||
final String amoTitle = mStringHelper.ABOUT_ADDONS_AMO_TITLE;
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
|
@ -31,13 +34,20 @@ public class testAddonManager extends PixelTest {
|
|||
// Set up listeners to catch the page load we're about to do
|
||||
tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
contentEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Content:DOMContentLoaded");
|
||||
amoTitleExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "about:addons");
|
||||
|
||||
// Wait for the new tab and page to load
|
||||
tabEventExpecter.blockForEvent();
|
||||
contentEventExpecter.blockForEvent();
|
||||
GeckoBundle addonsPageBundle = amoTitleExpecter.blockForBundle();
|
||||
|
||||
tabEventExpecter.unregisterListener();
|
||||
contentEventExpecter.unregisterListener();
|
||||
amoTitleExpecter.unregisterListener();
|
||||
|
||||
// Verify the AMO title
|
||||
final String actualAmoTitle = addonsPageBundle.getString("amoTitle");
|
||||
mAsserter.is(actualAmoTitle, amoTitle, "Incorrect AMO title");
|
||||
|
||||
// Verify the url
|
||||
verifyUrlBarTitle(aboutAddonsURL);
|
||||
|
|
|
@ -120,6 +120,8 @@ nsHttpConnection::nsHttpConnection()
|
|||
mIdleTimeout = (k5Sec < gHttpHandler->IdleTimeout())
|
||||
? k5Sec
|
||||
: gHttpHandler->IdleTimeout();
|
||||
|
||||
mThroughCaptivePortal = gHttpHandler->GetThroughCaptivePortal();
|
||||
}
|
||||
|
||||
nsHttpConnection::~nsHttpConnection() {
|
||||
|
@ -153,6 +155,20 @@ nsHttpConnection::~nsHttpConnection() {
|
|||
: Telemetry::HTTP_KBREAD_PER_CONN2,
|
||||
totalKBRead);
|
||||
}
|
||||
|
||||
if (mThroughCaptivePortal) {
|
||||
if (mTotalBytesRead || mTotalBytesWritten) {
|
||||
auto total = Clamp<uint32_t>(
|
||||
(mTotalBytesRead >> 10) + (mTotalBytesWritten >> 10), 0,
|
||||
std::numeric_limits<uint32_t>::max());
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::NETWORKING_DATA_TRANSFERRED_CAPTIVE_PORTAL, total);
|
||||
}
|
||||
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::NETWORKING_HTTP_CONNECTIONS_CAPTIVE_PORTAL, 1);
|
||||
}
|
||||
|
||||
if (mForceSendTimer) {
|
||||
mForceSendTimer->Cancel();
|
||||
mForceSendTimer = nullptr;
|
||||
|
|
|
@ -441,6 +441,7 @@ class nsHttpConnection final : public nsAHttpSegmentReader,
|
|||
bool mBootstrappedTimingsSet;
|
||||
|
||||
nsTArray<HttpTrafficCategory> mTrafficCategory;
|
||||
bool mThroughCaptivePortal;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnection, NS_HTTPCONNECTION_IID)
|
||||
|
|
|
@ -307,7 +307,8 @@ nsHttpHandler::nsHttpHandler()
|
|||
mProcessId(0),
|
||||
mNextChannelId(1),
|
||||
mLastActiveTabLoadOptimizationLock(
|
||||
"nsHttpConnectionMgr::LastActiveTabLoadOptimization") {
|
||||
"nsHttpConnectionMgr::LastActiveTabLoadOptimization"),
|
||||
mThroughCaptivePortal(false) {
|
||||
LOG(("Creating nsHttpHandler [this=%p].\n", this));
|
||||
|
||||
mUserAgentOverride.SetIsVoid(true);
|
||||
|
@ -567,6 +568,7 @@ nsresult nsHttpHandler::Init() {
|
|||
obsService->AddObserver(this, "psm:user-certificate-deleted", true);
|
||||
obsService->AddObserver(this, "intl:app-locales-changed", true);
|
||||
obsService->AddObserver(this, "browser-delayed-startup-finished", true);
|
||||
obsService->AddObserver(this, "network:captive-portal-connectivity", true);
|
||||
|
||||
if (!IsNeckoChild()) {
|
||||
obsService->AddObserver(
|
||||
|
@ -2338,6 +2340,9 @@ nsHttpHandler::Observe(nsISupports *subject, const char *topic,
|
|||
mAcceptLanguagesIsDirty = true;
|
||||
} else if (!strcmp(topic, "browser-delayed-startup-finished")) {
|
||||
MaybeEnableSpeculativeConnect();
|
||||
} else if (!strcmp(topic, "network:captive-portal-connectivity")) {
|
||||
nsAutoCString data8 = NS_ConvertUTF16toUTF8(data);
|
||||
mThroughCaptivePortal = data8.EqualsLiteral("captive");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -422,6 +422,7 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
|||
|
||||
HttpTrafficAnalyzer *GetHttpTrafficAnalyzer();
|
||||
|
||||
bool GetThroughCaptivePortal() { return mThroughCaptivePortal; }
|
||||
private:
|
||||
nsHttpHandler();
|
||||
|
||||
|
@ -737,6 +738,8 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
|||
|
||||
private:
|
||||
nsTHashtable<nsCStringHashKey> mBlacklistedSpdyOrigins;
|
||||
|
||||
bool mThroughCaptivePortal;
|
||||
};
|
||||
|
||||
extern StaticRefPtr<nsHttpHandler> gHttpHandler;
|
||||
|
|
|
@ -158,6 +158,8 @@ nsHttpTransaction::nsHttpTransaction()
|
|||
#endif
|
||||
mSelfAddr.raw.family = PR_AF_UNSPEC;
|
||||
mPeerAddr.raw.family = PR_AF_UNSPEC;
|
||||
|
||||
mThroughCaptivePortal = gHttpHandler->GetThroughCaptivePortal();
|
||||
}
|
||||
|
||||
void nsHttpTransaction::ResumeReading() {
|
||||
|
@ -1196,6 +1198,11 @@ void nsHttpTransaction::Close(nsresult reason) {
|
|||
}
|
||||
}
|
||||
|
||||
if (mThroughCaptivePortal) {
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::NETWORKING_HTTP_TRANSACTIONS_CAPTIVE_PORTAL, 1);
|
||||
}
|
||||
|
||||
if (relConn && mConnection) {
|
||||
MutexAutoLock lock(mLock);
|
||||
mConnection = nullptr;
|
||||
|
|
|
@ -484,6 +484,7 @@ class nsHttpTransaction final : public nsAHttpTransaction,
|
|||
RefPtr<SpdyConnectTransaction> mH2WSTransaction;
|
||||
|
||||
HttpTrafficCategory mTrafficCategory;
|
||||
bool mThroughCaptivePortal;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
[sub-sample-buffer-stitching.html]
|
||||
disabled:
|
||||
if (os == 'win' and processor == 'aarch64'): https://bugzilla.mozilla.org/show_bug.cgi?id=1533911
|
||||
if (os == 'win' and version == '6.1.7601'): https://bugzilla.mozilla.org/show_bug.cgi?id=1533762
|
||||
if (os == 'linux' and bits == 32): https://bugzilla.mozilla.org/show_bug.cgi?id=1533762
|
||||
[# AUDIT TASK RUNNER FINISHED: 2 out of 2 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -56,19 +56,11 @@ add_task(async function test_support_separator_properties() {
|
|||
);
|
||||
|
||||
let toolbox = document.querySelector("#navigator-toolbox");
|
||||
if (AppConstants.platform == "macosx") {
|
||||
Assert.ok(
|
||||
window.getComputedStyle(toolbox, "::after").boxShadow
|
||||
.includes(`rgb(${hexToRGB(SEPARATOR_BOTTOM_COLOR).join(", ")})`),
|
||||
"Bottom separator color properly set"
|
||||
);
|
||||
} else {
|
||||
Assert.equal(
|
||||
window.getComputedStyle(toolbox, "::after").borderBottomColor,
|
||||
`rgb(${hexToRGB(SEPARATOR_BOTTOM_COLOR).join(", ")})`,
|
||||
"Bottom separator color properly set"
|
||||
);
|
||||
}
|
||||
Assert.equal(
|
||||
window.getComputedStyle(toolbox).borderBottomColor,
|
||||
`rgb(${hexToRGB(SEPARATOR_BOTTOM_COLOR).join(", ")})`,
|
||||
"Bottom separator color properly set"
|
||||
);
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
|
|
|
@ -2862,6 +2862,8 @@ SearchService.prototype = {
|
|||
return val;
|
||||
},
|
||||
|
||||
_listJSONURL: ((AppConstants.platform == "android") ? APP_SEARCH_PREFIX : EXT_SEARCH_PREFIX) + "list.json",
|
||||
|
||||
_engines: { },
|
||||
__sortedEngines: null,
|
||||
_visibleDefaultEngines: [],
|
||||
|
@ -3467,11 +3469,9 @@ SearchService.prototype = {
|
|||
async _findEngines() {
|
||||
LOG("_findEngines: looking for engines in JARs");
|
||||
|
||||
let prefix = AppConstants.platform == "android" ? APP_SEARCH_PREFIX : EXT_SEARCH_PREFIX;
|
||||
let listURL = prefix + "list.json";
|
||||
let chan = makeChannel(listURL);
|
||||
let chan = makeChannel(this._listJSONURL);
|
||||
if (!chan) {
|
||||
LOG("_findEngines: " + prefix + " isn't registered");
|
||||
LOG("_findEngines: " + this._listJSONURL + " isn't registered");
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -3485,10 +3485,10 @@ SearchService.prototype = {
|
|||
resolve(event.target.responseText);
|
||||
};
|
||||
request.onerror = function(event) {
|
||||
LOG("_findEngines: failed to read " + listURL);
|
||||
LOG("_findEngines: failed to read " + this._listJSONURL);
|
||||
resolve();
|
||||
};
|
||||
request.open("GET", Services.io.newURI(listURL).spec, true);
|
||||
request.open("GET", Services.io.newURI(this._listJSONURL).spec, true);
|
||||
request.send();
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Ensure all the engines defined in list.json are valid by
|
||||
// creating a new list.json that contains every engine and
|
||||
// loading them all.
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
const {SearchService} = ChromeUtils.import("resource://gre/modules/SearchService.jsm");
|
||||
const LIST_JSON_URL = "resource://search-extensions/list.json";
|
||||
|
||||
function traverse(obj, fun) {
|
||||
for (var i in obj) {
|
||||
fun.apply(this, [i, obj[i]]);
|
||||
if (obj[i] !== null && typeof(obj[i]) == "object") {
|
||||
traverse(obj[i], fun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ss = new SearchService();
|
||||
|
||||
add_task(async function test_validate_engines() {
|
||||
let engines = await fetch(LIST_JSON_URL).then(req => req.json());
|
||||
|
||||
let visibleDefaultEngines = new Set();
|
||||
traverse(engines, (key, val) => {
|
||||
if (key === "visibleDefaultEngines") {
|
||||
val.forEach(engine => visibleDefaultEngines.add(engine));
|
||||
}
|
||||
});
|
||||
|
||||
let listjson = {default: {
|
||||
visibleDefaultEngines: Array.from(visibleDefaultEngines),
|
||||
}};
|
||||
ss._listJSONURL = "data:application/json," + JSON.stringify(listjson);
|
||||
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
await ss.init();
|
||||
});
|
|
@ -107,6 +107,7 @@ skip-if = (verify && !debug && (os == 'linux'))
|
|||
[test_paramSubstitution.js]
|
||||
[test_migrateWebExtensionEngine.js]
|
||||
[test_sendSubmissionURL.js]
|
||||
[test_validate_engines.js]
|
||||
[test_validate_manifests.js]
|
||||
[test_webextensions_install.js]
|
||||
[test_purpose.js]
|
||||
|
|
|
@ -2692,6 +2692,772 @@ update:
|
|||
operating_systems:
|
||||
- windows
|
||||
|
||||
update.startup:
|
||||
from_app_version:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the previous application version that the update was applied to
|
||||
when the update makes it to the last phase where the application has
|
||||
exited and started.
|
||||
expires: "72"
|
||||
kind: string
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
mar_partial_size_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes of a partial update MAR file when
|
||||
the update makes it to the last phase where the application has exited and
|
||||
started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
mar_complete_size_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes of a complete update MAR file when
|
||||
the update makes it to the last phase where the application has exited and
|
||||
started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
update.startup.intervals:
|
||||
check:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the check phase of the update process
|
||||
when an update makes it to the last phase where the application has exited
|
||||
and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
download_bits_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the BITS downloader for a partial update MAR file when the
|
||||
update makes it to the last phase where the application has exited and
|
||||
and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
download_bits_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the BITS downloader for a complete update MAR file when the
|
||||
update makes it to the last phase where the application has exited and
|
||||
started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
download_internal_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the internal application downloader for a partial update MAR
|
||||
file when the update makes it to the last phase where the application has
|
||||
exited and and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
download_internal_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the internal application downloader for a complete update
|
||||
MAR file when the update makes it to the last phase where the application
|
||||
has exited and and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
stage_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the stage phase of the update process
|
||||
for a partial update MAR file when the update makes it to the last phase
|
||||
where the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
stage_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the stage phase of the update process
|
||||
for a complete update MAR file when the update makes it to the last phase
|
||||
where the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
apply_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the apply phase of the update process
|
||||
for a partial update MAR file when the update makes it to the last phase
|
||||
where the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
apply_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the apply phase of the update process
|
||||
for a complete update MAR file when the update makes it to the last phase
|
||||
where the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
update.startup.downloads:
|
||||
bits_partial_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the BITS downloader for
|
||||
a partial update MAR file when the update makes it to the last phase where
|
||||
the application has exited and started. This value can be different than
|
||||
the size of the update MAR file because the value is only monitored
|
||||
during the initial download while the application is running and not if
|
||||
the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_partial_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the BITS downloader for a
|
||||
partial update MAR file when the update makes it to the last phase where
|
||||
the application has exited and started. This value can be used with the
|
||||
value of update.startup.downloads.bits_partial_bytes to estimate the bytes
|
||||
per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_complete_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the BITS downloader for
|
||||
a complete update MAR file when the update makes it to the last phase
|
||||
where the application has exited and started. This value can be different
|
||||
than the size of the update MAR file because the value is only monitored
|
||||
during the initial download while the application is running and not if
|
||||
the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_complete_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the BITS downloader for a
|
||||
complete update MAR file when the update makes it to the last phase where
|
||||
the application has exited and started. This value can be used with the
|
||||
value of update.startup.downloads.bits_complete_bytes to estimate the
|
||||
bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
internal_partial_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the internal application
|
||||
downloader for a partial update MAR file when the update makes it to the
|
||||
last phase where the application has exited and started. This value can be
|
||||
different than the size of the update MAR file because the value is only
|
||||
monitored during the initial download while the application is running and
|
||||
not if the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_partial_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the internal application
|
||||
downloader for a partial update MAR file when the update makes it to the
|
||||
last phase where the application has exited and started. This value can be
|
||||
used with the value of update.startup.downloads.internal_partial_bytes to
|
||||
estimate the bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_complete_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded by the internal
|
||||
application downloader for a complete update MAR file when an update makes
|
||||
it to the last phase where the application has exited and started. This
|
||||
value can be different than the size of the update MAR file because the
|
||||
value is only monitored during the initial download while the
|
||||
application is running and not if the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_complete_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the internal application
|
||||
downloader for a complete update MAR file when the update makes it to the
|
||||
last phase where the application has exited and started. This value can be
|
||||
used with the value of update.startup.downloads.internal_complete_bytes to
|
||||
estimate the bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
update.session:
|
||||
from_app_version:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the previous application version that the update was applied to
|
||||
when the update has finished due to a failure before the application has
|
||||
exited and started.
|
||||
expires: "72"
|
||||
kind: string
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
mar_partial_size_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes of a partial update MAR file when
|
||||
the update has finished due to a failure before the application has exited
|
||||
and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
mar_complete_size_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes of a complete update MAR file when
|
||||
the update has finished due to a failure before the application has exited
|
||||
and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
update.session.intervals:
|
||||
check:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the check phase of the update process
|
||||
when an update has finished due to a failure before the application has
|
||||
exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
download_bits_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the BITS downloader for a partial update MAR file when the
|
||||
update has finished due to a failure before the application has exited
|
||||
and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
download_bits_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the BITS downloader for a complete update MAR file when the
|
||||
update has finished due to a failure before the application has exited and
|
||||
started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
download_internal_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the internal application downloader for a partial update MAR
|
||||
file when the update has finished due to a failure before the application
|
||||
has exited and and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
download_internal_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the download phase of the update
|
||||
process using the internal application downloader for a complete update
|
||||
MAR file when the update has finished due to a failure before the
|
||||
application has exited and and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
stage_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the stage phase of the update process
|
||||
for a partial update MAR file when the update has finished due to a
|
||||
failure before the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
stage_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the stage phase of the update process
|
||||
for a complete update MAR file when the update has finished due to a
|
||||
failure before the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
apply_partial:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the apply phase of the update process
|
||||
for a partial update MAR file when the update has finished due to a
|
||||
failure before the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
apply_complete:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the interval in seconds of the apply phase of the update process
|
||||
for a complete update MAR file when the update has finished due to a
|
||||
failure before the application has exited and started.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
update.session.downloads:
|
||||
bits_partial_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the BITS downloader for
|
||||
a partial update MAR file when the update has finished due to a failure
|
||||
before the application has exited and started. This value can be
|
||||
different than the size of the update MAR file because the value is only
|
||||
monitored during the initial download while the application is running and
|
||||
not if the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_partial_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the BITS downloader for a
|
||||
partial update MAR file when the update has finished due to a failure
|
||||
before the application has exited and started. This value can be used with
|
||||
the value of update.session.downloads.bits_partial_bytes to estimate the
|
||||
bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_complete_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the BITS downloader for
|
||||
a complete update MAR file when the update has finished due to a failure
|
||||
before the application has exited and started. This value can be different
|
||||
than the size of the update MAR file because the value is only monitored
|
||||
during the initial download while the application is running and not if
|
||||
the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
bits_complete_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the BITS downloader for a
|
||||
complete update MAR file when the update has finished due to a failure
|
||||
before the application has exited and started. This value can be used with
|
||||
the value of update.session.downloads.bits_complete_bytes to estimate the
|
||||
bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
operating_systems:
|
||||
- "windows"
|
||||
|
||||
internal_partial_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded using the internal
|
||||
application downloader for a partial update MAR file when the update has
|
||||
finished due to a failure before the application has exited and started.
|
||||
This value can be different than the size of the update MAR file because
|
||||
the value is only monitored during the initial download while the
|
||||
application is running and not if the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_partial_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the internal application
|
||||
downloader for a partial update MAR file when the update has finished due
|
||||
to a failure before the application has exited and started. This value can
|
||||
be used with the value of update.session.downloads.internal_partial_bytes
|
||||
to estimate the bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_complete_bytes:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of bytes downloaded by the internal
|
||||
application downloader for a complete update MAR file when an update has
|
||||
finished due to a failure before the application has exited and started.
|
||||
This value can be different than the size of the update MAR file because
|
||||
the value is only monitored during the initial download while the
|
||||
application is running and not if the download is resumed.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
internal_complete_seconds:
|
||||
bug_numbers:
|
||||
- 1539154
|
||||
description: >
|
||||
Records the total number of seconds spent downloading during the initial
|
||||
download without exiting the application using the internal application
|
||||
downloader for a complete update MAR file when the update has finished due
|
||||
to a failure before the application has exited and started. This value can
|
||||
be used with the value of update.session.downloads.internal_complete_bytes
|
||||
to estimate the bytes per second for the download.
|
||||
expires: "72"
|
||||
kind: uint
|
||||
keyed: false
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
- rstrong@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
record_in_processes:
|
||||
- main
|
||||
|
||||
# The following section contains search counters.
|
||||
browser.search:
|
||||
with_ads:
|
||||
|
@ -2848,6 +3614,45 @@ networking:
|
|||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
data_transferred_captive_portal:
|
||||
bug_numbers:
|
||||
- 1543005
|
||||
description: >
|
||||
Hom many KB has been transfer over a captive portal during a subsession.
|
||||
expires: "73"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- ddamjanovic@mozilla.com
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
http_transactions_captive_portal:
|
||||
bug_numbers:
|
||||
- 1543005
|
||||
description: >
|
||||
Number of http transactions transfer over a captive portal during a subsession.
|
||||
expires: "73"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- ddamjanovic@mozilla.com
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
http_connections_captive_portal:
|
||||
bug_numbers:
|
||||
- 1543005
|
||||
description: >
|
||||
Number of http connections transfer over a captive portal during a subsession.
|
||||
expires: "73"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- ddamjanovic@mozilla.com
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
# The following section is for probes testing the Telemetry system. They will not be
|
||||
# submitted in pings and are only used for testing.
|
||||
telemetry.test:
|
||||
|
|
|
@ -62,8 +62,6 @@ skip-if = (verify && (os == 'win'))
|
|||
[test_autocomplete3.xul]
|
||||
[test_autocomplete4.xul]
|
||||
[test_autocomplete5.xul]
|
||||
[test_autocomplete_delayOnPaste.xul]
|
||||
subsuite = clipboard
|
||||
[test_autocomplete_emphasis.xul]
|
||||
[test_autocomplete_with_composition_on_input.html]
|
||||
[test_autocomplete_with_composition_on_textbox.xul]
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window title="Autocomplete Widget Test 4"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="runTest();">
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/globalOverlay.js"/>
|
||||
|
||||
<textbox id="autocomplete"
|
||||
type="autocomplete"
|
||||
completedefaultindex="true"
|
||||
onsearchcomplete="searchComplete();"
|
||||
timeout="0"
|
||||
autocompletesearch="simple"/>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function autoCompleteSimpleResult(aString) {
|
||||
this.searchString = aString;
|
||||
this.searchResult = Ci.nsIAutoCompleteResult.RESULT_SUCCESS;
|
||||
this.matchCount = 1;
|
||||
this._param = "Result";
|
||||
}
|
||||
autoCompleteSimpleResult.prototype = {
|
||||
_param: "",
|
||||
searchString: null,
|
||||
searchResult: Ci.nsIAutoCompleteResult.RESULT_FAILURE,
|
||||
defaultIndex: 0,
|
||||
errorDescription: null,
|
||||
matchCount: 0,
|
||||
getValueAt: function() { return this._param; },
|
||||
getCommentAt: function() { return null; },
|
||||
getStyleAt: function() { return null; },
|
||||
getImageAt: function() { return null; },
|
||||
getFinalCompleteValueAt: function() { return this.getValueAt(); },
|
||||
getLabelAt: function() { return null; },
|
||||
removeValueAt: function() {}
|
||||
};
|
||||
|
||||
// A basic autocomplete implementation that returns one result.
|
||||
let autoCompleteSimple = {
|
||||
classID: Components.ID("0a2afbdb-f30e-47d1-9cb1-0cd160240aca"),
|
||||
contractID: "@mozilla.org/autocomplete/search;1?name=simple",
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
Ci.nsIFactory,
|
||||
Ci.nsIAutoCompleteSearch
|
||||
]),
|
||||
createInstance: function (outer, iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
registerFactory: function () {
|
||||
let registrar =
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(this.classID, "Test Simple Autocomplete",
|
||||
this.contractID, this);
|
||||
},
|
||||
unregisterFactory: function () {
|
||||
let registrar =
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(this.classID, this);
|
||||
},
|
||||
|
||||
startSearch: function (aString, aParam, aResult, aListener) {
|
||||
let result = new autoCompleteSimpleResult(aString);
|
||||
aListener.onSearchResult(this, result);
|
||||
},
|
||||
stopSearch: function () {}
|
||||
};
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let gACTimer;
|
||||
let gAutoComplete;
|
||||
|
||||
function searchComplete() {
|
||||
is(gAutoComplete.value, "result", "Value should be autocompleted now");
|
||||
ok(Date.now() - gACTimer > 500, "There should be a delay before autocomplete");
|
||||
|
||||
// Unregister the factory so that we don't get in the way of other tests
|
||||
autoCompleteSimple.unregisterFactory();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
autoCompleteSimple.registerFactory();
|
||||
gAutoComplete = $("autocomplete");
|
||||
|
||||
const SEARCH_STRING = "res";
|
||||
|
||||
function cbCallback() {
|
||||
gAutoComplete.focus();
|
||||
synthesizeKey("v", { accelKey: true });
|
||||
is(gAutoComplete.value, SEARCH_STRING, "Value should not be autocompleted immediately");
|
||||
}
|
||||
|
||||
SimpleTest.waitForClipboard(SEARCH_STRING, function () {
|
||||
gACTimer = Date.now();
|
||||
Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper)
|
||||
.copyStringToClipboard(SEARCH_STRING, Ci.nsIClipboard.kGlobalClipboard);
|
||||
}, cbCallback, cbCallback);
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display">
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</window>
|
|
@ -45,15 +45,8 @@
|
|||
this._searchCompleteHandler = this.initEventHandler("searchcomplete");
|
||||
this._textEnteredHandler = this.initEventHandler("textentered");
|
||||
this._textRevertedHandler = this.initEventHandler("textreverted");
|
||||
|
||||
// For security reasons delay searches on pasted values.
|
||||
this.inputField.controllers.insertControllerAt(0, this._pasteController);
|
||||
]]></constructor>
|
||||
|
||||
<destructor><![CDATA[
|
||||
this.inputField.controllers.removeController(this._pasteController);
|
||||
]]></destructor>
|
||||
|
||||
<!-- =================== nsIAutoCompleteInput =================== -->
|
||||
|
||||
<field name="_popup">null</field>
|
||||
|
@ -113,18 +106,8 @@
|
|||
onget="var m = parseInt(this.getAttribute('minresultsforpopup')); return isNaN(m) ? 1 : m;"/>
|
||||
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;">
|
||||
<getter><![CDATA[
|
||||
// For security reasons delay searches on pasted values.
|
||||
if (this._valueIsPasted) {
|
||||
let t = parseInt(this.getAttribute("pastetimeout"));
|
||||
return isNaN(t) ? 1000 : t;
|
||||
}
|
||||
|
||||
let t = parseInt(this.getAttribute("timeout"));
|
||||
return isNaN(t) ? 50 : t;
|
||||
]]></getter>
|
||||
</property>
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="var t = parseInt(this.getAttribute('timeout')); return isNaN(t) ? 50 : t;"/>
|
||||
|
||||
<property name="searchParam"
|
||||
onget="return this.getAttribute('autocompletesearchparam') || '';"
|
||||
|
@ -554,25 +537,6 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_valueIsPasted">false</field>
|
||||
<field name="_pasteController"><![CDATA[
|
||||
({
|
||||
_autocomplete: this,
|
||||
_kGlobalClipboard: Ci.nsIClipboard.kGlobalClipboard,
|
||||
supportsCommand: aCommand => aCommand == "cmd_paste",
|
||||
doCommand(aCommand) {
|
||||
this._autocomplete._valueIsPasted = true;
|
||||
this._autocomplete.editor.paste(this._kGlobalClipboard);
|
||||
this._autocomplete._valueIsPasted = false;
|
||||
},
|
||||
isCommandEnabled(aCommand) {
|
||||
return this._autocomplete.editor.isSelectionEditable &&
|
||||
this._autocomplete.editor.canPaste(this._kGlobalClipboard);
|
||||
},
|
||||
onEvent() {},
|
||||
})
|
||||
]]></field>
|
||||
|
||||
<method name="_setValueInternal">
|
||||
<parameter name="aValue"/>
|
||||
<parameter name="aIsUserInput"/>
|
||||
|
|
|
@ -233,6 +233,8 @@ var gLogfileWritePromise;
|
|||
// at once. Computers with many users (ex: a school computer), should not end
|
||||
// up with dozens of BITS jobs.
|
||||
var gBITSInUseByAnotherUser = false;
|
||||
// The start time in milliseconds of the update check.
|
||||
var gCheckStartMs;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function aus_gLogEnabled() {
|
||||
return Services.prefs.getBoolPref(PREF_APP_UPDATE_LOG, false) ||
|
||||
|
@ -1933,8 +1935,16 @@ UpdateService.prototype = {
|
|||
// be resumed the next time the application starts. Downloads using
|
||||
// Windows BITS are not stopped since they don't require Firefox to be
|
||||
// running to perform the download.
|
||||
if (this._downloader && !this._downloader.usingBits) {
|
||||
this.stopDownload();
|
||||
if (this._downloader) {
|
||||
if (!this._downloader.usingBits) {
|
||||
this.stopDownload();
|
||||
} else {
|
||||
// The BITS downloader isn't stopped on exit so the
|
||||
// active-update.xml needs to be saved for the values sent to
|
||||
// telemetry to be saved to disk.
|
||||
Cc["@mozilla.org/updates/update-manager;1"].
|
||||
getService(Ci.nsIUpdateManager).saveUpdates();
|
||||
}
|
||||
}
|
||||
// Prevent leaking the downloader (bug 454964)
|
||||
this._downloader = null;
|
||||
|
@ -2127,6 +2137,10 @@ UpdateService.prototype = {
|
|||
update.errorCode = parseInt(parts[1]);
|
||||
}
|
||||
|
||||
if (update.state == STATE_SUCCEEDED || update.patchCount == 1 ||
|
||||
(update.selectedPatch && update.selectedPatch.type == "complete")) {
|
||||
AUSTLMY.pingUpdatePhases(update, true);
|
||||
}
|
||||
|
||||
if (status != STATE_SUCCEEDED) {
|
||||
// Rotate the update logs so the update log isn't removed. By passing
|
||||
|
@ -3175,6 +3189,10 @@ UpdateManager.prototype = {
|
|||
if (!update) {
|
||||
return;
|
||||
}
|
||||
|
||||
let patch = update.selectedPatch.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
patch.setProperty("stageFinished", Math.ceil(Date.now() / 1000));
|
||||
|
||||
var status = readStatusFile(getUpdatesDir());
|
||||
pingStateAndStatusCodes(update, false, status);
|
||||
var parts = status.split(":");
|
||||
|
@ -3200,6 +3218,10 @@ UpdateManager.prototype = {
|
|||
writeStatusFile(getUpdatesDir(), update.state = STATE_APPLIED_SERVICE);
|
||||
}
|
||||
|
||||
if (update.state == STATE_FAILED) {
|
||||
AUSTLMY.pingUpdatePhases(update, false);
|
||||
}
|
||||
|
||||
// Now that the active update's properties have been updated write the
|
||||
// active-update.xml to disk. Since there have been no changes to the update
|
||||
// history the updates.xml will not be written to disk.
|
||||
|
@ -3223,6 +3245,7 @@ UpdateManager.prototype = {
|
|||
update.state == STATE_PENDING ||
|
||||
update.state == STATE_PENDING_SERVICE ||
|
||||
update.state == STATE_PENDING_ELEVATE) {
|
||||
patch.setProperty("applyStart", Math.floor(Date.now() / 1000));
|
||||
// Notify the user that an update has been staged and is ready for
|
||||
// installation (i.e. that they should restart the application).
|
||||
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
|
||||
|
@ -3378,6 +3401,7 @@ Checker.prototype = {
|
|||
throw Cr.NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
gCheckStartMs = Date.now();
|
||||
let UpdateServiceInstance = UpdateServiceFactory.createInstance();
|
||||
// |force| can override |canCheckForUpdates| since |force| indicates a
|
||||
// manual update check. But nothing should override enterprise policies.
|
||||
|
@ -3650,6 +3674,17 @@ Downloader.prototype = {
|
|||
*/
|
||||
_bitsActiveNotifications: false,
|
||||
|
||||
/**
|
||||
* The start time of the first download attempt in milliseconds for telemetry.
|
||||
*/
|
||||
_startDownloadMs: null,
|
||||
|
||||
/**
|
||||
* The name of the downloader being used to download the update. This is used
|
||||
* when setting property names on the update patch for telemetry.
|
||||
*/
|
||||
_downloaderName: "bits",
|
||||
|
||||
/**
|
||||
* Cancels the active download.
|
||||
*
|
||||
|
@ -3878,13 +3913,28 @@ Downloader.prototype = {
|
|||
AUSTLMY.pingDownloadCode(undefined, AUSTLMY.DWNLD_ERR_NO_UPDATE_PATCH);
|
||||
return readStatusFile(updateDir);
|
||||
}
|
||||
// QI the update and the patch to nsIWritablePropertyBag so it isn't
|
||||
// necessary later in the download code.
|
||||
this._update.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
if (gCheckStartMs && !this._update.getProperty("checkInterval")) {
|
||||
let interval = Math.max(Math.ceil((Date.now() - gCheckStartMs) / 1000), 1);
|
||||
this._update.setProperty("checkInterval", interval);
|
||||
}
|
||||
// this._patch implements nsIWritablePropertyBag. Expose that interface
|
||||
// immediately after a patch is assigned so that this._patch.getProperty
|
||||
// and this._patch.setProperty can always safely be called.
|
||||
this._patch.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
this.isCompleteUpdate = this._patch.type == "complete";
|
||||
|
||||
if (!this._canUseBits(this._patch)) {
|
||||
let canUseBits = this._canUseBits(this._patch);
|
||||
if (!canUseBits) {
|
||||
this._downloaderName = "internal";
|
||||
}
|
||||
if (!this._patch.getProperty(this._downloaderName + "DownloadStart")) {
|
||||
this._patch.setProperty(this._downloaderName + "DownloadStart", Math.floor(Date.now() / 1000));
|
||||
}
|
||||
|
||||
if (!canUseBits) {
|
||||
let patchFile = getUpdatesDir().clone();
|
||||
patchFile.append(FILE_UPDATE_MAR);
|
||||
|
||||
|
@ -4108,6 +4158,17 @@ Downloader.prototype = {
|
|||
getService(Ci.nsIUpdateManager).saveUpdates();
|
||||
}
|
||||
}
|
||||
// Only record the download bytes per second when there isn't already a
|
||||
// value for the bytes per second so downloads that are already in progess
|
||||
// don't have their records overwritten. When the Update Agent is
|
||||
// implemented this should be reworked so that telemetry receives the bytes
|
||||
// and seconds it took to complete for the entire update download instead of
|
||||
// just the sample that is currently recorded. Note: this._patch has already
|
||||
// been QI'd to nsIWritablePropertyBag.
|
||||
if (!this._patch.getProperty("internalBytes") &&
|
||||
!this._patch.getProperty("bitsBytes")) {
|
||||
this._startDownloadMs = Date.now();
|
||||
}
|
||||
|
||||
// Make shallow copy in case listeners remove themselves when called.
|
||||
let listeners = this._listeners.concat();
|
||||
|
@ -4131,6 +4192,11 @@ Downloader.prototype = {
|
|||
onProgress: function Downloader_onProgress(request, context, progress,
|
||||
maxProgress) {
|
||||
LOG("Downloader:onProgress - progress: " + progress + "/" + maxProgress);
|
||||
if (this._startDownloadMs) {
|
||||
let seconds = Math.round((Date.now() - this._startDownloadMs) / 1000);
|
||||
this._patch.setProperty(this._downloaderName + "Seconds", seconds);
|
||||
this._patch.setProperty(this._downloaderName + "Bytes", progress);
|
||||
}
|
||||
|
||||
if (progress > this._patch.size) {
|
||||
LOG("Downloader:onProgress - progress: " + progress +
|
||||
|
@ -4253,6 +4319,8 @@ Downloader.prototype = {
|
|||
"current fail: " + this.updateService._consecutiveSocketErrors + ", " +
|
||||
"max fail: " + maxFail + ", " +
|
||||
"retryTimeout: " + retryTimeout);
|
||||
this._patch.setProperty(this._downloaderName + "DownloadFinished",
|
||||
Math.floor(Date.now() / 1000));
|
||||
if (Components.isSuccessCode(status)) {
|
||||
if (this._verifyDownload()) {
|
||||
if (shouldUseService()) {
|
||||
|
@ -4456,6 +4524,7 @@ Downloader.prototype = {
|
|||
Services.prefs.setIntPref(PREF_APP_UPDATE_DOWNLOAD_ATTEMPTS, downloadAttempts);
|
||||
let maxAttempts = Math.min(Services.prefs.getIntPref(PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS, 2), 10);
|
||||
|
||||
AUSTLMY.pingUpdatePhases(this._update, false);
|
||||
if (downloadAttempts > maxAttempts) {
|
||||
LOG("Downloader:onStopRequest - notifying observers of error. " +
|
||||
"topic: update-error, status: download-attempts-exceeded, " +
|
||||
|
@ -4496,6 +4565,7 @@ Downloader.prototype = {
|
|||
LOG("Downloader:onStopRequest - attempting to stage update: " +
|
||||
this._update.name);
|
||||
gUpdateFileWriteInfo = {phase: "stage", failure: false};
|
||||
this._patch.setProperty("stageStart", Math.floor(Date.now() / 1000));
|
||||
// Stage the update
|
||||
try {
|
||||
Cc["@mozilla.org/updates/update-processor;1"].
|
||||
|
@ -4509,6 +4579,8 @@ Downloader.prototype = {
|
|||
shouldShowPrompt = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._patch.setProperty("applyStart", Math.floor(Date.now() / 1000));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,14 @@ const {BitsError, BitsUnknownError} =
|
|||
ChromeUtils.import("resource://gre/modules/Bits.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||
|
||||
// It is possible for the update.session telemetry to be set more than once
|
||||
// which must be prevented since they are scalars and setting them more than
|
||||
// once could lead to values set in the first ping not being present in the
|
||||
// next ping which would make the values incomprehensible in relation to the
|
||||
// other values. This isn't needed for update.startup since this will only be
|
||||
// set once during startup.
|
||||
var gUpdatePhasesSetForSession = false;
|
||||
|
||||
var AUSTLMY = {
|
||||
// Telemetry for the application update background update check occurs when
|
||||
// the background update timer fires after the update interval which is
|
||||
|
@ -432,6 +440,111 @@ var AUSTLMY = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit the update phase telemetry. These are scalars and must only be
|
||||
* submitted once per sesssion. The update.startup is only submitted once
|
||||
* once per session due to it only being submitted during startup and only the
|
||||
* first call to pingUpdatePhases for update.session will be submitted.
|
||||
*
|
||||
* @param aUpdate
|
||||
* The update object which contains the values to submit to telemetry.
|
||||
* @param aIsStartup
|
||||
* If true the telemetry will be set under update.startup and if false
|
||||
* the telemetry will be set under update.session. When false
|
||||
* subsequent calls will return early and not submit telemetry.
|
||||
*/
|
||||
pingUpdatePhases: function UT_pingUpdatePhases(aUpdate, aIsStartup) {
|
||||
if (!aIsStartup && !Cu.isInAutomation) {
|
||||
if (gUpdatePhasesSetForSession) {
|
||||
return;
|
||||
}
|
||||
gUpdatePhasesSetForSession = true;
|
||||
}
|
||||
let basePrefix = aIsStartup ? "update.startup." : "update.session.";
|
||||
// None of the calls to getProperty should fail.
|
||||
try {
|
||||
let update = aUpdate.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
let scalarSet = Services.telemetry.scalarSet;
|
||||
|
||||
// Though it is possible that the previous app version that was updated
|
||||
// from could change the record is for the app version that initiated the
|
||||
// update.
|
||||
scalarSet(basePrefix + "from_app_version", aUpdate.previousAppVersion);
|
||||
|
||||
// The check interval only happens once even if the partial patch fails
|
||||
// to apply on restart and the complete patch is downloaded.
|
||||
scalarSet(basePrefix + "intervals.check",
|
||||
update.getProperty("checkInterval"));
|
||||
|
||||
for (let i = 0; i < aUpdate.patchCount; ++i) {
|
||||
let patch =
|
||||
aUpdate.getPatchAt(i).QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
let type = patch.type;
|
||||
|
||||
scalarSet(basePrefix + "mar_" + type + "_size_bytes", patch.size);
|
||||
|
||||
let prefix = basePrefix + "intervals.";
|
||||
let internalDownloadStart = patch.getProperty("internalDownloadStart");
|
||||
let internalDownloadFinished =
|
||||
patch.getProperty("internalDownloadFinished");
|
||||
if (internalDownloadStart !== null && internalDownloadFinished !== null) {
|
||||
scalarSet(prefix + "download_internal_" + type,
|
||||
Math.max((internalDownloadFinished - internalDownloadStart), 1));
|
||||
}
|
||||
|
||||
let bitsDownloadStart = patch.getProperty("bitsDownloadStart");
|
||||
let bitsDownloadFinished = patch.getProperty("bitsDownloadFinished");
|
||||
if (bitsDownloadStart !== null && bitsDownloadFinished !== null) {
|
||||
scalarSet(prefix + "download_bits_" + type,
|
||||
Math.max((bitsDownloadFinished - bitsDownloadStart), 1));
|
||||
}
|
||||
|
||||
|
||||
let stageStart = patch.getProperty("stageStart");
|
||||
let stageFinished = patch.getProperty("stageFinished");
|
||||
if (stageStart !== null && stageFinished !== null) {
|
||||
scalarSet(prefix + "stage_" + type,
|
||||
Math.max((stageFinished - stageStart), 1));
|
||||
}
|
||||
|
||||
// Both the partial and the complete patch are recorded for the apply
|
||||
// interval because it is possible for a partial patch to fail when it
|
||||
// is applied during a restart and then to try the complete patch.
|
||||
let applyStart = patch.getProperty("applyStart");
|
||||
if (applyStart !== null) {
|
||||
let applyFinished = Date.now() / 1000;
|
||||
scalarSet(prefix + "apply_" + type,
|
||||
Math.max((applyFinished - applyStart), 1));
|
||||
}
|
||||
|
||||
prefix = basePrefix + "downloads.";
|
||||
let internalBytes = patch.getProperty("internalBytes");
|
||||
if (internalBytes !== null) {
|
||||
scalarSet(prefix + "internal_" + type + "_bytes",
|
||||
Math.max(internalBytes, 1));
|
||||
}
|
||||
let internalSeconds = patch.getProperty("internalSeconds");
|
||||
if (internalSeconds !== null) {
|
||||
scalarSet(prefix + "internal_" + type + "_seconds",
|
||||
Math.max(internalSeconds, 1));
|
||||
}
|
||||
|
||||
let bitsBytes = patch.getProperty("bitsBytes");
|
||||
if (bitsBytes !== null) {
|
||||
scalarSet(prefix + "bits_" + type + "_bytes",
|
||||
Math.max(bitsBytes, 1));
|
||||
}
|
||||
let bitsSeconds = patch.getProperty("bitsSeconds");
|
||||
if (bitsSeconds !== null) {
|
||||
scalarSet(prefix + "bits_" + type + "_seconds",
|
||||
Math.max(bitsSeconds, 1));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit a telemetry ping for the last page displayed by the update wizard.
|
||||
*
|
||||
|
|
|
@ -74,4 +74,26 @@ reason = test must be able to prevent file deletion.
|
|||
[browser_doorhanger_sp_patch_partialApplyFailure_complete.js]
|
||||
[browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js]
|
||||
[browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js]
|
||||
|
||||
# Telemetry Application Update Tests
|
||||
[browser_telemetry_completeBadSize.js]
|
||||
[browser_telemetry_partialBadSize_completeBadSize.js]
|
||||
[browser_telemetry_complete_stageFailure.js]
|
||||
skip-if = asan
|
||||
reason = Bug 1545712
|
||||
[browser_telemetry_partial_stageFailure_complete_stageFailure.js]
|
||||
skip-if = asan
|
||||
reason = Bug 1545712
|
||||
[browser_telemetry_complete_applyFailure.js]
|
||||
[browser_telemetry_partial_applyFailure_complete_applyFailure.js]
|
||||
[browser_telemetry_partial_applyFailure_complete_stageFailure.js]
|
||||
skip-if = asan
|
||||
reason = Bug 1545712
|
||||
[browser_telemetry_partial_applyFailure_complete_applied.js]
|
||||
[browser_telemetry_partial_applyFailure_complete_staged_applied.js]
|
||||
[browser_telemetry_partialBadSize_complete_staged_applied.js]
|
||||
[browser_telemetry_complete_applied.js]
|
||||
[browser_telemetry_partial_applied.js]
|
||||
[browser_telemetry_partial_staged_applied.js]
|
||||
[browser_telemetry_complete_staged_applied.js]
|
||||
[browser_TelemetryUpdatePing.js]
|
||||
|
|
|
@ -2,7 +2,6 @@ add_task(async function testDownloadFailures() {
|
|||
const maxBackgroundErrors = 5;
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_BACKGROUNDMAXERRORS, maxBackgroundErrors],
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 2],
|
||||
]});
|
||||
let updateParams = "badURL=1";
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ add_task(async function testBackgroundWindowFailures() {
|
|||
const maxBackgroundErrors = 5;
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_BACKGROUNDMAXERRORS, maxBackgroundErrors],
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 2],
|
||||
]});
|
||||
|
||||
let updateParams = "badURL=1";
|
||||
|
|
|
@ -4,7 +4,6 @@ add_task(async function testCompleteAndPartialPatchesWithBadCompleteSize() {
|
|||
]});
|
||||
|
||||
let updateParams = "invalidCompleteSize=1&promptWaitTime=0";
|
||||
|
||||
await runUpdateTest(updateParams, 1, [
|
||||
{
|
||||
notificationId: "update-restart",
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
add_task(async function testCompletePatchWithBadCompleteSize() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 2],
|
||||
]});
|
||||
|
||||
let updateParams = "completePatchOnly=1&invalidCompleteSize=1";
|
||||
|
||||
await runUpdateTest(updateParams, 1, [
|
||||
{
|
||||
// if we fail maxBackgroundErrors download attempts, then we want to
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
add_task(async function testPartialPatchWithBadPartialSize() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 2],
|
||||
]});
|
||||
let updateParams = "partialPatchOnly=1&invalidPartialSize=1";
|
||||
|
||||
await runUpdateTest(updateParams, 1, [
|
||||
{
|
||||
// if we fail maxBackgroundErrors download attempts, then we want to
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
add_task(async function testCompleteAndPartialPatchesWithBadSizes() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 2],
|
||||
]});
|
||||
let updateParams = "invalidPartialSize=1&invalidCompleteSize=1";
|
||||
|
||||
await runUpdateTest(updateParams, 1, [
|
||||
{
|
||||
// if we fail maxBackgroundErrors download attempts, then we want to
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
add_task(async function testPartialPatchApplyFailureWithCompleteValidationFailure() {
|
||||
// because of the way we're simulating failure, we have to just pretend we've already
|
||||
// retried.
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS, 0],
|
||||
]});
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS, 0],
|
||||
],
|
||||
});
|
||||
|
||||
let patchProps = {type: "partial",
|
||||
state: STATE_PENDING};
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.session
|
||||
// Complete patch only
|
||||
// Complete patch download failure
|
||||
add_task(async function telemetry_completeBadSize() {
|
||||
let updateParams = "&completePatchOnly=1&invalidCompleteSize=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-error");
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
forSession: true,
|
||||
noPartialPatch: true,
|
||||
completeBadSize: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Complete patch only
|
||||
// Complete patch download
|
||||
// Complete patch applied
|
||||
add_task(async function telemetry_complete_applied() {
|
||||
let updateParams = "&completePatchOnly=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noPartialPatch: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Complete patch only
|
||||
// Complete patch download
|
||||
// Complete patch apply failure
|
||||
add_task(async function telemetry_complete_applyFailure() {
|
||||
let updateParams = "&completePatchOnly=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noPartialPatch: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.session
|
||||
// Complete patch only
|
||||
// Complete patch download
|
||||
// Complete patch stage failure
|
||||
add_task(async function telemetry_complete_stageFailure() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
|
||||
let updateParams = "&completePatchOnly=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-staged", true);
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
forSession: true,
|
||||
noPartialPatch: true,
|
||||
noApplyComplete: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Complete patch only
|
||||
// Complete patch download
|
||||
// Complete patch staged
|
||||
// Complete patch applied
|
||||
add_task(async function telemetry_complete_staged_applied() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
|
||||
let updateParams = "&completePatchOnly=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-staged");
|
||||
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noPartialPatch: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.session
|
||||
// Partial and complete patches
|
||||
// Partial patch download failure
|
||||
// Complete patch download failure
|
||||
add_task(async function telemetry_partialBadSize_completeBadSize() {
|
||||
let updateParams = "&invalidPartialSize=1&invalidCompleteSize=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-error");
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
forSession: true,
|
||||
partialBadSize: true,
|
||||
completeBadSize: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download failure
|
||||
// Complete patch download
|
||||
// Complete patch staged
|
||||
// Complete patch applied
|
||||
add_task(async function telemetry_partialBadSize_complete_staged_applied() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
|
||||
let updateParams = "&invalidPartialSize=1";
|
||||
await runTelemetryUpdateTest(updateParams, "update-staged");
|
||||
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
partialBadSize: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch applied
|
||||
add_task(async function telemetry_partial_applied() {
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noInternalComplete: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch apply failure
|
||||
// Complete patch download
|
||||
// Complete patch applied
|
||||
add_task(async function telemetry_sp_partialBadSize_complete_staged_applied() {
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
|
||||
// The download of the complete patch will happen automatically.
|
||||
await waitForEvent("update-downloaded");
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch apply failure
|
||||
// Complete patch download
|
||||
// Complete patch apply failure
|
||||
add_task(async function telemetry_partial_applyFailure_complete_applyFailure() {
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
|
||||
// The download of the complete patch will happen automatically.
|
||||
await waitForEvent("update-downloaded");
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.session
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch apply failure
|
||||
// Complete patch download
|
||||
// Complete patch stage failure
|
||||
add_task(async function telemetry_partial_applyFailure_complete_stageFailure() {
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
// Now that staging is enabled setup the test updater.
|
||||
await setupTestUpdater();
|
||||
// Remove the update-settings.ini file so staging fails.
|
||||
removeUpdateSettingsIni();
|
||||
// Fail applying the partial.
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry wasn't set.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
|
||||
// The download and staging of the complete patch will happen automatically.
|
||||
await waitForEvent("update-staged");
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
forSession: true,
|
||||
noStagePartial: true,
|
||||
noApplyComplete: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch apply failure
|
||||
// Complete patch download
|
||||
// Complete patch staged
|
||||
// Complete patch applied
|
||||
add_task(async function telemetry_partial_applyFailure_complete_staged_applied() {
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-downloaded");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
// Now that staging is enabled setup the test updater.
|
||||
await setupTestUpdater();
|
||||
// Fail applying the partial.
|
||||
writeStatusFile(STATE_FAILED_CRC_ERROR);
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
|
||||
// The download and staging of the complete will happen automatically.
|
||||
await waitForEvent("update-staged");
|
||||
// Succeed applying the complete patch.
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noStagePartial: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.session
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch stage failure
|
||||
// Complete patch download
|
||||
// Complete patch stage failure
|
||||
add_task(async function telemetry_partial_stageFailure_complete_stageFailure() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-staged", true);
|
||||
|
||||
await waitForEvent("update-staged");
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
forSession: true,
|
||||
noApplyPartial: true,
|
||||
noApplyComplete: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
testPostUpdateProcessing();
|
||||
// Verify that update phase startup telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(true);
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Telemetry test for Application Update phases.
|
||||
// Telemetry update.startup
|
||||
// Partial and complete patches
|
||||
// Partial patch download
|
||||
// Partial patch staged
|
||||
// Partial patch applied
|
||||
add_task(async function telemetry_partial_staged_applied() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, true],
|
||||
],
|
||||
});
|
||||
|
||||
let updateParams = "";
|
||||
await runTelemetryUpdateTest(updateParams, "update-staged");
|
||||
|
||||
writeStatusFile(STATE_SUCCEEDED);
|
||||
testPostUpdateProcessing();
|
||||
|
||||
let expected = getTelemetryUpdatePhaseValues({
|
||||
noInternalComplete: true,
|
||||
});
|
||||
checkTelemetryUpdatePhases(expected);
|
||||
|
||||
// Verify that update phase session telemetry is empty.
|
||||
checkTelemetryUpdatePhaseEmpty(false);
|
||||
});
|
|
@ -46,12 +46,16 @@ requestLongerTimeout(10);
|
|||
add_task(async function setupTestCommon() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_DOWNLOAD_ATTEMPTS, 0],
|
||||
[PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS, 2],
|
||||
[PREF_APP_UPDATE_LOG, gDebugTest],
|
||||
[PREF_APP_UPDATE_SERVICE_ENABLED, false],
|
||||
],
|
||||
});
|
||||
|
||||
setUpdateTimerPrefs();
|
||||
removeUpdateFiles(true);
|
||||
AppMenuNotifications.removeNotification(/.*/);
|
||||
// Most app update mochitest-browser-chrome tests expect auto update to be
|
||||
// enabled. Those that don't will explicitly change this.
|
||||
await setAppUpdateAutoEnabledHelper(true);
|
||||
|
@ -61,6 +65,7 @@ add_task(async function setupTestCommon() {
|
|||
* Common tasks to perform for all tests after each one has finished.
|
||||
*/
|
||||
registerCleanupFunction(async () => {
|
||||
AppMenuNotifications.removeNotification(/.*/);
|
||||
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
|
||||
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "");
|
||||
UpdateListener.reset();
|
||||
|
@ -120,8 +125,9 @@ async function continueFileHandler(leafName) {
|
|||
}
|
||||
}
|
||||
if (continueFile.exists()) {
|
||||
throw new Error("The continue file should not exist, path: " +
|
||||
continueFile.path);
|
||||
logTestInfo("The continue file should not exist, path: " +
|
||||
continueFile.path);
|
||||
continueFile.remove(false);
|
||||
}
|
||||
debugDump("Creating continue file, path: " + continueFile.path);
|
||||
continueFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
|
@ -258,7 +264,6 @@ function runUpdateTest(updateParams, checkAttempts, steps) {
|
|||
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
|
||||
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
|
||||
[PREF_APP_UPDATE_IDLETIME, 0],
|
||||
[PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
|
||||
|
@ -305,7 +310,6 @@ function runUpdateProcessingTest(updates, steps) {
|
|||
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
|
||||
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
|
||||
[PREF_APP_UPDATE_IDLETIME, 0],
|
||||
[PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
|
||||
|
@ -676,7 +680,6 @@ function runAboutDialogUpdateTest(updateParams, backgroundUpdate, steps) {
|
|||
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_SERVICE_ENABLED, false],
|
||||
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
|
||||
[PREF_APP_UPDATE_URL_MANUAL, detailsURL],
|
||||
],
|
||||
|
@ -805,7 +808,6 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
|
|||
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_SERVICE_ENABLED, false],
|
||||
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
|
||||
[PREF_APP_UPDATE_URL_MANUAL, detailsURL],
|
||||
],
|
||||
|
@ -841,3 +843,274 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
|
|||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the modified update-settings.ini file so the updater will fail to
|
||||
* stage an update.
|
||||
*/
|
||||
function removeUpdateSettingsIni() {
|
||||
if (Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
|
||||
let greDir = getGREDir();
|
||||
let updateSettingsIniBak = greDir.clone();
|
||||
updateSettingsIniBak.append(FILE_UPDATE_SETTINGS_INI_BAK);
|
||||
if (updateSettingsIniBak.exists()) {
|
||||
let updateSettingsIni = greDir.clone();
|
||||
updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
|
||||
updateSettingsIni.remove(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a telemetry update test. This will set various common prefs for
|
||||
* updating, checks for an update, and waits for the specified observer
|
||||
* notification.
|
||||
*
|
||||
* @param updateParams
|
||||
* Params which will be sent to app_update.sjs.
|
||||
* @param event
|
||||
* The observer notification to wait for before proceeding.
|
||||
* @param stageFailure (optional)
|
||||
* Whether to force a staging failure by removing the modified
|
||||
* update-settings.ini file.
|
||||
* @return A promise which will resolve after the .
|
||||
*/
|
||||
function runTelemetryUpdateTest(updateParams, event, stageFailure = false) {
|
||||
// Some elements append a trailing /. After the chrome tests are removed this
|
||||
// code can be changed so URL_HOST already has a trailing /.
|
||||
let detailsURL = URL_HOST + "/";
|
||||
return (async function() {
|
||||
Services.telemetry.clearScalars();
|
||||
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
|
||||
],
|
||||
});
|
||||
|
||||
await setupTestUpdater();
|
||||
|
||||
if (stageFailure) {
|
||||
removeUpdateSettingsIni();
|
||||
}
|
||||
|
||||
let updateURL = URL_HTTP_UPDATE_SJS + "?detailsURL=" + detailsURL +
|
||||
updateParams + getVersionParams();
|
||||
setUpdateURL(updateURL);
|
||||
if (Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
|
||||
// Since MOZ_TEST_SKIP_UPDATE_STAGE is checked before
|
||||
// MOZ_TEST_SLOW_SKIP_UPDATE_STAGE in updater.cpp this removes the need
|
||||
// for the continue file to continue staging the update.
|
||||
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
|
||||
}
|
||||
gAUS.checkForBackgroundUpdates();
|
||||
await waitForEvent(event);
|
||||
})();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object with the expected update phase values that can be passed to
|
||||
* checkTelemetryUpdatePhases for update phase telemetry tests.
|
||||
*
|
||||
* @param overrides
|
||||
* Params which can override the default values.
|
||||
* @return An object that can be passed to checkTelemetryUpdatePhases for update
|
||||
* phase telemetry tests.
|
||||
*/
|
||||
function getTelemetryUpdatePhaseValues(overrides) {
|
||||
// Set values that could never be recorded due to values that would prevent
|
||||
// them from occurring. This makes it so callers only have to specify a couple
|
||||
// of values.
|
||||
if (overrides.noPartialPatch) {
|
||||
if (!overrides.noInternalPartial) {
|
||||
overrides.noInternalPartial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overrides.noCompletePatch) {
|
||||
if (!overrides.noInternalComplete) {
|
||||
overrides.noInternalComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overrides.noPartialPatch || overrides.partialBadSize ||
|
||||
overrides.noInternalPartial) {
|
||||
if (!overrides.noStagePartial) {
|
||||
overrides.noStagePartial = true;
|
||||
}
|
||||
if (!overrides.noApplyPartial) {
|
||||
overrides.noApplyPartial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overrides.noCompletePatch || overrides.completeBadSize ||
|
||||
overrides.noInternalComplete) {
|
||||
if (!overrides.noStageComplete) {
|
||||
overrides.noStageComplete = true;
|
||||
}
|
||||
if (!overrides.noApplyComplete) {
|
||||
overrides.noApplyComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
|
||||
if (!overrides.noStagePartial) {
|
||||
overrides.noStagePartial = true;
|
||||
}
|
||||
if (!overrides.noStageComplete) {
|
||||
overrides.noStageComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
let marSize = parseInt(SIZE_SIMPLE_MAR);
|
||||
let partialSize =
|
||||
overrides.partialBadSize ? parseInt(SIZE_SIMPLE_MAR + "1") : marSize;
|
||||
let completeSize =
|
||||
overrides.completeBadSize ? parseInt(SIZE_SIMPLE_MAR + "1") : marSize;
|
||||
|
||||
let partialDownloadBytes = overrides.partialBadSize ? 1 : marSize;
|
||||
let completeDownloadBytes = overrides.completeBadSize ? 1 : marSize;
|
||||
|
||||
let obj = {};
|
||||
obj.basePrefix =
|
||||
overrides.forSession ? "update.session." : "update.startup.";
|
||||
obj.from_app_version = Services.appinfo.version;
|
||||
|
||||
obj.mars = {};
|
||||
obj.mars.mar_partial_size_bytes =
|
||||
overrides.noPartialPatch ? null : partialSize;
|
||||
obj.mars.mar_complete_size_bytes =
|
||||
overrides.noCompletePatch ? null : completeSize;
|
||||
|
||||
obj.intervals = {};
|
||||
obj.intervals.check = 1;
|
||||
obj.intervals.download_bits_partial = null;
|
||||
obj.intervals.download_bits_complete = null;
|
||||
obj.intervals.download_internal_partial =
|
||||
overrides.noInternalPartial ? null : 1;
|
||||
obj.intervals.download_internal_complete =
|
||||
overrides.noInternalComplete ? null : 1;
|
||||
obj.intervals.stage_partial = overrides.noStagePartial ? null : 1;
|
||||
obj.intervals.stage_complete = overrides.noStageComplete ? null : 1;
|
||||
obj.intervals.apply_partial = overrides.noApplyPartial ? null : 1;
|
||||
obj.intervals.apply_complete = overrides.noApplyComplete ? null : 1;
|
||||
|
||||
obj.downloads = {};
|
||||
obj.downloads.bits_partial_ = {};
|
||||
obj.downloads.bits_partial_.bytes = null;
|
||||
obj.downloads.bits_partial_.seconds = null;
|
||||
obj.downloads.bits_complete_ = {};
|
||||
obj.downloads.bits_complete_.bytes = null;
|
||||
obj.downloads.bits_complete_.seconds = null;
|
||||
obj.downloads.internal_partial_ = {};
|
||||
obj.downloads.internal_partial_.bytes =
|
||||
overrides.noInternalPartial ? null : partialDownloadBytes;
|
||||
obj.downloads.internal_partial_.seconds =
|
||||
overrides.noInternalPartial ? null : 1;
|
||||
obj.downloads.internal_complete_ = {};
|
||||
obj.downloads.internal_complete_.bytes =
|
||||
overrides.noInternalComplete ? null : completeDownloadBytes;
|
||||
obj.downloads.internal_complete_.seconds =
|
||||
overrides.noInternalComplete ? null : 1;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the telemetry values for app update phases under either update.startup
|
||||
* or update.session based on the object passed to this function.
|
||||
*
|
||||
* @param expected
|
||||
* An object containing the expected results to compare against the
|
||||
* actual results.
|
||||
*/
|
||||
function checkTelemetryUpdatePhases(expected) {
|
||||
let scalars = TelemetryTestUtils.getProcessScalars("parent");
|
||||
let basePrefix = expected.basePrefix;
|
||||
let namePrefix = basePrefix;
|
||||
{
|
||||
let name = namePrefix + "from_app_version";
|
||||
if (expected.from_app_version) {
|
||||
Assert.ok(!!scalars[name],
|
||||
"The " + name + " value should exist.");
|
||||
Assert.equal(scalars[name],
|
||||
expected.from_app_version,
|
||||
"The " + name + " value should equal the expected value.");
|
||||
} else {
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
for (let [nameSuffix, value] of Object.entries(expected.mars)) {
|
||||
let name = namePrefix + nameSuffix;
|
||||
if (value) {
|
||||
Assert.ok(!!scalars[name],
|
||||
"The " + name + " value should exist.");
|
||||
Assert.equal(scalars[name], value,
|
||||
"The " + name + " value should equal the expected value.");
|
||||
} else {
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
namePrefix = basePrefix + "intervals.";
|
||||
for (let [suffix, value] of Object.entries(expected.intervals)) {
|
||||
let name = namePrefix + suffix;
|
||||
if (value) {
|
||||
Assert.ok(!!scalars[name],
|
||||
"The " + name + " value should exist.");
|
||||
Assert.greaterOrEqual(scalars[name], value,
|
||||
"The " + name + " value should be equal to or " +
|
||||
"greater than " + value + ".");
|
||||
} else {
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
namePrefix = basePrefix + "downloads.";
|
||||
for (let [nameMid, values] of Object.entries(expected.downloads)) {
|
||||
let name = namePrefix + nameMid + "bytes";
|
||||
if (values.bytes) {
|
||||
Assert.ok(!!scalars[name],
|
||||
"The " + name + " value should exist.");
|
||||
Assert.greaterOrEqual(scalars[name], values.bytes,
|
||||
"The " + name + " value should be equal to or " +
|
||||
"greater than " + values.bytes + ".");
|
||||
} else {
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
|
||||
name = namePrefix + nameMid + "seconds";
|
||||
if (values.seconds) {
|
||||
Assert.ok(!!scalars[name],
|
||||
"The " + name + " value should exist.");
|
||||
Assert.greaterOrEqual(scalars[name], values.seconds,
|
||||
"The " + name + " value should be equal to or " +
|
||||
"greater than " + values.seconds + ".");
|
||||
} else {
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether telemetry for update.startup or update.session is set by
|
||||
* checking if there is a value for the from_app_version scalar.
|
||||
*
|
||||
* @param isStartup
|
||||
* When true update.startup.from_app_version will be checked and when
|
||||
* false update.session.from_app_version will be checked.
|
||||
*/
|
||||
function checkTelemetryUpdatePhaseEmpty(isStartup) {
|
||||
let scalars = TelemetryTestUtils.getProcessScalars("parent");
|
||||
let name =
|
||||
"update." + (isStartup ? "startup" : "session") + ".from_app_version";
|
||||
Assert.ok(!scalars[name],
|
||||
"The " + name + " value should not exist.");
|
||||
}
|
||||
|
|
|
@ -10,36 +10,38 @@
|
|||
|
||||
const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const {TelemetryTestUtils} =
|
||||
ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "ctypes",
|
||||
"resource://gre/modules/ctypes.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "UpdateUtils",
|
||||
"resource://gre/modules/UpdateUtils.jsm");
|
||||
|
||||
const PREF_APP_UPDATE_AUTO = "app.update.auto";
|
||||
const PREF_APP_UPDATE_BACKGROUNDERRORS = "app.update.backgroundErrors";
|
||||
const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors";
|
||||
const PREF_APP_UPDATE_BITS_ENABLED = "app.update.BITS.enabled";
|
||||
const PREF_APP_UPDATE_CANCELATIONS = "app.update.cancelations";
|
||||
const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
|
||||
const PREF_APP_UPDATE_DOORHANGER = "app.update.doorhanger";
|
||||
const PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS = "app.update.download.attempts";
|
||||
const PREF_APP_UPDATE_DOWNLOADPROMPT_MAXATTEMPTS = "app.update.download.maxAttempts";
|
||||
const PREF_APP_UPDATE_DISABLEDFORTESTING = "app.update.disabledForTesting";
|
||||
const PREF_APP_UPDATE_IDLETIME = "app.update.idletime";
|
||||
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
|
||||
const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
|
||||
const PREF_APP_UPDATE_LOG = "app.update.log";
|
||||
const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported";
|
||||
const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime";
|
||||
const PREF_APP_UPDATE_RETRYTIMEOUT = "app.update.socket.retryTimeout";
|
||||
const PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled";
|
||||
const PREF_APP_UPDATE_SILENT = "app.update.silent";
|
||||
const PREF_APP_UPDATE_SOCKET_MAXERRORS = "app.update.socket.maxErrors";
|
||||
const PREF_APP_UPDATE_STAGING_ENABLED = "app.update.staging.enabled";
|
||||
const PREF_APP_UPDATE_URL = "app.update.url";
|
||||
const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details";
|
||||
const PREF_APP_UPDATE_URL_MANUAL = "app.update.url.manual";
|
||||
const PREF_APP_UPDATE_AUTO = "app.update.auto";
|
||||
const PREF_APP_UPDATE_BACKGROUNDERRORS = "app.update.backgroundErrors";
|
||||
const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors";
|
||||
const PREF_APP_UPDATE_BITS_ENABLED = "app.update.BITS.enabled";
|
||||
const PREF_APP_UPDATE_CANCELATIONS = "app.update.cancelations";
|
||||
const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
|
||||
const PREF_APP_UPDATE_DOORHANGER = "app.update.doorhanger";
|
||||
const PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS = "app.update.download.maxAttempts";
|
||||
const PREF_APP_UPDATE_DOWNLOAD_ATTEMPTS = "app.update.download.attempts";
|
||||
const PREF_APP_UPDATE_DISABLEDFORTESTING = "app.update.disabledForTesting";
|
||||
const PREF_APP_UPDATE_IDLETIME = "app.update.idletime";
|
||||
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
|
||||
const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
|
||||
const PREF_APP_UPDATE_LOG = "app.update.log";
|
||||
const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported";
|
||||
const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime";
|
||||
const PREF_APP_UPDATE_RETRYTIMEOUT = "app.update.socket.retryTimeout";
|
||||
const PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled";
|
||||
const PREF_APP_UPDATE_SILENT = "app.update.silent";
|
||||
const PREF_APP_UPDATE_SOCKET_MAXERRORS = "app.update.socket.maxErrors";
|
||||
const PREF_APP_UPDATE_STAGING_ENABLED = "app.update.staging.enabled";
|
||||
const PREF_APP_UPDATE_URL = "app.update.url";
|
||||
const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details";
|
||||
const PREF_APP_UPDATE_URL_MANUAL = "app.update.url.manual";
|
||||
|
||||
const PREFBRANCH_APP_PARTNER = "app.partner.";
|
||||
const PREF_DISTRIBUTION_ID = "distribution.id";
|
||||
|
|
Загрузка…
Ссылка в новой задаче