This commit is contained in:
Phil Ringnalda 2014-03-22 17:50:05 -07:00
Родитель f7c2b9529d d5c29df48d
Коммит 236cb3aed6
179 изменённых файлов: 5457 добавлений и 2973 удалений

Просмотреть файл

@ -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&param2=value2&param3=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&param2=value2&param3=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&param2=value2&param3=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

Просмотреть файл

@ -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;
};

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше