зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team, a=merge
This commit is contained in:
Коммит
5225afcd1a
|
@ -228,7 +228,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
|
|||
}
|
||||
},
|
||||
|
||||
_getContentProcessTarget: function () {
|
||||
_getContentProcessTarget: function (processId) {
|
||||
// Create a DebuggerServer in order to connect locally to it
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
|
@ -241,49 +241,54 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
|
|||
|
||||
let deferred = defer();
|
||||
client.connect().then(() => {
|
||||
client.mainRoot.listProcesses(response => {
|
||||
// Do nothing if there is only one process, the parent process.
|
||||
let contentProcesses = response.processes.filter(p => (!p.parent));
|
||||
if (contentProcesses.length < 1) {
|
||||
let msg = L10N.getStr("toolbox.noContentProcess.message");
|
||||
Services.prompt.alert(null, "", msg);
|
||||
deferred.reject("No content processes available.");
|
||||
return;
|
||||
}
|
||||
// Otherwise, arbitrary connect to the unique content process.
|
||||
client.getProcess(contentProcesses[0].id)
|
||||
.then(response => {
|
||||
let options = {
|
||||
form: response.form,
|
||||
client: client,
|
||||
chrome: true,
|
||||
isTabActor: false
|
||||
};
|
||||
return TargetFactory.forRemoteTab(options);
|
||||
})
|
||||
.then(target => {
|
||||
// Ensure closing the connection in order to cleanup
|
||||
// the debugger client and also the server created in the
|
||||
// content process
|
||||
target.on("close", () => {
|
||||
client.close();
|
||||
});
|
||||
deferred.resolve(target);
|
||||
client.getProcess(processId)
|
||||
.then(response => {
|
||||
let options = {
|
||||
form: response.form,
|
||||
client: client,
|
||||
chrome: true,
|
||||
isTabActor: false
|
||||
};
|
||||
return TargetFactory.forRemoteTab(options);
|
||||
})
|
||||
.then(target => {
|
||||
// Ensure closing the connection in order to cleanup
|
||||
// the debugger client and also the server created in the
|
||||
// content process
|
||||
target.on("close", () => {
|
||||
client.close();
|
||||
});
|
||||
});
|
||||
deferred.resolve(target);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
// Used by browser-sets.inc, command
|
||||
openContentProcessToolbox: function () {
|
||||
this._getContentProcessTarget()
|
||||
.then(target => {
|
||||
// Display a new toolbox, in a new window, with debugger by default
|
||||
return gDevTools.showToolbox(target, "jsdebugger",
|
||||
Toolbox.HostType.WINDOW);
|
||||
});
|
||||
// Used by menus.js
|
||||
openContentProcessToolbox: function (gBrowser) {
|
||||
let { childCount } = Services.ppmm;
|
||||
// Get the process message manager for the current tab
|
||||
let mm = gBrowser.selectedBrowser.messageManager.processMessageManager;
|
||||
let processId = null;
|
||||
for (let i = 1; i < childCount; i++) {
|
||||
let child = Services.ppmm.getChildAt(i);
|
||||
if (child == mm) {
|
||||
processId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (processId) {
|
||||
this._getContentProcessTarget(processId)
|
||||
.then(target => {
|
||||
// Display a new toolbox, in a new window, with debugger by default
|
||||
return gDevTools.showToolbox(target, "jsdebugger",
|
||||
Toolbox.HostType.WINDOW);
|
||||
});
|
||||
} else {
|
||||
let msg = L10N.getStr("toolbox.noContentProcessForTab.message");
|
||||
Services.prompt.alert(null, "", msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -189,7 +189,7 @@ Rule.prototype = {
|
|||
}
|
||||
|
||||
this.applyProperties((modifications) => {
|
||||
modifications.createProperty(ind, name, value, priority);
|
||||
modifications.createProperty(ind, name, value, priority, enabled);
|
||||
// Now that the rule has been updated, the server might have given us data
|
||||
// that changes the state of the property. Update it now.
|
||||
prop.updateEditor();
|
||||
|
|
|
@ -29,7 +29,7 @@ function* setPropertyOnAllRules(view) {
|
|||
// view to be updated.
|
||||
let onRefreshed = view.once("ruleview-refreshed");
|
||||
for (let rule of view._elementStyle.rules) {
|
||||
rule.editor.addProperty("font-weight", "bold", "");
|
||||
rule.editor.addProperty("font-weight", "bold", "", true);
|
||||
}
|
||||
yield onRefreshed;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ add_task(function* () {
|
|||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
ruleEditor.addProperty("font-weight", "bold", "");
|
||||
ruleEditor.addProperty("font-weight", "bold", "", true);
|
||||
yield onRuleViewChanged;
|
||||
|
||||
let textProps = ruleEditor.rule.textProps;
|
||||
|
|
|
@ -47,7 +47,7 @@ function* addNewProperty(view, index, name, value) {
|
|||
info(`Adding new property "${name}: ${value};"`);
|
||||
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
idRuleEditor.addProperty(name, value, "");
|
||||
idRuleEditor.addProperty(name, value, "", true);
|
||||
yield onRuleViewChanged;
|
||||
|
||||
let textProps = idRuleEditor.rule.textProps;
|
||||
|
|
|
@ -39,7 +39,7 @@ add_task(function* () {
|
|||
|
||||
function* testAddingProperty(view, index) {
|
||||
let ruleEditor = getRuleViewRuleEditor(view, index);
|
||||
ruleEditor.addProperty("font-weight", "bold", "");
|
||||
ruleEditor.addProperty("font-weight", "bold", "", true);
|
||||
let textProps = ruleEditor.rule.textProps;
|
||||
let lastRule = textProps[textProps.length - 1];
|
||||
is(lastRule.name, "font-weight", "Last rule name is font-weight");
|
||||
|
|
|
@ -36,7 +36,7 @@ function* testPacman(inspector, view) {
|
|||
|
||||
// let defaultView = element.ownerDocument.defaultView;
|
||||
// let ruleEditor = view.element.children[5].childNodes[0]._ruleEditor;
|
||||
// ruleEditor.addProperty("opacity", "0");
|
||||
// ruleEditor.addProperty("opacity", "0", true);
|
||||
|
||||
// yield ruleEditor._applyingModifications;
|
||||
// yield once(element, "animationend");
|
||||
|
|
|
@ -70,12 +70,12 @@ function* testTopLeft(inspector, view) {
|
|||
|
||||
let onAdded = view.once("ruleview-changed");
|
||||
let firstProp = elementFirstLineRuleView.addProperty("background-color",
|
||||
"rgb(0, 255, 0)", "");
|
||||
"rgb(0, 255, 0)", "", true);
|
||||
yield onAdded;
|
||||
|
||||
onAdded = view.once("ruleview-changed");
|
||||
let secondProp = elementFirstLineRuleView.addProperty("font-style",
|
||||
"italic", "");
|
||||
"italic", "", true);
|
||||
yield onAdded;
|
||||
|
||||
is(firstProp,
|
||||
|
@ -108,7 +108,7 @@ function* testTopLeft(inspector, view) {
|
|||
|
||||
onAdded = view.once("ruleview-changed");
|
||||
firstProp = elementRuleView.addProperty("background-color",
|
||||
"rgb(0, 0, 255)", "");
|
||||
"rgb(0, 0, 255)", "", true);
|
||||
yield onAdded;
|
||||
|
||||
is((yield getComputedStyleProperty(id, null, "background-color")),
|
||||
|
|
|
@ -32,7 +32,7 @@ function* testPropertyChanges(inspector, ruleView) {
|
|||
info("Adding a second margin-top value in the element selector");
|
||||
let ruleEditor = ruleView._elementStyle.rules[0].editor;
|
||||
let onRefreshed = inspector.once("rule-view-refreshed");
|
||||
ruleEditor.addProperty("margin-top", "5px", "");
|
||||
ruleEditor.addProperty("margin-top", "5px", "", true);
|
||||
yield onRefreshed;
|
||||
|
||||
let rule = ruleView._elementStyle.rules[0];
|
||||
|
|
|
@ -93,10 +93,10 @@ pickButton.tooltip=Pick an element from the page
|
|||
# bar, when there's no enough space to show all tabs at once
|
||||
sidebar.showAllTabs.tooltip=All tabs
|
||||
|
||||
# LOCALIZATION NOTE (toolbox.noContentProcess.message)
|
||||
# LOCALIZATION NOTE (toolbox.noContentProcessForTab.message)
|
||||
# Used as a message in the alert displayed when trying to open a browser
|
||||
# content toolbox and there is no content process running
|
||||
toolbox.noContentProcess.message=No content process running.
|
||||
# content toolbox and there is no content process running for the current tab
|
||||
toolbox.noContentProcessForTab.message=No content process for this tab.
|
||||
|
||||
# LOCALIZATION NOTE (toolbox.viewCssSourceInStyleEditor.label)
|
||||
# Used as a message in either tooltips or contextual menu items to open the
|
||||
|
|
|
@ -112,8 +112,9 @@ exports.menuitems = [
|
|||
{ id: "menu_browserContentToolbox",
|
||||
l10nKey: "browserContentToolboxMenu",
|
||||
disabled: true,
|
||||
oncommand() {
|
||||
gDevToolsBrowser.openContentProcessToolbox();
|
||||
oncommand(event) {
|
||||
let window = event.target.ownerDocument.defaultView;
|
||||
gDevToolsBrowser.openContentProcessToolbox(window.gBrowser);
|
||||
}
|
||||
},
|
||||
{ id: "menu_browserConsole",
|
||||
|
|
|
@ -114,6 +114,8 @@ skip-if = (os == 'linux' && e10s && debug) # Bug 1242204
|
|||
[browser_net_reload-button.js]
|
||||
[browser_net_reload-markers.js]
|
||||
[browser_net_req-resp-bodies.js]
|
||||
[browser_net_resend_cors.js]
|
||||
[browser_net_resend_headers.js]
|
||||
[browser_net_resend.js]
|
||||
[browser_net_security-details.js]
|
||||
[browser_net_security-error.js]
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
const ADD_QUERY = "t1=t2";
|
||||
const ADD_HEADER = "Test-header: true";
|
||||
const ADD_UA_HEADER = "User-Agent: Custom-Agent";
|
||||
const ADD_POSTDATA = "&t3=t4";
|
||||
|
||||
add_task(function* () {
|
||||
|
@ -129,6 +130,11 @@ add_task(function* () {
|
|||
type(["VK_RETURN"]);
|
||||
type(ADD_HEADER);
|
||||
|
||||
// add a User-Agent header, to check if default headers can be modified
|
||||
// (there will be two of them, first gets overwritten by the second)
|
||||
type(["VK_RETURN"]);
|
||||
type(ADD_UA_HEADER);
|
||||
|
||||
let postData = document.getElementById("custom-postdata-value");
|
||||
let postFocus = once(postData, "focus", false);
|
||||
postData.focus();
|
||||
|
@ -149,6 +155,9 @@ add_task(function* () {
|
|||
let hasHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_HEADER);
|
||||
ok(hasHeader, "new header added to sent request");
|
||||
|
||||
let hasUAHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_UA_HEADER);
|
||||
ok(hasUAHeader, "User-Agent header added to sent request");
|
||||
|
||||
is(data.requestPostData.postData.text,
|
||||
origData.requestPostData.postData.text + ADD_POSTDATA,
|
||||
"post data added to sent request");
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests if resending a CORS request avoids the security checks and doesn't send
|
||||
* a preflight OPTIONS request (bug 1270096 and friends)
|
||||
*/
|
||||
|
||||
add_task(function* () {
|
||||
let { tab, monitor } = yield initNetMonitor(CORS_URL);
|
||||
info("Starting test... ");
|
||||
|
||||
let { EVENTS, NetMonitorView } = monitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
let requestUrl = "http://test1.example.com" + CORS_SJS_PATH;
|
||||
|
||||
info("Waiting for OPTIONS, then POST");
|
||||
let wait = waitForNetworkEvents(monitor, 1, 1);
|
||||
yield ContentTask.spawn(tab.linkedBrowser, requestUrl, function* (url) {
|
||||
content.wrappedJSObject.performRequests(url, "triggering/preflight", "post-data");
|
||||
});
|
||||
yield wait;
|
||||
|
||||
const METHODS = ["OPTIONS", "POST"];
|
||||
|
||||
// Check the requests that were sent
|
||||
for (let [i, method] of METHODS.entries()) {
|
||||
let { attachment } = RequestsMenu.getItemAtIndex(i);
|
||||
is(attachment.method, method, `The ${method} request has the right method`);
|
||||
is(attachment.url, requestUrl, `The ${method} request has the right URL`);
|
||||
}
|
||||
|
||||
// Resend both requests without modification. Wait for resent OPTIONS, then POST.
|
||||
// POST is supposed to have no preflight OPTIONS request this time (CORS is disabled)
|
||||
let onRequests = waitForNetworkEvents(monitor, 1, 1);
|
||||
for (let [i, method] of METHODS.entries()) {
|
||||
let item = RequestsMenu.getItemAtIndex(i);
|
||||
|
||||
info(`Selecting the ${method} request (at index ${i})`);
|
||||
let onUpdate = monitor.panelWin.once(EVENTS.TAB_UPDATED);
|
||||
RequestsMenu.selectedItem = item;
|
||||
yield onUpdate;
|
||||
|
||||
info("Cloning the selected request into a custom clone");
|
||||
let onPopulate = monitor.panelWin.once(EVENTS.CUSTOMREQUESTVIEW_POPULATED);
|
||||
RequestsMenu.cloneSelectedRequest();
|
||||
yield onPopulate;
|
||||
|
||||
info("Sending the cloned request (without change)");
|
||||
RequestsMenu.sendCustomRequest();
|
||||
}
|
||||
|
||||
info("Waiting for both resent requests");
|
||||
yield onRequests;
|
||||
|
||||
// Check the resent requests
|
||||
for (let [i, method] of METHODS.entries()) {
|
||||
let index = i + 2;
|
||||
let item = RequestsMenu.getItemAtIndex(index).attachment;
|
||||
is(item.method, method, `The ${method} request has the right method`);
|
||||
is(item.url, requestUrl, `The ${method} request has the right URL`);
|
||||
is(item.status, 200, `The ${method} response has the right status`);
|
||||
|
||||
if (method === "POST") {
|
||||
is(item.requestPostData.postData.text, "post-data",
|
||||
"The POST request has the right POST data");
|
||||
// eslint-disable-next-line mozilla/no-cpows-in-tests
|
||||
is(item.responseContent.content.text, "Access-Control-Allow-Origin: *",
|
||||
"The POST response has the right content");
|
||||
}
|
||||
}
|
||||
|
||||
info("Finishing the test");
|
||||
return teardown(monitor);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test if custom request headers are not ignored (bug 1270096 and friends)
|
||||
*/
|
||||
|
||||
add_task(function* () {
|
||||
let { monitor } = yield initNetMonitor(SIMPLE_SJS);
|
||||
info("Starting test... ");
|
||||
|
||||
let { NetMonitorView, NetMonitorController } = monitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
let requestUrl = SIMPLE_SJS;
|
||||
let requestHeaders = [
|
||||
{ name: "Host", value: "fakehost.example.com" },
|
||||
{ name: "User-Agent", value: "Testzilla" },
|
||||
{ name: "Referer", value: "http://example.com/referrer" },
|
||||
{ name: "Accept", value: "application/jarda"},
|
||||
{ name: "Accept-Encoding", value: "compress, identity, funcoding" },
|
||||
{ name: "Accept-Language", value: "cs-CZ" }
|
||||
];
|
||||
|
||||
let wait = waitForNetworkEvents(monitor, 0, 1);
|
||||
NetMonitorController.webConsoleClient.sendHTTPRequest({
|
||||
url: requestUrl,
|
||||
method: "POST",
|
||||
headers: requestHeaders,
|
||||
body: "Hello"
|
||||
});
|
||||
yield wait;
|
||||
|
||||
let { attachment } = RequestsMenu.getItemAtIndex(0);
|
||||
is(attachment.method, "POST", "The request has the right method");
|
||||
is(attachment.url, requestUrl, "The request has the right URL");
|
||||
|
||||
for (let { name, value } of attachment.requestHeaders.headers) {
|
||||
info(`Request header: ${name}: ${value}`);
|
||||
}
|
||||
|
||||
function hasRequestHeader(name, value) {
|
||||
let { headers } = attachment.requestHeaders;
|
||||
return headers.some(h => h.name === name && h.value === value);
|
||||
}
|
||||
|
||||
function hasNotRequestHeader(name) {
|
||||
let { headers } = attachment.requestHeaders;
|
||||
return headers.every(h => h.name !== name);
|
||||
}
|
||||
|
||||
for (let { name, value } of requestHeaders) {
|
||||
ok(hasRequestHeader(name, value), `The ${name} header has the right value`);
|
||||
}
|
||||
|
||||
// Check that the Cookie header was not added silently (i.e., that the request is
|
||||
// anonymous.
|
||||
for (let name of ["Cookie"]) {
|
||||
ok(hasNotRequestHeader(name), `The ${name} header is not present`);
|
||||
}
|
||||
|
||||
return teardown(monitor);
|
||||
});
|
|
@ -64,14 +64,14 @@ const TEST_DATA = [
|
|||
desc: "simple create",
|
||||
input: "",
|
||||
instruction: {type: "create", name: "p", value: "v", priority: "important",
|
||||
index: 0},
|
||||
index: 0, enabled: true},
|
||||
expected: "p: v !important;"
|
||||
},
|
||||
{
|
||||
desc: "create between two properties",
|
||||
input: "a:b; e: f;",
|
||||
instruction: {type: "create", name: "c", value: "d", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "a:b; c: d;e: f;"
|
||||
},
|
||||
// "create" is passed the name that the user entered, and must do
|
||||
|
@ -80,7 +80,7 @@ const TEST_DATA = [
|
|||
desc: "create requiring escape",
|
||||
input: "",
|
||||
instruction: {type: "create", name: "a b", value: "d", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "a\\ b: d;"
|
||||
},
|
||||
{
|
||||
|
@ -137,7 +137,7 @@ const TEST_DATA = [
|
|||
// Note the lack of a trailing semicolon.
|
||||
input: "color: red",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "color: red;a: b;"
|
||||
},
|
||||
|
||||
|
@ -146,7 +146,7 @@ const TEST_DATA = [
|
|||
desc: "simple newline insertion",
|
||||
input: "\ncolor: red;\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\ncolor: red;\na: b;\n"
|
||||
},
|
||||
// Newline insertion.
|
||||
|
@ -155,7 +155,7 @@ const TEST_DATA = [
|
|||
// Note the lack of a trailing semicolon.
|
||||
input: "\ncolor: red\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\ncolor: red;\na: b;\n"
|
||||
},
|
||||
// Newline insertion.
|
||||
|
@ -164,7 +164,7 @@ const TEST_DATA = [
|
|||
// Note the lack of a trailing semicolon and newline.
|
||||
input: "\ncolor: red",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\ncolor: red;\na: b;\n"
|
||||
},
|
||||
|
||||
|
@ -173,7 +173,7 @@ const TEST_DATA = [
|
|||
desc: "indentation with create",
|
||||
input: "\n color: red;\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\n color: red;\n a: b;\n"
|
||||
},
|
||||
// Newline insertion and indentation.
|
||||
|
@ -182,7 +182,7 @@ const TEST_DATA = [
|
|||
// Note the lack of a trailing semicolon.
|
||||
input: "\n color: red\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\n color: red;\n a: b;\n"
|
||||
},
|
||||
{
|
||||
|
@ -198,7 +198,7 @@ const TEST_DATA = [
|
|||
// the indentation of the "}".
|
||||
input: "\n color: red;\n ",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\n color: red;\n a: b;\n "
|
||||
},
|
||||
// Newline insertion and indentation.
|
||||
|
@ -207,7 +207,7 @@ const TEST_DATA = [
|
|||
// Note how the comment comes before the declaration.
|
||||
input: "\n /* comment */ color: red\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "\n /* comment */ color: red;\n a: b;\n"
|
||||
},
|
||||
// Default indentation.
|
||||
|
@ -215,7 +215,7 @@ const TEST_DATA = [
|
|||
desc: "use of default indentation",
|
||||
input: "\n",
|
||||
instruction: {type: "create", name: "a", value: "b", priority: "",
|
||||
index: 0},
|
||||
index: 0, enabled: true},
|
||||
expected: "\n\ta: b;\n"
|
||||
},
|
||||
|
||||
|
@ -275,7 +275,7 @@ const TEST_DATA = [
|
|||
desc: "create single quote termination",
|
||||
input: "content: 'hi",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "content: 'hi';color: red;",
|
||||
changed: {0: "'hi'"}
|
||||
},
|
||||
|
@ -293,7 +293,7 @@ const TEST_DATA = [
|
|||
desc: "create double quote termination",
|
||||
input: "content: \"hi",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "content: \"hi\";color: red;",
|
||||
changed: {0: "\"hi\""}
|
||||
},
|
||||
|
@ -312,7 +312,7 @@ const TEST_DATA = [
|
|||
desc: "create url termination",
|
||||
input: "background-image: url(something.jpg",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "background-image: url(something.jpg);color: red;",
|
||||
changed: {0: "url(something.jpg)"}
|
||||
},
|
||||
|
@ -331,7 +331,7 @@ const TEST_DATA = [
|
|||
desc: "create url single quote termination",
|
||||
input: "background-image: url('something.jpg",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "background-image: url('something.jpg');color: red;",
|
||||
changed: {0: "url('something.jpg')"}
|
||||
},
|
||||
|
@ -350,7 +350,7 @@ const TEST_DATA = [
|
|||
desc: "enable url double quote termination",
|
||||
input: "background-image: url(\"something.jpg",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "background-image: url(\"something.jpg\");color: red;",
|
||||
changed: {0: "url(\"something.jpg\")"}
|
||||
},
|
||||
|
@ -360,7 +360,7 @@ const TEST_DATA = [
|
|||
desc: "create backslash termination",
|
||||
input: "something: \\",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "something: \\\\;color: red;",
|
||||
// The lexer rewrites the token before we see it. However this is
|
||||
// so obscure as to be inconsequential.
|
||||
|
@ -372,7 +372,7 @@ const TEST_DATA = [
|
|||
desc: "enable backslash single quote termination",
|
||||
input: "something: '\\",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "something: '\\\\';color: red;",
|
||||
changed: {0: "'\\\\'"}
|
||||
},
|
||||
|
@ -380,7 +380,7 @@ const TEST_DATA = [
|
|||
desc: "enable backslash double quote termination",
|
||||
input: "something: \"\\",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "something: \"\\\\\";color: red;",
|
||||
changed: {0: "\"\\\\\""}
|
||||
},
|
||||
|
@ -390,7 +390,7 @@ const TEST_DATA = [
|
|||
desc: "enable comment termination",
|
||||
input: "something: blah /* comment ",
|
||||
instruction: {type: "create", name: "color", value: "red", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "something: blah /* comment*/; color: red;"
|
||||
},
|
||||
|
||||
|
@ -407,7 +407,7 @@ const TEST_DATA = [
|
|||
desc: "create sanitize unpaired brace",
|
||||
input: "",
|
||||
instruction: {type: "create", name: "p", value: "}", priority: "",
|
||||
index: 0},
|
||||
index: 0, enabled: true},
|
||||
expected: "p: \\};",
|
||||
changed: {0: "\\}"}
|
||||
},
|
||||
|
@ -435,10 +435,25 @@ const TEST_DATA = [
|
|||
desc: "disabled declaration does not need semicolon insertion",
|
||||
input: "/*! no: semicolon */\n",
|
||||
instruction: {type: "create", name: "walrus", value: "zebra", priority: "",
|
||||
index: 1},
|
||||
index: 1, enabled: true},
|
||||
expected: "/*! no: semicolon */\nwalrus: zebra;\n",
|
||||
changed: {}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "create commented-out property",
|
||||
input: "p: v",
|
||||
instruction: {type: "create", name: "shoveler", value: "duck", priority: "",
|
||||
index: 1, enabled: false},
|
||||
expected: "p: v;/*! shoveler: duck; */",
|
||||
},
|
||||
{
|
||||
desc: "disabled create with comment ender in string",
|
||||
input: "",
|
||||
instruction: {type: "create", name: "content", value: "'*/'", priority: "",
|
||||
index: 0, enabled: false},
|
||||
expected: "/*! content: '*\\/'; */"
|
||||
},
|
||||
];
|
||||
|
||||
function rewriteDeclarations(inputString, instruction, defaultIndentation) {
|
||||
|
@ -458,7 +473,8 @@ function rewriteDeclarations(inputString, instruction, defaultIndentation) {
|
|||
|
||||
case "create":
|
||||
rewriter.createProperty(instruction.index, instruction.name,
|
||||
instruction.value, instruction.priority);
|
||||
instruction.value, instruction.priority,
|
||||
instruction.enabled);
|
||||
break;
|
||||
|
||||
case "set":
|
||||
|
|
|
@ -95,6 +95,7 @@ skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
|
|||
[browser_styleeditor_sourcemap_large.js]
|
||||
[browser_styleeditor_sourcemap_watching.js]
|
||||
[browser_styleeditor_sync.js]
|
||||
[browser_styleeditor_syncAddProperty.js]
|
||||
[browser_styleeditor_syncAddRule.js]
|
||||
[browser_styleeditor_syncAlreadyOpen.js]
|
||||
[browser_styleeditor_syncEditSelector.js]
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that adding a new rule is synced to the style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
body {
|
||||
border-width: 15px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#testid {
|
||||
font-size: 4em;
|
||||
/*! background-color: yellow; */
|
||||
}
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
|
||||
info("Focusing a new property name in the rule-view");
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
let editor = yield focusEditableField(view, ruleEditor.closeBrace);
|
||||
is(inplaceEditor(ruleEditor.newPropSpan), editor,
|
||||
"The new property editor has focus");
|
||||
|
||||
let input = editor.input;
|
||||
input.value = "/* background-color: yellow; */";
|
||||
|
||||
info("Pressing return to commit and focus the new value field");
|
||||
let onModifications = view.once("ruleview-changed");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
|
||||
yield onModifications;
|
||||
|
||||
let { ui } = yield openStyleEditor();
|
||||
let sourceEditor = yield ui.editors[0].getSourceEditor();
|
||||
let text = sourceEditor.sourceEditor.getText();
|
||||
is(text, expectedText, "selector edits are synced");
|
||||
});
|
|
@ -23,6 +23,7 @@ loader.lazyRequireGetter(this, "events", "sdk/event/core");
|
|||
loader.lazyRequireGetter(this, "ServerLoggingListener", "devtools/shared/webconsole/server-logger", true);
|
||||
loader.lazyRequireGetter(this, "JSPropertyProvider", "devtools/shared/webconsole/js-property-provider", true);
|
||||
loader.lazyRequireGetter(this, "Parser", "resource://devtools/shared/Parser.jsm", true);
|
||||
loader.lazyRequireGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm", true);
|
||||
|
||||
for (let name of ["WebConsoleUtils", "ConsoleServiceListener",
|
||||
"ConsoleAPIListener", "addWebConsoleCommands",
|
||||
|
@ -1563,23 +1564,46 @@ WebConsoleActor.prototype =
|
|||
/**
|
||||
* Send a new HTTP request from the target's window.
|
||||
*
|
||||
* @param object aMessage
|
||||
* @param object message
|
||||
* Object with 'request' - the HTTP request details.
|
||||
*/
|
||||
onSendHTTPRequest: function WCA_onSendHTTPRequest(aMessage)
|
||||
{
|
||||
let details = aMessage.request;
|
||||
onSendHTTPRequest(message) {
|
||||
let { url, method, headers, body } = message.request;
|
||||
|
||||
// send request from target's window
|
||||
let request = new this.window.XMLHttpRequest();
|
||||
request.open(details.method, details.url, true);
|
||||
// Set the loadingNode and loadGroup to the target document - otherwise the
|
||||
// request won't show up in the opened netmonitor.
|
||||
let doc = this.window.document;
|
||||
|
||||
for (let {name, value} of details.headers) {
|
||||
request.setRequestHeader(name, value);
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(url),
|
||||
loadingNode: doc,
|
||||
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||
});
|
||||
|
||||
channel.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
channel.loadGroup = doc.documentLoadGroup;
|
||||
channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
|
||||
Ci.nsIRequest.INHIBIT_CACHING |
|
||||
Ci.nsIRequest.LOAD_ANONYMOUS;
|
||||
|
||||
channel.requestMethod = method;
|
||||
|
||||
for (let {name, value} of headers) {
|
||||
channel.setRequestHeader(name, value, false);
|
||||
}
|
||||
request.send(details.body);
|
||||
|
||||
let channel = request.channel.QueryInterface(Ci.nsIHttpChannel);
|
||||
if (body) {
|
||||
channel.QueryInterface(Ci.nsIUploadChannel2);
|
||||
let bodyStream = Cc["@mozilla.org/io/string-input-stream;1"]
|
||||
.createInstance(Ci.nsIStringInputStream);
|
||||
bodyStream.setData(body, body.length);
|
||||
channel.explicitSetUploadStream(bodyStream, null, -1, method, false);
|
||||
}
|
||||
|
||||
NetUtil.asyncFetch(channel, () => {});
|
||||
|
||||
let actor = this.getNetworkEventActor(channel.channelId);
|
||||
|
||||
// map channel to actor so we can associate future events with it
|
||||
|
|
|
@ -800,10 +800,12 @@ RuleRewriter.prototype = {
|
|||
* @param {String} value value of the new property
|
||||
* @param {String} priority priority of the new property; either
|
||||
* the empty string or "important"
|
||||
* @param {Boolean} enabled True if the new property should be
|
||||
* enabled, false if disabled
|
||||
* @return {Promise} a promise that is resolved when the edit has
|
||||
* completed
|
||||
*/
|
||||
internalCreateProperty: Task.async(function* (index, name, value, priority) {
|
||||
internalCreateProperty: Task.async(function* (index, name, value, priority, enabled) {
|
||||
this.completeInitialization(index);
|
||||
let newIndentation = "";
|
||||
if (this.hasNewLine) {
|
||||
|
@ -833,13 +835,18 @@ RuleRewriter.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
this.result += newIndentation + CSS.escape(name) + ": " +
|
||||
this.sanitizeText(value, index);
|
||||
|
||||
let newText = CSS.escape(name) + ": " + this.sanitizeText(value, index);
|
||||
if (priority === "important") {
|
||||
this.result += " !important";
|
||||
newText += " !important";
|
||||
}
|
||||
this.result += ";";
|
||||
newText += ";";
|
||||
|
||||
if (!enabled) {
|
||||
newText = "/*" + COMMENT_PARSING_HEURISTIC_BYPASS_CHAR + " " +
|
||||
escapeCSSComment(newText) + " */";
|
||||
}
|
||||
|
||||
this.result += newIndentation + newText;
|
||||
if (this.hasNewLine) {
|
||||
this.result += "\n";
|
||||
}
|
||||
|
@ -860,10 +867,12 @@ RuleRewriter.prototype = {
|
|||
* @param {String} value value of the new property
|
||||
* @param {String} priority priority of the new property; either
|
||||
* the empty string or "important"
|
||||
* @param {Boolean} enabled True if the new property should be
|
||||
* enabled, false if disabled
|
||||
*/
|
||||
createProperty: function (index, name, value, priority) {
|
||||
createProperty: function (index, name, value, priority, enabled) {
|
||||
this.editPromise = this.internalCreateProperty(index, name, value,
|
||||
priority);
|
||||
priority, enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -884,7 +893,7 @@ RuleRewriter.prototype = {
|
|||
// We might see a "set" on a previously non-existent property; in
|
||||
// that case, act like "create".
|
||||
if (!this.decl) {
|
||||
this.createProperty(index, name, value, priority);
|
||||
this.createProperty(index, name, value, priority, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -398,7 +398,7 @@ var RuleModificationList = Class({
|
|||
* Create a new property. This implementation does nothing, because
|
||||
* |setRuleText| is not available.
|
||||
*
|
||||
* These parameter are passed, but as they are not used in this
|
||||
* These parameters are passed, but as they are not used in this
|
||||
* implementation, they are omitted. They are documented here as
|
||||
* this code also defined the interface implemented by @see
|
||||
* RuleRewriter.
|
||||
|
@ -412,6 +412,8 @@ var RuleModificationList = Class({
|
|||
* @param {String} value value of the new property
|
||||
* @param {String} priority priority of the new property; either
|
||||
* the empty string or "important"
|
||||
* @param {Boolean} enabled True if the new property should be
|
||||
* enabled, false if disabled
|
||||
*/
|
||||
createProperty: function () {
|
||||
// Nothing.
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
@keyframes anim {
|
||||
to { transform: translate(100px); }
|
||||
}
|
||||
@keyframes anotherAnim {
|
||||
to { transform: translate(0px); }
|
||||
}
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
|
@ -1397,6 +1400,29 @@ function assert_records(expected, desc) {
|
|||
|
||||
e.style = "";
|
||||
});
|
||||
|
||||
addAsyncAnimTest("animtion_order_change", aOptions, function*() {
|
||||
e.style.animation = "anim 100s, anotherAnim 100s";
|
||||
|
||||
var animations = e.getAnimations();
|
||||
yield await_frame();
|
||||
assert_records([{ added: animations, changed: [], removed: []}],
|
||||
"records after creation");
|
||||
e.style.animation = "anotherAnim 100s, anim 100s";
|
||||
animations = e.getAnimations();
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: animations, removed: []}],
|
||||
"records after the order is changed");
|
||||
|
||||
e.style.animation = "anotherAnim 100s, anim 100s";
|
||||
yield await_frame();
|
||||
assert_records([],
|
||||
"no records after applying the same order");
|
||||
|
||||
e.style.animation = "";
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
||||
|
|
|
@ -5982,8 +5982,8 @@ nsGlobalWindow::DispatchResizeEvent(const CSSIntSize& aSize)
|
|||
CustomEvent* customEvent = static_cast<CustomEvent*>(domEvent.get());
|
||||
customEvent->InitCustomEvent(cx,
|
||||
NS_LITERAL_STRING("DOMWindowResize"),
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ true,
|
||||
/* aCanBubble = */ true,
|
||||
/* aCancelable = */ true,
|
||||
detailValue,
|
||||
res);
|
||||
if (res.Failed()) {
|
||||
|
|
|
@ -2778,6 +2778,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
|||
bool aScriptFromHead,
|
||||
const mozilla::net::ReferrerPolicy aReferrerPolicy)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(mDocument);
|
||||
// Check to see if scripts has been turned off.
|
||||
if (!mEnabled || !mDocument->IsScriptEnabled()) {
|
||||
return;
|
||||
|
@ -2794,7 +2795,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
|||
("nsScriptLoader::PreloadURI, integrity=%s",
|
||||
NS_ConvertUTF16toUTF8(aIntegrity).get()));
|
||||
nsAutoCString sourceUri;
|
||||
if (mDocument && mDocument->GetDocumentURI()) {
|
||||
if (mDocument->GetDocumentURI()) {
|
||||
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
|
||||
}
|
||||
SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
|
||||
|
|
|
@ -111,8 +111,8 @@ DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
|
|||
ErrorResult res;
|
||||
event->InitCustomEvent(cx,
|
||||
aEventName,
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ true,
|
||||
/* aCanBubble = */ true,
|
||||
/* aCancelable = */ true,
|
||||
aDetailValue,
|
||||
res);
|
||||
if (res.Failed()) {
|
||||
|
|
|
@ -729,11 +729,8 @@ WebGLContext::CreateAndInitGL(bool forceEnabled,
|
|||
const bool useEGL = PR_GetEnv("MOZ_WEBGL_FORCE_EGL");
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (!IsWebGL2()) {
|
||||
// Use only ANGLE on Windows for WebGL 1.
|
||||
tryNativeGL = false;
|
||||
tryANGLE = true;
|
||||
}
|
||||
tryNativeGL = false;
|
||||
tryANGLE = true;
|
||||
|
||||
if (gfxPrefs::WebGLDisableWGL()) {
|
||||
tryNativeGL = false;
|
||||
|
|
|
@ -4593,6 +4593,7 @@ skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.
|
|||
[generated/test_2_conformance2__state__gl-object-get-calls.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance2__transform_feedback__transform_feedback.html]
|
||||
fail-if = (os == 'win' && (os_version == '6.1' || os_version == '6.2' || os_version == '10.0'))
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance2__vertex_arrays__vertex-array-object.html]
|
||||
fail-if = (os == 'mac') || (os == 'win')
|
||||
|
@ -4792,22 +4793,16 @@ skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.
|
|||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec2.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec3.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec4.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec2.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec3.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec4.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-mat2.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-mat3.html]
|
||||
|
@ -4816,18 +4811,14 @@ skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.
|
|||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec-mat-corner-cases.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec-mat-index.html]
|
||||
skip-if = (os == 'mac') || (os == 'win') || (os == 'linux') || (os == 'android') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec2.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec3.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec4.html]
|
||||
skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__functions__glsl-function-abs.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__functions__glsl-function-acos.html]
|
||||
|
|
|
@ -628,49 +628,41 @@ skip-if = (os == 'win' && os_version == '6.1')
|
|||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec2.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec3.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-bvec4.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec2.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec3.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-ivec4.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec-mat-corner-cases.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec2.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec3.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__glsl__constructors__glsl-construct-vec4.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
fail-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance__textures__misc__tex-image-and-sub-image-2d-with-array-buffer-view.html]
|
||||
# Failure on win7 but got passed on win7 vm
|
||||
skip-if = (os == 'win' && os_version == '6.1')
|
||||
[generated/test_2_conformance__canvas__drawingbuffer-static-canvas-test.html]
|
||||
# Framebuffer size can't be GL_MAX_RENDERBUFFER_SIZE
|
||||
skip-if = (os == 'win' && os_version == '6.2')
|
||||
[generated/test_2_conformance2__transform_feedback__transform_feedback.html]
|
||||
fail-if = (os == 'win' && (os_version == '6.1' || os_version == '6.2' || os_version == '10.0'))
|
||||
|
||||
####################
|
||||
# failure on Windows
|
||||
|
|
|
@ -1257,7 +1257,7 @@ Geolocation::Shutdown()
|
|||
if (doc) {
|
||||
doc->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
||||
this,
|
||||
/* useCapture = */ true);
|
||||
/* aUseCapture = */ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
153
dom/ipc/Blob.cpp
153
dom/ipc/Blob.cpp
|
@ -45,6 +45,7 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "BackgroundChild.h" // BackgroundChild::GetForCurrentThread().
|
||||
|
@ -1700,10 +1701,17 @@ class BlobChild::RemoteBlobImpl
|
|||
{
|
||||
protected:
|
||||
class CreateStreamHelper;
|
||||
class WorkerHolder;
|
||||
|
||||
BlobChild* mActor;
|
||||
nsCOMPtr<nsIEventTarget> mActorTarget;
|
||||
|
||||
// These member variables are protected by mutex and it's set to null when the
|
||||
// worker goes away.
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsAutoPtr<WorkerHolder> mWorkerHolder;
|
||||
Mutex mMutex;
|
||||
|
||||
// We use this pointer to keep a live a blobImpl coming from a different
|
||||
// process until this one is fully created. We set it to null when
|
||||
// SendCreatedFromKnownBlob() is received. This is used only with KnownBlob
|
||||
|
@ -1823,6 +1831,16 @@ public:
|
|||
mDifferentProcessBlobImpl = nullptr;
|
||||
}
|
||||
|
||||
// Used only by CreateStreamHelper, it dispatches a runnable to the target
|
||||
// thread. This thread can be the main-thread, the background thread or a
|
||||
// worker. If the thread is a worker, the aRunnable is wrapper into a
|
||||
// ControlRunnable in order to avoid to be blocked into a sync event loop.
|
||||
nsresult
|
||||
DispatchToTarget(nsIRunnable* aRunnable);
|
||||
|
||||
void
|
||||
WorkerHasNotified();
|
||||
|
||||
protected:
|
||||
// For SliceImpl.
|
||||
RemoteBlobImpl(const nsAString& aContentType, uint64_t aLength);
|
||||
|
@ -1840,8 +1858,28 @@ protected:
|
|||
Destroy();
|
||||
};
|
||||
|
||||
class BlobChild::RemoteBlobImpl::WorkerHolder final
|
||||
: public workers::WorkerHolder
|
||||
{
|
||||
// Raw pointer because this class is kept alive by the mRemoteBlobImpl.
|
||||
RemoteBlobImpl* mRemoteBlobImpl;
|
||||
|
||||
public:
|
||||
explicit WorkerHolder(RemoteBlobImpl* aRemoteBlobImpl)
|
||||
: mRemoteBlobImpl(aRemoteBlobImpl)
|
||||
{
|
||||
MOZ_ASSERT(aRemoteBlobImpl);
|
||||
}
|
||||
|
||||
bool Notify(Status aStatus) override
|
||||
{
|
||||
mRemoteBlobImpl->WorkerHasNotified();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class BlobChild::RemoteBlobImpl::CreateStreamHelper final
|
||||
: public Runnable
|
||||
: public CancelableRunnable
|
||||
{
|
||||
Monitor mMonitor;
|
||||
RefPtr<RemoteBlobImpl> mRemoteBlobImpl;
|
||||
|
@ -1856,8 +1894,7 @@ public:
|
|||
nsresult
|
||||
GetStream(nsIInputStream** aInputStream);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
~CreateStreamHelper()
|
||||
|
@ -2054,6 +2091,8 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
|||
BlobImplIsDirectory aIsDirectory,
|
||||
bool aIsSameProcessBlob)
|
||||
: BlobImplBase(aName, aContentType, aLength, aModDate)
|
||||
, mWorkerPrivate(nullptr)
|
||||
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
||||
, mIsSlice(false), mIsDirectory(aIsDirectory == eDirectory)
|
||||
{
|
||||
SetPath(aPath);
|
||||
|
@ -2076,6 +2115,8 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
|||
uint64_t aLength,
|
||||
bool aIsSameProcessBlob)
|
||||
: BlobImplBase(aContentType, aLength)
|
||||
, mWorkerPrivate(nullptr)
|
||||
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
||||
, mIsSlice(false), mIsDirectory(false)
|
||||
{
|
||||
if (aIsSameProcessBlob) {
|
||||
|
@ -2092,6 +2133,8 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
|||
BlobChild::
|
||||
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
|
||||
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
|
||||
, mWorkerPrivate(nullptr)
|
||||
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
||||
, mIsSlice(false), mIsDirectory(false)
|
||||
{
|
||||
CommonInit(aActor);
|
||||
|
@ -2101,6 +2144,8 @@ BlobChild::
|
|||
RemoteBlobImpl::RemoteBlobImpl(const nsAString& aContentType, uint64_t aLength)
|
||||
: BlobImplBase(aContentType, aLength)
|
||||
, mActor(nullptr)
|
||||
, mWorkerPrivate(nullptr)
|
||||
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
||||
, mIsSlice(true)
|
||||
, mIsDirectory(false)
|
||||
{
|
||||
|
@ -2118,6 +2163,22 @@ RemoteBlobImpl::CommonInit(BlobChild* aActor)
|
|||
mActor = aActor;
|
||||
mActorTarget = aActor->EventTarget();
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
mWorkerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
// We must comunicate via IPC in the owning thread, so, if this BlobImpl has
|
||||
// been created on a Workerr and then it's sent to a different thread (for
|
||||
// instance the main-thread), we still need to keep alive that Worker.
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerHolder = new RemoteBlobImpl::WorkerHolder(this);
|
||||
if (NS_WARN_IF(!mWorkerHolder->HoldWorker(mWorkerPrivate, Closing))) {
|
||||
// We don't care too much if the worker is already going away because no
|
||||
// sync-event-loop can be created at this point.
|
||||
mWorkerPrivate = nullptr;
|
||||
mWorkerHolder = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mImmutable = true;
|
||||
}
|
||||
|
||||
|
@ -2161,6 +2222,13 @@ RemoteBlobImpl::Destroy()
|
|||
mActor->NoteDyingRemoteBlobImpl();
|
||||
}
|
||||
|
||||
if (mWorkerHolder) {
|
||||
// We are in the worker thread.
|
||||
MutexAutoLock lock(mMutex);
|
||||
mWorkerPrivate = nullptr;
|
||||
mWorkerHolder = nullptr;
|
||||
}
|
||||
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
@ -2345,6 +2413,71 @@ RemoteBlobImpl::GetBlobParent()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
class RemoteBlobControlRunnable : public WorkerControlRunnable
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
||||
public:
|
||||
RemoteBlobControlRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
nsIRunnable* aRunnable)
|
||||
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
||||
, mRunnable(aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(aRunnable);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
mRunnable->Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
nsresult
|
||||
BlobChild::
|
||||
RemoteBlobImpl::DispatchToTarget(nsIRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(aRunnable);
|
||||
|
||||
// We have to protected mWorkerPrivate because this method can be called by
|
||||
// any thread (sort of).
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mWorkerPrivate) {
|
||||
MOZ_ASSERT(mWorkerHolder);
|
||||
|
||||
RefPtr<RemoteBlobControlRunnable> controlRunnable =
|
||||
new RemoteBlobControlRunnable(mWorkerPrivate, aRunnable);
|
||||
if (!controlRunnable->Dispatch()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = BaseRemoteBlobImpl()->GetActorEventTarget();
|
||||
if (!target) {
|
||||
target = do_GetMainThread();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
return target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
BlobChild::
|
||||
RemoteBlobImpl::WorkerHasNotified()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mWorkerHolder->ReleaseWorker();
|
||||
|
||||
mWorkerHolder = nullptr;
|
||||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* BlobChild::RemoteBlobImpl::CreateStreamHelper
|
||||
******************************************************************************/
|
||||
|
@ -2382,16 +2515,7 @@ CreateStreamHelper::GetStream(nsIInputStream** aInputStream)
|
|||
if (EventTargetIsOnCurrentThread(baseRemoteBlobImpl->GetActorEventTarget())) {
|
||||
RunInternal(baseRemoteBlobImpl, false);
|
||||
} else {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = baseRemoteBlobImpl->GetActorEventTarget();
|
||||
if (!target) {
|
||||
target = do_GetMainThread();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
nsresult rv = baseRemoteBlobImpl->DispatchToTarget(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2462,9 +2586,6 @@ CreateStreamHelper::RunInternal(RemoteBlobImpl* aBaseRemoteBlobImpl,
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(BlobChild::RemoteBlobImpl::CreateStreamHelper,
|
||||
Runnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
BlobChild::RemoteBlobImpl::
|
||||
CreateStreamHelper::Run()
|
||||
|
|
|
@ -101,6 +101,13 @@
|
|||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
return helper.waitForFrames(vremote);
|
||||
},
|
||||
// For some reason, even though we're getting a 25x25 stream, sometimes
|
||||
// the resolution isn't updated on the video element on the first frame.
|
||||
function PC_REMOTE_WAIT_FOR_FRAMES_3() {
|
||||
var vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
return helper.waitForFrames(vremote);
|
||||
},
|
||||
function PC_REMOTE_CHECK_SIZE_2() {
|
||||
var vlocal = test.pcLocal.localMediaElements[0];
|
||||
var vremote = test.pcRemote.remoteMediaElements[0];
|
||||
|
|
|
@ -130,7 +130,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
|
|||
attribute XMLHttpRequestResponseType responseType;
|
||||
[Throws]
|
||||
readonly attribute any response;
|
||||
[Throws]
|
||||
[Cached, Pure, Throws]
|
||||
readonly attribute DOMString? responseText;
|
||||
|
||||
[Throws, Exposed=Window]
|
||||
|
|
|
@ -1437,7 +1437,9 @@ GetWorkerPrivateFromContext(JSContext* aCx)
|
|||
MOZ_ASSERT(aCx);
|
||||
|
||||
void* cxPrivate = JS_GetContextPrivate(aCx);
|
||||
MOZ_ASSERT(cxPrivate);
|
||||
if (!cxPrivate) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return
|
||||
static_cast<WorkerThreadContextPrivate*>(cxPrivate)->GetWorkerPrivate();
|
||||
|
@ -1457,7 +1459,13 @@ GetCurrentThreadWorkerPrivate()
|
|||
MOZ_ASSERT(cx);
|
||||
|
||||
void* cxPrivate = JS_GetContextPrivate(cx);
|
||||
MOZ_ASSERT(cxPrivate);
|
||||
if (!cxPrivate) {
|
||||
// This can happen if the nsCycleCollector_shutdown() in ~WorkerJSRuntime()
|
||||
// triggers any calls to GetCurrentThreadWorkerPrivate(). At this stage
|
||||
// CycleCollectedJSRuntime::Get() will still return a runtime, but
|
||||
// the context private has already been cleared.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return
|
||||
static_cast<WorkerThreadContextPrivate*>(cxPrivate)->GetWorkerPrivate();
|
||||
|
|
|
@ -103,6 +103,8 @@ support-files =
|
|||
importScripts_3rdParty_worker.js
|
||||
worker_bug1278777.js
|
||||
worker_setTimeoutWith0.js
|
||||
worker_bug1301094.js
|
||||
script_bug1301094.js
|
||||
!/dom/base/test/file_websocket_basic_wsh.py
|
||||
!/dom/base/test/file_websocket_hello_wsh.py
|
||||
!/dom/base/test/file_websocket_http_resource.txt
|
||||
|
@ -227,3 +229,4 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 982828
|
|||
[test_navigator_workers_hardwareConcurrency.html]
|
||||
[test_bug1278777.html]
|
||||
[test_setTimeoutWith0.html]
|
||||
[test_bug1301094.html]
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.importGlobalProperties(["File", "Directory"]);
|
||||
|
||||
addMessageListener("file.open", function (e) {
|
||||
var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIDirectoryService)
|
||||
.QueryInterface(Ci.nsIProperties)
|
||||
.get('TmpD', Ci.nsIFile)
|
||||
tmpFile.append('file.txt');
|
||||
tmpFile.createUnique(Components.interfaces.nsIFile.FILE_TYPE, 0o600);
|
||||
|
||||
sendAsyncMessage("file.opened", {
|
||||
data: new File(tmpFile)
|
||||
});
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1301094
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1301094</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301094">Mozilla Bug 1301094</a>
|
||||
<input id="file" type="file"></input>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var url = SimpleTest.getTestFileURL("script_bug1301094.js");
|
||||
script = SpecialPowers.loadChromeScript(url);
|
||||
|
||||
var mainThreadOk, workerOk;
|
||||
|
||||
function maybeFinish() {
|
||||
if (mainThreadOk & workerOk) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function onOpened(message) {
|
||||
var input = document.getElementById('file');
|
||||
SpecialPowers.wrap(input).mozSetDndFilesAndDirectories([message.data]);
|
||||
|
||||
var worker = new Worker('worker_bug1301094.js');
|
||||
worker.onerror = function() {
|
||||
ok(false, "We should not see any error.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
worker.onmessage = function(e) {
|
||||
ok(e.data, "Everything seems OK on the worker-side.");
|
||||
|
||||
workerOk = true;
|
||||
maybeFinish();
|
||||
}
|
||||
|
||||
is(input.files.length, 1, "We have something");
|
||||
ok(input.files[0] instanceof Blob, "We have one Blob");
|
||||
worker.postMessage(input.files[0]);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", 'worker_bug1301094.js', false);
|
||||
xhr.onload = function() {
|
||||
ok(xhr.responseText, "Everything seems OK on the main-thread-side.");
|
||||
mainThreadOk = true;
|
||||
maybeFinish();
|
||||
};
|
||||
|
||||
var fd = new FormData();
|
||||
fd.append('file', input.files[0]);
|
||||
xhr.send(fd);
|
||||
}
|
||||
|
||||
script.addMessageListener("file.opened", onOpened);
|
||||
script.sendAsyncMessage("file.open");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,11 @@
|
|||
onmessage = function(e) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", 'worker_bug1301094.js', false);
|
||||
xhr.onload = function() {
|
||||
self.postMessage("OK");
|
||||
};
|
||||
|
||||
var fd = new FormData();
|
||||
fd.append('file', e.data);
|
||||
xhr.send(fd);
|
||||
}
|
|
@ -288,7 +288,7 @@ XMLHttpRequestMainThread::ResetResponse()
|
|||
{
|
||||
mResponseXML = nullptr;
|
||||
mResponseBody.Truncate();
|
||||
mResponseText.Truncate();
|
||||
TruncateResponseText();
|
||||
mResponseBlob = nullptr;
|
||||
mDOMBlob = nullptr;
|
||||
mBlobSet = nullptr;
|
||||
|
@ -420,7 +420,7 @@ XMLHttpRequestMainThread::SizeOfEventTargetIncludingThis(
|
|||
// - Binary extensions, but they're *extremely* unlikely to do any memory
|
||||
// reporting.
|
||||
//
|
||||
n += mResponseText.SizeOfExcludingThisEvenIfShared(aMallocSizeOf);
|
||||
n += mResponseText.SizeOfThis(aMallocSizeOf);
|
||||
|
||||
return n;
|
||||
|
||||
|
@ -535,35 +535,30 @@ XMLHttpRequestMainThread::AppendToResponseText(const char * aSrcBuffer,
|
|||
&destBufferLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t size = mResponseText.Length() + destBufferLen;
|
||||
if (size < (uint32_t)destBufferLen) {
|
||||
CheckedInt32 size = mResponseText.Length();
|
||||
size += destBufferLen;
|
||||
if (!size.isValid()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!mResponseText.SetCapacity(size, fallible)) {
|
||||
XMLHttpRequestStringWriterHelper helper(mResponseText);
|
||||
|
||||
if (!helper.AddCapacity(destBufferLen)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char16_t* destBuffer = mResponseText.BeginWriting() + mResponseText.Length();
|
||||
|
||||
CheckedInt32 totalChars = mResponseText.Length();
|
||||
|
||||
// This code here is basically a copy of a similar thing in
|
||||
// nsScanner::Append(const char* aBuffer, uint32_t aLen).
|
||||
int32_t srclen = (int32_t)aSrcBufferLen;
|
||||
int32_t destlen = (int32_t)destBufferLen;
|
||||
rv = mDecoder->Convert(aSrcBuffer,
|
||||
&srclen,
|
||||
destBuffer,
|
||||
helper.EndOfExistingData(),
|
||||
&destlen);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(destlen <= destBufferLen);
|
||||
|
||||
totalChars += destlen;
|
||||
if (!totalChars.isValid()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mResponseText.SetLength(totalChars.value());
|
||||
helper.AddLength(destlen);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -571,9 +566,7 @@ NS_IMETHODIMP
|
|||
XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsString responseText;
|
||||
GetResponseText(responseText, rv);
|
||||
aResponseText = responseText;
|
||||
GetResponseText(aResponseText, rv);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
|
@ -581,7 +574,20 @@ void
|
|||
XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
aResponseText.Truncate();
|
||||
XMLHttpRequestStringSnapshot snapshot;
|
||||
GetResponseText(snapshot, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
snapshot.GetAsString(aResponseText);
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestMainThread::GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
aSnapshot.Reset();
|
||||
|
||||
if (mResponseType != XMLHttpRequestResponseType::_empty &&
|
||||
mResponseType != XMLHttpRequestResponseType::Text &&
|
||||
|
@ -592,7 +598,7 @@ XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText,
|
|||
|
||||
if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_text &&
|
||||
!mInLoadProgressEvent) {
|
||||
aResponseText.SetIsVoid(true);
|
||||
aSnapshot.SetVoid();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -605,7 +611,7 @@ XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText,
|
|||
// more.
|
||||
if ((!mResponseXML && !mErrorParsingXML) ||
|
||||
mResponseBodyDecodedPos == mResponseBody.Length()) {
|
||||
aResponseText = mResponseText;
|
||||
mResponseText.CreateSnapshot(aSnapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -627,7 +633,7 @@ XMLHttpRequestMainThread::GetResponseText(nsAString& aResponseText,
|
|||
mResponseBodyDecodedPos = 0;
|
||||
}
|
||||
|
||||
aResponseText = mResponseText;
|
||||
mResponseText.CreateSnapshot(aSnapshot);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -637,11 +643,12 @@ XMLHttpRequestMainThread::CreateResponseParsedJSON(JSContext* aCx)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoString string;
|
||||
mResponseText.GetAsString(string);
|
||||
|
||||
// The Unicode converter has already zapped the BOM if there was one
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ParseJSON(aCx,
|
||||
static_cast<const char16_t*>(mResponseText.get()), mResponseText.Length(),
|
||||
&value)) {
|
||||
if (!JS_ParseJSON(aCx, string.BeginReading(), string.Length(), &value)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -749,7 +756,7 @@ XMLHttpRequestMainThread::GetResponse(JSContext* aCx,
|
|||
case XMLHttpRequestResponseType::Text:
|
||||
case XMLHttpRequestResponseType::Moz_chunked_text:
|
||||
{
|
||||
nsString str;
|
||||
nsAutoString str;
|
||||
aRv = GetResponseText(str);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
|
@ -823,7 +830,7 @@ XMLHttpRequestMainThread::GetResponse(JSContext* aCx,
|
|||
|
||||
if (mResultJSON.isUndefined()) {
|
||||
aRv = CreateResponseParsedJSON(aCx);
|
||||
mResponseText.Truncate();
|
||||
TruncateResponseText();
|
||||
if (aRv.Failed()) {
|
||||
// Per spec, errors aren't propagated. null is returned instead.
|
||||
aRv = NS_OK;
|
||||
|
@ -1332,7 +1339,7 @@ XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
|
|||
if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_text ||
|
||||
mResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) {
|
||||
mResponseBody.Truncate();
|
||||
mResponseText.Truncate();
|
||||
TruncateResponseText();
|
||||
mResultArrayBuffer = nullptr;
|
||||
mArrayBufferBuilder.reset();
|
||||
}
|
||||
|
@ -1691,6 +1698,7 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request,
|
|||
MOZ_ASSERT(mContext.get() == ctxt,"start context different from OnDataAvailable context");
|
||||
|
||||
mProgressSinceLastProgressEvent = true;
|
||||
XMLHttpRequestBinding::ClearCachedResponseTextValue(this);
|
||||
|
||||
bool cancelable = false;
|
||||
if ((mResponseType == XMLHttpRequestResponseType::Blob ||
|
||||
|
@ -2145,7 +2153,7 @@ XMLHttpRequestMainThread::MatchCharsetAndDecoderToResponseDocument()
|
|||
{
|
||||
if (mResponseXML && mResponseCharset != mResponseXML->GetDocumentCharacterSet()) {
|
||||
mResponseCharset = mResponseXML->GetDocumentCharacterSet();
|
||||
mResponseText.Truncate();
|
||||
TruncateResponseText();
|
||||
mResponseBodyDecodedPos = 0;
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(mResponseCharset);
|
||||
}
|
||||
|
@ -3537,6 +3545,13 @@ XMLHttpRequestMainThread::ShouldBlockAuthPrompt()
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestMainThread::TruncateResponseText()
|
||||
{
|
||||
mResponseText.Truncate();
|
||||
XMLHttpRequestBinding::ClearCachedResponseTextValue(this);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(XMLHttpRequestMainThread::nsHeaderVisitor, nsIHttpHeaderVisitor)
|
||||
|
||||
NS_IMETHODIMP XMLHttpRequestMainThread::
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "mozilla/dom/XMLHttpRequest.h"
|
||||
#include "mozilla/dom/XMLHttpRequestBinding.h"
|
||||
#include "mozilla/dom/XMLHttpRequestEventTarget.h"
|
||||
#include "mozilla/dom/XMLHttpRequestString.h"
|
||||
|
||||
#ifdef Status
|
||||
/* Xlib headers insist on this for some reason... Nuke it because
|
||||
|
@ -469,6 +470,10 @@ public:
|
|||
virtual void
|
||||
GetResponseText(nsAString& aResponseText, ErrorResult& aRv) override;
|
||||
|
||||
void
|
||||
GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual nsIDocument*
|
||||
GetResponseXML(ErrorResult& aRv) override;
|
||||
|
||||
|
@ -573,6 +578,8 @@ protected:
|
|||
already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
|
||||
already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
|
||||
|
||||
void TruncateResponseText();
|
||||
|
||||
bool IsSystemXHR() const;
|
||||
bool InUploadPhase() const;
|
||||
|
||||
|
@ -628,7 +635,7 @@ protected:
|
|||
// lazily decode into this from mResponseBody only when .responseText is
|
||||
// accessed.
|
||||
// Only used for DEFAULT and TEXT responseTypes.
|
||||
nsString mResponseText;
|
||||
XMLHttpRequestString mResponseText;
|
||||
|
||||
// For DEFAULT responseType we use this to keep track of how far we've
|
||||
// lazily decoded from mResponseBody to mResponseText
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "XMLHttpRequestString.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class XMLHttpRequestStringBuffer final
|
||||
{
|
||||
friend class XMLHttpRequestStringWriterHelper;
|
||||
friend class XMLHttpRequestStringSnapshotReaderHelper;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer)
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
XMLHttpRequestStringBuffer()
|
||||
: mMutex("XMLHttpRequestStringBuffer::mMutex")
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Length()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mData.Length();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
UnsafeLength() const
|
||||
{
|
||||
return mData.Length();
|
||||
}
|
||||
|
||||
void
|
||||
Append(const nsAString& aString)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer);
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
mData.Append(aString);
|
||||
}
|
||||
|
||||
void
|
||||
GetAsString(nsAString& aString)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
aString = mData;
|
||||
}
|
||||
|
||||
size_t
|
||||
SizeOfThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
GetAsString(nsAString& aString, uint32_t aLength)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(aLength <= mData.Length());
|
||||
aString.Assign(mData.BeginReading(), aLength);
|
||||
}
|
||||
|
||||
void
|
||||
CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
aSnapshot.Set(this, mData.Length());
|
||||
}
|
||||
|
||||
private:
|
||||
~XMLHttpRequestStringBuffer()
|
||||
{}
|
||||
|
||||
nsString& UnsafeData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
Mutex mMutex;
|
||||
|
||||
// The following member variable is protected by mutex.
|
||||
nsString mData;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// XMLHttpRequestString
|
||||
|
||||
XMLHttpRequestString::XMLHttpRequestString()
|
||||
: mBuffer(new XMLHttpRequestStringBuffer())
|
||||
{
|
||||
}
|
||||
|
||||
XMLHttpRequestString::~XMLHttpRequestString()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestString::Truncate()
|
||||
{
|
||||
mBuffer = new XMLHttpRequestStringBuffer();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
XMLHttpRequestString::Length() const
|
||||
{
|
||||
return mBuffer->Length();
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestString::Append(const nsAString& aString)
|
||||
{
|
||||
mBuffer->Append(aString);
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestString::GetAsString(nsAString& aString) const
|
||||
{
|
||||
return mBuffer->GetAsString(aString);
|
||||
}
|
||||
|
||||
size_t
|
||||
XMLHttpRequestString::SizeOfThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mBuffer->SizeOfThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
bool
|
||||
XMLHttpRequestString::IsEmpty() const
|
||||
{
|
||||
return !mBuffer->Length();
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestString::CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot)
|
||||
{
|
||||
mBuffer->CreateSnapshot(aSnapshot);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// XMLHttpRequestStringSnapshot
|
||||
|
||||
XMLHttpRequestStringSnapshot::XMLHttpRequestStringSnapshot()
|
||||
: mLength(0)
|
||||
, mVoid(false)
|
||||
{
|
||||
}
|
||||
|
||||
XMLHttpRequestStringSnapshot::~XMLHttpRequestStringSnapshot()
|
||||
{
|
||||
}
|
||||
|
||||
XMLHttpRequestStringSnapshot&
|
||||
XMLHttpRequestStringSnapshot::operator=(const XMLHttpRequestStringSnapshot& aOther)
|
||||
{
|
||||
mBuffer = aOther.mBuffer;
|
||||
mLength = aOther.mLength;
|
||||
mVoid = aOther.mVoid;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestStringSnapshot::ResetInternal(bool aIsVoid)
|
||||
{
|
||||
mBuffer = nullptr;
|
||||
mLength = 0;
|
||||
mVoid = aIsVoid;
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestStringSnapshot::Set(XMLHttpRequestStringBuffer* aBuffer,
|
||||
uint32_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
MOZ_ASSERT(aLength <= aBuffer->UnsafeLength());
|
||||
|
||||
mBuffer = aBuffer;
|
||||
mLength = aLength;
|
||||
mVoid = false;
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestStringSnapshot::GetAsString(nsAString& aString) const
|
||||
{
|
||||
if (mBuffer) {
|
||||
MOZ_ASSERT(!mVoid);
|
||||
mBuffer->GetAsString(aString, mLength);
|
||||
return;
|
||||
}
|
||||
|
||||
aString.Truncate();
|
||||
|
||||
if (mVoid) {
|
||||
aString.SetIsVoid(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// XMLHttpRequestStringWriterHelper
|
||||
|
||||
XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper(XMLHttpRequestString& aString)
|
||||
: mBuffer(aString.mBuffer)
|
||||
, mLock(aString.mBuffer->mMutex)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
XMLHttpRequestStringWriterHelper::AddCapacity(int32_t aCapacity)
|
||||
{
|
||||
return mBuffer->UnsafeData().SetCapacity(mBuffer->UnsafeLength() + aCapacity, fallible);
|
||||
}
|
||||
|
||||
char16_t*
|
||||
XMLHttpRequestStringWriterHelper::EndOfExistingData()
|
||||
{
|
||||
return mBuffer->UnsafeData().BeginWriting() + mBuffer->UnsafeLength();
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestStringWriterHelper::AddLength(int32_t aLength)
|
||||
{
|
||||
mBuffer->UnsafeData().SetLength(mBuffer->UnsafeLength() + aLength);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// XMLHttpRequestStringReaderHelper
|
||||
|
||||
XMLHttpRequestStringSnapshotReaderHelper::XMLHttpRequestStringSnapshotReaderHelper(XMLHttpRequestStringSnapshot& aSnapshot)
|
||||
: mBuffer(aSnapshot.mBuffer)
|
||||
, mLock(aSnapshot.mBuffer->mMutex)
|
||||
{
|
||||
}
|
||||
|
||||
const char16_t*
|
||||
XMLHttpRequestStringSnapshotReaderHelper::Buffer() const
|
||||
{
|
||||
return mBuffer->UnsafeData().BeginReading();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
XMLHttpRequestStringSnapshotReaderHelper::Length() const
|
||||
{
|
||||
return mBuffer->UnsafeLength();
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
|
@ -0,0 +1,160 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_XMLHttpRequestString_h
|
||||
#define mozilla_dom_XMLHttpRequestString_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class Mutex;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class XMLHttpRequestStringBuffer;
|
||||
class XMLHttpRequestStringSnapshot;
|
||||
class XMLHttpRequestStringWriterHelper;
|
||||
class XMLHttpRequestStringSnapshotReaderHelper;
|
||||
|
||||
// We want to avoid the dup of strings when XHR in workers has access to
|
||||
// responseText for events dispatched during the loading state. For this reason
|
||||
// we use this class, able to create snapshots of the current size of itself
|
||||
// without making extra copies.
|
||||
class XMLHttpRequestString final
|
||||
{
|
||||
friend class XMLHttpRequestStringWriterHelper;
|
||||
|
||||
public:
|
||||
XMLHttpRequestString();
|
||||
~XMLHttpRequestString();
|
||||
|
||||
void Truncate();
|
||||
|
||||
uint32_t Length() const;
|
||||
|
||||
void Append(const nsAString& aString);
|
||||
|
||||
// This method should be called only when the string is really needed because
|
||||
// it can cause the duplication of the strings in case the loading of the XHR
|
||||
// is not completed yet.
|
||||
void GetAsString(nsAString& aString) const;
|
||||
|
||||
size_t SizeOfThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
const char16_t* Data() const;
|
||||
|
||||
bool IsEmpty() const;
|
||||
|
||||
void CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot);
|
||||
|
||||
private:
|
||||
XMLHttpRequestString(const XMLHttpRequestString&) = delete;
|
||||
XMLHttpRequestString& operator=(const XMLHttpRequestString&) = delete;
|
||||
XMLHttpRequestString& operator=(const XMLHttpRequestString&&) = delete;
|
||||
|
||||
RefPtr<XMLHttpRequestStringBuffer> mBuffer;
|
||||
};
|
||||
|
||||
// This class locks the buffer and allows the callee to write data into it.
|
||||
class MOZ_STACK_CLASS XMLHttpRequestStringWriterHelper final
|
||||
{
|
||||
public:
|
||||
explicit XMLHttpRequestStringWriterHelper(XMLHttpRequestString& aString);
|
||||
|
||||
bool
|
||||
AddCapacity(int32_t aCapacity);
|
||||
|
||||
char16_t*
|
||||
EndOfExistingData();
|
||||
|
||||
void
|
||||
AddLength(int32_t aLength);
|
||||
|
||||
private:
|
||||
XMLHttpRequestStringWriterHelper(const XMLHttpRequestStringWriterHelper&) = delete;
|
||||
XMLHttpRequestStringWriterHelper& operator=(const XMLHttpRequestStringWriterHelper&) = delete;
|
||||
XMLHttpRequestStringWriterHelper& operator=(const XMLHttpRequestStringWriterHelper&&) = delete;
|
||||
|
||||
RefPtr<XMLHttpRequestStringBuffer> mBuffer;
|
||||
MutexAutoLock mLock;
|
||||
};
|
||||
|
||||
// This class is the internal XMLHttpRequestStringBuffer of the
|
||||
// XMLHttpRequestString plus the current length. GetAsString will return the
|
||||
// string with that particular length also if the XMLHttpRequestStringBuffer is
|
||||
// grown in the meantime.
|
||||
class XMLHttpRequestStringSnapshot final
|
||||
{
|
||||
friend class XMLHttpRequestStringBuffer;
|
||||
friend class XMLHttpRequestStringSnapshotReaderHelper;
|
||||
|
||||
public:
|
||||
XMLHttpRequestStringSnapshot();
|
||||
~XMLHttpRequestStringSnapshot();
|
||||
|
||||
XMLHttpRequestStringSnapshot& operator=(const XMLHttpRequestStringSnapshot&);
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ResetInternal(false /* isVoid */);
|
||||
}
|
||||
|
||||
void SetVoid()
|
||||
{
|
||||
ResetInternal(true /* isVoid */);
|
||||
}
|
||||
|
||||
bool IsVoid() const
|
||||
{
|
||||
return mVoid;
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return !mLength;
|
||||
}
|
||||
|
||||
void GetAsString(nsAString& aString) const;
|
||||
|
||||
private:
|
||||
XMLHttpRequestStringSnapshot(const XMLHttpRequestStringSnapshot&) = delete;
|
||||
XMLHttpRequestStringSnapshot& operator=(const XMLHttpRequestStringSnapshot&&) = delete;
|
||||
|
||||
void Set(XMLHttpRequestStringBuffer* aBuffer, uint32_t aLength);
|
||||
|
||||
void ResetInternal(bool aIsVoid);
|
||||
|
||||
RefPtr<XMLHttpRequestStringBuffer> mBuffer;
|
||||
uint32_t mLength;
|
||||
bool mVoid;
|
||||
};
|
||||
|
||||
// This class locks the buffer and allows the callee to read data from it.
|
||||
class MOZ_STACK_CLASS XMLHttpRequestStringSnapshotReaderHelper final
|
||||
{
|
||||
public:
|
||||
explicit XMLHttpRequestStringSnapshotReaderHelper(XMLHttpRequestStringSnapshot& aSnapshot);
|
||||
|
||||
const char16_t*
|
||||
Buffer() const;
|
||||
|
||||
uint32_t
|
||||
Length() const;
|
||||
|
||||
private:
|
||||
XMLHttpRequestStringSnapshotReaderHelper(const XMLHttpRequestStringSnapshotReaderHelper&) = delete;
|
||||
XMLHttpRequestStringSnapshotReaderHelper& operator=(const XMLHttpRequestStringSnapshotReaderHelper&) = delete;
|
||||
XMLHttpRequestStringSnapshotReaderHelper& operator=(const XMLHttpRequestStringSnapshotReaderHelper&&) = delete;
|
||||
|
||||
RefPtr<XMLHttpRequestStringBuffer> mBuffer;
|
||||
MutexAutoLock mLock;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_XMLHttpRequestString_h
|
|
@ -476,7 +476,7 @@ class EventRunnable final : public MainThreadProxyRunnable
|
|||
nsString mType;
|
||||
nsString mResponseType;
|
||||
JS::Heap<JS::Value> mResponse;
|
||||
nsString mResponseText;
|
||||
XMLHttpRequestStringSnapshot mResponseText;
|
||||
nsString mResponseURL;
|
||||
nsCString mStatusText;
|
||||
uint64_t mLoaded;
|
||||
|
@ -1129,7 +1129,10 @@ EventRunnable::PreDispatch(WorkerPrivate* /* unused */)
|
|||
MOZ_ASSERT(false, "This should never fail!");
|
||||
}
|
||||
|
||||
mResponseTextResult = xhr->GetResponseText(mResponseText);
|
||||
ErrorResult rv;
|
||||
xhr->GetResponseText(mResponseText, rv);
|
||||
mResponseTextResult = rv.StealNSResult();
|
||||
|
||||
if (NS_SUCCEEDED(mResponseTextResult)) {
|
||||
mResponseResult = mResponseTextResult;
|
||||
if (mResponseText.IsVoid()) {
|
||||
|
@ -1172,7 +1175,6 @@ EventRunnable::PreDispatch(WorkerPrivate* /* unused */)
|
|||
}
|
||||
|
||||
if (doClone) {
|
||||
ErrorResult rv;
|
||||
Write(cx, response, transferable, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
NS_WARNING("Failed to clone response!");
|
||||
|
@ -1186,7 +1188,6 @@ EventRunnable::PreDispatch(WorkerPrivate* /* unused */)
|
|||
|
||||
mStatusResult = xhr->GetStatus(&mStatus);
|
||||
|
||||
ErrorResult rv;
|
||||
xhr->GetStatusText(mStatusText, rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
|
@ -1261,6 +1262,7 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
JS::Rooted<UniquePtr<XMLHttpRequestWorker::StateData>> state(aCx, new XMLHttpRequestWorker::StateData());
|
||||
|
||||
state->mResponseTextResult = mResponseTextResult;
|
||||
|
||||
state->mResponseText = mResponseText;
|
||||
|
||||
if (NS_SUCCEEDED(mResponseTextResult)) {
|
||||
|
@ -2390,10 +2392,11 @@ XMLHttpRequestWorker::GetResponse(JSContext* /* unused */,
|
|||
mStateData.mResponse =
|
||||
JS_GetEmptyStringValue(mWorkerPrivate->GetJSContext());
|
||||
} else {
|
||||
XMLHttpRequestStringSnapshotReaderHelper helper(mStateData.mResponseText);
|
||||
|
||||
JSString* str =
|
||||
JS_NewUCStringCopyN(mWorkerPrivate->GetJSContext(),
|
||||
mStateData.mResponseText.get(),
|
||||
mStateData.mResponseText.Length());
|
||||
helper.Buffer(), helper.Length());
|
||||
|
||||
if (!str) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -2413,7 +2416,13 @@ void
|
|||
XMLHttpRequestWorker::GetResponseText(nsAString& aResponseText, ErrorResult& aRv)
|
||||
{
|
||||
aRv = mStateData.mResponseTextResult;
|
||||
aResponseText = mStateData.mResponseText;
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString foo;
|
||||
mStateData.mResponseText.GetAsString(foo);
|
||||
aResponseText.Assign(foo.BeginReading(), foo.Length());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2432,6 +2441,8 @@ XMLHttpRequestWorker::UpdateState(const StateData& aStateData,
|
|||
else {
|
||||
mStateData = aStateData;
|
||||
}
|
||||
|
||||
XMLHttpRequestBinding::ClearCachedResponseTextValue(this);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "WorkerHolder.h"
|
||||
#include "XMLHttpRequest.h"
|
||||
#include "XMLHttpRequestString.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -27,7 +28,7 @@ class XMLHttpRequestWorker final : public XMLHttpRequest,
|
|||
public:
|
||||
struct StateData
|
||||
{
|
||||
nsString mResponseText;
|
||||
XMLHttpRequestStringSnapshot mResponseText;
|
||||
nsString mResponseURL;
|
||||
uint32_t mStatus;
|
||||
nsCString mStatusText;
|
||||
|
@ -266,7 +267,7 @@ public:
|
|||
void
|
||||
NullResponseText()
|
||||
{
|
||||
mStateData.mResponseText.SetIsVoid(true);
|
||||
mStateData.mResponseText.SetVoid();
|
||||
mStateData.mResponse.setNull();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ EXPORTS.mozilla.dom += [
|
|||
'XMLHttpRequest.h',
|
||||
'XMLHttpRequestEventTarget.h',
|
||||
'XMLHttpRequestMainThread.h',
|
||||
'XMLHttpRequestString.h',
|
||||
'XMLHttpRequestUpload.h',
|
||||
]
|
||||
|
||||
|
@ -21,6 +22,7 @@ UNIFIED_SOURCES += [
|
|||
'XMLHttpRequest.cpp',
|
||||
'XMLHttpRequestEventTarget.cpp',
|
||||
'XMLHttpRequestMainThread.cpp',
|
||||
'XMLHttpRequestString.cpp',
|
||||
'XMLHttpRequestUpload.cpp',
|
||||
'XMLHttpRequestWorker.cpp',
|
||||
]
|
||||
|
|
|
@ -17,15 +17,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1277814
|
|||
var subframe = document.getElementById('bug1277814-div');
|
||||
subframe.classList.add('a');
|
||||
|
||||
// The transform change is animated, so let's step through 1s of animation
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
for (var i = 0; i < 60; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
|
||||
// Wait for the layer tree with any updated dispatch-to-content region to
|
||||
// get pushed over to the APZ
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Trigger layerization of the subframe by scrolling the wheel over it
|
||||
moveMouseAndScrollWheelOver(subframe, 10, 10, testDriver);
|
||||
yield moveMouseAndScrollWheelOver(subframe, 10, 10, testDriver);
|
||||
|
||||
// Give APZ the chance to compute a displayport, and content
|
||||
// to render based on it.
|
||||
yield waitForApzFlushedRepaints(testDriver);
|
||||
|
||||
// Examine the content-side APZ test data
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
|
||||
// Test that the scroll frame for the div 'bug1277814-div' appears in
|
||||
|
|
|
@ -137,6 +137,10 @@ public:
|
|||
void SetAnimationIndex(uint64_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(IsTiedToMarkup());
|
||||
if (IsRelevant() &&
|
||||
mAnimationIndex != aIndex) {
|
||||
nsNodeUtils::AnimationChanged(this);
|
||||
}
|
||||
mAnimationIndex = aIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -318,19 +318,20 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
|||
return false;
|
||||
}
|
||||
|
||||
double nsCSSValue::GetAngleValueInRadians() const
|
||||
double
|
||||
nsCSSValue::GetAngleValueInRadians() const
|
||||
{
|
||||
double angle = GetFloatValue();
|
||||
|
||||
switch (GetUnit()) {
|
||||
case eCSSUnit_Radian: return angle;
|
||||
case eCSSUnit_Turn: return angle * 2 * M_PI;
|
||||
case eCSSUnit_Degree: return angle * M_PI / 180.0;
|
||||
case eCSSUnit_Grad: return angle * M_PI / 200.0;
|
||||
case eCSSUnit_Radian: return angle;
|
||||
case eCSSUnit_Turn: return angle * 2 * M_PI;
|
||||
case eCSSUnit_Degree: return angle * M_PI / 180.0;
|
||||
case eCSSUnit_Grad: return angle * M_PI / 200.0;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "unrecognized angular unit");
|
||||
return 0.0;
|
||||
default:
|
||||
MOZ_ASSERT(false, "unrecognized angular unit");
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSPR_4_13_BETA2
|
||||
NSPR_4_13_BETA3
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -3338,6 +3338,7 @@ static PRFileDesc *pt_SetMethods(
|
|||
case PR_DESC_PIPE:
|
||||
fd->methods = PR_GetPipeMethods();
|
||||
pt_MakeFdNonblock(osfd);
|
||||
fd->secret->nonblocking = PR_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -119,7 +119,7 @@ class TcpTransport(object):
|
|||
"""
|
||||
max_packet_length = 4096
|
||||
|
||||
def __init__(self, addr, port, socket_timeout=360.0):
|
||||
def __init__(self, addr, port, socket_timeout=60.0):
|
||||
"""If `socket_timeout` is `0` or `0.0`, non-blocking socket mode
|
||||
will be used. Setting it to `1` or `None` disables timeouts on
|
||||
socket operations altogether.
|
||||
|
|
|
@ -243,7 +243,7 @@ class MarionetteTextTestRunner(StructuredTestRunner):
|
|||
|
||||
|
||||
class BaseMarionetteArguments(ArgumentParser):
|
||||
socket_timeout_default = 360.0
|
||||
socket_timeout_default = 60.0
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
ArgumentParser.__init__(self, **kwargs)
|
||||
|
|
|
@ -68,7 +68,7 @@ def mach_parsed_kwargs(logger):
|
|||
'server_root': None,
|
||||
'shuffle': False,
|
||||
'shuffle_seed': 2276870381009474531,
|
||||
'socket_timeout': 360.0,
|
||||
'socket_timeout': 60.0,
|
||||
'sources': None,
|
||||
'startup_timeout': 60,
|
||||
'symbols_path': None,
|
||||
|
|
|
@ -42,9 +42,14 @@ function scheduleNextWindow() {
|
|||
}
|
||||
|
||||
function calcMedian( numbers ) {
|
||||
numbers.sort( function (a,b){ return a-b; } );
|
||||
var n = Math.floor( numbers.length / 2 );
|
||||
return numbers.length % 2 ? numbers[n] : ( numbers[n-1] + numbers[n] ) / 2;
|
||||
// Avoid changing the original array.
|
||||
var sortedNumbers = Array.from(numbers);
|
||||
sortedNumbers.sort( function (a,b){ return a-b; } );
|
||||
var n = Math.floor( sortedNumbers.length / 2 );
|
||||
if (sortedNumbers.length % 2) {
|
||||
return sortedNumbers[n];
|
||||
}
|
||||
return ( sortedNumbers[n-1] + sortedNumbers[n] ) / 2;
|
||||
}
|
||||
|
||||
function reportTimes() {
|
||||
|
|
|
@ -16,6 +16,49 @@ namespace mozilla {
|
|||
|
||||
using namespace dom;
|
||||
|
||||
InputData::InputData(InputType aInputType)
|
||||
: mInputType(aInputType)
|
||||
, mTime(0)
|
||||
, modifiers(0)
|
||||
{
|
||||
}
|
||||
|
||||
InputData::InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers)
|
||||
: mInputType(aInputType)
|
||||
, mTime(aTime)
|
||||
, mTimeStamp(aTimeStamp)
|
||||
, modifiers(aModifiers)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData(int32_t aIdentifier, ScreenIntPoint aScreenPoint,
|
||||
ScreenSize aRadius, float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier)
|
||||
, mScreenPoint(aScreenPoint)
|
||||
, mRadius(aRadius)
|
||||
, mRotationAngle(aRotationAngle)
|
||||
, mForce(aForce)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData(int32_t aIdentifier,
|
||||
ParentLayerPoint aLocalScreenPoint,
|
||||
ScreenSize aRadius, float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier)
|
||||
, mLocalScreenPoint(aLocalScreenPoint)
|
||||
, mRadius(aRadius)
|
||||
, mRotationAngle(aRotationAngle)
|
||||
, mForce(aForce)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData()
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Touch> SingleTouchData::ToNewDOMTouch() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
|
@ -28,147 +71,26 @@ already_AddRefed<Touch> SingleTouchData::ToNewDOMTouch() const
|
|||
return touch.forget();
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
|
||||
: InputData(MOUSE_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(aMouseEvent.inputSource)
|
||||
, mButtons(aMouseEvent.buttons)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
MultiTouchInput::MultiTouchInput(MultiTouchType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MULTITOUCH_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetTouchEvent on main thread");
|
||||
|
||||
mButtonType = NONE;
|
||||
|
||||
switch (aMouseEvent.button) {
|
||||
case WidgetMouseEventBase::eLeftButton:
|
||||
mButtonType = MouseInput::LEFT_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eMiddleButton:
|
||||
mButtonType = MouseInput::MIDDLE_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eRightButton:
|
||||
mButtonType = MouseInput::RIGHT_BUTTON;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseMove:
|
||||
mType = MOUSE_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MOUSE_UP;
|
||||
break;
|
||||
case eMouseDown:
|
||||
mType = MOUSE_DOWN;
|
||||
break;
|
||||
case eDragStart:
|
||||
mType = MOUSE_DRAG_START;
|
||||
break;
|
||||
case eDragEnd:
|
||||
mType = MOUSE_DRAG_END;
|
||||
break;
|
||||
case eMouseEnterIntoWidget:
|
||||
mType = MOUSE_WIDGET_ENTER;
|
||||
break;
|
||||
case eMouseExitFromWidget:
|
||||
mType = MOUSE_WIDGET_EXIT;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
mOrigin =
|
||||
ScreenPoint(ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
}
|
||||
|
||||
bool
|
||||
MouseInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
MultiTouchInput::MultiTouchInput()
|
||||
: InputData(MULTITOUCH_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalOrigin = *point;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WidgetMouseEvent
|
||||
MouseInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
MultiTouchInput::MultiTouchInput(const MultiTouchInput& aOther)
|
||||
: InputData(MULTITOUCH_INPUT, aOther.mTime, aOther.mTimeStamp, aOther.modifiers)
|
||||
, mType(aOther.mType)
|
||||
, mHandledByAPZ(aOther.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only convert To WidgetTouchEvent on main thread");
|
||||
|
||||
EventMessage msg = eVoidEvent;
|
||||
uint32_t clickCount = 0;
|
||||
switch (mType) {
|
||||
case MOUSE_MOVE:
|
||||
msg = eMouseMove;
|
||||
break;
|
||||
case MOUSE_UP:
|
||||
msg = eMouseUp;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DOWN:
|
||||
msg = eMouseDown;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DRAG_START:
|
||||
msg = eDragStart;
|
||||
break;
|
||||
case MOUSE_DRAG_END:
|
||||
msg = eDragEnd;
|
||||
break;
|
||||
case MOUSE_WIDGET_ENTER:
|
||||
msg = eMouseEnterIntoWidget;
|
||||
break;
|
||||
case MOUSE_WIDGET_EXIT:
|
||||
msg = eMouseExitFromWidget;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent in MouseInput");
|
||||
break;
|
||||
}
|
||||
|
||||
WidgetMouseEvent event(true, msg, aWidget, WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
|
||||
|
||||
if (msg == eVoidEvent) {
|
||||
return event;
|
||||
}
|
||||
|
||||
switch (mButtonType) {
|
||||
case MouseInput::LEFT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eLeftButton;
|
||||
break;
|
||||
case MouseInput::MIDDLE_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eMiddleButton;
|
||||
break;
|
||||
case MouseInput::RIGHT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eRightButton;
|
||||
break;
|
||||
case MouseInput::NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
event.buttons = mButtons;
|
||||
event.mModifiers = modifiers;
|
||||
event.mTime = mTime;
|
||||
event.mTimeStamp = mTimeStamp;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
event.mRefPoint =
|
||||
RoundedToInt(ViewAs<LayoutDevicePixel>(mOrigin,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
event.mClickCount = clickCount;
|
||||
event.inputSource = mInputSource;
|
||||
event.mIgnoreRootScrollFrame = true;
|
||||
|
||||
return event;
|
||||
mTouches.AppendElements(aOther.mTouches);
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
|
||||
|
@ -218,6 +140,43 @@ MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
|
|||
}
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const WidgetMouseEvent& aMouseEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetMouseEvent on main thread");
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseDown:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case eMouseMove:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
// The mouse pointer has been interrupted in an implementation-specific
|
||||
// manner, such as a synchronous event or action cancelling the touch, or a
|
||||
// touch point leaving the document window and going into a non-document
|
||||
// area capable of handling user interactions.
|
||||
case eMouseExitFromWidget:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
mTouches.AppendElement(SingleTouchData(0,
|
||||
ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
|
||||
ScreenSize(1, 1),
|
||||
180.0f,
|
||||
1.0f));
|
||||
}
|
||||
|
||||
WidgetTouchEvent
|
||||
MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
|
@ -314,49 +273,6 @@ MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// This conversion from WidgetMouseEvent to MultiTouchInput is needed because on
|
||||
// the B2G emulator we can only receive mouse events, but we need to be able
|
||||
// to pan correctly. To do this, we convert the events into a format that the
|
||||
// panning code can handle. This code is very limited and only supports
|
||||
// SingleTouchData. It also sends garbage for the identifier, radius, force
|
||||
// and rotation angle.
|
||||
MultiTouchInput::MultiTouchInput(const WidgetMouseEvent& aMouseEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetMouseEvent on main thread");
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseDown:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case eMouseMove:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
// The mouse pointer has been interrupted in an implementation-specific
|
||||
// manner, such as a synchronous event or action cancelling the touch, or a
|
||||
// touch point leaving the document window and going into a non-document
|
||||
// area capable of handling user interactions.
|
||||
case eMouseExitFromWidget:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
mTouches.AppendElement(SingleTouchData(0,
|
||||
ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
|
||||
ScreenSize(1, 1),
|
||||
180.0f,
|
||||
1.0f));
|
||||
}
|
||||
|
||||
bool
|
||||
MultiTouchInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
|
@ -370,6 +286,210 @@ MultiTouchInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform
|
|||
return true;
|
||||
}
|
||||
|
||||
MouseInput::MouseInput()
|
||||
: InputData(MOUSE_INPUT)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(0)
|
||||
, mButtons(0)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(MouseType aType, ButtonType aButtonType,
|
||||
uint16_t aInputSource, int16_t aButtons,
|
||||
const ScreenPoint& aPoint, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mButtonType(aButtonType)
|
||||
, mInputSource(aInputSource)
|
||||
, mButtons(aButtons)
|
||||
, mOrigin(aPoint)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
|
||||
: InputData(MOUSE_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(aMouseEvent.inputSource)
|
||||
, mButtons(aMouseEvent.buttons)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetTouchEvent on main thread");
|
||||
|
||||
mButtonType = NONE;
|
||||
|
||||
switch (aMouseEvent.button) {
|
||||
case WidgetMouseEventBase::eLeftButton:
|
||||
mButtonType = MouseInput::LEFT_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eMiddleButton:
|
||||
mButtonType = MouseInput::MIDDLE_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eRightButton:
|
||||
mButtonType = MouseInput::RIGHT_BUTTON;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseMove:
|
||||
mType = MOUSE_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MOUSE_UP;
|
||||
break;
|
||||
case eMouseDown:
|
||||
mType = MOUSE_DOWN;
|
||||
break;
|
||||
case eDragStart:
|
||||
mType = MOUSE_DRAG_START;
|
||||
break;
|
||||
case eDragEnd:
|
||||
mType = MOUSE_DRAG_END;
|
||||
break;
|
||||
case eMouseEnterIntoWidget:
|
||||
mType = MOUSE_WIDGET_ENTER;
|
||||
break;
|
||||
case eMouseExitFromWidget:
|
||||
mType = MOUSE_WIDGET_EXIT;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
mOrigin =
|
||||
ScreenPoint(ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
}
|
||||
|
||||
bool
|
||||
MouseInput::IsLeftButton() const
|
||||
{
|
||||
return mButtonType == LEFT_BUTTON;
|
||||
}
|
||||
|
||||
bool
|
||||
MouseInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalOrigin = *point;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WidgetMouseEvent
|
||||
MouseInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only convert To WidgetTouchEvent on main thread");
|
||||
|
||||
EventMessage msg = eVoidEvent;
|
||||
uint32_t clickCount = 0;
|
||||
switch (mType) {
|
||||
case MOUSE_MOVE:
|
||||
msg = eMouseMove;
|
||||
break;
|
||||
case MOUSE_UP:
|
||||
msg = eMouseUp;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DOWN:
|
||||
msg = eMouseDown;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DRAG_START:
|
||||
msg = eDragStart;
|
||||
break;
|
||||
case MOUSE_DRAG_END:
|
||||
msg = eDragEnd;
|
||||
break;
|
||||
case MOUSE_WIDGET_ENTER:
|
||||
msg = eMouseEnterIntoWidget;
|
||||
break;
|
||||
case MOUSE_WIDGET_EXIT:
|
||||
msg = eMouseExitFromWidget;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent in MouseInput");
|
||||
break;
|
||||
}
|
||||
|
||||
WidgetMouseEvent event(true, msg, aWidget, WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
|
||||
|
||||
if (msg == eVoidEvent) {
|
||||
return event;
|
||||
}
|
||||
|
||||
switch (mButtonType) {
|
||||
case MouseInput::LEFT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eLeftButton;
|
||||
break;
|
||||
case MouseInput::MIDDLE_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eMiddleButton;
|
||||
break;
|
||||
case MouseInput::RIGHT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eRightButton;
|
||||
break;
|
||||
case MouseInput::NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
event.buttons = mButtons;
|
||||
event.mModifiers = modifiers;
|
||||
event.mTime = mTime;
|
||||
event.mTimeStamp = mTimeStamp;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
event.mRefPoint =
|
||||
RoundedToInt(ViewAs<LayoutDevicePixel>(mOrigin,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
event.mClickCount = clickCount;
|
||||
event.inputSource = mInputSource;
|
||||
event.mIgnoreRootScrollFrame = true;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
PanGestureInput::PanGestureInput()
|
||||
: InputData(PANGESTURE_INPUT)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mHandledByAPZ(false)
|
||||
, mFollowedByMomentum(false)
|
||||
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
|
||||
PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aPanStartPoint,
|
||||
const ScreenPoint& aPanDisplacement,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mPanStartPoint(aPanStartPoint)
|
||||
, mPanDisplacement(aPanDisplacement)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mHandledByAPZ(false)
|
||||
, mFollowedByMomentum(false)
|
||||
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureInput::IsMomentum() const
|
||||
{
|
||||
|
@ -436,6 +556,37 @@ PanGestureInput::UserMultipliedLocalPanDisplacement() const
|
|||
mLocalPanDisplacement.y * mUserDeltaMultiplierY);
|
||||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput()
|
||||
: InputData(PINCHGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aFocusPoint,
|
||||
float aCurrentSpan, float aPreviousSpan,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mFocusPoint(aFocusPoint)
|
||||
, mCurrentSpan(aCurrentSpan)
|
||||
, mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalFocusPoint,
|
||||
float aCurrentSpan, float aPreviousSpan,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mLocalFocusPoint(aLocalFocusPoint)
|
||||
, mCurrentSpan(aCurrentSpan)
|
||||
, mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PinchGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
|
@ -447,6 +598,31 @@ PinchGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransfo
|
|||
return true;
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput()
|
||||
: InputData(TAPGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenIntPoint& aPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mPoint(aPoint)
|
||||
{
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mLocalPoint(aLocalPoint)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TapGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
|
@ -458,24 +634,45 @@ TapGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform
|
|||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
DeltaModeForDeltaType(ScrollWheelInput::ScrollDeltaType aDeltaType)
|
||||
ScrollWheelInput::ScrollWheelInput()
|
||||
: InputData(SCROLLWHEEL_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
{
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollWheelInput(uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers, ScrollMode aScrollMode,
|
||||
ScrollDeltaType aDeltaType,
|
||||
const ScreenPoint& aOrigin, double aDeltaX,
|
||||
double aDeltaY,
|
||||
bool aAllowToOverrideSystemScrollSpeed)
|
||||
: InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mDeltaType(aDeltaType)
|
||||
, mScrollMode(aScrollMode)
|
||||
, mOrigin(aOrigin)
|
||||
, mHandledByAPZ(false)
|
||||
, mDeltaX(aDeltaX)
|
||||
, mDeltaY(aDeltaY)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
, mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case ScrollWheelInput::SCROLLDELTA_LINE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PAGE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PAGE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PIXEL:
|
||||
default:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PIXEL;
|
||||
}
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent& aWheelEvent)
|
||||
: InputData(SCROLLWHEEL_INPUT,
|
||||
aWheelEvent.mTime,
|
||||
aWheelEvent.mTimeStamp,
|
||||
: InputData(SCROLLWHEEL_INPUT, aWheelEvent.mTime, aWheelEvent.mTimeStamp,
|
||||
aWheelEvent.mModifiers)
|
||||
, mDeltaType(DeltaTypeForDeltaMode(aWheelEvent.mDeltaMode))
|
||||
, mScrollMode(SCROLLMODE_INSTANT)
|
||||
|
@ -497,6 +694,52 @@ ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent& aWheelEvent)
|
|||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollDeltaType
|
||||
ScrollWheelInput::DeltaTypeForDeltaMode(uint32_t aDeltaMode)
|
||||
{
|
||||
switch (aDeltaMode) {
|
||||
case nsIDOMWheelEvent::DOM_DELTA_LINE:
|
||||
return SCROLLDELTA_LINE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PAGE:
|
||||
return SCROLLDELTA_PAGE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PIXEL:
|
||||
return SCROLLDELTA_PIXEL;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return SCROLLDELTA_LINE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case ScrollWheelInput::SCROLLDELTA_LINE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PAGE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PAGE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PIXEL:
|
||||
default:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PIXEL;
|
||||
}
|
||||
}
|
||||
|
||||
nsIScrollableFrame::ScrollUnit
|
||||
ScrollWheelInput::ScrollUnitForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case SCROLLDELTA_LINE:
|
||||
return nsIScrollableFrame::LINES;
|
||||
case SCROLLDELTA_PAGE:
|
||||
return nsIScrollableFrame::PAGES;
|
||||
case SCROLLDELTA_PIXEL:
|
||||
return nsIScrollableFrame::DEVICE_PIXELS;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return nsIScrollableFrame::LINES;
|
||||
}
|
||||
|
||||
WidgetWheelEvent
|
||||
ScrollWheelInput::ToWidgetWheelEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
|
|
|
@ -94,24 +94,11 @@ public:
|
|||
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(ScrollWheelInput, SCROLLWHEEL_INPUT)
|
||||
|
||||
explicit InputData(InputType aInputType)
|
||||
: mInputType(aInputType),
|
||||
mTime(0),
|
||||
modifiers(0)
|
||||
{
|
||||
}
|
||||
explicit InputData(InputType aInputType);
|
||||
|
||||
protected:
|
||||
InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers)
|
||||
: mInputType(aInputType),
|
||||
mTime(aTime),
|
||||
mTimeStamp(aTimeStamp),
|
||||
modifiers(aModifiers)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Modifiers aModifiers);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -138,14 +125,7 @@ public:
|
|||
ScreenIntPoint aScreenPoint,
|
||||
ScreenSize aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier),
|
||||
mScreenPoint(aScreenPoint),
|
||||
mRadius(aRadius),
|
||||
mRotationAngle(aRotationAngle),
|
||||
mForce(aForce)
|
||||
{
|
||||
}
|
||||
float aForce);
|
||||
|
||||
// Construct a SingleTouchData from a ParentLayer point.
|
||||
// mScreenPoint remains (0,0) unless it's set later.
|
||||
|
@ -155,18 +135,9 @@ public:
|
|||
ParentLayerPoint aLocalScreenPoint,
|
||||
ScreenSize aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier),
|
||||
mLocalScreenPoint(aLocalScreenPoint),
|
||||
mRadius(aRadius),
|
||||
mRotationAngle(aRotationAngle),
|
||||
mForce(aForce)
|
||||
{
|
||||
}
|
||||
float aForce);
|
||||
|
||||
SingleTouchData()
|
||||
{
|
||||
}
|
||||
SingleTouchData();
|
||||
|
||||
already_AddRefed<dom::Touch> ToNewDOMTouch() const;
|
||||
|
||||
|
@ -225,36 +196,10 @@ public:
|
|||
};
|
||||
|
||||
MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers)
|
||||
: InputData(MULTITOUCH_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MultiTouchInput()
|
||||
: InputData(MULTITOUCH_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MultiTouchInput(const MultiTouchInput& aOther)
|
||||
: InputData(MULTITOUCH_INPUT, aOther.mTime,
|
||||
aOther.mTimeStamp, aOther.modifiers)
|
||||
, mType(aOther.mType)
|
||||
, mHandledByAPZ(aOther.mHandledByAPZ)
|
||||
{
|
||||
mTouches.AppendElements(aOther.mTouches);
|
||||
}
|
||||
|
||||
Modifiers aModifiers);
|
||||
MultiTouchInput();
|
||||
MultiTouchInput(const MultiTouchInput& aOther);
|
||||
explicit MultiTouchInput(const WidgetTouchEvent& aTouchEvent);
|
||||
WidgetTouchEvent ToWidgetTouchEvent(nsIWidget* aWidget) const;
|
||||
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
|
||||
|
||||
// Return the index into mTouches of the SingleTouchData with the given
|
||||
// identifier, or -1 if there is no such SingleTouchData.
|
||||
int32_t IndexOfTouch(int32_t aTouchIdentifier);
|
||||
|
||||
// This conversion from WidgetMouseEvent to MultiTouchInput is needed because
|
||||
// on the B2G emulator we can only receive mouse events, but we need to be
|
||||
// able to pan correctly. To do this, we convert the events into a format that
|
||||
|
@ -263,6 +208,13 @@ public:
|
|||
// and rotation angle.
|
||||
explicit MultiTouchInput(const WidgetMouseEvent& aMouseEvent);
|
||||
|
||||
WidgetTouchEvent ToWidgetTouchEvent(nsIWidget* aWidget) const;
|
||||
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
|
||||
|
||||
// Return the index into mTouches of the SingleTouchData with the given
|
||||
// identifier, or -1 if there is no such SingleTouchData.
|
||||
int32_t IndexOfTouch(int32_t aTouchIdentifier);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
|
@ -278,14 +230,7 @@ protected:
|
|||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
MouseInput()
|
||||
: InputData(MOUSE_INPUT)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(0)
|
||||
, mButtons(0)
|
||||
, mHandledByAPZ(false)
|
||||
{}
|
||||
MouseInput();
|
||||
|
||||
public:
|
||||
enum MouseType
|
||||
|
@ -318,20 +263,12 @@ public:
|
|||
BUTTON_SENTINEL,
|
||||
};
|
||||
|
||||
MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource, int16_t aButtons, const ScreenPoint& aPoint,
|
||||
uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mButtonType(aButtonType)
|
||||
, mInputSource(aInputSource)
|
||||
, mButtons(aButtons)
|
||||
, mOrigin(aPoint)
|
||||
, mHandledByAPZ(false)
|
||||
{}
|
||||
|
||||
MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource,
|
||||
int16_t aButtons, const ScreenPoint& aPoint, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers);
|
||||
explicit MouseInput(const WidgetMouseEventBase& aMouseEvent);
|
||||
|
||||
bool IsLeftButton() const { return mButtonType == LEFT_BUTTON; }
|
||||
bool IsLeftButton() const;
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
|
||||
|
@ -357,17 +294,7 @@ protected:
|
|||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
PanGestureInput()
|
||||
: InputData(PANGESTURE_INPUT),
|
||||
mLineOrPageDeltaX(0),
|
||||
mLineOrPageDeltaY(0),
|
||||
mUserDeltaMultiplierX(1.0),
|
||||
mUserDeltaMultiplierY(1.0),
|
||||
mHandledByAPZ(false),
|
||||
mFollowedByMomentum(false),
|
||||
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
PanGestureInput();
|
||||
|
||||
public:
|
||||
enum PanGestureType
|
||||
|
@ -427,20 +354,7 @@ public:
|
|||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aPanStartPoint,
|
||||
const ScreenPoint& aPanDisplacement,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mPanStartPoint(aPanStartPoint),
|
||||
mPanDisplacement(aPanDisplacement),
|
||||
mLineOrPageDeltaX(0),
|
||||
mLineOrPageDeltaY(0),
|
||||
mUserDeltaMultiplierX(1.0),
|
||||
mUserDeltaMultiplierY(1.0),
|
||||
mHandledByAPZ(false),
|
||||
mFollowedByMomentum(false),
|
||||
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
Modifiers aModifiers);
|
||||
|
||||
bool IsMomentum() const;
|
||||
|
||||
|
@ -498,10 +412,7 @@ protected:
|
|||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
PinchGestureInput()
|
||||
: InputData(PINCHGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
PinchGestureInput();
|
||||
|
||||
public:
|
||||
enum PinchGestureType
|
||||
|
@ -518,37 +429,16 @@ public:
|
|||
|
||||
// Construct a tap gesture from a Screen point.
|
||||
// mLocalFocusPoint remains (0,0) unless it's set later.
|
||||
PinchGestureInput(PinchGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aFocusPoint,
|
||||
float aCurrentSpan,
|
||||
float aPreviousSpan,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mFocusPoint(aFocusPoint),
|
||||
mCurrentSpan(aCurrentSpan),
|
||||
mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
}
|
||||
PinchGestureInput(PinchGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, const ScreenPoint& aFocusPoint,
|
||||
float aCurrentSpan, float aPreviousSpan,
|
||||
Modifiers aModifiers);
|
||||
|
||||
// Construct a tap gesture from a ParentLayer point.
|
||||
// mFocusPoint remains (0,0) unless it's set later.
|
||||
PinchGestureInput(PinchGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalFocusPoint,
|
||||
float aCurrentSpan,
|
||||
float aPreviousSpan,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mLocalFocusPoint(aLocalFocusPoint),
|
||||
mCurrentSpan(aCurrentSpan),
|
||||
mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
}
|
||||
PinchGestureInput(PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalFocusPoint, float aCurrentSpan,
|
||||
float aPreviousSpan, Modifiers aModifiers);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
|
@ -592,10 +482,7 @@ protected:
|
|||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
TapGestureInput()
|
||||
: InputData(TAPGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
TapGestureInput();
|
||||
|
||||
public:
|
||||
enum TapGestureType
|
||||
|
@ -615,29 +502,13 @@ public:
|
|||
|
||||
// Construct a tap gesture from a Screen point.
|
||||
// mLocalPoint remains (0,0) unless it's set later.
|
||||
TapGestureInput(TapGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenIntPoint& aPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mPoint(aPoint)
|
||||
{
|
||||
}
|
||||
TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ScreenIntPoint& aPoint, Modifiers aModifiers);
|
||||
|
||||
// Construct a tap gesture from a ParentLayer point.
|
||||
// mPoint remains (0,0) unless it's set later.
|
||||
TapGestureInput(TapGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mLocalPoint(aLocalPoint)
|
||||
{
|
||||
}
|
||||
TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalPoint, Modifiers aModifiers);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
|
@ -662,17 +533,7 @@ protected:
|
|||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
ScrollWheelInput()
|
||||
: InputData(SCROLLWHEEL_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
{}
|
||||
ScrollWheelInput();
|
||||
|
||||
public:
|
||||
enum ScrollDeltaType
|
||||
|
@ -690,38 +551,6 @@ public:
|
|||
SCROLLDELTA_SENTINEL,
|
||||
};
|
||||
|
||||
static ScrollDeltaType
|
||||
DeltaTypeForDeltaMode(uint32_t aDeltaMode)
|
||||
{
|
||||
switch (aDeltaMode) {
|
||||
case nsIDOMWheelEvent::DOM_DELTA_LINE:
|
||||
return SCROLLDELTA_LINE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PAGE:
|
||||
return SCROLLDELTA_PAGE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PIXEL:
|
||||
return SCROLLDELTA_PIXEL;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return SCROLLDELTA_LINE;
|
||||
}
|
||||
|
||||
static nsIScrollableFrame::ScrollUnit
|
||||
ScrollUnitForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case SCROLLDELTA_LINE:
|
||||
return nsIScrollableFrame::LINES;
|
||||
case SCROLLDELTA_PAGE:
|
||||
return nsIScrollableFrame::PAGES;
|
||||
case SCROLLDELTA_PIXEL:
|
||||
return nsIScrollableFrame::DEVICE_PIXELS;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return nsIScrollableFrame::LINES;
|
||||
}
|
||||
|
||||
enum ScrollMode
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
|
@ -734,34 +563,16 @@ public:
|
|||
SCROLLMODE_SENTINEL,
|
||||
};
|
||||
|
||||
ScrollWheelInput(uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers,
|
||||
ScrollMode aScrollMode,
|
||||
ScrollDeltaType aDeltaType,
|
||||
const ScreenPoint& aOrigin,
|
||||
double aDeltaX,
|
||||
double aDeltaY,
|
||||
bool aAllowToOverrideSystemScrollSpeed)
|
||||
: InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mDeltaType(aDeltaType)
|
||||
, mScrollMode(aScrollMode)
|
||||
, mOrigin(aOrigin)
|
||||
, mHandledByAPZ(false)
|
||||
, mDeltaX(aDeltaX)
|
||||
, mDeltaY(aDeltaY)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
, mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed)
|
||||
{}
|
||||
|
||||
ScrollWheelInput(uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers,
|
||||
ScrollMode aScrollMode, ScrollDeltaType aDeltaType,
|
||||
const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY,
|
||||
bool aAllowToOverrideSystemScrollSpeed);
|
||||
explicit ScrollWheelInput(const WidgetWheelEvent& aEvent);
|
||||
|
||||
static ScrollDeltaType DeltaTypeForDeltaMode(uint32_t aDeltaMode);
|
||||
static uint32_t DeltaModeForDeltaType(ScrollDeltaType aDeltaType);
|
||||
static nsIScrollableFrame::ScrollUnit ScrollUnitForDeltaType(ScrollDeltaType aDeltaType);
|
||||
|
||||
WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче