mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Merge inbound to m-c. a=merge
This commit is contained in:
commit
75fa1fd85f
@ -217,6 +217,7 @@ dom/messagechannel/**
|
|||||||
dom/network/**
|
dom/network/**
|
||||||
dom/notification/**
|
dom/notification/**
|
||||||
dom/offline/**
|
dom/offline/**
|
||||||
|
dom/payments/**
|
||||||
dom/performance/**
|
dom/performance/**
|
||||||
dom/permission/**
|
dom/permission/**
|
||||||
dom/plugins/**
|
dom/plugins/**
|
||||||
|
@ -213,6 +213,7 @@
|
|||||||
@RESPATH@/components/dom_html.xpt
|
@RESPATH@/components/dom_html.xpt
|
||||||
@RESPATH@/components/dom_offline.xpt
|
@RESPATH@/components/dom_offline.xpt
|
||||||
@RESPATH@/components/dom_json.xpt
|
@RESPATH@/components/dom_json.xpt
|
||||||
|
@RESPATH@/components/dom_payments.xpt
|
||||||
@RESPATH@/components/dom_power.xpt
|
@RESPATH@/components/dom_power.xpt
|
||||||
@RESPATH@/components/dom_push.xpt
|
@RESPATH@/components/dom_push.xpt
|
||||||
@RESPATH@/components/dom_quota.xpt
|
@RESPATH@/components/dom_quota.xpt
|
||||||
|
@ -19,10 +19,6 @@ const childProcessMessageManager =
|
|||||||
Cc["@mozilla.org/childprocessmessagemanager;1"]
|
Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||||
.getService(Ci.nsISyncMessageSender);
|
.getService(Ci.nsISyncMessageSender);
|
||||||
|
|
||||||
// Amount of space that will be allocated for the stream's backing-store.
|
|
||||||
// Must be power of 2. Used to copy the data stream in onStopRequest.
|
|
||||||
const SEGMENT_SIZE = Math.pow(2, 17);
|
|
||||||
|
|
||||||
// Localization
|
// Localization
|
||||||
loader.lazyGetter(this, "jsonViewStrings", () => {
|
loader.lazyGetter(this, "jsonViewStrings", () => {
|
||||||
return Services.strings.createBundle(
|
return Services.strings.createBundle(
|
||||||
@ -54,9 +50,9 @@ Converter.prototype = {
|
|||||||
* 1. asyncConvertData captures the listener
|
* 1. asyncConvertData captures the listener
|
||||||
* 2. onStartRequest fires, initializes stuff, modifies the listener
|
* 2. onStartRequest fires, initializes stuff, modifies the listener
|
||||||
* to match our output type
|
* to match our output type
|
||||||
* 3. onDataAvailable transcodes the data into a UTF-8 string
|
* 3. onDataAvailable spits it back to the listener
|
||||||
* 4. onStopRequest gets the collected data and converts it,
|
* 4. onStopRequest spits it back to the listener and initializes
|
||||||
* spits it to the listener
|
the JSON Viewer
|
||||||
* 5. convert does nothing, it's just the synchronous version
|
* 5. convert does nothing, it's just the synchronous version
|
||||||
* of asyncConvertData
|
* of asyncConvertData
|
||||||
*/
|
*/
|
||||||
@ -69,32 +65,11 @@ Converter.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onDataAvailable: function (request, context, inputStream, offset, count) {
|
onDataAvailable: function (request, context, inputStream, offset, count) {
|
||||||
// From https://developer.mozilla.org/en/Reading_textual_data
|
this.listener.onDataAvailable(...arguments);
|
||||||
let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
|
||||||
.createInstance(Ci.nsIConverterInputStream);
|
|
||||||
is.init(inputStream, this.charset, -1,
|
|
||||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
|
||||||
|
|
||||||
// Seed it with something positive
|
|
||||||
while (count) {
|
|
||||||
let str = {};
|
|
||||||
let bytesRead = is.readString(count, str);
|
|
||||||
if (!bytesRead) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
count -= bytesRead;
|
|
||||||
this.data += str.value;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onStartRequest: function (request, context) {
|
onStartRequest: function (request, context) {
|
||||||
this.data = "";
|
this.channel = request;
|
||||||
this.uri = request.QueryInterface(Ci.nsIChannel).URI.spec;
|
|
||||||
|
|
||||||
// Sets the charset if it is available. (For documents loaded from the
|
|
||||||
// filesystem, this is not set.)
|
|
||||||
this.charset =
|
|
||||||
request.QueryInterface(Ci.nsIChannel).contentCharset || "UTF-8";
|
|
||||||
|
|
||||||
// Let "save as" save the original JSON, not the viewer.
|
// Let "save as" save the original JSON, not the viewer.
|
||||||
// To save with the proper extension we need the original content type,
|
// To save with the proper extension we need the original content type,
|
||||||
@ -102,12 +77,14 @@ Converter.prototype = {
|
|||||||
let originalType;
|
let originalType;
|
||||||
if (request instanceof Ci.nsIHttpChannel) {
|
if (request instanceof Ci.nsIHttpChannel) {
|
||||||
try {
|
try {
|
||||||
originalType = request.getResponseHeader("Content-Type");
|
let header = request.getResponseHeader("Content-Type");
|
||||||
|
originalType = header.split(";")[0];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Handled below
|
// Handled below
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let match = this.uri.match(/^data:(.*?)[,;]/);
|
let uri = request.QueryInterface(Ci.nsIChannel).URI.spec;
|
||||||
|
let match = uri.match(/^data:(.*?)[,;]/);
|
||||||
if (match) {
|
if (match) {
|
||||||
originalType = match[1];
|
originalType = match[1];
|
||||||
}
|
}
|
||||||
@ -119,33 +96,21 @@ Converter.prototype = {
|
|||||||
request.QueryInterface(Ci.nsIWritablePropertyBag);
|
request.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||||
request.setProperty("contentType", originalType);
|
request.setProperty("contentType", originalType);
|
||||||
|
|
||||||
this.channel = request;
|
// Parse source as JSON. This is like text/plain, but enforcing
|
||||||
this.channel.contentType = "text/html";
|
// UTF-8 charset (see bug 741776).
|
||||||
this.channel.contentCharset = "UTF-8";
|
request.QueryInterface(Ci.nsIChannel);
|
||||||
|
request.contentType = JSON_TYPES[0];
|
||||||
|
this.charset = request.contentCharset = "UTF-8";
|
||||||
|
|
||||||
// Because content might still have a reference to this window,
|
// Because content might still have a reference to this window,
|
||||||
// force setting it to a null principal to avoid it being same-
|
// force setting it to a null principal to avoid it being same-
|
||||||
// origin with (other) content.
|
// origin with (other) content.
|
||||||
this.channel.loadInfo.resetPrincipalToInheritToNullPrincipal();
|
request.loadInfo.resetPrincipalToInheritToNullPrincipal();
|
||||||
|
|
||||||
this.listener.onStartRequest(this.channel, context);
|
this.listener.onStartRequest(request, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* This should go something like this:
|
|
||||||
* 1. Make sure we have a unicode string.
|
|
||||||
* 2. Convert it to a Javascript object.
|
|
||||||
* 2.1 Removes the callback
|
|
||||||
* 3. Convert that to HTML? Or XUL?
|
|
||||||
* 4. Spit it back out at the listener
|
|
||||||
*/
|
|
||||||
onStopRequest: function (request, context, statusCode) {
|
onStopRequest: function (request, context, statusCode) {
|
||||||
let headers = {
|
|
||||||
response: [],
|
|
||||||
request: []
|
|
||||||
};
|
|
||||||
|
|
||||||
let win = NetworkHelper.getWindowForRequest(request);
|
|
||||||
|
|
||||||
let Locale = {
|
let Locale = {
|
||||||
$STR: key => {
|
$STR: key => {
|
||||||
try {
|
try {
|
||||||
@ -157,13 +122,10 @@ Converter.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
|
let headers = {
|
||||||
|
response: [],
|
||||||
win.addEventListener("DOMContentLoaded", event => {
|
request: []
|
||||||
win.addEventListener("contentMessage",
|
};
|
||||||
this.onContentMessage.bind(this), false, true);
|
|
||||||
}, {once: true});
|
|
||||||
|
|
||||||
// The request doesn't have to be always nsIHttpChannel
|
// The request doesn't have to be always nsIHttpChannel
|
||||||
// (e.g. in case of data: URLs)
|
// (e.g. in case of data: URLs)
|
||||||
if (request instanceof Ci.nsIHttpChannel) {
|
if (request instanceof Ci.nsIHttpChannel) {
|
||||||
@ -172,7 +134,6 @@ Converter.prototype = {
|
|||||||
headers.response.push({name: name, value: value});
|
headers.response.push({name: name, value: value});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
request.visitRequestHeaders({
|
request.visitRequestHeaders({
|
||||||
visitHeader: function (name, value) {
|
visitHeader: function (name, value) {
|
||||||
headers.request.push({name: name, value: value});
|
headers.request.push({name: name, value: value});
|
||||||
@ -180,117 +141,23 @@ Converter.prototype = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputDoc = "";
|
let win = NetworkHelper.getWindowForRequest(request);
|
||||||
|
JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
|
||||||
|
JsonViewUtils.exportIntoContentScope(win, headers, "headers");
|
||||||
|
|
||||||
try {
|
win.addEventListener("DOMContentLoaded", event => {
|
||||||
headers = JSON.stringify(headers);
|
win.addEventListener("contentMessage",
|
||||||
outputDoc = this.toHTML(this.data, headers);
|
onContentMessage.bind(this), false, true);
|
||||||
} catch (e) {
|
loadJsonViewer(win.document);
|
||||||
console.error("JSON Viewer ERROR " + e);
|
}, {once: true});
|
||||||
outputDoc = this.toErrorPage(e, this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
let storage = Cc["@mozilla.org/storagestream;1"]
|
|
||||||
.createInstance(Ci.nsIStorageStream);
|
|
||||||
|
|
||||||
storage.init(SEGMENT_SIZE, 0xffffffff, null);
|
|
||||||
let out = storage.getOutputStream(0);
|
|
||||||
|
|
||||||
let binout = Cc["@mozilla.org/binaryoutputstream;1"]
|
|
||||||
.createInstance(Ci.nsIBinaryOutputStream);
|
|
||||||
|
|
||||||
binout.setOutputStream(out);
|
|
||||||
binout.writeUtf8Z(outputDoc);
|
|
||||||
binout.close();
|
|
||||||
|
|
||||||
// We need to trim 4 bytes off the front (this could be underlying bug).
|
|
||||||
let trunc = 4;
|
|
||||||
let instream = storage.newInputStream(trunc);
|
|
||||||
|
|
||||||
// Pass the data to the main content listener
|
|
||||||
this.listener.onDataAvailable(this.channel, context, instream, 0,
|
|
||||||
instream.available());
|
|
||||||
|
|
||||||
this.listener.onStopRequest(this.channel, context, statusCode);
|
this.listener.onStopRequest(this.channel, context, statusCode);
|
||||||
|
|
||||||
this.listener = null;
|
this.listener = null;
|
||||||
},
|
|
||||||
|
|
||||||
htmlEncode: function (t) {
|
|
||||||
return t !== null ? t.toString()
|
|
||||||
.replace(/&/g, "&")
|
|
||||||
.replace(/"/g, """)
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">") : "";
|
|
||||||
},
|
|
||||||
|
|
||||||
toHTML: function (json, headers) {
|
|
||||||
let themeClassName = "theme-" + JsonViewUtils.getCurrentTheme();
|
|
||||||
let clientBaseUrl = "resource://devtools/client/";
|
|
||||||
let baseUrl = clientBaseUrl + "jsonview/";
|
|
||||||
let themeVarsUrl = clientBaseUrl + "themes/variables.css";
|
|
||||||
let commonUrl = clientBaseUrl + "themes/common.css";
|
|
||||||
let toolbarsUrl = clientBaseUrl + "themes/toolbars.css";
|
|
||||||
|
|
||||||
let os;
|
|
||||||
let platform = Services.appinfo.OS;
|
|
||||||
if (platform.startsWith("WINNT")) {
|
|
||||||
os = "win";
|
|
||||||
} else if (platform.startsWith("Darwin")) {
|
|
||||||
os = "mac";
|
|
||||||
} else {
|
|
||||||
os = "linux";
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
|
|
||||||
|
|
||||||
return "<!DOCTYPE html>\n" +
|
|
||||||
"<html platform=\"" + os + "\" class=\"" + themeClassName +
|
|
||||||
"\" dir=\"" + dir + "\">" +
|
|
||||||
"<head>" +
|
|
||||||
"<base href=\"" + this.htmlEncode(baseUrl) + "\">" +
|
|
||||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
|
|
||||||
themeVarsUrl + "\">" +
|
|
||||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
|
|
||||||
commonUrl + "\">" +
|
|
||||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
|
|
||||||
toolbarsUrl + "\">" +
|
|
||||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"css/main.css\">" +
|
|
||||||
"<script data-main=\"viewer-config\" src=\"lib/require.js\"></script>" +
|
|
||||||
"</head><body>" +
|
|
||||||
"<div id=\"content\">" +
|
|
||||||
"<pre id=\"json\">" + this.htmlEncode(json) + "</pre>" +
|
|
||||||
"</div><div id=\"headers\">" + this.htmlEncode(headers) + "</div>" +
|
|
||||||
"</body></html>";
|
|
||||||
},
|
|
||||||
|
|
||||||
toErrorPage: function (error, data) {
|
|
||||||
// Escape unicode nulls
|
|
||||||
data = data.replace("\u0000", "\uFFFD");
|
|
||||||
|
|
||||||
let errorInfo = error + "";
|
|
||||||
|
|
||||||
let output = "<div id=\"error\">" + "error parsing";
|
|
||||||
if (errorInfo.message) {
|
|
||||||
output += "<div class=\"errormessage\">" + errorInfo.message + "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
output += "</div><div id=\"json\">" + this.highlightError(data,
|
|
||||||
errorInfo.line, errorInfo.column) + "</div>";
|
|
||||||
|
|
||||||
let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
|
|
||||||
|
|
||||||
return "<!DOCTYPE html>\n" +
|
|
||||||
"<html><head>" +
|
|
||||||
"<base href=\"" + this.htmlEncode(this.data.url()) + "\">" +
|
|
||||||
"</head><body dir=\"" + dir + "\">" +
|
|
||||||
output +
|
|
||||||
"</body></html>";
|
|
||||||
},
|
|
||||||
|
|
||||||
// Chrome <-> Content communication
|
// Chrome <-> Content communication
|
||||||
|
function onContentMessage(e) {
|
||||||
onContentMessage: function (e) {
|
|
||||||
// Do not handle events from different documents.
|
// Do not handle events from different documents.
|
||||||
let win = NetworkHelper.getWindowForRequest(this.channel);
|
let win = NetworkHelper.getWindowForRequest(this.channel);
|
||||||
if (win != e.target) {
|
if (win != e.target) {
|
||||||
@ -304,7 +171,7 @@ Converter.prototype = {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "copy-headers":
|
case "copy-headers":
|
||||||
this.copyHeaders(win, value);
|
copyHeaders(win, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "save":
|
case "save":
|
||||||
@ -314,9 +181,56 @@ Converter.prototype = {
|
|||||||
childProcessMessageManager.sendAsyncMessage(
|
childProcessMessageManager.sendAsyncMessage(
|
||||||
"devtools:jsonview:save", {url: value, windowID: windowID});
|
"devtools:jsonview:save", {url: value, windowID: windowID});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
copyHeaders: function (win, headers) {
|
// Loads the JSON Viewer into a text/plain document
|
||||||
|
function loadJsonViewer(doc) {
|
||||||
|
function addStyleSheet(url) {
|
||||||
|
let link = doc.createElement("link");
|
||||||
|
link.rel = "stylesheet";
|
||||||
|
link.type = "text/css";
|
||||||
|
link.href = url;
|
||||||
|
doc.head.appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
let os;
|
||||||
|
let platform = Services.appinfo.OS;
|
||||||
|
if (platform.startsWith("WINNT")) {
|
||||||
|
os = "win";
|
||||||
|
} else if (platform.startsWith("Darwin")) {
|
||||||
|
os = "mac";
|
||||||
|
} else {
|
||||||
|
os = "linux";
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.documentElement.setAttribute("platform", os);
|
||||||
|
doc.documentElement.dataset.contentType = doc.contentType;
|
||||||
|
doc.documentElement.classList.add("theme-" + JsonViewUtils.getCurrentTheme());
|
||||||
|
doc.documentElement.dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
|
||||||
|
|
||||||
|
let base = doc.createElement("base");
|
||||||
|
base.href = "resource://devtools/client/jsonview/";
|
||||||
|
doc.head.appendChild(base);
|
||||||
|
|
||||||
|
addStyleSheet("../themes/variables.css");
|
||||||
|
addStyleSheet("../themes/common.css");
|
||||||
|
addStyleSheet("../themes/toolbars.css");
|
||||||
|
addStyleSheet("css/main.css");
|
||||||
|
|
||||||
|
let json = doc.querySelector("pre");
|
||||||
|
json.id = "json";
|
||||||
|
let content = doc.createElement("div");
|
||||||
|
content.id = "content";
|
||||||
|
content.appendChild(json);
|
||||||
|
doc.body.appendChild(content);
|
||||||
|
|
||||||
|
let script = doc.createElement("script");
|
||||||
|
script.src = "lib/require.js";
|
||||||
|
script.dataset.main = "viewer-config";
|
||||||
|
doc.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyHeaders(win, headers) {
|
||||||
let value = "";
|
let value = "";
|
||||||
let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
|
let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
|
||||||
|
|
||||||
@ -336,7 +250,6 @@ Converter.prototype = {
|
|||||||
|
|
||||||
copyString(win, value);
|
copyString(win, value);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function copyString(win, string) {
|
function copyString(win, string) {
|
||||||
win.document.addEventListener("copy", event => {
|
win.document.addEventListener("copy", event => {
|
||||||
|
@ -35,10 +35,6 @@ pre {
|
|||||||
margin: 8px;
|
margin: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headers {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Dark Theme */
|
/* Dark Theme */
|
||||||
|
|
||||||
@ -50,3 +46,10 @@ body.theme-dark {
|
|||||||
.theme-dark pre {
|
.theme-dark pre {
|
||||||
background-color: var(--theme-body-background);
|
background-color: var(--theme-body-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Fixes for quirks mode */
|
||||||
|
|
||||||
|
table {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
@ -12,7 +12,6 @@ define(function (require, exports, module) {
|
|||||||
const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
|
const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
|
||||||
|
|
||||||
const json = document.getElementById("json");
|
const json = document.getElementById("json");
|
||||||
const headers = document.getElementById("headers");
|
|
||||||
|
|
||||||
let jsonData;
|
let jsonData;
|
||||||
let prettyURL;
|
let prettyURL;
|
||||||
@ -28,13 +27,12 @@ define(function (require, exports, module) {
|
|||||||
jsonText: json.textContent,
|
jsonText: json.textContent,
|
||||||
jsonPretty: null,
|
jsonPretty: null,
|
||||||
json: jsonData,
|
json: jsonData,
|
||||||
headers: JSON.parse(headers.textContent),
|
headers: window.headers,
|
||||||
tabActive: 0,
|
tabActive: 0,
|
||||||
prettified: false
|
prettified: false
|
||||||
};
|
};
|
||||||
|
|
||||||
json.remove();
|
json.remove();
|
||||||
headers.remove();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application actions/commands. This list implements all commands
|
* Application actions/commands. This list implements all commands
|
||||||
|
@ -32,6 +32,8 @@ exports.exportIntoContentScope = function (win, obj, defineAs) {
|
|||||||
Cu.exportFunction(propValue, clone, {
|
Cu.exportFunction(propValue, clone, {
|
||||||
defineAs: propName
|
defineAs: propName
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
clone[propName] = Cu.cloneInto(propValue, win);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -27,6 +27,15 @@ let EnvironmentActor = ActorClassWithSpec(environmentSpec, {
|
|||||||
this.threadActor = threadActor;
|
this.threadActor = threadActor;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the Environment Actor is destroyed it removes the
|
||||||
|
* Debugger.Environment.actor field so that environment does not
|
||||||
|
* reference a destroyed actor.
|
||||||
|
*/
|
||||||
|
destroy: function () {
|
||||||
|
this.obj.actor = null;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an environment form for use in a protocol message.
|
* Return an environment form for use in a protocol message.
|
||||||
*/
|
*/
|
||||||
|
@ -231,6 +231,14 @@ function setBreakpoint(sourceClient, location) {
|
|||||||
return sourceClient.setBreakpoint(location);
|
return sourceClient.setBreakpoint(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPrototypeAndProperties(objClient) {
|
||||||
|
dump("getting prototype and properties.\n");
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
objClient.getPrototypeAndProperties(response => resolve(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function dumpn(msg) {
|
function dumpn(msg) {
|
||||||
dump("DBG-TEST: " + msg + "\n");
|
dump("DBG-TEST: " + msg + "\n");
|
||||||
}
|
}
|
||||||
@ -694,6 +702,16 @@ function executeOnNextTickAndWaitForPause(action, client) {
|
|||||||
return paused;
|
return paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function evalCallback(debuggeeGlobal, func) {
|
||||||
|
Components.utils.evalInSandbox(
|
||||||
|
"(" + func + ")()",
|
||||||
|
debuggeeGlobal,
|
||||||
|
"1.8",
|
||||||
|
"test.js",
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interrupt JS execution for the specified thread.
|
* Interrupt JS execution for the specified thread.
|
||||||
*
|
*
|
||||||
|
61
devtools/server/tests/unit/test_objectgrips-14.js
Normal file
61
devtools/server/tests/unit/test_objectgrips-14.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test out of scope objects with synchronous functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-object-grip");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect().then(function () {
|
||||||
|
attachTestTabAndResume(gClient, "test-object-grip",
|
||||||
|
function (response, tabClient, threadClient) {
|
||||||
|
gThreadClient = threadClient;
|
||||||
|
testObjectGroup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function evalCode() {
|
||||||
|
evalCallback(gDebuggee, function runTest() {
|
||||||
|
let ugh = [];
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
(function () {
|
||||||
|
ugh.push(i++);
|
||||||
|
debugger;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const testObjectGroup = Task.async(function* () {
|
||||||
|
let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||||
|
|
||||||
|
const ugh = packet.frame.environment.parent.parent.bindings.variables.ugh;
|
||||||
|
const ughClient = yield gThreadClient.pauseGrip(ugh.value);
|
||||||
|
|
||||||
|
packet = yield getPrototypeAndProperties(ughClient);
|
||||||
|
packet = yield resumeAndWaitForPause(gClient, gThreadClient);
|
||||||
|
|
||||||
|
const ugh2 = packet.frame.environment.bindings.variables.ugh;
|
||||||
|
const ugh2Client = gThreadClient.pauseGrip(ugh2.value);
|
||||||
|
|
||||||
|
packet = yield getPrototypeAndProperties(ugh2Client);
|
||||||
|
do_check_eq(packet.ownProperties.length.value, 1);
|
||||||
|
|
||||||
|
yield resume(gThreadClient);
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
59
devtools/server/tests/unit/test_objectgrips-15.js
Normal file
59
devtools/server/tests/unit/test_objectgrips-15.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test out of scope objects with async functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gDebuggee;
|
||||||
|
var gClient;
|
||||||
|
var gThreadClient;
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = addTestGlobal("test-object-grip");
|
||||||
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
gClient.connect().then(function () {
|
||||||
|
attachTestTabAndResume(gClient, "test-object-grip",
|
||||||
|
function (response, tabClient, threadClient) {
|
||||||
|
gThreadClient = threadClient;
|
||||||
|
testObjectGroup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function evalCode() {
|
||||||
|
evalCallback(gDebuggee, function runTest() {
|
||||||
|
let ugh = [];
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
function foo() {
|
||||||
|
ugh.push(i++);
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.resolve().then(foo).then(foo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const testObjectGroup = Task.async(function* () {
|
||||||
|
let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||||
|
|
||||||
|
const ugh = packet.frame.environment.parent.bindings.variables.ugh;
|
||||||
|
const ughClient = yield gThreadClient.pauseGrip(ugh.value);
|
||||||
|
|
||||||
|
packet = yield getPrototypeAndProperties(ughClient);
|
||||||
|
|
||||||
|
packet = yield resumeAndWaitForPause(gClient, gThreadClient);
|
||||||
|
const ugh2 = packet.frame.environment.parent.bindings.variables.ugh;
|
||||||
|
const ugh2Client = gThreadClient.pauseGrip(ugh2.value);
|
||||||
|
|
||||||
|
packet = yield getPrototypeAndProperties(ugh2Client);
|
||||||
|
do_check_eq(packet.ownProperties.length.value, 2);
|
||||||
|
|
||||||
|
yield resume(gThreadClient);
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
@ -169,6 +169,8 @@ reason = only ran on B2G
|
|||||||
[test_objectgrips-11.js]
|
[test_objectgrips-11.js]
|
||||||
[test_objectgrips-12.js]
|
[test_objectgrips-12.js]
|
||||||
[test_objectgrips-13.js]
|
[test_objectgrips-13.js]
|
||||||
|
[test_objectgrips-14.js]
|
||||||
|
[test_objectgrips-15.js]
|
||||||
[test_promise_state-01.js]
|
[test_promise_state-01.js]
|
||||||
[test_promise_state-02.js]
|
[test_promise_state-02.js]
|
||||||
[test_promise_state-03.js]
|
[test_promise_state-03.js]
|
||||||
|
@ -958,6 +958,8 @@ GK_ATOM(onselectstart, "onselectstart")
|
|||||||
GK_ATOM(onsending, "onsending")
|
GK_ATOM(onsending, "onsending")
|
||||||
GK_ATOM(onsent, "onsent")
|
GK_ATOM(onsent, "onsent")
|
||||||
GK_ATOM(onset, "onset")
|
GK_ATOM(onset, "onset")
|
||||||
|
GK_ATOM(onshippingaddresschange, "onshippingaddresschange")
|
||||||
|
GK_ATOM(onshippingoptionchange, "onshippingoptionchange")
|
||||||
GK_ATOM(onshow, "onshow")
|
GK_ATOM(onshow, "onshow")
|
||||||
GK_ATOM(onstatechange, "onstatechange")
|
GK_ATOM(onstatechange, "onstatechange")
|
||||||
GK_ATOM(onstatuschanged, "onstatuschanged")
|
GK_ATOM(onstatuschanged, "onstatuschanged")
|
||||||
|
@ -1575,7 +1575,7 @@ nsJSContext::BeginCycleCollectionCallback()
|
|||||||
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
||||||
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
|
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
|
||||||
kICCIntersliceDelay,
|
kICCIntersliceDelay,
|
||||||
nsITimer::TYPE_REPEATING_SLACK,
|
nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
|
||||||
"ICCTimerFired");
|
"ICCTimerFired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1989,7 +1989,7 @@ nsJSContext::PokeGC(JS::gcreason::Reason aReason,
|
|||||||
: (first
|
: (first
|
||||||
? NS_FIRST_GC_DELAY
|
? NS_FIRST_GC_DELAY
|
||||||
: NS_GC_DELAY),
|
: NS_GC_DELAY),
|
||||||
nsITimer::TYPE_ONE_SHOT,
|
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
|
||||||
"GCTimerFired");
|
"GCTimerFired");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
@ -2012,7 +2012,7 @@ nsJSContext::PokeShrinkingGC()
|
|||||||
sShrinkingGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
sShrinkingGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
||||||
sShrinkingGCTimer->InitWithNamedFuncCallback(ShrinkingGCTimerFired, nullptr,
|
sShrinkingGCTimer->InitWithNamedFuncCallback(ShrinkingGCTimerFired, nullptr,
|
||||||
sCompactOnUserInactiveDelay,
|
sCompactOnUserInactiveDelay,
|
||||||
nsITimer::TYPE_ONE_SHOT,
|
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
|
||||||
"ShrinkingGCTimerFired");
|
"ShrinkingGCTimerFired");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2036,7 +2036,7 @@ nsJSContext::MaybePokeCC()
|
|||||||
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
||||||
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
|
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
|
||||||
NS_CC_SKIPPABLE_DELAY,
|
NS_CC_SKIPPABLE_DELAY,
|
||||||
nsITimer::TYPE_REPEATING_SLACK,
|
nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
|
||||||
"CCTimerFired");
|
"CCTimerFired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2188,7 +2188,7 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
|
|||||||
sFullGCTimer->InitWithNamedFuncCallback(FullGCTimerFired,
|
sFullGCTimer->InitWithNamedFuncCallback(FullGCTimerFired,
|
||||||
nullptr,
|
nullptr,
|
||||||
NS_FULL_GC_DELAY,
|
NS_FULL_GC_DELAY,
|
||||||
nsITimer::TYPE_ONE_SHOT,
|
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
|
||||||
"FullGCTimerFired");
|
"FullGCTimerFired");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2219,7 +2219,7 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
|
|||||||
sInterSliceGCTimer->InitWithNamedFuncCallback(InterSliceGCTimerFired,
|
sInterSliceGCTimer->InitWithNamedFuncCallback(InterSliceGCTimerFired,
|
||||||
nullptr,
|
nullptr,
|
||||||
NS_INTERSLICE_GC_DELAY,
|
NS_INTERSLICE_GC_DELAY,
|
||||||
nsITimer::TYPE_ONE_SHOT,
|
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
|
||||||
"InterSliceGCTimerFired");
|
"InterSliceGCTimerFired");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2630,7 +2630,7 @@ nsJSContext::NotifyDidPaint()
|
|||||||
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
||||||
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
|
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
|
||||||
kICCIntersliceDelay,
|
kICCIntersliceDelay,
|
||||||
nsITimer::TYPE_REPEATING_SLACK,
|
nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
|
||||||
"ICCTimerFired");
|
"ICCTimerFired");
|
||||||
}
|
}
|
||||||
} else if (sCCTimer) {
|
} else if (sCCTimer) {
|
||||||
@ -2649,7 +2649,7 @@ nsJSContext::NotifyDidPaint()
|
|||||||
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
|
||||||
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
|
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
|
||||||
NS_CC_SKIPPABLE_DELAY,
|
NS_CC_SKIPPABLE_DELAY,
|
||||||
nsITimer::TYPE_REPEATING_SLACK,
|
nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
|
||||||
"CCTimerFired");
|
"CCTimerFired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,7 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||||||
js::MemoryReportingSundriesThreshold();
|
js::MemoryReportingSundriesThreshold();
|
||||||
|
|
||||||
size_t frameSundriesSize = 0;
|
size_t frameSundriesSize = 0;
|
||||||
#define FRAME_ID(classname) \
|
#define FRAME_ID(classname, ...) \
|
||||||
{ \
|
{ \
|
||||||
size_t frameSize \
|
size_t frameSize \
|
||||||
= windowSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname); \
|
= windowSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname); \
|
||||||
@ -421,8 +421,10 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||||||
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
|
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
|
||||||
+= frameSize; \
|
+= frameSize; \
|
||||||
}
|
}
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
|
|
||||||
if (frameSundriesSize > 0) {
|
if (frameSundriesSize > 0) {
|
||||||
REPORT_SIZE("/layout/frames/sundries", frameSundriesSize,
|
REPORT_SIZE("/layout/frames/sundries", frameSundriesSize,
|
||||||
@ -564,10 +566,12 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||||||
"This is the sum of all windows' 'layout/pres-contexts' numbers.");
|
"This is the sum of all windows' 'layout/pres-contexts' numbers.");
|
||||||
|
|
||||||
size_t frameTotal = 0;
|
size_t frameTotal = 0;
|
||||||
#define FRAME_ID(classname) \
|
#define FRAME_ID(classname, ...) \
|
||||||
frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
|
frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
|
|
||||||
REPORT("window-objects/layout/frames", frameTotal,
|
REPORT("window-objects/layout/frames", frameTotal,
|
||||||
"Memory used for layout frames within windows. "
|
"Memory used for layout frames within windows. "
|
||||||
|
@ -33,6 +33,7 @@ MSG_DEF(MSG_METHOD_THIS_UNWRAPPING_DENIED, 1, JSEXN_TYPEERR, "Permission to call
|
|||||||
MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" object does not implement interface {0}.")
|
MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" object does not implement interface {0}.")
|
||||||
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
|
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
|
||||||
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
|
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
|
||||||
|
MSG_DEF(MSG_ILLEGAL_PR_CONSTRUCTOR, 1, JSEXN_TYPEERR, "TypeError:{0}")
|
||||||
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
|
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
|
||||||
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
|
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
|
||||||
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
|
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
|
||||||
|
@ -50,8 +50,6 @@ const browserElementTestHelpers = {
|
|||||||
|
|
||||||
enableProcessPriorityManager: function() {
|
enableProcessPriorityManager: function() {
|
||||||
this._setPrefs(
|
this._setPrefs(
|
||||||
['dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2],
|
|
||||||
['dom.ipc.processPriorityManager.BACKGROUND_PERCEIVABLE.LRUPoolLevels', 2],
|
|
||||||
['dom.ipc.processPriorityManager.testMode', true],
|
['dom.ipc.processPriorityManager.testMode', true],
|
||||||
['dom.ipc.processPriorityManager.enabled', true]
|
['dom.ipc.processPriorityManager.enabled', true]
|
||||||
);
|
);
|
||||||
@ -197,46 +195,6 @@ function expectPriorityChange(childID, expectedPriority) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a promise which is resolved or rejected the next time the
|
|
||||||
// process childID changes its priority. We resolve if the expectedPriority
|
|
||||||
// matches the priority and the LRU parameter matches expectedLRU and we
|
|
||||||
// reject otherwise.
|
|
||||||
|
|
||||||
function expectPriorityWithLRUSet(childID, expectedPriority, expectedLRU) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
var observed = false;
|
|
||||||
browserElementTestHelpers.addProcessPriorityObserver(
|
|
||||||
'process-priority-with-LRU-set',
|
|
||||||
function(subject, topic, data) {
|
|
||||||
if (observed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var [id, priority, lru] = data.split(":");
|
|
||||||
if (id != childID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we run the is() calls in this observer only once,
|
|
||||||
// otherwise we'll expect /every/ priority/LRU change to match
|
|
||||||
// expectedPriority/expectedLRU.
|
|
||||||
observed = true;
|
|
||||||
|
|
||||||
is(lru, expectedLRU,
|
|
||||||
'Expected LRU ' + lru +
|
|
||||||
' of childID ' + childID +
|
|
||||||
' to change to ' + expectedLRU);
|
|
||||||
|
|
||||||
if ((priority == expectedPriority) && (lru == expectedLRU)) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a promise which is resolved the first time the given iframe fires
|
// Returns a promise which is resolved the first time the given iframe fires
|
||||||
// the mozbrowser##eventName event.
|
// the mozbrowser##eventName event.
|
||||||
function expectMozbrowserEvent(iframe, eventName) {
|
function expectMozbrowserEvent(iframe, eventName) {
|
||||||
|
13
dom/interfaces/payments/moz.build
Normal file
13
dom/interfaces/payments/moz.build
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
XPIDL_SOURCES += [
|
||||||
|
'nsIPaymentActionRequest.idl',
|
||||||
|
'nsIPaymentRequest.idl',
|
||||||
|
'nsIPaymentRequestService.idl',
|
||||||
|
]
|
||||||
|
|
||||||
|
XPIDL_MODULE = 'dom_payments'
|
76
dom/interfaces/payments/nsIPaymentActionRequest.idl
Normal file
76
dom/interfaces/payments/nsIPaymentActionRequest.idl
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 "nsISupports.idl"
|
||||||
|
#include "nsIVariant.idl"
|
||||||
|
#include "nsIPaymentRequest.idl"
|
||||||
|
|
||||||
|
interface nsIArray;
|
||||||
|
|
||||||
|
[builtinclass, uuid(7ddbe8be-beac-4952-96f6-619981dff7a6)]
|
||||||
|
interface nsIPaymentActionRequest : nsISupports
|
||||||
|
{
|
||||||
|
const uint32_t CREATE_ACTION = 1;
|
||||||
|
/*
|
||||||
|
* The payment request identifier.
|
||||||
|
*/
|
||||||
|
readonly attribute AString requestId;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The type of the requested task.
|
||||||
|
*/
|
||||||
|
readonly attribute uint32_t type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize function for this request.
|
||||||
|
*/
|
||||||
|
void init(in AString aRequestId,
|
||||||
|
in uint32_t aType);
|
||||||
|
};
|
||||||
|
|
||||||
|
[builtinclass, uuid(1d38dce6-8bcd-441b-aa94-68e300b6e175)]
|
||||||
|
interface nsIPaymentCreateActionRequest : nsIPaymentActionRequest
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The tab identifier
|
||||||
|
*/
|
||||||
|
readonly attribute uint64_t tabId;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The methodData information of the payment request.
|
||||||
|
*/
|
||||||
|
readonly attribute nsIArray methodData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Details information of the payment request.
|
||||||
|
*/
|
||||||
|
readonly attribute nsIPaymentDetails details;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Options information of the payment request.
|
||||||
|
*/
|
||||||
|
readonly attribute nsIPaymentOptions options;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize function the this request.
|
||||||
|
*/
|
||||||
|
void initRequest(in AString aRequestId,
|
||||||
|
in uint64_t aTabId,
|
||||||
|
in nsIArray aMethodData,
|
||||||
|
in nsIPaymentDetails aDetails,
|
||||||
|
in nsIPaymentOptions aOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#define NS_PAYMENT_ACTION_REQUEST_CID \
|
||||||
|
{ 0x7ddbe8be, 0xbeac, 0x4952, { 0x96, 0xf6, 0x61, 0x99, 0x81, 0xdf, 0xf7, 0xa6 } }
|
||||||
|
#define NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID \
|
||||||
|
"@mozilla.org/dom/payments/payment-action-request;1"
|
||||||
|
|
||||||
|
#define NS_PAYMENT_CREATE_ACTION_REQUEST_CID \
|
||||||
|
{ 0x1d38dce6, 0x8bcd, 0x441b, { 0xaa, 0x94, 0x68, 0xe3, 0x00, 0xb6, 0xe1, 0x75 } }
|
||||||
|
#define NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID \
|
||||||
|
"@mozilla.org/dom/payments/payment-create-action-request;1"
|
||||||
|
%}
|
84
dom/interfaces/payments/nsIPaymentRequest.idl
Normal file
84
dom/interfaces/payments/nsIPaymentRequest.idl
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 "nsISupports.idl"
|
||||||
|
#include "nsIVariant.idl"
|
||||||
|
|
||||||
|
interface nsIArray;
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(2fe296cc-d917-4820-b492-aa42df23f9b4)]
|
||||||
|
interface nsIPaymentMethodData : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute nsIArray supportedMethods;
|
||||||
|
readonly attribute AString data;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(d22a6f5f-767b-4fea-bf92-68b0b8003eba)]
|
||||||
|
interface nsIPaymentCurrencyAmount : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute AString currency;
|
||||||
|
readonly attribute AString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(4f78a59f-b5ff-4fb5-ab48-3b37d0101b02)]
|
||||||
|
interface nsIPaymentItem : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute AString label;
|
||||||
|
readonly attribute nsIPaymentCurrencyAmount amount;
|
||||||
|
readonly attribute boolean pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(74259861-c318-40e8-b3d5-518e701bed80)]
|
||||||
|
interface nsIPaymentDetailsModifier : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute nsIArray supportedMethods;
|
||||||
|
readonly attribute nsIPaymentItem total;
|
||||||
|
readonly attribute nsIArray additionalDisplayItems;
|
||||||
|
readonly attribute AString data;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(68341551-3605-4381-b936-41e830aa88fb)]
|
||||||
|
interface nsIPaymentShippingOption : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute AString id;
|
||||||
|
readonly attribute AString label;
|
||||||
|
readonly attribute nsIPaymentCurrencyAmount amount;
|
||||||
|
attribute boolean selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(73a5a3f1-45b9-4605-a6e6-7aa60daa9039)]
|
||||||
|
interface nsIPaymentDetails : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute AString id;
|
||||||
|
readonly attribute nsIPaymentItem totalItem;
|
||||||
|
readonly attribute nsIArray displayItems;
|
||||||
|
readonly attribute nsIArray shippingOptions;
|
||||||
|
readonly attribute nsIArray modifiers;
|
||||||
|
readonly attribute AString error;
|
||||||
|
|
||||||
|
void update(in nsIPaymentDetails aDetails);
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(d53f9f20-138e-47cc-9fd5-db16a3f6d301)]
|
||||||
|
interface nsIPaymentOptions : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute boolean requestPayerName;
|
||||||
|
readonly attribute boolean requestPayerEmail;
|
||||||
|
readonly attribute boolean requestPayerPhone;
|
||||||
|
readonly attribute boolean requestShipping;
|
||||||
|
readonly attribute AString shippingType;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, builtinclass, uuid(2fa36783-d684-4487-b7a8-9def6ae3128f)]
|
||||||
|
interface nsIPaymentRequest : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute uint64_t tabId;
|
||||||
|
readonly attribute AString requestId;
|
||||||
|
readonly attribute nsIArray paymentMethods;
|
||||||
|
readonly attribute nsIPaymentDetails paymentDetails;
|
||||||
|
readonly attribute nsIPaymentOptions paymentOptions;
|
||||||
|
|
||||||
|
void updatePaymentDetails(in nsIPaymentDetails aDetails);
|
||||||
|
};
|
40
dom/interfaces/payments/nsIPaymentRequestService.idl
Normal file
40
dom/interfaces/payments/nsIPaymentRequestService.idl
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 "nsISupports.idl"
|
||||||
|
#include "nsIVariant.idl"
|
||||||
|
#include "nsIPaymentRequest.idl"
|
||||||
|
#include "nsIPaymentActionRequest.idl"
|
||||||
|
#include "nsISimpleEnumerator.idl"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nsPaymentRequestService is used to manage the created PaymentRequest in the
|
||||||
|
* chrome process. It is also the IPC agent for payment UI to communicate with
|
||||||
|
* merchant side.
|
||||||
|
*/
|
||||||
|
[scriptable, builtinclass, uuid(cccd665f-edf3-41fc-ab9b-fc55b37340aa)]
|
||||||
|
interface nsIPaymentRequestService : nsISupports
|
||||||
|
{
|
||||||
|
nsIPaymentRequest getPaymentRequestById(in AString requestId);
|
||||||
|
nsISimpleEnumerator enumerate();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is only for testing.
|
||||||
|
*/
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* requestPayment is used to handle the asked action request of the payment
|
||||||
|
* from content process.
|
||||||
|
*/
|
||||||
|
void requestPayment(in nsIPaymentActionRequest aRequest);
|
||||||
|
};
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#define NS_PAYMENT_REQUEST_SERVICE_CID \
|
||||||
|
{ 0xcccd665f, 0xedf3, 0x41fc, { 0xab, 0x9b, 0xfc, 0x55, 0xb3, 0x73, 0x40, 0xaa } }
|
||||||
|
#define NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID \
|
||||||
|
"@mozilla.org/dom/payments/payment-request-service;1"
|
||||||
|
%}
|
@ -19,6 +19,7 @@ include protocol PChildToParentStream;
|
|||||||
include protocol PParentToChildStream;
|
include protocol PParentToChildStream;
|
||||||
include protocol PFileDescriptorSet;
|
include protocol PFileDescriptorSet;
|
||||||
include protocol PIPCBlobInputStream;
|
include protocol PIPCBlobInputStream;
|
||||||
|
include protocol PPaymentRequest;
|
||||||
|
|
||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
include IPCBlob;
|
include IPCBlob;
|
||||||
@ -115,6 +116,7 @@ nested(upto inside_cpow) sync protocol PBrowser
|
|||||||
manages PIndexedDBPermissionRequest;
|
manages PIndexedDBPermissionRequest;
|
||||||
manages PRenderFrame;
|
manages PRenderFrame;
|
||||||
manages PPluginWidget;
|
manages PPluginWidget;
|
||||||
|
manages PPaymentRequest;
|
||||||
|
|
||||||
both:
|
both:
|
||||||
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
|
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
|
||||||
@ -145,6 +147,8 @@ parent:
|
|||||||
*/
|
*/
|
||||||
sync PPluginWidget();
|
sync PPluginWidget();
|
||||||
|
|
||||||
|
async PPaymentRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return native data of root widget
|
* Return native data of root widget
|
||||||
*/
|
*/
|
||||||
|
@ -92,40 +92,6 @@ namespace {
|
|||||||
|
|
||||||
class ParticularProcessPriorityManager;
|
class ParticularProcessPriorityManager;
|
||||||
|
|
||||||
class ProcessLRUPool final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a new process LRU pool for the specified priority.
|
|
||||||
*/
|
|
||||||
explicit ProcessLRUPool(ProcessPriority aPriority);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to remove a particular process priority manager from the LRU pool
|
|
||||||
* when the associated ContentParent is destroyed or its priority changes.
|
|
||||||
*/
|
|
||||||
void Remove(ParticularProcessPriorityManager* aParticularManager);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to add a particular process priority manager into the LRU pool when
|
|
||||||
* the associated ContentParent's priority changes.
|
|
||||||
*/
|
|
||||||
void Add(ParticularProcessPriorityManager* aParticularManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProcessPriority mPriority;
|
|
||||||
uint32_t mLRUPoolLevels;
|
|
||||||
nsTArray<ParticularProcessPriorityManager*> mLRUPool;
|
|
||||||
|
|
||||||
uint32_t CalculateLRULevel(uint32_t aLRUPoolIndex);
|
|
||||||
|
|
||||||
void AdjustLRUValues(
|
|
||||||
nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
|
|
||||||
bool removed);
|
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(ProcessLRUPool);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This singleton class does the work to implement the process priority manager
|
* This singleton class does the work to implement the process priority manager
|
||||||
* in the main process. This class may not be used in child processes. (You
|
* in the main process. This class may not be used in child processes. (You
|
||||||
@ -160,8 +126,7 @@ public:
|
|||||||
* This function implements ProcessPriorityManager::SetProcessPriority.
|
* This function implements ProcessPriorityManager::SetProcessPriority.
|
||||||
*/
|
*/
|
||||||
void SetProcessPriority(ContentParent* aContentParent,
|
void SetProcessPriority(ContentParent* aContentParent,
|
||||||
ProcessPriority aPriority,
|
ProcessPriority aPriority);
|
||||||
uint32_t aLRU = 0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a magic testing-only pref is set, notify the observer service on the
|
* If a magic testing-only pref is set, notify the observer service on the
|
||||||
@ -238,12 +203,6 @@ private:
|
|||||||
|
|
||||||
/** Contains the PIDs of child processes holding high-priority wakelocks */
|
/** Contains the PIDs of child processes holding high-priority wakelocks */
|
||||||
nsTHashtable<nsUint64HashKey> mHighPriorityChildIDs;
|
nsTHashtable<nsUint64HashKey> mHighPriorityChildIDs;
|
||||||
|
|
||||||
/** Contains a pseudo-LRU list of background processes */
|
|
||||||
ProcessLRUPool mBackgroundLRUPool;
|
|
||||||
|
|
||||||
/** Contains a pseudo-LRU list of background-perceivable processes */
|
|
||||||
ProcessLRUPool mBackgroundPerceivableLRUPool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,7 +273,6 @@ public:
|
|||||||
|
|
||||||
bool IsExpectingSystemMessage();
|
bool IsExpectingSystemMessage();
|
||||||
|
|
||||||
void OnAudioChannelProcessChanged(nsISupports* aSubject);
|
|
||||||
void OnRemoteBrowserFrameShown(nsISupports* aSubject);
|
void OnRemoteBrowserFrameShown(nsISupports* aSubject);
|
||||||
void OnTabParentDestroyed(nsISupports* aSubject);
|
void OnTabParentDestroyed(nsISupports* aSubject);
|
||||||
void OnFrameloaderVisibleChanged(nsISupports* aSubject);
|
void OnFrameloaderVisibleChanged(nsISupports* aSubject);
|
||||||
@ -332,7 +290,7 @@ public:
|
|||||||
void ScheduleResetPriority(TimeoutPref aTimeoutPref);
|
void ScheduleResetPriority(TimeoutPref aTimeoutPref);
|
||||||
void ResetPriority();
|
void ResetPriority();
|
||||||
void ResetPriorityNow();
|
void ResetPriorityNow();
|
||||||
void SetPriorityNow(ProcessPriority aPriority, uint32_t aLRU = 0);
|
void SetPriorityNow(ProcessPriority aPriority);
|
||||||
void Freeze();
|
void Freeze();
|
||||||
void Unfreeze();
|
void Unfreeze();
|
||||||
|
|
||||||
@ -353,7 +311,6 @@ private:
|
|||||||
ContentParent* mContentParent;
|
ContentParent* mContentParent;
|
||||||
uint64_t mChildID;
|
uint64_t mChildID;
|
||||||
ProcessPriority mPriority;
|
ProcessPriority mPriority;
|
||||||
uint32_t mLRU;
|
|
||||||
bool mHoldsCPUWakeLock;
|
bool mHoldsCPUWakeLock;
|
||||||
bool mHoldsHighPriorityWakeLock;
|
bool mHoldsHighPriorityWakeLock;
|
||||||
bool mIsActivityOpener;
|
bool mIsActivityOpener;
|
||||||
@ -463,8 +420,6 @@ ProcessPriorityManagerImpl::GetSingleton()
|
|||||||
|
|
||||||
ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
|
ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
|
||||||
: mHighPriority(false)
|
: mHighPriority(false)
|
||||||
, mBackgroundLRUPool(PROCESS_PRIORITY_BACKGROUND)
|
|
||||||
, mBackgroundPerceivableLRUPool(PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
RegisterWakeLockObserver(this);
|
RegisterWakeLockObserver(this);
|
||||||
@ -540,14 +495,13 @@ ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
|
|||||||
|
|
||||||
void
|
void
|
||||||
ProcessPriorityManagerImpl::SetProcessPriority(ContentParent* aContentParent,
|
ProcessPriorityManagerImpl::SetProcessPriority(ContentParent* aContentParent,
|
||||||
ProcessPriority aPriority,
|
ProcessPriority aPriority)
|
||||||
uint32_t aLRU)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aContentParent);
|
MOZ_ASSERT(aContentParent);
|
||||||
RefPtr<ParticularProcessPriorityManager> pppm =
|
RefPtr<ParticularProcessPriorityManager> pppm =
|
||||||
GetParticularProcessPriorityManager(aContentParent);
|
GetParticularProcessPriorityManager(aContentParent);
|
||||||
if (pppm) {
|
if (pppm) {
|
||||||
pppm->SetPriorityNow(aPriority, aLRU);
|
pppm->SetPriorityNow(aPriority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,10 +529,6 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
|||||||
RefPtr<ParticularProcessPriorityManager> pppm;
|
RefPtr<ParticularProcessPriorityManager> pppm;
|
||||||
mParticularManagers.Get(childID, &pppm);
|
mParticularManagers.Get(childID, &pppm);
|
||||||
if (pppm) {
|
if (pppm) {
|
||||||
// Unconditionally remove the manager from the pools
|
|
||||||
mBackgroundLRUPool.Remove(pppm);
|
|
||||||
mBackgroundPerceivableLRUPool.Remove(pppm);
|
|
||||||
|
|
||||||
pppm->ShutDown();
|
pppm->ShutDown();
|
||||||
|
|
||||||
mParticularManagers.Remove(childID);
|
mParticularManagers.Remove(childID);
|
||||||
@ -616,22 +566,6 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
|
|||||||
{
|
{
|
||||||
ProcessPriority newPriority = aParticularManager->CurrentPriority();
|
ProcessPriority newPriority = aParticularManager->CurrentPriority();
|
||||||
|
|
||||||
if (newPriority == PROCESS_PRIORITY_BACKGROUND &&
|
|
||||||
aOldPriority != PROCESS_PRIORITY_BACKGROUND) {
|
|
||||||
mBackgroundLRUPool.Add(aParticularManager);
|
|
||||||
} else if (newPriority != PROCESS_PRIORITY_BACKGROUND &&
|
|
||||||
aOldPriority == PROCESS_PRIORITY_BACKGROUND) {
|
|
||||||
mBackgroundLRUPool.Remove(aParticularManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE &&
|
|
||||||
aOldPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE) {
|
|
||||||
mBackgroundPerceivableLRUPool.Add(aParticularManager);
|
|
||||||
} else if (newPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE &&
|
|
||||||
aOldPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE) {
|
|
||||||
mBackgroundPerceivableLRUPool.Remove(aParticularManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH &&
|
if (newPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH &&
|
||||||
aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH) {
|
aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH) {
|
||||||
mHighPriorityChildIDs.PutEntry(aParticularManager->ChildID());
|
mHighPriorityChildIDs.PutEntry(aParticularManager->ChildID());
|
||||||
@ -669,7 +603,6 @@ ParticularProcessPriorityManager::ParticularProcessPriorityManager(
|
|||||||
: mContentParent(aContentParent)
|
: mContentParent(aContentParent)
|
||||||
, mChildID(aContentParent->ChildID())
|
, mChildID(aContentParent->ChildID())
|
||||||
, mPriority(PROCESS_PRIORITY_UNKNOWN)
|
, mPriority(PROCESS_PRIORITY_UNKNOWN)
|
||||||
, mLRU(0)
|
|
||||||
, mHoldsCPUWakeLock(false)
|
, mHoldsCPUWakeLock(false)
|
||||||
, mHoldsHighPriorityWakeLock(false)
|
, mHoldsHighPriorityWakeLock(false)
|
||||||
, mIsActivityOpener(false)
|
, mIsActivityOpener(false)
|
||||||
@ -695,7 +628,6 @@ ParticularProcessPriorityManager::Init()
|
|||||||
|
|
||||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||||
if (os) {
|
if (os) {
|
||||||
os->AddObserver(this, "audio-channel-process-changed", /* ownsWeak */ true);
|
|
||||||
os->AddObserver(this, "remote-browser-shown", /* ownsWeak */ true);
|
os->AddObserver(this, "remote-browser-shown", /* ownsWeak */ true);
|
||||||
os->AddObserver(this, "ipc:browser-destroyed", /* ownsWeak */ true);
|
os->AddObserver(this, "ipc:browser-destroyed", /* ownsWeak */ true);
|
||||||
os->AddObserver(this, "frameloader-visible-changed", /* ownsWeak */ true);
|
os->AddObserver(this, "frameloader-visible-changed", /* ownsWeak */ true);
|
||||||
@ -768,9 +700,7 @@ ParticularProcessPriorityManager::Observe(nsISupports* aSubject,
|
|||||||
|
|
||||||
nsDependentCString topic(aTopic);
|
nsDependentCString topic(aTopic);
|
||||||
|
|
||||||
if (topic.EqualsLiteral("audio-channel-process-changed")) {
|
if (topic.EqualsLiteral("remote-browser-shown")) {
|
||||||
OnAudioChannelProcessChanged(aSubject);
|
|
||||||
} else if (topic.EqualsLiteral("remote-browser-shown")) {
|
|
||||||
OnRemoteBrowserFrameShown(aSubject);
|
OnRemoteBrowserFrameShown(aSubject);
|
||||||
} else if (topic.EqualsLiteral("ipc:browser-destroyed")) {
|
} else if (topic.EqualsLiteral("ipc:browser-destroyed")) {
|
||||||
OnTabParentDestroyed(aSubject);
|
OnTabParentDestroyed(aSubject);
|
||||||
@ -822,19 +752,6 @@ ParticularProcessPriorityManager::NameWithComma()
|
|||||||
return mNameWithComma;
|
return mNameWithComma;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ParticularProcessPriorityManager::OnAudioChannelProcessChanged(nsISupports* aSubject)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
|
|
||||||
NS_ENSURE_TRUE_VOID(props);
|
|
||||||
|
|
||||||
uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
|
|
||||||
props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
|
|
||||||
if (childID == ChildID()) {
|
|
||||||
ResetPriority();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ParticularProcessPriorityManager::OnRemoteBrowserFrameShown(nsISupports* aSubject)
|
ParticularProcessPriorityManager::OnRemoteBrowserFrameShown(nsISupports* aSubject)
|
||||||
{
|
{
|
||||||
@ -1048,8 +965,7 @@ ParticularProcessPriorityManager::ComputePriority()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority)
|
||||||
uint32_t aLRU)
|
|
||||||
{
|
{
|
||||||
if (aPriority == PROCESS_PRIORITY_UNKNOWN) {
|
if (aPriority == PROCESS_PRIORITY_UNKNOWN) {
|
||||||
MOZ_ASSERT(false);
|
MOZ_ASSERT(false);
|
||||||
@ -1059,19 +975,12 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
|||||||
if (!ProcessPriorityManagerImpl::PrefsEnabled() ||
|
if (!ProcessPriorityManagerImpl::PrefsEnabled() ||
|
||||||
!mContentParent ||
|
!mContentParent ||
|
||||||
mFrozen ||
|
mFrozen ||
|
||||||
((mPriority == aPriority) && (mLRU == aLRU))) {
|
mPriority == aPriority) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mPriority == aPriority) && (mLRU != aLRU)) {
|
if (mPriority == aPriority) {
|
||||||
mLRU = aLRU;
|
hal::SetProcessPriority(Pid(), mPriority);
|
||||||
hal::SetProcessPriority(Pid(), mPriority, aLRU);
|
|
||||||
|
|
||||||
nsPrintfCString processPriorityWithLRU("%s:%d",
|
|
||||||
ProcessPriorityToString(mPriority), aLRU);
|
|
||||||
|
|
||||||
FireTestOnlyObserverNotification("process-priority-with-LRU-set",
|
|
||||||
processPriorityWithLRU.get());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,112 +1168,6 @@ ProcessPriorityManagerChild::CurrentProcessIsHighPriority()
|
|||||||
mCachedPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH;
|
mCachedPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessLRUPool::ProcessLRUPool(ProcessPriority aPriority)
|
|
||||||
: mPriority(aPriority)
|
|
||||||
, mLRUPoolLevels(1)
|
|
||||||
{
|
|
||||||
// We set mLRUPoolLevels according to our pref.
|
|
||||||
// This value is used to set background process LRU pool
|
|
||||||
const char* str = ProcessPriorityToString(aPriority);
|
|
||||||
nsPrintfCString pref("dom.ipc.processPriorityManager.%s.LRUPoolLevels", str);
|
|
||||||
|
|
||||||
Preferences::GetUint(pref.get(), &mLRUPoolLevels);
|
|
||||||
|
|
||||||
// GonkHal defines OOM_ADJUST_MAX is 15 and b2g.js defines
|
|
||||||
// PROCESS_PRIORITY_BACKGROUND's oom_score_adj is 667 and oom_adj is 10.
|
|
||||||
// This means we can only have at most (15 -10 + 1) = 6 background LRU levels.
|
|
||||||
// Similarly we can have at most 4 background perceivable LRU levels. We
|
|
||||||
// should really be getting rid of oom_adj and just rely on oom_score_adj
|
|
||||||
// only which would lift this constraint.
|
|
||||||
MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND || mLRUPoolLevels <= 6);
|
|
||||||
MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE ||
|
|
||||||
mLRUPoolLevels <= 4);
|
|
||||||
|
|
||||||
// LRU pool size = 2 ^ (number of background LRU pool levels) - 1
|
|
||||||
uint32_t LRUPoolSize = (1 << mLRUPoolLevels) - 1;
|
|
||||||
|
|
||||||
LOG("Making %s LRU pool with size(%d)", str, LRUPoolSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t
|
|
||||||
ProcessLRUPool::CalculateLRULevel(uint32_t aLRU)
|
|
||||||
{
|
|
||||||
// This is used to compute the LRU adjustment for the specified LRU position.
|
|
||||||
// We use power-of-two groups with increasing adjustments that look like the
|
|
||||||
// following:
|
|
||||||
|
|
||||||
// Priority : LRU0, LRU1
|
|
||||||
// Priority+1: LRU2, LRU3
|
|
||||||
// Priority+2: LRU4, LRU5, LRU6, LRU7
|
|
||||||
// Priority+3: LRU8, LRU9, LRU10, LRU11, LRU12, LRU12, LRU13, LRU14, LRU15
|
|
||||||
// ...
|
|
||||||
// Priority+L-1: 2^(number of LRU pool levels - 1)
|
|
||||||
// (End of buffer)
|
|
||||||
|
|
||||||
int exp;
|
|
||||||
Unused << frexp(static_cast<double>(aLRU), &exp);
|
|
||||||
uint32_t level = std::max(exp - 1, 0);
|
|
||||||
|
|
||||||
return std::min(mLRUPoolLevels - 1, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ProcessLRUPool::Remove(ParticularProcessPriorityManager* aParticularManager)
|
|
||||||
{
|
|
||||||
nsTArray<ParticularProcessPriorityManager*>::index_type index =
|
|
||||||
mLRUPool.IndexOf(aParticularManager);
|
|
||||||
|
|
||||||
if (index == nsTArray<ParticularProcessPriorityManager*>::NoIndex) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mLRUPool.RemoveElementAt(index);
|
|
||||||
AdjustLRUValues(index, /* removed */ true);
|
|
||||||
|
|
||||||
LOG("Remove ChildID(%" PRIu64 ") from %s LRU pool",
|
|
||||||
static_cast<uint64_t>(aParticularManager->ChildID()),
|
|
||||||
ProcessPriorityToString(mPriority));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adjust the LRU values of all the processes in an LRU pool. When true the
|
|
||||||
* `removed` parameter indicates that the processes were shifted left because
|
|
||||||
* an element was removed; otherwise it means the elements were shifted right
|
|
||||||
* as an element was added.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ProcessLRUPool::AdjustLRUValues(
|
|
||||||
nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
|
|
||||||
bool removed)
|
|
||||||
{
|
|
||||||
uint32_t adj = (removed ? 2 : 1);
|
|
||||||
|
|
||||||
for (nsTArray<ParticularProcessPriorityManager*>::index_type i = aStart;
|
|
||||||
i < mLRUPool.Length();
|
|
||||||
i++) {
|
|
||||||
/* Check whether i is a power of two. If so, then it crossed a LRU group
|
|
||||||
* boundary and we need to assign its new process priority LRU. Note that
|
|
||||||
* depending on the direction and the bias this test will pick different
|
|
||||||
* elements. */
|
|
||||||
if (((i + adj) & (i + adj - 1)) == 0) {
|
|
||||||
mLRUPool[i]->SetPriorityNow(mPriority, CalculateLRULevel(i + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ProcessLRUPool::Add(ParticularProcessPriorityManager* aParticularManager)
|
|
||||||
{
|
|
||||||
// Shift the list in the pool, so we have room at index 0 for the newly added
|
|
||||||
// manager
|
|
||||||
mLRUPool.InsertElementAt(0, aParticularManager);
|
|
||||||
AdjustLRUValues(1, /* removed */ false);
|
|
||||||
|
|
||||||
LOG("Add ChildID(%" PRIu64 ") into %s LRU pool",
|
|
||||||
static_cast<uint64_t>(aParticularManager->ChildID()),
|
|
||||||
ProcessPriorityToString(mPriority));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/EventListenerManager.h"
|
#include "mozilla/EventListenerManager.h"
|
||||||
#include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
|
#include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestChild.h"
|
||||||
#include "mozilla/dom/TelemetryScrollProbe.h"
|
#include "mozilla/dom/TelemetryScrollProbe.h"
|
||||||
#include "mozilla/IMEStateManager.h"
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/ipc/DocumentRendererChild.h"
|
#include "mozilla/ipc/DocumentRendererChild.h"
|
||||||
@ -3208,6 +3209,19 @@ TabChild::CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut)
|
|||||||
}
|
}
|
||||||
#endif // XP_WIN
|
#endif // XP_WIN
|
||||||
|
|
||||||
|
PPaymentRequestChild*
|
||||||
|
TabChild::AllocPPaymentRequestChild()
|
||||||
|
{
|
||||||
|
MOZ_CRASH("We should never be manually allocating PPaymentRequestChild actors");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TabChild::DeallocPPaymentRequestChild(PPaymentRequestChild* actor)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ScreenIntSize
|
ScreenIntSize
|
||||||
TabChild::GetInnerSize()
|
TabChild::GetInnerSize()
|
||||||
{
|
{
|
||||||
|
@ -620,6 +620,12 @@ public:
|
|||||||
nsresult CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut);
|
nsresult CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual PPaymentRequestChild*
|
||||||
|
AllocPPaymentRequestChild() override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
DeallocPPaymentRequestChild(PPaymentRequestChild* aActor) override;
|
||||||
|
|
||||||
LayoutDeviceIntPoint GetClientOffset() const { return mClientOffset; }
|
LayoutDeviceIntPoint GetClientOffset() const { return mClientOffset; }
|
||||||
LayoutDeviceIntPoint GetChromeDisplacement() const { return mChromeDisp; };
|
LayoutDeviceIntPoint GetChromeDisplacement() const { return mChromeDisp; };
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
#include "mozilla/dom/indexedDB/ActorsParent.h"
|
#include "mozilla/dom/indexedDB/ActorsParent.h"
|
||||||
#include "mozilla/dom/IPCBlobUtils.h"
|
#include "mozilla/dom/IPCBlobUtils.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestParent.h"
|
||||||
#include "mozilla/EventStateManager.h"
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||||
@ -2859,6 +2860,21 @@ TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aAc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PPaymentRequestParent*
|
||||||
|
TabParent::AllocPPaymentRequestParent()
|
||||||
|
{
|
||||||
|
RefPtr<PaymentRequestParent> actor = new PaymentRequestParent(GetTabId());
|
||||||
|
return actor.forget().take();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TabParent::DeallocPPaymentRequestParent(PPaymentRequestParent* aActor)
|
||||||
|
{
|
||||||
|
RefPtr<PaymentRequestParent> actor =
|
||||||
|
dont_AddRef(static_cast<PaymentRequestParent*>(aActor));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
TabParent::HandleEvent(nsIDOMEvent* aEvent)
|
TabParent::HandleEvent(nsIDOMEvent* aEvent)
|
||||||
{
|
{
|
||||||
|
@ -553,6 +553,12 @@ public:
|
|||||||
virtual bool
|
virtual bool
|
||||||
DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) override;
|
DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) override;
|
||||||
|
|
||||||
|
virtual PPaymentRequestParent*
|
||||||
|
AllocPPaymentRequestParent() override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
DeallocPPaymentRequestParent(PPaymentRequestParent* aActor) override;
|
||||||
|
|
||||||
void SetInitedByParent() { mInitedByParent = true; }
|
void SetInitedByParent() { mInitedByParent = true; }
|
||||||
|
|
||||||
bool IsInitedByParent() const { return mInitedByParent; }
|
bool IsInitedByParent() const { return mInitedByParent; }
|
||||||
|
@ -36,6 +36,7 @@ interfaces = [
|
|||||||
'svg',
|
'svg',
|
||||||
'smil',
|
'smil',
|
||||||
'push',
|
'push',
|
||||||
|
'payments',
|
||||||
]
|
]
|
||||||
|
|
||||||
DIRS += ['interfaces/' + i for i in interfaces]
|
DIRS += ['interfaces/' + i for i in interfaces]
|
||||||
@ -105,6 +106,7 @@ DIRS += [
|
|||||||
'xhr',
|
'xhr',
|
||||||
'worklet',
|
'worklet',
|
||||||
'script',
|
'script',
|
||||||
|
'payments',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||||
|
110
dom/payments/PaymentActionRequest.cpp
Normal file
110
dom/payments/PaymentActionRequest.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "nsArrayUtils.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "PaymentActionRequest.h"
|
||||||
|
#include "PaymentRequestData.h"
|
||||||
|
|
||||||
|
using namespace mozilla::dom::payments;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
/* PaymentActionRequest */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentActionRequest,
|
||||||
|
nsIPaymentActionRequest)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentActionRequest::Init(const nsAString& aRequestId,
|
||||||
|
const uint32_t aType)
|
||||||
|
{
|
||||||
|
mRequestId = aRequestId;
|
||||||
|
mType = aType;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentActionRequest::GetRequestId(nsAString& aRequestId)
|
||||||
|
{
|
||||||
|
aRequestId = mRequestId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentActionRequest::GetType(uint32_t* aType)
|
||||||
|
{
|
||||||
|
*aType = mType;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentCreateActionRequest */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED(PaymentCreateActionRequest,
|
||||||
|
PaymentActionRequest,
|
||||||
|
nsIPaymentCreateActionRequest)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCreateActionRequest::InitRequest(const nsAString& aRequestId,
|
||||||
|
const uint64_t aTabId,
|
||||||
|
nsIArray* aMethodData,
|
||||||
|
nsIPaymentDetails* aDetails,
|
||||||
|
nsIPaymentOptions* aOptions)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aMethodData);
|
||||||
|
NS_ENSURE_ARG_POINTER(aDetails);
|
||||||
|
NS_ENSURE_ARG_POINTER(aOptions);
|
||||||
|
Init(aRequestId, nsIPaymentActionRequest::CREATE_ACTION);
|
||||||
|
mTabId = aTabId;
|
||||||
|
mMethodData = aMethodData;
|
||||||
|
mDetails = aDetails;
|
||||||
|
mOptions = aOptions;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCreateActionRequest::GetTabId(uint64_t* aTabId)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aTabId);
|
||||||
|
*aTabId = mTabId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCreateActionRequest::GetMethodData(nsIArray** aMethodData)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aMethodData);
|
||||||
|
*aMethodData = nullptr;
|
||||||
|
MOZ_ASSERT(mMethodData);
|
||||||
|
nsCOMPtr<nsIArray> methodData = mMethodData;
|
||||||
|
methodData.forget(aMethodData);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCreateActionRequest::GetDetails(nsIPaymentDetails** aDetails)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aDetails);
|
||||||
|
*aDetails = nullptr;
|
||||||
|
MOZ_ASSERT(mDetails);
|
||||||
|
nsCOMPtr<nsIPaymentDetails> details = mDetails;
|
||||||
|
details.forget(aDetails);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCreateActionRequest::GetOptions(nsIPaymentOptions** aOptions)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aOptions);
|
||||||
|
*aOptions = nullptr;
|
||||||
|
MOZ_ASSERT(mOptions);
|
||||||
|
nsCOMPtr<nsIPaymentOptions> options = mOptions;
|
||||||
|
options.forget(aOptions);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
56
dom/payments/PaymentActionRequest.h
Normal file
56
dom/payments/PaymentActionRequest.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentActionRequest_h
|
||||||
|
#define mozilla_dom_PaymentActionRequest_h
|
||||||
|
|
||||||
|
#include "nsIPaymentActionRequest.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsCOMArray.h"
|
||||||
|
#include "nsIArray.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class PaymentActionRequest : public nsIPaymentActionRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTACTIONREQUEST
|
||||||
|
|
||||||
|
PaymentActionRequest() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~PaymentActionRequest() = default;
|
||||||
|
|
||||||
|
nsString mRequestId;
|
||||||
|
uint32_t mType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentCreateActionRequest final : public nsIPaymentCreateActionRequest
|
||||||
|
, public PaymentActionRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_FORWARD_NSIPAYMENTACTIONREQUEST(PaymentActionRequest::)
|
||||||
|
NS_DECL_NSIPAYMENTCREATEACTIONREQUEST
|
||||||
|
|
||||||
|
PaymentCreateActionRequest() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PaymentCreateActionRequest() = default;
|
||||||
|
|
||||||
|
uint64_t mTabId;
|
||||||
|
nsCOMPtr<nsIArray> mMethodData;
|
||||||
|
nsCOMPtr<nsIPaymentDetails> mDetails;
|
||||||
|
nsCOMPtr<nsIPaymentOptions> mOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
281
dom/payments/PaymentRequest.cpp
Normal file
281
dom/payments/PaymentRequest.cpp
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "mozilla/dom/PaymentRequest.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "PaymentRequestManager.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentRequest)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequest,
|
||||||
|
DOMEventTargetHelper)
|
||||||
|
// Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
|
||||||
|
// DOMEventTargetHelper does it for us.
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PaymentRequest,
|
||||||
|
DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PaymentRequest,
|
||||||
|
DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PaymentRequest)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(PaymentRequest, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(PaymentRequest, DOMEventTargetHelper)
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj)
|
||||||
|
{
|
||||||
|
return Preferences::GetBool("dom.payments.request.enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::IsValidNumber(const nsAString& aItem,
|
||||||
|
const nsAString& aStr,
|
||||||
|
nsAString& aErrorMsg)
|
||||||
|
{
|
||||||
|
nsAutoString aValue(aStr);
|
||||||
|
nsresult error = NS_OK;
|
||||||
|
aValue.ToFloat(&error);
|
||||||
|
if (NS_FAILED(error)) {
|
||||||
|
aErrorMsg.AssignLiteral("The amount.value of \"");
|
||||||
|
aErrorMsg.Append(aItem);
|
||||||
|
aErrorMsg.AppendLiteral("\"(");
|
||||||
|
aErrorMsg.Append(aValue);
|
||||||
|
aErrorMsg.AppendLiteral(") must be a valid decimal monetary value.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::IsPositiveNumber(const nsAString& aItem,
|
||||||
|
const nsAString& aStr,
|
||||||
|
nsAString& aErrorMsg)
|
||||||
|
{
|
||||||
|
nsAutoString aValue(aStr);
|
||||||
|
nsresult error = NS_OK;
|
||||||
|
float value = aValue.ToFloat(&error);
|
||||||
|
if (NS_FAILED(error) || value < 0) {
|
||||||
|
aErrorMsg.AssignLiteral("The amount.value of \"");
|
||||||
|
aErrorMsg.Append(aItem);
|
||||||
|
aErrorMsg.AppendLiteral("\"(");
|
||||||
|
aErrorMsg.Append(aValue);
|
||||||
|
aErrorMsg.AppendLiteral(") must be a valid and positive decimal monetary value.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::IsValidDetailsInit(const PaymentDetailsInit& aDetails, nsAString& aErrorMsg)
|
||||||
|
{
|
||||||
|
// Check the amount.value of detail.total
|
||||||
|
if (!IsPositiveNumber(NS_LITERAL_STRING("details.total"),
|
||||||
|
aDetails.mTotal.mAmount.mValue, aErrorMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsValidDetailsBase(aDetails, aErrorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::IsValidDetailsBase(const PaymentDetailsBase& aDetails, nsAString& aErrorMsg)
|
||||||
|
{
|
||||||
|
// Check the amount.value of each item in the display items
|
||||||
|
if (aDetails.mDisplayItems.WasPassed()) {
|
||||||
|
const Sequence<PaymentItem>& displayItems = aDetails.mDisplayItems.Value();
|
||||||
|
for (const PaymentItem& displayItem : displayItems) {
|
||||||
|
if (!IsValidNumber(displayItem.mLabel,
|
||||||
|
displayItem.mAmount.mValue, aErrorMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the shipping option
|
||||||
|
if (aDetails.mShippingOptions.WasPassed()) {
|
||||||
|
const Sequence<PaymentShippingOption>& shippingOptions = aDetails.mShippingOptions.Value();
|
||||||
|
for (const PaymentShippingOption& shippingOption : shippingOptions) {
|
||||||
|
if (!IsValidNumber(NS_LITERAL_STRING("details.shippingOptions"),
|
||||||
|
shippingOption.mAmount.mValue, aErrorMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check payment details modifiers
|
||||||
|
if (aDetails.mModifiers.WasPassed()) {
|
||||||
|
const Sequence<PaymentDetailsModifier>& modifiers = aDetails.mModifiers.Value();
|
||||||
|
for (const PaymentDetailsModifier& modifier : modifiers) {
|
||||||
|
if (!IsPositiveNumber(NS_LITERAL_STRING("details.modifiers.total"),
|
||||||
|
modifier.mTotal.mAmount.mValue, aErrorMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (modifier.mAdditionalDisplayItems.WasPassed()) {
|
||||||
|
const Sequence<PaymentItem>& displayItems = modifier.mAdditionalDisplayItems.Value();
|
||||||
|
for (const PaymentItem& displayItem : displayItems) {
|
||||||
|
if (!IsValidNumber(displayItem.mLabel,
|
||||||
|
displayItem.mAmount.mValue, aErrorMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequest>
|
||||||
|
PaymentRequest::Constructor(const GlobalObject& aGlobal,
|
||||||
|
const Sequence<PaymentMethodData>& aMethodData,
|
||||||
|
const PaymentDetailsInit& aDetails,
|
||||||
|
const PaymentOptions& aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
if (!window) {
|
||||||
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [TODO] Bug 1318988 - Implement `allowPaymentRequest` on iframe
|
||||||
|
|
||||||
|
// Check payment methods is done by webidl
|
||||||
|
|
||||||
|
// Check payment details
|
||||||
|
nsAutoString message;
|
||||||
|
if (!IsValidDetailsInit(aDetails, message)) {
|
||||||
|
aRv.ThrowTypeError<MSG_ILLEGAL_PR_CONSTRUCTOR>(message);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||||
|
if (NS_WARN_IF(!manager)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create PaymentRequest and set its |mId|
|
||||||
|
RefPtr<PaymentRequest> request;
|
||||||
|
nsresult rv = manager->CreatePayment(window, aMethodData, aDetails,
|
||||||
|
aOptions, getter_AddRefs(request));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequest>
|
||||||
|
PaymentRequest::CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv)
|
||||||
|
{
|
||||||
|
// Generate a unique id for identification
|
||||||
|
nsID uuid;
|
||||||
|
aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(aRv))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
char buffer[NSID_LENGTH];
|
||||||
|
uuid.ToProvidedString(buffer);
|
||||||
|
nsAutoString id;
|
||||||
|
CopyASCIItoUTF16(buffer, id);
|
||||||
|
|
||||||
|
RefPtr<PaymentRequest> request = new PaymentRequest(aWindow, id);
|
||||||
|
return request.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
PaymentRequest::PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId)
|
||||||
|
: DOMEventTargetHelper(aWindow)
|
||||||
|
, mInternalId(aInternalId)
|
||||||
|
, mUpdating(false)
|
||||||
|
, mState(eCreated)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
PaymentRequest::Show(ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
PaymentRequest::CanMakePayment(ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise>
|
||||||
|
PaymentRequest::Abort(ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequest::GetId(nsAString& aRetVal) const
|
||||||
|
{
|
||||||
|
aRetVal = mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequest::GetInternalId(nsAString& aRetVal)
|
||||||
|
{
|
||||||
|
aRetVal = mInternalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequest::SetId(const nsAString& aId)
|
||||||
|
{
|
||||||
|
mId = aId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequest::Equals(const nsAString& aInternalId) const
|
||||||
|
{
|
||||||
|
return mInternalId.Equals(aInternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequest::SetUpdating(bool aUpdating)
|
||||||
|
{
|
||||||
|
mUpdating = aUpdating;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequest::GetShippingOption(nsAString& aRetVal) const
|
||||||
|
{
|
||||||
|
aRetVal = mShippingOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nullable<PaymentShippingType>
|
||||||
|
PaymentRequest::GetShippingType() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaymentRequest::~PaymentRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
PaymentRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
|
{
|
||||||
|
return PaymentRequestBinding::Wrap(aCx, this, aGivenProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
110
dom/payments/PaymentRequest.h
Normal file
110
dom/payments/PaymentRequest.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequest_h
|
||||||
|
#define mozilla_dom_PaymentRequest_h
|
||||||
|
|
||||||
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestBinding.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/ErrorResult.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class EventHandlerNonNull;
|
||||||
|
class PaymentResponse;
|
||||||
|
|
||||||
|
class PaymentRequest final : public DOMEventTargetHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentRequest, DOMEventTargetHelper)
|
||||||
|
|
||||||
|
virtual JSObject* WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
static already_AddRefed<PaymentRequest>
|
||||||
|
CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv);
|
||||||
|
|
||||||
|
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsValidNumber(const nsAString& aItem,
|
||||||
|
const nsAString& aStr,
|
||||||
|
nsAString& aErrorMsg);
|
||||||
|
static bool
|
||||||
|
IsPositiveNumber(const nsAString& aItem,
|
||||||
|
const nsAString& aStr,
|
||||||
|
nsAString& aErrorMsg);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsValidDetailsInit(const PaymentDetailsInit& aDetails,
|
||||||
|
nsAString& aErrorMsg);
|
||||||
|
static bool
|
||||||
|
IsValidDetailsBase(const PaymentDetailsBase& aDetails,
|
||||||
|
nsAString& aErrorMsg);
|
||||||
|
|
||||||
|
static already_AddRefed<PaymentRequest>
|
||||||
|
Constructor(const GlobalObject& aGlobal,
|
||||||
|
const Sequence<PaymentMethodData>& aMethodData,
|
||||||
|
const PaymentDetailsInit& aDetails,
|
||||||
|
const PaymentOptions& aOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
already_AddRefed<Promise> Show(ErrorResult& aRv);
|
||||||
|
already_AddRefed<Promise> Abort(ErrorResult& aRv);
|
||||||
|
already_AddRefed<Promise> CanMakePayment(ErrorResult& aRv);
|
||||||
|
|
||||||
|
void GetId(nsAString& aRetVal) const;
|
||||||
|
void GetInternalId(nsAString& aRetVal);
|
||||||
|
void SetId(const nsAString& aId);
|
||||||
|
|
||||||
|
bool Equals(const nsAString& aInternalId) const;
|
||||||
|
|
||||||
|
void SetUpdating(bool aUpdating);
|
||||||
|
|
||||||
|
void GetShippingOption(nsAString& aRetVal) const;
|
||||||
|
|
||||||
|
Nullable<PaymentShippingType> GetShippingType() const;
|
||||||
|
|
||||||
|
IMPL_EVENT_HANDLER(shippingaddresschange);
|
||||||
|
IMPL_EVENT_HANDLER(shippingoptionchange);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~PaymentRequest();
|
||||||
|
|
||||||
|
PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId);
|
||||||
|
|
||||||
|
// Id for internal identification
|
||||||
|
nsString mInternalId;
|
||||||
|
// Id for communicating with merchant side
|
||||||
|
// mId is initialized to details.id if it exists
|
||||||
|
// otherwise, mId has the same value as mInternalId.
|
||||||
|
nsString mId;
|
||||||
|
// It is populated when the user chooses a shipping option.
|
||||||
|
nsString mShippingOption;
|
||||||
|
|
||||||
|
// "true" when there is a pending updateWith() call to update the payment request
|
||||||
|
// and "false" otherwise.
|
||||||
|
bool mUpdating;
|
||||||
|
// The error is set in AbortUpdate(). The value is NS_OK by default.
|
||||||
|
//nsresult mUpdateError;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
eUnknown,
|
||||||
|
eCreated,
|
||||||
|
eInteractive,
|
||||||
|
eClosed
|
||||||
|
} mState;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_PaymentRequest_h
|
660
dom/payments/PaymentRequestData.cpp
Normal file
660
dom/payments/PaymentRequestData.cpp
Normal file
@ -0,0 +1,660 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "nsArrayUtils.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "nsISupportsPrimitives.h"
|
||||||
|
#include "PaymentRequestData.h"
|
||||||
|
#include "PaymentRequestUtils.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace payments {
|
||||||
|
|
||||||
|
/* PaymentMethodData */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentMethodData,
|
||||||
|
nsIPaymentMethodData)
|
||||||
|
|
||||||
|
PaymentMethodData::PaymentMethodData(nsIArray* aSupportedMethods,
|
||||||
|
const nsAString& aData)
|
||||||
|
: mSupportedMethods(aSupportedMethods)
|
||||||
|
, mData(aData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentMethodData::Create(const IPCPaymentMethodData& aIPCMethodData,
|
||||||
|
nsIPaymentMethodData** aMethodData)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aMethodData);
|
||||||
|
nsCOMPtr<nsIArray> supportedMethods;
|
||||||
|
nsresult rv = ConvertStringstoISupportsStrings(aIPCMethodData.supportedMethods(),
|
||||||
|
getter_AddRefs(supportedMethods));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentMethodData> methodData =
|
||||||
|
new PaymentMethodData(supportedMethods, aIPCMethodData.data());
|
||||||
|
methodData.forget(aMethodData);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentMethodData::GetSupportedMethods(nsIArray** aSupportedMethods)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aSupportedMethods);
|
||||||
|
MOZ_ASSERT(mSupportedMethods);
|
||||||
|
nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
|
||||||
|
supportedMethods.forget(aSupportedMethods);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentMethodData::GetData(nsAString& aData)
|
||||||
|
{
|
||||||
|
aData = mData;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentCurrencyAmount */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentCurrencyAmount,
|
||||||
|
nsIPaymentCurrencyAmount)
|
||||||
|
|
||||||
|
PaymentCurrencyAmount::PaymentCurrencyAmount(const nsAString& aCurrency,
|
||||||
|
const nsAString& aValue)
|
||||||
|
: mCurrency(aCurrency)
|
||||||
|
, mValue(aValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentCurrencyAmount::Create(const IPCPaymentCurrencyAmount& aIPCAmount,
|
||||||
|
nsIPaymentCurrencyAmount** aAmount)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aAmount);
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> amount =
|
||||||
|
new PaymentCurrencyAmount(aIPCAmount.currency(), aIPCAmount.value());
|
||||||
|
amount.forget(aAmount);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCurrencyAmount::GetCurrency(nsAString& aCurrency)
|
||||||
|
{
|
||||||
|
aCurrency = mCurrency;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentCurrencyAmount::GetValue(nsAString& aValue)
|
||||||
|
{
|
||||||
|
aValue = mValue;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentItem */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentItem,
|
||||||
|
nsIPaymentItem)
|
||||||
|
|
||||||
|
PaymentItem::PaymentItem(const nsAString& aLabel,
|
||||||
|
nsIPaymentCurrencyAmount* aAmount,
|
||||||
|
const bool aPending)
|
||||||
|
: mLabel(aLabel)
|
||||||
|
, mAmount(aAmount)
|
||||||
|
, mPending(aPending)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentItem::Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aItem);
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> amount;
|
||||||
|
nsresult rv = PaymentCurrencyAmount::Create(aIPCItem.amount(),
|
||||||
|
getter_AddRefs(amount));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentItem> item =
|
||||||
|
new PaymentItem(aIPCItem.label(), amount, aIPCItem.pending());
|
||||||
|
item.forget(aItem);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentItem::GetLabel(nsAString& aLabel)
|
||||||
|
{
|
||||||
|
aLabel = mLabel;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentItem::GetAmount(nsIPaymentCurrencyAmount** aAmount)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aAmount);
|
||||||
|
MOZ_ASSERT(mAmount);
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
|
||||||
|
amount.forget(aAmount);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentItem::GetPending(bool* aPending)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPending);
|
||||||
|
*aPending = mPending;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentDetailsModifier */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentDetailsModifier,
|
||||||
|
nsIPaymentDetailsModifier)
|
||||||
|
|
||||||
|
PaymentDetailsModifier::PaymentDetailsModifier(nsIArray* aSupportedMethods,
|
||||||
|
nsIPaymentItem* aTotal,
|
||||||
|
nsIArray* aAdditionalDisplayItems,
|
||||||
|
const nsAString& aData)
|
||||||
|
: mSupportedMethods(aSupportedMethods)
|
||||||
|
, mTotal(aTotal)
|
||||||
|
, mAdditionalDisplayItems(aAdditionalDisplayItems)
|
||||||
|
, mData(aData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentDetailsModifier::Create(const IPCPaymentDetailsModifier& aIPCModifier,
|
||||||
|
nsIPaymentDetailsModifier** aModifier)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aModifier);
|
||||||
|
nsCOMPtr<nsIPaymentItem> total;
|
||||||
|
nsresult rv = PaymentItem::Create(aIPCModifier.total(), getter_AddRefs(total));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> supportedMethods;
|
||||||
|
rv = ConvertStringstoISupportsStrings(aIPCModifier.supportedMethods(),
|
||||||
|
getter_AddRefs(supportedMethods));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> displayItems;
|
||||||
|
if (aIPCModifier.additionalDisplayItemsPassed()) {
|
||||||
|
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
MOZ_ASSERT(items);
|
||||||
|
for (const IPCPaymentItem& item : aIPCModifier.additionalDisplayItems()) {
|
||||||
|
nsCOMPtr<nsIPaymentItem> additionalItem;
|
||||||
|
rv = PaymentItem::Create(item, getter_AddRefs(additionalItem));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = items->AppendElement(additionalItem, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayItems = items.forget();
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentDetailsModifier> modifier =
|
||||||
|
new PaymentDetailsModifier(supportedMethods, total, displayItems, aIPCModifier.data());
|
||||||
|
modifier.forget(aModifier);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetailsModifier::GetSupportedMethods(nsIArray** aSupportedMethods)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aSupportedMethods);
|
||||||
|
MOZ_ASSERT(mSupportedMethods);
|
||||||
|
nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
|
||||||
|
supportedMethods.forget(aSupportedMethods);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetailsModifier::GetTotal(nsIPaymentItem** aTotal)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aTotal);
|
||||||
|
MOZ_ASSERT(mTotal);
|
||||||
|
nsCOMPtr<nsIPaymentItem> total = mTotal;
|
||||||
|
total.forget(aTotal);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetailsModifier::GetAdditionalDisplayItems(nsIArray** aAdditionalDisplayItems)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aAdditionalDisplayItems);
|
||||||
|
nsCOMPtr<nsIArray> additionalItems = mAdditionalDisplayItems;
|
||||||
|
additionalItems.forget(aAdditionalDisplayItems);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetailsModifier::GetData(nsAString& aData)
|
||||||
|
{
|
||||||
|
aData = mData;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentShippingOption */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentShippingOption,
|
||||||
|
nsIPaymentShippingOption)
|
||||||
|
|
||||||
|
PaymentShippingOption::PaymentShippingOption(const nsAString& aId,
|
||||||
|
const nsAString& aLabel,
|
||||||
|
nsIPaymentCurrencyAmount* aAmount,
|
||||||
|
const bool aSelected)
|
||||||
|
: mId(aId)
|
||||||
|
, mLabel(aLabel)
|
||||||
|
, mAmount(aAmount)
|
||||||
|
, mSelected(aSelected)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentShippingOption::Create(const IPCPaymentShippingOption& aIPCOption,
|
||||||
|
nsIPaymentShippingOption** aOption)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aOption);
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> amount;
|
||||||
|
nsresult rv = PaymentCurrencyAmount::Create(aIPCOption.amount(), getter_AddRefs(amount));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentShippingOption> option =
|
||||||
|
new PaymentShippingOption(aIPCOption.id(), aIPCOption.label(), amount, aIPCOption.selected());
|
||||||
|
option.forget(aOption);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentShippingOption::GetId(nsAString& aId)
|
||||||
|
{
|
||||||
|
aId = mId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentShippingOption::GetLabel(nsAString& aLabel)
|
||||||
|
{
|
||||||
|
aLabel = mLabel;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentShippingOption::GetAmount(nsIPaymentCurrencyAmount** aAmount)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aAmount);
|
||||||
|
MOZ_ASSERT(mAmount);
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
|
||||||
|
amount.forget(aAmount);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentShippingOption::GetSelected(bool* aSelected)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aSelected);
|
||||||
|
*aSelected = mSelected;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentShippingOption::SetSelected(bool aSelected)
|
||||||
|
{
|
||||||
|
mSelected = aSelected;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentDetails */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentDetails,
|
||||||
|
nsIPaymentDetails)
|
||||||
|
|
||||||
|
PaymentDetails::PaymentDetails(const nsAString& aId,
|
||||||
|
nsIPaymentItem* aTotalItem,
|
||||||
|
nsIArray* aDisplayItems,
|
||||||
|
nsIArray* aShippingOptions,
|
||||||
|
nsIArray* aModifiers,
|
||||||
|
const nsAString& aError)
|
||||||
|
: mId(aId)
|
||||||
|
, mTotalItem(aTotalItem)
|
||||||
|
, mDisplayItems(aDisplayItems)
|
||||||
|
, mShippingOptions(aShippingOptions)
|
||||||
|
, mModifiers(aModifiers)
|
||||||
|
, mError(aError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentDetails::Create(const IPCPaymentDetails& aIPCDetails,
|
||||||
|
nsIPaymentDetails** aDetails)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aDetails);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentItem> total;
|
||||||
|
nsresult rv = PaymentItem::Create(aIPCDetails.total(), getter_AddRefs(total));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> displayItems;
|
||||||
|
if (aIPCDetails.displayItemsPassed()) {
|
||||||
|
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
MOZ_ASSERT(items);
|
||||||
|
for (const IPCPaymentItem& displayItem : aIPCDetails.displayItems()) {
|
||||||
|
nsCOMPtr<nsIPaymentItem> item;
|
||||||
|
rv = PaymentItem::Create(displayItem, getter_AddRefs(item));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = items->AppendElement(item, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayItems = items.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> shippingOptions;
|
||||||
|
if (aIPCDetails.shippingOptionsPassed()) {
|
||||||
|
nsCOMPtr<nsIMutableArray> options = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
MOZ_ASSERT(options);
|
||||||
|
for (const IPCPaymentShippingOption& shippingOption : aIPCDetails.shippingOptions()) {
|
||||||
|
nsCOMPtr<nsIPaymentShippingOption> option;
|
||||||
|
rv = PaymentShippingOption::Create(shippingOption, getter_AddRefs(option));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = options->AppendElement(option, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shippingOptions = options.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> modifiers;
|
||||||
|
if (aIPCDetails.modifiersPassed()) {
|
||||||
|
nsCOMPtr<nsIMutableArray> detailsModifiers = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
MOZ_ASSERT(detailsModifiers);
|
||||||
|
for (const IPCPaymentDetailsModifier& modifier : aIPCDetails.modifiers()) {
|
||||||
|
nsCOMPtr<nsIPaymentDetailsModifier> detailsModifier;
|
||||||
|
rv = PaymentDetailsModifier::Create(modifier, getter_AddRefs(detailsModifier));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = detailsModifiers->AppendElement(detailsModifier, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modifiers = detailsModifiers.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentDetails> details =
|
||||||
|
new PaymentDetails(aIPCDetails.id(), total, displayItems, shippingOptions,
|
||||||
|
modifiers, aIPCDetails.error());
|
||||||
|
|
||||||
|
details.forget(aDetails);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetId(nsAString& aId)
|
||||||
|
{
|
||||||
|
aId = mId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetTotalItem(nsIPaymentItem** aTotalItem)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aTotalItem);
|
||||||
|
MOZ_ASSERT(mTotalItem);
|
||||||
|
nsCOMPtr<nsIPaymentItem> total = mTotalItem;
|
||||||
|
total.forget(aTotalItem);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetDisplayItems(nsIArray** aDisplayItems)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aDisplayItems);
|
||||||
|
nsCOMPtr<nsIArray> displayItems = mDisplayItems;
|
||||||
|
displayItems.forget(aDisplayItems);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetShippingOptions(nsIArray** aShippingOptions)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aShippingOptions);
|
||||||
|
nsCOMPtr<nsIArray> options = mShippingOptions;
|
||||||
|
options.forget(aShippingOptions);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetModifiers(nsIArray** aModifiers)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aModifiers);
|
||||||
|
nsCOMPtr<nsIArray> modifiers = mModifiers;
|
||||||
|
modifiers.forget(aModifiers);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::GetError(nsAString& aError)
|
||||||
|
{
|
||||||
|
aError = mError;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentDetails::Update(nsIPaymentDetails* aDetails)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aDetails);
|
||||||
|
/*
|
||||||
|
* According to the spec [1], update the attributes if they present in new
|
||||||
|
* details (i.e., PaymentDetailsUpdate); otherwise, keep original value.
|
||||||
|
* Note |id| comes only from initial details (i.e., PaymentDetailsInit) and
|
||||||
|
* |error| only from new details.
|
||||||
|
*
|
||||||
|
* [1] https://www.w3.org/TR/payment-request/#updatewith-method
|
||||||
|
*/
|
||||||
|
|
||||||
|
nsresult rv = aDetails->GetTotalItem(getter_AddRefs(mTotalItem));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> displayItems;
|
||||||
|
rv = aDetails->GetDisplayItems(getter_AddRefs(displayItems));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
if (displayItems) {
|
||||||
|
mDisplayItems = displayItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> shippingOptions;
|
||||||
|
rv = aDetails->GetShippingOptions(getter_AddRefs(shippingOptions));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
if (shippingOptions) {
|
||||||
|
mShippingOptions = shippingOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> modifiers;
|
||||||
|
rv = aDetails->GetModifiers(getter_AddRefs(modifiers));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
if (modifiers) {
|
||||||
|
mModifiers = modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = aDetails->GetError(mError);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* PaymentOptions */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentOptions,
|
||||||
|
nsIPaymentOptions)
|
||||||
|
|
||||||
|
PaymentOptions::PaymentOptions(const bool aRequestPayerName,
|
||||||
|
const bool aRequestPayerEmail,
|
||||||
|
const bool aRequestPayerPhone,
|
||||||
|
const bool aRequestShipping,
|
||||||
|
const nsAString& aShippingType)
|
||||||
|
: mRequestPayerName(aRequestPayerName)
|
||||||
|
, mRequestPayerEmail(aRequestPayerEmail)
|
||||||
|
, mRequestPayerPhone(aRequestPayerPhone)
|
||||||
|
, mRequestShipping(aRequestShipping)
|
||||||
|
, mShippingType(aShippingType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentOptions::Create(const IPCPaymentOptions& aIPCOptions,
|
||||||
|
nsIPaymentOptions** aOptions)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aOptions);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentOptions> options =
|
||||||
|
new PaymentOptions(aIPCOptions.requestPayerName(),
|
||||||
|
aIPCOptions.requestPayerEmail(),
|
||||||
|
aIPCOptions.requestPayerPhone(),
|
||||||
|
aIPCOptions.requestShipping(),
|
||||||
|
aIPCOptions.shippingType());
|
||||||
|
options.forget(aOptions);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentOptions::GetRequestPayerName(bool* aRequestPayerName)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequestPayerName);
|
||||||
|
*aRequestPayerName = mRequestPayerName;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentOptions::GetRequestPayerEmail(bool* aRequestPayerEmail)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequestPayerEmail);
|
||||||
|
*aRequestPayerEmail = mRequestPayerEmail;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentOptions::GetRequestPayerPhone(bool* aRequestPayerPhone)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequestPayerPhone);
|
||||||
|
*aRequestPayerPhone = mRequestPayerPhone;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentOptions::GetRequestShipping(bool* aRequestShipping)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequestShipping);
|
||||||
|
*aRequestShipping = mRequestShipping;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentOptions::GetShippingType(nsAString& aShippingType)
|
||||||
|
{
|
||||||
|
aShippingType = mShippingType;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PaymentReqeust */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentRequest,
|
||||||
|
nsIPaymentRequest)
|
||||||
|
|
||||||
|
PaymentRequest::PaymentRequest(const uint64_t aTabId,
|
||||||
|
const nsAString& aRequestId,
|
||||||
|
nsIArray* aPaymentMethods,
|
||||||
|
nsIPaymentDetails* aPaymentDetails,
|
||||||
|
nsIPaymentOptions* aPaymentOptions)
|
||||||
|
: mTabId(aTabId)
|
||||||
|
, mRequestId(aRequestId)
|
||||||
|
, mPaymentMethods(aPaymentMethods)
|
||||||
|
, mPaymentDetails(aPaymentDetails)
|
||||||
|
, mPaymentOptions(aPaymentOptions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::GetTabId(uint64_t* aTabId)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aTabId);
|
||||||
|
*aTabId = mTabId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::GetRequestId(nsAString& aRequestId)
|
||||||
|
{
|
||||||
|
aRequestId = mRequestId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::GetPaymentMethods(nsIArray** aPaymentMethods)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPaymentMethods);
|
||||||
|
MOZ_ASSERT(mPaymentMethods);
|
||||||
|
nsCOMPtr<nsIArray> methods = mPaymentMethods;
|
||||||
|
methods.forget(aPaymentMethods);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::GetPaymentDetails(nsIPaymentDetails** aPaymentDetails)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPaymentDetails);
|
||||||
|
MOZ_ASSERT(mPaymentDetails);
|
||||||
|
nsCOMPtr<nsIPaymentDetails> details = mPaymentDetails;
|
||||||
|
details.forget(aPaymentDetails);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::GetPaymentOptions(nsIPaymentOptions** aPaymentOptions)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPaymentOptions);
|
||||||
|
MOZ_ASSERT(mPaymentOptions);
|
||||||
|
nsCOMPtr<nsIPaymentOptions> options = mPaymentOptions;
|
||||||
|
options.forget(aPaymentOptions);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequest::UpdatePaymentDetails(nsIPaymentDetails* aPaymentDetails)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aPaymentDetails);
|
||||||
|
return mPaymentDetails->Update(aPaymentDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace payment
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
199
dom/payments/PaymentRequestData.h
Normal file
199
dom/payments/PaymentRequestData.h
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestData_h
|
||||||
|
#define mozilla_dom_PaymentRequestData_h
|
||||||
|
|
||||||
|
#include "nsIPaymentRequest.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "mozilla/dom/PPaymentRequest.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace payments {
|
||||||
|
|
||||||
|
class PaymentMethodData final : public nsIPaymentMethodData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTMETHODDATA
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentMethodData& aIPCMethodData,
|
||||||
|
nsIPaymentMethodData** aMethodData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentMethodData(nsIArray* aSupportedMethods,
|
||||||
|
const nsAString& aData);
|
||||||
|
|
||||||
|
~PaymentMethodData() = default;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> mSupportedMethods;
|
||||||
|
nsString mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentCurrencyAmount final : public nsIPaymentCurrencyAmount
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTCURRENCYAMOUNT
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentCurrencyAmount& aIPCAmount,
|
||||||
|
nsIPaymentCurrencyAmount** aAmount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentCurrencyAmount(const nsAString& aCurrency,
|
||||||
|
const nsAString& aValue);
|
||||||
|
|
||||||
|
~PaymentCurrencyAmount() = default;
|
||||||
|
|
||||||
|
nsString mCurrency;
|
||||||
|
nsString mValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentItem final : public nsIPaymentItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTITEM
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentItem(const nsAString& aLabel,
|
||||||
|
nsIPaymentCurrencyAmount* aAmount,
|
||||||
|
const bool aPending);
|
||||||
|
|
||||||
|
~PaymentItem() = default;
|
||||||
|
|
||||||
|
nsString mLabel;
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
|
||||||
|
bool mPending;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentDetailsModifier final : public nsIPaymentDetailsModifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTDETAILSMODIFIER
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentDetailsModifier& aIPCModifier,
|
||||||
|
nsIPaymentDetailsModifier** aModifier);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentDetailsModifier(nsIArray* aSupportedMethods,
|
||||||
|
nsIPaymentItem* aTotal,
|
||||||
|
nsIArray* aAdditionalDisplayItems,
|
||||||
|
const nsAString& aData);
|
||||||
|
|
||||||
|
~PaymentDetailsModifier() = default;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> mSupportedMethods;
|
||||||
|
nsCOMPtr<nsIPaymentItem> mTotal;
|
||||||
|
nsCOMPtr<nsIArray> mAdditionalDisplayItems;
|
||||||
|
nsString mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentShippingOption final : public nsIPaymentShippingOption
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTSHIPPINGOPTION
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentShippingOption& aIPCOption,
|
||||||
|
nsIPaymentShippingOption** aOption);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentShippingOption(const nsAString& aId,
|
||||||
|
const nsAString& aLabel,
|
||||||
|
nsIPaymentCurrencyAmount* aAmount,
|
||||||
|
const bool aSelected=false);
|
||||||
|
|
||||||
|
~PaymentShippingOption() = default;
|
||||||
|
|
||||||
|
nsString mId;
|
||||||
|
nsString mLabel;
|
||||||
|
nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
|
||||||
|
bool mSelected;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentDetails final : public nsIPaymentDetails
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTDETAILS
|
||||||
|
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentDetails& aIPCDetails,
|
||||||
|
nsIPaymentDetails** aDetails);
|
||||||
|
private:
|
||||||
|
PaymentDetails(const nsAString& aId,
|
||||||
|
nsIPaymentItem* aTotalItem,
|
||||||
|
nsIArray* aDisplayItems,
|
||||||
|
nsIArray* aShippingOptions,
|
||||||
|
nsIArray* aModifiers,
|
||||||
|
const nsAString& aError);
|
||||||
|
|
||||||
|
~PaymentDetails() = default;
|
||||||
|
|
||||||
|
nsString mId;
|
||||||
|
nsCOMPtr<nsIPaymentItem> mTotalItem;
|
||||||
|
nsCOMPtr<nsIArray> mDisplayItems;
|
||||||
|
nsCOMPtr<nsIArray> mShippingOptions;
|
||||||
|
nsCOMPtr<nsIArray> mModifiers;
|
||||||
|
nsString mError;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentOptions final : public nsIPaymentOptions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTOPTIONS
|
||||||
|
|
||||||
|
static nsresult Create(const IPCPaymentOptions& aIPCOptions,
|
||||||
|
nsIPaymentOptions** aOptions);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaymentOptions(const bool aRequestPayerName,
|
||||||
|
const bool aRequestPayerEmail,
|
||||||
|
const bool aRequestPayerPhone,
|
||||||
|
const bool aRequestShipping,
|
||||||
|
const nsAString& aShippintType);
|
||||||
|
~PaymentOptions() = default;
|
||||||
|
|
||||||
|
bool mRequestPayerName;
|
||||||
|
bool mRequestPayerEmail;
|
||||||
|
bool mRequestPayerPhone;
|
||||||
|
bool mRequestShipping;
|
||||||
|
nsString mShippingType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaymentRequest final : public nsIPaymentRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTREQUEST
|
||||||
|
|
||||||
|
PaymentRequest(const uint64_t aTabId,
|
||||||
|
const nsAString& aRequestId,
|
||||||
|
nsIArray* aPaymentMethods,
|
||||||
|
nsIPaymentDetails* aPaymentDetails,
|
||||||
|
nsIPaymentOptions* aPaymentOptions);
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PaymentRequest() = default;
|
||||||
|
|
||||||
|
uint64_t mTabId;
|
||||||
|
nsString mRequestId;
|
||||||
|
nsCOMPtr<nsIArray> mPaymentMethods;
|
||||||
|
nsCOMPtr<nsIPaymentDetails> mPaymentDetails;
|
||||||
|
nsCOMPtr<nsIPaymentOptions> mPaymentOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace payment
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
394
dom/payments/PaymentRequestManager.cpp
Normal file
394
dom/payments/PaymentRequestManager.cpp
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "PaymentRequestManager.h"
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "mozilla/dom/ContentChild.h"
|
||||||
|
#include "mozilla/dom/TabChild.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestChild.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsIJSON.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following Convert* functions are used for convert PaymentRequest structs
|
||||||
|
* to transferable structs for IPC.
|
||||||
|
*/
|
||||||
|
nsresult
|
||||||
|
SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject){
|
||||||
|
nsCOMPtr<nsIJSON> serializer = do_CreateInstance("@mozilla.org/dom/json;1");
|
||||||
|
if (NS_WARN_IF(!serializer)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
JS::RootedValue value(aCx, JS::ObjectValue(*aObject));
|
||||||
|
//JS::Value value = JS::ObjectValue(*aObject);
|
||||||
|
return serializer->EncodeFromJSVal(value.address(), aCx, aSerializedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertMethodData(const PaymentMethodData& aMethodData,
|
||||||
|
IPCPaymentMethodData& aIPCMethodData)
|
||||||
|
{
|
||||||
|
// Convert Sequence<nsString> to nsTArray<nsString>
|
||||||
|
nsTArray<nsString> supportedMethods;
|
||||||
|
for (const nsString& method : aMethodData.mSupportedMethods) {
|
||||||
|
supportedMethods.AppendElement(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JSObject to a serialized string
|
||||||
|
nsAutoString serializedData;
|
||||||
|
if (aMethodData.mData.WasPassed()) {
|
||||||
|
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||||
|
MOZ_ASSERT(cx);
|
||||||
|
JS::RootedObject object(cx, aMethodData.mData.Value());
|
||||||
|
nsresult rv = SerializeFromJSObject(cx, object, serializedData);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aIPCMethodData = IPCPaymentMethodData(supportedMethods, serializedData);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertCurrencyAmount(const PaymentCurrencyAmount& aAmount,
|
||||||
|
IPCPaymentCurrencyAmount& aIPCCurrencyAmount)
|
||||||
|
{
|
||||||
|
aIPCCurrencyAmount = IPCPaymentCurrencyAmount(aAmount.mCurrency, aAmount.mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertItem(const PaymentItem& aItem, IPCPaymentItem& aIPCItem)
|
||||||
|
{
|
||||||
|
IPCPaymentCurrencyAmount amount;
|
||||||
|
ConvertCurrencyAmount(aItem.mAmount, amount);
|
||||||
|
aIPCItem = IPCPaymentItem(aItem.mLabel, amount, aItem.mPending);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertModifier(const PaymentDetailsModifier& aModifier,
|
||||||
|
IPCPaymentDetailsModifier& aIPCModifier)
|
||||||
|
{
|
||||||
|
// Convert Sequence<nsString> to nsTArray<nsString>
|
||||||
|
nsTArray<nsString> supportedMethods;
|
||||||
|
for (const nsString& method : aModifier.mSupportedMethods) {
|
||||||
|
supportedMethods.AppendElement(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JSObject to a serialized string
|
||||||
|
nsAutoString serializedData;
|
||||||
|
if (aModifier.mData.WasPassed()) {
|
||||||
|
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||||
|
MOZ_ASSERT(cx);
|
||||||
|
JS::RootedObject object(cx, aModifier.mData.Value());
|
||||||
|
nsresult rv = SerializeFromJSObject(cx, object, serializedData);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCPaymentItem total;
|
||||||
|
ConvertItem(aModifier.mTotal, total);
|
||||||
|
|
||||||
|
nsTArray<IPCPaymentItem> additionalDisplayItems;
|
||||||
|
if (aModifier.mAdditionalDisplayItems.WasPassed()) {
|
||||||
|
for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
|
||||||
|
IPCPaymentItem displayItem;
|
||||||
|
ConvertItem(item, displayItem);
|
||||||
|
additionalDisplayItems.AppendElement(displayItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aIPCModifier = IPCPaymentDetailsModifier(supportedMethods,
|
||||||
|
total,
|
||||||
|
additionalDisplayItems,
|
||||||
|
serializedData,
|
||||||
|
aModifier.mAdditionalDisplayItems.WasPassed());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertShippingOption(const PaymentShippingOption& aOption,
|
||||||
|
IPCPaymentShippingOption& aIPCOption)
|
||||||
|
{
|
||||||
|
IPCPaymentCurrencyAmount amount;
|
||||||
|
ConvertCurrencyAmount(aOption.mAmount, amount);
|
||||||
|
aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount, aOption.mSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertDetailsBase(const PaymentDetailsBase& aDetails,
|
||||||
|
nsTArray<IPCPaymentItem>& aDisplayItems,
|
||||||
|
nsTArray<IPCPaymentShippingOption>& aShippingOptions,
|
||||||
|
nsTArray<IPCPaymentDetailsModifier>& aModifiers)
|
||||||
|
{
|
||||||
|
if (aDetails.mDisplayItems.WasPassed()) {
|
||||||
|
for (const PaymentItem& item : aDetails.mDisplayItems.Value()) {
|
||||||
|
IPCPaymentItem displayItem;
|
||||||
|
ConvertItem(item, displayItem);
|
||||||
|
aDisplayItems.AppendElement(displayItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aDetails.mShippingOptions.WasPassed()) {
|
||||||
|
for (const PaymentShippingOption& option : aDetails.mShippingOptions.Value()) {
|
||||||
|
IPCPaymentShippingOption shippingOption;
|
||||||
|
ConvertShippingOption(option, shippingOption);
|
||||||
|
aShippingOptions.AppendElement(shippingOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aDetails.mModifiers.WasPassed()) {
|
||||||
|
for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) {
|
||||||
|
IPCPaymentDetailsModifier detailsModifier;
|
||||||
|
nsresult rv = ConvertModifier(modifier, detailsModifier);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
aModifiers.AppendElement(detailsModifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertDetailsInit(const PaymentDetailsInit& aDetails,
|
||||||
|
IPCPaymentDetails& aIPCDetails)
|
||||||
|
{
|
||||||
|
// Convert PaymentDetailsBase members
|
||||||
|
nsTArray<IPCPaymentItem> displayItems;
|
||||||
|
nsTArray<IPCPaymentShippingOption> shippingOptions;
|
||||||
|
nsTArray<IPCPaymentDetailsModifier> modifiers;
|
||||||
|
nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert |id|
|
||||||
|
nsString id(EmptyString());
|
||||||
|
if (aDetails.mId.WasPassed()) {
|
||||||
|
id = aDetails.mId.Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert required |total|
|
||||||
|
IPCPaymentItem total;
|
||||||
|
ConvertItem(aDetails.mTotal, total);
|
||||||
|
|
||||||
|
aIPCDetails = IPCPaymentDetails(id,
|
||||||
|
total,
|
||||||
|
displayItems,
|
||||||
|
shippingOptions,
|
||||||
|
modifiers,
|
||||||
|
EmptyString(), // error message
|
||||||
|
aDetails.mDisplayItems.WasPassed(),
|
||||||
|
aDetails.mShippingOptions.WasPassed(),
|
||||||
|
aDetails.mModifiers.WasPassed());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertOptions(const PaymentOptions& aOptions,
|
||||||
|
IPCPaymentOptions& aIPCOption)
|
||||||
|
{
|
||||||
|
uint8_t shippingTypeIndex = static_cast<uint8_t>(aOptions.mShippingType);
|
||||||
|
nsString shippingType(NS_LITERAL_STRING("shipping"));
|
||||||
|
if (shippingTypeIndex < ArrayLength(PaymentShippingTypeValues::strings)) {
|
||||||
|
shippingType.AssignASCII(
|
||||||
|
PaymentShippingTypeValues::strings[shippingTypeIndex].value);
|
||||||
|
}
|
||||||
|
aIPCOption = IPCPaymentOptions(aOptions.mRequestPayerName,
|
||||||
|
aOptions.mRequestPayerEmail,
|
||||||
|
aOptions.mRequestPayerPhone,
|
||||||
|
aOptions.mRequestShipping,
|
||||||
|
shippingType);
|
||||||
|
}
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
|
/* PaymentRequestManager */
|
||||||
|
|
||||||
|
StaticRefPtr<PaymentRequestManager> gPaymentManager;
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentRequestManager::GetPaymentChild(PaymentRequest* aRequest,
|
||||||
|
PaymentRequestChild** aChild)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequest);
|
||||||
|
NS_ENSURE_ARG_POINTER(aChild);
|
||||||
|
*aChild = nullptr;
|
||||||
|
|
||||||
|
RefPtr<PaymentRequestChild> paymentChild;
|
||||||
|
if (mPaymentChildHash.Get(aRequest, getter_AddRefs(paymentChild))) {
|
||||||
|
paymentChild.forget(aChild);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsPIDOMWindowInner* win = aRequest->GetOwner();
|
||||||
|
NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
|
||||||
|
TabChild* tabChild = TabChild::GetFrom(win->GetDocShell());
|
||||||
|
NS_ENSURE_TRUE(tabChild, NS_ERROR_FAILURE);
|
||||||
|
nsAutoString requestId;
|
||||||
|
aRequest->GetInternalId(requestId);
|
||||||
|
|
||||||
|
// Only one payment request can interact with user at the same time.
|
||||||
|
// Before we create a new PaymentRequestChild, make sure there is no other
|
||||||
|
// payment request are interacting on the same tab.
|
||||||
|
for (auto iter = mPaymentChildHash.ConstIter(); !iter.Done(); iter.Next()) {
|
||||||
|
RefPtr<PaymentRequest> request = iter.Key();
|
||||||
|
if (request->Equals(requestId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nsPIDOMWindowInner* requestOwner = request->GetOwner();
|
||||||
|
NS_ENSURE_TRUE(requestOwner, NS_ERROR_FAILURE);
|
||||||
|
TabChild* tmpChild = TabChild::GetFrom(requestOwner->GetDocShell());
|
||||||
|
NS_ENSURE_TRUE(tmpChild, NS_ERROR_FAILURE);
|
||||||
|
if (tmpChild->GetTabId() == tabChild->GetTabId()) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentChild = new PaymentRequestChild();
|
||||||
|
tabChild->SendPPaymentRequestConstructor(paymentChild);
|
||||||
|
if (!mPaymentChildHash.Put(aRequest, paymentChild, mozilla::fallible) ) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
paymentChild.forget(aChild);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentRequestManager::ReleasePaymentChild(PaymentRequestChild* aPaymentChild)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPaymentChild);
|
||||||
|
for (auto iter = mPaymentChildHash.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
RefPtr<PaymentRequestChild> child = iter.Data();
|
||||||
|
if (NS_WARN_IF(!child)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
if (child == aPaymentChild) {
|
||||||
|
iter.Remove();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentRequestManager::ReleasePaymentChild(PaymentRequest* aRequest)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequest);
|
||||||
|
|
||||||
|
RefPtr<PaymentRequestChild> paymentChild;
|
||||||
|
if(!mPaymentChildHash.Remove(aRequest, getter_AddRefs(paymentChild))) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(!paymentChild)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
paymentChild->MaybeDelete();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequestManager>
|
||||||
|
PaymentRequestManager::GetSingleton()
|
||||||
|
{
|
||||||
|
if (!gPaymentManager) {
|
||||||
|
gPaymentManager = new PaymentRequestManager();
|
||||||
|
ClearOnShutdown(&gPaymentManager);
|
||||||
|
}
|
||||||
|
RefPtr<PaymentRequestManager> manager = gPaymentManager;
|
||||||
|
return manager.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequest>
|
||||||
|
PaymentRequestManager::GetPaymentRequestById(const nsAString& aRequestId)
|
||||||
|
{
|
||||||
|
for (const RefPtr<PaymentRequest>& request : mRequestQueue) {
|
||||||
|
if (request->Equals(aRequestId)) {
|
||||||
|
RefPtr<PaymentRequest> paymentRequest = request;
|
||||||
|
return paymentRequest.forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentRequestManager::CreatePayment(nsPIDOMWindowInner* aWindow,
|
||||||
|
const Sequence<PaymentMethodData>& aMethodData,
|
||||||
|
const PaymentDetailsInit& aDetails,
|
||||||
|
const PaymentOptions& aOptions,
|
||||||
|
PaymentRequest** aRequest)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequest);
|
||||||
|
*aRequest = nullptr;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
nsTArray<IPCPaymentMethodData> methodData;
|
||||||
|
for (const PaymentMethodData& data : aMethodData) {
|
||||||
|
IPCPaymentMethodData ipcMethodData;
|
||||||
|
rv = ConvertMethodData(data, ipcMethodData);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
methodData.AppendElement(ipcMethodData);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCPaymentDetails details;
|
||||||
|
rv = ConvertDetailsInit(aDetails, details);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCPaymentOptions options;
|
||||||
|
ConvertOptions(aOptions, options);
|
||||||
|
|
||||||
|
RefPtr<PaymentRequest> paymentRequest = PaymentRequest::CreatePaymentRequest(aWindow, rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set request's |mId| to details.id if details.id exists.
|
||||||
|
* Otherwise, set |mId| to internal id.
|
||||||
|
*/
|
||||||
|
nsAutoString requestId;
|
||||||
|
if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) {
|
||||||
|
requestId = aDetails.mId.Value();
|
||||||
|
} else {
|
||||||
|
paymentRequest->GetInternalId(requestId);
|
||||||
|
}
|
||||||
|
paymentRequest->SetId(requestId);
|
||||||
|
|
||||||
|
RefPtr<PaymentRequestChild> requestChild;
|
||||||
|
rv = GetPaymentChild(paymentRequest, getter_AddRefs(requestChild));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString internalId;
|
||||||
|
paymentRequest->GetInternalId(internalId);
|
||||||
|
IPCPaymentCreateActionRequest request(internalId,
|
||||||
|
methodData,
|
||||||
|
details,
|
||||||
|
options);
|
||||||
|
rv = requestChild->RequestPayment(request);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ReleasePaymentChild(paymentRequest);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRequestQueue.AppendElement(paymentRequest);
|
||||||
|
paymentRequest.forget(aRequest);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
65
dom/payments/PaymentRequestManager.h
Normal file
65
dom/payments/PaymentRequestManager.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestManager_h
|
||||||
|
#define mozilla_dom_PaymentRequestManager_h
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "PaymentRequest.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestBinding.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class PaymentRequestChild;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PaymentRequestManager is a singleton used to manage the created PaymentRequests.
|
||||||
|
* It is also the communication agent to chrome proces.
|
||||||
|
*/
|
||||||
|
class PaymentRequestManager final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(PaymentRequestManager)
|
||||||
|
|
||||||
|
static already_AddRefed<PaymentRequestManager> GetSingleton();
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequest>
|
||||||
|
GetPaymentRequestById(const nsAString& aRequestId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is used to create PaymentRequest object and send corresponding
|
||||||
|
* data to chrome process for internal payment creation, such that content
|
||||||
|
* process can ask specific task by sending requestId only.
|
||||||
|
*/
|
||||||
|
nsresult
|
||||||
|
CreatePayment(nsPIDOMWindowInner* aWindow,
|
||||||
|
const Sequence<PaymentMethodData>& aMethodData,
|
||||||
|
const PaymentDetailsInit& aDetails,
|
||||||
|
const PaymentOptions& aOptions,
|
||||||
|
PaymentRequest** aRequest);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ReleasePaymentChild(PaymentRequestChild* aPaymentChild);
|
||||||
|
protected:
|
||||||
|
PaymentRequestManager() = default;
|
||||||
|
~PaymentRequestManager() = default;
|
||||||
|
|
||||||
|
nsresult GetPaymentChild(PaymentRequest* aRequest,
|
||||||
|
PaymentRequestChild** aPaymentChild);
|
||||||
|
nsresult ReleasePaymentChild(PaymentRequest* aRequest);
|
||||||
|
|
||||||
|
// The container for the created PaymentRequests
|
||||||
|
nsTArray<RefPtr<PaymentRequest>> mRequestQueue;
|
||||||
|
nsRefPtrHashtable<nsRefPtrHashKey<PaymentRequest>, PaymentRequestChild> mPaymentChildHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
52
dom/payments/PaymentRequestModule.cpp
Normal file
52
dom/payments/PaymentRequestModule.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "mozilla/ModuleUtils.h"
|
||||||
|
#include "PaymentActionRequest.h"
|
||||||
|
#include "PaymentRequestService.h"
|
||||||
|
|
||||||
|
using mozilla::dom::PaymentActionRequest;
|
||||||
|
using mozilla::dom::PaymentCreateActionRequest;
|
||||||
|
using mozilla::dom::PaymentRequestService;
|
||||||
|
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentActionRequest)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentCreateActionRequest)
|
||||||
|
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(PaymentRequestService,
|
||||||
|
PaymentRequestService::GetSingleton)
|
||||||
|
|
||||||
|
NS_DEFINE_NAMED_CID(NS_PAYMENT_ACTION_REQUEST_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_PAYMENT_CREATE_ACTION_REQUEST_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_PAYMENT_REQUEST_SERVICE_CID);
|
||||||
|
|
||||||
|
static const mozilla::Module::CIDEntry kPaymentRequestCIDs[] = {
|
||||||
|
{ &kNS_PAYMENT_ACTION_REQUEST_CID, false, nullptr, PaymentActionRequestConstructor},
|
||||||
|
{ &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID, false, nullptr, PaymentCreateActionRequestConstructor},
|
||||||
|
{ &kNS_PAYMENT_REQUEST_SERVICE_CID, true, nullptr, PaymentRequestServiceConstructor },
|
||||||
|
{ nullptr }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const mozilla::Module::ContractIDEntry kPaymentRequestContracts[] = {
|
||||||
|
{ NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_ACTION_REQUEST_CID },
|
||||||
|
{ NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID },
|
||||||
|
{ NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID, &kNS_PAYMENT_REQUEST_SERVICE_CID },
|
||||||
|
{ nullptr }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const mozilla::Module::CategoryEntry kPaymentRequestCategories[] = {
|
||||||
|
{ "payment-request", "PaymentActionRequest", NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID },
|
||||||
|
{ "payment-request", "PaymentCreateActionRequest", NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID },
|
||||||
|
{ "payment-request", "PaymentRequestService", NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID },
|
||||||
|
{ nullptr }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const mozilla::Module kPaymentRequestModule = {
|
||||||
|
mozilla::Module::kVersion,
|
||||||
|
kPaymentRequestCIDs,
|
||||||
|
kPaymentRequestContracts,
|
||||||
|
kPaymentRequestCategories
|
||||||
|
};
|
||||||
|
|
||||||
|
NSMODULE_DEFN(PaymentRequestModule) = &kPaymentRequestModule;
|
201
dom/payments/PaymentRequestService.cpp
Normal file
201
dom/payments/PaymentRequestService.cpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "PaymentRequestData.h"
|
||||||
|
#include "PaymentRequestService.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
StaticRefPtr<PaymentRequestService> gPaymentService;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class PaymentRequestEnumerator final : public nsISimpleEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSISIMPLEENUMERATOR
|
||||||
|
|
||||||
|
PaymentRequestEnumerator()
|
||||||
|
: mIndex(0)
|
||||||
|
{}
|
||||||
|
private:
|
||||||
|
~PaymentRequestEnumerator() = default;
|
||||||
|
uint32_t mIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentRequestEnumerator, nsISimpleEnumerator)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestEnumerator::HasMoreElements(bool* aReturn)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aReturn);
|
||||||
|
*aReturn = false;
|
||||||
|
if (NS_WARN_IF(!gPaymentService)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
RefPtr<PaymentRequestService> service = gPaymentService;
|
||||||
|
*aReturn = mIndex < service->NumPayments();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestEnumerator::GetNext(nsISupports** aItem)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aItem);
|
||||||
|
if (NS_WARN_IF(!gPaymentService)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentRequest> request =
|
||||||
|
gPaymentService->GetPaymentRequestByIndex(mIndex);
|
||||||
|
if (NS_WARN_IF(!request)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsISupports> item = do_QueryInterface(request);
|
||||||
|
if (NS_WARN_IF(!item)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
mIndex++;
|
||||||
|
item.forget(aItem);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
||||||
|
|
||||||
|
/* PaymentRequestService */
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(PaymentRequestService,
|
||||||
|
nsIPaymentRequestService)
|
||||||
|
|
||||||
|
already_AddRefed<PaymentRequestService>
|
||||||
|
PaymentRequestService::GetSingleton()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
if (!gPaymentService) {
|
||||||
|
gPaymentService = new PaymentRequestService();
|
||||||
|
ClearOnShutdown(&gPaymentService);
|
||||||
|
}
|
||||||
|
RefPtr<PaymentRequestService> service = gPaymentService;
|
||||||
|
return service.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
PaymentRequestService::NumPayments() const
|
||||||
|
{
|
||||||
|
return mRequestQueue.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIPaymentRequest>
|
||||||
|
PaymentRequestService::GetPaymentRequestByIndex(const uint32_t aIndex)
|
||||||
|
{
|
||||||
|
if (aIndex >= mRequestQueue.Length()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[aIndex];
|
||||||
|
MOZ_ASSERT(request);
|
||||||
|
return request.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId,
|
||||||
|
nsIPaymentRequest** aRequest)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequest);
|
||||||
|
*aRequest = nullptr;
|
||||||
|
uint32_t numRequests = mRequestQueue.Length();
|
||||||
|
for (uint32_t index = 0; index < numRequests; ++index) {
|
||||||
|
nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[index];
|
||||||
|
MOZ_ASSERT(request);
|
||||||
|
nsAutoString requestId;
|
||||||
|
nsresult rv = request->GetRequestId(requestId);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (requestId == aRequestId) {
|
||||||
|
request.forget(aRequest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestService::Enumerate(nsISimpleEnumerator** aEnumerator)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aEnumerator);
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> enumerator = new PaymentRequestEnumerator();
|
||||||
|
enumerator.forget(aEnumerator);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestService::Cleanup()
|
||||||
|
{
|
||||||
|
mRequestQueue.Clear();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aRequest);
|
||||||
|
uint32_t type;
|
||||||
|
nsresult rv = aRequest->GetType(&type);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case nsIPaymentActionRequest::CREATE_ACTION: {
|
||||||
|
nsCOMPtr<nsIPaymentCreateActionRequest> request =
|
||||||
|
do_QueryInterface(aRequest);
|
||||||
|
MOZ_ASSERT(request);
|
||||||
|
uint64_t tabId;
|
||||||
|
rv = request->GetTabId(&tabId);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString requestId;
|
||||||
|
rv = request->GetRequestId(requestId);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> methodData;
|
||||||
|
rv = request->GetMethodData(getter_AddRefs(methodData));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv) || !methodData)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentDetails> details;
|
||||||
|
rv = request->GetDetails(getter_AddRefs(details));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv) || !details)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentOptions> options;
|
||||||
|
rv = request->GetOptions(getter_AddRefs(options));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv) || !options)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentRequest> payment =
|
||||||
|
new payments::PaymentRequest(tabId, requestId, methodData, details, options);
|
||||||
|
|
||||||
|
if (!mRequestQueue.AppendElement(payment, mozilla::fallible)) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
45
dom/payments/PaymentRequestService.h
Normal file
45
dom/payments/PaymentRequestService.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestService_h
|
||||||
|
#define mozilla_dom_PaymentRequestService_h
|
||||||
|
|
||||||
|
#include "nsIPaymentRequest.h"
|
||||||
|
#include "nsIPaymentRequestService.h"
|
||||||
|
#include "nsISimpleEnumerator.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
// The implmentation of nsIPaymentRequestService
|
||||||
|
|
||||||
|
class PaymentRequestService final : public nsIPaymentRequestService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPAYMENTREQUESTSERVICE
|
||||||
|
|
||||||
|
PaymentRequestService() = default;
|
||||||
|
|
||||||
|
static already_AddRefed<PaymentRequestService> GetSingleton();
|
||||||
|
|
||||||
|
already_AddRefed<nsIPaymentRequest>
|
||||||
|
GetPaymentRequestByIndex(const uint32_t index);
|
||||||
|
|
||||||
|
uint32_t NumPayments() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PaymentRequestService() = default;
|
||||||
|
|
||||||
|
FallibleTArray<nsCOMPtr<nsIPaymentRequest>> mRequestQueue;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
90
dom/payments/PaymentRequestUtils.cpp
Normal file
90
dom/payments/PaymentRequestUtils.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "nsArrayUtils.h"
|
||||||
|
#include "PaymentRequestUtils.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "nsISupportsPrimitives.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
|
||||||
|
nsIArray** aIStrings)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aIStrings);
|
||||||
|
*aIStrings = nullptr;
|
||||||
|
nsCOMPtr<nsIMutableArray> iStrings = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
for (const nsString& string : aStrings) {
|
||||||
|
nsCOMPtr<nsISupportsString> iString =
|
||||||
|
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||||
|
if (NS_WARN_IF(!iString)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
nsresult rv = iString->SetData(string);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = iStrings->AppendElement(iString, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iStrings.forget(aIStrings);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertISupportsStringstoStrings(nsIArray* aIStrings,
|
||||||
|
nsTArray<nsString>& aStrings)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aIStrings);
|
||||||
|
uint32_t length;
|
||||||
|
aStrings.Clear();
|
||||||
|
nsresult rv = aIStrings->GetLength(&length);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
for (uint32_t index = 0; index < length; ++index) {
|
||||||
|
nsCOMPtr<nsISupportsString> iString = do_QueryElementAt(aIStrings, index);
|
||||||
|
if (NS_WARN_IF(!iString)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
nsString string;
|
||||||
|
rv = iString->GetData(string);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
aStrings.AppendElement(string);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aTargetStrings);
|
||||||
|
*aTargetStrings = nullptr;
|
||||||
|
nsCOMPtr<nsIMutableArray> strings = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
uint32_t length;
|
||||||
|
nsresult rv = aSourceStrings->GetLength(&length);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
for (uint32_t index = 0; index < length; ++index) {
|
||||||
|
nsCOMPtr<nsISupportsString> string = do_QueryElementAt(aSourceStrings, index);
|
||||||
|
if (NS_WARN_IF(!string)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
strings->AppendElement(string, false);
|
||||||
|
}
|
||||||
|
strings.forget(aTargetStrings);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
30
dom/payments/PaymentRequestUtils.h
Normal file
30
dom/payments/PaymentRequestUtils.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestUtils_h
|
||||||
|
#define mozilla_dom_PaymentRequestUtils_h
|
||||||
|
|
||||||
|
#include "nsIArray.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
|
||||||
|
nsIArray** aIStrings);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ConvertISupportsStringstoStrings(nsIArray* aIStrings,
|
||||||
|
nsTArray<nsString>& aStrings);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings);
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
94
dom/payments/ipc/PPaymentRequest.ipdl
Normal file
94
dom/payments/ipc/PPaymentRequest.ipdl
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||||
|
/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
|
||||||
|
/* 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 protocol PBrowser;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
struct IPCPaymentMethodData
|
||||||
|
{
|
||||||
|
nsString[] supportedMethods;
|
||||||
|
nsString data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentCurrencyAmount
|
||||||
|
{
|
||||||
|
nsString currency;
|
||||||
|
nsString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentItem
|
||||||
|
{
|
||||||
|
nsString label;
|
||||||
|
IPCPaymentCurrencyAmount amount;
|
||||||
|
bool pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentDetailsModifier
|
||||||
|
{
|
||||||
|
nsString[] supportedMethods;
|
||||||
|
IPCPaymentItem total;
|
||||||
|
IPCPaymentItem[] additionalDisplayItems;
|
||||||
|
nsString data;
|
||||||
|
bool additionalDisplayItemsPassed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentShippingOption
|
||||||
|
{
|
||||||
|
nsString id;
|
||||||
|
nsString label;
|
||||||
|
IPCPaymentCurrencyAmount amount;
|
||||||
|
bool selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentDetails
|
||||||
|
{
|
||||||
|
nsString id;
|
||||||
|
IPCPaymentItem total;
|
||||||
|
IPCPaymentItem[] displayItems;
|
||||||
|
IPCPaymentShippingOption[] shippingOptions;
|
||||||
|
IPCPaymentDetailsModifier[] modifiers;
|
||||||
|
nsString error;
|
||||||
|
bool displayItemsPassed;
|
||||||
|
bool shippingOptionsPassed;
|
||||||
|
bool modifiersPassed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentOptions
|
||||||
|
{
|
||||||
|
bool requestPayerName;
|
||||||
|
bool requestPayerEmail;
|
||||||
|
bool requestPayerPhone;
|
||||||
|
bool requestShipping;
|
||||||
|
nsString shippingType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCPaymentCreateActionRequest
|
||||||
|
{
|
||||||
|
nsString requestId;
|
||||||
|
IPCPaymentMethodData[] methodData;
|
||||||
|
IPCPaymentDetails details;
|
||||||
|
IPCPaymentOptions options;
|
||||||
|
};
|
||||||
|
|
||||||
|
union IPCPaymentActionRequest
|
||||||
|
{
|
||||||
|
IPCPaymentCreateActionRequest;
|
||||||
|
};
|
||||||
|
|
||||||
|
sync protocol PPaymentRequest
|
||||||
|
{
|
||||||
|
manager PBrowser;
|
||||||
|
|
||||||
|
parent:
|
||||||
|
async __delete__();
|
||||||
|
|
||||||
|
async RequestPayment(IPCPaymentActionRequest aAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
53
dom/payments/ipc/PaymentRequestChild.cpp
Normal file
53
dom/payments/ipc/PaymentRequestChild.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "PaymentRequestChild.h"
|
||||||
|
#include "mozilla/dom/PaymentRequestManager.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
PaymentRequestChild::PaymentRequestChild()
|
||||||
|
: mActorAlive(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PaymentRequestChild::RequestPayment(const IPCPaymentActionRequest& aAction)
|
||||||
|
{
|
||||||
|
if (!mActorAlive) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
SendRequestPayment(aAction);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
|
{
|
||||||
|
mActorAlive = false;
|
||||||
|
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||||
|
MOZ_ASSERT(manager);
|
||||||
|
manager->ReleasePaymentChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequestChild::MaybeDelete()
|
||||||
|
{
|
||||||
|
if (mActorAlive) {
|
||||||
|
mActorAlive = false;
|
||||||
|
Send__delete__(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PaymentRequestChild::SendRequestPayment(const IPCPaymentActionRequest& aAction)
|
||||||
|
{
|
||||||
|
return PPaymentRequestChild::SendRequestPayment(aAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
37
dom/payments/ipc/PaymentRequestChild.h
Normal file
37
dom/payments/ipc/PaymentRequestChild.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestChild_h
|
||||||
|
#define mozilla_dom_PaymentRequestChild_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/PPaymentRequestChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class PaymentRequestChild final : public PPaymentRequestChild
|
||||||
|
{
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestChild);
|
||||||
|
public:
|
||||||
|
PaymentRequestChild();
|
||||||
|
|
||||||
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
|
||||||
|
void MaybeDelete();
|
||||||
|
|
||||||
|
nsresult RequestPayment(const IPCPaymentActionRequest& aAction);
|
||||||
|
private:
|
||||||
|
~PaymentRequestChild() = default;
|
||||||
|
|
||||||
|
bool SendRequestPayment(const IPCPaymentActionRequest& aAction);
|
||||||
|
|
||||||
|
bool mActorAlive;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
109
dom/payments/ipc/PaymentRequestParent.cpp
Normal file
109
dom/payments/ipc/PaymentRequestParent.cpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "mozilla/ipc/InputStreamUtils.h"
|
||||||
|
#include "nsArrayUtils.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "nsIPaymentActionRequest.h"
|
||||||
|
#include "nsIPaymentRequestService.h"
|
||||||
|
#include "nsISupportsPrimitives.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "PaymentRequestData.h"
|
||||||
|
#include "PaymentRequestParent.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
PaymentRequestParent::PaymentRequestParent(uint64_t aTabId)
|
||||||
|
: mActorAlived(true)
|
||||||
|
, mTabId(aTabId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
PaymentRequestParent::RecvRequestPayment(const IPCPaymentActionRequest& aRequest)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mActorAlived);
|
||||||
|
nsCOMPtr<nsIPaymentActionRequest> actionRequest;
|
||||||
|
nsresult rv;
|
||||||
|
switch (aRequest.type()) {
|
||||||
|
case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: {
|
||||||
|
IPCPaymentCreateActionRequest request = aRequest;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIMutableArray> methodData = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
MOZ_ASSERT(methodData);
|
||||||
|
for (IPCPaymentMethodData data : request.methodData()) {
|
||||||
|
nsCOMPtr<nsIPaymentMethodData> method;
|
||||||
|
rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
rv = methodData->AppendElement(method, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentDetails> details;
|
||||||
|
rv = payments::PaymentDetails::Create(request.details(), getter_AddRefs(details));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentOptions> options;
|
||||||
|
rv = payments::PaymentOptions::Create(request.options(), getter_AddRefs(options));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPaymentCreateActionRequest> createRequest =
|
||||||
|
do_CreateInstance(NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID);
|
||||||
|
if (NS_WARN_IF(!createRequest)) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
rv = createRequest->InitRequest(request.requestId(),
|
||||||
|
mTabId,
|
||||||
|
methodData,
|
||||||
|
details,
|
||||||
|
options);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
actionRequest = do_QueryInterface(createRequest);
|
||||||
|
MOZ_ASSERT(actionRequest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return IPC_FAIL(this, "Unexpected request type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentRequestService> service =
|
||||||
|
do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID);
|
||||||
|
MOZ_ASSERT(service);
|
||||||
|
rv = service->RequestPayment(actionRequest);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
}
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
PaymentRequestParent::Recv__delete__()
|
||||||
|
{
|
||||||
|
mActorAlived = false;
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
|
{
|
||||||
|
mActorAlived = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
40
dom/payments/ipc/PaymentRequestParent.h
Normal file
40
dom/payments/ipc/PaymentRequestParent.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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_PaymentRequestParent_h
|
||||||
|
#define mozilla_dom_PaymentRequestParent_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/PPaymentRequestParent.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class PaymentRequestParent final : public PPaymentRequestParent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestParent)
|
||||||
|
|
||||||
|
explicit PaymentRequestParent(uint64_t aTabId);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
RecvRequestPayment(const IPCPaymentActionRequest& aRequest) override;
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult Recv__delete__() override;
|
||||||
|
|
||||||
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
private:
|
||||||
|
~PaymentRequestParent() = default;
|
||||||
|
|
||||||
|
bool mActorAlived;
|
||||||
|
uint64_t mTabId;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace dom
|
||||||
|
} // end of namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
23
dom/payments/ipc/moz.build
Normal file
23
dom/payments/ipc/moz.build
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
'PaymentRequestChild.h',
|
||||||
|
'PaymentRequestParent.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'PaymentRequestChild.cpp',
|
||||||
|
'PaymentRequestParent.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
|
IPDL_SOURCES += [
|
||||||
|
'PPaymentRequest.ipdl',
|
||||||
|
]
|
||||||
|
|
||||||
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
|
FINAL_LIBRARY = 'xul'
|
35
dom/payments/moz.build
Normal file
35
dom/payments/moz.build
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
DIRS += [
|
||||||
|
'ipc',
|
||||||
|
]
|
||||||
|
|
||||||
|
EXPORTS += [
|
||||||
|
'PaymentRequestData.h',
|
||||||
|
'PaymentRequestService.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
'PaymentRequest.h',
|
||||||
|
'PaymentRequestManager.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'PaymentActionRequest.cpp',
|
||||||
|
'PaymentRequest.cpp',
|
||||||
|
'PaymentRequestData.cpp',
|
||||||
|
'PaymentRequestManager.cpp',
|
||||||
|
'PaymentRequestModule.cpp',
|
||||||
|
'PaymentRequestService.cpp',
|
||||||
|
'PaymentRequestUtils.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
||||||
|
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
11
dom/payments/test/browser.ini
Normal file
11
dom/payments/test/browser.ini
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
# skip-if !e10s will be removed once non-e10s is supported
|
||||||
|
skip-if = !e10s
|
||||||
|
support-files =
|
||||||
|
head.js
|
||||||
|
simple_payment_request.html
|
||||||
|
multiple_payment_request.html
|
||||||
|
|
||||||
|
[browser_payment_construction.js]
|
||||||
|
[browser_multiple_construction.js]
|
||||||
|
[browser_payment_in_different_tabs.js]
|
32
dom/payments/test/browser_multiple_construction.js
Normal file
32
dom/payments/test/browser_multiple_construction.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
// kTestRoot is from head.js
|
||||||
|
const kTestPage = kTestRoot + "multiple_payment_request.html";
|
||||||
|
|
||||||
|
registerCleanupFunction(cleanup);
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", true);
|
||||||
|
yield BrowserTestUtils.withNewTab(kTestPage,
|
||||||
|
function*(browser) {
|
||||||
|
|
||||||
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||||
|
ok(paymentSrv, "Fail to get PaymentRequestService.");
|
||||||
|
|
||||||
|
const paymentEnum = paymentSrv.enumerate();
|
||||||
|
ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
|
||||||
|
while (paymentEnum.hasMoreElements()) {
|
||||||
|
let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
|
||||||
|
ok(payment, "Fail to get existing payment request.");
|
||||||
|
if (payment.paymentDetails.id == "complex details") {
|
||||||
|
checkComplexPayment(payment);
|
||||||
|
} else if (payment.paymentDetails.id == "simple details") {
|
||||||
|
checkSimplePayment(payment);
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown payment.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
26
dom/payments/test/browser_payment_construction.js
Normal file
26
dom/payments/test/browser_payment_construction.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
// kTestRoot is from head.js
|
||||||
|
const kTestPage = kTestRoot + "simple_payment_request.html";
|
||||||
|
|
||||||
|
registerCleanupFunction(cleanup);
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", true);
|
||||||
|
yield BrowserTestUtils.withNewTab(kTestPage,
|
||||||
|
function*(browser) {
|
||||||
|
|
||||||
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||||
|
ok(paymentSrv, "Fail to get PaymentRequestService.");
|
||||||
|
|
||||||
|
const paymentEnum = paymentSrv.enumerate();
|
||||||
|
ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
|
||||||
|
while (paymentEnum.hasMoreElements()) {
|
||||||
|
let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
|
||||||
|
ok(payment, "Fail to get existing payment request.");
|
||||||
|
checkSimplePayment(payment);
|
||||||
|
}
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
33
dom/payments/test/browser_payment_in_different_tabs.js
Normal file
33
dom/payments/test/browser_payment_in_different_tabs.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
// kTestRoot is from head.js
|
||||||
|
const kTestPage = kTestRoot + "simple_payment_request.html";
|
||||||
|
|
||||||
|
registerCleanupFunction(cleanup);
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", true);
|
||||||
|
yield BrowserTestUtils.withNewTab(kTestPage,
|
||||||
|
function*(browser) {
|
||||||
|
yield BrowserTestUtils.withNewTab(kTestPage,
|
||||||
|
function*(browser) {
|
||||||
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||||
|
ok(paymentSrv, "Fail to get PaymentRequestService.");
|
||||||
|
|
||||||
|
const paymentEnum = paymentSrv.enumerate();
|
||||||
|
ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
|
||||||
|
let tabIds = [];
|
||||||
|
while (paymentEnum.hasMoreElements()) {
|
||||||
|
let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
|
||||||
|
ok(payment, "Fail to get existing payment request.");
|
||||||
|
checkSimplePayment(payment);
|
||||||
|
tabIds.push(payment.tabId);
|
||||||
|
}
|
||||||
|
is(tabIds.length, 2, "TabId array length should be 2.");
|
||||||
|
ok(tabIds[0] != tabIds[1], "TabIds should be different.");
|
||||||
|
Services.prefs.setBoolPref("dom.payments.request.enabled", false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
120
dom/payments/test/head.js
Normal file
120
dom/payments/test/head.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
const kTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content",
|
||||||
|
"https://example.com");
|
||||||
|
|
||||||
|
function checkSimplePayment(aSimplePayment) {
|
||||||
|
// checking the passed PaymentMethods parameter
|
||||||
|
is(aSimplePayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
|
||||||
|
|
||||||
|
const methodData = aSimplePayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
|
||||||
|
ok(methodData, "Fail to get payment methodData.");
|
||||||
|
is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
|
||||||
|
let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
|
||||||
|
is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
|
||||||
|
supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
|
||||||
|
is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
|
||||||
|
is(methodData.data, "", "method data should be empty");
|
||||||
|
|
||||||
|
// checking the passed PaymentDetails parameter
|
||||||
|
const details = aSimplePayment.paymentDetails;
|
||||||
|
is(details.id, "simple details", "details.id should be 'simple details'.");
|
||||||
|
is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
|
||||||
|
is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
|
||||||
|
is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
|
||||||
|
|
||||||
|
ok(!details.displayItems, "details.displayItems should be undefined.");
|
||||||
|
ok(!details.modifiers, "details.modifiers should be undefined.");
|
||||||
|
ok(!details.shippingOptions, "details.shippingOptions should be undefined.");
|
||||||
|
|
||||||
|
// checking the default generated PaymentOptions parameter
|
||||||
|
const paymentOptions = aSimplePayment.paymentOptions;
|
||||||
|
ok(!paymentOptions.requestPayerName, "payerName option should be false");
|
||||||
|
ok(!paymentOptions.requestPayerEmail, "payerEmail option should be false");
|
||||||
|
ok(!paymentOptions.requestPayerPhone, "payerPhone option should be false");
|
||||||
|
ok(!paymentOptions.requestShipping, "requestShipping option should be false");
|
||||||
|
is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkComplexPayment(aPayment) {
|
||||||
|
// checking the passed PaymentMethods parameter
|
||||||
|
is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
|
||||||
|
|
||||||
|
const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
|
||||||
|
ok(methodData, "Fail to get payment methodData.");
|
||||||
|
is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
|
||||||
|
let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
|
||||||
|
is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
|
||||||
|
supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
|
||||||
|
is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
|
||||||
|
is(methodData.data, "", "method data should be empty");
|
||||||
|
|
||||||
|
// checking the passed PaymentDetails parameter
|
||||||
|
const details = aPayment.paymentDetails;
|
||||||
|
is(details.id, "complex details", "details.id should be 'complex details'.");
|
||||||
|
is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
|
||||||
|
is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
|
||||||
|
is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
|
||||||
|
|
||||||
|
const displayItems = details.displayItems;
|
||||||
|
is(displayItems.length, 2, "displayItems' length should be 2.");
|
||||||
|
let item = displayItems.queryElementAt(0, Ci.nsIPaymentItem);
|
||||||
|
is(item.label, "Original donation amount", "1st display item's label should be 'Original donation amount'.");
|
||||||
|
is(item.amount.currency, "USD", "1st display item's currency should be 'USD'.");
|
||||||
|
is(item.amount.value, "-65.00", "1st display item's value should be '-65.00'.");
|
||||||
|
item = displayItems.queryElementAt(1, Ci.nsIPaymentItem);
|
||||||
|
is(item.label, "Friends and family discount", "2nd display item's label should be 'Friends and family discount'.");
|
||||||
|
is(item.amount.currency, "USD", "2nd display item's currency should be 'USD'.");
|
||||||
|
is(item.amount.value, "10.00", "2nd display item's value should be '10.00'.");
|
||||||
|
|
||||||
|
const modifiers = details.modifiers;
|
||||||
|
is(modifiers.length, 1, "modifiers' length should be 1.");
|
||||||
|
|
||||||
|
const modifier = modifiers.queryElementAt(0, Ci.nsIPaymentDetailsModifier);
|
||||||
|
const modifierSupportedMethods = modifier.supportedMethods;
|
||||||
|
is(modifierSupportedMethods.length, 1, "modifier's supported methods length should be 1.");
|
||||||
|
supportedMethod = modifierSupportedMethods.queryElementAt(0, Ci.nsISupportsString);
|
||||||
|
is(supportedMethod, "MyPay", "modifier's supported method name should be 'MyPay'.");
|
||||||
|
is(modifier.total.label, "Discounted donation", "modifier's total label should be 'Discounted donation'.");
|
||||||
|
is(modifier.total.amount.currency, "USD", "modifier's total currency should be 'USD'.");
|
||||||
|
is(modifier.total.amount.value, "45.00", "modifier's total value should be '45.00'.");
|
||||||
|
|
||||||
|
const additionalItems = modifier.additionalDisplayItems;
|
||||||
|
is(additionalItems.length, "1", "additionalDisplayItems' length should be 1.");
|
||||||
|
const additionalItem = additionalItems.queryElementAt(0, Ci.nsIPaymentItem);
|
||||||
|
is(additionalItem.label, "MyPay discount", "additional item's label should be 'MyPay discount'.");
|
||||||
|
is(additionalItem.amount.currency, "USD", "additional item's currency should be 'USD'.");
|
||||||
|
is(additionalItem.amount.value, "-10.00", "additional item's value should be '-10.00'.");
|
||||||
|
is(modifier.data, "{\"discountProgramParticipantId\":\"86328764873265\"}",
|
||||||
|
"modifier's data should be '{\"discountProgramParticipantId\":\"86328764873265\"}'.");
|
||||||
|
|
||||||
|
const shippingOptions = details.shippingOptions;
|
||||||
|
is(shippingOptions.length, 2, "shippingOptions' length should be 2.");
|
||||||
|
|
||||||
|
let shippingOption = shippingOptions.queryElementAt(0, Ci.nsIPaymentShippingOption);
|
||||||
|
is(shippingOption.id, "NormalShipping", "1st shippingOption's id should be 'NoramlShpping'.");
|
||||||
|
is(shippingOption.label, "NormalShipping", "1st shippingOption's lable should be 'NormalShipping'.");
|
||||||
|
is(shippingOption.amount.currency, "USD", "1st shippingOption's amount currency should be 'USD'.");
|
||||||
|
is(shippingOption.amount.value, "10.00", "1st shippingOption's amount value should be '10.00'.");
|
||||||
|
ok(shippingOption.selected, "1st shippingOption should be selected.");
|
||||||
|
|
||||||
|
shippingOption = shippingOptions.queryElementAt(1, Ci.nsIPaymentShippingOption);
|
||||||
|
is(shippingOption.id, "FastShipping", "2nd shippingOption's id should be 'FastShpping'.");
|
||||||
|
is(shippingOption.label, "FastShipping", "2nd shippingOption's lable should be 'FastShipping'.");
|
||||||
|
is(shippingOption.amount.currency, "USD", "2nd shippingOption's amount currency should be 'USD'.");
|
||||||
|
is(shippingOption.amount.value, "30.00", "2nd shippingOption's amount value should be '30.00'.");
|
||||||
|
ok(!shippingOption.selected, "2nd shippingOption should not be selected.");
|
||||||
|
|
||||||
|
// checking the passed PaymentOptions parameter
|
||||||
|
const paymentOptions = aPayment.paymentOptions;
|
||||||
|
ok(paymentOptions.requestPayerName, "payerName option should be true");
|
||||||
|
ok(paymentOptions.requestPayerEmail, "payerEmail option should be true");
|
||||||
|
ok(paymentOptions.requestPayerPhone, "payerPhone option should be true");
|
||||||
|
ok(paymentOptions.requestShipping, "requestShipping option should be true");
|
||||||
|
is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||||
|
if (paymentSrv) {
|
||||||
|
paymentSrv.cleanup();
|
||||||
|
}
|
||||||
|
}
|
84
dom/payments/test/multiple_payment_request.html
Normal file
84
dom/payments/test/multiple_payment_request.html
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Payment Request Testing</title>
|
||||||
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||||
|
<meta content="utf-8" http-equiv="encoding">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const supportedInstruments = [{
|
||||||
|
supportedMethods: [ "MyPay", "TestPay" ]
|
||||||
|
}];
|
||||||
|
const complexDetails = {
|
||||||
|
id: "complex details",
|
||||||
|
total: {
|
||||||
|
label: "Donation",
|
||||||
|
amount: { currency: "USD", value: "55.00" }
|
||||||
|
},
|
||||||
|
displayItems: [
|
||||||
|
{
|
||||||
|
label: "Original donation amount",
|
||||||
|
amount: { currency: "USD", value: "-65.00", }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Friends and family discount",
|
||||||
|
amount: { currency: "USD", value: "10.00", }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
supportedMethods: ["MyPay"],
|
||||||
|
total: {
|
||||||
|
label: "Discounted donation",
|
||||||
|
amount: { currency: "USD", value: "45.00", }
|
||||||
|
},
|
||||||
|
additionalDisplayItems: [
|
||||||
|
{
|
||||||
|
label: "MyPay discount",
|
||||||
|
amount: { currency: "USD", value: "-10.00", }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: { discountProgramParticipantId: "86328764873265", }
|
||||||
|
},
|
||||||
|
],
|
||||||
|
shippingOptions: [
|
||||||
|
{
|
||||||
|
id: "NormalShipping",
|
||||||
|
label: "NormalShipping",
|
||||||
|
amount: { currency: "USD", value: "10.00", },
|
||||||
|
selected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "FastShipping",
|
||||||
|
label: "FastShipping",
|
||||||
|
amount: { currency: "USD", value: "30.00", },
|
||||||
|
selected: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const simpleDetails = {
|
||||||
|
id: "simple details",
|
||||||
|
total: {
|
||||||
|
label: "Donation",
|
||||||
|
amount: { currency: "USD", value: "55.00" }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
requestPayerName: true,
|
||||||
|
requestPayerEmail: true,
|
||||||
|
requestPayerPhone: true,
|
||||||
|
requestShipping: true,
|
||||||
|
shippingType: "shipping",
|
||||||
|
};
|
||||||
|
|
||||||
|
const paymentRequest1 = new PaymentRequest(supportedInstruments,
|
||||||
|
complexDetails,
|
||||||
|
options);
|
||||||
|
const paymentRequest2 = new PaymentRequest(supportedInstruments,
|
||||||
|
simpleDetails);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
dom/payments/test/simple_payment_request.html
Normal file
23
dom/payments/test/simple_payment_request.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Payment Request Testing</title>
|
||||||
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||||
|
<meta content="utf-8" http-equiv="encoding">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const supportedInstruments = [{
|
||||||
|
supportedMethods: [ "MyPay", "TestPay" ]
|
||||||
|
}];
|
||||||
|
const details = {
|
||||||
|
id: "simple details",
|
||||||
|
total: {
|
||||||
|
label: "Donation",
|
||||||
|
amount: { currency: "USD", value: "55.00" }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const payRequest = new PaymentRequest(supportedInstruments, details);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
89
dom/webidl/PaymentRequest.webidl
Normal file
89
dom/webidl/PaymentRequest.webidl
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/.
|
||||||
|
*
|
||||||
|
* The origin of this WebIDL file is
|
||||||
|
* https://www.w3.org/TR/payment-request/#paymentrequest-interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
dictionary PaymentMethodData {
|
||||||
|
required sequence<DOMString> supportedMethods;
|
||||||
|
object data;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentCurrencyAmount {
|
||||||
|
required DOMString currency;
|
||||||
|
required DOMString value;
|
||||||
|
DOMString currencySystem = "urn:iso:std:iso:4217";
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentItem {
|
||||||
|
required DOMString label;
|
||||||
|
required PaymentCurrencyAmount amount;
|
||||||
|
boolean pending = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentShippingOption {
|
||||||
|
required DOMString id;
|
||||||
|
required DOMString label;
|
||||||
|
required PaymentCurrencyAmount amount;
|
||||||
|
boolean selected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentDetailsModifier {
|
||||||
|
required sequence<DOMString> supportedMethods;
|
||||||
|
PaymentItem total;
|
||||||
|
sequence<PaymentItem> additionalDisplayItems;
|
||||||
|
object data;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentDetailsBase {
|
||||||
|
sequence<PaymentItem> displayItems;
|
||||||
|
sequence<PaymentShippingOption> shippingOptions;
|
||||||
|
sequence<PaymentDetailsModifier> modifiers;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentDetailsInit : PaymentDetailsBase {
|
||||||
|
DOMString id;
|
||||||
|
required PaymentItem total;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PaymentShippingType {
|
||||||
|
"shipping",
|
||||||
|
"delivery",
|
||||||
|
"pickup"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PaymentOptions {
|
||||||
|
boolean requestPayerName = false;
|
||||||
|
boolean requestPayerEmail = false;
|
||||||
|
boolean requestPayerPhone = false;
|
||||||
|
boolean requestShipping = false;
|
||||||
|
PaymentShippingType shippingType = "shipping";
|
||||||
|
};
|
||||||
|
|
||||||
|
[Constructor(sequence<PaymentMethodData> methodData, PaymentDetailsInit details,
|
||||||
|
optional PaymentOptions options),
|
||||||
|
SecureContext,
|
||||||
|
Func="mozilla::dom::PaymentRequest::PrefEnabled"]
|
||||||
|
interface PaymentRequest : EventTarget {
|
||||||
|
/* TODO : Add show() support in Bug 1345366
|
||||||
|
[NewObject]
|
||||||
|
Promise<PaymentResponse> show();
|
||||||
|
*/
|
||||||
|
[NewObject]
|
||||||
|
Promise<void> abort();
|
||||||
|
[NewObject]
|
||||||
|
Promise<boolean> canMakePayment();
|
||||||
|
|
||||||
|
readonly attribute DOMString id;
|
||||||
|
/* TODO : Add PaymentAddress support in Bug 1345369
|
||||||
|
readonly attribute PaymentAddress? shippingAddress;
|
||||||
|
*/
|
||||||
|
readonly attribute DOMString? shippingOption;
|
||||||
|
readonly attribute PaymentShippingType? shippingType;
|
||||||
|
|
||||||
|
attribute EventHandler onshippingaddresschange;
|
||||||
|
attribute EventHandler onshippingoptionchange;
|
||||||
|
};
|
@ -721,6 +721,7 @@ WEBIDL_FILES = [
|
|||||||
'PaintWorkletGlobalScope.webidl',
|
'PaintWorkletGlobalScope.webidl',
|
||||||
'PannerNode.webidl',
|
'PannerNode.webidl',
|
||||||
'ParentNode.webidl',
|
'ParentNode.webidl',
|
||||||
|
'PaymentRequest.webidl',
|
||||||
'Performance.webidl',
|
'Performance.webidl',
|
||||||
'PerformanceEntry.webidl',
|
'PerformanceEntry.webidl',
|
||||||
'PerformanceMark.webidl',
|
'PerformanceMark.webidl',
|
||||||
|
23
dom/xslt/crashtests/1361892.html
Normal file
23
dom/xslt/crashtests/1361892.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script id=o_xml type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tag_name/>
|
||||||
|
</script>
|
||||||
|
<script id=o_xslt type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="42">
|
||||||
|
<xsl:template match="*">
|
||||||
|
<xsl:value-of xmlns:regexp="http://exslt.org/regular-expressions" select="regexp:match('foo','bar','-2')"/>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
window.onload = function(){
|
||||||
|
let doc = new DOMParser(), proc = new XSLTProcessor();
|
||||||
|
proc.importStylesheet(doc.parseFromString(document.getElementById('o_xslt').textContent, "text/xml"));
|
||||||
|
proc.transformToDocument(doc.parseFromString(document.getElementById('o_xml').textContent, "text/xml"));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
</html>
|
@ -19,3 +19,4 @@ load 1089049.html
|
|||||||
load 1205163.xml
|
load 1205163.xml
|
||||||
load 1243337.xml
|
load 1243337.xml
|
||||||
load 1338277.html
|
load 1338277.html
|
||||||
|
load 1361892.html
|
||||||
|
@ -345,11 +345,13 @@ txParamArrayHolder::~txParamArrayHolder()
|
|||||||
variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
|
variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
|
||||||
"We only support cleanup of strings and interfaces "
|
"We only support cleanup of strings and interfaces "
|
||||||
"here, and this looks like neither!");
|
"here, and this looks like neither!");
|
||||||
|
if (variant.val.p != nullptr) {
|
||||||
static_cast<nsISupports*>(variant.val.p)->Release();
|
static_cast<nsISupports*>(variant.val.p)->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
txParamArrayHolder::Init(uint8_t aCount)
|
txParamArrayHolder::Init(uint8_t aCount)
|
||||||
|
@ -851,11 +851,11 @@ NotifySwitchChange(const SwitchEvent& aEvent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
|
SetProcessPriority(int aPid, ProcessPriority aPriority)
|
||||||
{
|
{
|
||||||
// n.b. The sandboxed implementation crashes; SetProcessPriority works only
|
// n.b. The sandboxed implementation crashes; SetProcessPriority works only
|
||||||
// from the main process.
|
// from the main process.
|
||||||
PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aLRU));
|
PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -437,9 +437,7 @@ void NotifySwitchStateFromInputDevice(hal::SwitchDevice aDevice,
|
|||||||
* background processes higher nice values. On other platforms, we might
|
* background processes higher nice values. On other platforms, we might
|
||||||
* ignore this call entirely.
|
* ignore this call entirely.
|
||||||
*/
|
*/
|
||||||
void SetProcessPriority(int aPid,
|
void SetProcessPriority(int aPid, hal::ProcessPriority aPriority);
|
||||||
hal::ProcessPriority aPriority,
|
|
||||||
uint32_t aLRU = 0);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,10 +11,10 @@ namespace mozilla {
|
|||||||
namespace hal_impl {
|
namespace hal_impl {
|
||||||
|
|
||||||
void
|
void
|
||||||
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
|
SetProcessPriority(int aPid, ProcessPriority aPriority)
|
||||||
{
|
{
|
||||||
HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s, %u)\n",
|
HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s)\n",
|
||||||
aPid, ProcessPriorityToString(aPriority), aLRU);
|
aPid, ProcessPriorityToString(aPriority));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace hal_impl
|
} // namespace hal_impl
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
[scriptable, uuid(bc24fb33-a0c1-49ca-aa43-05f167e02fb6)]
|
|
||||||
interface nsIRecoveryService : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Possible values of fotaStatus.result. These should stay in sync with
|
|
||||||
* librecovery/librecovery.h
|
|
||||||
*/
|
|
||||||
const long FOTA_UPDATE_UNKNOWN = 0;
|
|
||||||
const long FOTA_UPDATE_FAIL = 1;
|
|
||||||
const long FOTA_UPDATE_SUCCESS = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses recovery to wipe the data and cache partitions. If this call is
|
|
||||||
* successful, the device should reboot before the function call ever returns.
|
|
||||||
*
|
|
||||||
* @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
|
|
||||||
*/
|
|
||||||
void factoryReset(in string reason);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use recovery to install an OTA update.zip. If this call is
|
|
||||||
* successful, the device should reboot before the function call ever returns.
|
|
||||||
*
|
|
||||||
* @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
|
|
||||||
*/
|
|
||||||
void installFotaUpdate(in string updatePath);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The status of the last FOTA update. One of FOTA_UPDATE_UNKNOWN,
|
|
||||||
* FOTA_UPDATE_FAIL, FOTA_UPDATE_SUCCESS.
|
|
||||||
*/
|
|
||||||
long getFotaUpdateStatus();
|
|
||||||
};
|
|
@ -7,12 +7,6 @@
|
|||||||
with Files('**'):
|
with Files('**'):
|
||||||
BUG_COMPONENT = ('Core', 'Hardware Abstraction Layer (HAL)')
|
BUG_COMPONENT = ('Core', 'Hardware Abstraction Layer (HAL)')
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
|
||||||
'gonk/nsIRecoveryService.idl',
|
|
||||||
]
|
|
||||||
|
|
||||||
XPIDL_MODULE = 'hal'
|
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'Hal.h',
|
'Hal.h',
|
||||||
'HalImpl.h',
|
'HalImpl.h',
|
||||||
|
@ -349,7 +349,7 @@ SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
|
SetProcessPriority(int aPid, ProcessPriority aPriority)
|
||||||
{
|
{
|
||||||
NS_RUNTIMEABORT("Only the main process may set processes' priorities.");
|
NS_RUNTIMEABORT("Only the main process may set processes' priorities.");
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||||
|
#include "mozilla/ipc/URIUtils.h"
|
||||||
#include "mozilla/net/NeckoChannelParams.h"
|
#include "mozilla/net/NeckoChannelParams.h"
|
||||||
#include "ExpandedPrincipal.h"
|
#include "ExpandedPrincipal.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
@ -21,6 +22,7 @@
|
|||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
#include "mozilla/nsRedirectHistoryEntry.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
@ -258,6 +260,46 @@ IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo)
|
|||||||
return !!info.attrs().mPrivateBrowsingId;
|
return !!info.attrs().mPrivateBrowsingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIRedirectHistoryEntry>
|
||||||
|
RHEntryInfoToRHEntry(const RedirectHistoryEntryInfo& aRHEntryInfo)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIPrincipal> principal =
|
||||||
|
PrincipalInfoToPrincipal(aRHEntryInfo.principalInfo(), &rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aRHEntryInfo.referrerUri());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRedirectHistoryEntry> entry =
|
||||||
|
new nsRedirectHistoryEntry(principal, referrerUri, aRHEntryInfo.remoteAddress());
|
||||||
|
|
||||||
|
return entry.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry,
|
||||||
|
RedirectHistoryEntryInfo* aRHEntryInfo)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aRHEntry);
|
||||||
|
MOZ_ASSERT(aRHEntryInfo);
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
aRHEntry->GetRemoteAddress(aRHEntryInfo->remoteAddress());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> referrerUri;
|
||||||
|
rv = aRHEntry->GetReferrerURI(getter_AddRefs(referrerUri));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
SerializeURI(referrerUri, aRHEntryInfo->referrerUri());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
rv = aRHEntry->GetPrincipal(getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return PrincipalToPrincipalInfo(principal, &aRHEntryInfo->principalInfo());
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
||||||
OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
|
OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
|
||||||
@ -304,15 +346,19 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
|||||||
sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp;
|
sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects;
|
nsTArray<RedirectHistoryEntryInfo> redirectChainIncludingInternalRedirects;
|
||||||
for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) {
|
for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
|
||||||
rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement());
|
aLoadInfo->RedirectChainIncludingInternalRedirects()) {
|
||||||
|
RedirectHistoryEntryInfo* entry = redirectChainIncludingInternalRedirects.AppendElement();
|
||||||
|
rv = RHEntryToRHEntryInfo(redirectEntry, entry);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<PrincipalInfo> redirectChain;
|
nsTArray<RedirectHistoryEntryInfo> redirectChain;
|
||||||
for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) {
|
for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
|
||||||
rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement());
|
aLoadInfo->RedirectChain()) {
|
||||||
|
RedirectHistoryEntryInfo* entry = redirectChain.AppendElement();
|
||||||
|
rv = RHEntryToRHEntryInfo(redirectEntry, entry);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,20 +431,21 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<nsCOMPtr<nsIPrincipal>> redirectChainIncludingInternalRedirects;
|
RedirectHistoryArray redirectChainIncludingInternalRedirects;
|
||||||
for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChainIncludingInternalRedirects()) {
|
for (const RedirectHistoryEntryInfo& entryInfo :
|
||||||
nsCOMPtr<nsIPrincipal> redirectedPrincipal =
|
loadInfoArgs.redirectChainIncludingInternalRedirects()) {
|
||||||
PrincipalInfoToPrincipal(principalInfo, &rv);
|
nsCOMPtr<nsIRedirectHistoryEntry> redirectHistoryEntry =
|
||||||
|
RHEntryInfoToRHEntry(entryInfo);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
redirectChainIncludingInternalRedirects.AppendElement(redirectedPrincipal.forget());
|
redirectChainIncludingInternalRedirects.AppendElement(redirectHistoryEntry.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<nsCOMPtr<nsIPrincipal>> redirectChain;
|
RedirectHistoryArray redirectChain;
|
||||||
for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChain()) {
|
for (const RedirectHistoryEntryInfo& entryInfo : loadInfoArgs.redirectChain()) {
|
||||||
nsCOMPtr<nsIPrincipal> redirectedPrincipal =
|
nsCOMPtr<nsIRedirectHistoryEntry> redirectHistoryEntry =
|
||||||
PrincipalInfoToPrincipal(principalInfo, &rv);
|
RHEntryInfoToRHEntry(entryInfo);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
redirectChain.AppendElement(redirectedPrincipal.forget());
|
redirectChain.AppendElement(redirectHistoryEntry.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
class nsILoadInfo;
|
class nsILoadInfo;
|
||||||
class nsIPrincipal;
|
class nsIPrincipal;
|
||||||
|
class nsIRedirectHistoryEntry;
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ struct ParamTraits<mozilla::OriginAttributes>
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
class OptionalLoadInfoArgs;
|
class OptionalLoadInfoArgs;
|
||||||
|
class RedirectHistoryEntryInfo;
|
||||||
} // namespace net
|
} // namespace net
|
||||||
|
|
||||||
using namespace mozilla::net;
|
using namespace mozilla::net;
|
||||||
@ -82,6 +84,21 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
|
|||||||
bool
|
bool
|
||||||
IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo);
|
IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an RedirectHistoryEntryInfo to a nsIRedirectHistoryEntry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
already_AddRefed<nsIRedirectHistoryEntry>
|
||||||
|
RHEntryInfoToRHEntry(const RedirectHistoryEntryInfo& aRHEntryInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an nsIRedirectHistoryEntry to a RedirectHistoryEntryInfo.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry,
|
||||||
|
RedirectHistoryEntryInfo* aRHEntryInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a LoadInfo to LoadInfoArgs struct.
|
* Convert a LoadInfo to LoadInfoArgs struct.
|
||||||
*/
|
*/
|
||||||
|
@ -559,12 +559,15 @@ function StringIteratorNext() {
|
|||||||
if (first >= 0xD800 && first <= 0xDBFF && index + 1 < size) {
|
if (first >= 0xD800 && first <= 0xDBFF && index + 1 < size) {
|
||||||
var second = callFunction(std_String_charCodeAt, S, index + 1);
|
var second = callFunction(std_String_charCodeAt, S, index + 1);
|
||||||
if (second >= 0xDC00 && second <= 0xDFFF) {
|
if (second >= 0xDC00 && second <= 0xDFFF) {
|
||||||
|
first = (first - 0xD800) * 0x400 + (second - 0xDC00) + 0x10000;
|
||||||
charCount = 2;
|
charCount = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
|
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
|
||||||
result.value = callFunction(String_substring, S, index, index + charCount);
|
|
||||||
|
// Communicate |first|'s possible range to the compiler.
|
||||||
|
result.value = callFunction(std_String_fromCodePoint, null, first & 0x1fffff);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -782,6 +782,7 @@ CheckSelfTime(Phase parent,
|
|||||||
selfTimes[parent].ToMilliseconds(),
|
selfTimes[parent].ToMilliseconds(),
|
||||||
phases[child].name,
|
phases[child].name,
|
||||||
childTime.ToMilliseconds());
|
childTime.ToMilliseconds());
|
||||||
|
fflush(stderr);
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
js/src/jit-test/tests/ion/recover-newstringiterator.js
Normal file
63
js/src/jit-test/tests/ion/recover-newstringiterator.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
var max = 40;
|
||||||
|
setJitCompilerOption("ion.warmup.trigger", max - 10);
|
||||||
|
|
||||||
|
function selfhosted() {
|
||||||
|
if (typeof getSelfHostedValue === "undefined")
|
||||||
|
return;
|
||||||
|
|
||||||
|
var NewStringIterator = getSelfHostedValue("NewStringIterator");
|
||||||
|
var iter = NewStringIterator();
|
||||||
|
bailout();
|
||||||
|
// assertRecoveredOnBailout(iter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function iterator(i) {
|
||||||
|
var string = String.fromCharCode(0x41, i);
|
||||||
|
var iter = string[Symbol.iterator]();
|
||||||
|
assertEq(iter.next().value, 'A');
|
||||||
|
bailout();
|
||||||
|
// This sometimes fails
|
||||||
|
// assertRecoveredOnBailout(iter, true);
|
||||||
|
var result = iter.next();
|
||||||
|
assertEq(result.value, String.fromCharCode(i));
|
||||||
|
assertEq(result.done, false);
|
||||||
|
assertEq(iter.next().done, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function forof(i) {
|
||||||
|
var string = String.fromCharCode(0x41, i);
|
||||||
|
var first = true;
|
||||||
|
|
||||||
|
for (var x of string) {
|
||||||
|
if (first) {
|
||||||
|
assertEq(x, 'A');
|
||||||
|
bailout();
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
assertEq(x, String.fromCharCode(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
a: 'foo',
|
||||||
|
b: {c: 'd'},
|
||||||
|
str: 'ABC'
|
||||||
|
};
|
||||||
|
|
||||||
|
function fn() {
|
||||||
|
var {a, b:{c:b}, str:[, c]} = data;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function destructuring() {
|
||||||
|
for (var i = 0; i < max; i++)
|
||||||
|
assertEq(fn(), 'B');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < max; i++) {
|
||||||
|
selfhosted();
|
||||||
|
iterator(i);
|
||||||
|
forof(i);
|
||||||
|
destructuring();
|
||||||
|
}
|
@ -783,6 +783,8 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
|||||||
|
|
||||||
RootedScript script(cx, frame->script());
|
RootedScript script(cx, frame->script());
|
||||||
jsbytecode* pc = stub->icEntry()->pc(frame->script());
|
jsbytecode* pc = stub->icEntry()->pc(frame->script());
|
||||||
|
StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
|
||||||
JSOp op = JSOp(*pc);
|
JSOp op = JSOp(*pc);
|
||||||
FallbackICSpew(cx, stub, "GetElem(%s)", CodeName[op]);
|
FallbackICSpew(cx, stub, "GetElem(%s)", CodeName[op]);
|
||||||
|
|
||||||
@ -797,7 +799,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
|||||||
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
|
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
|
||||||
return false;
|
return false;
|
||||||
if (isOptimizedArgs)
|
if (isOptimizedArgs)
|
||||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
TypeScript::Monitor(cx, script, pc, types, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool attached = false;
|
bool attached = false;
|
||||||
@ -828,7 +830,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
|||||||
if (!isOptimizedArgs) {
|
if (!isOptimizedArgs) {
|
||||||
if (!GetElementOperation(cx, op, lhsCopy, rhs, res))
|
if (!GetElementOperation(cx, op, lhsCopy, rhs, res))
|
||||||
return false;
|
return false;
|
||||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
TypeScript::Monitor(cx, script, pc, types, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if debug mode toggling made the stub invalid.
|
// Check if debug mode toggling made the stub invalid.
|
||||||
@ -836,7 +838,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Add a type monitor stub for the resulting value.
|
// Add a type monitor stub for the resulting value.
|
||||||
if (!stub->addMonitorStubForValue(cx, frame, res))
|
if (!stub->addMonitorStubForValue(cx, frame, types, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (attached)
|
if (attached)
|
||||||
@ -1372,14 +1374,15 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeScript::Monitor(cx, script, pc, res);
|
StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
TypeScript::Monitor(cx, script, pc, types, res);
|
||||||
|
|
||||||
// Check if debug mode toggling made the stub invalid.
|
// Check if debug mode toggling made the stub invalid.
|
||||||
if (stub.invalid())
|
if (stub.invalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Add a type monitor stub for the resulting value.
|
// Add a type monitor stub for the resulting value.
|
||||||
if (!stub->addMonitorStubForValue(cx, frame, res))
|
if (!stub->addMonitorStubForValue(cx, frame, types, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!attached)
|
if (!attached)
|
||||||
@ -2015,6 +2018,11 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
|
|||||||
return !!res;
|
return !!res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (native == js::intrinsic_NewStringIterator) {
|
||||||
|
res.set(NewStringIteratorObject(cx, TenuredObject));
|
||||||
|
return !!res;
|
||||||
|
}
|
||||||
|
|
||||||
if (JitSupportsSimd() && GetTemplateObjectForSimd(cx, target, res))
|
if (JitSupportsSimd() && GetTemplateObjectForSimd(cx, target, res))
|
||||||
return !!res;
|
return !!res;
|
||||||
|
|
||||||
@ -2450,14 +2458,15 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint
|
|||||||
res.set(callArgs.rval());
|
res.set(callArgs.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeScript::Monitor(cx, script, pc, res);
|
StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
TypeScript::Monitor(cx, script, pc, types, res);
|
||||||
|
|
||||||
// Check if debug mode toggling made the stub invalid.
|
// Check if debug mode toggling made the stub invalid.
|
||||||
if (stub.invalid())
|
if (stub.invalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Add a type monitor stub for the resulting value.
|
// Add a type monitor stub for the resulting value.
|
||||||
if (!stub->addMonitorStubForValue(cx, frame, res))
|
if (!stub->addMonitorStubForValue(cx, frame, types, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If 'callee' is a potential Call_StringSplit, try to attach an
|
// If 'callee' is a potential Call_StringSplit, try to attach an
|
||||||
@ -2509,7 +2518,8 @@ DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Add a type monitor stub for the resulting value.
|
// Add a type monitor stub for the resulting value.
|
||||||
if (!stub->addMonitorStubForValue(cx, frame, res))
|
StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
if (!stub->addMonitorStubForValue(cx, frame, types, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!handled)
|
if (!handled)
|
||||||
|
@ -5653,16 +5653,32 @@ typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*, NewObjectKi
|
|||||||
static const VMFunction NewArrayIteratorObjectInfo =
|
static const VMFunction NewArrayIteratorObjectInfo =
|
||||||
FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject, "NewArrayIteratorObject");
|
FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject, "NewArrayIteratorObject");
|
||||||
|
|
||||||
|
typedef StringIteratorObject* (*NewStringIteratorObjectFn)(JSContext*, NewObjectKind);
|
||||||
|
static const VMFunction NewStringIteratorObjectInfo =
|
||||||
|
FunctionInfo<NewStringIteratorObjectFn>(NewStringIteratorObject, "NewStringIteratorObject");
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGenerator::visitNewArrayIterator(LNewArrayIterator* lir)
|
CodeGenerator::visitNewIterator(LNewIterator* lir)
|
||||||
{
|
{
|
||||||
Register objReg = ToRegister(lir->output());
|
Register objReg = ToRegister(lir->output());
|
||||||
Register tempReg = ToRegister(lir->temp());
|
Register tempReg = ToRegister(lir->temp());
|
||||||
JSObject* templateObject = lir->mir()->templateObject();
|
JSObject* templateObject = lir->mir()->templateObject();
|
||||||
|
|
||||||
OutOfLineCode* ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
|
OutOfLineCode* ool;
|
||||||
|
switch (lir->mir()->type()) {
|
||||||
|
case MNewIterator::ArrayIterator:
|
||||||
|
ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
|
||||||
ArgList(Imm32(GenericObject)),
|
ArgList(Imm32(GenericObject)),
|
||||||
StoreRegisterTo(objReg));
|
StoreRegisterTo(objReg));
|
||||||
|
break;
|
||||||
|
case MNewIterator::StringIterator:
|
||||||
|
ool = oolCallVM(NewStringIteratorObjectInfo, lir,
|
||||||
|
ArgList(Imm32(GenericObject)),
|
||||||
|
StoreRegisterTo(objReg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("unexpected iterator type");
|
||||||
|
}
|
||||||
|
|
||||||
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, ool->entry());
|
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, ool->entry());
|
||||||
|
|
||||||
@ -8043,24 +8059,90 @@ CodeGenerator::visitFromCodePoint(LFromCodePoint* lir)
|
|||||||
{
|
{
|
||||||
Register codePoint = ToRegister(lir->codePoint());
|
Register codePoint = ToRegister(lir->codePoint());
|
||||||
Register output = ToRegister(lir->output());
|
Register output = ToRegister(lir->output());
|
||||||
|
Register temp1 = ToRegister(lir->temp1());
|
||||||
|
Register temp2 = ToRegister(lir->temp2());
|
||||||
LSnapshot* snapshot = lir->snapshot();
|
LSnapshot* snapshot = lir->snapshot();
|
||||||
|
|
||||||
|
// The OOL path is only taken when we can't allocate the inline string.
|
||||||
OutOfLineCode* ool = oolCallVM(StringFromCodePointInfo, lir, ArgList(codePoint),
|
OutOfLineCode* ool = oolCallVM(StringFromCodePointInfo, lir, ArgList(codePoint),
|
||||||
StoreRegisterTo(output));
|
StoreRegisterTo(output));
|
||||||
|
|
||||||
|
Label isTwoByte;
|
||||||
|
Label* done = ool->rejoin();
|
||||||
|
|
||||||
|
static_assert(StaticStrings::UNIT_STATIC_LIMIT -1 == JSString::MAX_LATIN1_CHAR,
|
||||||
|
"Latin-1 strings can be loaded from static strings");
|
||||||
|
masm.branch32(Assembler::AboveOrEqual, codePoint, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
|
||||||
|
&isTwoByte);
|
||||||
|
{
|
||||||
|
masm.movePtr(ImmPtr(&GetJitContext()->runtime->staticStrings().unitStaticTable), output);
|
||||||
|
masm.loadPtr(BaseIndex(output, codePoint, ScalePointer), output);
|
||||||
|
masm.jump(done);
|
||||||
|
}
|
||||||
|
masm.bind(&isTwoByte);
|
||||||
|
{
|
||||||
// Use a bailout if the input is not a valid code point, because
|
// Use a bailout if the input is not a valid code point, because
|
||||||
// MFromCodePoint is movable and it'd be observable when a moved
|
// MFromCodePoint is movable and it'd be observable when a moved
|
||||||
// fromCodePoint throws an exception before its actual call site.
|
// fromCodePoint throws an exception before its actual call site.
|
||||||
bailoutCmp32(Assembler::Above, codePoint, Imm32(unicode::NonBMPMax), snapshot);
|
bailoutCmp32(Assembler::Above, codePoint, Imm32(unicode::NonBMPMax), snapshot);
|
||||||
|
|
||||||
// OOL path if code point >= UNIT_STATIC_LIMIT.
|
// Allocate a JSThinInlineString.
|
||||||
masm.branch32(Assembler::AboveOrEqual, codePoint, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
|
{
|
||||||
ool->entry());
|
static_assert(JSThinInlineString::MAX_LENGTH_TWO_BYTE >= 2,
|
||||||
|
"JSThinInlineString can hold a supplementary code point");
|
||||||
|
|
||||||
masm.movePtr(ImmPtr(&GetJitContext()->runtime->staticStrings().unitStaticTable), output);
|
uint32_t flags = JSString::INIT_THIN_INLINE_FLAGS;
|
||||||
masm.loadPtr(BaseIndex(output, codePoint, ScalePointer), output);
|
masm.newGCString(output, temp1, ool->entry());
|
||||||
|
masm.store32(Imm32(flags), Address(output, JSString::offsetOfFlags()));
|
||||||
|
}
|
||||||
|
|
||||||
masm.bind(ool->rejoin());
|
Label isSupplementary;
|
||||||
|
masm.branch32(Assembler::AboveOrEqual, codePoint, Imm32(unicode::NonBMPMin),
|
||||||
|
&isSupplementary);
|
||||||
|
{
|
||||||
|
// Store length.
|
||||||
|
masm.store32(Imm32(1), Address(output, JSString::offsetOfLength()));
|
||||||
|
|
||||||
|
// Load chars pointer in temp1.
|
||||||
|
masm.computeEffectiveAddress(Address(output, JSInlineString::offsetOfInlineStorage()),
|
||||||
|
temp1);
|
||||||
|
|
||||||
|
masm.store16(codePoint, Address(temp1, 0));
|
||||||
|
|
||||||
|
// Null-terminate.
|
||||||
|
masm.store16(Imm32(0), Address(temp1, sizeof(char16_t)));
|
||||||
|
|
||||||
|
masm.jump(done);
|
||||||
|
}
|
||||||
|
masm.bind(&isSupplementary);
|
||||||
|
{
|
||||||
|
// Store length.
|
||||||
|
masm.store32(Imm32(2), Address(output, JSString::offsetOfLength()));
|
||||||
|
|
||||||
|
// Load chars pointer in temp1.
|
||||||
|
masm.computeEffectiveAddress(Address(output, JSInlineString::offsetOfInlineStorage()),
|
||||||
|
temp1);
|
||||||
|
|
||||||
|
// Inlined unicode::LeadSurrogate(uint32_t).
|
||||||
|
masm.move32(codePoint, temp2);
|
||||||
|
masm.rshift32(Imm32(10), temp2);
|
||||||
|
masm.add32(Imm32(unicode::LeadSurrogateMin - (unicode::NonBMPMin >> 10)), temp2);
|
||||||
|
|
||||||
|
masm.store16(temp2, Address(temp1, 0));
|
||||||
|
|
||||||
|
// Inlined unicode::TrailSurrogate(uint32_t).
|
||||||
|
masm.move32(codePoint, temp2);
|
||||||
|
masm.and32(Imm32(0x3FF), temp2);
|
||||||
|
masm.or32(Imm32(unicode::TrailSurrogateMin), temp2);
|
||||||
|
|
||||||
|
masm.store16(temp2, Address(temp1, sizeof(char16_t)));
|
||||||
|
|
||||||
|
// Null-terminate.
|
||||||
|
masm.store16(Imm32(0), Address(temp1, 2 * sizeof(char16_t)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
masm.bind(done);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -198,7 +198,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||||||
void visitOutOfLineNewArray(OutOfLineNewArray* ool);
|
void visitOutOfLineNewArray(OutOfLineNewArray* ool);
|
||||||
void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
|
void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
|
||||||
void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
|
void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
|
||||||
void visitNewArrayIterator(LNewArrayIterator* lir);
|
void visitNewIterator(LNewIterator* lir);
|
||||||
void visitNewTypedArray(LNewTypedArray* lir);
|
void visitNewTypedArray(LNewTypedArray* lir);
|
||||||
void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir);
|
void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir);
|
||||||
void visitNewObjectVMCall(LNewObject* lir);
|
void visitNewObjectVMCall(LNewObject* lir);
|
||||||
|
@ -130,6 +130,7 @@
|
|||||||
_(IntrinsicGetNextSetEntryForIterator) \
|
_(IntrinsicGetNextSetEntryForIterator) \
|
||||||
\
|
\
|
||||||
_(IntrinsicNewArrayIterator) \
|
_(IntrinsicNewArrayIterator) \
|
||||||
|
_(IntrinsicNewStringIterator) \
|
||||||
\
|
\
|
||||||
_(IntrinsicArrayBufferByteLength) \
|
_(IntrinsicArrayBufferByteLength) \
|
||||||
_(IntrinsicPossiblyWrappedArrayBufferByteLength) \
|
_(IntrinsicPossiblyWrappedArrayBufferByteLength) \
|
||||||
|
@ -633,8 +633,8 @@ class IonBuilder
|
|||||||
InliningResult inlineArraySlice(CallInfo& callInfo);
|
InliningResult inlineArraySlice(CallInfo& callInfo);
|
||||||
InliningResult inlineArrayJoin(CallInfo& callInfo);
|
InliningResult inlineArrayJoin(CallInfo& callInfo);
|
||||||
|
|
||||||
// Array intrinsics.
|
// Iterator intrinsics.
|
||||||
InliningResult inlineNewArrayIterator(CallInfo& callInfo);
|
InliningResult inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type);
|
||||||
|
|
||||||
// Math natives.
|
// Math natives.
|
||||||
InliningResult inlineMathAbs(CallInfo& callInfo);
|
InliningResult inlineMathAbs(CallInfo& callInfo);
|
||||||
|
@ -244,9 +244,9 @@ LIRGenerator::visitNewArrayDynamicLength(MNewArrayDynamicLength* ins)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LIRGenerator::visitNewArrayIterator(MNewArrayIterator* ins)
|
LIRGenerator::visitNewIterator(MNewIterator* ins)
|
||||||
{
|
{
|
||||||
LNewArrayIterator* lir = new(alloc()) LNewArrayIterator(temp());
|
LNewIterator* lir = new(alloc()) LNewIterator(temp());
|
||||||
define(lir, ins);
|
define(lir, ins);
|
||||||
assignSafepoint(lir, ins);
|
assignSafepoint(lir, ins);
|
||||||
}
|
}
|
||||||
@ -2005,7 +2005,7 @@ LIRGenerator::visitFromCodePoint(MFromCodePoint* ins)
|
|||||||
|
|
||||||
MOZ_ASSERT(codePoint->type() == MIRType::Int32);
|
MOZ_ASSERT(codePoint->type() == MIRType::Int32);
|
||||||
|
|
||||||
LFromCodePoint* lir = new(alloc()) LFromCodePoint(useRegister(codePoint));
|
LFromCodePoint* lir = new(alloc()) LFromCodePoint(useRegister(codePoint), temp(), temp());
|
||||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||||
define(lir, ins);
|
define(lir, ins);
|
||||||
assignSafepoint(lir, ins);
|
assignSafepoint(lir, ins);
|
||||||
|
@ -78,7 +78,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||||||
void visitNewArray(MNewArray* ins);
|
void visitNewArray(MNewArray* ins);
|
||||||
void visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins);
|
void visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins);
|
||||||
void visitNewArrayDynamicLength(MNewArrayDynamicLength* ins);
|
void visitNewArrayDynamicLength(MNewArrayDynamicLength* ins);
|
||||||
void visitNewArrayIterator(MNewArrayIterator* ins);
|
void visitNewIterator(MNewIterator* ins);
|
||||||
void visitNewTypedArray(MNewTypedArray* ins);
|
void visitNewTypedArray(MNewTypedArray* ins);
|
||||||
void visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins);
|
void visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins);
|
||||||
void visitNewObject(MNewObject* ins);
|
void visitNewObject(MNewObject* ins);
|
||||||
|
@ -90,7 +90,7 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||||||
|
|
||||||
// Array intrinsics.
|
// Array intrinsics.
|
||||||
case InlinableNative::IntrinsicNewArrayIterator:
|
case InlinableNative::IntrinsicNewArrayIterator:
|
||||||
return inlineNewArrayIterator(callInfo);
|
return inlineNewIterator(callInfo, MNewIterator::ArrayIterator);
|
||||||
|
|
||||||
// Atomic natives.
|
// Atomic natives.
|
||||||
case InlinableNative::AtomicsCompareExchange:
|
case InlinableNative::AtomicsCompareExchange:
|
||||||
@ -225,6 +225,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||||||
return inlineStringReplaceString(callInfo);
|
return inlineStringReplaceString(callInfo);
|
||||||
case InlinableNative::IntrinsicStringSplitString:
|
case InlinableNative::IntrinsicStringSplitString:
|
||||||
return inlineStringSplitString(callInfo);
|
return inlineStringSplitString(callInfo);
|
||||||
|
case InlinableNative::IntrinsicNewStringIterator:
|
||||||
|
return inlineNewIterator(callInfo, MNewIterator::StringIterator);
|
||||||
|
|
||||||
// Object natives.
|
// Object natives.
|
||||||
case InlinableNative::ObjectCreate:
|
case InlinableNative::ObjectCreate:
|
||||||
@ -897,24 +899,34 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningResult
|
IonBuilder::InliningResult
|
||||||
IonBuilder::inlineNewArrayIterator(CallInfo& callInfo)
|
IonBuilder::inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type)
|
||||||
{
|
{
|
||||||
if (callInfo.argc() != 0 || callInfo.constructing()) {
|
if (callInfo.argc() != 0 || callInfo.constructing()) {
|
||||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
|
JSObject* templateObject = nullptr;
|
||||||
|
switch (type) {
|
||||||
|
case MNewIterator::ArrayIterator:
|
||||||
|
templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
|
||||||
|
MOZ_ASSERT_IF(templateObject, templateObject->is<ArrayIteratorObject>());
|
||||||
|
break;
|
||||||
|
case MNewIterator::StringIterator:
|
||||||
|
templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewStringIterator);
|
||||||
|
MOZ_ASSERT_IF(templateObject, templateObject->is<StringIteratorObject>());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!templateObject)
|
if (!templateObject)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
MOZ_ASSERT(templateObject->is<ArrayIteratorObject>());
|
|
||||||
|
|
||||||
callInfo.setImplicitlyUsedUnchecked();
|
callInfo.setImplicitlyUsedUnchecked();
|
||||||
|
|
||||||
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
||||||
current->add(templateConst);
|
current->add(templateConst);
|
||||||
|
|
||||||
MNewArrayIterator* ins = MNewArrayIterator::New(alloc(), constraints(), templateConst);
|
MNewIterator* ins = MNewIterator::New(alloc(), constraints(), templateConst, type);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
|
@ -4961,8 +4961,8 @@ MObjectState::templateObjectOf(MDefinition* obj)
|
|||||||
return obj->toCreateThisWithTemplate()->templateObject();
|
return obj->toCreateThisWithTemplate()->templateObject();
|
||||||
else if (obj->isNewCallObject())
|
else if (obj->isNewCallObject())
|
||||||
return obj->toNewCallObject()->templateObject();
|
return obj->toNewCallObject()->templateObject();
|
||||||
else if (obj->isNewArrayIterator())
|
else if (obj->isNewIterator())
|
||||||
return obj->toNewArrayIterator()->templateObject();
|
return obj->toNewIterator()->templateObject();
|
||||||
|
|
||||||
MOZ_CRASH("unreachable");
|
MOZ_CRASH("unreachable");
|
||||||
}
|
}
|
||||||
|
@ -3536,12 +3536,22 @@ class MNewObject
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MNewArrayIterator
|
class MNewIterator
|
||||||
: public MUnaryInstruction,
|
: public MUnaryInstruction,
|
||||||
public NoTypePolicy::Data
|
public NoTypePolicy::Data
|
||||||
{
|
{
|
||||||
explicit MNewArrayIterator(CompilerConstraintList* constraints, MConstant* templateConst)
|
public:
|
||||||
: MUnaryInstruction(templateConst)
|
enum Type {
|
||||||
|
ArrayIterator,
|
||||||
|
StringIterator,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type type_;
|
||||||
|
|
||||||
|
MNewIterator(CompilerConstraintList* constraints, MConstant* templateConst, Type type)
|
||||||
|
: MUnaryInstruction(templateConst),
|
||||||
|
type_(type)
|
||||||
{
|
{
|
||||||
setResultType(MIRType::Object);
|
setResultType(MIRType::Object);
|
||||||
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
|
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
|
||||||
@ -3549,9 +3559,13 @@ class MNewArrayIterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(NewArrayIterator)
|
INSTRUCTION_HEADER(NewIterator)
|
||||||
TRIVIAL_NEW_WRAPPERS
|
TRIVIAL_NEW_WRAPPERS
|
||||||
|
|
||||||
|
Type type() const {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
JSObject* templateObject() {
|
JSObject* templateObject() {
|
||||||
return getOperand(0)->toConstant()->toObjectOrNull();
|
return getOperand(0)->toConstant()->toObjectOrNull();
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ namespace jit {
|
|||||||
_(NewArray) \
|
_(NewArray) \
|
||||||
_(NewArrayCopyOnWrite) \
|
_(NewArrayCopyOnWrite) \
|
||||||
_(NewArrayDynamicLength) \
|
_(NewArrayDynamicLength) \
|
||||||
_(NewArrayIterator) \
|
_(NewIterator) \
|
||||||
_(NewTypedArray) \
|
_(NewTypedArray) \
|
||||||
_(NewTypedArrayDynamicLength) \
|
_(NewTypedArrayDynamicLength) \
|
||||||
_(NewObject) \
|
_(NewObject) \
|
||||||
|
@ -1367,25 +1367,35 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MNewArrayIterator::writeRecoverData(CompactBufferWriter& writer) const
|
MNewIterator::writeRecoverData(CompactBufferWriter& writer) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(canRecoverOnBailout());
|
MOZ_ASSERT(canRecoverOnBailout());
|
||||||
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArrayIterator));
|
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewIterator));
|
||||||
|
writer.writeByte(type_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RNewArrayIterator::RNewArrayIterator(CompactBufferReader& reader)
|
RNewIterator::RNewIterator(CompactBufferReader& reader)
|
||||||
{
|
{
|
||||||
|
type_ = reader.readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RNewArrayIterator::recover(JSContext* cx, SnapshotIterator& iter) const
|
RNewIterator::recover(JSContext* cx, SnapshotIterator& iter) const
|
||||||
{
|
{
|
||||||
RootedObject templateObject(cx, &iter.read().toObject());
|
RootedObject templateObject(cx, &iter.read().toObject());
|
||||||
RootedValue result(cx);
|
RootedValue result(cx);
|
||||||
|
|
||||||
|
JSObject* resultObject = nullptr;
|
||||||
|
switch (MNewIterator::Type(type_)) {
|
||||||
|
case MNewIterator::ArrayIterator:
|
||||||
|
resultObject = NewArrayIteratorObject(cx);
|
||||||
|
break;
|
||||||
|
case MNewIterator::StringIterator:
|
||||||
|
resultObject = NewStringIteratorObject(cx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
JSObject* resultObject = NewArrayIteratorObject(cx);
|
|
||||||
if (!resultObject)
|
if (!resultObject)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace jit {
|
|||||||
_(NewObject) \
|
_(NewObject) \
|
||||||
_(NewTypedArray) \
|
_(NewTypedArray) \
|
||||||
_(NewArray) \
|
_(NewArray) \
|
||||||
_(NewArrayIterator) \
|
_(NewIterator) \
|
||||||
_(NewDerivedTypedObject) \
|
_(NewDerivedTypedObject) \
|
||||||
_(CreateThisWithTemplate) \
|
_(CreateThisWithTemplate) \
|
||||||
_(Lambda) \
|
_(Lambda) \
|
||||||
@ -595,10 +595,13 @@ class RNewArray final : public RInstruction
|
|||||||
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
|
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RNewArrayIterator final : public RInstruction
|
class RNewIterator final : public RInstruction
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
uint8_t type_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RINSTRUCTION_HEADER_NUM_OP_(NewArrayIterator, 1)
|
RINSTRUCTION_HEADER_NUM_OP_(NewIterator, 1)
|
||||||
|
|
||||||
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
|
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
|
||||||
};
|
};
|
||||||
|
@ -139,7 +139,7 @@ static inline bool
|
|||||||
IsOptimizableObjectInstruction(MInstruction* ins)
|
IsOptimizableObjectInstruction(MInstruction* ins)
|
||||||
{
|
{
|
||||||
return ins->isNewObject() || ins->isCreateThisWithTemplate() || ins->isNewCallObject() ||
|
return ins->isNewObject() || ins->isCreateThisWithTemplate() || ins->isNewCallObject() ||
|
||||||
ins->isNewArrayIterator();
|
ins->isNewIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns False if the object is not escaped and if it is optimizable by
|
// Returns False if the object is not escaped and if it is optimizable by
|
||||||
|
@ -456,9 +456,9 @@ ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx, ICStubSpace* space)
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
|
ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
|
||||||
HandleValue val)
|
StackTypeSet* types, HandleValue val)
|
||||||
{
|
{
|
||||||
return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, val);
|
return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, types, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -2059,14 +2059,15 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_
|
|||||||
if (!ComputeGetPropResult(cx, frame, op, name, val, res))
|
if (!ComputeGetPropResult(cx, frame, op, name, val, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TypeScript::Monitor(cx, script, pc, res);
|
StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
TypeScript::Monitor(cx, script, pc, types, res);
|
||||||
|
|
||||||
// Check if debug mode toggling made the stub invalid.
|
// Check if debug mode toggling made the stub invalid.
|
||||||
if (stub.invalid())
|
if (stub.invalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Add a type monitor stub for the resulting value.
|
// Add a type monitor stub for the resulting value.
|
||||||
if (!stub->addMonitorStubForValue(cx, frame, res))
|
if (!stub->addMonitorStubForValue(cx, frame, types, res))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (attached)
|
if (attached)
|
||||||
@ -2173,8 +2174,11 @@ BaselineScript::noteAccessedGetter(uint32_t pcOffset)
|
|||||||
//
|
//
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val)
|
ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
|
||||||
|
StackTypeSet* types, HandleValue val)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(types);
|
||||||
|
|
||||||
bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
|
bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
|
||||||
MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
|
MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
|
||||||
|
|
||||||
@ -2298,7 +2302,10 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac
|
|||||||
jsbytecode* pc = stub->icEntry()->pc(script);
|
jsbytecode* pc = stub->icEntry()->pc(script);
|
||||||
TypeFallbackICSpew(cx, stub, "TypeMonitor");
|
TypeFallbackICSpew(cx, stub, "TypeMonitor");
|
||||||
|
|
||||||
if (value.isMagic()) {
|
// Copy input value to res.
|
||||||
|
res.set(value);
|
||||||
|
|
||||||
|
if (MOZ_UNLIKELY(value.isMagic())) {
|
||||||
// It's possible that we arrived here from bailing out of Ion, and that
|
// It's possible that we arrived here from bailing out of Ion, and that
|
||||||
// Ion proved that the value is dead and optimized out. In such cases,
|
// Ion proved that the value is dead and optimized out. In such cases,
|
||||||
// do nothing. However, it's also possible that we have an uninitialized
|
// do nothing. However, it's also possible that we have an uninitialized
|
||||||
@ -2306,7 +2313,6 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac
|
|||||||
|
|
||||||
if (value.whyMagic() == JS_OPTIMIZED_OUT) {
|
if (value.whyMagic() == JS_OPTIMIZED_OUT) {
|
||||||
MOZ_ASSERT(!stub->monitorsThis());
|
MOZ_ASSERT(!stub->monitorsThis());
|
||||||
res.set(value);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2317,32 +2323,38 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac
|
|||||||
MOZ_ASSERT(stub->monitorsThis() ||
|
MOZ_ASSERT(stub->monitorsThis() ||
|
||||||
*GetNextPc(pc) == JSOP_CHECKTHIS ||
|
*GetNextPc(pc) == JSOP_CHECKTHIS ||
|
||||||
*GetNextPc(pc) == JSOP_CHECKRETURN);
|
*GetNextPc(pc) == JSOP_CHECKRETURN);
|
||||||
}
|
if (stub->monitorsThis())
|
||||||
|
|
||||||
uint32_t argument;
|
|
||||||
if (stub->monitorsThis()) {
|
|
||||||
MOZ_ASSERT(pc == script->code());
|
|
||||||
if (value.isMagic(JS_UNINITIALIZED_LEXICAL))
|
|
||||||
TypeScript::SetThis(cx, script, TypeSet::UnknownType());
|
TypeScript::SetThis(cx, script, TypeSet::UnknownType());
|
||||||
else
|
else
|
||||||
TypeScript::SetThis(cx, script, value);
|
|
||||||
} else if (stub->monitorsArgument(&argument)) {
|
|
||||||
MOZ_ASSERT(pc == script->code());
|
|
||||||
MOZ_ASSERT(!value.isMagic(JS_UNINITIALIZED_LEXICAL));
|
|
||||||
TypeScript::SetArgument(cx, script, argument, value);
|
|
||||||
} else {
|
|
||||||
if (value.isMagic(JS_UNINITIALIZED_LEXICAL))
|
|
||||||
TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
|
TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
|
||||||
else
|
return true;
|
||||||
TypeScript::Monitor(cx, script, pc, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stub->invalid() && !stub->addMonitorStubForValue(cx, frame, value))
|
// Note: ideally we would merge this if-else statement with the one below,
|
||||||
return false;
|
// but that triggers an MSVC 2015 compiler bug. See bug 1363054.
|
||||||
|
StackTypeSet* types;
|
||||||
|
uint32_t argument;
|
||||||
|
if (stub->monitorsArgument(&argument))
|
||||||
|
types = TypeScript::ArgTypes(script, argument);
|
||||||
|
else if (stub->monitorsThis())
|
||||||
|
types = TypeScript::ThisTypes(script);
|
||||||
|
else
|
||||||
|
types = TypeScript::BytecodeTypes(script, pc);
|
||||||
|
|
||||||
// Copy input value to res.
|
if (stub->monitorsArgument(&argument)) {
|
||||||
res.set(value);
|
MOZ_ASSERT(pc == script->code());
|
||||||
|
TypeScript::SetArgument(cx, script, argument, value);
|
||||||
|
} else if (stub->monitorsThis()) {
|
||||||
|
MOZ_ASSERT(pc == script->code());
|
||||||
|
TypeScript::SetThis(cx, script, value);
|
||||||
|
} else {
|
||||||
|
TypeScript::Monitor(cx, script, pc, types, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MOZ_UNLIKELY(stub->invalid()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
return stub->addMonitorStubForValue(cx, frame, types, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*,
|
typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*,
|
||||||
|
@ -1208,7 +1208,8 @@ class ICMonitoredFallbackStub : public ICFallbackStub
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space);
|
MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space);
|
||||||
MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val);
|
MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
|
||||||
|
StackTypeSet* types, HandleValue val);
|
||||||
|
|
||||||
inline ICTypeMonitor_Fallback* fallbackMonitorStub() const {
|
inline ICTypeMonitor_Fallback* fallbackMonitorStub() const {
|
||||||
return fallbackMonitorStub_;
|
return fallbackMonitorStub_;
|
||||||
@ -1468,7 +1469,8 @@ class ICTypeMonitor_Fallback : public ICStub
|
|||||||
|
|
||||||
// Create a new monitor stub for the type of the given value, and
|
// Create a new monitor stub for the type of the given value, and
|
||||||
// add it to this chain.
|
// add it to this chain.
|
||||||
MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val);
|
MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
|
||||||
|
StackTypeSet* types, HandleValue val);
|
||||||
|
|
||||||
void resetMonitorStubChain(Zone* zone);
|
void resetMonitorStubChain(Zone* zone);
|
||||||
|
|
||||||
|
@ -283,6 +283,7 @@ template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const Data
|
|||||||
template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
|
template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
|
||||||
template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
|
template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
|
||||||
template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
|
template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
|
||||||
|
template <> struct TypeToDataType<StringIteratorObject*> { static const DataType result = Type_Object; };
|
||||||
template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
|
template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
|
||||||
template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
|
template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
|
||||||
template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
|
template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
|
||||||
|
@ -1062,12 +1062,12 @@ class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LNewArrayIterator : public LInstructionHelper<1, 0, 1>
|
class LNewIterator : public LInstructionHelper<1, 0, 1>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LIR_HEADER(NewArrayIterator)
|
LIR_HEADER(NewIterator)
|
||||||
|
|
||||||
explicit LNewArrayIterator(const LDefinition& temp) {
|
explicit LNewIterator(const LDefinition& temp) {
|
||||||
setTemp(0, temp);
|
setTemp(0, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,8 +1075,8 @@ class LNewArrayIterator : public LInstructionHelper<1, 0, 1>
|
|||||||
return getTemp(0);
|
return getTemp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MNewArrayIterator* mir() const {
|
MNewIterator* mir() const {
|
||||||
return mir_->toNewArrayIterator();
|
return mir_->toNewIterator();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4110,18 +4110,30 @@ class LFromCharCode : public LInstructionHelper<1, 1, 0>
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Convert uint32 code point to a string.
|
// Convert uint32 code point to a string.
|
||||||
class LFromCodePoint : public LInstructionHelper<1, 1, 0>
|
class LFromCodePoint : public LInstructionHelper<1, 1, 2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LIR_HEADER(FromCodePoint)
|
LIR_HEADER(FromCodePoint)
|
||||||
|
|
||||||
explicit LFromCodePoint(const LAllocation& codePoint) {
|
explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp1,
|
||||||
|
const LDefinition& temp2)
|
||||||
|
{
|
||||||
setOperand(0, codePoint);
|
setOperand(0, codePoint);
|
||||||
|
setTemp(0, temp1);
|
||||||
|
setTemp(1, temp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LAllocation* codePoint() {
|
const LAllocation* codePoint() {
|
||||||
return this->getOperand(0);
|
return this->getOperand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LDefinition* temp1() {
|
||||||
|
return this->getTemp(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LDefinition* temp2() {
|
||||||
|
return this->getTemp(1);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculates sincos(x) and returns two values (sin/cos).
|
// Calculates sincos(x) and returns two values (sin/cos).
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
_(NewArray) \
|
_(NewArray) \
|
||||||
_(NewArrayCopyOnWrite) \
|
_(NewArrayCopyOnWrite) \
|
||||||
_(NewArrayDynamicLength) \
|
_(NewArrayDynamicLength) \
|
||||||
_(NewArrayIterator) \
|
_(NewIterator) \
|
||||||
_(NewTypedArray) \
|
_(NewTypedArray) \
|
||||||
_(NewTypedArrayDynamicLength) \
|
_(NewTypedArrayDynamicLength) \
|
||||||
_(NewObject) \
|
_(NewObject) \
|
||||||
|
@ -1175,6 +1175,16 @@ static const JSFunctionSpec string_iterator_methods[] = {
|
|||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StringIteratorObject*
|
||||||
|
js::NewStringIteratorObject(JSContext* cx, NewObjectKind newKind)
|
||||||
|
{
|
||||||
|
RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
|
||||||
|
if (!proto)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return NewObjectWithGivenProto<StringIteratorObject>(cx, proto, newKind);
|
||||||
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp)
|
js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +154,9 @@ class StringIteratorObject : public JSObject
|
|||||||
static const Class class_;
|
static const Class class_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StringIteratorObject*
|
||||||
|
NewStringIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp);
|
GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp);
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ ResolvePath(JSContext* cx, HandleString filenameStr, PathResolutionMode resolveM
|
|||||||
resolveMode = RootRelative;
|
resolveMode = RootRelative;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char buffer[PATH_MAX+1];
|
char buffer[PATH_MAX+1];
|
||||||
if (resolveMode == ScriptRelative) {
|
if (resolveMode == ScriptRelative) {
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// The docs say it can return EINVAL, but the compiler says it's void
|
// The docs say it can return EINVAL, but the compiler says it's void
|
||||||
@ -232,7 +232,7 @@ FileAsTypedArray(JSContext* cx, JS::HandleString pathnameStr)
|
|||||||
UniqueChars
|
UniqueChars
|
||||||
GetCWD()
|
GetCWD()
|
||||||
{
|
{
|
||||||
static char buffer[PATH_MAX + 1];
|
char buffer[PATH_MAX + 1];
|
||||||
const char* cwd = getcwd(buffer, PATH_MAX);
|
const char* cwd = getcwd(buffer, PATH_MAX);
|
||||||
if (!cwd)
|
if (!cwd)
|
||||||
return UniqueChars();
|
return UniqueChars();
|
||||||
|
@ -773,17 +773,13 @@ intrinsic_CreateSetIterationResult(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp)
|
js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
MOZ_ASSERT(args.length() == 0);
|
MOZ_ASSERT(args.length() == 0);
|
||||||
|
|
||||||
RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
|
JSObject* obj = NewStringIteratorObject(cx);
|
||||||
if (!proto)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSObject* obj = NewObjectWithGivenProto(cx, &StringIteratorObject::class_, proto);
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2277,6 +2273,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||||||
JS_FN("std_Set_iterator", SetObject::values, 0,0),
|
JS_FN("std_Set_iterator", SetObject::values, 0,0),
|
||||||
|
|
||||||
JS_INLINABLE_FN("std_String_fromCharCode", str_fromCharCode, 1,0, StringFromCharCode),
|
JS_INLINABLE_FN("std_String_fromCharCode", str_fromCharCode, 1,0, StringFromCharCode),
|
||||||
|
JS_INLINABLE_FN("std_String_fromCodePoint", str_fromCodePoint, 1,0, StringFromCodePoint),
|
||||||
JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1,0, StringCharCodeAt),
|
JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1,0, StringCharCodeAt),
|
||||||
JS_FN("std_String_includes", str_includes, 1,0),
|
JS_FN("std_String_includes", str_includes, 1,0),
|
||||||
JS_FN("std_String_indexOf", str_indexOf, 1,0),
|
JS_FN("std_String_indexOf", str_indexOf, 1,0),
|
||||||
@ -2408,7 +2405,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||||||
CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2,0),
|
CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2,0),
|
||||||
|
|
||||||
|
|
||||||
JS_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0),
|
JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0,
|
||||||
|
IntrinsicNewStringIterator),
|
||||||
JS_FN("CallStringIteratorMethodIfWrapped",
|
JS_FN("CallStringIteratorMethodIfWrapped",
|
||||||
CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2,0),
|
CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2,0),
|
||||||
|
|
||||||
|
@ -50,6 +50,9 @@ intrinsic_StringSplitString(JSContext* cx, unsigned argc, JS::Value* vp);
|
|||||||
bool
|
bool
|
||||||
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
|
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||||
|
|
||||||
|
bool
|
||||||
|
intrinsic_NewStringIterator(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* vm_SelfHosting_h_ */
|
#endif /* vm_SelfHosting_h_ */
|
||||||
|
@ -489,6 +489,8 @@ MarkObjectStateChange(JSContext* cx, JSObject* obj)
|
|||||||
|
|
||||||
/* Interface helpers for JSScript*. */
|
/* Interface helpers for JSScript*. */
|
||||||
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type);
|
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type);
|
||||||
|
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
|
||||||
|
TypeSet::Type type);
|
||||||
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval);
|
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
@ -589,6 +591,15 @@ TypeScript::Monitor(JSContext* cx, const js::Value& rval)
|
|||||||
Monitor(cx, script, pc, rval);
|
Monitor(cx, script, pc, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ inline void
|
||||||
|
TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
|
||||||
|
const js::Value& rval)
|
||||||
|
{
|
||||||
|
TypeSet::Type type = TypeSet::GetValueType(rval);
|
||||||
|
if (!types->hasType(type))
|
||||||
|
TypeMonitorResult(cx, script, pc, types, type);
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ inline void
|
/* static */ inline void
|
||||||
TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id)
|
TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id)
|
||||||
{
|
{
|
||||||
|
@ -3341,6 +3341,22 @@ js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::
|
|||||||
types->addType(cx, type);
|
types->addType(cx, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
|
||||||
|
TypeSet::Type type)
|
||||||
|
{
|
||||||
|
assertSameCompartment(cx, script, type);
|
||||||
|
|
||||||
|
AutoEnterAnalysis enter(cx);
|
||||||
|
|
||||||
|
MOZ_ASSERT(types == TypeScript::BytecodeTypes(script, pc));
|
||||||
|
MOZ_ASSERT(!types->hasType(type));
|
||||||
|
|
||||||
|
InferSpew(ISpewOps, "bytecodeType: %p %05" PRIuSIZE ": %s",
|
||||||
|
script, script->pcToOffset(pc), TypeSet::TypeString(type));
|
||||||
|
types->addType(cx, type);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval)
|
js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval)
|
||||||
{
|
{
|
||||||
|
@ -1245,6 +1245,9 @@ class TypeScript
|
|||||||
TypeSet::Type type);
|
TypeSet::Type type);
|
||||||
static inline void Monitor(JSContext* cx, const js::Value& rval);
|
static inline void Monitor(JSContext* cx, const js::Value& rval);
|
||||||
|
|
||||||
|
static inline void Monitor(JSContext* cx, JSScript* script, jsbytecode* pc,
|
||||||
|
StackTypeSet* types, const js::Value& val);
|
||||||
|
|
||||||
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
|
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
|
||||||
static inline void MonitorAssign(JSContext* cx, HandleObject obj, jsid id);
|
static inline void MonitorAssign(JSContext* cx, HandleObject obj, jsid id);
|
||||||
|
|
||||||
|
@ -50,9 +50,11 @@ struct nsArenaMemoryStats {
|
|||||||
#define ZERO_SIZE(kind, mSize) mSize(0),
|
#define ZERO_SIZE(kind, mSize) mSize(0),
|
||||||
FOR_EACH_SIZE(ZERO_SIZE)
|
FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
#undef ZERO_SIZE
|
#undef ZERO_SIZE
|
||||||
#define FRAME_ID(classname) FRAME_ID_STAT_FIELD(classname)(),
|
#define FRAME_ID(classname, ...) FRAME_ID_STAT_FIELD(classname)(),
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
dummy()
|
dummy()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -61,10 +63,12 @@ struct nsArenaMemoryStats {
|
|||||||
#define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
|
#define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
|
||||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||||
#undef ADD_TO_TAB_SIZES
|
#undef ADD_TO_TAB_SIZES
|
||||||
#define FRAME_ID(classname) \
|
#define FRAME_ID(classname, ...) \
|
||||||
sizes->add(nsTabSizes::Other, FRAME_ID_STAT_FIELD(classname));
|
sizes->add(nsTabSizes::Other, FRAME_ID_STAT_FIELD(classname));
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getTotalSize() const
|
size_t getTotalSize() const
|
||||||
@ -73,19 +77,23 @@ struct nsArenaMemoryStats {
|
|||||||
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
|
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
|
||||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||||
#undef ADD_TO_TOTAL_SIZE
|
#undef ADD_TO_TOTAL_SIZE
|
||||||
#define FRAME_ID(classname) \
|
#define FRAME_ID(classname, ...) \
|
||||||
total += FRAME_ID_STAT_FIELD(classname);
|
total += FRAME_ID_STAT_FIELD(classname);
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECL_SIZE(kind, mSize) size_t mSize;
|
#define DECL_SIZE(kind, mSize) size_t mSize;
|
||||||
FOR_EACH_SIZE(DECL_SIZE)
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
#undef DECL_SIZE
|
#undef DECL_SIZE
|
||||||
#define FRAME_ID(classname) size_t FRAME_ID_STAT_FIELD(classname);
|
#define FRAME_ID(classname, ...) size_t FRAME_ID_STAT_FIELD(classname);
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
int dummy; // present just to absorb the trailing comma from FRAME_ID in the
|
int dummy; // present just to absorb the trailing comma from FRAME_ID in the
|
||||||
// constructor
|
// constructor
|
||||||
|
|
||||||
|
@ -194,12 +194,14 @@ nsPresArena::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
|||||||
size_t* p;
|
size_t* p;
|
||||||
|
|
||||||
switch (entry - mFreeLists) {
|
switch (entry - mFreeLists) {
|
||||||
#define FRAME_ID(classname) \
|
#define FRAME_ID(classname, ...) \
|
||||||
case nsQueryFrame::classname##_id: \
|
case nsQueryFrame::classname##_id: \
|
||||||
p = &aArenaStats->FRAME_ID_STAT_FIELD(classname); \
|
p = &aArenaStats->FRAME_ID_STAT_FIELD(classname); \
|
||||||
break;
|
break;
|
||||||
|
#define ABSTRACT_FRAME_ID(...)
|
||||||
#include "nsFrameIdList.h"
|
#include "nsFrameIdList.h"
|
||||||
#undef FRAME_ID
|
#undef FRAME_ID
|
||||||
|
#undef ABSTRACT_FRAME_ID
|
||||||
case eArenaObjectID_nsLineBox:
|
case eArenaObjectID_nsLineBox:
|
||||||
p = &aArenaStats->mLineBoxes;
|
p = &aArenaStats->mLineBoxes;
|
||||||
break;
|
break;
|
||||||
|
@ -235,12 +235,12 @@ public:
|
|||||||
return mLastFireSkipped;
|
return mLastFireSkipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<TimeStamp> GetIdleDeadlineHint()
|
TimeStamp GetIdleDeadlineHint(TimeStamp aDefault)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (LastTickSkippedAnyPaints()) {
|
if (LastTickSkippedAnyPaints()) {
|
||||||
return Some(TimeStamp());
|
return TimeStamp::Now();
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStamp mostRecentRefresh = MostRecentRefresh();
|
TimeStamp mostRecentRefresh = MostRecentRefresh();
|
||||||
@ -250,11 +250,12 @@ public:
|
|||||||
if (idleEnd +
|
if (idleEnd +
|
||||||
refreshRate * nsLayoutUtils::QuiescentFramesBeforeIdlePeriod() <
|
refreshRate * nsLayoutUtils::QuiescentFramesBeforeIdlePeriod() <
|
||||||
TimeStamp::Now()) {
|
TimeStamp::Now()) {
|
||||||
return Nothing();
|
return aDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(idleEnd - TimeDuration::FromMilliseconds(
|
idleEnd = idleEnd - TimeDuration::FromMilliseconds(
|
||||||
nsLayoutUtils::IdlePeriodDeadlineLimit()));
|
nsLayoutUtils::IdlePeriodDeadlineLimit());
|
||||||
|
return idleEnd < aDefault ? idleEnd : aDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -2315,13 +2316,14 @@ nsRefreshDriver::CancelPendingEvents(nsIDocument* aDocument)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Maybe<TimeStamp>
|
/* static */ TimeStamp
|
||||||
nsRefreshDriver::GetIdleDeadlineHint()
|
nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!aDefault.IsNull());
|
||||||
|
|
||||||
if (!sRegularRateTimer) {
|
if (!sRegularRateTimer) {
|
||||||
return Nothing();
|
return aDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For computing idleness of refresh drivers we only care about
|
// For computing idleness of refresh drivers we only care about
|
||||||
@ -2330,7 +2332,7 @@ nsRefreshDriver::GetIdleDeadlineHint()
|
|||||||
// resulting from a tick on the sRegularRateTimer counts as being
|
// resulting from a tick on the sRegularRateTimer counts as being
|
||||||
// busy but tasks resulting from a tick on sThrottledRateTimer
|
// busy but tasks resulting from a tick on sThrottledRateTimer
|
||||||
// counts as being idle.
|
// counts as being idle.
|
||||||
return sRegularRateTimer->GetIdleDeadlineHint();
|
return sRegularRateTimer->GetIdleDeadlineHint(aDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user