зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound
This commit is contained in:
Коммит
e7bafde7bc
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "7bf976de32cf817ed4529ac875755ac6f6895b89",
|
||||
"revision": "cbd0b3d032bd97c35448bd906fde77e2cfb0967d",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="870a5c518742665d36b17e7e88c2ab07d440b94c"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -32,10 +32,6 @@ function spawnTest () {
|
|||
ise(type, "square", "AudioNode:setParam correctly sets a `string` non-AudioParam");
|
||||
is(resSuccess, undefined, "AudioNode:setParam returns undefined for correctly set AudioParam");
|
||||
|
||||
resSuccess = yield oscNode.setParam("type", "\"triangle\"");
|
||||
type = yield oscNode.getParam("type");
|
||||
ise(type, "triangle", "AudioNode:setParam correctly removes quotes in `string` non-AudioParam");
|
||||
|
||||
try {
|
||||
yield oscNode.setParam("frequency", "hello");
|
||||
ok(false, "setParam with invalid types should throw");
|
||||
|
|
|
@ -19,24 +19,32 @@ function spawnTest() {
|
|||
get3Spread(panel.panelWin, EVENTS.UI_ADD_NODE_LIST)
|
||||
]);
|
||||
|
||||
let setAndCheck = setAndCheckVariable(panel.panelWin, gVars);
|
||||
|
||||
checkVariableView(gVars, 1, {
|
||||
"type": "\"sine\"",
|
||||
"frequency": 440,
|
||||
"detune": 0
|
||||
});
|
||||
}, "default loaded string");
|
||||
|
||||
checkVariableView(gVars, 2, {
|
||||
"gain": 0
|
||||
});
|
||||
}, "default loaded number");
|
||||
|
||||
yield modifyVariableView(panel.panelWin, gVars, 1, "type", "square");
|
||||
yield setAndCheck(1, "type", "\"square\"", "\"square\"", "sets string as string");
|
||||
|
||||
checkVariableView(gVars, 1, {
|
||||
"type": "\"square\""
|
||||
});
|
||||
yield setAndCheck(2, "gain", 0.005, 0.005, "sets number as number");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function setAndCheckVariable (panelWin, gVars) {
|
||||
return Task.async(function (varNum, prop, value, expected, desc) {
|
||||
yield modifyVariableView(panelWin, gVars, varNum, prop, value);
|
||||
var props = {};
|
||||
props[prop] = expected;
|
||||
checkVariableView(gVars, varNum, props, desc);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ function waitForGraphRendered (front, nodeCount, edgeCount) {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkVariableView (view, index, hash) {
|
||||
function checkVariableView (view, index, hash, description = "") {
|
||||
let scope = view.getScopeAtIndex(index);
|
||||
let variables = Object.keys(hash);
|
||||
variables.forEach(variable => {
|
||||
|
@ -219,7 +219,7 @@ function checkVariableView (view, index, hash) {
|
|||
is(aVar.target.querySelector(".name").getAttribute("value"), variable,
|
||||
"Correct property name for " + variable);
|
||||
is(aVar.target.querySelector(".value").getAttribute("value"), hash[variable],
|
||||
"Correct property value of " + hash[variable] + " for " + variable);
|
||||
"Correct property value of " + hash[variable] + " for " + variable + " " + description);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -269,12 +269,21 @@ let WebAudioParamView = {
|
|||
let ownerScope = variable.ownerView;
|
||||
let node = getViewNodeById(ownerScope.actorID);
|
||||
let propName = variable.name;
|
||||
let errorMessage = yield node.actor.setParam(propName, value);
|
||||
let error;
|
||||
|
||||
// Cast value to proper type
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
error = yield node.actor.setParam(propName, value);
|
||||
}
|
||||
catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
// TODO figure out how to handle and display set param errors
|
||||
// and enable `test/brorwser_wa_params_view_edit_error.js`
|
||||
// Bug 994258
|
||||
if (!errorMessage) {
|
||||
if (!error) {
|
||||
ownerScope.get(propName).setGrip(value);
|
||||
window.emit(EVENTS.UI_SET_PARAM, node.id, propName, value);
|
||||
} else {
|
||||
|
|
|
@ -1165,7 +1165,11 @@ Experiments.Experiments.prototype = {
|
|||
}
|
||||
|
||||
if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
|
||||
gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id);
|
||||
try {
|
||||
gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id);
|
||||
} catch (e) {
|
||||
// It's ok if crash reporting is disabled.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@ public final class EventDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
@Deprecated
|
||||
public static void sendResponse(JSONObject message, Object response) {
|
||||
sendResponseHelper(STATUS_SUCCESS, message, response);
|
||||
|
|
|
@ -92,6 +92,7 @@ public class StringHelper {
|
|||
public static final String ROBOCOP_SEARCH_TITLE = "Robocop Search Engine";
|
||||
public static final String ROBOCOP_TEXT_PAGE_TITLE = "Robocop Text Page";
|
||||
public static final String ROBOCOP_INPUT_TITLE = "Robocop Input";
|
||||
public static final String ROBOCOP_SELECTION_HANDLER_TITLE = "Automated Text Selection tests for Mobile";
|
||||
|
||||
// Settings menu strings
|
||||
// Section labels - ordered as found in the settings menu
|
||||
|
|
|
@ -134,9 +134,14 @@ skip-if = android_version == "8"
|
|||
[testAboutHomeVisibility]
|
||||
# disabled on Android 2.3; bug 979597
|
||||
skip-if = android_version == "10"
|
||||
[testEventDispatcher]
|
||||
[testInputConnection]
|
||||
# disabled on Android 2.3; bug 983440
|
||||
skip-if = android_version == "10"
|
||||
[testJavascriptBridge]
|
||||
[testNativeCrypto]
|
||||
[testSessionHistory]
|
||||
|
||||
# testSelectionHandler disabled on Android 2.3 by trailing skip-if, due to bug 980074
|
||||
[testSelectionHandler]
|
||||
skip-if = android_version == "10"
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Automated Text Selection tests for Mobile</title>
|
||||
<meta name="viewport" content="initial-scale=1.0"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
const DIV_POINT_TEXT = "Under";
|
||||
const INPUT_TEXT = "Text for select all in an <input>";
|
||||
const TEXTAREA_TEXT = "Text for select all in a <textarea>";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* Start of all text selection tests, check initialization state.
|
||||
*
|
||||
*/
|
||||
function startTests() {
|
||||
testSelectAllDivs().
|
||||
then(testSelectDivAtPoint).
|
||||
then(testSelectInput).
|
||||
then(testSelectTextarea).
|
||||
then(testCloseSelection).
|
||||
then(finishTests, function(err) {
|
||||
ok(false, "Error in selection test " + err);
|
||||
finishTests();
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* "Select all" text selection tests, for <div> (non-editable) fields.
|
||||
*
|
||||
*/
|
||||
function testSelectAllDivs() {
|
||||
var sh = getSelectionHandler();
|
||||
var selDiv = document.getElementById("selDiv");
|
||||
var nonSelDiv = document.getElementById("nonSelDiv");
|
||||
|
||||
// Check the initial state of the selection handler, and selectable/non-selectable <div>s.
|
||||
return Promise.all([
|
||||
ok(!sh.isSelectionActive(), "Selection should not be active at start of testSelectAllDivs"),
|
||||
ok(sh.canSelect(selDiv), "Can select selectable <div>"),
|
||||
ok(!sh.canSelect(nonSelDiv), "Can't select non-selectable <div>"),
|
||||
|
||||
]).then(function() {
|
||||
// Select all on a non-editable text node selects all the text in the page.
|
||||
sh.startSelection(selDiv);
|
||||
var selection = sh._getSelection();
|
||||
|
||||
return Promise.all([
|
||||
ok(sh.isSelectionActive(), "Selection should be active now"),
|
||||
is(selection.anchorNode, document.documentElement, "Anchor Node should be start of document"),
|
||||
is(selection.anchorOffset, 0, "Anchor offset should be 0"),
|
||||
is(selection.focusNode, document.body.lastChild, "Focus node should be lastChild of document"),
|
||||
is(selection.focusOffset, document.body.lastChild.textContent.length, "Focus offset should be it's length"),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* "Select word-at-point" text selection test, for <div> (non-editable) field.
|
||||
* "collapseToStart" test closes selection (Bug 864589).
|
||||
*
|
||||
*/
|
||||
function testSelectDivAtPoint() {
|
||||
var sh = getSelectionHandler();
|
||||
var selDiv = document.getElementById("selDiv");
|
||||
|
||||
// Select word at point in <div>
|
||||
var rect = selDiv.getBoundingClientRect();
|
||||
sh.startSelection(selDiv, {
|
||||
mode: sh.SELECT_AT_POINT,
|
||||
x: rect.left + 1,
|
||||
y: rect.top + 1
|
||||
});
|
||||
var selection = sh._getSelection();
|
||||
|
||||
// Check the state of the selection handler after selecting at a point.
|
||||
return Promise.all([
|
||||
ok(sh.isSelectionActive(), "Selection should be active at start of testSelectDivAtPoint"),
|
||||
is(selection.toString(), DIV_POINT_TEXT, "The first word in the <div> was selected"),
|
||||
|
||||
]).then(function() {
|
||||
// Check the state of the selection handler after collapsing a selection.
|
||||
selection.collapseToStart();
|
||||
|
||||
return Promise.all([
|
||||
ok(selection.getRangeAt(0).collapsed, "Selection should be collapsed"),
|
||||
ok(!sh.isSelectionActive(), "Selection should not be active"),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* "Select all" text selection test, for <input> (editable) field.
|
||||
*
|
||||
*/
|
||||
function testSelectInput() {
|
||||
var sh = getSelectionHandler();
|
||||
var inputNode = document.getElementById("inputNode");
|
||||
inputNode.value = INPUT_TEXT;
|
||||
|
||||
// Test that calling startSelection with an input selects all the text in the input.
|
||||
return Promise.all([
|
||||
ok(!sh.isSelectionActive(), "Selection should not be active at start of testSelectInput"),
|
||||
ok(sh.canSelect(inputNode), "Can select selectable <input>"),
|
||||
|
||||
]).then(function() {
|
||||
// Check the state of the selection handler after calling startSelection on it.
|
||||
sh.startSelection(inputNode);
|
||||
var selection = sh._getSelection();
|
||||
|
||||
return Promise.all([
|
||||
ok(sh.isSelectionActive(), "Selection should be active"),
|
||||
ok((sh._targetElement instanceof Ci.nsIDOMNSEditableElement), "Selected element is editable"),
|
||||
is(selection.toString(), INPUT_TEXT, "All text in the <input> was selected"),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* "Select all" text selection test, for <textarea> (editable) field.
|
||||
*
|
||||
*/
|
||||
|
||||
function testSelectTextarea() {
|
||||
var sh = getSelectionHandler();
|
||||
var textareaNode = document.getElementById("textareaNode");
|
||||
textareaNode.value = TEXTAREA_TEXT;
|
||||
|
||||
// Change (still-active) selection from previous <input> field to <textarea>
|
||||
sh.startSelection(textareaNode);
|
||||
var selection = sh._getSelection();
|
||||
|
||||
return Promise.all([
|
||||
ok(sh.isSelectionActive(), "Selection should be active at start of testSelectTextarea"),
|
||||
ok((sh._targetElement instanceof Ci.nsIDOMHTMLTextAreaElement), "Selected element is editable, and a <textarea>"),
|
||||
is(selection.toString(), TEXTAREA_TEXT, "All text in the <textarea> was selected"),
|
||||
|
||||
]).then(function() {
|
||||
// Collpase the selection to close it again.
|
||||
selection.collapseToStart();
|
||||
|
||||
return Promise.all([
|
||||
ok(!sh.isSelectionActive(), "Selection should not be active"),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* Various text selection tests to end active selections, including:
|
||||
* 1.) Clicking outside the selection.
|
||||
* 2.) SelectionEnd or Tab:Selected messages from java.
|
||||
*
|
||||
*/
|
||||
function testCloseSelection() {
|
||||
var sh = getSelectionHandler();
|
||||
var inputNode = document.getElementById("inputNode");
|
||||
inputNode.value = INPUT_TEXT;
|
||||
|
||||
// Check the initial state of the selection handler.
|
||||
return Promise.all([
|
||||
ok(!sh.isSelectionActive(), "Selection should not be active at start of testCloseSelection"),
|
||||
|
||||
]).then(function() {
|
||||
// Start by selecting all in an <input>.
|
||||
sh.startSelection(inputNode);
|
||||
return is(sh._activeType, sh.TYPE_SELECTION, "Selection should be active in <input> before Gesture:SingleTap");
|
||||
|
||||
}).then(function() {
|
||||
// Tap outside <input> to close active selection.
|
||||
sh.observe(null, "Gesture:SingleTap", JSON.stringify({
|
||||
x: 1,
|
||||
y: 1
|
||||
}));
|
||||
return ok(!sh.isSelectionActive(), "Gesture:SingleTap outside <input> should close active selection");
|
||||
|
||||
// Various other ways to close an active selection.
|
||||
}).then(function() {
|
||||
sh.startSelection(inputNode);
|
||||
sh.observe(null, "TextSelection:End", {});
|
||||
return ok(!sh.isSelectionActive(), "TextSelection:End should close active selection");
|
||||
|
||||
}).then(function() {
|
||||
sh.startSelection(inputNode);
|
||||
sh.observe(null, "Tab:Selected", {});
|
||||
return ok(!sh.isSelectionActive(), "Tab:Selected should close active selection");
|
||||
|
||||
}).then(function() {
|
||||
sh.startSelection(inputNode);
|
||||
sh.handleEvent({ type: "pagehide" });
|
||||
return ok(!sh.isSelectionActive(), "pagehide should close active selection");
|
||||
|
||||
}).then(function() {
|
||||
sh.startSelection(inputNode);
|
||||
sh.handleEvent({ type: "blur" });
|
||||
return ok(!sh.isSelectionActive(), "blur should close active selection");
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* After finish of all selection tests, wrap up and go home.
|
||||
*
|
||||
*/
|
||||
function finishTests() {
|
||||
sendMessageToJava({
|
||||
type: "Robocop:testSelectionHandler",
|
||||
result: true,
|
||||
msg: "Done!",
|
||||
done: true
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================== Utility functions ======================
|
||||
*
|
||||
* Common functions available to all tests.
|
||||
*
|
||||
*/
|
||||
function getSelectionHandler() {
|
||||
return (!this._selectionHandler) ?
|
||||
this._selectionHandler = Services.wm.getMostRecentWindow("navigator:browser").SelectionHandler :
|
||||
this._selectionHandler;
|
||||
}
|
||||
|
||||
function ok(one, msg) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
sendMessageToJava({
|
||||
type: "Robocop:testSelectionHandler",
|
||||
result: one,
|
||||
msg: msg
|
||||
},
|
||||
function (res, err) {
|
||||
(err) ? reject(err) : resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function is(one, two, msg) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
sendMessageToJava({
|
||||
type: "Robocop:testSelectionHandler",
|
||||
result: one === two,
|
||||
msg: msg + " : " + one + " === " + two
|
||||
},
|
||||
function (res, err) {
|
||||
(err) ? reject(err) : resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* =================================================================================
|
||||
*
|
||||
* Page definition for all tests.
|
||||
*
|
||||
*/
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="startTests();">
|
||||
|
||||
<div id="selDiv">Under sufficiently extreme conditions, quarks may become
|
||||
deconfined and exist as free particles. In the course of asymptotic freedom,
|
||||
the strong interaction becomes weaker at higher temperatures. Eventually,
|
||||
color confinement would be lost and an extremely hot plasma of freely moving
|
||||
quarks and gluons would be formed. This theoretical phase of matter is called
|
||||
quark-gluon plasma.[81] The exact conditions needed to give rise to this state
|
||||
are unknown and have been the subject of a great deal of speculation and
|
||||
experimentation. A recent estimate puts the needed temperature at
|
||||
(1.90±0.02)×1012 Kelvin. While a state of entirely free quarks and gluons has
|
||||
never been achieved (despite numerous attempts by CERN in the 1980s and 1990s),
|
||||
recent experiments at the Relativistic Heavy Ion Collider have yielded evidence
|
||||
for liquid-like quark matter exhibiting "nearly perfect" fluid motion.</div><br>
|
||||
|
||||
<div id="nonSelDiv" style="-moz-user-select: none;">Lorem ipsum dolor sit amet,
|
||||
consectetur adipiscing elit. Proin in blandit magna, non porttitor augue.
|
||||
Nam in neque sagittis, varius augue at, ornare velit. Vestibulum eget nisl
|
||||
congue odio molestie scelerisque. Pellentesque ut augue orci. In hac habitasse
|
||||
platea dictumst. Sed placerat tellus quis lacus condimentum, quis luctus elit
|
||||
pellentesque. Mauris cursus neque diam, sit amet gravida quam porta ac.
|
||||
Aliquam aliquam feugiat vestibulum. Proin commodo nulla ligula, in bibendum
|
||||
massa euismod a. Ut ac lobortis dui. Ut id augue id arcu ornare suscipit eu
|
||||
ornare lorem. Pellentesque nec dictum ante. Nam quis ligula ultricies, auctor
|
||||
nunc vel, fringilla turpis. Nulla lacinia, leo ut egestas hendrerit, risus
|
||||
ligula interdum enim, vel varius libero sem ut ligula.</div><br>
|
||||
|
||||
<input id="inputNode" type="text"><br>
|
||||
|
||||
<textarea id="textareaNode"></textarea><br>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,159 @@
|
|||
package org.mozilla.gecko.tests;
|
||||
|
||||
import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
|
||||
|
||||
import org.mozilla.gecko.tests.helpers.*;
|
||||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Tests the proper operation of EventDispatcher,
|
||||
* including associated NativeJSObject objects.
|
||||
*/
|
||||
public class testEventDispatcher extends UITest
|
||||
implements GeckoEventListener, NativeEventListener {
|
||||
|
||||
private static final String TEST_JS = "testEventDispatcher.js";
|
||||
private static final String GECKO_EVENT = "Robocop:TestGeckoEvent";
|
||||
private static final String GECKO_RESPONSE_EVENT = "Robocop:TestGeckoResponse";
|
||||
private static final String NATIVE_EVENT = "Robocop:TestNativeEvent";
|
||||
private static final String NATIVE_RESPONSE_EVENT = "Robocop:TestNativeResponse";
|
||||
|
||||
private JavascriptBridge js;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
js = new JavascriptBridge(this);
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(
|
||||
(GeckoEventListener) this, GECKO_EVENT, GECKO_RESPONSE_EVENT);
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(
|
||||
(NativeEventListener) this, NATIVE_EVENT, NATIVE_RESPONSE_EVENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(
|
||||
(GeckoEventListener) this, GECKO_EVENT, GECKO_RESPONSE_EVENT);
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(
|
||||
(NativeEventListener) this, NATIVE_EVENT, NATIVE_RESPONSE_EVENT);
|
||||
|
||||
js.disconnect();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testEventDispatcher() {
|
||||
GeckoHelper.blockForReady();
|
||||
NavigationHelper.enterAndLoadUrl(StringHelper.ROBOCOP_JS_HARNESS_URL +
|
||||
"?path=" + TEST_JS);
|
||||
|
||||
js.syncCall("send_test_message", GECKO_EVENT);
|
||||
js.syncCall("send_message_for_response", GECKO_RESPONSE_EVENT, "success");
|
||||
js.syncCall("send_message_for_response", GECKO_RESPONSE_EVENT, "error");
|
||||
js.syncCall("send_test_message", NATIVE_EVENT);
|
||||
js.syncCall("send_message_for_response", NATIVE_RESPONSE_EVENT, "success");
|
||||
js.syncCall("send_message_for_response", NATIVE_RESPONSE_EVENT, "error");
|
||||
js.syncCall("send_message_for_response", NATIVE_RESPONSE_EVENT, "cancel");
|
||||
js.syncCall("finish_test");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
|
||||
try {
|
||||
if (GECKO_EVENT.equals(event)) {
|
||||
checkJSONObject(message);
|
||||
checkJSONObject(message.getJSONObject("object"));
|
||||
|
||||
} else if (GECKO_RESPONSE_EVENT.equals(event)) {
|
||||
final String response = message.getString("response");
|
||||
if ("success".equals(response)) {
|
||||
EventDispatcher.getInstance().sendResponse(message, response);
|
||||
} else if ("error".equals(response)) {
|
||||
EventDispatcher.getInstance().sendError(message, response);
|
||||
} else {
|
||||
fFail("Response type should be valid: " + response);
|
||||
}
|
||||
|
||||
} else {
|
||||
fFail("Event type should be valid: " + event);
|
||||
}
|
||||
} catch (final JSONException e) {
|
||||
fFail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
final EventCallback callback) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
|
||||
if (NATIVE_EVENT.equals(event)) {
|
||||
checkNativeJSObject(message);
|
||||
checkNativeJSObject(message.getObject("object"));
|
||||
fAssertNotSame("optObject returns existent value",
|
||||
null, message.optObject("object", null));
|
||||
fAssertSame("optObject returns fallback value if nonexistent",
|
||||
null, message.optObject("nonexistent_object", null));
|
||||
|
||||
} else if (NATIVE_RESPONSE_EVENT.equals(event)) {
|
||||
final String response = message.getString("response");
|
||||
if ("success".equals(response)) {
|
||||
callback.sendSuccess(response);
|
||||
} else if ("error".equals(response)) {
|
||||
callback.sendError(response);
|
||||
} else if ("cancel".equals(response)) {
|
||||
callback.sendCancel();
|
||||
} else {
|
||||
fFail("Response type should be valid: " + response);
|
||||
}
|
||||
|
||||
} else {
|
||||
fFail("Event type should be valid: " + event);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkJSONObject(final JSONObject object) throws JSONException {
|
||||
fAssertEquals("JSON boolean has correct value", true, object.getBoolean("boolean"));
|
||||
fAssertEquals("JSON int has correct value", 1, object.getInt("int"));
|
||||
fAssertEquals("JSON double has correct value", 0.5, object.getDouble("double"));
|
||||
fAssertEquals("JSON string has correct value", "foo", object.getString("string"));
|
||||
}
|
||||
|
||||
private void checkNativeJSObject(final NativeJSObject object) {
|
||||
fAssertEquals("Native boolean has correct value",
|
||||
true, object.getBoolean("boolean"));
|
||||
fAssertEquals("optBoolean returns existent value",
|
||||
true, object.optBoolean("boolean", false));
|
||||
fAssertEquals("optBoolean returns fallback value if nonexistent",
|
||||
false, object.optBoolean("nonexistent_boolean", false));
|
||||
fAssertEquals("Native int has correct value",
|
||||
1, object.getInt("int"));
|
||||
fAssertEquals("optInt returns existent value",
|
||||
1, object.optInt("int", 0));
|
||||
fAssertEquals("optInt returns fallback value if nonexistent",
|
||||
0, object.optInt("nonexistent_int", 0));
|
||||
fAssertEquals("Native double has correct value",
|
||||
0.5, object.getDouble("double"));
|
||||
fAssertEquals("optDouble returns existent value",
|
||||
0.5, object.optDouble("double", -0.5));
|
||||
fAssertEquals("optDouble returns fallback value if nonexistent",
|
||||
-0.5, object.optDouble("nonexistent_double", -0.5));
|
||||
fAssertEquals("Native string has correct value",
|
||||
"foo", object.getString("string"));
|
||||
fAssertEquals("optDouble returns existent value",
|
||||
"foo", object.optString("string", "bar"));
|
||||
fAssertEquals("optDouble returns fallback value if nonexistent",
|
||||
"bar", object.optString("nonexistent_string", "bar"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
Components.utils.import("resource://gre/modules/Messaging.jsm");
|
||||
|
||||
let java = new JavaBridge(this);
|
||||
|
||||
do_register_cleanup(() => {
|
||||
java.disconnect();
|
||||
});
|
||||
do_test_pending();
|
||||
|
||||
function send_test_message(type) {
|
||||
sendMessageToJava({
|
||||
type: type,
|
||||
boolean: true,
|
||||
int: 1,
|
||||
double: 0.5,
|
||||
string: "foo",
|
||||
object: {
|
||||
boolean: true,
|
||||
int: 1,
|
||||
double: 0.5,
|
||||
string: "foo",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function send_message_for_response(type, response) {
|
||||
sendMessageToJava({
|
||||
type: type,
|
||||
response: response,
|
||||
}, (success, error) => {
|
||||
if (response === "success") {
|
||||
do_check_eq(success, response);
|
||||
do_check_eq(error, null);
|
||||
} else if (response === "error") {
|
||||
do_check_eq(success, null);
|
||||
do_check_eq(error, response);
|
||||
} else {
|
||||
do_throw("Unexpected response: " + response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function finish_test() {
|
||||
do_test_finished();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.Actions;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.tests.helpers.GeckoHelper;
|
||||
import org.mozilla.gecko.tests.helpers.NavigationHelper;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
public class testSelectionHandler extends UITest {
|
||||
|
||||
public void testSelectionHandler() {
|
||||
GeckoHelper.blockForReady();
|
||||
|
||||
Actions.EventExpecter robocopTestExpecter = getActions().expectGeckoEvent("Robocop:testSelectionHandler");
|
||||
NavigationHelper.enterAndLoadUrl("chrome://roboextender/content/testSelectionHandler.html");
|
||||
mToolbar.assertTitle(StringHelper.ROBOCOP_SELECTION_HANDLER_TITLE);
|
||||
|
||||
while (!test(robocopTestExpecter)) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
robocopTestExpecter.unregisterListener();
|
||||
}
|
||||
|
||||
private boolean test(Actions.EventExpecter expecter) {
|
||||
final JSONObject eventData;
|
||||
try {
|
||||
eventData = new JSONObject(expecter.blockForEventData());
|
||||
} catch(Exception ex) {
|
||||
// Log and ignore
|
||||
getAsserter().ok(false, "JS Test", "Error decoding data " + ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eventData.has("result")) {
|
||||
getAsserter().ok(eventData.optBoolean("result"), "JS Test", eventData.optString("msg"));
|
||||
}
|
||||
|
||||
EventDispatcher.sendResponse(eventData, new JSONObject());
|
||||
return eventData.optBoolean("done", false);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.mozilla.gecko.util;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
/**
|
||||
* Callback interface for Gecko requests.
|
||||
*
|
||||
|
@ -7,6 +9,7 @@ package org.mozilla.gecko.util;
|
|||
* must be called to prevent observer leaks. If more than one send* method is called, or if a
|
||||
* single send method is called multiple times, an {@link IllegalStateException} will be thrown.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public interface EventCallback {
|
||||
/**
|
||||
* Sends a success response with the given data.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Handler;
|
||||
|
@ -118,6 +120,7 @@ public final class ThreadUtils {
|
|||
assertOnThread(getUiThread(), AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void assertOnGeckoThread() {
|
||||
assertOnThread(sGeckoThread, AssertBehavior.THROW);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
|||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
window.addEventListener("load", function onload(event) {
|
||||
try {
|
||||
window.removeEventListener("load", onload, false);
|
||||
Troubleshoot.snapshot(function (snapshot) {
|
||||
for (let prop in snapshotFormatters)
|
||||
|
@ -20,6 +21,9 @@ window.addEventListener("load", function onload(event) {
|
|||
});
|
||||
populateResetBox();
|
||||
setupEventListeners();
|
||||
} catch (e) {
|
||||
Cu.reportError("stack of load error for about:support: " + e + ": " + e.stack);
|
||||
}
|
||||
}, false);
|
||||
|
||||
// Each property in this object corresponds to a property in Troubleshoot.jsm's
|
||||
|
|
|
@ -1352,7 +1352,7 @@ EnsureDirectoryExists(nsIFile* dir)
|
|||
nsresult rv = dir->Create(nsIFile::DIRECTORY_TYPE, 0700);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2081,45 +2081,20 @@ nsresult SetSubmitReports(bool aSubmitReports)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateCrashEventsDir()
|
||||
static void
|
||||
SetCrashEventsDir(nsIFile* aDir)
|
||||
{
|
||||
nsCOMPtr<nsIFile> eventsDir;
|
||||
nsCOMPtr<nsIFile> eventsDir = aDir;
|
||||
|
||||
// We prefer the following locations in order:
|
||||
//
|
||||
// 1. If environment variable is present, use it. We don't expect
|
||||
// the environment variable except for tests and other atypical setups.
|
||||
// 2. Inside the profile directory.
|
||||
// 3. Inside the user application data directory (no profile available).
|
||||
// 4. A temporary directory (setup likely is invalid / application is buggy).
|
||||
const char *env = PR_GetEnv("CRASHES_EVENTS_DIR");
|
||||
if (env) {
|
||||
eventsDir = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
if (!eventsDir) {
|
||||
return;
|
||||
}
|
||||
eventsDir->InitWithNativePath(nsDependentCString(env));
|
||||
if (env && *env) {
|
||||
NS_NewNativeLocalFile(nsDependentCString(env),
|
||||
false, getter_AddRefs(eventsDir));
|
||||
EnsureDirectoryExists(eventsDir);
|
||||
} else {
|
||||
nsresult rv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(eventsDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
eventsDir->Append(NS_LITERAL_STRING("crashes"));
|
||||
EnsureDirectoryExists(eventsDir);
|
||||
eventsDir->Append(NS_LITERAL_STRING("events"));
|
||||
EnsureDirectoryExists(eventsDir);
|
||||
} else {
|
||||
rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(eventsDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
eventsDir->Append(NS_LITERAL_STRING("Crash Reports"));
|
||||
EnsureDirectoryExists(eventsDir);
|
||||
eventsDir->Append(NS_LITERAL_STRING("events"));
|
||||
EnsureDirectoryExists(eventsDir);
|
||||
} else {
|
||||
NS_WARNING("Couldn't get the user appdata directory. Crash events may not be produced.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventsDirectory) {
|
||||
NS_Free(eventsDirectory);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -2133,6 +2108,56 @@ UpdateCrashEventsDir()
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SetProfileDirectory(nsIFile* aDir)
|
||||
{
|
||||
nsCOMPtr<nsIFile> dir;
|
||||
aDir->Clone(getter_AddRefs(dir));
|
||||
|
||||
dir->Append(NS_LITERAL_STRING("crashes"));
|
||||
EnsureDirectoryExists(dir);
|
||||
dir->Append(NS_LITERAL_STRING("events"));
|
||||
EnsureDirectoryExists(dir);
|
||||
SetCrashEventsDir(dir);
|
||||
}
|
||||
|
||||
void
|
||||
SetUserAppDataDirectory(nsIFile* aDir)
|
||||
{
|
||||
nsCOMPtr<nsIFile> dir;
|
||||
aDir->Clone(getter_AddRefs(dir));
|
||||
|
||||
dir->Append(NS_LITERAL_STRING("Crash Reports"));
|
||||
EnsureDirectoryExists(dir);
|
||||
dir->Append(NS_LITERAL_STRING("events"));
|
||||
EnsureDirectoryExists(dir);
|
||||
SetCrashEventsDir(dir);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateCrashEventsDir()
|
||||
{
|
||||
const char *env = PR_GetEnv("CRASHES_EVENTS_DIR");
|
||||
if (env && *env) {
|
||||
SetCrashEventsDir(nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> eventsDir;
|
||||
nsresult rv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(eventsDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetProfileDirectory(eventsDir);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(eventsDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetUserAppDataDirectory(eventsDir);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_WARNING("Couldn't get the user appdata directory. Crash events may not be produced.");
|
||||
}
|
||||
|
||||
bool GetCrashEventsDir(nsAString& aPath)
|
||||
{
|
||||
if (!eventsDirectory) {
|
||||
|
|
|
@ -36,10 +36,19 @@ nsresult UnsetExceptionHandler();
|
|||
|
||||
/**
|
||||
* Tell the crash reporter to recalculate where crash events files should go.
|
||||
* SetCrashEventsDir is used before XPCOM is initialized from the startup
|
||||
* code.
|
||||
*
|
||||
* This should be called during crash reporter initialization and when a
|
||||
* profile is activated or deactivated.
|
||||
* UpdateCrashEventsDir uses the directory service to re-set the
|
||||
* crash event directory based on the current profile.
|
||||
*
|
||||
* 1. If environment variable is present, use it. We don't expect
|
||||
* the environment variable except for tests and other atypical setups.
|
||||
* 2. <profile>/crashes/events
|
||||
* 3. <UAppData>/Crash Reports/events
|
||||
*/
|
||||
void SetUserAppDataDirectory(nsIFile* aDir);
|
||||
void SetProfileDirectory(nsIFile* aDir);
|
||||
void UpdateCrashEventsDir();
|
||||
|
||||
/**
|
||||
|
|
|
@ -155,9 +155,8 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
|
|||
}),
|
||||
|
||||
/**
|
||||
* Changes a param on the audio node. Responds with a `string` that's either
|
||||
* an empty string `""` on success, or a description of the error upon
|
||||
* param set failure.
|
||||
* Changes a param on the audio node. Responds with either `undefined`
|
||||
* on success, or a description of the error upon param set failure.
|
||||
*
|
||||
* @param String param
|
||||
* Name of the AudioParam to change.
|
||||
|
@ -165,10 +164,6 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
|
|||
* Value to change AudioParam to.
|
||||
*/
|
||||
setParam: method(function (param, value) {
|
||||
// Strip quotes because sometimes UIs include that for strings
|
||||
if (typeof value === "string") {
|
||||
value = value.replace(/[\'\"]*/g, "");
|
||||
}
|
||||
try {
|
||||
if (isAudioParam(this.node, param))
|
||||
this.node[param].value = value;
|
||||
|
|
|
@ -783,8 +783,13 @@ MockProvider.prototype = {
|
|||
* Called when the provider should shutdown.
|
||||
*/
|
||||
shutdown: function MP_shutdown() {
|
||||
for (let timer of this.callbackTimers)
|
||||
if (this.callbackTimers.length) {
|
||||
info("MockProvider: pending callbacks at shutdown(): calling immediately");
|
||||
}
|
||||
for (let timer of this.callbackTimers) {
|
||||
timer.callback();
|
||||
timer.cancel();
|
||||
}
|
||||
this.callbackTimers = [];
|
||||
|
||||
this.started = false;
|
||||
|
@ -968,17 +973,20 @@ MockProvider.prototype = {
|
|||
*/
|
||||
_delayCallback: function MP_delayCallback(aCallback, ...aArgs) {
|
||||
if (!this.useAsyncCallbacks) {
|
||||
aCallback.apply(null, params);
|
||||
aCallback.apply(null, aArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
// Need to keep a reference to the timer, so it doesn't get GC'ed
|
||||
var pos = this.callbackTimers.length;
|
||||
this.callbackTimers.push(timer);
|
||||
var self = this;
|
||||
timer.initWithCallback(function() {
|
||||
self.callbackTimers.splice(pos, 1);
|
||||
timer.initWithCallback(() => {
|
||||
let idx = this.callbackTimers.indexOf(timer);
|
||||
if (idx == -1) {
|
||||
info("MockProvider._delayCallback lost track of a timer.");
|
||||
} else {
|
||||
this.callbackTimers.splice(idx, 1);
|
||||
}
|
||||
aCallback.apply(null, aArgs);
|
||||
}, this.apiDelay, timer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
|
|
@ -3021,7 +3021,11 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
|
||||
NS_SUCCEEDED(
|
||||
CrashReporter::SetExceptionHandler(mAppData->xreDirectory))) {
|
||||
CrashReporter::UpdateCrashEventsDir();
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = mDirProvider.GetUserAppDataDirectory(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CrashReporter::SetUserAppDataDirectory(file);
|
||||
}
|
||||
if (mAppData->crashReporterURL)
|
||||
CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
|
||||
|
||||
|
@ -3676,7 +3680,7 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
|
|||
if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
|
||||
MakeOrSetMinidumpPath(mProfD);
|
||||
|
||||
CrashReporter::UpdateCrashEventsDir();
|
||||
CrashReporter::SetProfileDirectory(mProfD);
|
||||
#endif
|
||||
|
||||
nsAutoCString version;
|
||||
|
|
Загрузка…
Ссылка в новой задаче