зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b-i
This commit is contained in:
Коммит
236cb3aed6
|
@ -41,9 +41,11 @@ ifndef MOZ_PROFILE_USE
|
|||
# otherwise the rule in rules.mk doesn't run early enough.
|
||||
libs binaries export tools:: CLOBBER $(configure_dir)/configure config.status backend.RecursiveMakeBackend
|
||||
ifndef JS_STANDALONE
|
||||
ifndef LIBXUL_SDK
|
||||
libs binaries export tools:: $(topsrcdir)/js/src/configure js/src/config.status
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JS_STANDALONE
|
||||
.PHONY: CLOBBER
|
||||
|
@ -101,11 +103,13 @@ install_manifest_depends = \
|
|||
$(NULL)
|
||||
|
||||
ifndef JS_STANDALONE
|
||||
ifndef LIBXUL_SDK
|
||||
install_manifest_depends += \
|
||||
$(topsrcdir)/js/src/configure \
|
||||
js/src/config.status \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: install-manifests
|
||||
install-manifests: $(addprefix install-dist-,$(install_manifests))
|
||||
|
|
|
@ -187,7 +187,8 @@ pref("privacy.item.syncAccount", true);
|
|||
|
||||
// base url for the wifi geolocation network provider
|
||||
pref("geo.provider.use_mls", false);
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
pref("geo.cell.scan", true);
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZ_MOZILLA_API_KEY%");
|
||||
|
||||
// enable geo
|
||||
pref("geo.enabled", true);
|
||||
|
|
|
@ -34,11 +34,6 @@ var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptS
|
|||
|
||||
let permissionSpecificChecker = {};
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"PermSettings",
|
||||
"@mozilla.org/permissionSettings;1",
|
||||
"nsIDOMPermissionSettings");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"AudioManager",
|
||||
"@mozilla.org/telephony/audiomanager;1",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1394054454000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1395351978000">
|
||||
<emItems>
|
||||
<emItem blockID="i454" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
|
@ -1051,7 +1051,7 @@
|
|||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i547" id="{87934c42-161d-45bc-8cef-ef18abe2a30c}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
<versionRange minVersion="0" maxVersion="3.7.9999999999" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
|
|
|
@ -1369,6 +1369,11 @@ pref("dom.debug.propagate_gesture_events_through_content", false);
|
|||
|
||||
// The request URL of the GeoLocation backend.
|
||||
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("geo.wifi.logging.enabled", false);
|
||||
#else
|
||||
pref("geo.wifi.logging.enabled", true);
|
||||
#endif
|
||||
|
||||
// Necko IPC security checks only needed for app isolation for cookies/cache/etc:
|
||||
// currently irrelevant for desktop e10s
|
||||
|
|
|
@ -140,6 +140,9 @@ Object.defineProperty(this, "NetworkHelper", {
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Curl",
|
||||
"resource:///modules/devtools/Curl.jsm");
|
||||
|
||||
/**
|
||||
* Object defining the network monitor controller components.
|
||||
*/
|
||||
|
|
|
@ -523,6 +523,37 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
clipboardHelper.copyString(selected.url, document);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a cURL command from the currently selected item.
|
||||
*/
|
||||
copyAsCurl: function() {
|
||||
let selected = this.selectedItem.attachment;
|
||||
Task.spawn(function*() {
|
||||
// Create a sanitized object for the Curl command generator.
|
||||
let data = {
|
||||
url: selected.url,
|
||||
method: selected.method,
|
||||
headers: [],
|
||||
httpVersion: selected.httpVersion,
|
||||
postDataText: null
|
||||
};
|
||||
|
||||
// Fetch header values.
|
||||
for (let { name, value } of selected.requestHeaders.headers) {
|
||||
let text = yield gNetwork.getString(value);
|
||||
data.headers.push({ name: name, value: text });
|
||||
}
|
||||
|
||||
// Fetch the request payload.
|
||||
if (selected.requestPostData) {
|
||||
let postData = selected.requestPostData.postData.text;
|
||||
data.postDataText = yield gNetwork.getString(postData);
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(Curl.generateCommand(data), document);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy image as data uri.
|
||||
*/
|
||||
|
@ -1560,6 +1591,9 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
let copyUrlElement = $("#request-menu-context-copy-url");
|
||||
copyUrlElement.hidden = !selectedItem;
|
||||
|
||||
let copyAsCurlElement = $("#request-menu-context-copy-as-curl");
|
||||
copyAsCurlElement.hidden = !selectedItem || !selectedItem.attachment.responseContent;
|
||||
|
||||
let copyImageAsDataUriElement = $("#request-menu-context-copy-image-as-data-uri");
|
||||
copyImageAsDataUriElement.hidden = !selectedItem ||
|
||||
!selectedItem.attachment.responseContent ||
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
<menuitem id="request-menu-context-copy-url"
|
||||
label="&netmonitorUI.context.copyUrl;"
|
||||
accesskey="&netmonitorUI.context.copyUrl.accesskey;"/>
|
||||
<menuitem id="request-menu-context-copy-as-curl"
|
||||
label="&netmonitorUI.context.copyAsCurl;"
|
||||
oncommand="NetMonitorView.RequestsMenu.copyAsCurl();"/>
|
||||
<menuitem id="request-menu-context-copy-image-as-data-uri"
|
||||
label="&netmonitorUI.context.copyImageAsDataUri;"
|
||||
accesskey="&netmonitorUI.context.copyImageAsDataUri.accesskey;"/>
|
||||
|
|
|
@ -21,6 +21,8 @@ support-files =
|
|||
html_sorting-test-page.html
|
||||
html_statistics-test-page.html
|
||||
html_status-codes-test-page.html
|
||||
html_copy-as-curl.html
|
||||
html_curl-utils.html
|
||||
sjs_content-type-test-server.sjs
|
||||
sjs_simple-test-server.sjs
|
||||
sjs_sorting-test-server.sjs
|
||||
|
@ -39,8 +41,10 @@ support-files =
|
|||
[browser_net_clear.js]
|
||||
[browser_net_complex-params.js]
|
||||
[browser_net_content-type.js]
|
||||
[browser_net_curl-utils.js]
|
||||
[browser_net_copy_image_as_data_uri.js]
|
||||
[browser_net_copy_url.js]
|
||||
[browser_net_copy_as_curl.js]
|
||||
[browser_net_cyrillic-01.js]
|
||||
[browser_net_cyrillic-02.js]
|
||||
[browser_net_filter-01.js]
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if Copy as cURL works.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(CURL_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
const EXPECTED_POSIX_RESULT = [
|
||||
"curl",
|
||||
"'" + SIMPLE_SJS + "'",
|
||||
"-H 'Host: example.com'",
|
||||
"-H 'User-Agent: " + aDebuggee.navigator.userAgent + "'",
|
||||
"-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'",
|
||||
"-H 'Accept-Language: " + aDebuggee.navigator.language + "'",
|
||||
"-H 'Accept-Encoding: gzip, deflate'",
|
||||
"-H 'X-Custom-Header-1: Custom value'",
|
||||
"-H 'X-Custom-Header-2: 8.8.8.8'",
|
||||
"-H 'X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
|
||||
"-H 'Referer: " + CURL_URL + "'",
|
||||
"-H 'Connection: keep-alive'"
|
||||
].join(" ");
|
||||
|
||||
const EXPECTED_WIN_RESULT = [
|
||||
'curl',
|
||||
'"' + SIMPLE_SJS + '"',
|
||||
'-H "Host: example.com"',
|
||||
'-H "User-Agent: ' + aDebuggee.navigator.userAgent + '"',
|
||||
'-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"',
|
||||
'-H "Accept-Language: ' + aDebuggee.navigator.language + '"',
|
||||
'-H "Accept-Encoding: gzip, deflate"',
|
||||
'-H "X-Custom-Header-1: Custom value"',
|
||||
'-H "X-Custom-Header-2: 8.8.8.8"',
|
||||
'-H "X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
|
||||
'-H "Referer: ' + CURL_URL + '"',
|
||||
'-H "Connection: keep-alive"'
|
||||
].join(" ");
|
||||
|
||||
const EXPECTED_RESULT = Services.appinfo.OS == "WINNT" ?
|
||||
EXPECTED_WIN_RESULT : EXPECTED_POSIX_RESULT;
|
||||
|
||||
let { NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1).then(() => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
RequestsMenu.selectedItem = requestItem;
|
||||
|
||||
waitForClipboard(EXPECTED_RESULT, function setup() {
|
||||
RequestsMenu.copyAsCurl();
|
||||
}, function onSuccess() {
|
||||
ok(true, "Clipboard contains a cURL command for the currently selected item's url.");
|
||||
cleanUp();
|
||||
}, function onFailure() {
|
||||
ok(false, "Creating a cURL command for the currently selected item was unsuccessful.");
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
aDebuggee.performRequest(SIMPLE_SJS);
|
||||
|
||||
function cleanUp(){
|
||||
teardown(aMonitor).then(finish);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests Curl Utils functionality.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(CURL_UTILS_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { NetMonitorView, gNetwork } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1, 3).then(() => {
|
||||
let requests = {
|
||||
get: RequestsMenu.getItemAtIndex(0),
|
||||
post: RequestsMenu.getItemAtIndex(1),
|
||||
multipart: RequestsMenu.getItemAtIndex(2),
|
||||
multipartForm: RequestsMenu.getItemAtIndex(3)
|
||||
};
|
||||
|
||||
Task.spawn(function*() {
|
||||
yield createCurlData(requests.get.attachment, gNetwork).then((aData) => {
|
||||
test_findHeader(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.post.attachment, gNetwork).then((aData) => {
|
||||
test_isUrlEncodedRequest(aData);
|
||||
test_writePostDataTextParams(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.multipart.attachment, gNetwork).then((aData) => {
|
||||
test_isMultipartRequest(aData);
|
||||
test_getMultipartBoundary(aData);
|
||||
test_removeBinaryDataFromMultipartText(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.multipartForm.attachment, gNetwork).then((aData) => {
|
||||
test_getHeadersFromMultipartText(aData);
|
||||
});
|
||||
|
||||
if (Services.appinfo.OS != "WINNT") {
|
||||
test_escapeStringPosix();
|
||||
} else {
|
||||
test_escapeStringWin();
|
||||
}
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
});
|
||||
|
||||
aDebuggee.performRequests(SIMPLE_SJS);
|
||||
});
|
||||
}
|
||||
|
||||
function test_isUrlEncodedRequest(aData) {
|
||||
let isUrlEncoded = CurlUtils.isUrlEncodedRequest(aData);
|
||||
ok(isUrlEncoded, "Should return true for url encoded requests.");
|
||||
}
|
||||
|
||||
function test_isMultipartRequest(aData) {
|
||||
let isMultipart = CurlUtils.isMultipartRequest(aData);
|
||||
ok(isMultipart, "Should return true for multipart/form-data requests.");
|
||||
}
|
||||
|
||||
function test_findHeader(aData) {
|
||||
let headers = aData.headers;
|
||||
let hostName = CurlUtils.findHeader(headers, "Host");
|
||||
let requestedWithLowerCased = CurlUtils.findHeader(headers, "x-requested-with");
|
||||
let doesNotExist = CurlUtils.findHeader(headers, "X-Does-Not-Exist");
|
||||
|
||||
is(hostName, "example.com",
|
||||
"Header with name 'Host' should be found in the request array.");
|
||||
is(requestedWithLowerCased, "XMLHttpRequest",
|
||||
"The search should be case insensitive.");
|
||||
is(doesNotExist, null,
|
||||
"Should return null when a header is not found.");
|
||||
}
|
||||
|
||||
function test_writePostDataTextParams(aData) {
|
||||
let params = CurlUtils.writePostDataTextParams(aData.postDataText);
|
||||
is(params, "param1=value1¶m2=value2¶m3=value3",
|
||||
"Should return a serialized representation of the request parameters");
|
||||
}
|
||||
|
||||
function test_getMultipartBoundary(aData) {
|
||||
let boundary = CurlUtils.getMultipartBoundary(aData);
|
||||
ok(/-{3,}\w+/.test(boundary),
|
||||
"A boundary string should be found in a multipart request.");
|
||||
}
|
||||
|
||||
function test_removeBinaryDataFromMultipartText(aData) {
|
||||
let generatedBoundary = CurlUtils.getMultipartBoundary(aData);
|
||||
let text = aData.postDataText;
|
||||
let binaryRemoved =
|
||||
CurlUtils.removeBinaryDataFromMultipartText(text, generatedBoundary);
|
||||
let boundary = "--" + generatedBoundary;
|
||||
|
||||
const EXPECTED_POSIX_RESULT = [
|
||||
"$'",
|
||||
boundary,
|
||||
"\\r\\n\\r\\n",
|
||||
"Content-Disposition: form-data; name=\"param1\"",
|
||||
"\\r\\n\\r\\n",
|
||||
"value1",
|
||||
"\\r\\n",
|
||||
boundary,
|
||||
"\\r\\n\\r\\n",
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"filename.png\"",
|
||||
"\\r\\n",
|
||||
"Content-Type: image/png",
|
||||
"\\r\\n\\r\\n",
|
||||
generatedBoundary,
|
||||
"--\\r\\n",
|
||||
"'"
|
||||
].join("");
|
||||
|
||||
const EXPECTED_WIN_RESULT = [
|
||||
'"' + boundary + '"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"Content-Disposition: form-data; name=""param1"""^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"value1"^',
|
||||
'\u000d\u000A',
|
||||
'"' + boundary + '"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"Content-Disposition: form-data; name=""file""; filename=""filename.png"""^',
|
||||
'\u000d\u000A',
|
||||
'"Content-Type: image/png"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"' + generatedBoundary + '--"^',
|
||||
'\u000d\u000A',
|
||||
'""'
|
||||
].join("");
|
||||
|
||||
if (Services.appinfo.OS != "WINNT") {
|
||||
is(CurlUtils.escapeStringPosix(binaryRemoved), EXPECTED_POSIX_RESULT,
|
||||
"The mulitpart request payload should not contain binary data.");
|
||||
} else {
|
||||
is(CurlUtils.escapeStringWin(binaryRemoved), EXPECTED_WIN_RESULT,
|
||||
"WinNT: The mulitpart request payload should not contain binary data.");
|
||||
}
|
||||
}
|
||||
|
||||
function test_getHeadersFromMultipartText(aData) {
|
||||
let headers = CurlUtils.getHeadersFromMultipartText(aData.postDataText);
|
||||
|
||||
ok(Array.isArray(headers),
|
||||
"Should return an array.");
|
||||
ok(headers.length > 0,
|
||||
"There should exist at least one request header.");
|
||||
is(headers[0].name, "Content-Type",
|
||||
"The first header name should be 'Content-Type'.");
|
||||
}
|
||||
|
||||
function test_escapeStringPosix() {
|
||||
let surroundedWithQuotes = "A simple string";
|
||||
is(CurlUtils.escapeStringPosix(surroundedWithQuotes), "'A simple string'",
|
||||
"The string should be surrounded with single quotes.");
|
||||
|
||||
let singleQuotes = "It's unusual to put crickets in your coffee.";
|
||||
is(CurlUtils.escapeStringPosix(singleQuotes),
|
||||
"$'It\\'s unusual to put crickets in your coffee.'",
|
||||
"Single quotes should be escaped.");
|
||||
|
||||
let newLines = "Line 1\r\nLine 2\u000d\u000ALine3";
|
||||
is(CurlUtils.escapeStringPosix(newLines), "$'Line 1\\r\\nLine 2\\r\\nLine3'",
|
||||
"Newlines should be escaped.");
|
||||
|
||||
let controlChars = "\u0007 \u0009 \u000C \u001B";
|
||||
is(CurlUtils.escapeStringPosix(controlChars), "$'\\x07 \\x09 \\x0c \\x1b'",
|
||||
"Control characters should be escaped.");
|
||||
|
||||
let extendedAsciiChars = "æ ø ü ß ö é";
|
||||
is(CurlUtils.escapeStringPosix(extendedAsciiChars),
|
||||
"$'\\xc3\\xa6 \\xc3\\xb8 \\xc3\\xbc \\xc3\\x9f \\xc3\\xb6 \\xc3\\xa9'",
|
||||
"Character codes outside of the decimal range 32 - 126 should be escaped.");
|
||||
}
|
||||
|
||||
function test_escapeStringWin() {
|
||||
let surroundedWithDoubleQuotes = "A simple string";
|
||||
is(CurlUtils.escapeStringWin(surroundedWithDoubleQuotes), '"A simple string"',
|
||||
"The string should be surrounded with double quotes.");
|
||||
|
||||
let doubleQuotes = "Quote: \"Time is an illusion. Lunchtime doubly so.\"";
|
||||
is(CurlUtils.escapeStringWin(doubleQuotes),
|
||||
'"Quote: ""Time is an illusion. Lunchtime doubly so."""',
|
||||
"Double quotes should be escaped.");
|
||||
|
||||
let percentSigns = "%AppData%";
|
||||
is(CurlUtils.escapeStringWin(percentSigns), '""%"AppData"%""',
|
||||
"Percent signs should be escaped.");
|
||||
|
||||
let backslashes = "\\A simple string\\";
|
||||
is(CurlUtils.escapeStringWin(backslashes), '"\\\\A simple string\\\\"',
|
||||
"Backslashes should be escaped.");
|
||||
|
||||
let newLines = "line1\r\nline2\r\nline3";
|
||||
is(CurlUtils.escapeStringWin(newLines),
|
||||
'"line1"^\u000d\u000A"line2"^\u000d\u000A"line3"',
|
||||
"Newlines should be escaped.");
|
||||
}
|
||||
|
||||
function createCurlData(aSelected, aNetwork) {
|
||||
return Task.spawn(function*() {
|
||||
// Create a sanitized object for the Curl command generator.
|
||||
let data = {
|
||||
url: aSelected.url,
|
||||
method: aSelected.method,
|
||||
headers: [],
|
||||
httpVersion: aSelected.httpVersion,
|
||||
postDataText: null
|
||||
};
|
||||
|
||||
// Fetch header values.
|
||||
for (let { name, value } of aSelected.requestHeaders.headers) {
|
||||
let text = yield aNetwork.getString(value);
|
||||
data.headers.push({ name: name, value: text });
|
||||
}
|
||||
|
||||
// Fetch the request payload.
|
||||
if (aSelected.requestPostData) {
|
||||
let postData = aSelected.requestPostData.postData.text;
|
||||
data.postDataText = yield aNetwork.getString(postData);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}
|
|
@ -9,6 +9,7 @@ let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
|||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { CurlUtils } = Cu.import("resource:///modules/devtools/Curl.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
let Toolbox = devtools.Toolbox;
|
||||
|
||||
|
@ -34,6 +35,8 @@ const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
|
|||
const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";
|
||||
const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html";
|
||||
const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
|
||||
const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
|
||||
const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
|
||||
|
||||
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
|
||||
const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Performing a GET request</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function performRequest(aUrl) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aUrl, true);
|
||||
xhr.setRequestHeader("Accept-Language", window.navigator.language);
|
||||
xhr.setRequestHeader("X-Custom-Header-1", "Custom value");
|
||||
xhr.setRequestHeader("X-Custom-Header-2", "8.8.8.8");
|
||||
xhr.setRequestHeader("X-Custom-Header-3", "Mon, 3 Mar 2014 11:11:11 GMT");
|
||||
xhr.send(null);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,99 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Performing requests</p>
|
||||
|
||||
<p>
|
||||
<canvas width="100" height="100"></canvas>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<form method="post" action="#" enctype="multipart/form-data" target="target" id="post-form">
|
||||
<input type="text" name="param1" value="value1"/>
|
||||
<input type="text" name="param2" value="value2"/>
|
||||
<input type="text" name="param3" value="value3"/>
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
<iframe name="target"></iframe>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function ajaxGet(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aUrl + "?param1=value1¶m2=value2¶m3=value3", true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function ajaxPost(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
var params = "param1=value1¶m2=value2¶m3=value3";
|
||||
xhr.send(params);
|
||||
}
|
||||
|
||||
function ajaxMultipart(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aUrl, true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
|
||||
getCanvasElem().toBlob((blob) => {
|
||||
var formData = new FormData();
|
||||
formData.append("param1", "value1");
|
||||
formData.append("file", blob, "filename.png");
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
var form = document.querySelector("#post-form");
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function getCanvasElem() {
|
||||
return document.querySelector("canvas");
|
||||
}
|
||||
|
||||
function initCanvas() {
|
||||
var canvas = getCanvasElem();
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillRect(0,0,100,100);
|
||||
ctx.clearRect(20,20,60,60);
|
||||
ctx.strokeRect(25,25,50,50);
|
||||
}
|
||||
|
||||
function performRequests(aUrl) {
|
||||
ajaxGet(aUrl, () => {
|
||||
ajaxPost(aUrl, () => {
|
||||
ajaxMultipart(aUrl, () => {
|
||||
submitForm();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initCanvas();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,396 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
|
||||
* Copyright (C) 2011 Google Inc. All rights reserved.
|
||||
* Copyright (C) 2009 Mozilla Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Curl", "CurlUtils"];
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const DEFAULT_HTTP_VERSION = "HTTP/1.1";
|
||||
|
||||
this.Curl = {
|
||||
/**
|
||||
* Generates a cURL command string which can be used from the command line etc.
|
||||
*
|
||||
* @param object aData
|
||||
* Datasource to create the command from.
|
||||
* The object must contain the following properties:
|
||||
* - url:string, the URL of the request.
|
||||
* - method:string, the request method upper cased. HEAD / GET / POST etc.
|
||||
* - headers:array, an array of request headers {name:x, value:x} tuples.
|
||||
* - httpVersion:string, http protocol version rfc2616 formatted. Eg. "HTTP/1.1"
|
||||
* - postDataText:string, optional - the request payload.
|
||||
*
|
||||
* @return string
|
||||
* A cURL command.
|
||||
*/
|
||||
generateCommand: function(aData) {
|
||||
let utils = CurlUtils;
|
||||
|
||||
let command = ["curl"];
|
||||
let ignoredHeaders = new Set();
|
||||
|
||||
// The cURL command is expected to run on the same platform that Firefox runs
|
||||
// (it may be different from the inspected page platform).
|
||||
let escapeString = Services.appinfo.OS == "WINNT" ?
|
||||
utils.escapeStringWin : utils.escapeStringPosix;
|
||||
|
||||
// Add URL.
|
||||
command.push(escapeString(aData.url));
|
||||
|
||||
let postDataText = null;
|
||||
let multipartRequest = utils.isMultipartRequest(aData);
|
||||
|
||||
// Create post data.
|
||||
let data = [];
|
||||
if (utils.isUrlEncodedRequest(aData) || aData.method == "PUT") {
|
||||
postDataText = aData.postDataText;
|
||||
data.push("--data");
|
||||
data.push(escapeString(utils.writePostDataTextParams(postDataText)));
|
||||
ignoredHeaders.add("Content-Length");
|
||||
} else if (multipartRequest) {
|
||||
postDataText = aData.postDataText;
|
||||
data.push("--data-binary");
|
||||
let boundary = utils.getMultipartBoundary(aData);
|
||||
let text = utils.removeBinaryDataFromMultipartText(postDataText, boundary);
|
||||
data.push(escapeString(text));
|
||||
ignoredHeaders.add("Content-Length");
|
||||
}
|
||||
|
||||
// Add method.
|
||||
// For GET and POST requests this is not necessary as GET is the
|
||||
// default. If --data or --binary is added POST is the default.
|
||||
if (!(aData.method == "GET" || aData.method == "POST")) {
|
||||
command.push("-X");
|
||||
command.push(aData.method);
|
||||
}
|
||||
|
||||
// Add -I (HEAD)
|
||||
// For servers that supports HEAD.
|
||||
// This will fetch the header of a document only.
|
||||
if (aData.method == "HEAD") {
|
||||
command.push("-I");
|
||||
}
|
||||
|
||||
// Add http version.
|
||||
if (aData.httpVersion && aData.httpVersion != DEFAULT_HTTP_VERSION) {
|
||||
command.push("--" + aData.httpVersion.split("/")[1]);
|
||||
}
|
||||
|
||||
// Add request headers.
|
||||
let headers = aData.headers;
|
||||
if (multipartRequest) {
|
||||
let multipartHeaders = utils.getHeadersFromMultipartText(postDataText);
|
||||
headers = headers.concat(multipartHeaders);
|
||||
}
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let header = headers[i];
|
||||
if (ignoredHeaders.has(header.name)) {
|
||||
continue;
|
||||
}
|
||||
command.push("-H");
|
||||
command.push(escapeString(header.name + ": " + header.value));
|
||||
}
|
||||
|
||||
// Add post data.
|
||||
command = command.concat(data);
|
||||
|
||||
return command.join(" ");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility functions for the Curl command generator.
|
||||
*/
|
||||
this.CurlUtils = {
|
||||
/**
|
||||
* Check if the request is an URL encoded request.
|
||||
*
|
||||
* @param object aData
|
||||
* The data source. See the description in the Curl object.
|
||||
* @return boolean
|
||||
* True if the request is URL encoded, false otherwise.
|
||||
*/
|
||||
isUrlEncodedRequest: function(aData) {
|
||||
let postDataText = aData.postDataText;
|
||||
if (!postDataText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postDataText = postDataText.toLowerCase();
|
||||
if (postDataText.contains("content-type: application/x-www-form-urlencoded")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let contentType = this.findHeader(aData.headers, "content-type");
|
||||
|
||||
return (contentType &&
|
||||
contentType.toLowerCase().contains("application/x-www-form-urlencoded"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the request is a multipart request.
|
||||
*
|
||||
* @param object aData
|
||||
* The data source.
|
||||
* @return boolean
|
||||
* True if the request is multipart reqeust, false otherwise.
|
||||
*/
|
||||
isMultipartRequest: function(aData) {
|
||||
let postDataText = aData.postDataText;
|
||||
if (!postDataText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postDataText = postDataText.toLowerCase();
|
||||
if (postDataText.contains("content-type: multipart/form-data")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let contentType = this.findHeader(aData.headers, "content-type");
|
||||
|
||||
return (contentType &&
|
||||
contentType.toLowerCase().contains("multipart/form-data;"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Write out paramters from post data text.
|
||||
*
|
||||
* @param object aPostDataText
|
||||
* Post data text.
|
||||
* @return string
|
||||
* Post data parameters.
|
||||
*/
|
||||
writePostDataTextParams: function(aPostDataText) {
|
||||
let lines = aPostDataText.split("\r\n");
|
||||
return lines[lines.length - 1];
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the header with the given name in the headers array.
|
||||
*
|
||||
* @param array aHeaders
|
||||
* Array of headers info {name:x, value:x}.
|
||||
* @param string aName
|
||||
* The header name to find.
|
||||
* @return string
|
||||
* The found header value or null if not found.
|
||||
*/
|
||||
findHeader: function(aHeaders, aName) {
|
||||
if (!aHeaders) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let name = aName.toLowerCase();
|
||||
for (let header of aHeaders) {
|
||||
if (name == header.name.toLowerCase()) {
|
||||
return header.value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the boundary string for a multipart request.
|
||||
*
|
||||
* @param string aData
|
||||
* The data source. See the description in the Curl object.
|
||||
* @return string
|
||||
* The boundary string for the request.
|
||||
*/
|
||||
getMultipartBoundary: function(aData) {
|
||||
let boundaryRe = /\bboundary=(-{3,}\w+)/i;
|
||||
|
||||
// Get the boundary string from the Content-Type request header.
|
||||
let contentType = this.findHeader(aData.headers, "Content-Type");
|
||||
if (boundaryRe.test(contentType)) {
|
||||
return contentType.match(boundaryRe)[1];
|
||||
}
|
||||
// Temporary workaround. As of 2014-03-11 the requestHeaders array does not
|
||||
// always contain the Content-Type header for mulitpart requests. See bug 978144.
|
||||
// Find the header from the request payload.
|
||||
let boundaryString = aData.postDataText.match(boundaryRe)[1];
|
||||
if (boundaryString) {
|
||||
return boundaryString;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the binary data from mulitpart text.
|
||||
*
|
||||
* @param string aMultipartText
|
||||
* Multipart form data text.
|
||||
* @param string aBoundary
|
||||
* The boundary string.
|
||||
* @return string
|
||||
* The mulitpart text without the binary data.
|
||||
*/
|
||||
removeBinaryDataFromMultipartText: function(aMultipartText, aBoundary) {
|
||||
let result = "";
|
||||
let boundary = "--" + aBoundary;
|
||||
let parts = aMultipartText.split(boundary);
|
||||
for (let part of parts) {
|
||||
// Each part is expected to have a content disposition line.
|
||||
let contentDispositionLine = part.trimLeft().split("\r\n")[0];
|
||||
if (!contentDispositionLine) {
|
||||
continue;
|
||||
}
|
||||
contentDispositionLine = contentDispositionLine.toLowerCase();
|
||||
if (contentDispositionLine.contains("content-disposition: form-data")) {
|
||||
if (contentDispositionLine.contains("filename=")) {
|
||||
// The header lines and the binary blob is separated by 2 CRLF's.
|
||||
// Add only the headers to the result.
|
||||
let headers = part.split("\r\n\r\n")[0];
|
||||
result += boundary + "\r\n" + headers + "\r\n\r\n";
|
||||
}
|
||||
else {
|
||||
result += boundary + "\r\n" + part;
|
||||
}
|
||||
}
|
||||
}
|
||||
result += aBoundary + "--\r\n";
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the headers from a multipart post data text.
|
||||
*
|
||||
* @param string aMultipartText
|
||||
* Multipart post text.
|
||||
* @return array
|
||||
* An array of header objects {name:x, value:x}
|
||||
*/
|
||||
getHeadersFromMultipartText: function(aMultipartText) {
|
||||
let headers = [];
|
||||
if (!aMultipartText || aMultipartText.startsWith("---")) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Get the header section.
|
||||
let index = aMultipartText.indexOf("\r\n\r\n");
|
||||
if (index == -1) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Parse the header lines.
|
||||
let headersText = aMultipartText.substring(0, index);
|
||||
let headerLines = headersText.split("\r\n");
|
||||
let lastHeaderName = null;
|
||||
|
||||
for (let line of headerLines) {
|
||||
// Create a header for each line in fields that spans across multiple lines.
|
||||
// Subsquent lines always begins with at least one space or tab character.
|
||||
// (rfc2616)
|
||||
if (lastHeaderName && /^\s+/.test(line)) {
|
||||
headers.push({ name: lastHeaderName, value: line.trim() });
|
||||
continue;
|
||||
}
|
||||
|
||||
let indexOfColon = line.indexOf(":");
|
||||
if (indexOfColon == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let header = [line.slice(0, indexOfColon), line.slice(indexOfColon + 1)];
|
||||
if (header.length != 2) {
|
||||
continue;
|
||||
}
|
||||
lastHeaderName = header[0].trim();
|
||||
headers.push({ name: lastHeaderName, value: header[1].trim() });
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Escape util function for POSIX oriented operating systems.
|
||||
* Credit: Google DevTools
|
||||
*/
|
||||
escapeStringPosix: function(str) {
|
||||
function escapeCharacter(x) {
|
||||
let code = x.charCodeAt(0);
|
||||
if (code < 256) {
|
||||
// Add leading zero when needed to not care about the next character.
|
||||
return code < 16 ? "\\x0" + code.toString(16) : "\\x" + code.toString(16);
|
||||
}
|
||||
code = code.toString(16);
|
||||
return "\\u" + ("0000" + code).substr(code.length, 4);
|
||||
}
|
||||
|
||||
if (/[^\x20-\x7E]|\'/.test(str)) {
|
||||
// Use ANSI-C quoting syntax.
|
||||
return "$\'" + str.replace(/\\/g, "\\\\")
|
||||
.replace(/\'/g, "\\\'")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/[^\x20-\x7E]/g, escapeCharacter) + "'";
|
||||
} else {
|
||||
// Use single quote syntax.
|
||||
return "'" + str + "'";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Escape util function for Windows systems.
|
||||
* Credit: Google DevTools
|
||||
*/
|
||||
escapeStringWin: function(str) {
|
||||
/* Replace quote by double quote (but not by \") because it is
|
||||
recognized by both cmd.exe and MS Crt arguments parser.
|
||||
|
||||
Replace % by "%" because it could be expanded to an environment
|
||||
variable value. So %% becomes "%""%". Even if an env variable ""
|
||||
(2 doublequotes) is declared, the cmd.exe will not
|
||||
substitute it with its value.
|
||||
|
||||
Replace each backslash with double backslash to make sure
|
||||
MS Crt arguments parser won't collapse them.
|
||||
|
||||
Replace new line outside of quotes since cmd.exe doesn't let
|
||||
to do it inside.
|
||||
*/
|
||||
return "\"" + str.replace(/"/g, "\"\"")
|
||||
.replace(/%/g, "\"%\"")
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/[\r\n]+/g, "\"^$&\"") + "\"";
|
||||
}
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"Experiments",
|
||||
"ExperimentsProvider",
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
@ -19,6 +20,7 @@ Cu.import("resource://gre/modules/Log.jsm");
|
|||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
|
||||
Cu.import("resource://gre/modules/Metrics.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
|
||||
"resource://gre/modules/UpdateChannel.jsm");
|
||||
|
@ -388,6 +390,45 @@ Experiments.Experiments.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine whether another date has the same UTC day as now().
|
||||
*/
|
||||
_dateIsTodayUTC: function (d) {
|
||||
let now = this._policy.now();
|
||||
|
||||
return stripDateToMidnight(now).getTime() == stripDateToMidnight(d).getTime();
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain the entry of the most recent active experiment that was active
|
||||
* today.
|
||||
*
|
||||
* If no experiment was active today, this resolves to nothing.
|
||||
*
|
||||
* Assumption: Only a single experiment can be active at a time.
|
||||
*
|
||||
* @return Promise<object>
|
||||
*/
|
||||
lastActiveToday: function () {
|
||||
return Task.spawn(function* getMostRecentActiveExperimentTask() {
|
||||
let experiments = yield this.getExperiments();
|
||||
|
||||
// Assumption: Ordered chronologically, descending, with active always
|
||||
// first.
|
||||
for (let experiment of experiments) {
|
||||
if (experiment.active) {
|
||||
return experiment;
|
||||
}
|
||||
|
||||
if (experiment.endDate && this._dateIsTodayUTC(experiment.endDate)) {
|
||||
return experiment;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch an updated list of experiments and trigger experiment updates.
|
||||
* Do only use when experiments are enabled.
|
||||
|
@ -1432,3 +1473,105 @@ Experiments.ExperimentEntry.prototype = {
|
|||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Strip a Date down to its UTC midnight.
|
||||
*
|
||||
* This will return a cloned Date object. The original is unchanged.
|
||||
*/
|
||||
let stripDateToMidnight = function (d) {
|
||||
let m = new Date(d);
|
||||
m.setUTCHours(0, 0, 0, 0);
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
function ExperimentsLastActiveMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
const FIELD_DAILY_LAST_TEXT = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT};
|
||||
|
||||
ExperimentsLastActiveMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "info",
|
||||
version: 1,
|
||||
|
||||
fields: {
|
||||
lastActive: FIELD_DAILY_LAST_TEXT,
|
||||
}
|
||||
});
|
||||
|
||||
this.ExperimentsProvider = function () {
|
||||
Metrics.Provider.call(this);
|
||||
|
||||
this._experiments = null;
|
||||
};
|
||||
|
||||
ExperimentsProvider.prototype = Object.freeze({
|
||||
__proto__: Metrics.Provider.prototype,
|
||||
|
||||
name: "org.mozilla.experiments",
|
||||
|
||||
measurementTypes: [
|
||||
ExperimentsLastActiveMeasurement1,
|
||||
],
|
||||
|
||||
_OBSERVERS: [
|
||||
OBSERVER_TOPIC,
|
||||
],
|
||||
|
||||
postInit: function () {
|
||||
this._experiments = Experiments.instance();
|
||||
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.addObserver(this, o, false);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
onShutdown: function () {
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.removeObserver(this, o);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
switch (topic) {
|
||||
case OBSERVER_TOPIC:
|
||||
this.recordLastActiveExperiment();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
collectDailyData: function () {
|
||||
return this.recordLastActiveExperiment();
|
||||
},
|
||||
|
||||
recordLastActiveExperiment: function () {
|
||||
let m = this.getMeasurement(ExperimentsLastActiveMeasurement1.prototype.name,
|
||||
ExperimentsLastActiveMeasurement1.prototype.version);
|
||||
|
||||
return this.enqueueStorageOperation(() => {
|
||||
return Task.spawn(function* recordTask() {
|
||||
let todayActive = yield this._experiments.lastActiveToday();
|
||||
|
||||
if (!todayActive) {
|
||||
this._log.info("No active experiment on this day: " +
|
||||
this._experiments._policy.now());
|
||||
return;
|
||||
}
|
||||
|
||||
this._log.info("Recording last active experiment: " + todayActive.id);
|
||||
yield m.setDailyLastText("lastActive", todayActive.id,
|
||||
this._experiments._policy.now());
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -2,3 +2,7 @@ component {f7800463-3b97-47f9-9341-b7617e6d8d49} ExperimentsService.js
|
|||
contract @mozilla.org/browser/experiments-service;1 {f7800463-3b97-47f9-9341-b7617e6d8d49}
|
||||
category update-timer ExperimentsService @mozilla.org/browser/experiments-service;1,getService,experiments-update-timer,experiments.manifest.fetchIntervalSeconds,86400
|
||||
category profile-after-change ExperimentsService @mozilla.org/browser/experiments-service;1
|
||||
|
||||
category healthreport-js-provider-default ExperimentsProvider resource://gre/browser/modules/Experiments/Experiments.jsm
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,35 @@ const EXPERIMENT2_ID = "test-experiment-2@tests.mozilla.org"
|
|||
const EXPERIMENT2_XPI_SHA1 = "sha1:81877991ec70360fb48db84c34a9b2da7aa41d6a";
|
||||
const EXPERIMENT2_XPI_NAME = "experiment-2.xpi";
|
||||
|
||||
const FAKE_EXPERIMENTS_1 = [
|
||||
{
|
||||
id: "id1",
|
||||
name: "experiment1",
|
||||
description: "experiment 1",
|
||||
active: true,
|
||||
detailUrl: "https://dummy/experiment1",
|
||||
},
|
||||
];
|
||||
|
||||
const FAKE_EXPERIMENTS_2 = [
|
||||
{
|
||||
id: "id2",
|
||||
name: "experiment2",
|
||||
description: "experiment 2",
|
||||
active: false,
|
||||
endDate: new Date(2014, 2, 11, 2, 4, 35, 42).getTime(),
|
||||
detailUrl: "https://dummy/experiment2",
|
||||
},
|
||||
{
|
||||
id: "id1",
|
||||
name: "experiment1",
|
||||
description: "experiment 1",
|
||||
active: false,
|
||||
endDate: new Date(2014, 2, 10, 0, 0, 0, 0).getTime(),
|
||||
detailURL: "https://dummy/experiment1",
|
||||
},
|
||||
];
|
||||
|
||||
let gAppInfo = null;
|
||||
|
||||
function getReporter(name, uri, inspected) {
|
||||
|
@ -129,3 +158,18 @@ function createAppInfo(options) {
|
|||
registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
|
||||
XULAPPINFO_CONTRACTID, XULAppInfoFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the experiments on an Experiments with a new list.
|
||||
*
|
||||
* This monkeypatches getExperiments(). It doesn't monkeypatch the internal
|
||||
* experiments list. So its utility is not as great as it could be.
|
||||
*/
|
||||
function replaceExperiments(experiment, list) {
|
||||
Object.defineProperty(experiment, "getExperiments", {
|
||||
writable: true,
|
||||
value: () => {
|
||||
return Promise.resolve(list);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -264,6 +264,33 @@ add_task(function* test_getExperiments() {
|
|||
yield removeCacheFile();
|
||||
});
|
||||
|
||||
add_task(function* test_lastActiveToday() {
|
||||
let experiments = new Experiments.Experiments(gPolicy);
|
||||
|
||||
replaceExperiments(experiments, FAKE_EXPERIMENTS_1);
|
||||
|
||||
let e = yield experiments.getExperiments();
|
||||
Assert.equal(e.length, 1, "Monkeypatch successful.");
|
||||
Assert.equal(e[0].id, "id1", "ID looks sane");
|
||||
Assert.ok(e[0].active, "Experiment is active.");
|
||||
|
||||
let lastActive = yield experiments.lastActiveToday();
|
||||
Assert.equal(e[0], lastActive, "Last active object is expected.");
|
||||
|
||||
replaceExperiments(experiments, FAKE_EXPERIMENTS_2);
|
||||
e = yield experiments.getExperiments();
|
||||
Assert.equal(e.length, 2, "Monkeypatch successful.");
|
||||
|
||||
defineNow(gPolicy, e[0].endDate);
|
||||
|
||||
lastActive = yield experiments.lastActiveToday();
|
||||
Assert.ok(lastActive, "Have a last active experiment");
|
||||
Assert.equal(lastActive, e[0], "Last active object is expected.");
|
||||
|
||||
yield experiments.uninit();
|
||||
yield removeCacheFile();
|
||||
});
|
||||
|
||||
// Test explicitly disabling experiments.
|
||||
|
||||
add_task(function* test_disableExperiment() {
|
||||
|
@ -636,6 +663,9 @@ add_task(function* test_userDisabledAndUpdated() {
|
|||
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
|
||||
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
|
||||
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
|
||||
let todayActive = yield experiments.lastActiveToday();
|
||||
Assert.ok(todayActive, "Last active for today reports a value.");
|
||||
Assert.equal(todayActive.id, list[0].id, "The entry is what we expect.");
|
||||
|
||||
// Explicitly disable an experiment.
|
||||
|
||||
|
@ -649,6 +679,9 @@ add_task(function* test_userDisabledAndUpdated() {
|
|||
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
|
||||
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
|
||||
Assert.equal(list[0].active, false, "Experiment should not be active anymore.");
|
||||
todayActive = yield experiments.lastActiveToday();
|
||||
Assert.ok(todayActive, "Last active for today still returns a value.");
|
||||
Assert.equal(todayActive.id, list[0].id, "The ID is still the same.");
|
||||
|
||||
// Trigger an update with a faked change for experiment 1.
|
||||
|
||||
|
@ -718,6 +751,9 @@ add_task(function* test_updateActiveExperiment() {
|
|||
let list = yield experiments.getExperiments();
|
||||
Assert.equal(list.length, 0, "Experiment list should be empty.");
|
||||
|
||||
let todayActive = yield experiments.lastActiveToday();
|
||||
Assert.equal(todayActive, null, "No experiment active today.");
|
||||
|
||||
// Trigger update, clock set for the experiment to start.
|
||||
|
||||
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
|
||||
|
@ -731,6 +767,9 @@ add_task(function* test_updateActiveExperiment() {
|
|||
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
|
||||
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
|
||||
Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match.");
|
||||
todayActive = yield experiments.lastActiveToday();
|
||||
Assert.ok(todayActive, "todayActive() returns a value.");
|
||||
Assert.equal(todayActive.id, list[0].id, "It returns the active experiment.");
|
||||
|
||||
// Trigger an update for the active experiment by changing it's hash (and xpi)
|
||||
// in the manifest.
|
||||
|
@ -748,6 +787,8 @@ add_task(function* test_updateActiveExperiment() {
|
|||
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
|
||||
Assert.equal(list[0].active, true, "Experiment 1 should still be active.");
|
||||
Assert.equal(list[0].name, EXPERIMENT1A_NAME, "Experiments name should have been updated.");
|
||||
todayActive = yield experiments.lastActiveToday();
|
||||
Assert.equal(todayActive.id, list[0].id, "last active today is still sane.");
|
||||
|
||||
// Cleanup.
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource:///modules/experiments/Experiments.jsm");
|
||||
Cu.import("resource://testing-common/services/healthreport/utils.jsm");
|
||||
Cu.import("resource://testing-common/services-common/logging.js");
|
||||
|
||||
function getStorageAndProvider(name) {
|
||||
return Task.spawn(function* get() {
|
||||
let storage = yield Metrics.Storage(name);
|
||||
let provider = new ExperimentsProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
return [storage, provider];
|
||||
});
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
initTestLogging();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_constructor() {
|
||||
let provider = new ExperimentsProvider();
|
||||
});
|
||||
|
||||
add_task(function* test_init() {
|
||||
let storage = yield Metrics.Storage("init");
|
||||
let provider = new ExperimentsProvider();
|
||||
yield provider.init(storage);
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function* test_collect() {
|
||||
let [storage, provider] = yield getStorageAndProvider("no_active");
|
||||
|
||||
// Initial state should not report anything.
|
||||
yield provider.collectDailyData();
|
||||
let m = provider.getMeasurement("info", 1);
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 0, "Have no data if no experiments known.");
|
||||
|
||||
// An old experiment that ended today should be reported.
|
||||
replaceExperiments(provider._experiments, FAKE_EXPERIMENTS_2);
|
||||
let now = new Date(FAKE_EXPERIMENTS_2[0].endDate);
|
||||
defineNow(provider._experiments._policy, now.getTime());
|
||||
|
||||
yield provider.collectDailyData();
|
||||
values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 1, "Have 1 day of data");
|
||||
Assert.ok(values.days.hasDay(now), "Has day the experiment ended.");
|
||||
let day = values.days.getDay(now);
|
||||
Assert.ok(day.has("lastActive"), "Has lastActive field.");
|
||||
Assert.equal(day.get("lastActive"), "id2", "Last active ID is sane.");
|
||||
|
||||
// Making an experiment active replaces the lastActive value.
|
||||
replaceExperiments(provider._experiments, FAKE_EXPERIMENTS_1);
|
||||
yield provider.collectDailyData();
|
||||
values = yield m.getValues();
|
||||
day = values.days.getDay(now);
|
||||
Assert.equal(day.get("lastActive"), "id1", "Last active ID is the active experiment.");
|
||||
|
||||
// And make sure the observer works.
|
||||
replaceExperiments(provider._experiments, FAKE_EXPERIMENTS_2);
|
||||
Services.obs.notifyObservers(null, "experiments-changed", null);
|
||||
// This may not wait long enough. It relies on the SQL insert happening
|
||||
// in the same tick as the observer notification.
|
||||
yield storage.enqueueOperation(function () {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
values = yield m.getValues();
|
||||
day = values.days.getDay(now);
|
||||
Assert.equal(day.get("lastActive"), "id2", "Last active ID set by observer.");
|
||||
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function* test_healthreporterJSON() {
|
||||
let reporter = yield getHealthReporter("healthreporterJSON");
|
||||
yield reporter.init();
|
||||
try {
|
||||
yield reporter._providerManager.registerProvider(new ExperimentsProvider());
|
||||
let experiments = Experiments.instance();
|
||||
defineNow(experiments._policy, Date.now());
|
||||
replaceExperiments(experiments, FAKE_EXPERIMENTS_1);
|
||||
yield reporter.collectMeasurements();
|
||||
|
||||
let payload = yield reporter.getJSONPayload(true);
|
||||
let today = reporter._formatDate(reporter._policy.now());
|
||||
|
||||
Assert.ok(today in payload.data.days, "Day in payload.");
|
||||
let day = payload.data.days[today];
|
||||
|
||||
Assert.ok("org.mozilla.experiments.info" in day, "Measurement present.");
|
||||
let m = day["org.mozilla.experiments.info"];
|
||||
Assert.ok("lastActive" in m, "lastActive field present.");
|
||||
Assert.equal(m["lastActive"], "id1", "Last active ID proper.");
|
||||
} finally {
|
||||
reporter._shutdown();
|
||||
}
|
||||
});
|
|
@ -12,3 +12,4 @@ support-files =
|
|||
[test_api.js]
|
||||
[test_conditions.js]
|
||||
[test_fetch.js]
|
||||
[test_healthreport.js]
|
||||
|
|
|
@ -202,6 +202,12 @@
|
|||
- on the context menu that copies the selected request's url -->
|
||||
<!ENTITY netmonitorUI.context.copyUrl "Copy URL">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.context.copyAsCurl): This is the label displayed
|
||||
- on the context menu that copies the selected request as a cURL command.
|
||||
- The capitalization is part of the official name and should be used throughout all languages.
|
||||
- http://en.wikipedia.org/wiki/CURL -->
|
||||
<!ENTITY netmonitorUI.context.copyAsCurl "Copy as cURL">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.context.copyUrl.accesskey): This is the access key
|
||||
- for the Copy URL menu item displayed in the context menu for a request -->
|
||||
<!ENTITY netmonitorUI.context.copyUrl.accesskey "C">
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
%include ../browser.inc
|
||||
|
||||
#PanelUI-popup #PanelUI-contents:empty {
|
||||
height: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
#PanelUI-popup #PanelUI-contents:empty::before {
|
||||
|
@ -328,6 +328,16 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"] > iframe {
|
|||
margin: 4px auto;
|
||||
}
|
||||
|
||||
#PanelUI-multiView[viewtype="subview"] > .panel-viewcontainer > .panel-viewstack > .panel-mainview > #PanelUI-mainView {
|
||||
background-color: hsla(210,4%,10%,.1);
|
||||
}
|
||||
|
||||
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .panel-wide-item,
|
||||
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .toolbarbutton-1:not([panel-multiview-anchor="true"]),
|
||||
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXgijs: this is a workaround for a layout issue that was caused by these iframes,
|
||||
* which was affecting subview display. Because of this, we're hiding the iframe *only*
|
||||
|
|
|
@ -22,6 +22,9 @@ export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:${_VSPAT
|
|||
## paths: win8 sdk x86 (32-bit) tools, msvc 10 (32-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
|
||||
|
||||
## WindowsSDKDir ##
|
||||
export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/"
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs2010-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
|
|
|
@ -19,6 +19,9 @@ export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:${_VSPAT
|
|||
## paths: win8 sdk x64 (64-bit) tools, msvc 10 (64-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x64:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/VC/BIN/x86_amd64:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:${PATH}"
|
||||
|
||||
## WindowsSDKDir ##
|
||||
export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/"
|
||||
|
||||
# Use 32bit linker for PGO crash bug.
|
||||
# https://connect.microsoft.com/VisualStudio/feedback/details/686117/
|
||||
if [ -f /c/PROGRA~2/MICROS~2.0/VC/BIN/x86_amd64/link.exe ]; then
|
||||
|
|
|
@ -903,7 +903,6 @@ LOCAL_INCLUDES += \
|
|||
ifeq (WINNT,$(OS_TARGET))
|
||||
# These get set via VC project file settings for normal GYP builds.
|
||||
DEFINES += -DUNICODE -D_UNICODE
|
||||
LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
|
||||
endif
|
||||
|
||||
DISABLE_STL_WRAPPING := 1
|
||||
|
|
137
configure.in
137
configure.in
|
@ -5770,10 +5770,12 @@ dnl = * only applies to win32
|
|||
dnl = * enabled by default (shipping build); requires explicit --disable to disable
|
||||
dnl ========================================================
|
||||
MOZ_ANGLE_RENDERER=
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
MOZ_DIRECTX_SDK_CPU_SUFFIX=
|
||||
MOZ_D3DCOMPILER_CAB=
|
||||
MOZ_DIRECTX_SDK_PATH=
|
||||
MOZ_D3DCOMPILER_DLL=
|
||||
MOZ_HAS_WINSDK_WITH_D3D=
|
||||
MOZ_D3DCOMPILER_DLL_PATH=
|
||||
MOZ_D3DCOMPILER_CAB=
|
||||
case "$target_os" in
|
||||
*mingw*)
|
||||
MOZ_ANGLE_RENDERER=1
|
||||
|
@ -5795,6 +5797,11 @@ MOZ_ARG_DISABLE_BOOL(webgl,
|
|||
MOZ_WEBGL_DISABLED=1,
|
||||
MOZ_WEBGL_DISABLED=)
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(winsdk-directx,
|
||||
[ --enable-winsdk-directx use DirectX SDK in Windows SDK],
|
||||
MOZ_WINSDK_DIRECTX=1,
|
||||
MOZ_WINSDK_DIRECTX=)
|
||||
|
||||
if test -n "$MOZ_WEBGL_DISABLED"; then
|
||||
MOZ_WEBGL=
|
||||
MOZ_ANGLE_RENDERER=
|
||||
|
@ -5808,6 +5815,7 @@ if test -n "$MOZ_WEBGL_CONFORMANT"; then
|
|||
AC_DEFINE(MOZ_WEBGL_CONFORMANT)
|
||||
fi
|
||||
|
||||
|
||||
# Locate a DirectX SDK here so we can use it for both ANGLE and
|
||||
# Joystick support.
|
||||
if test "$OS_TARGET" = "WINNT" -a -z "$CROSS_COMPILE"; then
|
||||
|
@ -5819,37 +5827,95 @@ if test "$OS_TARGET" = "WINNT" -a -z "$CROSS_COMPILE"; then
|
|||
MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK' | head -n 1`
|
||||
fi
|
||||
MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/' | sed 's,\\\\,/,g'`
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_ANGLE_RENDERER" -a -z "$CROSS_COMPILE"; then
|
||||
if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
|
||||
AC_MSG_ERROR([Found the February 2010 DirectX SDK. Need the June 2010 DirectX SDK, or newer. Upgrade your SDK or reconfigure with --disable-webgl.])
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH" &&
|
||||
test -f "$MOZ_DIRECTX_SDK_PATH"/include/d3dx9.h &&
|
||||
test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/dxguid.lib ; then
|
||||
AC_MSG_RESULT([Found DirectX SDK via registry, using $MOZ_DIRECTX_SDK_PATH])
|
||||
else
|
||||
AC_MSG_ERROR([Couldn't find the DirectX SDK, needed for WebGL. Either install it (June 2010 version or newer), or reconfigure with --disable-webgl.])
|
||||
AC_MSG_RESULT([Couldn't find the DirectX SDK.])
|
||||
fi
|
||||
|
||||
# Get the SDK numeric version (e.g. 43) by looking at the dependencies of d3dx9.lib
|
||||
MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'`
|
||||
|
||||
if test -z "$MOZ_D3DX9_VERSION" ; then
|
||||
AC_MSG_ERROR([Couldn't determine the D3DX9 version, needed for WebGL. Either reinstall the DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
|
||||
fi
|
||||
|
||||
MOZ_D3DCOMPILER_CAB=`find "$MOZ_DIRECTX_SDK_PATH"/Redist -name *D3DCompiler_${MOZ_D3DX9_VERSION}_${MOZ_DIRECTX_SDK_CPU_SUFFIX}.cab | head -n1`
|
||||
|
||||
if test -z "$MOZ_D3DCOMPILER_CAB"; then
|
||||
AC_MSG_ERROR([Couldn't find the DirectX redistributable files. Either reinstall the DirectX SDK (making sure the "DirectX Redistributable Files" option is selected), or reconfigure with --disable-webgl.])
|
||||
fi
|
||||
|
||||
MOZ_D3DCOMPILER_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
|
||||
fi
|
||||
|
||||
|
||||
dnl ========================================================
|
||||
dnl D3D compiler DLL
|
||||
dnl ========================================================
|
||||
|
||||
if test -n "$MOZ_ANGLE_RENDERER"; then
|
||||
# Check that our DirectX SDK is acceptable.
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH"; then
|
||||
if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
|
||||
AC_MSG_RESULT([Found the February 2010 DirectX SDK, which is unacceptable to ANGLE.])
|
||||
MOZ_DIRECTX_SDK_PATH_BAD=1
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH" &&
|
||||
test -f "$MOZ_DIRECTX_SDK_PATH"/include/d3dx9.h &&
|
||||
test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/dxguid.lib ; then
|
||||
AC_MSG_RESULT([Found acceptable DirectX SDK for ANGLE.])
|
||||
else
|
||||
AC_MSG_RESULT([Found DirectX SDK is unacceptable for ANGLE.])
|
||||
MOZ_DIRECTX_SDK_PATH_BAD=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH_BAD"; then
|
||||
AC_MSG_ERROR([Couldn't find an acceptable DirectX SDK for ANGLE. Either install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
|
||||
fi
|
||||
|
||||
# Find a D3D compiler DLL in a Windows SDK.
|
||||
MOZ_D3DCOMPILER_DLL=
|
||||
if test -n "$MOZ_WINSDK_DIRECTX"; then
|
||||
case "$MOZ_WINSDK_MAXVER" in
|
||||
0x0603*)
|
||||
MOZ_D3DCOMPILER_DLL=d3dcompiler_47.dll
|
||||
AC_MSG_RESULT([Found D3D compiler in Windows SDK 8.1.])
|
||||
;;
|
||||
0x0602*)
|
||||
MOZ_D3DCOMPILER_DLL=d3dcompiler_46.dll
|
||||
AC_MSG_RESULT([Found D3D compiler in Windows SDK 8.0.])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_D3DCOMPILER_DLL"; then
|
||||
# We have a name, now track down the path.
|
||||
if test -n "$WINDOWSSDKDIR"; then
|
||||
MOZ_D3DCOMPILER_DLL_PATH="$WINDOWSSDKDIR/Redist/D3D/$MOZ_DIRECTX_SDK_CPU_SUFFIX/$MOZ_D3DCOMPILER_DLL"
|
||||
if test -f "$MOZ_D3DCOMPILER_DLL_PATH"; then
|
||||
MOZ_HAS_WINSDK_WITH_D3D=1
|
||||
AC_MSG_RESULT([Found MOZ_D3DCOMPILER_DLL_PATH: $MOZ_D3DCOMPILER_DLL_PATH])
|
||||
else
|
||||
AC_MSG_RESULT([MOZ_D3DCOMPILER_DLL_PATH doesn't exist: $MOZ_D3DCOMPILER_DLL_PATH])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([WINDOWSSDKDIR is missing.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Find a D3D compiler DLL in the DirectX SDK, if we didn't find one already.
|
||||
# Get the SDK numeric version (e.g. 43) by looking at the dependencies of d3dx9.lib
|
||||
if test -z "$MOZ_HAS_WINSDK_WITH_D3D"; then
|
||||
MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'`
|
||||
|
||||
if test -n "$MOZ_D3DX9_VERSION" ; then
|
||||
MOZ_D3DCOMPILER_CAB=`find "$MOZ_DIRECTX_SDK_PATH"/Redist -name *D3DCompiler_${MOZ_D3DX9_VERSION}_${MOZ_DIRECTX_SDK_CPU_SUFFIX}.cab | head -n1`
|
||||
MOZ_D3DCOMPILER_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
|
||||
else
|
||||
AC_MSG_RESULT([Couldn't determine the D3DX9 version for the DirectX SDK.])
|
||||
fi
|
||||
|
||||
if test -z "$MOZ_D3DCOMPILER_CAB"; then
|
||||
AC_MSG_RESULT([Couldn't find a CAB containing the D3D compiler DLL.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$MOZ_D3DCOMPILER_DLL_PATH" -a -z "$MOZ_D3DCOMPILER_CAB"; then
|
||||
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL. Either install Windows SDK 8.0+ and reconfigure with --enable-winsdk-directx, install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
dnl ========================================================
|
||||
dnl Gamepad support
|
||||
dnl ========================================================
|
||||
|
@ -5876,12 +5942,14 @@ if test "$MOZ_GAMEPAD"; then
|
|||
MOZ_GAMEPAD_BACKEND=cocoa
|
||||
;;
|
||||
WINNT)
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH" ; then
|
||||
if ! test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/dxguid.lib ; then
|
||||
MOZ_GAMEPAD=
|
||||
if test -z "$MOZ_HAS_WINSDK_WITH_D3D"; then
|
||||
if test -n "$MOZ_DIRECTX_SDK_PATH" ; then
|
||||
if ! test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/dxguid.lib ; then
|
||||
MOZ_GAMEPAD=
|
||||
fi
|
||||
elif test "$GCC" != "yes"; then
|
||||
MOZ_GAMEPAD=
|
||||
fi
|
||||
elif test "$GCC" != "yes"; then
|
||||
MOZ_GAMEPAD=
|
||||
fi
|
||||
if test -z "$MOZ_GAMEPAD"; then
|
||||
AC_MSG_ERROR([Couldn't find the DirectX SDK, needed for gamepad support. Please install it or, reconfigure with --disable-gamepad to disable gamepad support.])
|
||||
|
@ -8388,12 +8456,15 @@ AC_SUBST(MOZ_STUB_INSTALLER)
|
|||
AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE)
|
||||
AC_SUBST(MOZ_ENABLE_SIGNMAR)
|
||||
AC_SUBST(MOZ_UPDATER)
|
||||
|
||||
AC_SUBST(MOZ_ANGLE_RENDERER)
|
||||
AC_SUBST(MOZ_DIRECTX_SDK_PATH)
|
||||
AC_SUBST(MOZ_DIRECTX_SDK_CPU_SUFFIX)
|
||||
AC_SUBST(MOZ_D3DX9_VERSION)
|
||||
AC_SUBST(MOZ_D3DCOMPILER_CAB)
|
||||
AC_SUBST(MOZ_DIRECTX_SDK_PATH)
|
||||
AC_SUBST(MOZ_D3DCOMPILER_DLL)
|
||||
AC_SUBST(MOZ_HAS_WINSDK_WITH_D3D)
|
||||
AC_SUBST(MOZ_D3DCOMPILER_DLL_PATH)
|
||||
AC_SUBST(MOZ_D3DCOMPILER_CAB)
|
||||
|
||||
AC_SUBST(MOZ_METRO)
|
||||
|
||||
AC_SUBST(MOZ_ANDROID_HISTORY)
|
||||
|
|
|
@ -1772,9 +1772,6 @@ this.CSPNonceSource = function CSPNonceSource() {
|
|||
}
|
||||
|
||||
CSPNonceSource.fromString = function(aStr, aCSPRep) {
|
||||
if (!CSPPrefObserver.experimentalEnabled)
|
||||
return null;
|
||||
|
||||
let nonce = R_NONCESRC.exec(aStr)[1];
|
||||
if (!nonce) {
|
||||
cspError(aCSPRep, "Error in parsing nonce-source from string: nonce was empty");
|
||||
|
@ -1789,8 +1786,6 @@ CSPNonceSource.fromString = function(aStr, aCSPRep) {
|
|||
CSPNonceSource.prototype = {
|
||||
|
||||
permits: function(aContext) {
|
||||
if (!CSPPrefObserver.experimentalEnabled) return false;
|
||||
|
||||
if (aContext instanceof Ci.nsIDOMHTMLElement) {
|
||||
return this._nonce === aContext.getAttribute('nonce');
|
||||
} else if (typeof aContext === 'string') {
|
||||
|
@ -1822,9 +1817,6 @@ this.CSPHashSource = function CSPHashSource() {
|
|||
}
|
||||
|
||||
CSPHashSource.fromString = function(aStr, aCSPRep) {
|
||||
if (!CSPPrefObserver.experimentalEnabled)
|
||||
return null;
|
||||
|
||||
let hashSrcMatch = R_HASHSRC.exec(aStr);
|
||||
let algo = hashSrcMatch[1];
|
||||
let hash = hashSrcMatch[2];
|
||||
|
@ -1846,8 +1838,6 @@ CSPHashSource.fromString = function(aStr, aCSPRep) {
|
|||
CSPHashSource.prototype = {
|
||||
|
||||
permits: function(aContext) {
|
||||
if (!CSPPrefObserver.experimentalEnabled) return false;
|
||||
|
||||
let ScriptableUnicodeConverter =
|
||||
Components.Constructor("@mozilla.org/intl/scriptableunicodeconverter",
|
||||
"nsIScriptableUnicodeConverter");
|
||||
|
|
|
@ -208,9 +208,6 @@ ContentSecurityPolicy.prototype = {
|
|||
},
|
||||
|
||||
getAllowsNonce: function(aNonce, aContentType, shouldReportViolation) {
|
||||
if (!CSPPrefObserver.experimentalEnabled)
|
||||
return false;
|
||||
|
||||
if (!(aContentType == Ci.nsIContentPolicy.TYPE_SCRIPT ||
|
||||
aContentType == Ci.nsIContentPolicy.TYPE_STYLESHEET)) {
|
||||
CSPdebug("Nonce check requested for an invalid content type (not script or style): " + aContentType);
|
||||
|
@ -223,7 +220,9 @@ ContentSecurityPolicy.prototype = {
|
|||
|
||||
shouldReportViolation.value = this._policies.some(function(policy, i) {
|
||||
// Don't report a violation if the policy didn't use nonce-source
|
||||
return policy._directives[directive]._hasNonceSource && !policyAllowsNonce[i];
|
||||
return policy._directives.hasOwnProperty(directive) &&
|
||||
policy._directives[directive]._hasNonceSource &&
|
||||
!policyAllowsNonce[i];
|
||||
});
|
||||
|
||||
// allow it to execute? (Do all the policies allow it to execute)?
|
||||
|
@ -233,9 +232,6 @@ ContentSecurityPolicy.prototype = {
|
|||
},
|
||||
|
||||
getAllowsHash: function(aContent, aContentType, shouldReportViolation) {
|
||||
if (!CSPPrefObserver.experimentalEnabled)
|
||||
return false;
|
||||
|
||||
if (!(aContentType == Ci.nsIContentPolicy.TYPE_SCRIPT ||
|
||||
aContentType == Ci.nsIContentPolicy.TYPE_STYLESHEET)) {
|
||||
CSPdebug("Hash check requested for an invalid content type (not script or style): " + aContentType);
|
||||
|
@ -248,7 +244,9 @@ ContentSecurityPolicy.prototype = {
|
|||
|
||||
shouldReportViolation.value = this._policies.some(function(policy, i) {
|
||||
// Don't report a violation if the policy didn't use hash-source
|
||||
return policy._directives[directive]._hasHashSource && !policyAllowsHash[i];
|
||||
return policy._directives.hasOwnProperty(directive) &&
|
||||
policy._directives[directive]._hasHashSource &&
|
||||
!policyAllowsHash[i];
|
||||
});
|
||||
|
||||
// allow it to execute? (Do all the policies allow it to execute)?
|
||||
|
|
|
@ -126,8 +126,7 @@ function checkInline () {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set':[["security.csp.speccompliant", true],
|
||||
["security.csp.experimentalEnabled", true]]},
|
||||
{'set':[["security.csp.speccompliant", true]]},
|
||||
function() {
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
|
|
|
@ -113,8 +113,7 @@ window.examiner = new examiner();
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set':[["security.csp.speccompliant", true],
|
||||
["security.csp.experimentalEnabled", true]]},
|
||||
{'set':[["security.csp.speccompliant", true]]},
|
||||
function() {
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
|
|
|
@ -89,6 +89,22 @@ VideoData::~VideoData()
|
|||
MOZ_COUNT_DTOR(VideoData);
|
||||
}
|
||||
|
||||
size_t
|
||||
VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
// Currently only PLANAR_YCBCR has a well defined function for determining
|
||||
// it's size, so reporting is limited to that type.
|
||||
if (mImage && mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
|
||||
const mozilla::layers::PlanarYCbCrImage* img =
|
||||
static_cast<const mozilla::layers::PlanarYCbCrImage*>(mImage.get());
|
||||
size += img->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* static */
|
||||
VideoData* VideoData::ShallowCopyUpdateDuration(VideoData* aOther,
|
||||
int64_t aDuration)
|
||||
|
|
|
@ -225,6 +225,8 @@ public:
|
|||
|
||||
~VideoData();
|
||||
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
// Dimensions at which to display the video frame. The picture region
|
||||
// will be scaled to this size. This is should be the picture region's
|
||||
// dimensions scaled with respect to its aspect ratio.
|
||||
|
|
|
@ -1564,9 +1564,9 @@ nsresult MediaDecoder::GetBuffered(dom::TimeRanges* aBuffered) {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int64_t MediaDecoder::VideoQueueMemoryInUse() {
|
||||
size_t MediaDecoder::SizeOfVideoQueue() {
|
||||
if (mDecoderStateMachine) {
|
||||
return mDecoderStateMachine->VideoQueueMemoryInUse();
|
||||
return mDecoderStateMachine->SizeOfVideoQueue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1836,7 +1836,7 @@ MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
DecodersArray& decoders = Decoders();
|
||||
for (size_t i = 0; i < decoders.Length(); ++i) {
|
||||
MediaDecoder* decoder = decoders[i];
|
||||
video += decoder->VideoQueueMemoryInUse();
|
||||
video += decoder->SizeOfVideoQueue();
|
||||
audio += decoder->SizeOfAudioQueue();
|
||||
|
||||
if (decoder->GetResource()) {
|
||||
|
|
|
@ -646,7 +646,7 @@ public:
|
|||
|
||||
// Returns the size, in bytes, of the heap memory used by the currently
|
||||
// queued decoded video and audio data.
|
||||
virtual int64_t VideoQueueMemoryInUse();
|
||||
size_t SizeOfVideoQueue();
|
||||
size_t SizeOfAudioQueue();
|
||||
|
||||
VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE
|
||||
|
|
|
@ -31,18 +31,36 @@ extern PRLogModuleInfo* gMediaDecoderLog;
|
|||
#define SEEK_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
void* MediaDecoderReader::VideoQueueMemoryFunctor::operator()(void* anObject) {
|
||||
const VideoData* v = static_cast<const VideoData*>(anObject);
|
||||
if (!v->mImage) {
|
||||
class VideoQueueMemoryFunctor : public nsDequeFunctor {
|
||||
public:
|
||||
VideoQueueMemoryFunctor() : mSize(0) {}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
virtual void* operator()(void* aObject) {
|
||||
const VideoData* v = static_cast<const VideoData*>(aObject);
|
||||
mSize += v->SizeOfIncludingThis(MallocSizeOf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (v->mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
|
||||
mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());
|
||||
mResult += vi->GetDataSize();
|
||||
size_t mSize;
|
||||
};
|
||||
|
||||
|
||||
class AudioQueueMemoryFunctor : public nsDequeFunctor {
|
||||
public:
|
||||
AudioQueueMemoryFunctor() : mSize(0) {}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
virtual void* operator()(void* aObject) {
|
||||
const AudioData* audioData = static_cast<const AudioData*>(aObject);
|
||||
mSize += audioData->SizeOfIncludingThis(MallocSizeOf);
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t mSize;
|
||||
};
|
||||
|
||||
MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
|
||||
: mAudioCompactor(mAudioQueue),
|
||||
|
@ -58,6 +76,20 @@ MediaDecoderReader::~MediaDecoderReader()
|
|||
MOZ_COUNT_DTOR(MediaDecoderReader);
|
||||
}
|
||||
|
||||
size_t MediaDecoderReader::SizeOfVideoQueueInBytes() const
|
||||
{
|
||||
VideoQueueMemoryFunctor functor;
|
||||
mVideoQueue.LockedForEach(functor);
|
||||
return functor.mSize;
|
||||
}
|
||||
|
||||
size_t MediaDecoderReader::SizeOfAudioQueueInBytes() const
|
||||
{
|
||||
AudioQueueMemoryFunctor functor;
|
||||
mAudioQueue.LockedForEach(functor);
|
||||
return functor.mSize;
|
||||
}
|
||||
|
||||
nsresult MediaDecoderReader::ResetDecode()
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
|
|
|
@ -132,41 +132,13 @@ public:
|
|||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
||||
int64_t aStartTime);
|
||||
|
||||
class VideoQueueMemoryFunctor : public nsDequeFunctor {
|
||||
public:
|
||||
VideoQueueMemoryFunctor() : mResult(0) {}
|
||||
// Returns the number of bytes of memory allocated by structures/frames in
|
||||
// the video queue.
|
||||
size_t SizeOfVideoQueueInBytes() const;
|
||||
|
||||
virtual void* operator()(void* anObject);
|
||||
|
||||
int64_t mResult;
|
||||
};
|
||||
|
||||
virtual int64_t VideoQueueMemoryInUse() {
|
||||
VideoQueueMemoryFunctor functor;
|
||||
mVideoQueue.LockedForEach(functor);
|
||||
return functor.mResult;
|
||||
}
|
||||
|
||||
class AudioQueueMemoryFunctor : public nsDequeFunctor {
|
||||
public:
|
||||
AudioQueueMemoryFunctor() : mSize(0) {}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
virtual void* operator()(void* anObject) {
|
||||
const AudioData* audioData = static_cast<const AudioData*>(anObject);
|
||||
mSize += audioData->SizeOfIncludingThis(MallocSizeOf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t mSize;
|
||||
};
|
||||
|
||||
size_t SizeOfAudioQueue() {
|
||||
AudioQueueMemoryFunctor functor;
|
||||
mAudioQueue.LockedForEach(functor);
|
||||
return functor.mSize;
|
||||
}
|
||||
// Returns the number of bytes of memory allocated by structures/frames in
|
||||
// the audio queue.
|
||||
size_t SizeOfAudioQueueInBytes() const;
|
||||
|
||||
// Only used by WebMReader and MediaOmxReader for now, so stub here rather
|
||||
// than in every reader than inherits from MediaDecoderReader.
|
||||
|
|
|
@ -266,16 +266,16 @@ public:
|
|||
void SetPlaybackRate(double aPlaybackRate);
|
||||
void SetPreservesPitch(bool aPreservesPitch);
|
||||
|
||||
int64_t VideoQueueMemoryInUse() {
|
||||
size_t SizeOfVideoQueue() {
|
||||
if (mReader) {
|
||||
return mReader->VideoQueueMemoryInUse();
|
||||
return mReader->SizeOfVideoQueueInBytes();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SizeOfAudioQueue() {
|
||||
if (mReader) {
|
||||
return mReader->SizeOfAudioQueue();
|
||||
return mReader->SizeOfAudioQueueInBytes();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,20 @@ using mozilla::AudioDataValue;
|
|||
using mozilla::MediaDecoderReader;
|
||||
using mozilla::MediaQueue;
|
||||
|
||||
class MemoryFunctor : public nsDequeFunctor {
|
||||
public:
|
||||
MemoryFunctor() : mSize(0) {}
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
virtual void* operator()(void* anObject) {
|
||||
const AudioData* audioData = static_cast<const AudioData*>(anObject);
|
||||
mSize += audioData->SizeOfIncludingThis(MallocSizeOf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t mSize;
|
||||
};
|
||||
|
||||
class TestCopy
|
||||
{
|
||||
public:
|
||||
|
@ -60,7 +74,7 @@ static void TestAudioCompactor(size_t aBytes)
|
|||
EXPECT_GT(callCount, 0U) << "copy functor never called";
|
||||
EXPECT_EQ(frames, frameCount) << "incorrect number of frames copied";
|
||||
|
||||
MediaDecoderReader::AudioQueueMemoryFunctor memoryFunc;
|
||||
MemoryFunctor memoryFunc;
|
||||
queue.LockedForEach(memoryFunc);
|
||||
size_t allocSize = memoryFunc.mSize - (callCount * sizeof(AudioData));
|
||||
size_t slop = allocSize - aBytes;
|
||||
|
|
|
@ -10,14 +10,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=500261
|
|||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500261">Mozilla Bug 500261</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="1" id="svg">
|
||||
<image width="1" height="1" xlink:href="http://localhost/serverGone.gif" onerror="run()"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
|
@ -31,6 +23,14 @@ function run()
|
|||
|
||||
]]>
|
||||
</script>
|
||||
<div id="content">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="1" id="svg">
|
||||
<image width="1" height="1" xlink:href="http://localhost/serverGone.gif" onerror="run()"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
XPIDL_SOURCES += [
|
||||
'nsIActivityProxy.idl',
|
||||
'nsIActivityUIGlue.idl',
|
||||
'nsIDOMActivityRequestHandler.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_activities'
|
||||
|
|
|
@ -1,13 +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 "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(e93c4df2-af49-4421-8d75-1237b51c555b)]
|
||||
interface nsIDOMMozActivityRequestHandler : nsISupports
|
||||
{
|
||||
void postResult(in jsval result);
|
||||
void postError(in DOMString error);
|
||||
readonly attribute jsval source;
|
||||
};
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
|
@ -25,30 +24,28 @@ function debug(aMsg) {
|
|||
|
||||
function ActivityRequestHandler() {
|
||||
debug("ActivityRequestHandler");
|
||||
this.wrappedJSObject = this;
|
||||
|
||||
// When a system message of type 'activity' is emitted, it forces the
|
||||
// creation of an ActivityWrapper which in turns replace the default
|
||||
// system message callback. The newly created wrapper then create a
|
||||
// nsIDOMActivityRequestHandler object and fills up the properties of
|
||||
// this object as well as the properties of the ActivityOptions
|
||||
// dictionary contained by the request handler.
|
||||
this._id = null;
|
||||
this._options = null;
|
||||
// system message callback. The newly created wrapper then create an
|
||||
// ActivityRequestHandler object.
|
||||
}
|
||||
|
||||
ActivityRequestHandler.prototype = {
|
||||
__exposedProps__: {
|
||||
source: "r",
|
||||
postResult: "r",
|
||||
postError: "r"
|
||||
},
|
||||
init: function arh_init(aWindow) {
|
||||
this._window = aWindow;
|
||||
},
|
||||
|
||||
__init: function arh___init(aId, aOptions) {
|
||||
this._id = aId;
|
||||
this._options = aOptions;
|
||||
},
|
||||
|
||||
get source() {
|
||||
if (this._options === null) {
|
||||
Cu.reportError("ActivityRequestHandler._options must be initialized at this point");
|
||||
}
|
||||
return this._options;
|
||||
// We need to clone this object because the this._options.data has
|
||||
// the type any in WebIDL which will cause the binding layer to pass
|
||||
// the value which is a COW unmodified to content.
|
||||
return Cu.cloneInto(this._options, this._window);
|
||||
},
|
||||
|
||||
postResult: function arh_postResult(aResult) {
|
||||
|
@ -70,16 +67,8 @@ ActivityRequestHandler.prototype = {
|
|||
classID: Components.ID("{9326952a-dbe3-4d81-a51f-d9c160d96d6b}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIDOMMozActivityRequestHandler
|
||||
]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: Components.ID("{9326952a-dbe3-4d81-a51f-d9c160d96d6b}"),
|
||||
contractID: "@mozilla.org/dom/activities/request-handler;1",
|
||||
interfaces: [Ci.nsIDOMMozActivityRequestHandler],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Activity Request Handler"
|
||||
})
|
||||
Ci.nsIDOMGlobalPropertyInitializer
|
||||
])
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ActivityRequestHandler]);
|
||||
|
|
|
@ -37,15 +37,7 @@ ActivityWrapper.prototype = {
|
|||
// Activity workflow.
|
||||
cpmm.sendAsyncMessage("Activity:Ready", { id: aMessage.id });
|
||||
|
||||
let handler = Cc["@mozilla.org/dom/activities/request-handler;1"]
|
||||
.createInstance(Ci.nsIDOMMozActivityRequestHandler);
|
||||
handler.wrappedJSObject._id = aMessage.id;
|
||||
|
||||
// options is an ActivityOptions dictionary.
|
||||
handler.wrappedJSObject._options = Cu.cloneInto({
|
||||
name: aMessage.payload.name,
|
||||
data: Cu.cloneInto(aMessage.payload.data, aWindow),
|
||||
}, aWindow);
|
||||
let handler = new aWindow.ActivityRequestHandler(aMessage.id, aMessage.payload);
|
||||
|
||||
// When the activity window is closed, fire an error to notify the activity
|
||||
// caller of the situation.
|
||||
|
|
|
@ -2296,6 +2296,14 @@ Navigator::HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal)
|
|||
Preferences::GetBool("dom.mozDownloads.enabled");
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasPermissionSettingsSupport(JSContext* /* unused */, JSObject* aGlobal)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
|
||||
return CheckPermission(win, "permissions");
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsPIDOMWindow>
|
||||
Navigator::GetWindowFromGlobal(JSObject* aGlobal)
|
||||
|
|
|
@ -306,6 +306,8 @@ public:
|
|||
|
||||
static bool HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static bool HasPermissionSettingsSupport(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return GetWindow();
|
||||
|
|
|
@ -162,6 +162,23 @@ nsDOMWindowUtils::GetDocument()
|
|||
return window->GetExtantDoc();
|
||||
}
|
||||
|
||||
LayerTransactionChild*
|
||||
nsDOMWindowUtils::GetLayerTransaction()
|
||||
{
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (!widget)
|
||||
return nullptr;
|
||||
|
||||
LayerManager* manager = widget->GetLayerManager();
|
||||
if (!manager)
|
||||
return nullptr;
|
||||
|
||||
ShadowLayerForwarder* forwarder = manager->AsShadowForwarder();
|
||||
return forwarder && forwarder->HasShadowManager() ?
|
||||
forwarder->GetShadowManager() :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetImageAnimationMode(uint16_t *aMode)
|
||||
{
|
||||
|
@ -2552,12 +2569,9 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
|
|||
nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
|
||||
driver->AdvanceTimeAndRefresh(aMilliseconds);
|
||||
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (widget) {
|
||||
CompositorChild* compositor = widget->GetRemoteRenderer();
|
||||
if (compositor) {
|
||||
compositor->SendSetTestSampleTime(driver->MostRecentRefresh());
|
||||
}
|
||||
LayerTransactionChild* transaction = GetLayerTransaction();
|
||||
if (transaction) {
|
||||
transaction->SendSetTestSampleTime(driver->MostRecentRefresh());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2573,12 +2587,9 @@ nsDOMWindowUtils::RestoreNormalRefresh()
|
|||
// Kick the compositor out of test mode before the refresh driver, so that
|
||||
// the refresh driver doesn't send an update that gets ignored by the
|
||||
// compositor.
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (widget) {
|
||||
CompositorChild* compositor = widget->GetRemoteRenderer();
|
||||
if (compositor) {
|
||||
compositor->SendLeaveTestMode();
|
||||
}
|
||||
LayerTransactionChild* transaction = GetLayerTransaction();
|
||||
if (transaction) {
|
||||
transaction->SendLeaveTestMode();
|
||||
}
|
||||
|
||||
nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
|
||||
|
|
|
@ -19,6 +19,12 @@ class nsPresContext;
|
|||
class nsPoint;
|
||||
class nsIDocument;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class LayerTransactionChild;
|
||||
}
|
||||
}
|
||||
|
||||
class nsDOMWindowUtils MOZ_FINAL : public nsIDOMWindowUtils,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
|
@ -41,6 +47,7 @@ protected:
|
|||
nsIPresShell* GetPresShell();
|
||||
nsPresContext* GetPresContext();
|
||||
nsIDocument* GetDocument();
|
||||
mozilla::layers::LayerTransactionChild* GetLayerTransaction();
|
||||
|
||||
NS_IMETHOD SendMouseEventCommon(const nsAString& aType,
|
||||
float aX,
|
||||
|
|
|
@ -27,8 +27,8 @@ class nsIDOMWindow;
|
|||
class nsIURI;
|
||||
|
||||
#define NS_ISCRIPTCONTEXT_IID \
|
||||
{ 0x7cf47061, 0x745d, 0x4c6c, \
|
||||
{ 0xa0, 0xe5, 0x9f, 0xef, 0xa8, 0xcc, 0x2a, 0xf0 } }
|
||||
{ 0x274840b6, 0x7349, 0x4798, \
|
||||
{ 0xbe, 0x24, 0xbd, 0x75, 0xa6, 0x46, 0x99, 0xb7 } }
|
||||
|
||||
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
|
||||
know what language we have is a little silly... */
|
||||
|
@ -45,32 +45,6 @@ class nsIScriptContext : public nsISupports
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTCONTEXT_IID)
|
||||
|
||||
/**
|
||||
* Bind an already-compiled event handler function to the given
|
||||
* target. Scripting languages with static scoping must re-bind the
|
||||
* scope chain for aHandler to begin (after the activation scope for
|
||||
* aHandler itself, typically) with aTarget's scope.
|
||||
*
|
||||
* The result of the bind operation is a new handler object, with
|
||||
* principals now set and scope set as above. This is returned in
|
||||
* aBoundHandler. When this function is called, aBoundHandler is
|
||||
* expected to not be holding an object.
|
||||
*
|
||||
* @param aTarget an object telling the scope in which to bind the compiled
|
||||
* event handler function. The context will presumably associate
|
||||
* this nsISupports with a native script object.
|
||||
* @param aScope the scope in which the script object for aTarget should be
|
||||
* looked for.
|
||||
* @param aHandler the function object to bind, created by an earlier call to
|
||||
* CompileEventHandler
|
||||
* @param aBoundHandler [out] the result of the bind operation.
|
||||
* @return NS_OK if the function was successfully bound
|
||||
*/
|
||||
virtual nsresult BindCompiledEventHandler(nsISupports* aTarget,
|
||||
JS::Handle<JSObject*> aScope,
|
||||
JS::Handle<JSObject*> aHandler,
|
||||
JS::MutableHandle<JSObject*> aBoundHandler) = 0;
|
||||
|
||||
/**
|
||||
* Return the global object.
|
||||
*
|
||||
|
|
|
@ -909,95 +909,6 @@ AtomIsEventHandlerName(nsIAtom *aName)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Helper function to find the JSObject associated with a (presumably DOM)
|
||||
// interface.
|
||||
nsresult
|
||||
nsJSContext::JSObjectFromInterface(nsISupports* aTarget,
|
||||
JS::Handle<JSObject*> aScope,
|
||||
JSObject** aRet)
|
||||
{
|
||||
// It is legal to specify a null target.
|
||||
if (!aTarget) {
|
||||
*aRet = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoJSContext cx;
|
||||
|
||||
// Get the jsobject associated with this target
|
||||
// We don't wrap here because we trust the JS engine to wrap the target
|
||||
// later.
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
nsresult rv = nsContentUtils::WrapNative(cx, aScope, aTarget, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject* obj = v.toObjectOrNull();
|
||||
if (obj) {
|
||||
JS::ExposeObjectToActiveJS(obj);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JS::Rooted<JSObject*> rootedObj(cx, obj);
|
||||
nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsISupports> native =
|
||||
nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, rootedObj);
|
||||
NS_ASSERTION(native == targetSupp, "Native should be the target!");
|
||||
obj = rootedObj;
|
||||
#endif
|
||||
|
||||
*aRet = obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSContext::BindCompiledEventHandler(nsISupports* aTarget,
|
||||
JS::Handle<JSObject*> aScope,
|
||||
JS::Handle<JSObject*> aHandler,
|
||||
JS::MutableHandle<JSObject*> aBoundHandler)
|
||||
{
|
||||
NS_ENSURE_ARG(aHandler);
|
||||
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_PRECONDITION(!aBoundHandler, "Shouldn't already have a bound handler!");
|
||||
|
||||
if (aScope) {
|
||||
JS::ExposeObjectToActiveJS(aScope);
|
||||
}
|
||||
JS::ExposeObjectToActiveJS(aHandler);
|
||||
AutoPushJSContext cx(mContext);
|
||||
|
||||
// Get the jsobject associated with this target
|
||||
JS::Rooted<JSObject*> target(cx);
|
||||
JS::Rooted<JSObject*> scope(cx, aScope);
|
||||
nsresult rv = JSObjectFromInterface(aTarget, scope, target.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSAutoCompartment ac(cx, aHandler);
|
||||
JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*aHandler));
|
||||
NS_ASSERTION(JS_TypeOfValue(cx, val) == JSTYPE_FUNCTION,
|
||||
"Event handler object not a function");
|
||||
}
|
||||
#endif
|
||||
|
||||
JSAutoCompartment ac(cx, target);
|
||||
|
||||
JSObject* funobj;
|
||||
// Make sure the handler function is parented by its event target object
|
||||
if (aHandler) {
|
||||
funobj = JS_CloneFunctionObject(cx, aHandler, target);
|
||||
if (!funobj) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
funobj = nullptr;
|
||||
}
|
||||
|
||||
aBoundHandler.set(funobj);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject *
|
||||
nsJSContext::GetGlobalObject()
|
||||
{
|
||||
|
|
|
@ -44,11 +44,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext,
|
||||
nsIScriptContext)
|
||||
|
||||
virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
|
||||
JS::Handle<JSObject*> aScope,
|
||||
JS::Handle<JSObject*> aHandler,
|
||||
JS::MutableHandle<JSObject*> aBoundHandler) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsIScriptGlobalObject *GetGlobalObject() MOZ_OVERRIDE;
|
||||
inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
|
||||
|
||||
|
@ -145,12 +140,6 @@ protected:
|
|||
|
||||
nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv);
|
||||
|
||||
// given an nsISupports object (presumably an event target or some other
|
||||
// DOM object), get (or create) the JSObject wrapping it.
|
||||
nsresult JSObjectFromInterface(nsISupports *aSup,
|
||||
JS::Handle<JSObject*> aScript,
|
||||
JSObject **aRet);
|
||||
|
||||
// Report the pending exception on our mContext, if any. This
|
||||
// function will set aside the frame chain on mContext before
|
||||
// reporting.
|
||||
|
@ -168,8 +157,6 @@ private:
|
|||
bool mGCOnDestruction;
|
||||
bool mProcessingScriptTag;
|
||||
|
||||
PRTime mOperationCallbackTime;
|
||||
|
||||
PRTime mModalStateTime;
|
||||
uint32_t mModalStateDepth;
|
||||
|
||||
|
|
|
@ -260,7 +260,15 @@ class IDLScope(IDLObject):
|
|||
isinstance(newObject, IDLExternalInterface) and \
|
||||
originalObject.identifier.name == newObject.identifier.name:
|
||||
return originalObject
|
||||
|
||||
|
||||
if (isinstance(originalObject, IDLExternalInterface) or
|
||||
isinstance(newObject, IDLExternalInterface)):
|
||||
raise WebIDLError(
|
||||
"Name collision between "
|
||||
"interface declarations for identifier '%s' at '%s' and '%s'"
|
||||
% (identifier.name,
|
||||
originalObject.location, newObject.location), [])
|
||||
|
||||
# We do the merging of overloads here as opposed to in IDLInterface
|
||||
# because we need to merge overloads of NamedConstructors and we need to
|
||||
# detect conflicts in those across interfaces. See also the comment in
|
||||
|
|
|
@ -597,14 +597,11 @@ EventListenerManager::FindEventHandler(uint32_t aEventType,
|
|||
|
||||
EventListenerManager::Listener*
|
||||
EventListenerManager::SetEventHandlerInternal(
|
||||
JS::Handle<JSObject*> aScopeObject,
|
||||
nsIAtom* aName,
|
||||
const nsAString& aTypeString,
|
||||
const nsEventHandler& aHandler,
|
||||
bool aPermitUntrustedEvents)
|
||||
{
|
||||
MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
|
||||
"Must have one or the other!");
|
||||
MOZ_ASSERT(aName || !aTypeString.IsEmpty());
|
||||
|
||||
uint32_t eventType = nsContentUtils::GetEventId(aName);
|
||||
|
@ -617,7 +614,7 @@ EventListenerManager::SetEventHandlerInternal(
|
|||
flags.mListenerIsJSListener = true;
|
||||
|
||||
nsCOMPtr<nsIJSEventListener> jsListener;
|
||||
NS_NewJSEventListener(aScopeObject, mTarget, aName,
|
||||
NS_NewJSEventListener(mTarget, aName,
|
||||
aHandler, getter_AddRefs(jsListener));
|
||||
EventListenerHolder listenerHolder(jsListener);
|
||||
AddEventListenerInternal(listenerHolder, eventType, aName, aTypeString,
|
||||
|
@ -631,7 +628,7 @@ EventListenerManager::SetEventHandlerInternal(
|
|||
|
||||
bool same = jsListener->GetHandler() == aHandler;
|
||||
// Possibly the same listener, but update still the context and scope.
|
||||
jsListener->SetHandler(aHandler, aScopeObject);
|
||||
jsListener->SetHandler(aHandler);
|
||||
if (mTarget && !same && aName) {
|
||||
mTarget->EventListenerRemoved(aName);
|
||||
mTarget->EventListenerAdded(aName);
|
||||
|
@ -746,14 +743,9 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
|
|||
|
||||
nsIScriptContext* context = global->GetScriptContext();
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
||||
|
||||
NS_ENSURE_STATE(global->GetGlobalJSObject());
|
||||
|
||||
JSAutoRequest ar(context->GetNativeContext());
|
||||
JS::Rooted<JSObject*> scope(context->GetNativeContext(),
|
||||
global->GetGlobalJSObject());
|
||||
|
||||
Listener* listener = SetEventHandlerInternal(scope, aName,
|
||||
Listener* listener = SetEventHandlerInternal(aName,
|
||||
EmptyString(),
|
||||
nsEventHandler(),
|
||||
aPermitUntrustedEvents);
|
||||
|
@ -791,17 +783,12 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
|
|||
const nsAString* aBody,
|
||||
Element* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aListener->GetJSListener(),
|
||||
"Why do we not have a JS listener?");
|
||||
NS_PRECONDITION(aListener->mHandlerIsString,
|
||||
"Why are we compiling a non-string JS listener?");
|
||||
MOZ_ASSERT(aListener->GetJSListener());
|
||||
MOZ_ASSERT(aListener->mHandlerIsString, "Why are we compiling a non-string JS listener?");
|
||||
nsIJSEventListener* jsListener = aListener->GetJSListener();
|
||||
MOZ_ASSERT(!jsListener->GetHandler().HasEventHandler(), "What is there to compile?");
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
nsIJSEventListener* jsListener = aListener->GetJSListener();
|
||||
NS_ASSERTION(!jsListener->GetHandler().HasEventHandler(),
|
||||
"What is there to compile?");
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIScriptGlobalObject> global =
|
||||
GetScriptGlobalAndDocument(getter_AddRefs(doc));
|
||||
|
@ -812,132 +799,127 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
|
|||
|
||||
// Push a context to make sure exceptions are reported in the right place.
|
||||
AutoPushJSContextForErrorReporting cx(context->GetNativeContext());
|
||||
JS::Rooted<JSObject*> handler(cx);
|
||||
|
||||
JS::Rooted<JSObject*> scope(cx, jsListener->GetEventScope());
|
||||
|
||||
nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
|
||||
nsIAtom* attrName = typeAtom;
|
||||
|
||||
if (aListener->mHandlerIsString) {
|
||||
// OK, we didn't find an existing compiled event handler. Flag us
|
||||
// as not a string so we don't keep trying to compile strings
|
||||
// which can't be compiled
|
||||
aListener->mHandlerIsString = false;
|
||||
// Flag us as not a string so we don't keep trying to compile strings which
|
||||
// can't be compiled.
|
||||
aListener->mHandlerIsString = false;
|
||||
|
||||
// mTarget may not be an Element if it's a window and we're
|
||||
// getting an inline event listener forwarded from <html:body> or
|
||||
// <html:frameset> or <xul:window> or the like.
|
||||
// XXX I don't like that we have to reference content from
|
||||
// here. The alternative is to store the event handler string on
|
||||
// the nsIJSEventListener itself, and that still doesn't address
|
||||
// the arg names issue.
|
||||
nsCOMPtr<Element> element = do_QueryInterface(mTarget);
|
||||
MOZ_ASSERT(element || aBody, "Where will we get our body?");
|
||||
nsAutoString handlerBody;
|
||||
const nsAString* body = aBody;
|
||||
if (!aBody) {
|
||||
if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) {
|
||||
attrName = nsGkAtoms::onload;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) {
|
||||
attrName = nsGkAtoms::onunload;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) {
|
||||
attrName = nsGkAtoms::onresize;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) {
|
||||
attrName = nsGkAtoms::onscroll;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) {
|
||||
attrName = nsGkAtoms::onzoom;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) {
|
||||
attrName = nsGkAtoms::onbegin;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) {
|
||||
attrName = nsGkAtoms::onrepeat;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) {
|
||||
attrName = nsGkAtoms::onend;
|
||||
}
|
||||
|
||||
element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
body = &handlerBody;
|
||||
aElement = element;
|
||||
}
|
||||
aListener = nullptr;
|
||||
|
||||
uint32_t lineNo = 0;
|
||||
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
|
||||
MOZ_ASSERT(body);
|
||||
MOZ_ASSERT(aElement);
|
||||
nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
|
||||
if (uri) {
|
||||
uri->GetSpec(url);
|
||||
lineNo = 1;
|
||||
// mTarget may not be an Element if it's a window and we're
|
||||
// getting an inline event listener forwarded from <html:body> or
|
||||
// <html:frameset> or <xul:window> or the like.
|
||||
// XXX I don't like that we have to reference content from
|
||||
// here. The alternative is to store the event handler string on
|
||||
// the nsIJSEventListener itself, and that still doesn't address
|
||||
// the arg names issue.
|
||||
nsCOMPtr<Element> element = do_QueryInterface(mTarget);
|
||||
MOZ_ASSERT(element || aBody, "Where will we get our body?");
|
||||
nsAutoString handlerBody;
|
||||
const nsAString* body = aBody;
|
||||
if (!aBody) {
|
||||
if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) {
|
||||
attrName = nsGkAtoms::onload;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) {
|
||||
attrName = nsGkAtoms::onunload;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) {
|
||||
attrName = nsGkAtoms::onresize;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) {
|
||||
attrName = nsGkAtoms::onscroll;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) {
|
||||
attrName = nsGkAtoms::onzoom;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) {
|
||||
attrName = nsGkAtoms::onbegin;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) {
|
||||
attrName = nsGkAtoms::onrepeat;
|
||||
} else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) {
|
||||
attrName = nsGkAtoms::onend;
|
||||
}
|
||||
|
||||
uint32_t argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
|
||||
typeAtom,
|
||||
&argCount, &argNames);
|
||||
element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
body = &handlerBody;
|
||||
aElement = element;
|
||||
}
|
||||
aListener = nullptr;
|
||||
|
||||
JSAutoCompartment ac(cx, context->GetWindowProxy());
|
||||
JS::CompileOptions options(cx);
|
||||
options.setIntroductionType("eventHandler")
|
||||
.setFileAndLine(url.get(), lineNo)
|
||||
.setVersion(SCRIPTVERSION_DEFAULT);
|
||||
|
||||
JS::Rooted<JS::Value> targetVal(cx);
|
||||
// Go ahead and wrap into the current compartment of cx directly.
|
||||
JS::Rooted<JSObject*> wrapScope(cx, JS::CurrentGlobalOrNull(cx));
|
||||
if (WrapNewBindingObject(cx, wrapScope, aElement, &targetVal)) {
|
||||
MOZ_ASSERT(targetVal.isObject());
|
||||
|
||||
nsDependentAtomString str(attrName);
|
||||
// Most of our names are short enough that we don't even have to malloc
|
||||
// the JS string stuff, so don't worry about playing games with
|
||||
// refcounting XPCOM stringbuffers.
|
||||
JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
|
||||
str.BeginReading(),
|
||||
str.Length()));
|
||||
NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
options.setElement(&targetVal.toObject())
|
||||
.setElementAttributeName(jsStr);
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> handlerFun(cx);
|
||||
result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options,
|
||||
nsAtomCString(typeAtom),
|
||||
argCount, argNames, *body, handlerFun.address());
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
handler = handlerFun;
|
||||
NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
|
||||
} else {
|
||||
aListener = nullptr;
|
||||
uint32_t lineNo = 0;
|
||||
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
|
||||
MOZ_ASSERT(body);
|
||||
MOZ_ASSERT(aElement);
|
||||
nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
|
||||
if (uri) {
|
||||
uri->GetSpec(url);
|
||||
lineNo = 1;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
|
||||
// Bind it
|
||||
JS::Rooted<JSObject*> boundHandler(cx);
|
||||
context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
|
||||
// Note - We pass null for aIncumbentGlobal below. We could also pass the
|
||||
// compilation global, but since the handler is guaranteed to be scripted,
|
||||
// there's no need to use an override, since the JS engine will always give
|
||||
// us the right answer.
|
||||
if (!boundHandler) {
|
||||
jsListener->ForgetHandler();
|
||||
} else if (jsListener->EventName() == nsGkAtoms::onerror && win) {
|
||||
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
|
||||
new OnErrorEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
} else if (jsListener->EventName() == nsGkAtoms::onbeforeunload && win) {
|
||||
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
|
||||
new OnBeforeUnloadEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
} else {
|
||||
nsRefPtr<EventHandlerNonNull> handlerCallback =
|
||||
new EventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
uint32_t argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
|
||||
typeAtom,
|
||||
&argCount, &argNames);
|
||||
|
||||
// Wrap the event target, so that we can use it as the scope for the event
|
||||
// handler. Note that mTarget is different from aElement in the <body> case,
|
||||
// where mTarget is a Window.
|
||||
//
|
||||
// The wrapScope doesn't really matter here, because the target will create
|
||||
// its reflector in the proper scope, and then we'll enter that compartment.
|
||||
JS::Rooted<JSObject*> wrapScope(cx, context->GetWindowProxy());
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, wrapScope);
|
||||
nsresult rv = nsContentUtils::WrapNative(cx, wrapScope, mTarget, &v,
|
||||
/* aAllowWrapping = */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
JS::Rooted<JSObject*> target(cx, &v.toObject());
|
||||
JSAutoCompartment ac(cx, target);
|
||||
|
||||
nsDependentAtomString str(attrName);
|
||||
// Most of our names are short enough that we don't even have to malloc
|
||||
// the JS string stuff, so don't worry about playing games with
|
||||
// refcounting XPCOM stringbuffers.
|
||||
JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
|
||||
str.BeginReading(),
|
||||
str.Length()));
|
||||
NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Get the reflector for |aElement|, so that we can pass to setElement.
|
||||
if (NS_WARN_IF(!WrapNewBindingObject(cx, target, aElement, &v))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JS::CompileOptions options(cx);
|
||||
options.setIntroductionType("eventHandler")
|
||||
.setFileAndLine(url.get(), lineNo)
|
||||
.setVersion(SCRIPTVERSION_DEFAULT)
|
||||
.setElement(&v.toObject())
|
||||
.setElementAttributeName(jsStr)
|
||||
.setDefineOnScope(false);
|
||||
|
||||
JS::Rooted<JSObject*> handler(cx);
|
||||
result = nsJSUtils::CompileFunction(cx, target, options,
|
||||
nsAtomCString(typeAtom),
|
||||
argCount, argNames, *body, handler.address());
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
|
||||
if (jsListener->EventName() == nsGkAtoms::onerror && win) {
|
||||
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
|
||||
new OnErrorEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
} else if (jsListener->EventName() == nsGkAtoms::onbeforeunload && win) {
|
||||
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
|
||||
new OnBeforeUnloadEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
} else {
|
||||
nsRefPtr<EventHandlerNonNull> handlerCallback =
|
||||
new EventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
|
||||
jsListener->SetHandler(handlerCallback);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1240,8 +1222,7 @@ EventListenerManager::SetEventHandler(nsIAtom* aEventName,
|
|||
|
||||
// Untrusted events are always permitted for non-chrome script
|
||||
// handlers.
|
||||
SetEventHandlerInternal(JS::NullPtr(), aEventName,
|
||||
aTypeString, nsEventHandler(aHandler),
|
||||
SetEventHandlerInternal(aEventName, aTypeString, nsEventHandler(aHandler),
|
||||
!mIsMainThreadELM ||
|
||||
!nsContentUtils::IsCallerChrome());
|
||||
}
|
||||
|
@ -1257,8 +1238,8 @@ EventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
|
|||
|
||||
// Untrusted events are always permitted for non-chrome script
|
||||
// handlers.
|
||||
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onerror,
|
||||
EmptyString(), nsEventHandler(aHandler),
|
||||
SetEventHandlerInternal(nsGkAtoms::onerror, EmptyString(),
|
||||
nsEventHandler(aHandler),
|
||||
!nsContentUtils::IsCallerChrome());
|
||||
} else {
|
||||
if (!aHandler) {
|
||||
|
@ -1267,8 +1248,7 @@ EventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
|
|||
}
|
||||
|
||||
// Untrusted events are always permitted.
|
||||
SetEventHandlerInternal(JS::NullPtr(), nullptr,
|
||||
NS_LITERAL_STRING("error"),
|
||||
SetEventHandlerInternal(nullptr, NS_LITERAL_STRING("error"),
|
||||
nsEventHandler(aHandler), true);
|
||||
}
|
||||
}
|
||||
|
@ -1284,8 +1264,8 @@ EventListenerManager::SetEventHandler(
|
|||
|
||||
// Untrusted events are always permitted for non-chrome script
|
||||
// handlers.
|
||||
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onbeforeunload,
|
||||
EmptyString(), nsEventHandler(aHandler),
|
||||
SetEventHandlerInternal(nsGkAtoms::onbeforeunload, EmptyString(),
|
||||
nsEventHandler(aHandler),
|
||||
!mIsMainThreadELM ||
|
||||
!nsContentUtils::IsCallerChrome());
|
||||
}
|
||||
|
@ -1341,9 +1321,6 @@ EventListenerManager::MarkForCC()
|
|||
if (jsListener->GetHandler().HasEventHandler()) {
|
||||
JS::ExposeObjectToActiveJS(jsListener->GetHandler().Ptr()->Callable());
|
||||
}
|
||||
if (JSObject* scope = jsListener->GetEventScope()) {
|
||||
JS::ExposeObjectToActiveJS(scope);
|
||||
}
|
||||
} else if (listener.mListenerType == Listener::eWrappedJSListener) {
|
||||
xpc_TryUnmarkWrappedGrayObject(listener.mListener.GetXPCOMCallback());
|
||||
} else if (listener.mListenerType == Listener::eWebIDLListener) {
|
||||
|
|
|
@ -447,8 +447,7 @@ protected:
|
|||
* aScopeGlobal must be non-null. Otherwise, aContext and aScopeGlobal are
|
||||
* allowed to be null.
|
||||
*/
|
||||
Listener* SetEventHandlerInternal(JS::Handle<JSObject*> aScopeGlobal,
|
||||
nsIAtom* aName,
|
||||
Listener* SetEventHandlerInternal(nsIAtom* aName,
|
||||
const nsAString& aTypeString,
|
||||
const nsEventHandler& aHandler,
|
||||
bool aPermitUntrustedEvents);
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
#include "mozilla/dom/EventHandlerBinding.h"
|
||||
|
||||
#define NS_IJSEVENTLISTENER_IID \
|
||||
{ 0x5077b12a, 0x5a1f, 0x4583, \
|
||||
{ 0xbb, 0xa7, 0x78, 0x84, 0x94, 0x0e, 0x5e, 0xff } }
|
||||
{ 0x8f06b4af, 0xbd0d, 0x486b, \
|
||||
{ 0x81, 0xc8, 0x20, 0x42, 0x40, 0x2b, 0xf1, 0xef } }
|
||||
|
||||
class nsEventHandler
|
||||
{
|
||||
|
@ -172,10 +172,9 @@ class nsIJSEventListener : public nsIDOMEventListener
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
|
||||
|
||||
nsIJSEventListener(JSObject* aScopeObject,
|
||||
nsISupports *aTarget, nsIAtom* aType,
|
||||
nsIJSEventListener(nsISupports *aTarget, nsIAtom* aType,
|
||||
const nsEventHandler& aHandler)
|
||||
: mScopeObject(aScopeObject), mEventName(aType), mHandler(aHandler)
|
||||
: mEventName(aType), mHandler(aHandler)
|
||||
{
|
||||
nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
|
||||
mTarget = base.get();
|
||||
|
@ -191,17 +190,6 @@ public:
|
|||
mTarget = nullptr;
|
||||
}
|
||||
|
||||
// Can return null if we already have a handler.
|
||||
JSObject* GetEventScope() const
|
||||
{
|
||||
if (!mScopeObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::ExposeObjectToActiveJS(mScopeObject);
|
||||
return mScopeObject;
|
||||
}
|
||||
|
||||
const nsEventHandler& GetHandler() const
|
||||
{
|
||||
return mHandler;
|
||||
|
@ -219,11 +207,9 @@ public:
|
|||
|
||||
// Set a handler for this event listener. The handler must already
|
||||
// be bound to the right target.
|
||||
void SetHandler(const nsEventHandler& aHandler,
|
||||
JS::Handle<JSObject*> aScopeObject)
|
||||
void SetHandler(const nsEventHandler& aHandler)
|
||||
{
|
||||
mHandler.SetHandler(aHandler);
|
||||
UpdateScopeObject(aScopeObject);
|
||||
}
|
||||
void SetHandler(mozilla::dom::EventHandlerNonNull* aHandler)
|
||||
{
|
||||
|
@ -247,8 +233,6 @@ public:
|
|||
// - mTarget
|
||||
//
|
||||
// The following members are not measured:
|
||||
// - mScopeObject: because they're measured by the JS memory
|
||||
// reporters
|
||||
// - mHandler: may be shared with others
|
||||
// - mEventName: shared with others
|
||||
}
|
||||
|
@ -264,11 +248,6 @@ protected:
|
|||
NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
|
||||
}
|
||||
|
||||
// Update our mScopeObject; we have to make sure we properly handle
|
||||
// the hold/drop stuff, so have to do it in nsJSEventListener.
|
||||
virtual void UpdateScopeObject(JS::Handle<JSObject*> aScopeObject) = 0;
|
||||
|
||||
JS::Heap<JSObject*> mScopeObject;
|
||||
nsISupports* mTarget;
|
||||
nsCOMPtr<nsIAtom> mEventName;
|
||||
nsEventHandler mHandler;
|
||||
|
@ -279,8 +258,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
|
|||
/* factory function. aHandler must already be bound to aTarget.
|
||||
aContext is allowed to be null if aHandler is already set up.
|
||||
*/
|
||||
nsresult NS_NewJSEventListener(JSObject* aScopeObject, nsISupports* aTarget,
|
||||
nsIAtom* aType, const nsEventHandler& aHandler,
|
||||
nsresult NS_NewJSEventListener(nsISupports* aTarget, nsIAtom* aType,
|
||||
const nsEventHandler& aHandler,
|
||||
nsIJSEventListener **aReturn);
|
||||
|
||||
#endif // nsIJSEventListener_h__
|
||||
|
|
|
@ -43,45 +43,16 @@ using namespace mozilla::dom;
|
|||
/*
|
||||
* nsJSEventListener implementation
|
||||
*/
|
||||
nsJSEventListener::nsJSEventListener(JSObject* aScopeObject,
|
||||
nsISupports *aTarget,
|
||||
nsJSEventListener::nsJSEventListener(nsISupports *aTarget,
|
||||
nsIAtom* aType,
|
||||
const nsEventHandler& aHandler)
|
||||
: nsIJSEventListener(aScopeObject, aTarget, aType, aHandler)
|
||||
: nsIJSEventListener(aTarget, aType, aHandler)
|
||||
{
|
||||
if (mScopeObject) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsJSEventListener::~nsJSEventListener()
|
||||
{
|
||||
if (mScopeObject) {
|
||||
mScopeObject = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void
|
||||
nsJSEventListener::UpdateScopeObject(JS::Handle<JSObject*> aScopeObject)
|
||||
{
|
||||
if (mScopeObject && !aScopeObject) {
|
||||
mScopeObject = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
} else if (aScopeObject && !mScopeObject) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
mScopeObject = aScopeObject;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
|
||||
if (tmp->mScopeObject) {
|
||||
tmp->mScopeObject = nullptr;
|
||||
mozilla::DropJSObjects(tmp);
|
||||
}
|
||||
tmp->mHandler.ForgetHandler();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
|
||||
|
@ -98,10 +69,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScopeObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsJSEventListener)
|
||||
if (tmp->IsBlackForCC()) {
|
||||
return true;
|
||||
|
@ -143,12 +110,7 @@ nsJSEventListener::IsBlackForCC()
|
|||
{
|
||||
// We can claim to be black if all the things we reference are
|
||||
// effectively black already.
|
||||
if ((!mScopeObject || !xpc_IsGrayGCThing(mScopeObject)) &&
|
||||
(!mHandler.HasEventHandler() ||
|
||||
!mHandler.Ptr()->HasGrayCallable())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !mHandler.HasEventHandler() || !mHandler.Ptr()->HasGrayCallable();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -274,14 +236,13 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
*/
|
||||
|
||||
nsresult
|
||||
NS_NewJSEventListener(JSObject* aScopeObject,
|
||||
nsISupports*aTarget, nsIAtom* aEventType,
|
||||
NS_NewJSEventListener(nsISupports*aTarget, nsIAtom* aEventType,
|
||||
const nsEventHandler& aHandler,
|
||||
nsIJSEventListener** aReturn)
|
||||
{
|
||||
NS_ENSURE_ARG(aEventType || !NS_IsMainThread());
|
||||
nsJSEventListener* it =
|
||||
new nsJSEventListener(aScopeObject, aTarget, aEventType, aHandler);
|
||||
new nsJSEventListener(aTarget, aEventType, aHandler);
|
||||
NS_ADDREF(*aReturn = it);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
class nsJSEventListener : public nsIJSEventListener
|
||||
{
|
||||
public:
|
||||
nsJSEventListener(JSObject* aScopeObject, nsISupports* aTarget,
|
||||
nsIAtom* aType, const nsEventHandler& aHandler);
|
||||
virtual ~nsJSEventListener();
|
||||
nsJSEventListener(nsISupports* aTarget, nsIAtom* aType,
|
||||
const nsEventHandler& aHandler);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
|
@ -37,10 +36,7 @@ public:
|
|||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsJSEventListener)
|
||||
|
||||
protected:
|
||||
virtual void UpdateScopeObject(JS::Handle<JSObject*> aScopeObject);
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(nsJSEventListener)
|
||||
|
||||
bool IsBlackForCC();
|
||||
};
|
||||
|
|
|
@ -1,14 +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/.
|
||||
|
||||
SUPPORT_FILES = \
|
||||
testharness.js \
|
||||
testharnessreport.js \
|
||||
testharness.css \
|
||||
idlharness.js \
|
||||
WebIDLParser.js \
|
||||
$(NULL)
|
||||
|
||||
SUPPORT_DEST = $(DEPTH)/_tests/testing/mochitest/resources
|
||||
INSTALL_TARGETS += SUPPORT
|
|
@ -0,0 +1,7 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
/resources/testharness.js
|
||||
/resources/testharnessreport.js
|
||||
/resources/testharness.css
|
||||
/resources/idlharness.js
|
||||
/resources/WebIDLParser.js
|
|
@ -7,6 +7,7 @@
|
|||
MOCHITEST_MANIFESTS += [
|
||||
'editing/mochitest.ini',
|
||||
'html/mochitest.ini',
|
||||
'mochitest.ini',
|
||||
'webapps/mochitest.ini',
|
||||
]
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMPermissionSettings.idl',
|
||||
'nsIPermissionPromptService.idl',
|
||||
]
|
||||
|
||||
|
|
|
@ -1,21 +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 "domstubs.idl"
|
||||
|
||||
interface nsIDOMDOMRequest;
|
||||
|
||||
[scriptable, uuid(18390770-02ab-11e2-a21f-0800200c9a66)]
|
||||
interface nsIDOMPermissionSettings : nsISupports
|
||||
{
|
||||
DOMString get(in DOMString permission, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
|
||||
|
||||
void set(in DOMString permission, in DOMString value, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
|
||||
|
||||
bool isExplicit(in DOMString permission, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
|
||||
|
||||
// Removing a permission is only allowed for pages with a different origin than the app
|
||||
// and pages that have browserFlag=true, so remove() doesn't have a browserFlag parameter.
|
||||
void remove(in DOMString permission, in DOMString manifestURI, in DOMString origin);
|
||||
};
|
|
@ -14,7 +14,7 @@ interface nsIPermissionPromptService : nsISupports
|
|||
{
|
||||
/**
|
||||
* Checks if the capability requires a permission, fires the corresponding cancel()
|
||||
* or allow() method in aRequest after consulting nsIDOMPermissionSettings, etc.
|
||||
* or allow() method in aRequest after consulting PermissionSettings, etc.
|
||||
*/
|
||||
void getPermission(in nsIContentPermissionRequest aRequest);
|
||||
};
|
||||
|
|
|
@ -628,7 +628,7 @@ TabChild::HandlePossibleViewportChange()
|
|||
defaultZoom <= viewportInfo.GetMaxZoom());
|
||||
metrics.SetZoom(defaultZoom);
|
||||
|
||||
metrics.mScrollId = viewId;
|
||||
metrics.SetScrollId(viewId);
|
||||
}
|
||||
|
||||
metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
|
||||
|
@ -1472,7 +1472,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
|
|||
bool
|
||||
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
MOZ_ASSERT(aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID);
|
||||
MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
|
||||
|
||||
if (aFrameMetrics.mIsRoot) {
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
|
@ -1485,7 +1485,7 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
|||
// aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
|
||||
// This requires special handling.
|
||||
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
|
||||
aFrameMetrics.mScrollId);
|
||||
aFrameMetrics.GetScrollId());
|
||||
if (content) {
|
||||
FrameMetrics newSubFrameMetrics(aFrameMetrics);
|
||||
APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
|
||||
|
|
|
@ -26,11 +26,6 @@ const PERMISSIONPROMPTSERVICE_CONTRACTID = "@mozilla.org/permission-prompt-servi
|
|||
const PERMISSIONPROMPTSERVICE_CID = Components.ID("{e5f953b3-a6ca-444e-a88d-cdc81383741c}");
|
||||
const permissionPromptService = Ci.nsIPermissionPromptService;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"PermSettings",
|
||||
"@mozilla.org/permissionSettings;1",
|
||||
"nsIDOMPermissionSettings");
|
||||
|
||||
var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
|
||||
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ var cpm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncM
|
|||
|
||||
const PERMISSIONSETTINGS_CONTRACTID = "@mozilla.org/permissionSettings;1";
|
||||
const PERMISSIONSETTINGS_CID = Components.ID("{cd2cf7a1-f4c1-487b-8c1b-1a71c7097431}");
|
||||
const nsIDOMPermissionSettings = Ci.nsIDOMPermissionSettings;
|
||||
|
||||
function PermissionSettings()
|
||||
{
|
||||
|
@ -129,27 +128,8 @@ PermissionSettings.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
init: function init(aWindow) {
|
||||
debug("init");
|
||||
|
||||
// Set navigator.mozPermissionSettings to null.
|
||||
let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "permissions");
|
||||
if (!Services.prefs.getBoolPref("dom.mozPermissionSettings.enabled")
|
||||
|| perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
return null;
|
||||
}
|
||||
|
||||
debug("Permission to get/set permissions granted!");
|
||||
},
|
||||
|
||||
classID : PERMISSIONSETTINGS_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMPermissionSettings, Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: PERMISSIONSETTINGS_CID,
|
||||
contractID: PERMISSIONSETTINGS_CONTRACTID,
|
||||
classDescription: "PermissionSettings",
|
||||
interfaces: [nsIDOMPermissionSettings],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT})
|
||||
QueryInterface : XPCOMUtils.generateQI([])
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PermissionSettings])
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
component {cd2cf7a1-f4c1-487b-8c1b-1a71c7097431} PermissionSettings.js
|
||||
contract @mozilla.org/permissionSettings;1 {cd2cf7a1-f4c1-487b-8c1b-1a71c7097431}
|
||||
category JavaScript-navigator-property mozPermissionSettings @mozilla.org/permissionSettings;1
|
||||
|
|
|
@ -20,7 +20,7 @@ var gData = [
|
|||
{
|
||||
perm: ["permissions"],
|
||||
obj: "mozPermissionSettings",
|
||||
idl: "nsIDOMPermissionSettings",
|
||||
webidl: "PermissionSettings",
|
||||
settings: [["dom.mozPermissionSettings.enabled", true]],
|
||||
},
|
||||
]
|
||||
|
|
|
@ -181,13 +181,7 @@ SettingsServiceLock.prototype = {
|
|||
},
|
||||
|
||||
classID : SETTINGSSERVICELOCK_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({ classID: SETTINGSSERVICELOCK_CID,
|
||||
contractID: SETTINGSSERVICELOCK_CONTRACTID,
|
||||
classDescription: "SettingsServiceLock",
|
||||
interfaces: [nsISettingsServiceLock],
|
||||
flags: nsIClassInfo.DOM_OBJECT })
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
|
||||
};
|
||||
|
||||
const SETTINGSSERVICE_CID = Components.ID("{f656f0c0-f776-11e1-a21f-0800200c9a66}");
|
||||
|
@ -221,13 +215,7 @@ SettingsService.prototype = {
|
|||
},
|
||||
|
||||
classID : SETTINGSSERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService]),
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: SETTINGSSERVICE_CID,
|
||||
contractID: "@mozilla.org/settingsService;1",
|
||||
interfaces: [Ci.nsISettingsService],
|
||||
flags: nsIClassInfo.DOM_OBJECT
|
||||
})
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
|
||||
|
|
|
@ -28,7 +28,7 @@ LOCAL_INCLUDES += [
|
|||
|
||||
if CONFIG['MOZ_ENABLE_QT5GEOPOSITION']:
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/system/unix',
|
||||
'/dom/system/qt',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
|
|
|
@ -684,7 +684,7 @@ nsresult nsGeolocationService::Init()
|
|||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
mProvider = do_GetService(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID);
|
||||
mProvider = do_CreateInstance(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
|
@ -694,7 +694,7 @@ nsresult nsGeolocationService::Init()
|
|||
#endif
|
||||
|
||||
if (Preferences::GetBool("geo.provider.use_mls", false)) {
|
||||
mProvider = do_GetService("@mozilla.org/geolocation/mls-provider;1");
|
||||
mProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
|
||||
}
|
||||
|
||||
// Override platform-specific providers with the default (network)
|
||||
|
|
|
@ -87,6 +87,8 @@ WifiGeoPositionProvider.prototype = {
|
|||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider,
|
||||
Ci.nsIWifiListener,
|
||||
Ci.nsITimerCallback]),
|
||||
listener: null,
|
||||
|
||||
startup: function() {
|
||||
if (this.started)
|
||||
return;
|
||||
|
@ -104,6 +106,7 @@ WifiGeoPositionProvider.prototype = {
|
|||
},
|
||||
|
||||
watch: function(c) {
|
||||
this.listener = c;
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
|
@ -121,6 +124,7 @@ WifiGeoPositionProvider.prototype = {
|
|||
this.wifiService.stopWatching(this);
|
||||
this.wifiService = null;
|
||||
}
|
||||
this.listener = null;
|
||||
this.started = false;
|
||||
},
|
||||
|
||||
|
@ -186,17 +190,18 @@ WifiGeoPositionProvider.prototype = {
|
|||
|
||||
notify: function (timeoutTimer) {
|
||||
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
|
||||
let listener = this.listener;
|
||||
LOG("Sending request: " + url + "\n");
|
||||
|
||||
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
getGeoService().locationUpdatePending();
|
||||
listener.locationUpdatePending();
|
||||
|
||||
try {
|
||||
xhr.open("POST", url, true);
|
||||
} catch (e) {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
listener.notifyError(POSITION_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
|
@ -204,13 +209,13 @@ WifiGeoPositionProvider.prototype = {
|
|||
xhr.mozBackgroundRequest = true;
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
xhr.onerror = function() {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
listener.notifyError(POSITION_UNAVAILABLE);
|
||||
};
|
||||
xhr.onload = function() {
|
||||
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
|
||||
if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
|
||||
!xhr.response || !xhr.response.location) {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
listener.notifyError(POSITION_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -218,7 +223,7 @@ WifiGeoPositionProvider.prototype = {
|
|||
xhr.response.location.lng,
|
||||
xhr.response.accuracy);
|
||||
|
||||
getGeoService().update(newLocation);
|
||||
listener.update(newLocation);
|
||||
};
|
||||
|
||||
if (gCellScanningEnabled) {
|
||||
|
@ -239,8 +244,4 @@ WifiGeoPositionProvider.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
function getGeoService() {
|
||||
return Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate);
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "prtime.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIDOMIccInfo.h"
|
||||
|
@ -98,6 +99,7 @@ GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
|
|||
NS_IMETHOD Run() {
|
||||
nsRefPtr<GonkGPSGeolocationProvider> provider =
|
||||
GonkGPSGeolocationProvider::GetSingleton();
|
||||
provider->mLastGPSDerivedLocationTime = PR_Now();
|
||||
nsCOMPtr<nsIGeolocationUpdate> callback = provider->mLocationCallback;
|
||||
if (callback) {
|
||||
callback->Update(mPosition);
|
||||
|
@ -285,8 +287,8 @@ GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
|
|||
: mStarted(false)
|
||||
, mSupportsScheduling(false)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
, mSupportsMSB(false)
|
||||
, mSupportsMSA(false)
|
||||
, mSupportsMSB(false)
|
||||
, mSupportsMSA(false)
|
||||
#endif
|
||||
, mSupportsSingleShot(false)
|
||||
, mSupportsTimeInjection(false)
|
||||
|
@ -523,8 +525,29 @@ GonkGPSGeolocationProvider::SetReferenceLocation()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
void
|
||||
GonkGPSGeolocationProvider::InjectLocation(double latitude,
|
||||
double longitude,
|
||||
float accuracy)
|
||||
{
|
||||
#ifdef DEBUG_GPS
|
||||
printf_stderr("*** injecting location\n");
|
||||
printf_stderr("*** lat: %f\n", latitude);
|
||||
printf_stderr("*** lon: %f\n", longitude);
|
||||
printf_stderr("*** accuracy: %f\n", accuracy);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mGpsInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGpsInterface->inject_location(latitude, longitude, accuracy);
|
||||
}
|
||||
|
||||
void
|
||||
GonkGPSGeolocationProvider::Init()
|
||||
{
|
||||
|
@ -626,6 +649,49 @@ GonkGPSGeolocationProvider::SetupAGPS()
|
|||
}
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider::NetworkLocationUpdate,
|
||||
nsIGeolocationUpdate)
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *position)
|
||||
{
|
||||
nsRefPtr<GonkGPSGeolocationProvider> provider =
|
||||
GonkGPSGeolocationProvider::GetSingleton();
|
||||
|
||||
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
|
||||
position->GetCoords(getter_AddRefs(coords));
|
||||
if (!coords) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// if we haven't seen anything from the GPS device for 1s,
|
||||
// use this network derived location.
|
||||
int64_t diff = PR_Now() - provider->mLastGPSDerivedLocationTime;
|
||||
if (provider->mLocationCallback && diff > kDefaultPeriod) {
|
||||
provider->mLocationCallback->Update(position);
|
||||
}
|
||||
|
||||
double lat, lon, acc;
|
||||
coords->GetLatitude(&lat);
|
||||
coords->GetLongitude(&lon);
|
||||
coords->GetAccuracy(&acc);
|
||||
provider->InjectLocation(lat, lon, acc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::NetworkLocationUpdate::LocationUpdatePending()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::NetworkLocationUpdate::NotifyError(uint16_t error)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Startup()
|
||||
{
|
||||
|
@ -643,6 +709,16 @@ GonkGPSGeolocationProvider::Startup()
|
|||
mInitThread->Dispatch(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::Init),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
mNetworkLocationProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
|
||||
if (mNetworkLocationProvider) {
|
||||
nsresult rv = mNetworkLocationProvider->Startup();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsRefPtr<NetworkLocationUpdate> update = new NetworkLocationUpdate();
|
||||
mNetworkLocationProvider->Watch(update);
|
||||
}
|
||||
}
|
||||
|
||||
mLastGPSDerivedLocationTime = 0;
|
||||
mStarted = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -665,6 +741,7 @@ GonkGPSGeolocationProvider::Shutdown()
|
|||
return NS_OK;
|
||||
}
|
||||
mStarted = false;
|
||||
mNetworkLocationProvider = nullptr;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (mRadioInterface) {
|
||||
|
|
|
@ -55,7 +55,7 @@ private:
|
|||
GonkGPSGeolocationProvider();
|
||||
GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
|
||||
GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
|
||||
~GonkGPSGeolocationProvider();
|
||||
virtual ~GonkGPSGeolocationProvider();
|
||||
|
||||
static void LocationCallback(GpsLocation* location);
|
||||
static void StatusCallback(GpsStatus* status);
|
||||
|
@ -81,6 +81,7 @@ private:
|
|||
void Init();
|
||||
void StartGPS();
|
||||
void ShutdownGPS();
|
||||
void InjectLocation(double latitude, double longitude, float accuracy);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void SetupAGPS();
|
||||
int32_t GetDataConnectionState();
|
||||
|
@ -113,7 +114,21 @@ private:
|
|||
nsCOMPtr<nsIRadioInterface> mRadioInterface;
|
||||
#endif
|
||||
nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
|
||||
PRTime mLastGPSDerivedLocationTime;
|
||||
nsCOMPtr<nsIThread> mInitThread;
|
||||
nsCOMPtr<nsIGeolocationProvider> mNetworkLocationProvider;
|
||||
|
||||
class NetworkLocationUpdate : public nsIGeolocationUpdate
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGEOLOCATIONUPDATE
|
||||
|
||||
NetworkLocationUpdate() {}
|
||||
|
||||
private:
|
||||
virtual ~NetworkLocationUpdate() {}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* GonkGPSGeolocationProvider_h */
|
||||
|
|
|
@ -743,6 +743,8 @@ var interfaceNamesInGlobalScope =
|
|||
"PerformanceTiming",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"PeriodicWave",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "PermissionSettings", b2g: true, permission: "permissions"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"PhoneNumberService",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* 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/. */
|
||||
|
||||
[Pref="dom.sysmsg.enabled",
|
||||
JSImplementation="@mozilla.org/dom/activities/request-handler;1",
|
||||
ChromeConstructor(DOMString id, optional ActivityOptions options),
|
||||
ChromeOnly]
|
||||
interface ActivityRequestHandler
|
||||
{
|
||||
void postResult(any result);
|
||||
void postError(DOMString error);
|
||||
[Pure, Cached, Frozen]
|
||||
readonly attribute ActivityOptions source;
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/* 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 at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
[JSImplementation="@mozilla.org/permissionSettings;1",
|
||||
Func="Navigator::HasPermissionSettingsSupport",
|
||||
Pref="dom.mozPermissionSettings.enabled",
|
||||
NavigatorProperty="mozPermissionSettings"]
|
||||
interface PermissionSettings
|
||||
{
|
||||
DOMString get(DOMString permission, DOMString manifestURI, DOMString origin, boolean browserFlag);
|
||||
|
||||
void set(DOMString permission, DOMString value, DOMString manifestURI, DOMString origin, boolean browserFlag);
|
||||
|
||||
boolean isExplicit(DOMString permission, DOMString manifestURI, DOMString origin, boolean browserFlag);
|
||||
|
||||
// Removing a permission is only allowed for pages with a different origin than the app
|
||||
// and pages that have browserFlag=true, so remove() doesn't have a browserFlag parameter.
|
||||
void remove(DOMString permission, DOMString manifestURI, DOMString origin);
|
||||
};
|
|
@ -16,6 +16,7 @@ PREPROCESSED_WEBIDL_FILES = [
|
|||
|
||||
WEBIDL_FILES = [
|
||||
'AbstractWorker.webidl',
|
||||
'ActivityRequestHandler.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'AnimationEvent.webidl',
|
||||
'AppInfo.webidl',
|
||||
|
@ -270,6 +271,7 @@ WEBIDL_FILES = [
|
|||
'PerformanceNavigation.webidl',
|
||||
'PerformanceTiming.webidl',
|
||||
'PeriodicWave.webidl',
|
||||
'PermissionSettings.webidl',
|
||||
'PhoneNumberService.webidl',
|
||||
'Plugin.webidl',
|
||||
'PluginArray.webidl',
|
||||
|
@ -615,7 +617,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'BluetoothStatusChangedEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_BUILD_APP'] in ['browser', 'xulrunner']:
|
||||
if CONFIG['MOZ_BUILD_APP'] == 'browser':
|
||||
WEBIDL_FILES += [
|
||||
'BrowserFeedWriter.webidl',
|
||||
]
|
||||
|
|
|
@ -326,8 +326,7 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
|
|||
|
||||
// Execute it.
|
||||
nsCOMPtr<nsIJSEventListener> eventListener;
|
||||
rv = NS_NewJSEventListener(globalObject,
|
||||
scriptTarget, onEventAtom,
|
||||
rv = NS_NewJSEventListener(scriptTarget, onEventAtom,
|
||||
eventHandler,
|
||||
getter_AddRefs(eventListener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -1108,8 +1108,8 @@ FilterNodeTransformSoftware::Render(const IntRect& aRect)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Matrix transform = Matrix().Translate(srcRect.x, srcRect.y) * mMatrix *
|
||||
Matrix().Translate(-aRect.x, -aRect.y);
|
||||
Matrix transform = Matrix::Translation(srcRect.x, srcRect.y) * mMatrix *
|
||||
Matrix::Translation(-aRect.x, -aRect.y);
|
||||
if (transform.IsIdentity() && srcRect.Size() == aRect.Size()) {
|
||||
return input;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,15 @@
|
|||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static float CubicRoot(float aValue) {
|
||||
if (aValue < 0.0) {
|
||||
return -CubicRoot(-aValue);
|
||||
}
|
||||
else {
|
||||
return powf(aValue, 1.0f / 3.0f);
|
||||
}
|
||||
}
|
||||
|
||||
struct BezierControlPoints
|
||||
{
|
||||
BezierControlPoints() {}
|
||||
|
@ -269,8 +278,8 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
|||
|
||||
if (cp21.x == 0 && cp21.y == 0) {
|
||||
// In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
|
||||
*aMin = aT - pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));
|
||||
*aMax = aT + pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));;
|
||||
*aMin = aT - CubicRoot(double(aTolerance / (cp41.x - cp41.y)));
|
||||
*aMax = aT + CubicRoot(aTolerance / (cp41.x - cp41.y));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,7 +294,7 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
|||
return;
|
||||
}
|
||||
|
||||
Float tf = pow(abs(aTolerance / s3), Float(1. / 3.));
|
||||
Float tf = CubicRoot(abs(aTolerance / s3));
|
||||
|
||||
*aMin = aT - tf * (1 - aT);
|
||||
*aMax = aT + tf * (1 - aT);
|
||||
|
@ -445,7 +454,7 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
|||
&remainingCP, t1min);
|
||||
FlattenBezierCurveSegment(prevCPs, aSink, aTolerance);
|
||||
}
|
||||
if (t1max < 1.0 && (count == 1 || t2min > t1max)) {
|
||||
if (t1max >= 0 && t1max < 1.0 && (count == 1 || t2min > t1max)) {
|
||||
// The second inflection point's approximation range begins after the end
|
||||
// of the first, approximate the first inflection point by a line and
|
||||
// subsequently flatten up until the end or the next inflection point.
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
ifdef MOZ_ANGLE_RENDERER
|
||||
|
||||
libs::
|
||||
ifdef MOZ_HAS_WINSDK_WITH_D3D
|
||||
cp -fp "$(MOZ_D3DCOMPILER_DLL_PATH)" "$(DIST)/bin"
|
||||
else
|
||||
ifdef MOZ_D3DCOMPILER_CAB
|
||||
expand '$(MOZ_D3DCOMPILER_CAB)' -F:$(MOZ_D3DCOMPILER_DLL) '$(DIST)/bin'
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ endif
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef MOZ_HAS_WINSDK_WITH_D3D
|
||||
CXXFLAGS += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
|
||||
endif
|
||||
|
||||
#OS_LIBS += $(call EXPAND_LIBNAME,dwmapi)
|
||||
|
||||
|
@ -24,8 +26,12 @@ OS_LIBS += -ld3d9 -llibGLESv2
|
|||
|
||||
else
|
||||
|
||||
ifdef MOZ_HAS_WINSDK_WITH_D3D
|
||||
EXTRA_DSO_LDOPTS = d3d9.lib "$(DIST)/lib/libGLESv2.lib" delayimp.lib
|
||||
else
|
||||
EXTRA_DSO_LDOPTS = '$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib' \
|
||||
'$(DIST)/lib/libGLESv2.lib' \
|
||||
delayimp.lib
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -11,7 +11,9 @@ endif
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef MOZ_HAS_WINSDK_WITH_D3D
|
||||
CXXFLAGS += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
|
||||
endif
|
||||
|
||||
ifdef GNU_CC
|
||||
|
||||
|
@ -20,8 +22,12 @@ OS_LIBS += -ld3d9 -ldxguid
|
|||
|
||||
else
|
||||
|
||||
ifdef MOZ_HAS_WINSDK_WITH_D3D
|
||||
EXTRA_DSO_LDOPTS = d3d9.lib dxguid.lib delayimp.lib
|
||||
else
|
||||
EXTRA_DSO_LDOPTS = '$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/d3d9.lib' \
|
||||
'$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)/dxguid.lib' \
|
||||
delayimp.lib
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -71,7 +71,6 @@ public:
|
|||
, mDisplayPort(0, 0, 0, 0)
|
||||
, mCriticalDisplayPort(0, 0, 0, 0)
|
||||
, mViewport(0, 0, 0, 0)
|
||||
, mScrollId(NULL_SCROLL_ID)
|
||||
, mScrollableRect(0, 0, 0, 0)
|
||||
, mResolution(1)
|
||||
, mCumulativeResolution(1)
|
||||
|
@ -81,6 +80,7 @@ public:
|
|||
, mMayHaveTouchListeners(false)
|
||||
, mIsRoot(false)
|
||||
, mHasScrollgrab(false)
|
||||
, mScrollId(NULL_SCROLL_ID)
|
||||
, mScrollOffset(0, 0)
|
||||
, mZoom(1)
|
||||
, mUpdateScrollOffset(false)
|
||||
|
@ -97,7 +97,6 @@ public:
|
|||
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
|
||||
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
|
||||
mViewport.IsEqualEdges(aOther.mViewport) &&
|
||||
mScrollId == aOther.mScrollId &&
|
||||
mScrollableRect.IsEqualEdges(aOther.mScrollableRect) &&
|
||||
mResolution == aOther.mResolution &&
|
||||
mCumulativeResolution == aOther.mCumulativeResolution &&
|
||||
|
@ -105,6 +104,7 @@ public:
|
|||
mMayHaveTouchListeners == aOther.mMayHaveTouchListeners &&
|
||||
mPresShellId == aOther.mPresShellId &&
|
||||
mIsRoot == aOther.mIsRoot &&
|
||||
mScrollId == aOther.mScrollId &&
|
||||
mScrollOffset == aOther.mScrollOffset &&
|
||||
mHasScrollgrab == aOther.mHasScrollgrab &&
|
||||
mUpdateScrollOffset == aOther.mUpdateScrollOffset;
|
||||
|
@ -265,9 +265,6 @@ public:
|
|||
// meaningless and invalid.
|
||||
CSSRect mViewport;
|
||||
|
||||
// A unique ID assigned to each scrollable frame.
|
||||
ViewID mScrollId;
|
||||
|
||||
// The scrollable bounds of a frame. This is determined by reflow.
|
||||
// Ordinarily the x and y will be 0 and the width and height will be the
|
||||
// size of the element being scrolled. However for RTL pages or elements
|
||||
|
@ -370,10 +367,23 @@ public:
|
|||
mContentDescription = aContentDescription;
|
||||
}
|
||||
|
||||
ViewID GetScrollId() const
|
||||
{
|
||||
return mScrollId;
|
||||
}
|
||||
|
||||
void SetScrollId(ViewID scrollId)
|
||||
{
|
||||
mScrollId = scrollId;
|
||||
}
|
||||
|
||||
private:
|
||||
// New fields from now on should be made private and old fields should
|
||||
// be refactored to be private.
|
||||
|
||||
// A unique ID assigned to each scrollable frame.
|
||||
ViewID mScrollId;
|
||||
|
||||
// The position of the top-left of the CSS viewport, relative to the document
|
||||
// (or the document relative to the viewport, if that helps understand it).
|
||||
//
|
||||
|
@ -441,7 +451,7 @@ struct ScrollableLayerGuid {
|
|||
ScrollableLayerGuid(uint64_t aLayersId, const FrameMetrics& aMetrics)
|
||||
: mLayersId(aLayersId)
|
||||
, mPresShellId(aMetrics.mPresShellId)
|
||||
, mScrollId(aMetrics.mScrollId)
|
||||
, mScrollId(aMetrics.GetScrollId())
|
||||
{
|
||||
MOZ_COUNT_CTOR(ScrollableLayerGuid);
|
||||
}
|
||||
|
|
|
@ -472,6 +472,26 @@ PlanarYCbCrImage::~PlanarYCbCrImage()
|
|||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
PlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
// Ignoring:
|
||||
// - mData - just wraps mBuffer
|
||||
// - Surfaces should be reported under gfx-surfaces-*:
|
||||
// - mDeprecatedSurface
|
||||
// - mSourceSurface
|
||||
// - Base class:
|
||||
// - mImplData is not used
|
||||
// Not owned:
|
||||
// - mRecycleBin
|
||||
size_t size = mBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Could add in the future:
|
||||
// - mBackendData (from base class)
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
|
||||
{
|
||||
|
|
|
@ -863,6 +863,12 @@ public:
|
|||
virtual SharedPlanarYCbCrImage *AsSharedPlanarYCbCrImage() { return nullptr; }
|
||||
virtual DeprecatedSharedPlanarYCbCrImage *AsDeprecatedSharedPlanarYCbCrImage() { return nullptr; }
|
||||
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Make a copy of the YCbCr data into local storage.
|
||||
|
|
|
@ -500,16 +500,16 @@ Layer::SnapTransformTranslation(const Matrix4x4& aTransform,
|
|||
!matrix2D.HasNonTranslation() &&
|
||||
matrix2D.HasNonIntegerTranslation()) {
|
||||
IntPoint snappedTranslation = RoundedToInt(matrix2D.GetTranslation());
|
||||
Matrix snappedMatrix = Matrix().Translate(snappedTranslation.x,
|
||||
snappedTranslation.y);
|
||||
Matrix snappedMatrix = Matrix::Translation(snappedTranslation.x,
|
||||
snappedTranslation.y);
|
||||
result = Matrix4x4::From2D(snappedMatrix);
|
||||
if (aResidualTransform) {
|
||||
// set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
|
||||
// (I.e., appying snappedMatrix after aResidualTransform gives the
|
||||
// ideal transform.)
|
||||
*aResidualTransform =
|
||||
Matrix().Translate(matrix2D._31 - snappedTranslation.x,
|
||||
matrix2D._32 - snappedTranslation.y);
|
||||
Matrix::Translation(matrix2D._31 - snappedTranslation.x,
|
||||
matrix2D._32 - snappedTranslation.y);
|
||||
}
|
||||
} else {
|
||||
result = aTransform;
|
||||
|
|
|
@ -121,7 +121,7 @@ AppendToString(nsACString& s, const FrameMetrics& m,
|
|||
AppendToString(s, m.GetScrollOffset(), " viewportScroll=");
|
||||
AppendToString(s, m.mDisplayPort, " displayport=");
|
||||
AppendToString(s, m.mScrollableRect, " scrollableRect=");
|
||||
AppendToString(s, m.mScrollId, " scrollId=", " }");
|
||||
AppendToString(s, m.GetScrollId(), " scrollId=", " }");
|
||||
return s += sfx;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,18 @@ public:
|
|||
already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
|
||||
TemporaryRef<gfx::SourceSurface> GetAsSourceSurface();
|
||||
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
size_t size = PlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mDecodedBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoArrayPtr<uint8_t> mDecodedBuffer;
|
||||
gfx::IntSize mScaleHint;
|
||||
|
|
|
@ -29,7 +29,7 @@ ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManage
|
|||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(ClientTiledThebesLayer);
|
||||
mPaintData.mLastScrollOffset = ScreenPoint(0, 0);
|
||||
mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0);
|
||||
mPaintData.mFirstPaint = true;
|
||||
}
|
||||
|
||||
|
@ -67,73 +67,106 @@ ClientTiledThebesLayer::BeginPaint()
|
|||
|
||||
mPaintData.mLowPrecisionPaintCount = 0;
|
||||
mPaintData.mPaintFinished = false;
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mCriticalDisplayPort.SetEmpty();
|
||||
|
||||
// Get the metrics of the nearest scroll container.
|
||||
if (!GetBaseTransform().Is2DIntegerTranslation()) {
|
||||
// Give up if the layer is transformed. The code below assumes that there
|
||||
// is no transform set, and not making that assumption would cause huge
|
||||
// complication to handle a quite rare case.
|
||||
//
|
||||
// FIXME The intention is to bail out of this function when there's a CSS
|
||||
// transform set on the layer, but unfortunately there's no way to
|
||||
// distinguish transforms due to scrolling from transforms due to
|
||||
// CSS transforms.
|
||||
//
|
||||
// Because of this, there may be unintended behaviour when setting
|
||||
// 2d CSS translations on the children of scrollable displayport
|
||||
// layers.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the metrics of the nearest scrollable layer and the nearest layer
|
||||
// with a displayport.
|
||||
ContainerLayer* displayPortParent = nullptr;
|
||||
ContainerLayer* scrollParent = nullptr;
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
if (metrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) {
|
||||
if (!scrollParent && metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
|
||||
scrollParent = parent;
|
||||
}
|
||||
if (!metrics.mDisplayPort.IsEmpty()) {
|
||||
displayPortParent = parent;
|
||||
// Any layer that has a displayport must be scrollable, so we can break
|
||||
// here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollParent) {
|
||||
// XXX I don't think this can happen, but if it does, warn and set the
|
||||
// composition bounds to empty so that progressive updates are disabled.
|
||||
if (!displayPortParent || !scrollParent) {
|
||||
// No displayport or scroll parent, so we can't do progressive rendering.
|
||||
// Just set the composition bounds to empty and return.
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_B2G)
|
||||
// Both Android and b2g are guaranteed to have a displayport set, so this
|
||||
// should never happen.
|
||||
NS_WARNING("Tiled Thebes layer with no scrollable container parent");
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& metrics = scrollParent->GetFrameMetrics();
|
||||
// Note, not handling transformed layers lets us assume that LayoutDevice
|
||||
// space of the scroll parent layer is the same as LayoutDevice space of
|
||||
// this layer.
|
||||
const FrameMetrics& scrollMetrics = scrollParent->GetFrameMetrics();
|
||||
const FrameMetrics& displayportMetrics = displayPortParent->GetFrameMetrics();
|
||||
|
||||
// Calculate the transform required to convert parent layer space into
|
||||
// transformed layout device space.
|
||||
gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
if (parent->UseIntermediateSurface()) {
|
||||
effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
|
||||
}
|
||||
// Calculate the transform required to convert ParentLayer space of our
|
||||
// display port parent to LayoutDevice space of this layer.
|
||||
gfx::Matrix4x4 transform = scrollParent->GetTransform();
|
||||
ContainerLayer* displayPortParentParent = displayPortParent->GetParent() ?
|
||||
displayPortParent->GetParent()->GetParent() : nullptr;
|
||||
for (ContainerLayer* parent = scrollParent->GetParent();
|
||||
parent != displayPortParentParent;
|
||||
parent = parent->GetParent()) {
|
||||
transform = transform * parent->GetTransform();
|
||||
}
|
||||
gfx3DMatrix layoutToParentLayer;
|
||||
gfx::To3DMatrix(effectiveTransform, layoutToParentLayer);
|
||||
layoutToParentLayer.ScalePost(metrics.GetParentResolution().scale,
|
||||
metrics.GetParentResolution().scale,
|
||||
1.f);
|
||||
gfx3DMatrix layoutDeviceToScrollParentLayer;
|
||||
gfx::To3DMatrix(transform, layoutDeviceToScrollParentLayer);
|
||||
layoutDeviceToScrollParentLayer.ScalePost(scrollMetrics.mCumulativeResolution.scale,
|
||||
scrollMetrics.mCumulativeResolution.scale,
|
||||
1.f);
|
||||
|
||||
mPaintData.mTransformParentLayerToLayout = layoutToParentLayer.Inverse();
|
||||
mPaintData.mTransformParentLayerToLayoutDevice = layoutDeviceToScrollParentLayer.Inverse();
|
||||
|
||||
// Compute the critical display port in layer space.
|
||||
mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
|
||||
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Convert the display port to screen space first so that we can transform
|
||||
// it into layout device space.
|
||||
const ParentLayerRect& criticalDisplayPort = metrics.mCriticalDisplayPort
|
||||
* metrics.mDevPixelsPerCSSPixel
|
||||
* metrics.GetParentResolution();
|
||||
LayoutDeviceRect transformedCriticalDisplayPort =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout, criticalDisplayPort);
|
||||
mPaintData.mLayoutCriticalDisplayPort =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
|
||||
}
|
||||
// Compute the critical display port of the display port layer in
|
||||
// LayoutDevice space of this layer.
|
||||
ParentLayerRect criticalDisplayPort =
|
||||
(displayportMetrics.mCriticalDisplayPort + displayportMetrics.GetScrollOffset()) *
|
||||
displayportMetrics.GetZoomToParent();
|
||||
mPaintData.mCriticalDisplayPort = LayoutDeviceIntRect::ToUntyped(RoundedOut(
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayoutDevice,
|
||||
criticalDisplayPort)));
|
||||
|
||||
// Calculate the frame resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use mZoom for this.
|
||||
mPaintData.mResolution = metrics.GetZoom();
|
||||
// Compute the viewport of the display port layer in LayoutDevice space of
|
||||
// this layer.
|
||||
ParentLayerRect viewport =
|
||||
(displayportMetrics.mViewport + displayportMetrics.GetScrollOffset()) *
|
||||
displayportMetrics.GetZoomToParent();
|
||||
mPaintData.mViewport = ApplyParentLayerToLayoutTransform(
|
||||
mPaintData.mTransformParentLayerToLayoutDevice, viewport);
|
||||
|
||||
// Calculate the scroll offset since the last transaction, and the
|
||||
// composition bounds.
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mScrollOffset.MoveTo(0, 0);
|
||||
Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
|
||||
if (primaryScrollable) {
|
||||
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
||||
mPaintData.mScrollOffset = metrics.GetScrollOffset() * metrics.GetZoom();
|
||||
mPaintData.mCompositionBounds =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout,
|
||||
ParentLayerRect(metrics.mCompositionBounds));
|
||||
}
|
||||
// Store the scroll parent resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use the zoom for this.
|
||||
mPaintData.mResolution = displayportMetrics.GetZoomToParent();
|
||||
|
||||
// Store the parent composition bounds in LayoutDevice units.
|
||||
// This is actually in LayoutDevice units of the scrollParent's parent layer,
|
||||
// but because there is no transform, we can assume that these are the same.
|
||||
mPaintData.mCompositionBounds =
|
||||
scrollMetrics.mCompositionBounds / scrollMetrics.GetParentResolution();
|
||||
|
||||
// Calculate the scroll offset since the last transaction
|
||||
mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -213,15 +246,15 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// discarded on the first update.
|
||||
if (!ClientManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, mVisibleRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Make sure that tiles that fall outside of the critical displayport are
|
||||
// discarded on the first update.
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRegion lowPrecisionInvalidRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
if (gfxPrefs::UseLowPrecisionBuffer()) {
|
||||
// Calculate the invalid region for the low precision buffer
|
||||
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
|
||||
|
@ -232,7 +265,7 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
}
|
||||
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort);
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
|
@ -250,8 +283,8 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// used to decide stale content (currently valid and previously visible)
|
||||
nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
|
||||
updatedBuffer =
|
||||
|
@ -261,8 +294,8 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
} else {
|
||||
updatedBuffer = true;
|
||||
mValidRegion = mVisibleRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
|
@ -292,7 +325,7 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// visible region is larger than the critical display port.
|
||||
bool updatedLowPrecision = false;
|
||||
if (!lowPrecisionInvalidRegion.IsEmpty() &&
|
||||
!nsIntRegion(mPaintData.mLayoutCriticalDisplayPort).Contains(mVisibleRegion)) {
|
||||
!nsIntRegion(mPaintData.mCriticalDisplayPort).Contains(mVisibleRegion)) {
|
||||
nsIntRegion oldValidRegion =
|
||||
mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
|
|
|
@ -248,9 +248,6 @@ SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* a
|
|||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer);
|
||||
|
||||
mPaintData.mLastScrollOffset = ScreenPoint(0, 0);
|
||||
mPaintData.mFirstPaint = true;
|
||||
}
|
||||
|
||||
SimpleClientTiledThebesLayer::~SimpleClientTiledThebesLayer()
|
||||
|
@ -264,102 +261,6 @@ SimpleClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aA
|
|||
aAttrs = ThebesLayerAttributes(GetValidRegion());
|
||||
}
|
||||
|
||||
static LayoutDeviceRect
|
||||
ApplyParentLayerToLayoutTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
|
||||
{
|
||||
return TransformTo<LayoutDevicePixel>(aTransform, aParentLayerRect);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::BeginPaint()
|
||||
{
|
||||
if (ClientManager()->IsRepeatTransaction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPaintData.mLowPrecisionPaintCount = 0;
|
||||
mPaintData.mPaintFinished = false;
|
||||
|
||||
// Get the metrics of the nearest scroll container.
|
||||
ContainerLayer* scrollParent = nullptr;
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
if (metrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) {
|
||||
scrollParent = parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollParent) {
|
||||
// XXX I don't think this can happen, but if it does, warn and set the
|
||||
// composition bounds to empty so that progressive updates are disabled.
|
||||
NS_WARNING("Tiled Thebes layer with no scrollable container parent");
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& metrics = scrollParent->GetFrameMetrics();
|
||||
|
||||
// Calculate the transform required to convert screen space into transformed
|
||||
// layout device space.
|
||||
gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
if (parent->UseIntermediateSurface()) {
|
||||
effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
|
||||
}
|
||||
}
|
||||
gfx3DMatrix layoutToParentLayer;
|
||||
gfx::To3DMatrix(effectiveTransform, layoutToParentLayer);
|
||||
layoutToParentLayer.ScalePost(metrics.GetParentResolution().scale,
|
||||
metrics.GetParentResolution().scale,
|
||||
1.f);
|
||||
|
||||
mPaintData.mTransformParentLayerToLayout = layoutToParentLayer.Inverse();
|
||||
|
||||
// Compute the critical display port in layer space.
|
||||
mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
|
||||
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Convert the display port to screen space first so that we can transform
|
||||
// it into layout device space.
|
||||
const ParentLayerRect& criticalDisplayPort = metrics.mCriticalDisplayPort
|
||||
* metrics.mDevPixelsPerCSSPixel
|
||||
* metrics.GetParentResolution();
|
||||
LayoutDeviceRect transformedCriticalDisplayPort =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout, criticalDisplayPort);
|
||||
mPaintData.mLayoutCriticalDisplayPort =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
|
||||
}
|
||||
|
||||
// Calculate the frame resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use mZoom for this.
|
||||
mPaintData.mResolution = metrics.GetZoom();
|
||||
|
||||
// Calculate the scroll offset since the last transaction, and the
|
||||
// composition bounds.
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mScrollOffset.MoveTo(0, 0);
|
||||
Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
|
||||
if (primaryScrollable) {
|
||||
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
||||
mPaintData.mScrollOffset = metrics.GetScrollOffset() * metrics.GetZoom();
|
||||
mPaintData.mCompositionBounds =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout,
|
||||
ParentLayerRect(metrics.mCompositionBounds));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::EndPaint(bool aFinish)
|
||||
{
|
||||
if (!aFinish && !mPaintData.mPaintFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
|
||||
mPaintData.mPaintFinished = true;
|
||||
mPaintData.mFirstPaint = false;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::RenderLayer()
|
||||
{
|
||||
|
@ -388,83 +289,29 @@ SimpleClientTiledThebesLayer::RenderLayer()
|
|||
nsIntRegion invalidRegion = mVisibleRegion;
|
||||
invalidRegion.Sub(invalidRegion, mValidRegion);
|
||||
if (invalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
|
||||
|
||||
nsIntRegion wantToPaintRegion = mVisibleRegion;
|
||||
|
||||
// Only paint the mask layer on the first transaction.
|
||||
if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
|
||||
ToClientLayer(GetMaskLayer())->RenderLayer();
|
||||
}
|
||||
|
||||
// Fast path for no progressive updates, no low-precision updates and no
|
||||
// critical display-port set, or no display-port set.
|
||||
if (parentMetrics.mCriticalDisplayPort.IsEmpty() ||
|
||||
parentMetrics.mDisplayPort.IsEmpty())
|
||||
{
|
||||
mValidRegion = wantToPaintRegion;
|
||||
// SimpleTiledContentClient doesn't support progressive updates or the low
|
||||
// precision buffer yet.
|
||||
MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() &&
|
||||
!gfxPrefs::UseLowPrecisionBuffer());
|
||||
|
||||
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
|
||||
mValidRegion = mVisibleRegion;
|
||||
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
|
||||
|
||||
ClientManager()->Hold(this);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
ClientManager()->Hold(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate everything we need to perform the paint.
|
||||
BeginPaint();
|
||||
|
||||
if (mPaintData.mPaintFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
// discarded on the first update.
|
||||
if (!ClientManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, wantToPaintRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
// Make sure that tiles that fall outside of the critical displayport are
|
||||
// discarded on the first update.
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRegion lowPrecisionInvalidRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!invalidRegion.IsEmpty()) {
|
||||
mValidRegion = wantToPaintRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
}
|
||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
|
||||
ClientManager()->Hold(this);
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
|
||||
EndPaint(false);
|
||||
return;
|
||||
}
|
||||
|
||||
EndPaint(false);
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const CSSToScreenScale& GetFrameResolution() const { return mFrameResolution; }
|
||||
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() const { return mFrameResolution; }
|
||||
void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
|
||||
|
||||
bool HasFormatChanged() const;
|
||||
private:
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
ClientLayerManager* mManager;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mLastPaintOpaque;
|
||||
|
||||
gfxContentType GetContentType() const;
|
||||
|
@ -180,11 +180,7 @@ public:
|
|||
protected:
|
||||
ClientLayerManager* ClientManager() { return static_cast<ClientLayerManager*>(mManager); }
|
||||
|
||||
void BeginPaint();
|
||||
void EndPaint(bool aFinish);
|
||||
|
||||
RefPtr<SimpleTiledContentClient> mContentClient;
|
||||
BasicTiledLayerPaintData mPaintData;
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
|
|
@ -156,7 +156,7 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
|
|||
const FrameMetrics& contentMetrics = aLayer->GetFrameMetrics();
|
||||
FrameMetrics compositorMetrics;
|
||||
|
||||
if (!compositor->LookupCompositorFrameMetrics(contentMetrics.mScrollId,
|
||||
if (!compositor->LookupCompositorFrameMetrics(contentMetrics.GetScrollId(),
|
||||
compositorMetrics)) {
|
||||
FindFallbackContentFrameMetrics(aLayer, aCompositionBounds, aZoom);
|
||||
return false;
|
||||
|
@ -861,18 +861,18 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
|
|||
static LayoutDeviceRect
|
||||
TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
|
||||
const CSSToParentLayerScale& aZoom,
|
||||
const ScreenPoint& aScrollOffset,
|
||||
const CSSToScreenScale& aResolution,
|
||||
const gfx3DMatrix& aTransformScreenToLayout)
|
||||
const ParentLayerPoint& aScrollOffset,
|
||||
const CSSToParentLayerScale& aResolution,
|
||||
const gfx3DMatrix& aTransformParentLayerToLayoutDevice)
|
||||
{
|
||||
// Transform the current composition bounds into transformed layout device
|
||||
// space by compensating for the difference in resolution and subtracting the
|
||||
// Transform the current composition bounds into ParentLayer coordinates
|
||||
// by compensating for the difference in resolution and subtracting the
|
||||
// old composition bounds origin.
|
||||
ScreenRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
|
||||
ParentLayerRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
|
||||
offsetViewportRect.MoveBy(-aScrollOffset);
|
||||
|
||||
gfxRect transformedViewport =
|
||||
aTransformScreenToLayout.TransformBounds(
|
||||
aTransformParentLayerToLayoutDevice.TransformBounds(
|
||||
gfxRect(offsetViewportRect.x, offsetViewportRect.y,
|
||||
offsetViewportRect.width, offsetViewportRect.height));
|
||||
|
||||
|
@ -884,10 +884,10 @@ TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
|
|||
|
||||
bool
|
||||
ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
BasicTiledLayerPaintData* aPaintData,
|
||||
bool aIsRepeated)
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
BasicTiledLayerPaintData* aPaintData,
|
||||
bool aIsRepeated)
|
||||
{
|
||||
aRegionToPaint = aInvalidRegion;
|
||||
|
||||
|
@ -942,20 +942,27 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
|
|||
}
|
||||
}
|
||||
|
||||
// Transform the screen coordinates into transformed layout device coordinates.
|
||||
// Transform the composition bounds, which is in the ParentLayer coordinates
|
||||
// of the nearest ContainerLayer with a valid displayport to LayoutDevice
|
||||
// coordinates relative to this layer.
|
||||
LayoutDeviceRect transformedCompositionBounds =
|
||||
TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
|
||||
aPaintData->mResolution, aPaintData->mTransformParentLayerToLayout);
|
||||
aPaintData->mResolution, aPaintData->mTransformParentLayerToLayoutDevice);
|
||||
|
||||
// Paint tiles that have stale content or that intersected with the screen
|
||||
// at the time of issuing the draw command in a single transaction first.
|
||||
// This is to avoid rendering glitches on animated page content, and when
|
||||
// layers change size/shape.
|
||||
LayoutDeviceRect coherentUpdateRect =
|
||||
LayoutDeviceRect typedCoherentUpdateRect =
|
||||
transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds);
|
||||
|
||||
// Offset by the viewport origin, as the composition bounds are stored in
|
||||
// Layer space and not LayoutDevice space.
|
||||
typedCoherentUpdateRect.MoveBy(aPaintData->mViewport.TopLeft());
|
||||
|
||||
// Convert to untyped to intersect with the invalid region.
|
||||
nsIntRect roundedCoherentUpdateRect =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(coherentUpdateRect));
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(typedCoherentUpdateRect));
|
||||
|
||||
aRegionToPaint.And(aInvalidRegion, roundedCoherentUpdateRect);
|
||||
aRegionToPaint.Or(aRegionToPaint, staleRegion);
|
||||
|
|
|
@ -244,41 +244,46 @@ struct BasicTiledLayerPaintData {
|
|||
* The scroll offset of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set.
|
||||
*/
|
||||
ScreenPoint mScrollOffset;
|
||||
ParentLayerPoint mScrollOffset;
|
||||
|
||||
/*
|
||||
* The scroll offset of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set, for the last
|
||||
* layer update transaction.
|
||||
*/
|
||||
ScreenPoint mLastScrollOffset;
|
||||
ParentLayerPoint mLastScrollOffset;
|
||||
|
||||
/*
|
||||
* The transform matrix to go from ParentLayer units to transformed
|
||||
* LayoutDevice units.
|
||||
* The transform matrix to go from Screen units to ParentLayer units.
|
||||
*/
|
||||
gfx3DMatrix mTransformParentLayerToLayout;
|
||||
gfx3DMatrix mTransformParentLayerToLayoutDevice;
|
||||
|
||||
/*
|
||||
* The critical displayport of the content from the nearest ancestor layer
|
||||
* that represents scrollable content with a display port set. Empty if a
|
||||
* critical displayport is not set.
|
||||
*
|
||||
* This is in transformed LayoutDevice coordinates, but is stored as an
|
||||
* nsIntRect for convenience when intersecting with the layer's mValidRegion.
|
||||
* This is in LayoutDevice coordinates, but is stored as an nsIntRect for
|
||||
* convenience when intersecting with the layer's mValidRegion.
|
||||
*/
|
||||
nsIntRect mLayoutCriticalDisplayPort;
|
||||
nsIntRect mCriticalDisplayPort;
|
||||
|
||||
/*
|
||||
* The viewport of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set.
|
||||
*/
|
||||
LayoutDeviceRect mViewport;
|
||||
|
||||
/*
|
||||
* The render resolution of the document that the content this layer
|
||||
* represents is in.
|
||||
*/
|
||||
CSSToScreenScale mResolution;
|
||||
CSSToParentLayerScale mResolution;
|
||||
|
||||
/*
|
||||
* The composition bounds of the primary scrollable layer, in transformed
|
||||
* layout device coordinates. This is used to make sure that tiled updates to
|
||||
* regions that are visible to the user are grouped coherently.
|
||||
* The composition bounds of the layer, in LayoutDevice coordinates. This is
|
||||
* used to make sure that tiled updates to regions that are visible to the
|
||||
* user are grouped coherently.
|
||||
*/
|
||||
LayoutDeviceRect mCompositionBounds;
|
||||
|
||||
|
@ -381,9 +386,9 @@ public:
|
|||
|
||||
void DiscardBackBuffers();
|
||||
|
||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
|
||||
|
||||
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
||||
void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
|
||||
|
||||
bool HasFormatChanged() const;
|
||||
|
||||
|
@ -424,7 +429,7 @@ private:
|
|||
ClientLayerManager* mManager;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mLastPaintOpaque;
|
||||
|
||||
// The DrawTarget we use when UseSinglePaintBuffer() above is true.
|
||||
|
|
|
@ -211,7 +211,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
|||
apzc->SetPrevSibling(nullptr);
|
||||
apzc->SetLastChild(nullptr);
|
||||
}
|
||||
APZC_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, container->GetFrameMetrics().mScrollId);
|
||||
APZC_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, container->GetFrameMetrics().GetScrollId());
|
||||
|
||||
apzc->NotifyLayersUpdated(metrics,
|
||||
aIsFirstPaint && (aLayersId == aFirstPaintLayersId));
|
||||
|
|
|
@ -244,7 +244,7 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
|
|||
bool isStickyForSubtree = aLayer->GetIsStickyPosition() &&
|
||||
aTransformedSubtreeRoot->AsContainerLayer() &&
|
||||
aLayer->GetStickyScrollContainerId() ==
|
||||
aTransformedSubtreeRoot->AsContainerLayer()->GetFrameMetrics().mScrollId;
|
||||
aTransformedSubtreeRoot->AsContainerLayer()->GetFrameMetrics().GetScrollId();
|
||||
if (aLayer != aTransformedSubtreeRoot && (isRootFixed || isStickyForSubtree)) {
|
||||
// Insert a translation so that the position of the anchor point is the same
|
||||
// before and after the change to the transform of aTransformedSubtreeRoot.
|
||||
|
@ -606,7 +606,7 @@ AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer)
|
|||
continue;
|
||||
}
|
||||
const FrameMetrics& metrics = scrollTarget->AsContainerLayer()->GetFrameMetrics();
|
||||
if (metrics.mScrollId != aLayer->GetScrollbarTargetContainerId()) {
|
||||
if (metrics.GetScrollId() != aLayer->GetScrollbarTargetContainerId()) {
|
||||
continue;
|
||||
}
|
||||
if (!LayerHasNonContainerDescendants(scrollTarget->AsContainerLayer())) {
|
||||
|
|
|
@ -182,7 +182,7 @@ ThebesLayerComposite::GetEffectiveResolution()
|
|||
{
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
if (metrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) {
|
||||
if (metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
|
||||
return metrics.GetZoom();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocat
|
|||
mRetainedWidth = aDescriptor.retainedWidth();
|
||||
mRetainedHeight = aDescriptor.retainedHeight();
|
||||
mResolution = aDescriptor.resolution();
|
||||
mFrameResolution = CSSToScreenScale(aDescriptor.frameResolution());
|
||||
mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution());
|
||||
|
||||
// Combine any valid content that wasn't already uploaded
|
||||
nsIntRegion oldPaintedRegion(aOldPaintedRegion);
|
||||
|
@ -379,8 +379,8 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
|||
// We assume that the current frame resolution is the one used in our primary
|
||||
// layer buffer. Compensate for a changing frame resolution.
|
||||
if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
|
||||
const CSSToScreenScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
||||
const CSSToScreenScale& localResolution = mTiledBuffer.GetFrameResolution();
|
||||
const CSSToParentLayerScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
||||
const CSSToParentLayerScale& localResolution = mTiledBuffer.GetFrameResolution();
|
||||
layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
|
||||
aVisibleRect.ScaleRoundOut(layerScale.width, layerScale.height);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
|
||||
// Stores the absolute resolution of the containing frame, calculated
|
||||
// by the sum of the resolutions of all parent layers' FrameMetrics.
|
||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
|
||||
|
||||
void ReadUnlock();
|
||||
|
||||
|
@ -144,7 +144,7 @@ protected:
|
|||
void SwapTiles(TileHost& aTileA, TileHost& aTileB) { std::swap(aTileA, aTileB); }
|
||||
|
||||
private:
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mHasDoubleBufferedTiles;
|
||||
bool mUninitialized;
|
||||
};
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче