diff --git a/b2g/chrome/content/devtools/hud.js b/b2g/chrome/content/devtools/hud.js index 54a612da4ae..6b49dbfbc88 100644 --- a/b2g/chrome/content/devtools/hud.js +++ b/b2g/chrome/content/devtools/hud.js @@ -8,6 +8,8 @@ const DEVELOPER_HUD_LOG_PREFIX = 'DeveloperHUD'; const CUSTOM_HISTOGRAM_PREFIX = 'DEVTOOLS_HUD_CUSTOM_'; +const APPNAME_IDX = 3; +const HISTNAME_IDX = 4; XPCOMUtils.defineLazyGetter(this, 'devtools', function() { const {devtools} = Cu.import('resource://devtools/shared/Loader.jsm', {}); @@ -322,14 +324,16 @@ Target.prototype = { }, _getAddonHistogram(item) { - let APPNAME_IDX = 3; - let HISTNAME_IDX = 4; + let appName = this._getAddonHistogramName(item, APPNAME_IDX); + let histName = this._getAddonHistogramName(item, HISTNAME_IDX); + return Services.telemetry.getAddonHistogram(appName, CUSTOM_HISTOGRAM_PREFIX + + histName); + }, + + _getAddonHistogramName(item, index) { let array = item.split('_'); - let appName = array[APPNAME_IDX].toUpperCase(); - let histName = array[HISTNAME_IDX].toUpperCase(); - return Services.telemetry.getAddonHistogram(appName, - CUSTOM_HISTOGRAM_PREFIX + histName); + return array[index].toUpperCase(); }, _clearTelemetryData() { @@ -357,11 +361,21 @@ Target.prototype = { payload.keyedHistograms[item] = Services.telemetry.getKeyedHistogramById(item).snapshot(); }); + // Package the registered hud custom histograms developerHUD._customHistograms.forEach(item => { - payload.addonHistograms[item] = this._getAddonHistogram(item).snapshot(); + let appName = this._getAddonHistogramName(item, APPNAME_IDX); + let histName = CUSTOM_HISTOGRAM_PREFIX + + this._getAddonHistogramName(item, HISTNAME_IDX); + let addonHist = Services.telemetry.getAddonHistogram(appName, histName).snapshot(); + if (!(appName in payload.addonHistograms)) { + payload.addonHistograms[appName] = {}; + } + // Do not include histograms with sum of 0. + if (addonHist.sum > 0) { + payload.addonHistograms[appName][histName] = addonHist; + } }); - shell.sendEvent(frame, 'advanced-telemetry-update', Cu.cloneInto(payload, frame)); }, diff --git a/b2g/components/PersistentDataBlock.jsm b/b2g/components/PersistentDataBlock.jsm new file mode 100644 index 00000000000..16349cc2433 --- /dev/null +++ b/b2g/components/PersistentDataBlock.jsm @@ -0,0 +1,765 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * The Persistent Partition has this layout: + * + * Bytes: 32 4 4 1 + * Fields: [[DIGEST][MAGIC][DATA_LENGTH][ DATA ][OEM_UNLOCK_ENABLED]] + * + */ + +"use strict"; + +const DEBUG = false; + +this.EXPORTED_SYMBOLS = [ "PersistentDataBlock" ]; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +// This is a marker that will be written after digest in the partition. +const PARTITION_MAGIC = 0x19901873; +// This is the limit in Android because of issues with Binder if blocks are > 100k +// We dont really have this issues because we don't use Binder, but let's stick +// to Android implementation. +const MAX_DATA_BLOCK_SIZE = 1024 * 100; +const DIGEST_SIZE_BYTES = 32; +const HEADER_SIZE_BYTES = 8; +const PARTITION_MAGIC_SIZE_BYTES = 4; +const DATA_SIZE_BYTES = 4; +const OEM_UNLOCK_ENABLED_BYTES = 1; +// The position of the Digest +const DIGEST_OFFSET = 0; +const XPCOM_SHUTDOWN_OBSERVER_TOPIC = "xpcom-shutdown"; +// This property will have the path to the persistent partition +const PERSISTENT_DATA_BLOCK_PROPERTY = "ro.frp.pst"; +const OEM_UNLOCK_PROPERTY = "sys.oem_unlock_allowed"; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); + +XPCOMUtils.defineLazyGetter(this, "libcutils", function () { + Cu.import("resource://gre/modules/systemlibs.js"); + return libcutils; +}); + +var inParent = Cc["@mozilla.org/xre/app-info;1"] + .getService(Ci.nsIXULRuntime) + .processType === Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + +function log(str) { + dump("PersistentDataBlock.jsm: " + str + "\n"); +} + +function debug(str) { + DEBUG && log(str); +} + +function toHexString(data) { + function toHexChar(charCode) { + return ("0" + charCode.toString(16).slice(-2)); + } + let hexString = ""; + if (typeof data === "string") { + hexString = [toHexChar(data.charCodeAt(i)) for (i in data)].join(""); + } else if (typeof data === "array") { + hexString = [toHexChar(data[i]) for (i in data)].join(""); + } + return hexString; +} + +function arr2bstr(arr) { + let bstr = ""; + for (let i = 0; i < arr.length; i++) { + bstr += String.fromCharCode(arr[i]); + } + return bstr; +} + +this.PersistentDataBlock = { + + /** + * libc funcionality. Accessed via ctypes + */ + _libc: { + handler: null, + open: function() {}, + close: function() {}, + ioctl: function() {} + }, + + /** + * Component to access property_get/set functions + */ + _libcutils: null, + + /** + * The size of a device block. This is assigned by querying the kernel. + */ + _blockDeviceSize: -1, + + /** + * Data block file + */ + _dataBlockFile: "", + + /** + * Change the behavior of the class for some methods to testing mode. This will fake the return value of some + * methods realted to native operations with block devices. + */ + _testing: false, + + /* + * *** USE ONLY FOR TESTING *** + * This component will interface between Gecko and a special secure partition with no formatting, a raw partition. + * This interaction requires a specific partition layout structure which emulators don't have so far. So for + * our unit tests to pass, we need a way for some methods to behave differently. This method will change this + * behavior at runtime so some low-level platform-specific operations will be faked: + * - Getting the size of a partition: We can use any partition to get the size, is up to the test to choose + * which partition to use. But, in testing mode we use files instead of partitions, so we need to fake the + * return value of this method in this case. + * - Wipping a partition: This will fully remove the partition as well as it filesystem type, so we cannot + * test it on any existing emulator partition. Testing mode will skip this operation. + * + * @param enabled {Bool} Set testing mode. See _testing property. + */ + setTestingMode: function(enabled) { + this._testing = enabled || false; + }, + + /** + * Initialize the class. + * + */ + init: function(mode) { + debug("init()"); + + if (libcutils) { + this._libcutils = libcutils; + } + + if (!this.ctypes) { + Cu.import("resource://gre/modules/ctypes.jsm", this); + } + + if (this._libc.handler === null) { +#ifdef MOZ_WIDGET_GONK + try { + this._libc.handler = this.ctypes.open(this.ctypes.libraryName("c")); + this._libc.close = this._libc.handler.declare("close", + this.ctypes.default_abi, + this.ctypes.int, + this.ctypes.int + ); + this._libc.open = this._libc.handler.declare("open", + this.ctypes.default_abi, + this.ctypes.int, + this.ctypes.char.ptr, + this.ctypes.int + ); + this._libc.ioctl = this._libc.handler.declare("ioctl", + this.ctypes.default_abi, + this.ctypes.int, + this.ctypes.int, + this.ctypes.unsigned_long, + this.ctypes.unsigned_long.ptr); + + } catch(ex) { + log("Unable to open libc.so: ex = " + ex); + throw Cr.NS_ERROR_FAILURE; + } +#else + log("This component requires Gonk!"); + throw Cr.NS_ERROR_ABORT; +#endif + } + + this._dataBlockFile = this._libcutils.property_get(PERSISTENT_DATA_BLOCK_PROPERTY); + if (this._dataBlockFile === null) { + log("init: ERROR: property " + PERSISTENT_DATA_BLOCK_PROPERTY + " doesn't exist!"); + throw Cr.NS_ERROR_FAILURE; + } + + Services.obs.addObserver(this, XPCOM_SHUTDOWN_OBSERVER_TOPIC, false); + }, + + uninit: function() { + debug("uninit()"); + this._libc.handler.close(); + Services.obs.removeObserver(this, XPCOM_SHUTDOWN_OBSERVER_TOPIC); + }, + + _checkLibcUtils: function() { + debug("_checkLibcUtils"); + if (!this._libcutils) { + log("No proper libcutils binding, aborting."); + throw Cr.NS_ERROR_NO_INTERFACE; + } + + return true; + }, + + /** + * Callback mehtod for addObserver + */ + observe: function(aSubject, aTopic, aData) { + debug("observe()"); + switch (aTopic) { + case XPCOM_SHUTDOWN_OBSERVER_TOPIC: + this.uninit(); + break; + + default: + log("Wrong observer topic: " + aTopic); + break; + } + }, + + /** + * This method will format the persistent partition if it detects manipulation (digest calculation will fail) + * or if the OEM Unlock Enabled byte is set to true. + * We need to call this method on every boot. + */ + start: function() { + debug("start()"); + return this._enforceChecksumValidity().then(() => { + return this._formatIfOemUnlockEnabled().then(() => { + return Promise.resolve(true); + }) + }).catch(ex => { + return Promise.reject(ex); + }); + }, + + /** + * Computes the digest of the entire data block. + * The digest is saved in the first 32 bytes of the block. + * + * @param isStoredDigestReturned {Bool} Tells the function to return the stored digest as well as the calculated. + * True means to return stored digest and the calculated + * False means to return just the calculated one + * + * @return Promise {Object} The calculated digest into the "calculated" property, and the stored + * digest into the "stored" property. + */ + _computeDigest: function (isStoredDigestReturned) { + debug("_computeDigest()"); + let digest = {calculated: "", stored: ""}; + let partition; + debug("_computeDigest: _dataBlockFile = " + this._dataBlockFile); + return OS.File.open(this._dataBlockFile, {existing:true, append:false, read:true}).then(_partition => { + partition = _partition; + return partition.read(DIGEST_SIZE_BYTES); + }).then(digestDataRead => { + // If storedDigest is passed as a parameter, the caller will likely compare the + // one is already stored in the partition with the one we are going to compute later. + if (isStoredDigestReturned === true) { + debug("_computeDigest: get stored digest from the partition"); + digest.stored = arr2bstr(digestDataRead); + } + return partition.read(); + }).then(data => { + // Calculate Digest with the data retrieved after the digest + let hasher = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); + hasher.init(hasher.SHA256); + hasher.update(data, data.byteLength); + digest.calculated = hasher.finish(false); + debug("_computeDigest(): Digest = " + toHexString(digest.calculated) + + "(" + digest.calculated.length + ")"); + return partition.close(); + }).then(() => { + return Promise.resolve(digest); + }).catch(ex => { + log("_computeDigest(): Failed to read partition: ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Returns the size of a block from the undelaying filesystem + * + * @return {Number} The size of the block + */ + _getBlockDeviceSize: function() { + debug("_getBlockDeviceSize()"); + + // See _testing property + if (this._testing === true) { + debug("_getBlockDeviceSize: No real block device size in testing mode!. Returning 1024."); + return 1024; + } + +#ifdef MOZ_WIDGET_GONK + const O_READONLY = 0; + const O_NONBLOCK = 1 << 11; + /* Getting the correct values for ioctl() operations by reading the headers is not a trivial task, so + * the better way to get the values below is by writting a simple test aplication in C that will + * print the values to the output. + * 32bits and 64bits value for ioctl() BLKGETSIZE64 operation is different. So we will fallback in + * case ioctl() returns ENOTTY (22). */ + const BLKGETSIZE64_32_BITS = 0x80041272; + const BLKGETSIZE64_64_BITS = 0x80081272; + const ENOTTY = 25; + + debug("_getBlockDeviceSize: _dataBlockFile = " + this._dataBlockFile); + let fd = this._libc.open(this._dataBlockFile, O_READONLY | O_NONBLOCK); + if (fd < 0) { + log("_getBlockDeviceSize: couldn't open partition!: errno = " + this.ctypes.errno); + throw Cr.NS_ERROR_FAILURE; + } + + let size = new this.ctypes.unsigned_long(); + let sizeAddress = size.address(); + let ret = this._libc.ioctl(fd, BLKGETSIZE64_32_BITS, sizeAddress); + if (ret < 0) { + if (this.ctypes.errno === ENOTTY) { + log("_getBlockDeviceSize: errno is ENOTTY, falling back to 64 bit version of BLKGETSIZE64..."); + ret = this._libc.ioctl(fd, BLKGETSIZE64_64_BITS, sizeAddress); + if (ret < 0) { + this._libc.close(fd); + log("_getBlockDeviceSize: BLKGETSIZE64 failed again!. errno = " + this.ctypes.errno); + throw Cr.NS_ERROR_FAILURE; + } + } else { + this._libc.close(fd); + log("_getBlockDeviceSize: couldn't get block device size!: errno = " + this.ctypes.errno); + throw Cr.NS_ERROR_FAILURE; + } + } + this._libc.close(fd); + debug("_getBlockDeviceSize: size =" + size.value); + return size.value; +#else + log("_getBlockDeviceSize: ERROR: This feature is only supported in Gonk!"); + return -1; +#endif + }, + + /** + * Sets the byte into the partition which represents the OEM Unlock Enabled feature. + * A value of "1" means that the user doesn't want to enable KillSwitch. + * The byte is the last one byte into the device block. + * + * @param isSetOemUnlockEnabled {bool} If true, sets the OEM Unlock Enabled byte to 1. + * Otherwise, sets it to 0. + */ + _doSetOemUnlockEnabled: function(isSetOemUnlockEnabled) { + debug("_doSetOemUnlockEnabled()"); + let partition; + return OS.File.open(this._dataBlockFile, {existing:true, append:false, write:true}).then(_partition => { + partition = _partition; + return partition.setPosition(this._getBlockDeviceSize() - OEM_UNLOCK_ENABLED_BYTES, OS.File.POS_START); + }).then(() => { + return partition.write(new Uint8Array([ isSetOemUnlockEnabled === true ? 1 : 0 ])); + }).then(bytesWrittenLength => { + if (bytesWrittenLength != 1) { + log("_doSetOemUnlockEnabled: Error writting OEM Unlock Enabled byte!"); + return Promise.reject(); + } + return partition.close(); + }).then(() => { + let oemUnlockByte = (isSetOemUnlockEnabled === true ? "1" : "0"); + debug("_doSetOemUnlockEnabled: OEM unlock enabled written to " + oemUnlockByte); + this._libcutils.property_set(OEM_UNLOCK_PROPERTY, oemUnlockByte); + return Promise.resolve(); + }).catch(ex => { + return Promise.reject(ex); + }); + }, + + /** + * Computes the digest by reading the entire block of data and write it to the digest field + * + * @return true Promise Operation succeed + * @return false Promise Operation failed + */ + _computeAndWriteDigest: function() { + debug("_computeAndWriteDigest()"); + let digest; + let partition; + return this._computeDigest().then(_digest => { + digest = _digest; + return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}); + }).then(_partition => { + partition = _partition; + return partition.setPosition(DIGEST_OFFSET, OS.File.POS_START); + }).then(() => { + return partition.write(new Uint8Array([digest.calculated.charCodeAt(i) for (i in digest.calculated)])); + }).then(bytesWrittenLength => { + if (bytesWrittenLength != DIGEST_SIZE_BYTES) { + log("_computeAndWriteDigest: Error writting digest to partition!. Expected: " + DIGEST_SIZE_BYTES + " Written: " + bytesWrittenLength); + return Promise.reject(); + } + return partition.close(); + }).then(() => { + debug("_computeAndWriteDigest: digest written to partition"); + return Promise.resolve(true); + }).catch(ex => { + log("_computeAndWriteDigest: Couldn't write digest in the persistent partion. ex = " + ex ); + return Promise.reject(ex); + }); + }, + + /** + * Formats the persistent partition if the OEM Unlock Enabled field is set to true, and + * write the Unlock Property accordingly. + * + * @return true Promise OEM Unlock was enabled, so the partition has been formated + * @return false Promise OEM Unlock was disabled, so the partition hasn't been formated + */ + _formatIfOemUnlockEnabled: function () { + debug("_formatIfOemUnlockEnabled()"); + return this.getOemUnlockEnabled().then(enabled => { + this._libcutils.property_set(OEM_UNLOCK_PROPERTY,(enabled === true ? "1" : "0")); + if (enabled === true) { + return this._formatPartition(true); + } + return Promise.resolve(false); + }).then(result => { + if (result === false) { + return Promise.resolve(false); + } else { + return Promise.resolve(true); + } + }).catch(ex => { + log("_formatIfOemUnlockEnabled: An error ocurred!. ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Formats the persistent data partition with the proper structure. + * + * @param isSetOemUnlockEnabled {bool} If true, writes a "1" in the OEM Unlock Enabled field (last + * byte of the block). If false, writes a "0". + * + * @return Promise + */ + _formatPartition: function(isSetOemUnlockEnabled) { + debug("_formatPartition()"); + let partition; + return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}).then(_partition => { + partition = _partition; + return partition.write(new Uint8Array(DIGEST_SIZE_BYTES)); + }).then(bytesWrittenLength => { + if (bytesWrittenLength != DIGEST_SIZE_BYTES) { + log("_formatPartition Error writting zero-digest!. Expected: " + DIGEST_SIZE_BYTES + " Written: " + bytesWrittenLength); + return Promise.reject(); + } + return partition.write(new Uint32Array([PARTITION_MAGIC])); + }).then(bytesWrittenLength => { + if (bytesWrittenLength != PARTITION_MAGIC_SIZE_BYTES) { + log("_formatPartition Error writting magic number!. Expected: " + PARTITION_MAGIC_SIZE_BYTES + " Written: " + bytesWrittenLength); + return Promise.reject(); + } + return partition.write(new Uint8Array(DATA_SIZE_BYTES)); + }).then(bytesWrittenLength => { + if (bytesWrittenLength != DATA_SIZE_BYTES) { + log("_formatPartition Error writting data size!. Expected: " + DATA_SIZE_BYTES + " Written: " + bytesWrittenLength); + return Promise.reject(); + } + return partition.close(); + }).then(() => { + return this._doSetOemUnlockEnabled(isSetOemUnlockEnabled); + }).then(() => { + return this._computeAndWriteDigest(); + }).then(() => { + return Promise.resolve(); + }).catch(ex => { + log("_formatPartition: Failed to format block device!: ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Check digest validity. If it's not valid, formats the persistent partition + * + * @return true Promise The checksum is valid so the promise is resolved to true + * @return false Promise The checksum is not valid, so the partition is going to be + * formatted and the OEM Unlock Enabled field written to 0 (false). + */ + _enforceChecksumValidity: function() { + debug("_enforceChecksumValidity"); + return this._computeDigest(true).then(digest => { + if (digest.stored != digest.calculated) { + log("_enforceChecksumValidity: Validation failed! Stored digest: " + toHexString(digest.stored) + + " is not the same as the calculated one: " + toHexString(digest.calculated)); + return Promise.reject(); + } + debug("_enforceChecksumValidity: Digest computation succeed."); + return Promise.resolve(true); + }).catch(ex => { + log("_enforceChecksumValidity: Digest computation failed: ex = " + ex); + log("_enforceChecksumValidity: Formatting FRP partition..."); + return this._formatPartition(false).then(() => { + return Promise.resolve(false); + }).catch(ex => { + log("_enforceChecksumValidity: Error ocurred while formating the partition!: ex = " + ex); + return Promise.reject(ex); + }); + }); + }, + + /** + * Reads the entire data field + * + * @return bytes Promise A promise resolved with the bytes read + */ + read: function() { + debug("read()"); + let partition; + let bytes; + let dataSize; + return this.getDataFieldSize().then(_dataSize => { + dataSize = _dataSize; + return OS.File.open(this._dataBlockFile, {read:true, existing:true, append:false}); + }).then(_partition => { + partition = _partition; + return partition.setPosition(DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES, OS.File.POS_START); + }).then(() => { + return partition.read(dataSize); + }).then(_bytes => { + bytes = _bytes; + if (bytes.byteLength < dataSize) { + log("read: Failed to read entire data block. Bytes read: " + bytes.byteLength + "/" + dataSize); + return Promise.reject(); + } + return partition.close(); + }).then(() => { + return Promise.resolve(bytes); + }).catch(ex => { + log("read: Failed to read entire data block. Exception: " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Writes an entire block to the persistent partition + * + * @param data {Uint8Array} + * + * @return Promise Promise resolved to the number of bytes written. + */ + write: function(data) { + debug("write()"); + // Ensure that we don't overwrite digest/magic/data-length and the last byte + let maxBlockSize = this._getBlockDeviceSize() - (DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES + 1); + if (data.byteLength > maxBlockSize) { + log("write: Couldn't write more than " + maxBlockSize + " bytes to the partition. " + + maxBlockSize + " bytes given."); + return Promise.reject(); + } + + let partition; + return OS.File.open(this._dataBlockFile, {write:true, existing:true, append:false}).then(_partition => { + let digest = new Uint8Array(DIGEST_SIZE_BYTES); + let magic = new Uint8Array((new Uint32Array([PARTITION_MAGIC])).buffer); + let dataLength = new Uint8Array((new Uint32Array([data.byteLength])).buffer); + let bufferToWrite = new Uint8Array(digest.byteLength + magic.byteLength + dataLength.byteLength + data.byteLength ); + let offset = 0; + bufferToWrite.set(digest, offset); + offset += digest.byteLength; + bufferToWrite.set(magic, offset); + offset += magic.byteLength; + bufferToWrite.set(dataLength, offset); + offset += dataLength.byteLength; + bufferToWrite.set(data, offset); + partition = _partition; + return partition.write(bufferToWrite); + }).then(bytesWrittenLength => { + let expectedWrittenLength = DIGEST_SIZE_BYTES + HEADER_SIZE_BYTES + data.byteLength; + if (bytesWrittenLength != expectedWrittenLength) { + log("write: Error writting data to partition!: Expected: " + expectedWrittenLength + " Written: " + bytesWrittenLength); + return Promise.reject(); + } + return partition.close(); + }).then(() => { + return this._computeAndWriteDigest(); + }).then(couldComputeAndWriteDigest => { + if (couldComputeAndWriteDigest === true) { + return Promise.resolve(data.byteLength); + } else { + log("write: Failed to compute and write the digest"); + return Promise.reject(); + } + }).catch(ex => { + log("write: Failed to write to the persistent partition: ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Wipes the persistent partition. + * + * @return Promise If no errors, the promise is resolved + */ + wipe: function() { + debug("wipe()"); + + if (this._testing === true) { + log("wipe: No wipe() funcionality in testing mode"); + return Promise.resolve(); + } + +#ifdef MOZ_WIDGET_GONK + const O_READONLY = 0; + const O_RDWR = 2; + const O_NONBLOCK = 1 << 11; + // This constant value is the same under 32 and 64 bits arch. + const BLKSECDISCARD = 0x127D; + // This constant value is the same under 32 and 64 bits arch. + const BLKDISCARD = 0x1277; + + return new Promise((resolve, reject) => { + let range = new this.ctypes.unsigned_long(); + let rangeAddress = range.address(); + let blockDeviceLength = this._getBlockDeviceSize(); + range[0] = 0; + range[1] = blockDeviceLength; + if (range[1] === 0) { + log("wipe: Block device size is 0!"); + return reject(); + } + let fd = this._libc.open(this._dataBlockFile, O_RDWR); + if (fd < 0) { + log("wipe: ERROR couldn't open partition!: error = " + this.ctypes.errno); + return reject(); + } + let ret = this._libc.ioctl(fd, BLKSECDISCARD, rangeAddress); + if (ret < 0) { + log("wipe: Something went wrong secure discarding block: errno: " + this.ctypes.errno + ": Falling back to non-secure discarding..."); + ret = this._libc.ioctl(fd, BLKDISCARD, rangeAddress); + if (ret < 0) { + this._libc.close(fd); + log("wipe: CRITICAL: non-secure discarding failed too!!: errno: " + this.ctypes.errno); + return reject(); + } else { + this._libc.close(fd); + log("wipe: non-secure discard used and succeed"); + return resolve(); + } + } + this._libc.close(fd); + log("wipe: secure discard succeed"); + return resolve(); + }); +#else + log("wipe: ERROR: This feature is only supported in Gonk!"); + return Promise.reject(); +#endif + }, + + /** + * Set the OEM Unlock Enabled field (one byte at the end of the partition), to 1 or 0 depending on + * the input parameter. + * + * @param enabled {bool} If enabled, we write a 1 in the last byte of the partition. + * + * @return Promise + * + */ + setOemUnlockEnabled: function(enabled) { + debug("setOemUnlockEnabled()"); + return this._doSetOemUnlockEnabled(enabled).then(() => { + return this._computeAndWriteDigest(); + }).then(() => { + return Promise.resolve(); + }).catch(ex => { + return Promise.reject(ex); + }); + }, + + /** + * Gets the byte from the partition which represents the OEM Unlock Enabled state. + * + * @return true Promise The user didn't activate KillSwitch. + * @return false Promise The user did activate KillSwitch. + */ + getOemUnlockEnabled: function() { + log("getOemUnlockEnabled()"); + let ret = false; + let partition; + return OS.File.open(this._dataBlockFile, {existing:true, append:false, read:true}).then(_partition => { + partition = _partition; + return partition.setPosition(this._getBlockDeviceSize() - OEM_UNLOCK_ENABLED_BYTES, OS.File.POS_START); + }).then(() => { + return partition.read(OEM_UNLOCK_ENABLED_BYTES); + }).then(data => { + debug("getOemUnlockEnabled: OEM unlock enabled byte = '" + data[0] + "'"); + ret = (data[0] === 1 ? true : false); + return partition.close(); + }).then(() => { + return Promise.resolve(ret); + }).catch(ex => { + log("getOemUnlockEnabled: Error reading OEM unlock enabled byte from partition: ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Gets the size of the data block by reading the data-length field + * + * @return Promise A promise resolved to the number of bytes os the data field. + */ + getDataFieldSize: function() { + debug("getDataFieldSize()"); + let partition + let dataLength = 0; + return OS.File.open(this._dataBlockFile, {read:true, existing:true, append:false}).then(_partition => { + partition = _partition; + // Skip the digest field + return partition.setPosition(DIGEST_SIZE_BYTES, OS.File.POS_START); + }).then(() => { + // Read the Magic field + return partition.read(PARTITION_MAGIC_SIZE_BYTES); + }).then(_magic => { + let magic = new Uint32Array(_magic.buffer)[0]; + if (magic === PARTITION_MAGIC) { + return partition.read(PARTITION_MAGIC_SIZE_BYTES); + } else { + log("getDataFieldSize: ERROR: Invalid Magic number!"); + return Promise.reject(); + } + }).then(_dataLength => { + if (_dataLength) { + dataLength = new Uint32Array(_dataLength.buffer)[0]; + } + return partition.close(); + }).then(() => { + if (dataLength && dataLength != 0) { + return Promise.resolve(dataLength); + } else { + return Promise.reject(); + } + }).catch(ex => { + log("getDataFieldSize: Couldn't get data field size: ex = " + ex); + return Promise.reject(ex); + }); + }, + + /** + * Gets the maximum possible size of a data field + * + * @return Promise A Promise resolved to the maximum number of bytes allowed for the data field + * + */ + getMaximumDataBlockSize: function() { + debug("getMaximumDataBlockSize()"); + return new Promise((resolve, reject) => { + let actualSize = this._getBlockDeviceSize() - HEADER_SIZE_BYTES - OEM_UNLOCK_ENABLED_BYTES; + resolve(actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE); + }); + } + +}; + +// This code should ALWAYS be living only on the parent side. +if (!inParent) { + log("PersistentDataBlock should only be living on parent side."); + throw Cr.NS_ERROR_ABORT; +} else { + this.PersistentDataBlock.init(); +} diff --git a/b2g/components/moz.build b/b2g/components/moz.build index 31d7982aba2..288efcc3666 100644 --- a/b2g/components/moz.build +++ b/b2g/components/moz.build @@ -78,6 +78,10 @@ EXTRA_JS_MODULES += [ 'WebappsUpdater.jsm', ] +EXTRA_PP_JS_MODULES += [ + 'PersistentDataBlock.jsm' +] + if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': EXTRA_JS_MODULES += [ 'GlobalSimulatorScreen.jsm' diff --git a/b2g/components/test/unit/file_persistentdatablock.js b/b2g/components/test/unit/file_persistentdatablock.js new file mode 100644 index 00000000000..de913c3ef8e --- /dev/null +++ b/b2g/components/test/unit/file_persistentdatablock.js @@ -0,0 +1,412 @@ +/* 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/. */ + +"use strict"; + +var {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); +// This constants must be synced with the ones in PersistentDataBlock.jsm +const PARTITION_MAGIC = 0x19901873; +const DIGEST_SIZE_BYTES = 32; +const PARTITION_MAGIC_SIZE_BYTES = 4; +const DATA_SIZE_BYTES = 4; +const OEM_UNLOCK_ENABLED_BYTES = 1; + +const CACHE_PARTITION = "/dev/block/mtdblock2"; +const PARTITION_FAKE_FILE = "/data/local/tmp/frp.test"; +const CACHE_PARTITION_SIZE = 69206016; + +function log(str) { + do_print("head_persistentdatablock: " + str + "\n"); +} + +function toHexString(data) { + function toHexChar(charCode) { + return ("0" + charCode.toString(16).slice(-2)); + } + let hexString = ""; + if (typeof data === "string") { + hexString = [toHexChar(data.charCodeAt(i)) for (i in data)].join(""); + } else if (typeof data === "array") { + hexString = [toHexChar(data[i]) for (i in data)].join(""); + } + return hexString; +} + +function _prepareConfig(_args) { + let args = _args || {}; + // This digest has been previously calculated given the data to be written later, and setting the OEM Unlocked Enabled byte + // to 1. If we need different values, some tests will fail because this precalculated digest won't be valid then. + args.digest = args.digest || new Uint8Array([0x00, 0x41, 0x7e, 0x5f, 0xe2, 0xdd, 0xaa, 0xed, 0x11, 0x90, 0x0e, 0x1d, 0x26, + 0x10, 0x30, 0xbd, 0x44, 0x9e, 0xcc, 0x4b, 0x65, 0xbe, 0x2e, 0x99, 0x9f, 0x86, + 0xf0, 0xfc, 0x5b, 0x33, 0x00, 0xd0]); + args.dataLength = args.dataLength || 6; + args.data = args.data || new Uint8Array(["P", "A", "S", "S", "W", "D"]); + args.oem = args.oem === undefined ? true : args.oem; + args.oemUnlockAllowed = args.oemUnlockAllowed === undefined ? true : args.oemUnlockAllowed; + + log("_prepareConfig: args.digest = " + args.digest); + log("_prepareConfig: args.dataLength = " + args.dataLength); + log("_prepareConfig: args.data = " + args.data); + log("_prepareConfig: args.oem = " + args.oem); + log("_prepareConfig: args.oemUnlockAllowed = " + args.oemUnlockAllowed); + + /* This function will be called after passing all native stuff tests, so we will write into a file instead of a real + * partition. Obviously, there are some native operations like getting the device block size or wipping, that will not + * work in a regular file, so we need to fake them. */ + PersistentDataBlock._libcutils.property_set("sys.oem_unlock_allowed", args.oemUnlockAllowed === true ? "true" : "false"); + PersistentDataBlock.setTestingMode(true); + PersistentDataBlock._dataBlockFile = PARTITION_FAKE_FILE; + // Create the test file with the same structure as the partition will be + let tempFile; + return OS.File.open(PersistentDataBlock._dataBlockFile, {write:true, append:false, truncate: true}).then(_tempFile => { + log("_prepareConfig: Writing DIGEST..."); + tempFile = _tempFile; + return tempFile.write(args.digest); + }).then(bytes => { + log("_prepareConfig: Writing the magic: " + PARTITION_MAGIC); + return tempFile.write(new Uint32Array([PARTITION_MAGIC])); + }).then(bytes => { + log("_prepareConfig: Writing the length of data field"); + return tempFile.write(new Uint32Array([args.dataLength])); + }).then(bytes => { + log("_prepareConfig: Writing the data field"); + let data = new Uint8Array(PersistentDataBlock._getBlockDeviceSize() - + (DIGEST_SIZE_BYTES + PARTITION_MAGIC_SIZE_BYTES + DATA_SIZE_BYTES + OEM_UNLOCK_ENABLED_BYTES)); + data.set(args.data); + return tempFile.write(data); + }).then(bytes => { + return tempFile.write(new Uint8Array([ args.oem === true ? 1 : 0 ])); + }).then(bytes => { + return tempFile.close(); + }).then(() =>{ + return Promise.resolve(true); + }).catch(ex => { + log("_prepareConfig: ERROR: ex = " + ex); + return Promise.reject(ex); + }); +} + +function utils_getByteAt(pos) { + let file; + let byte; + return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { + file = _file; + return file.setPosition(pos, OS.File.POS_START); + }).then(() => { + return file.read(1); + }).then(_byte => { + byte = _byte; + return file.close(); + }).then(() => { + return Promise.resolve(byte[0]); + }).catch(ex => { + return Promise.reject(ex); + }); +} + +function utils_getHeader() { + let file; + let header = {}; + return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { + file = _file; + return file.read(DIGEST_SIZE_BYTES); + }).then(digest => { + header.digest = digest; + return file.read(PARTITION_MAGIC_SIZE_BYTES); + }).then(magic => { + header.magic = magic; + return file.read(DATA_SIZE_BYTES); + }).then(dataLength => { + header.dataLength = dataLength; + return file.close(); + }).then(() => { + return Promise.resolve(header); + }).catch(ex => { + return Promise.reject(ex); + }); +} + +function utils_getData() { + let file; + let data; + return OS.File.open(PersistentDataBlock._dataBlockFile, {read:true, existing:true, append:false}).then(_file => { + file = _file; + return file.setPosition(DIGEST_SIZE_BYTES + PARTITION_MAGIC_SIZE_BYTES, OS.File.POS_START); + }).then(() => { + return file.read(4); + }).then(_dataLength => { + let dataLength = new Uint32Array(_dataLength.buffer); + log("utils_getData: dataLength = " + dataLength[0]); + return file.read(dataLength[0]); + }).then(_data => { + data = _data; + return file.close(); + }).then(() => { + return Promise.resolve(data); + }).catch(ex => { + return Promise.reject(ex); + }); +} + +function _installTests() { + // Native operation tests go first + add_test(function test_getBlockDeviceSize() { + // We will use emulator /cache partition to get it's size. + PersistentDataBlock._dataBlockFile = CACHE_PARTITION; + // Disable testing mode for this specific test because we can get the size of a real block device, + // but we need to flip to testing mode after this test because we use files instead of partitions + // and we cannot run this operation on files. + PersistentDataBlock.setTestingMode(false); + let blockSize = PersistentDataBlock._getBlockDeviceSize(); + ok(blockSize !== CACHE_PARTITION_SIZE, "test_getBlockDeviceSize: Block device size should be greater than 0"); + run_next_test(); + }); + + add_test(function test_wipe() { + // Turning into testing mode again. + PersistentDataBlock.setTestingMode(true); + PersistentDataBlock.wipe().then(() => { + // We don't evaluate anything because in testing mode we always return ok! + run_next_test(); + }).catch(ex => { + // ... something went really really bad if this happens. + ok(false, "test_wipe failed!: ex: " + ex); + }); + }); + // + + add_test(function test_computeDigest() { + _prepareConfig().then(() => { + PersistentDataBlock._computeDigest().then(digest => { + // So in order to update this value in a future (should only happens if the partition data is changed), you just need + // to launch this test manually, see the result in the logs and update this constant with that value. + const _EXPECTED_VALUE = "0004107e05f0e20dd0aa0ed0110900e01d0260100300bd04409e0cc04b0650be02e09909f0860f00fc05b033000d0"; + let calculatedValue = toHexString(digest.calculated); + strictEqual(calculatedValue, _EXPECTED_VALUE); + run_next_test(); + }).catch(ex => { + ok(false, "test_computeDigest failed!: ex: " + ex); + }); + }); + }); + + add_test(function test_getDataFieldSize() { + PersistentDataBlock.getDataFieldSize().then(dataFieldLength => { + log("test_getDataFieldSize: dataFieldLength is " + dataFieldLength); + strictEqual(dataFieldLength, 6); + run_next_test(); + }).catch(ex => { + ok(false, "test_getOemUnlockedEnabled failed: ex:" + ex); + }); + }); + + add_test(function test_setOemUnlockedEnabledToTrue() { + PersistentDataBlock.setOemUnlockEnabled(true).then(() => { + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + log("test_setOemUnlockedEnabledToTrue: byte = " + byte ); + strictEqual(byte, 1); + run_next_test(); + }).catch(ex => { + ok(false, "test_setOemUnlockedEnabledToTrue failed!: ex: " + ex); + }); + }); + + add_test(function test_setOemUnlockedEnabledToFalse() { + PersistentDataBlock.setOemUnlockEnabled(false).then(() => { + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + log("test_setOemUnlockedEnabledToFalse: byte = " + byte ); + strictEqual(byte, 0); + run_next_test(); + }).catch(ex => { + ok(false, "test_setOemUnlockedEnabledToFalse failed!: ex: " + ex); + }); + }); + + add_test(function test_getOemUnlockedEnabledWithTrue() { + // We first need to set the OEM Unlock Enabled byte to true so we can test + // the getter properly + PersistentDataBlock.setOemUnlockEnabled(true).then(() => { + return PersistentDataBlock.getOemUnlockEnabled().then(enabled => { + log("test_getOemUnlockedEnabledWithTrue: enabled is " + enabled); + ok(enabled === true, "test_getOemUnlockedEnabledWithTrue: enabled value should be true"); + run_next_test(); + }).catch(ex => { + ok(false, "test_getOemUnlockedEnabledWithTrue failed: ex:" + ex); + }); + }).catch(ex => { + ok(false, "test_getOemUnlockedEnabledWithTrue failed: An error ocurred while setting the OEM Unlock Enabled byte to true: ex:" + ex); + }); + }); + + add_test(function test_getOemUnlockedEnabledWithFalse() { + // We first need to set the OEM Unlock Enabled byte to false so we can test + // the getter properly + PersistentDataBlock.setOemUnlockEnabled(false).then(() => { + return PersistentDataBlock.getOemUnlockEnabled().then(enabled => { + log("test_getOemUnlockedEnabledWithFalse: enabled is " + enabled); + ok(enabled === false, "test_getOemUnlockedEnabledWithFalse: enabled value should be false"); + run_next_test(); + }).catch(ex => { + ok(false, "test_getOemUnlockedEnabledWithFalse failed: ex:" + ex); + }); + }).catch(ex => { + ok(false, "test_getOemUnlockedEnabledWithFalse failed: An error ocurred while setting the OEM Unlock Enabled byte to false: ex:" + ex); + }); + }); + + add_test(function test_computeAndWriteDigest() { + PersistentDataBlock._computeAndWriteDigest().then(() => { + return utils_getHeader(); + }).then(header => { + log("test_computeAndWriteDigest: header = " + header); + let magicRead = new Uint32Array(header.magic.buffer); + let magicSupposed = new Uint32Array([PARTITION_MAGIC]); + strictEqual(magicRead[0], magicSupposed[0]); + let dataLength = new Uint32Array([header.dataLength]); + strictEqual(header.dataLength[0], 6); + run_next_test(); + }).catch(ex => { + ok(false, "test_computeAndWriteDigest failed!: ex: " + ex); + }); + }); + + add_test(function test_formatIfOemUnlockEnabledWithTrue() { + _prepareConfig({oem:true}).then(() => { + return PersistentDataBlock._formatIfOemUnlockEnabled(); + }).then(result => { + ok(result === true, "test_formatIfOemUnlockEnabledWithTrue: result should be true"); + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + // Check if the OEM Unlock Enabled byte is 1 + strictEqual(byte, 1); + run_next_test(); + }).catch(ex => { + ok(false, "test_formatIfOemUnlockEnabledWithTrue failed!: ex: " + ex); + }); + }); + + add_test(function test_formatIfOemUnlockEnabledWithFalse() { + _prepareConfig({oem:false}).then(() => { + return PersistentDataBlock._formatIfOemUnlockEnabled(); + }).then(result => { + log("test_formatIfOemUnlockEnabledWithFalse: result = " + result); + ok(result === false, "test_formatIfOemUnlockEnabledWithFalse: result should be false"); + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + // Check if the OEM Unlock Enabled byte is 0 + strictEqual(byte, 0); + run_next_test(); + }).catch(ex => { + ok(false, "test_formatIfOemUnlockEnabledWithFalse failed!: ex: " + ex); + }); + }); + + add_test(function test_formatPartition() { + // Restore a fullfilled partition so we can check if formatting works... + _prepareConfig({oem:true}).then(() => { + return PersistentDataBlock._formatPartition(true); + }).then(() => { + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + // Check if the last byte is 1 + strictEqual(byte, 1); + return utils_getHeader(); + }).then(header => { + // The Magic number should exists in a formatted partition + let magicRead = new Uint32Array(header.magic.buffer); + let magicSupposed = new Uint32Array([PARTITION_MAGIC]); + strictEqual(magicRead[0], magicSupposed[0]); + // In a formatted partition, the digest field is always 32 bytes of zeros. + let digestSupposed = new Uint8Array(DIGEST_SIZE_BYTES); + strictEqual(header.digest.join(""), "94227253995810864198417798821014713171138121254110134189198178208133167236184116199"); + return PersistentDataBlock._formatPartition(false); + }).then(() => { + return utils_getByteAt(PersistentDataBlock._getBlockDeviceSize() - 1); + }).then(byte => { + // In this case OEM Unlock enabled byte should be set to 0 because we passed false to the _formatPartition method before. + strictEqual(byte, 0); + run_next_test(); + }).catch(ex => { + ok(false, "test_formatPartition failed!: ex: " + ex); + }); + }); + + add_test(function test_enforceChecksumValidityWithValidChecksum() { + // We need a valid partition layout to pass this test + _prepareConfig().then(() => { + PersistentDataBlock._enforceChecksumValidity().then(() => { + ok(true, "test_enforceChecksumValidityWithValidChecksum passed"); + run_next_test(); + }).catch(ex => { + ok(false, "test_enforceChecksumValidityWithValidChecksum failed!: ex: " + ex); + }); + }); + }); + + add_test(function test_enforceChecksumValidityWithInvalidChecksum() { + var badDigest = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, 0x20]); + // We need a valid partition layout to pass this test + _prepareConfig({digest: badDigest}).then(() => { + PersistentDataBlock._enforceChecksumValidity().then(() => { + return utils_getHeader(); + }).then(header => { + // Check that we have a valid magic after formatting + let magicRead = new Uint32Array(header.magic.buffer)[0]; + let magicSupposed = new Uint32Array([PARTITION_MAGIC])[0]; + strictEqual(magicRead, magicSupposed); + // Data length field should be 0, because we formatted the partition + let dataLengthRead = new Uint32Array(header.dataLength.buffer)[0]; + strictEqual(dataLengthRead, 0); + run_next_test(); + }).catch(ex => { + ok(false, "test_enforceChecksumValidityWithValidChecksum failed!: ex: " + ex); + }); + }); + }); + + add_test(function test_read() { + // Before reading, let's write some bytes of data first. + PersistentDataBlock.write(new Uint8Array([1,2,3,4])).then(() => { + PersistentDataBlock.read().then(bytes => { + log("test_read: bytes (in hex): " + toHexString(bytes)); + strictEqual(bytes[0], 1); + strictEqual(bytes[1], 2); + strictEqual(bytes[2], 3); + strictEqual(bytes[3], 4); + run_next_test(); + }).catch(ex => { + ok(false, "test_read failed!: ex: " + ex); + }); + }); + + }); + + add_test(function test_write() { + let data = new Uint8Array(['1','2','3','4','5']); + PersistentDataBlock.write(data).then(bytesWrittenLength => { + log("test_write: bytesWrittenLength = " + bytesWrittenLength); + return utils_getData(); + }).then(data => { + strictEqual(data[0], 1); + strictEqual(data[1], 2); + strictEqual(data[2], 3); + strictEqual(data[3], 4); + strictEqual(data[4], 5); + run_next_test(); + }).catch(ex => { + ok(false, "test_write failed!: ex: " + ex); + }); + }); +} diff --git a/b2g/components/test/unit/test_persistentdatablock_gonk.js b/b2g/components/test/unit/test_persistentdatablock_gonk.js new file mode 100644 index 00000000000..067eb83e334 --- /dev/null +++ b/b2g/components/test/unit/test_persistentdatablock_gonk.js @@ -0,0 +1,21 @@ +/* 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/. */ + +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "libcutils", function () { + Cu.import("resource://gre/modules/systemlibs.js"); + return libcutils; +}); + +function run_test() { + do_get_profile(); + Cu.import("resource://gre/modules/PersistentDataBlock.jsm"); + // We need to point to a valid partition for some of the tests. This is the /cache + // partition in the emulator (x86-KitaKat). + run_next_test(); +} + +_installTests(); diff --git a/b2g/components/test/unit/xpcshell.ini b/b2g/components/test/unit/xpcshell.ini index 9897ac072ac..35b6261f276 100644 --- a/b2g/components/test/unit/xpcshell.ini +++ b/b2g/components/test/unit/xpcshell.ini @@ -50,3 +50,9 @@ skip-if = (toolkit == "gonk") head = file_killswitch.js # Bug 1193677: disable on B2G ICS Emulator for intermittent failures with IndexedDB skip-if = ((toolkit != "gonk") || (toolkit == "gonk" && debug)) + +[test_persistentdatablock_gonk.js] +head = file_persistentdatablock.js +skip-if = (toolkit != "gonk") + + diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index 4a91bfebec1..7d01fc4364a 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index fcd1bd8c216..2d0305461d4 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 6ab4dd959df..e3d5b2d2cd5 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index ba670368af0..e98721d6cda 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 88c0ab8a827..6309324a097 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 3830796e423..edf30de9133 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 6ab4dd959df..e3d5b2d2cd5 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 6f133957e8b..6873119be87 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 14fa25ae5da..6eb766fdf8e 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "14aefb2519becfa32f31bcc3c9c995693421f19c", + "git_revision": "f3cf488a97ecaec43369f3e3d8a7dda52be019f9", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "e384f9eb4a149302c38df25a4aa772ddd1415f7e", + "revision": "295225a48cf2607651e83cdcda92a57516f1509e", "repo_path": "integration/gaia-central" } diff --git a/b2g/config/nexus-4-kk/sources.xml b/b2g/config/nexus-4-kk/sources.xml index 51d11c8fecc..947c7cd3bcb 100644 --- a/b2g/config/nexus-4-kk/sources.xml +++ b/b2g/config/nexus-4-kk/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2f2bb1eb731..5b65070dda4 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 68dccbeda9e..9d7e68ad178 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index a89041e9b04..cb60461a04c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4752,7 +4752,7 @@ var CombinedStopReload = { var TabsProgressListener = { onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { // Collect telemetry data about tab load times. - if (aWebProgress.isTopLevel) { + if (aWebProgress.isTopLevel && (!aRequest.originalURI || aRequest.originalURI.spec.scheme != "about")) { if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) { if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) { TelemetryStopwatch.start("FX_PAGE_LOAD_MS", aBrowser); diff --git a/browser/base/content/test/popupNotifications/browser.ini b/browser/base/content/test/popupNotifications/browser.ini index 8ddee59be4f..6003781fad3 100644 --- a/browser/base/content/test/popupNotifications/browser.ini +++ b/browser/base/content/test/popupNotifications/browser.ini @@ -5,10 +5,10 @@ support-files = [browser_displayURI.js] skip-if = (os == "linux" && (debug || asan)) [browser_popupNotification.js] -skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc +skip-if = (os == "linux" && (debug || asan)) [browser_popupNotification_2.js] -skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc +skip-if = (os == "linux" && (debug || asan)) [browser_popupNotification_3.js] -skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc +skip-if = (os == "linux" && (debug || asan)) [browser_popupNotification_4.js] -skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc +skip-if = (os == "linux" && (debug || asan)) diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 003a42e1c11..ba802dc0785 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -552,6 +552,9 @@ @RESPATH@/components/SlowScriptDebug.manifest @RESPATH@/components/SlowScriptDebug.js +@RESPATH@/components/TVSimulatorService.js +@RESPATH@/components/TVSimulatorService.manifest + #ifndef RELEASE_BUILD @RESPATH@/components/InterAppComm.manifest @RESPATH@/components/InterAppCommService.js diff --git a/browser/modules/BrowserUITelemetry.jsm b/browser/modules/BrowserUITelemetry.jsm index 0fca7117516..b1077f6b874 100644 --- a/browser/modules/BrowserUITelemetry.jsm +++ b/browser/modules/BrowserUITelemetry.jsm @@ -535,7 +535,7 @@ this.BrowserUITelemetry = { let paletteItems = CustomizableUI.getUnusedWidgets(aWindow.gNavToolbox.palette); let defaultRemoved = []; - for (item of paletteItems) { + for (let item of paletteItems) { if (DEFAULT_ITEMS.indexOf(item.id) != -1) { defaultRemoved.push(item.id); } diff --git a/config/external/moz.build b/config/external/moz.build index 769a33d4760..17a3057df04 100644 --- a/config/external/moz.build +++ b/config/external/moz.build @@ -26,13 +26,10 @@ if CONFIG['MOZ_VORBIS']: if CONFIG['MOZ_TREMOR']: external_dirs += ['media/libtremor'] -if CONFIG['MOZ_WEBM']: - external_dirs += ['media/libnestegg'] - if CONFIG['MOZ_WEBM_ENCODER']: external_dirs += ['media/libmkv'] -if CONFIG['MOZ_VPX'] and not CONFIG['MOZ_NATIVE_LIBVPX']: +if not CONFIG['MOZ_NATIVE_LIBVPX']: external_dirs += ['media/libvpx'] if not CONFIG['MOZ_NATIVE_PNG']: @@ -50,6 +47,7 @@ if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']: external_dirs += [ 'media/kiss_fft', 'media/libcubeb', + 'media/libnestegg', 'media/libogg', 'media/libopus', 'media/libtheora', diff --git a/configure.in b/configure.in index c8cc10b1e9c..583ce8384fd 100644 --- a/configure.in +++ b/configure.in @@ -92,8 +92,8 @@ _PTHREAD_LDFLAGS="" dnl Do not allow objdir == srcdir builds. dnl ============================================================== -_topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd` -_objdir=`pwd` +_topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd -P` +_objdir=`pwd -P` dnl TODO Don't exempt L10N builds once bug 842760 is resolved. if test "$_topsrcdir" = "$_objdir" -a "${with_l10n_base+set}" != set; then @@ -134,7 +134,7 @@ EOF exit 1 break fi -MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd` +MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P` DIST="$MOZ_BUILD_ROOT/dist" MOZ_PYTHON @@ -157,7 +157,7 @@ if test -n "$L10NBASEDIR"; then if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then AC_MSG_ERROR([--with-l10n-base must specify a path]) elif test -d "$L10NBASEDIR"; then - L10NBASEDIR=`cd "$L10NBASEDIR" && pwd` + L10NBASEDIR=`cd "$L10NBASEDIR" && pwd -P` else AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist]) fi @@ -3692,10 +3692,8 @@ fi MOZ_RAW= MOZ_VORBIS= MOZ_TREMOR= -MOZ_WAVE=1 MOZ_SAMPLE_TYPE_FLOAT32= MOZ_SAMPLE_TYPE_S16= -MOZ_WEBM=1 MOZ_GSTREAMER= MOZ_DIRECTSHOW= MOZ_WMF= @@ -3715,7 +3713,6 @@ MOZ_SCTP= MOZ_ANDROID_OMX= MOZ_MEDIA_NAVIGATOR= MOZ_OMX_PLUGIN= -MOZ_VPX= MOZ_VPX_ERROR_CONCEALMENT= MOZ_WEBSPEECH=1 MOZ_WEBSPEECH_MODELS= @@ -4998,7 +4995,6 @@ if test -n "$MOZ_WEBRTC"; then dnl opt/production builds (via MOZ_CRASH()) AC_DEFINE(MOZ_WEBRTC_ASSERT_ALWAYS) MOZ_RAW=1 - MOZ_VPX=1 MOZ_VPX_ERROR_CONCEALMENT=1 dnl enable once Signaling lands @@ -5143,19 +5139,6 @@ if test "${ac_cv_c_attribute_aligned}" != "0"; then [${ac_cv_c_attribute_aligned}],[Maximum supported data alignment]) fi -dnl ======================================================== -dnl = Disable VP8 decoder support -dnl ======================================================== -MOZ_ARG_DISABLE_BOOL(webm, -[ --disable-webm Disable support for WebM media (VP8 video and Vorbis audio)], - MOZ_WEBM=, - MOZ_WEBM=1) - -if test -n "$MOZ_WEBM"; then - AC_DEFINE(MOZ_WEBM) - MOZ_VPX=1 -fi; - dnl ======================================================== dnl = Apple platform decoder support dnl ======================================================== @@ -5361,54 +5344,49 @@ MOZ_ARG_WITH_BOOL(system-libvpx, MOZ_LIBVPX_CFLAGS= MOZ_LIBVPX_LIBS= -if test -n "$MOZ_VPX"; then - AC_DEFINE(MOZ_VPX) - if test -n "$MOZ_VPX_ERROR_CONCEALMENT" ; then - AC_DEFINE(MOZ_VPX_ERROR_CONCEALMENT) - fi - - _SAVE_CFLAGS=$CFLAGS - _SAVE_LIBS=$LIBS - if test -n "$MOZ_NATIVE_LIBVPX"; then - dnl ============================ - dnl === libvpx Version check === - dnl ============================ - dnl Check to see if we have a system libvpx package. - PKG_CHECK_MODULES(MOZ_LIBVPX, vpx >= 1.3.0) - - CFLAGS="$CFLAGS $MOZ_LIBVPX_CFLAGS" - LIBS="$LIBS $MOZ_LIBVPX_LIBS" - - MOZ_CHECK_HEADER([vpx/vpx_decoder.h], [], - [AC_MSG_ERROR([Couldn't find vpx/vpx_decoder.h which is required for build with system libvpx. Use --without-system-libvpx to build with in-tree libvpx.])]) - - AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver, [], - [AC_MSG_ERROR([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found])]) - - MOZ_CHECK_HEADER([vpx_mem/vpx_mem.h], - [AC_CHECK_FUNC(vpx_mem_set_functions)]) - if test "$ac_cv_header_vpx_mem_vpx_mem_h" = no -o \ - "$ac_cv_func_vpx_mem_set_functions" = no; then - AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING) - fi - fi - CFLAGS=$_SAVE_CFLAGS - LIBS=$_SAVE_LIBS +if test -n "$MOZ_VPX_ERROR_CONCEALMENT" ; then + AC_DEFINE(MOZ_VPX_ERROR_CONCEALMENT) fi +_SAVE_CFLAGS=$CFLAGS +_SAVE_LIBS=$LIBS +if test -n "$MOZ_NATIVE_LIBVPX"; then + dnl ============================ + dnl === libvpx Version check === + dnl ============================ + dnl Check to see if we have a system libvpx package. + PKG_CHECK_MODULES(MOZ_LIBVPX, vpx >= 1.3.0) + + CFLAGS="$CFLAGS $MOZ_LIBVPX_CFLAGS" + LIBS="$LIBS $MOZ_LIBVPX_LIBS" + + MOZ_CHECK_HEADER([vpx/vpx_decoder.h], [], + [AC_MSG_ERROR([Couldn't find vpx/vpx_decoder.h which is required for build with system libvpx. Use --without-system-libvpx to build with in-tree libvpx.])]) + + AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver, [], + [AC_MSG_ERROR([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found])]) + + MOZ_CHECK_HEADER([vpx_mem/vpx_mem.h], + [AC_CHECK_FUNC(vpx_mem_set_functions)]) + if test "$ac_cv_header_vpx_mem_vpx_mem_h" = no -o \ + "$ac_cv_func_vpx_mem_set_functions" = no; then + AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING) + fi +fi +CFLAGS=$_SAVE_CFLAGS +LIBS=$_SAVE_LIBS + AC_SUBST(MOZ_NATIVE_LIBVPX) AC_SUBST_LIST(MOZ_LIBVPX_CFLAGS) AC_SUBST_LIST(MOZ_LIBVPX_LIBS) -if test "$MOZ_WEBM"; then - if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then - MOZ_VORBIS=1 - else - MOZ_TREMOR=1 - fi +if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then + MOZ_VORBIS=1 +else + MOZ_TREMOR=1 fi -if test -n "$MOZ_VPX" -a -z "$MOZ_NATIVE_LIBVPX"; then +if test -z "$MOZ_NATIVE_LIBVPX"; then dnl Detect if we can use an assembler to compile optimized assembly for libvpx. dnl We currently require yasm on all x86 platforms and require yasm 1.1.0 on Win32. @@ -5510,18 +5488,6 @@ if test -n "$MOZ_VPX" -a -z "$MOZ_NATIVE_LIBVPX"; then AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING) fi -dnl ======================================================== -dnl = Disable Wave decoder support -dnl ======================================================== -MOZ_ARG_DISABLE_BOOL(wave, -[ --disable-wave Disable Wave decoder support], - MOZ_WAVE=, - MOZ_WAVE=1) - -if test -n "$MOZ_WAVE"; then - AC_DEFINE(MOZ_WAVE) -fi - dnl ======================================================== dnl = Handle dependent MEDIA defines dnl ======================================================== @@ -8926,10 +8892,8 @@ AC_SUBST(NS_ENABLE_TSF) AC_SUBST(WIN32_CONSOLE_EXE_LDFLAGS) AC_SUBST(WIN32_GUI_EXE_LDFLAGS) -AC_SUBST(MOZ_WAVE) AC_SUBST(MOZ_VORBIS) AC_SUBST(MOZ_TREMOR) -AC_SUBST(MOZ_WEBM) AC_SUBST(MOZ_WMF) AC_SUBST(MOZ_FFMPEG) AC_SUBST(MOZ_FMP4) @@ -8939,7 +8903,6 @@ AC_SUBST(MOZ_ANDROID_OMX) AC_SUBST(MOZ_APPLEMEDIA) AC_SUBST(MOZ_OMX_PLUGIN) AC_SUBST(MOZ_VPX_ERROR_CONCEALMENT) -AC_SUBST(MOZ_VPX) AC_SUBST(VPX_AS) AC_SUBST_LIST(VPX_ASFLAGS) AC_SUBST(VPX_AS_CONVERSION) diff --git a/devtools/server/actors/script.js b/devtools/server/actors/script.js index a9dcb46cc32..e445f0727fa 100644 --- a/devtools/server/actors/script.js +++ b/devtools/server/actors/script.js @@ -12,7 +12,7 @@ const { ActorPool, OriginalLocation, GeneratedLocation } = require("devtools/ser const { ObjectActor, createValueGrip, longStringGrip } = require("devtools/server/actors/object"); const { DebuggerServer } = require("devtools/server/main"); const DevToolsUtils = require("devtools/shared/DevToolsUtils"); -const { assert, dbg_assert, dumpn, update, fetch } = DevToolsUtils; +const { assert, dumpn, update, fetch } = DevToolsUtils; const { dirname, joinURI } = require("devtools/shared/path"); const promise = require("promise"); const PromiseDebugging = require("PromiseDebugging"); @@ -354,8 +354,6 @@ EventLoop.prototype = { } } - dbg_assert(this._thread.state === "running", "Should be in the running state"); - if (this._hooks.postNest) { this._hooks.postNest(nestData); } diff --git a/devtools/shared/DevToolsUtils.js b/devtools/shared/DevToolsUtils.js index af01b6a0c35..481fbddbcb7 100644 --- a/devtools/shared/DevToolsUtils.js +++ b/devtools/shared/DevToolsUtils.js @@ -183,8 +183,12 @@ exports.executeSoon = function executeSoon(aFn) { if (isWorker) { setImmediate(aFn); } else { + let stack = components.stack; + let executor = () => { + Cu.callFunctionWithAsyncStack(aFn, stack, "DevToolsUtils.executeSoon"); + }; Services.tm.mainThread.dispatch({ - run: exports.makeInfallible(aFn) + run: exports.makeInfallible(executor) }, Ci.nsIThread.DISPATCH_NORMAL); } }; @@ -457,24 +461,6 @@ exports.defineLazyGetter = function defineLazyGetter(aObject, aName, aLambda) { }); }; -// DEPRECATED: use DevToolsUtils.assert(condition, message) instead! -let haveLoggedDeprecationMessage = false; -exports.dbg_assert = function dbg_assert(cond, e) { - if (!haveLoggedDeprecationMessage) { - haveLoggedDeprecationMessage = true; - const deprecationMessage = "DevToolsUtils.dbg_assert is deprecated! Use DevToolsUtils.assert instead!\n" - + Error().stack; - dump(deprecationMessage); - if (typeof console === "object" && console && console.warn) { - console.warn(deprecationMessage); - } - } - - if (!cond) { - return e; - } -}; - exports.defineLazyGetter(this, "AppConstants", () => { if (isWorker) { return {}; diff --git a/devtools/shared/tests/unit/test_executeSoon.js b/devtools/shared/tests/unit/test_executeSoon.js new file mode 100644 index 00000000000..043fb3b95ab --- /dev/null +++ b/devtools/shared/tests/unit/test_executeSoon.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Client request stacks should span the entire process from before making the + * request to handling the reply from the server. The server frames are not + * included, nor can they be in most cases, since the server can be a remote + * device. + */ + +var { executeSoon } = require("devtools/shared/DevToolsUtils"); +var promise = require("promise"); +var Services = require("Services"); + +var asyncStackEnabled = + Services.prefs.getBoolPref("javascript.options.asyncstack"); + +do_register_cleanup(() => { + Services.prefs.setBoolPref("javascript.options.asyncstack", + asyncStackEnabled); +}); + +add_task(function*() { + Services.prefs.setBoolPref("javascript.options.asyncstack", true); + + yield waitForTick(); + + let stack = Components.stack; + while (stack) { + do_print(stack.name); + if (stack.name == "waitForTick") { + // Reached back to outer function before executeSoon + ok(true, "Complete stack"); + return; + } + stack = stack.asyncCaller || stack.caller; + } + ok(false, "Incomplete stack"); +}); + +function waitForTick() { + let deferred = promise.defer(); + executeSoon(deferred.resolve); + return deferred.promise; +} diff --git a/devtools/shared/tests/unit/xpcshell.ini b/devtools/shared/tests/unit/xpcshell.ini index aa3f0b20671..29d0277775f 100644 --- a/devtools/shared/tests/unit/xpcshell.ini +++ b/devtools/shared/tests/unit/xpcshell.ini @@ -24,3 +24,4 @@ support-files = [test_require_lazy.js] [test_require.js] [test_stack.js] +[test_executeSoon.js] diff --git a/dom/animation/DocumentTimeline.cpp b/dom/animation/DocumentTimeline.cpp index 3d457bab977..dc9f13302b6 100644 --- a/dom/animation/DocumentTimeline.cpp +++ b/dom/animation/DocumentTimeline.cpp @@ -110,6 +110,8 @@ void DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime) { MOZ_ASSERT(mIsObservingRefreshDriver); + MOZ_ASSERT(GetRefreshDriver(), + "Should be able to reach refresh driver from within WillRefresh"); bool needsTicks = false; nsTArray animationsToRemove(mAnimations.Count()); @@ -143,10 +145,13 @@ DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime) } if (!needsTicks) { - // If another refresh driver observer destroys the nsPresContext, - // nsRefreshDriver will detect it and we won't be called. + // We already assert that GetRefreshDriver() is non-null at the beginning + // of this function but we check it again here to be sure that ticking + // animations does not have any side effects that cause us to lose the + // connection with the refresh driver, such as triggering the destruction + // of mDocument's PresShell. MOZ_ASSERT(GetRefreshDriver(), - "Refresh driver should still be valid inside WillRefresh"); + "Refresh driver should still be valid at end of WillRefresh"); GetRefreshDriver()->RemoveRefreshObserver(this, Flush_Style); mIsObservingRefreshDriver = false; } diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index a9fdacda9a1..10c66c63374 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -96,7 +96,6 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly( , mPseudoType(aPseudoType) { MOZ_ASSERT(aTarget, "null animation target is not yet supported"); - ResetIsRunningOnCompositor(); } JSObject* @@ -466,19 +465,6 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr& aStyleRule, } } -bool -KeyframeEffectReadOnly::IsPropertyRunningOnCompositor( - nsCSSProperty aProperty) const -{ - const auto& info = LayerAnimationInfo::sRecords; - for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) { - if (info[i].mProperty == aProperty) { - return mIsPropertyRunningOnCompositor[i]; - } - } - return false; -} - bool KeyframeEffectReadOnly::IsRunningOnCompositor() const { @@ -486,8 +472,8 @@ KeyframeEffectReadOnly::IsRunningOnCompositor() const // one property running on compositor. // Animation.IsRunningOnCompotitor will return more fine grained // information in bug 1196114. - for (bool isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) { - if (isPropertyRunningOnCompositor) { + for (const AnimationProperty& property : mProperties) { + if (property.mIsRunningOnCompositor) { return true; } } @@ -498,19 +484,13 @@ void KeyframeEffectReadOnly::SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning) { - static_assert( - MOZ_ARRAY_LENGTH(LayerAnimationInfo::sRecords) == - MOZ_ARRAY_LENGTH(mIsPropertyRunningOnCompositor), - "The length of mIsPropertyRunningOnCompositor should equal to" - "the length of LayserAnimationInfo::sRecords"); MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR), "Property being animated on compositor is a recognized " "compositor-animatable property"); - const auto& info = LayerAnimationInfo::sRecords; - for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) { - if (info[i].mProperty == aProperty) { - mIsPropertyRunningOnCompositor[i] = aIsRunning; + for (AnimationProperty& property : mProperties) { + if (property.mProperty == aProperty) { + property.mIsRunningOnCompositor = aIsRunning; return; } } @@ -523,8 +503,8 @@ KeyframeEffectReadOnly::~KeyframeEffectReadOnly() void KeyframeEffectReadOnly::ResetIsRunningOnCompositor() { - for (bool& isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) { - isPropertyRunningOnCompositor = false; + for (AnimationProperty& property : mProperties) { + property.mIsRunningOnCompositor = false; } } @@ -556,9 +536,7 @@ KeyframeEffectReadOnly::UpdateTargetRegistration() // Any effects not in the effect set will not be included in the set of // candidate effects for running on the compositor and hence they won't // have their compositor status updated so we should do that now. - for (bool& isRunningOnCompositor : mIsPropertyRunningOnCompositor) { - isRunningOnCompositor = false; - } + ResetIsRunningOnCompositor(); } } @@ -1822,7 +1800,7 @@ KeyframeEffectReadOnly::CanThrottle() const } // First we need to check layer generation and transform overflow - // prior to the IsPropertyRunningOnCompositor check because we should + // prior to the property.mIsRunningOnCompositor check because we should // occasionally unthrottle these animations even if the animations are // already running on compositor. for (const LayerAnimationInfo::Record& record : @@ -1854,7 +1832,7 @@ KeyframeEffectReadOnly::CanThrottle() const } for (const AnimationProperty& property : mProperties) { - if (!IsPropertyRunningOnCompositor(property.mProperty)) { + if (!property.mIsRunningOnCompositor) { return false; } } diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h index e809ac85079..8fe3d4f3401 100644 --- a/dom/animation/KeyframeEffect.h +++ b/dom/animation/KeyframeEffect.h @@ -118,7 +118,7 @@ struct AnimationPropertySegment struct AnimationProperty { - nsCSSProperty mProperty; + nsCSSProperty mProperty = eCSSProperty_UNKNOWN; // Does this property win in the CSS Cascade? // @@ -136,16 +136,26 @@ struct AnimationProperty // For other properties, we make it always be true. // **NOTE 2**: This member is not included when comparing AnimationProperty // objects for equality. - bool mWinsInCascade; + bool mWinsInCascade = true; + + // If true, the propery is currently being animated on the compositor. + // + // Note that when the owning Animation requests a non-throttled restyle, in + // between calling RequestRestyle on its AnimationCollection and when the + // restyle is performed, this member may temporarily become false even if + // the animation remains on the layer after the restyle. + bool mIsRunningOnCompositor = false; InfallibleTArray mSegments; - // NOTE: This operator does *not* compare the mWinsInCascade member. + // NOTE: This operator does *not* compare the mWinsInCascade member *or* the + // mIsRunningOnCompositor member. // This is because AnimationProperty objects are compared when recreating // CSS animations to determine if mutation observer change records need to // be created or not. However, at the point when these objects are compared - // the mWinsInCascade will not have been set on the new objects so we ignore - // this member to avoid generating spurious change records. + // neither the mWinsInCascade nor the mIsRunningOnCompositor will have been + // set on the new objects so we ignore these members to avoid generating + // spurious change records. bool operator==(const AnimationProperty& aOther) const { return mProperty == aOther.mProperty && mSegments == aOther.mSegments; @@ -279,8 +289,6 @@ public: // Any updated properties are added to |aSetProperties|. void ComposeStyle(RefPtr& aStyleRule, nsCSSPropertySet& aSetProperties); - // Returns true if |aProperty| is currently being animated on compositor. - bool IsPropertyRunningOnCompositor(nsCSSProperty aProperty) const; // Returns true if at least one property is being animated on compositor. bool IsRunningOnCompositor() const; void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning); @@ -341,17 +349,6 @@ protected: InfallibleTArray mProperties; - // Parallel array corresponding to CommonAnimationManager::sLayerAnimationInfo - // such that mIsPropertyRunningOnCompositor[x] is true only if this effect has - // an animation of CommonAnimationManager::sLayerAnimationInfo[x].mProperty - // that is currently running on the compositor. - // - // Note that when the owning Animation requests a non-throttled restyle, in - // between calling RequestRestyle on its AnimationCollection and when the - // restyle is performed, this member may temporarily become false even if - // the animation remains on the layer after the restyle. - bool mIsPropertyRunningOnCompositor[LayerAnimationInfo::kRecords]; - private: nsIFrame* GetAnimationFrame() const; diff --git a/dom/animation/test/chrome/test_running_on_compositor.html b/dom/animation/test/chrome/test_running_on_compositor.html index 7f2b12fc50e..26944b7e317 100644 --- a/dom/animation/test/chrome/test_running_on_compositor.html +++ b/dom/animation/test/chrome/test_running_on_compositor.html @@ -207,6 +207,9 @@ promise_test(function(t) { resolve(); })); observer.observe(div, { animations: true, subtree: false }); + t.add_cleanup(function() { + observer.disconnect(); + }); div.style.animationDuration = "200s"; })); })); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 7bfbf938f5b..6e06dfc2696 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -2117,7 +2117,15 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) // Note that, since mTiming does not change during a reset, the // navigationStart time remains unchanged and therefore any future new // timeline will have the same global clock time as the old one. - mDocumentTimeline = nullptr; + if (mDocumentTimeline) { + nsRefreshDriver* rd = mPresShell && mPresShell->GetPresContext() ? + mPresShell->GetPresContext()->RefreshDriver() : + nullptr; + if (rd) { + mDocumentTimeline->NotifyRefreshDriverDestroying(rd); + } + mDocumentTimeline = nullptr; + } nsCOMPtr bag = do_QueryInterface(aChannel); if (bag) { diff --git a/dom/bindings/test/mochitest.ini b/dom/bindings/test/mochitest.ini index c5f834d2f17..2559c5f9417 100644 --- a/dom/bindings/test/mochitest.ini +++ b/dom/bindings/test/mochitest.ini @@ -64,6 +64,7 @@ skip-if = debug == false [test_worker_UnwrapArg.html] [test_unforgeablesonexpando.html] [test_crossOriginWindowSymbolAccess.html] +[test_primitive_this.html] [test_callback_exceptions.html] [test_bug1123516_maplikesetlike.html] skip-if = debug == false diff --git a/dom/bindings/test/test_primitive_this.html b/dom/bindings/test/test_primitive_this.html new file mode 100644 index 00000000000..d2b733dffeb --- /dev/null +++ b/dom/bindings/test/test_primitive_this.html @@ -0,0 +1,45 @@ + + + + + + Test for Bug 603201 + + + + + +
Test
+ + diff --git a/dom/html/HTMLAudioElement.cpp b/dom/html/HTMLAudioElement.cpp index e570ce4f7da..03db82ad241 100644 --- a/dom/html/HTMLAudioElement.cpp +++ b/dom/html/HTMLAudioElement.cpp @@ -25,11 +25,8 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Audio) namespace mozilla { namespace dom { -extern bool IsAudioAPIEnabled(); - NS_IMPL_ELEMENT_CLONE(HTMLAudioElement) - HTMLAudioElement::HTMLAudioElement(already_AddRefed& aNodeInfo) : HTMLMediaElement(aNodeInfo) { @@ -79,13 +76,9 @@ HTMLAudioElement::Audio(const GlobalObject& aGlobal, nsresult HTMLAudioElement::SetAcceptHeader(nsIHttpChannel* aChannel) { nsAutoCString value( -#ifdef MOZ_WEBM "audio/webm," -#endif "audio/ogg," -#ifdef MOZ_WAVE "audio/wav," -#endif "audio/*;q=0.9," "application/ogg;q=0.7," "video/*;q=0.6,*/*;q=0.5"); diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index ecad501e664..93d70f78629 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -936,6 +936,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLInputElement, } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFilesAndDirectoriesPromise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement, @@ -944,6 +945,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement, NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers) NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles) NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileList) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilesAndDirectoriesPromise) if (tmp->IsSingleLineTextControl(false)) { tmp->mInputData.mState->Unlink(); } diff --git a/dom/html/HTMLVideoElement.cpp b/dom/html/HTMLVideoElement.cpp index 438e3a2a9c0..04872caa19a 100644 --- a/dom/html/HTMLVideoElement.cpp +++ b/dom/html/HTMLVideoElement.cpp @@ -113,9 +113,7 @@ HTMLVideoElement::GetAttributeMappingFunction() const nsresult HTMLVideoElement::SetAcceptHeader(nsIHttpChannel* aChannel) { nsAutoCString value( -#ifdef MOZ_WEBM "video/webm," -#endif "video/ogg," "video/*;q=0.9," "application/ogg;q=0.7," diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 9115fcdc909..4466fdcd358 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1498,7 +1498,12 @@ TabChild::ApplyShowInfo(const ShowInfo& aInfo) void TabChild::MaybeRequestPreinitCamera() { - // Check if this tab will use the `camera` permission. + // Check if this tab is an app (not a browser frame) and will use the + // `camera` permission, + if (IsBrowserElement()) { + return; + } + nsCOMPtr appsService = do_GetService("@mozilla.org/AppsService;1"); if (NS_WARN_IF(!appsService)) { return; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index eb3e8c03de9..cd626cd81b1 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -458,8 +458,31 @@ static void LogChannelRelevantInfo(nsIURI* aURI, LOG("Result principal origin: %s\n", resultPrincipalOrigin.get()); } +// This is similar to nsIScriptSecurityManager.getChannelResultPrincipal +// but taking signedPkg into account. The reason we can't rely on channel +// loadContext/loadInfo is it's dangerous to mutate them on parent process. +static already_AddRefed +GetChannelPrincipalWithSingedPkg(nsIChannel* aChannel, const nsACString& aSignedPkg) +{ + NeckoOriginAttributes neckoAttrs; + NS_GetOriginAttributes(aChannel, neckoAttrs); + + PrincipalOriginAttributes attrs; + attrs.InheritFromNecko(neckoAttrs); + attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aSignedPkg); + + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, nullptr); + + nsCOMPtr principal = + BasePrincipal::CreateCodebasePrincipal(uri, attrs); + + return principal.forget(); +} + bool -TabParent::ShouldSwitchProcess(nsIChannel* aChannel) +TabParent::ShouldSwitchProcess(nsIChannel* aChannel, const nsACString& aSignedPkg) { // If we lack of any information which is required to decide the need of // process switch, consider that we should switch process. @@ -473,19 +496,18 @@ TabParent::ShouldSwitchProcess(nsIChannel* aChannel) NS_ENSURE_TRUE(loadingPrincipal, true); // Prepare the channel result principal. - nsCOMPtr resultPrincipal; - nsContentUtils::GetSecurityManager()-> - GetChannelResultPrincipal(aChannel, getter_AddRefs(resultPrincipal)); + nsCOMPtr channelPrincipal = + GetChannelPrincipalWithSingedPkg(aChannel, aSignedPkg); // Log the debug info which is used to decide the need of proces switch. nsCOMPtr uri; aChannel->GetURI(getter_AddRefs(uri)); - LogChannelRelevantInfo(uri, loadingPrincipal, resultPrincipal, + LogChannelRelevantInfo(uri, loadingPrincipal, channelPrincipal, loadInfo->InternalContentPolicyType()); // Check if the signed package is loaded from the same origin. bool sameOrigin = false; - loadingPrincipal->Equals(resultPrincipal, &sameOrigin); + loadingPrincipal->Equals(channelPrincipal, &sameOrigin); if (sameOrigin) { LOG("Loading singed package from the same origin. Don't switch process.\n"); return false; @@ -516,7 +538,7 @@ void TabParent::OnStartSignedPackageRequest(nsIChannel* aChannel, const nsACString& aPackageId) { - if (!ShouldSwitchProcess(aChannel)) { + if (!ShouldSwitchProcess(aChannel, aPackageId)) { return; } @@ -2347,7 +2369,7 @@ TabParent::RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent, return true; } widget->StartPluginIME(aKeyboardEvent, - (int32_t&)aPanelX, + (int32_t&)aPanelX, (int32_t&)aPanelY, *aCommitted); return true; diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 1bc1aeb0b5e..ff3c7cd6b72 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -495,7 +495,7 @@ protected: // Decide whether we have to use a new process to reload the URI associated // with the given channel. - bool ShouldSwitchProcess(nsIChannel* aChannel); + bool ShouldSwitchProcess(nsIChannel* aChannel, const nsACString& aSignedPkg); ContentCacheInParent mContentCache; diff --git a/dom/media/DecoderTraits.cpp b/dom/media/DecoderTraits.cpp index 3bcb4500652..db73da4c372 100644 --- a/dom/media/DecoderTraits.cpp +++ b/dom/media/DecoderTraits.cpp @@ -12,15 +12,14 @@ #include "OggDecoder.h" #include "OggReader.h" -#ifdef MOZ_WAVE + #include "WaveDecoder.h" #include "WaveReader.h" -#endif -#ifdef MOZ_WEBM + #include "WebMDecoder.h" #include "WebMReader.h" #include "WebMDemuxer.h" -#endif + #ifdef MOZ_RAW #include "RawDecoder.h" #include "RawReader.h" @@ -128,7 +127,6 @@ IsOggType(const nsACString& aType) return CodecListContains(gOggTypes, aType); } -#ifdef MOZ_WAVE // See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions // of WAVE media types and codec types. However, the audio/vnd.wave // MIME type described there is not used. @@ -154,33 +152,24 @@ IsWaveType(const nsACString& aType) return CodecListContains(gWaveTypes, aType); } -#endif -#ifdef MOZ_WEBM static bool IsWebMSupportedType(const nsACString& aType, const nsAString& aCodecs = EmptyString()) { return WebMDecoder::CanHandleMediaType(aType, aCodecs); } -#endif /* static */ bool DecoderTraits::IsWebMTypeAndEnabled(const nsACString& aType) { -#ifdef MOZ_WEBM return IsWebMSupportedType(aType); -#endif - return false; } /* static */ bool DecoderTraits::IsWebMAudioType(const nsACString& aType) { -#ifdef MOZ_WEBM return aType.EqualsASCII("audio/webm"); -#endif - return false; } #ifdef MOZ_GSTREAMER @@ -367,7 +356,6 @@ IsAACSupportedType(const nsACString& aType, /* static */ bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType) { -#ifdef MOZ_WAVE if (IsWaveType(nsDependentCString(aMIMEType))) { // We should not return true for Wave types, since there are some // Wave codecs actually in use in the wild that we don't support, and @@ -376,7 +364,6 @@ bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType) // means. return false; } -#endif return CanHandleMediaType(aMIMEType, false, EmptyString()) != CANPLAY_NO; } @@ -394,11 +381,9 @@ DecoderTraits::CanHandleCodecsType(const char* aMIMEType, if (IsOggType(nsDependentCString(aMIMEType))) { codecList = MediaDecoder::IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs; } -#ifdef MOZ_WAVE if (IsWaveType(nsDependentCString(aMIMEType))) { codecList = gWaveCodecs; } -#endif #if !defined(MOZ_OMX_WEBM_DECODER) if (IsWebMTypeAndEnabled(nsDependentCString(aMIMEType))) { if (IsWebMSupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) { @@ -496,11 +481,9 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType, if (IsOggType(nsDependentCString(aMIMEType))) { return CANPLAY_MAYBE; } -#ifdef MOZ_WAVE if (IsWaveType(nsDependentCString(aMIMEType))) { return CANPLAY_MAYBE; } -#endif if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) { return CANPLAY_MAYBE; } @@ -583,12 +566,10 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner) decoder = new OggDecoder(aOwner); return decoder.forget(); } -#ifdef MOZ_WAVE if (IsWaveType(aType)) { decoder = new WaveDecoder(aOwner); return decoder.forget(); } -#endif #ifdef MOZ_OMX_DECODER if (IsOmxSupportedType(aType)) { // we are discouraging Web and App developers from using those formats in @@ -623,12 +604,12 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner) return decoder.forget(); } #endif -#ifdef MOZ_WEBM + if (IsWebMSupportedType(aType)) { decoder = new WebMDecoder(aOwner); return decoder.forget(); } -#endif + #ifdef MOZ_DIRECTSHOW // Note: DirectShow should come before WMF, so that we prefer DirectShow's // MP3 support over WMF's. @@ -682,11 +663,9 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac if (IsOggType(aType)) { decoderReader = new OggReader(aDecoder); } else -#ifdef MOZ_WAVE if (IsWaveType(aType)) { decoderReader = new WaveReader(aDecoder); } else -#endif #ifdef MOZ_OMX_DECODER if (IsOmxSupportedType(aType)) { decoderReader = new MediaOmxReader(aDecoder); @@ -698,13 +677,13 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac decoderReader = new AndroidMediaReader(aDecoder, aType); } else #endif -#ifdef MOZ_WEBM + if (IsWebMSupportedType(aType)) { decoderReader = Preferences::GetBool("media.format-reader.webm", true) ? static_cast(new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource()))) : new WebMReader(aDecoder); } else -#endif + #ifdef MOZ_DIRECTSHOW if (IsDirectShowSupportedType(aType)) { decoderReader = new DirectShowReader(aDecoder); @@ -735,9 +714,7 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType) (IsOmxSupportedType(aType) && !IsB2GSupportOnlyType(aType)) || #endif -#ifdef MOZ_WEBM IsWebMSupportedType(aType) || -#endif #ifdef MOZ_GSTREAMER IsGStreamerSupportedType(aType) || #endif diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index d3fba3552b0..aab3bd0cd1d 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1641,21 +1641,17 @@ MediaDecoder::IsOggEnabled() return Preferences::GetBool("media.ogg.enabled"); } -#ifdef MOZ_WAVE bool MediaDecoder::IsWaveEnabled() { return Preferences::GetBool("media.wave.enabled"); } -#endif -#ifdef MOZ_WEBM bool MediaDecoder::IsWebMEnabled() { return Preferences::GetBool("media.webm.enabled"); } -#endif #ifdef NECKO_PROTOCOL_rtsp bool diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 5dcd07454ce..9a6c4c955f3 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -662,14 +662,9 @@ private: static bool IsOggEnabled(); static bool IsOpusEnabled(); - -#ifdef MOZ_WAVE static bool IsWaveEnabled(); -#endif - -#ifdef MOZ_WEBM static bool IsWebMEnabled(); -#endif + #ifdef NECKO_PROTOCOL_rtsp static bool IsRtspEnabled(); #endif diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 5e2013147e6..25d5208e6d5 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -224,6 +224,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mIsVideoPrerolling(false), mAudioCaptured(false, "MediaDecoderStateMachine::mAudioCaptured"), mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"), + mVideoCompleted(false, "MediaDecoderStateMachine::mVideoCompleted"), mNotifyMetadataBeforeFirstFrame(false), mDispatchedEventToDecode(false), mQuickBuffering(false), @@ -355,6 +356,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated); mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus); mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus); + mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus); mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged); mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged); mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged); @@ -2352,10 +2354,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine() // Play the remaining media. We want to run AdvanceFrame() at least // once to ensure the current playback position is advanced to the // end of the media, and so that we update the readyState. - if (VideoQueue().GetSize() > 1 || - (HasAudio() && !mAudioCompleted) || - (mAudioCaptured && !mStreamSink->IsFinished())) - { + if ((HasVideo() && !mVideoCompleted) || + (HasAudio() && !mAudioCompleted)) { // Start playback if necessary to play the remaining media. MaybeStartPlayback(); UpdatePlaybackPositionPeriodically(); @@ -2425,6 +2425,7 @@ MediaDecoderStateMachine::Reset() mDecodedVideoEndTime = -1; mDecodedAudioEndTime = -1; mAudioCompleted = false; + mVideoCompleted = false; AudioQueue().Reset(); VideoQueue().Reset(); mFirstVideoFrameAfterSeek = nullptr; @@ -2836,9 +2837,11 @@ void MediaDecoderStateMachine::OnMediaSinkVideoComplete() { MOZ_ASSERT(OnTaskQueue()); + MOZ_ASSERT(mInfo.HasVideo()); VERBOSE_LOG("[%s]", __func__); mMediaSinkVideoPromise.Complete(); + mVideoCompleted = true; ScheduleStateMachine(); } @@ -2846,9 +2849,11 @@ void MediaDecoderStateMachine::OnMediaSinkVideoError() { MOZ_ASSERT(OnTaskQueue()); + MOZ_ASSERT(mInfo.HasVideo()); VERBOSE_LOG("[%s]", __func__); mMediaSinkVideoPromise.Complete(); + mVideoCompleted = true; if (HasAudio()) { return; } @@ -2858,11 +2863,11 @@ MediaDecoderStateMachine::OnMediaSinkVideoError() void MediaDecoderStateMachine::OnMediaSinkAudioComplete() { MOZ_ASSERT(OnTaskQueue()); + MOZ_ASSERT(mInfo.HasAudio()); VERBOSE_LOG("[%s]", __func__); mMediaSinkAudioPromise.Complete(); - // Set true only when we have audio. - mAudioCompleted = mInfo.HasAudio(); + mAudioCompleted = true; // To notify PlaybackEnded as soon as possible. ScheduleStateMachine(); } @@ -2870,11 +2875,11 @@ void MediaDecoderStateMachine::OnMediaSinkAudioComplete() void MediaDecoderStateMachine::OnMediaSinkAudioError() { MOZ_ASSERT(OnTaskQueue()); + MOZ_ASSERT(mInfo.HasAudio()); VERBOSE_LOG("[%s]", __func__); mMediaSinkAudioPromise.Complete(); - // Set true only when we have audio. - mAudioCompleted = mInfo.HasAudio(); + mAudioCompleted = true; // Make the best effort to continue playback when there is video. if (HasVideo()) { diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index e677c73a4ec..10a44709335 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -1101,6 +1101,9 @@ private: // been written to the MediaStream. Watchable mAudioCompleted; + // True if all video frames are already rendered. + Watchable mVideoCompleted; + // Set if MDSM receives dormant request during reading metadata. Maybe mPendingDormant; diff --git a/dom/media/mediasink/DecodedStream.cpp b/dom/media/mediasink/DecodedStream.cpp index 83076bded47..0d8e2805f15 100644 --- a/dom/media/mediasink/DecodedStream.cpp +++ b/dom/media/mediasink/DecodedStream.cpp @@ -26,7 +26,6 @@ public: : mMutex("DecodedStreamGraphListener::mMutex") , mStream(aStream) , mLastOutputTime(aStream->StreamTimeToMicroseconds(aStream->GetCurrentTime())) - , mStreamFinishedOnMainThread(false) { mFinishPromise = Move(aPromise); } @@ -52,8 +51,6 @@ public: void DoNotifyFinished() { mFinishPromise.ResolveIfExists(true, __func__); - MutexAutoLock lock(mMutex); - mStreamFinishedOnMainThread = true; } int64_t GetLastOutputTime() @@ -70,18 +67,11 @@ public: mStream = nullptr; } - bool IsFinishedOnMainThread() - { - MutexAutoLock lock(mMutex); - return mStreamFinishedOnMainThread; - } - private: Mutex mMutex; // Members below are protected by mMutex. RefPtr mStream; int64_t mLastOutputTime; // microseconds - bool mStreamFinishedOnMainThread; // Main thread only. MozPromiseHolder mFinishPromise; }; @@ -119,7 +109,6 @@ public: DecodedStreamData(SourceMediaStream* aStream, MozPromiseHolder&& aPromise); ~DecodedStreamData(); - bool IsFinished() const; int64_t GetPosition() const; void SetPlaying(bool aPlaying); @@ -180,12 +169,6 @@ DecodedStreamData::~DecodedStreamData() mStream->Destroy(); } -bool -DecodedStreamData::IsFinished() const -{ - return mListener->IsFinishedOnMainThread(); -} - int64_t DecodedStreamData::GetPosition() const { @@ -346,13 +329,14 @@ DecodedStream::OnEnded(TrackType aType) AssertOwnerThread(); MOZ_ASSERT(mStartTime.isSome()); - if (aType == TrackInfo::kAudioTrack) { + if (aType == TrackInfo::kAudioTrack && mInfo.HasAudio()) { // TODO: we should return a promise which is resolved when the audio track // is finished. For now this promise is resolved when the whole stream is // finished. return mFinishPromise; + } else if (aType == TrackInfo::kVideoTrack && mInfo.HasVideo()) { + return mFinishPromise; } - // TODO: handle video track. return nullptr; } @@ -883,13 +867,6 @@ DecodedStream::GetPosition(TimeStamp* aTimeStamp) const return mStartTime.ref() + (mData ? mData->GetPosition() : 0); } -bool -DecodedStream::IsFinished() const -{ - AssertOwnerThread(); - return mData && mData->IsFinished(); -} - void DecodedStream::ConnectListener() { diff --git a/dom/media/mediasink/DecodedStream.h b/dom/media/mediasink/DecodedStream.h index 7e2e97f521d..08bcae1743d 100644 --- a/dom/media/mediasink/DecodedStream.h +++ b/dom/media/mediasink/DecodedStream.h @@ -123,7 +123,6 @@ public: void AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded); void RemoveOutput(MediaStream* aStream); void SetSameOrigin(bool aSameOrigin); - bool IsFinished() const; bool HasConsumers() const; protected: diff --git a/dom/media/mediasink/VideoSink.cpp b/dom/media/mediasink/VideoSink.cpp index 9a2fb741f2d..5fa85d65833 100644 --- a/dom/media/mediasink/VideoSink.cpp +++ b/dom/media/mediasink/VideoSink.cpp @@ -166,8 +166,29 @@ VideoSink::Start(int64_t aStartTime, const MediaInfo& aInfo) if (mHasVideo) { mEndPromise = mEndPromiseHolder.Ensure(__func__); + + // If the underlying MediaSink has an end promise for the video track (which + // happens when mAudioSink refers to a DecodedStream), we must wait for it + // to complete before resolving our own end promise. Otherwise, MDSM might + // stop playback before DecodedStream plays to the end and cause + // test_streams_element_capture.html to time out. + RefPtr p = mAudioSink->OnEnded(TrackInfo::kVideoTrack); + if (p) { + RefPtr self = this; + mVideoSinkEndRequest.Begin(p->Then(mOwnerThread, __func__, + [self] () { + self->mVideoSinkEndRequest.Complete(); + self->TryUpdateRenderedVideoFrames(); + }, [self] () { + self->mVideoSinkEndRequest.Complete(); + self->TryUpdateRenderedVideoFrames(); + })); + } + ConnectListener(); - TryUpdateRenderedVideoFrames(); + // Run the render loop at least once so we can resolve the end promise + // when video duration is 0. + UpdateRenderedVideoFrames(); } } @@ -183,7 +204,8 @@ VideoSink::Stop() mUpdateScheduler.Reset(); if (mHasVideo) { DisconnectListener(); - mEndPromiseHolder.Resolve(true, __func__); + mVideoSinkEndRequest.DisconnectIfExists(); + mEndPromiseHolder.ResolveIfExists(true, __func__); mEndPromise = nullptr; } mVideoFrameEndTime = -1; @@ -216,7 +238,7 @@ VideoSink::Shutdown() } void -VideoSink::OnVideoQueueEvent(RefPtr&& aSample) +VideoSink::OnVideoQueuePushed(RefPtr&& aSample) { AssertOwnerThread(); // Listen to push event, VideoSink should try rendering ASAP if first frame @@ -230,6 +252,18 @@ VideoSink::OnVideoQueueEvent(RefPtr&& aSample) } } +void +VideoSink::OnVideoQueueFinished() +{ + AssertOwnerThread(); + // Run render loop if the end promise is not resolved yet. + if (!mUpdateScheduler.IsScheduled() && + mAudioSink->IsPlaying() && + !mEndPromiseHolder.IsEmpty()) { + UpdateRenderedVideoFrames(); + } +} + void VideoSink::Redraw() { @@ -260,7 +294,9 @@ VideoSink::ConnectListener() { AssertOwnerThread(); mPushListener = VideoQueue().PushEvent().Connect( - mOwnerThread, this, &VideoSink::OnVideoQueueEvent); + mOwnerThread, this, &VideoSink::OnVideoQueuePushed); + mFinishListener = VideoQueue().FinishEvent().Connect( + mOwnerThread, this, &VideoSink::OnVideoQueueFinished); } void @@ -268,6 +304,7 @@ VideoSink::DisconnectListener() { AssertOwnerThread(); mPushListener.Disconnect(); + mFinishListener.Disconnect(); } void @@ -371,6 +408,13 @@ VideoSink::UpdateRenderedVideoFrames() } } + // All frames are rendered, Let's resolve the promise. + if (VideoQueue().IsFinished() && + VideoQueue().GetSize() <= 1 && + !mVideoSinkEndRequest.Exists()) { + mEndPromiseHolder.ResolveIfExists(true, __func__); + } + RenderVideoFrames(mVideoQueueSendToCompositorSize, clockTime, nowTime); // No next fame to render. There is no need to schedule next render diff --git a/dom/media/mediasink/VideoSink.h b/dom/media/mediasink/VideoSink.h index 2bfdc0b7f07..f1ddb4f3919 100644 --- a/dom/media/mediasink/VideoSink.h +++ b/dom/media/mediasink/VideoSink.h @@ -72,7 +72,8 @@ private: virtual ~VideoSink(); // VideoQueue listener related. - void OnVideoQueueEvent(RefPtr&& aSample); + void OnVideoQueuePushed(RefPtr&& aSample); + void OnVideoQueueFinished(); void ConnectListener(); void DisconnectListener(); @@ -129,6 +130,7 @@ private: // Event listeners for VideoQueue MediaEventListener mPushListener; + MediaEventListener mFinishListener; // True if this sink is going to handle video track. bool mHasVideo; diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp index 3cece0247c8..81697c90578 100644 --- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -12,10 +12,7 @@ #include "mozilla/StateMirroring.h" #include "SourceBufferResource.h" #include "SourceBuffer.h" - -#ifdef MOZ_WEBM #include "WebMDemuxer.h" -#endif #ifdef MOZ_FMP4 #include "MP4Demuxer.h" @@ -798,12 +795,10 @@ TrackBuffersManager::CreateDemuxerforMIMEType() { ShutdownDemuxers(); -#ifdef MOZ_WEBM if (mType.LowerCaseEqualsLiteral("video/webm") || mType.LowerCaseEqualsLiteral("audio/webm")) { mInputDemuxer = new WebMDemuxer(mCurrentInputBuffer, true /* IsMediaSource*/ ); return; } -#endif #ifdef MOZ_FMP4 if (mType.LowerCaseEqualsLiteral("video/mp4") || mType.LowerCaseEqualsLiteral("audio/mp4")) { diff --git a/dom/media/moz.build b/dom/media/moz.build index 24393a69bf2..77316dcf931 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -30,7 +30,9 @@ DIRS += [ 'ogg', 'platforms', 'systemservices', + 'wave', 'webaudio', + 'webm', 'webrtc', 'webspeech', 'webvtt', @@ -40,12 +42,6 @@ DIRS += [ if CONFIG['MOZ_RAW']: DIRS += ['raw'] -if CONFIG['MOZ_WAVE']: - DIRS += ['wave'] - -if CONFIG['MOZ_WEBM']: - DIRS += ['webm'] - if CONFIG['MOZ_GSTREAMER']: DIRS += ['gstreamer'] diff --git a/dom/media/platforms/omx/OmxDataDecoder.cpp b/dom/media/platforms/omx/OmxDataDecoder.cpp index 421934a9fe7..d21170da182 100644 --- a/dom/media/platforms/omx/OmxDataDecoder.cpp +++ b/dom/media/platforms/omx/OmxDataDecoder.cpp @@ -68,7 +68,7 @@ OmxDataDecoder::OmxDataDecoder(const TrackInfo& aTrackInfo, , mOmxState(OMX_STATETYPE::OMX_StateInvalid, "OmxDataDecoder::mOmxState") , mTrackInfo(aTrackInfo.Clone()) , mFlushing(false) - , mShutdown(false) + , mShuttingDown(false) , mCheckingInputExhausted(false) , mPortSettingsChanged(-1, "OmxDataDecoder::mPortSettingsChanged") , mAudioCompactor(mAudioQueue) @@ -86,7 +86,6 @@ OmxDataDecoder::~OmxDataDecoder() { LOG("(%p)", this); mWatchManager.Shutdown(); - mOmxTaskQueue->AwaitShutdownAndIdle(); } void @@ -207,12 +206,25 @@ OmxDataDecoder::Shutdown() { LOG("(%p)", this); - mShutdown = true; + mShuttingDown = true; nsCOMPtr r = NS_NewRunnableMethod(this, &OmxDataDecoder::DoAsyncShutdown); mOmxTaskQueue->Dispatch(r.forget()); + { + // DoAsyncShutdown() will be running for a while, it could be still running + // when reader releasing the decoder and then it causes problem. To avoid it, + // Shutdown() must block until DoAsyncShutdown() is completed. + MonitorAutoLock lock(mMonitor); + while (mShuttingDown) { + lock.Wait(); + } + } + + mOmxTaskQueue->BeginShutdown(); + mOmxTaskQueue->AwaitShutdownAndIdle(); + return NS_OK; } @@ -273,9 +285,17 @@ OmxDataDecoder::DoAsyncShutdown() [self] () { LOG("DoAsyncShutdown: OMX_StateLoaded, it is safe to shutdown omx"); self->mOmxLayer->Shutdown(); + + MonitorAutoLock lock(self->mMonitor); + self->mShuttingDown = false; + self->mMonitor.Notify(); }, [self] () { self->mOmxLayer->Shutdown(); + + MonitorAutoLock lock(self->mMonitor); + self->mShuttingDown = false; + self->mMonitor.Notify(); }); } @@ -400,12 +420,8 @@ OmxDataDecoder::FillAndEmptyBuffers() MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn()); MOZ_ASSERT(mOmxState == OMX_StateExecuting); - // During the port setting changed, it is forbided to do any buffer operations. - if (mPortSettingsChanged != -1 || mShutdown) { - return; - } - - if (mFlushing) { + // During the port setting changed, it is forbidden to do any buffer operation. + if (mPortSettingsChanged != -1 || mShuttingDown || mFlushing) { return; } @@ -842,7 +858,6 @@ OmxDataDecoder::DoFlush() // 1. Call OMX command OMX_CommandFlush in Omx TaskQueue. // 2. Remove all elements in mMediaRawDatas when flush is completed. - RefPtr self = this; mOmxLayer->SendCommand(OMX_CommandFlush, OMX_ALL, nullptr) ->Then(mOmxTaskQueue, __func__, this, &OmxDataDecoder::FlushComplete, diff --git a/dom/media/platforms/omx/OmxDataDecoder.h b/dom/media/platforms/omx/OmxDataDecoder.h index d5fd5527f67..dde57e119dd 100644 --- a/dom/media/platforms/omx/OmxDataDecoder.h +++ b/dom/media/platforms/omx/OmxDataDecoder.h @@ -163,7 +163,7 @@ protected: Atomic mFlushing; // It is accessed in Omx/reader TaskQeueu. - Atomic mShutdown; + Atomic mShuttingDown; // It is accessed in Omx TaskQeueu. bool mCheckingInputExhausted; diff --git a/dom/media/platforms/omx/OmxPromiseLayer.cpp b/dom/media/platforms/omx/OmxPromiseLayer.cpp index d275c411208..ef75b54bc7e 100644 --- a/dom/media/platforms/omx/OmxPromiseLayer.cpp +++ b/dom/media/platforms/omx/OmxPromiseLayer.cpp @@ -22,9 +22,10 @@ extern mozilla::LogModule* GetPDMLog(); namespace mozilla { +extern void GetPortIndex(nsTArray& aPortIndex); + OmxPromiseLayer::OmxPromiseLayer(TaskQueue* aTaskQueue, OmxDataDecoder* aDataDecoder) : mTaskQueue(aTaskQueue) - , mFlushPortIndex(0) { #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21 mPlatformLayer = new GonkOmxPlatformLayer(aDataDecoder, this, aTaskQueue); @@ -196,27 +197,48 @@ OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData::BufferID aID RefPtr OmxPromiseLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmdData) { - // No need to issue flush because of buffers are in client already. - // - // Some components fail to respond flush event when all of buffers are in - // client. if (aCmd == OMX_CommandFlush) { - bool needFlush = false; - if ((aParam1 & OMX_DirInput && mInbufferHolders.Length()) || - (aParam1 & OMX_DirOutput && mOutbufferHolders.Length())) { - needFlush = true; - } - if (!needFlush) { - LOG("SendCommand: buffers are in client already, no need to flush"); - mRawDatas.Clear(); - return OmxCommandPromise::CreateAndResolve(OMX_CommandFlush, __func__); - } - } + // It doesn't support another flush commands before previous one is completed. + MOZ_RELEASE_ASSERT(!mFlushCommands.Length()); - OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData); - if (err != OMX_ErrorNone) { - OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd); - return OmxCommandPromise::CreateAndReject(failure, __func__); + // Some coomponents don't send event with OMX_ALL, they send flush complete + // event with input port and another event for output port. + // In prupose of better compatibility, we inteprete the OMX_ALL to OMX_DirInput + // and OMX_DirOutput flush separately. + OMX_DIRTYPE types[] = {OMX_DIRTYPE::OMX_DirInput, OMX_DIRTYPE::OMX_DirOutput}; + for(const auto type : types) { + if ((aParam1 == type) || (aParam1 == OMX_ALL)) { + mFlushCommands.AppendElement(FlushCommand({type, aCmdData})); + } + + if (type == OMX_DirInput) { + // Clear all buffered raw data. + mRawDatas.Clear(); + } + } + + // Don't overlay more than one fush command, some components can't overlay flush commands. + // So here we send another flush after receiving the previous flush completed event. + if (mFlushCommands.Length()) { + OMX_ERRORTYPE err = + mPlatformLayer->SendCommand(OMX_CommandFlush, + mFlushCommands.ElementAt(0).type, + mFlushCommands.ElementAt(0).cmd); + if (err != OMX_ErrorNone) { + OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush); + return OmxCommandPromise::CreateAndReject(failure, __func__); + } + } else { + LOG("SendCommand: OMX_CommandFlush parameter error"); + OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush); + return OmxCommandPromise::CreateAndReject(failure, __func__); + } + } else { + OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData); + if (err != OMX_ErrorNone) { + OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd); + return OmxCommandPromise::CreateAndReject(failure, __func__); + } } RefPtr p; @@ -224,9 +246,6 @@ OmxPromiseLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmd p = mCommandStatePromise.Ensure(__func__); } else if (aCmd == OMX_CommandFlush) { p = mFlushPromise.Ensure(__func__); - mFlushPortIndex = aParam1; - // Clear all buffered raw data. - mRawDatas.Clear(); } else if (aCmd == OMX_CommandPortEnable) { p = mPortEnablePromise.Ensure(__func__); } else if (aCmd == OMX_CommandPortDisable) { @@ -248,8 +267,24 @@ OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2) { if (cmd == OMX_CommandStateSet) { mCommandStatePromise.Resolve(OMX_CommandStateSet, __func__); - } else if (cmd == OMX_CommandFlush && mFlushPortIndex == aData2) { - mFlushPromise.Resolve(OMX_CommandFlush, __func__); + } else if (cmd == OMX_CommandFlush) { + MOZ_RELEASE_ASSERT(mFlushCommands.ElementAt(0).type == aData2); + LOG("Event: OMX_CommandFlush completed port type %d", aData2); + mFlushCommands.RemoveElementAt(0); + + // Sending next flush command. + if (mFlushCommands.Length()) { + OMX_ERRORTYPE err = + mPlatformLayer->SendCommand(OMX_CommandFlush, + mFlushCommands.ElementAt(0).type, + mFlushCommands.ElementAt(0).cmd); + if (err != OMX_ErrorNone) { + OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush); + mFlushPromise.Reject(failure, __func__); + } + } else { + mFlushPromise.Resolve(OMX_CommandFlush, __func__); + } } else if (cmd == OMX_CommandPortDisable) { mPortDisablePromise.Resolve(OMX_CommandPortDisable, __func__); } else if (cmd == OMX_CommandPortEnable) { @@ -262,7 +297,7 @@ OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2) if (cmd == OMX_CommandStateSet) { OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet); mCommandStatePromise.Reject(failure, __func__); - } else if (cmd == OMX_CommandFlush && mFlushPortIndex == aData2) { + } else if (cmd == OMX_CommandFlush) { OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandFlush); mFlushPromise.Reject(failure, __func__); } else if (cmd == OMX_CommandPortDisable) { diff --git a/dom/media/platforms/omx/OmxPromiseLayer.h b/dom/media/platforms/omx/OmxPromiseLayer.h index aa130d340dd..11d1bef51e1 100644 --- a/dom/media/platforms/omx/OmxPromiseLayer.h +++ b/dom/media/platforms/omx/OmxPromiseLayer.h @@ -183,6 +183,11 @@ public: bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2); protected: + struct FlushCommand { + OMX_DIRTYPE type; + OMX_PTR cmd; + }; + BUFFERLIST* GetBufferHolders(OMX_DIRTYPE aType); already_AddRefed FindAndRemoveRawData(OMX_TICKS aTimecode); @@ -197,7 +202,7 @@ protected: MozPromiseHolder mFlushPromise; - OMX_U32 mFlushPortIndex; + nsTArray mFlushCommands; nsAutoPtr mPlatformLayer; diff --git a/dom/media/platforms/wrappers/FuzzingWrapper.cpp b/dom/media/platforms/wrappers/FuzzingWrapper.cpp index 6b87a8fb5ad..0cb776c582e 100644 --- a/dom/media/platforms/wrappers/FuzzingWrapper.cpp +++ b/dom/media/platforms/wrappers/FuzzingWrapper.cpp @@ -50,11 +50,12 @@ DecoderFuzzingWrapper::Input(MediaRawData* aData) nsresult DecoderFuzzingWrapper::Flush() { - DFW_LOGV(""); + DFW_LOGV("Calling mDecoder[%p]->Flush()", mDecoder.get()); MOZ_ASSERT(mDecoder); // Flush may output some frames (though unlikely). // Flush may block a bit, it's ok if we output some frames in the meantime. nsresult result = mDecoder->Flush(); + DFW_LOGV("mDecoder[%p]->Flush() -> result=%u", mDecoder.get(), uint32_t(result)); // Clear any delayed output we may have. mCallbackWrapper->ClearDelayedOutput(); return result; @@ -254,13 +255,28 @@ void DecoderCallbackFuzzingWrapper::ScheduleOutputDelayedFrame() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + if (mDelayedOutputRequest.Exists()) { + // A delayed output is already scheduled, no need for more than one timer. + return; + } RefPtr self = this; - mDelayedOutputTimer->WaitUntil( - mPreviousOutput + mFrameOutputMinimumInterval, - __func__) - ->Then(mTaskQueue, __func__, - [self] () -> void { self->OutputDelayedFrame(); }, - [self] () -> void { self->OutputDelayedFrame(); }); + mDelayedOutputRequest.Begin( + mDelayedOutputTimer->WaitUntil( + mPreviousOutput + mFrameOutputMinimumInterval, + __func__) + ->Then(mTaskQueue, __func__, + [self] () -> void { + if (self->mDelayedOutputRequest.Exists()) { + self->mDelayedOutputRequest.Complete(); + self->OutputDelayedFrame(); + } + }, + [self] () -> void { + if (self->mDelayedOutputRequest.Exists()) { + self->mDelayedOutputRequest.Complete(); + self->ClearDelayedOutput(); + } + })); } void @@ -300,11 +316,16 @@ void DecoderCallbackFuzzingWrapper::ClearDelayedOutput() { if (!mTaskQueue->IsCurrentThreadIn()) { + DFW_LOGV("(dispatching self)"); nsCOMPtr task = NS_NewRunnableMethod(this, &DecoderCallbackFuzzingWrapper::ClearDelayedOutput); mTaskQueue->Dispatch(task.forget()); return; } + DFW_LOGV(""); + // In case a timer hasn't lapsed yet, before destroying the timer and its + // attached waitUntil() promise, the 'Then' request must be disconnected. + mDelayedOutputRequest.DisconnectIfExists(); mDelayedOutputTimer = nullptr; mDelayedOutput.clear(); } @@ -312,10 +333,16 @@ DecoderCallbackFuzzingWrapper::ClearDelayedOutput() void DecoderCallbackFuzzingWrapper::Shutdown() { - DFW_LOGV("Shutting down mTaskQueue"); + CFW_LOGV("Clear delayed output (if any) before shutting down mTaskQueue"); + ClearDelayedOutput(); + // Await idle here, so that 'ClearDelayedOutput' runs to completion before + // the task queue is shutdown (and tasks can't be queued anymore). + mTaskQueue->AwaitIdle(); + + CFW_LOGV("Shutting down mTaskQueue"); mTaskQueue->BeginShutdown(); mTaskQueue->AwaitIdle(); - DFW_LOGV("mTaskQueue shut down"); + CFW_LOGV("mTaskQueue shut down"); } } // namespace mozilla diff --git a/dom/media/platforms/wrappers/FuzzingWrapper.h b/dom/media/platforms/wrappers/FuzzingWrapper.h index 0aa41e68a05..838aae9e7d0 100644 --- a/dom/media/platforms/wrappers/FuzzingWrapper.h +++ b/dom/media/platforms/wrappers/FuzzingWrapper.h @@ -81,6 +81,7 @@ private: typedef Pair, bool> MediaDataAndInputExhausted; std::deque mDelayedOutput; RefPtr mDelayedOutputTimer; + MozPromiseRequestHolder mDelayedOutputRequest; // If draining, a 'DrainComplete' will be sent after all delayed frames have // been output. bool mDraining; diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index e7afb2eb840..ac7853d67c4 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -851,14 +851,6 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439 # The tests below contain backend-specific tests. Write backend independent # tests rather than adding to this list. [test_can_play_type_webm.html] -skip-if = !webm -[test_can_play_type_no_webm.html] -skip-if = webm [test_can_play_type_wave.html] -skip-if = !wave -[test_can_play_type_no_wave.html] -skip-if = wave [test_fragment_noplay.html] -skip-if = !wave [test_fragment_play.html] -skip-if = !wave diff --git a/dom/media/test/test_can_play_type_no_wave.html b/dom/media/test/test_can_play_type_no_wave.html deleted file mode 100644 index 20e96f01170..00000000000 --- a/dom/media/test/test_can_play_type_no_wave.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Test for Bug 469247: WAVE backend disabled - - - - - - -Mozill -a Bug 469247 -

- - - - -
-
-
-check_wave(document.getElementById('v'), false);
-
-mediaTestCleanup();
-
-
-
- - diff --git a/dom/media/test/test_can_play_type_no_webm.html b/dom/media/test/test_can_play_type_no_webm.html deleted file mode 100644 index 4feda8cead6..00000000000 --- a/dom/media/test/test_can_play_type_no_webm.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Test for Bug 566245: WebM backend disabled - - - - - - -Mozill -a Bug 566245 -

- - - - -
-
-
-check_webm(document.getElementById('v'), false);
-
-mediaTestCleanup();
-
-
-
- - diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index 13e7719c3c1..323970df4e8 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -90,11 +90,11 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' & [test_peerConnection_basicScreenshare.html] # no screenshare on b2g/android # frequent timeouts/crashes on e10s (bug 1048455) -skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s # Bug 1141029 Mulet parity with B2G Desktop for TC +skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Bug 1141029 Mulet parity with B2G Desktop for TC [test_peerConnection_basicWindowshare.html] # no screenshare on b2g/android # frequent timeouts/crashes on e10s (bug 1048455) -skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s # Bug 1141029 Mulet parity with B2G Desktop for TC +skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Bug 1141029 Mulet parity with B2G Desktop for TC [test_peerConnection_basicH264Video.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' || os == 'android' # bug 1043403 # Bug 1141029 Mulet parity with B2G Desktop for TC [test_peerConnection_bug822674.html] @@ -161,16 +161,16 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' & skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g (Bug 1059867), android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_twoAudioVideoStreams.html] # b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' [test_peerConnection_twoAudioVideoStreamsCombined.html] # b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' [test_peerConnection_twoVideoStreams.html] # b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' [test_peerConnection_twoVideoTracksInOneStream.html] # b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug) +skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) [test_peerConnection_addSecondAudioStream.html] skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes [test_peerConnection_answererAddSecondAudioStream.html] @@ -181,26 +181,26 @@ skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_addSecondVideoStream.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || android_version == '18' [test_peerConnection_removeVideoTrack.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug) +skip-if = toolkit == 'gonk' || (android_version == '18' && debug) [test_peerConnection_removeThenAddVideoTrack.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug) +skip-if = toolkit == 'gonk' || (android_version == '18' && debug) [test_peerConnection_replaceVideoThenRenegotiate.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug) +skip-if = toolkit == 'gonk' || (android_version == '18' && debug) [test_peerConnection_addSecondAudioStreamNoBundle.html] skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_removeThenAddAudioTrackNoBundle.html] skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_addSecondVideoStreamNoBundle.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || android_version == '18' [test_peerConnection_removeThenAddVideoTrackNoBundle.html] # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator) -skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18' +skip-if = toolkit == 'gonk' || android_version == '18' [test_peerConnection_addDataChannel.html] skip-if = toolkit == 'gonk' # B2G emulator seems to be so slow that DTLS cannot establish properly [test_peerConnection_addDataChannelNoBundle.html] diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 896df2f1911..201c7837abc 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -2650,7 +2650,12 @@ Notification::CreateAndShow(nsIGlobalObject* aGlobal, MOZ_ASSERT(aGlobal); AutoJSAPI jsapi; - jsapi.Init(aGlobal); + if (NS_WARN_IF(!jsapi.Init(aGlobal))) + { + aRv.Throw(NS_ERROR_DOM_ABORT_ERR); + return nullptr; + } + JSContext* cx = jsapi.cx(); RefPtr notification = CreateInternal(aGlobal, EmptyString(), diff --git a/dom/tv/FakeTVService.cpp b/dom/tv/FakeTVService.cpp deleted file mode 100644 index a62620b3380..00000000000 --- a/dom/tv/FakeTVService.cpp +++ /dev/null @@ -1,532 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/TVServiceRunnables.h" -#include "mozilla/dom/TVTypes.h" -#include "nsCOMPtr.h" -#include "nsIMutableArray.h" -#include "nsITimer.h" -#include "nsServiceManagerUtils.h" -#include "prtime.h" -#include "FakeTVService.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(FakeTVService) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FakeTVService) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTuners) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannels) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrograms) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEITBroadcastedTimer) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScanCompleteTimer) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FakeTVService) - tmp->Shutdown(); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mTuners) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannels) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrograms) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mEITBroadcastedTimer) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mScanCompleteTimer) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(FakeTVService) -NS_IMPL_CYCLE_COLLECTING_RELEASE(FakeTVService) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FakeTVService) - NS_INTERFACE_MAP_ENTRY(nsITVService) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -FakeTVService::FakeTVService() -{ - Init(); -} - -FakeTVService::~FakeTVService() -{ - Shutdown(); -} - -void -FakeTVService::Init() -{ - const char* sourceTypes1[2] = {"dvb-t", "dvb-c"}; - nsCOMPtr tunerData1 = MockTuner(NS_LITERAL_STRING("1"), 2, sourceTypes1); - mTuners.AppendElement(tunerData1); - const char* sourceTypes2[1] = {"dvb-s"}; - nsCOMPtr tunerData2 = MockTuner(NS_LITERAL_STRING("2"), 1, sourceTypes2); - mTuners.AppendElement(tunerData2); - - nsCOMPtr channelData1 = - MockChannel(NS_LITERAL_STRING("networkId1"), NS_LITERAL_STRING("transportStreamId1"), - NS_LITERAL_STRING("serviceId1"), NS_LITERAL_STRING("tv"), - NS_LITERAL_STRING("1"), NS_LITERAL_STRING("name1"), true, true); - mChannels.AppendElement(channelData1); - nsCOMPtr channelData2 = - MockChannel(NS_LITERAL_STRING("networkId2"), NS_LITERAL_STRING("transportStreamId2"), - NS_LITERAL_STRING("serviceId2"), NS_LITERAL_STRING("radio"), - NS_LITERAL_STRING("2"), NS_LITERAL_STRING("name2"), true, true); - mChannels.AppendElement(channelData2); - - uint64_t now = PR_Now(); - const char* audioLanguages1[2] = {"eng", "jpn"}; - const char* subtitleLanguages1[2] = {"fre", "spa"}; - nsCOMPtr programData1 = - MockProgram(NS_LITERAL_STRING("eventId1"), NS_LITERAL_STRING("title1"), - now - 1, 3600000, - NS_LITERAL_STRING("description1"), NS_LITERAL_STRING("rating1"), - 2, audioLanguages1, 2, subtitleLanguages1); - mPrograms.AppendElement(programData1); - nsCOMPtr programData2 = - MockProgram(NS_LITERAL_STRING("eventId2"), NS_LITERAL_STRING("title2"), - now + 3600000 , 3600000, - NS_LITERAL_STRING(""), NS_LITERAL_STRING(""), - 0, nullptr, 0, nullptr); - mPrograms.AppendElement(programData2); -} - -void -FakeTVService::Shutdown() -{ - if (mEITBroadcastedTimer) { - mEITBroadcastedTimer->Cancel(); - } - if (mScanCompleteTimer) { - mScanCompleteTimer->Cancel(); - } -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::GetSourceListener(nsITVSourceListener** aSourceListener) -{ - if (!mSourceListener) { - *aSourceListener = nullptr; - return NS_OK; - } - - *aSourceListener = mSourceListener; - NS_ADDREF(*aSourceListener); - return NS_OK; -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::SetSourceListener(nsITVSourceListener* aSourceListener) -{ - mSourceListener = aSourceListener; - return NS_OK; -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::GetTuners(nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr tunerDataList = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!tunerDataList) { - return NS_ERROR_OUT_OF_MEMORY; - } - - for (uint32_t i = 0; i < mTuners.Length(); i++) { - tunerDataList->AppendElement(mTuners[i], false); - } - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, tunerDataList); - return NS_DispatchToCurrentThread(runnable); -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::SetSource(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - for (uint32_t i = 0; i < mTuners.Length(); i++) { - nsString tunerId; - mTuners[i]->GetId(tunerId); - if (aTunerId.Equals(tunerId)) { - uint32_t sourceTypeCount; - char** sourceTypes; - mTuners[i]->GetSupportedSourceTypes(&sourceTypeCount, &sourceTypes); - for (uint32_t j = 0; j < sourceTypeCount; j++) { - nsString sourceType; - sourceType.AssignASCII(sourceTypes[j]); - if (aSourceType.Equals(sourceType)) { - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes); - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, nullptr); - return NS_DispatchToCurrentThread(runnable); - } - } - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes); - } - } - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, nullptr, nsITVServiceCallback::TV_ERROR_FAILURE); - return NS_DispatchToCurrentThread(runnable); -} - -class EITBroadcastedCallback final : public nsITimerCallback -{ -public: - NS_DECL_ISUPPORTS - - EITBroadcastedCallback(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVSourceListener* aSourceListener, - nsITVChannelData* aChannelData) - : mTunerId(aTunerId) - , mSourceType(aSourceType) - , mSourceListener(aSourceListener) - , mChannelData(aChannelData) - {} - - NS_IMETHODIMP - Notify(nsITimer* aTimer) override - { - // Notify mock EIT broadcasting. - nsITVProgramData** programDataList = - static_cast(moz_xmalloc(1 * sizeof(nsITVProgramData*))); - programDataList[0] = new TVProgramData(); - programDataList[0]->SetEventId(NS_LITERAL_STRING("eventId")); - programDataList[0]->SetTitle(NS_LITERAL_STRING("title")); - programDataList[0]->SetStartTime(PR_Now() + 3600000); - programDataList[0]->SetDuration(3600000); - programDataList[0]->SetDescription(NS_LITERAL_STRING("description")); - programDataList[0]->SetRating(NS_LITERAL_STRING("rating")); - programDataList[0]->SetAudioLanguages(0, nullptr); - programDataList[0]->SetSubtitleLanguages(0, nullptr); - nsresult rv = mSourceListener->NotifyEITBroadcasted(mTunerId, mSourceType, - mChannelData, - programDataList, 1); - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(1, programDataList); - return rv; - } - -private: - ~EITBroadcastedCallback() {} - - nsString mTunerId; - nsString mSourceType; - nsCOMPtr mSourceListener; - nsCOMPtr mChannelData; -}; - -NS_IMPL_ISUPPORTS(EITBroadcastedCallback, nsITimerCallback) - -class ScanCompleteCallback final : public nsITimerCallback -{ -public: - NS_DECL_ISUPPORTS - - ScanCompleteCallback(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVSourceListener* aSourceListener) - : mTunerId(aTunerId) - , mSourceType(aSourceType) - , mSourceListener(aSourceListener) - {} - - NS_IMETHODIMP - Notify(nsITimer* aTimer) override - { - return mSourceListener->NotifyChannelScanComplete(mTunerId, mSourceType); - } - -private: - ~ScanCompleteCallback() {} - - nsString mTunerId; - nsString mSourceType; - nsCOMPtr mSourceListener; -}; - -NS_IMPL_ISUPPORTS(ScanCompleteCallback, nsITimerCallback) - -/* virtual */ NS_IMETHODIMP -FakeTVService::StartScanningChannels(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, nullptr); - nsresult rv = NS_DispatchToCurrentThread(runnable); - NS_ENSURE_SUCCESS(rv, rv); - - if (IsAllowed(aTunerId, aSourceType)) { - rv = mSourceListener->NotifyChannelScanned(aTunerId, aSourceType, mChannels[0]); - NS_ENSURE_SUCCESS(rv, rv); - - // Set a timer. |notifyEITBroadcasted| will be called after the timer - // fires (10ms). (The timer could be canceled if |StopScanningChannels| gets - // called before firing.) - mEITBroadcastedTimer = do_CreateInstance(NS_TIMER_CONTRACTID); - NS_ENSURE_TRUE(mEITBroadcastedTimer, NS_ERROR_OUT_OF_MEMORY); - RefPtr eitBroadcastedCb = - new EITBroadcastedCallback(aTunerId, aSourceType, mSourceListener, mChannels[0]); - rv = mEITBroadcastedTimer->InitWithCallback(eitBroadcastedCb, 10, - nsITimer::TYPE_ONE_SHOT); - NS_ENSURE_SUCCESS(rv, rv); - - // Set a timer. |notifyChannelScanComplete| will be called after the timer - // fires (20ms). (The timer could be canceled if |StopScanningChannels| gets - // called before firing.) - mScanCompleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID); - NS_ENSURE_TRUE(mScanCompleteTimer, NS_ERROR_OUT_OF_MEMORY); - RefPtr scanCompleteCb = - new ScanCompleteCallback(aTunerId, aSourceType, mSourceListener); - rv = mScanCompleteTimer->InitWithCallback(scanCompleteCb, 20, - nsITimer::TYPE_ONE_SHOT); - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::StopScanningChannels(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - if (mEITBroadcastedTimer) { - mEITBroadcastedTimer->Cancel(); - mEITBroadcastedTimer = nullptr; - } - if (mScanCompleteTimer) { - mScanCompleteTimer->Cancel(); - mScanCompleteTimer = nullptr; - } - nsresult rv = mSourceListener->NotifyChannelScanStopped(aTunerId, aSourceType); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, nullptr); - return NS_DispatchToCurrentThread(runnable); -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::ClearScannedChannelsCache() -{ - // Fake service doesn't support channel cache, so there's nothing to do here. - return NS_OK; -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::SetChannel(const nsAString& aTunerId, - const nsAString& aSourceType, - const nsAString& aChannelNumber, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr channelDataList = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!channelDataList) { - return NS_ERROR_OUT_OF_MEMORY; - } - - if (IsAllowed(aTunerId, aSourceType)) { - for (uint32_t i = 0; i < mChannels.Length(); i++) { - nsString channelNumber; - mChannels[i]->GetNumber(channelNumber); - if (aChannelNumber.Equals(channelNumber)) { - channelDataList->AppendElement(mChannels[i], false); - break; - } - } - } - - uint32_t length; - nsresult rv = channelDataList->GetLength(&length); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr runnable = new TVServiceNotifyRunnable( - aCallback, - (length == 1) ? channelDataList : nullptr, - (length == 1) ? nsITVServiceCallback::TV_ERROR_OK : nsITVServiceCallback::TV_ERROR_FAILURE - ); - return NS_DispatchToCurrentThread(runnable); -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::GetChannels(const nsAString& aTunerId, - const nsAString& aSourceType, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr channelDataList = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!channelDataList) { - return NS_ERROR_OUT_OF_MEMORY; - } - - if (IsAllowed(aTunerId, aSourceType)) { - for (uint32_t i = 0; i < mChannels.Length(); i++) { - channelDataList->AppendElement(mChannels[i], false); - } - } - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, channelDataList); - return NS_DispatchToCurrentThread(runnable); -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::GetPrograms(const nsAString& aTunerId, - const nsAString& aSourceType, - const nsAString& aChannelNumber, - uint64_t startTime, - uint64_t endTime, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr programDataList = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!programDataList) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // Only return mock programs for the first channel. - nsString channelNumber; - mChannels[0]->GetNumber(channelNumber); - if (IsAllowed(aTunerId, aSourceType) && aChannelNumber.Equals(channelNumber)) { - for (uint32_t i = 0; i < mPrograms.Length(); i++) { - programDataList->AppendElement(mPrograms[i], false); - } - } - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, programDataList); - return NS_DispatchToCurrentThread(runnable); -} - -/* virtual */ NS_IMETHODIMP -FakeTVService::GetOverlayId(const nsAString& aTunerId, - nsITVServiceCallback* aCallback) -{ - if (!aCallback) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr overlayIds = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!overlayIds) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // TODO Implement in follow-up patches. - - nsCOMPtr runnable = - new TVServiceNotifyRunnable(aCallback, overlayIds); - return NS_DispatchToCurrentThread(runnable); -} - -bool -FakeTVService::IsAllowed(const nsAString& aTunerId, - const nsAString& aSourceType) -{ - // Only allow for the first source of the first tuner. - nsString tunerId; - mTuners[0]->GetId(tunerId); - if (!aTunerId.Equals(tunerId)) { - return false; - } - - uint32_t sourceTypeCount; - char** sourceTypes; - mTuners[0]->GetSupportedSourceTypes(&sourceTypeCount, &sourceTypes); - nsString sourceType; - sourceType.AssignASCII(sourceTypes[0]); - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(sourceTypeCount, sourceTypes); - if (!aSourceType.Equals(sourceType)) { - return false; - } - - return true; -} - -already_AddRefed -FakeTVService::MockTuner(const nsAString& aId, - uint32_t aSupportedSourceTypeCount, - const char** aSupportedSourceTypes) -{ - nsCOMPtr tunerData = new TVTunerData(); - tunerData->SetId(aId); - tunerData->SetSupportedSourceTypes(aSupportedSourceTypeCount, aSupportedSourceTypes); - return tunerData.forget(); -} - -already_AddRefed -FakeTVService::MockChannel(const nsAString& aNetworkId, - const nsAString& aTransportStreamId, - const nsAString& aServiceId, - const nsAString& aType, - const nsAString& aNumber, - const nsAString& aName, - bool aIsEmergency, - bool aIsFree) -{ - nsCOMPtr channelData = new TVChannelData(); - channelData->SetNetworkId(aNetworkId); - channelData->SetTransportStreamId(aTransportStreamId); - channelData->SetServiceId(aServiceId); - channelData->SetType(aType); - channelData->SetNumber(aNumber); - channelData->SetName(aName); - channelData->SetIsEmergency(aIsEmergency); - channelData->SetIsFree(aIsFree); - return channelData.forget(); -} - -already_AddRefed -FakeTVService::MockProgram(const nsAString& aEventId, - const nsAString& aTitle, - uint64_t aStartTime, - uint64_t aDuration, - const nsAString& aDescription, - const nsAString& aRating, - uint32_t aAudioLanguageCount, - const char** aAudioLanguages, - uint32_t aSubtitleLanguageCount, - const char** aSubtitleLanguages) -{ - nsCOMPtr programData = new TVProgramData(); - programData->SetEventId(aEventId); - programData->SetTitle(aTitle); - programData->SetStartTime(aStartTime); - programData->SetDuration(aDuration); - programData->SetDescription(aDescription); - programData->SetRating(aRating); - programData->SetAudioLanguages(aAudioLanguageCount, aAudioLanguages); - programData->SetSubtitleLanguages(aSubtitleLanguageCount, aSubtitleLanguages); - return programData.forget(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/tv/FakeTVService.h b/dom/tv/FakeTVService.h deleted file mode 100644 index 5ab07108a3b..00000000000 --- a/dom/tv/FakeTVService.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_FakeTVService_h -#define mozilla_dom_FakeTVService_h - -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsITVService.h" -#include "nsTArray.h" - -#define FAKE_TV_SERVICE_CONTRACTID \ - "@mozilla.org/tv/faketvservice;1" -#define FAKE_TV_SERVICE_CID \ - { 0x60fb3c53, 0x017f, 0x4340, { 0x91, 0x1b, 0xd5, 0x5c, 0x31, 0x28, 0x88, 0xb6 } } - -class nsITimer; -class nsITVTunerData; -class nsITVChannelData; -class nsITVProgramData; - -namespace mozilla { -namespace dom { - -class FakeTVService final : public nsITVService -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(FakeTVService) - NS_DECL_NSITVSERVICE - - FakeTVService(); - -private: - ~FakeTVService(); - - void Init(); - - void Shutdown(); - - bool IsAllowed(const nsAString& aTunerId, - const nsAString& aSourceType); - - already_AddRefed MockTuner(const nsAString& aId, - uint32_t aSupportedSourceTypeCount, - const char** aSupportedSourceTypes); - - already_AddRefed MockChannel(const nsAString& aNetworkId, - const nsAString& aTransportStreamId, - const nsAString& aServiceId, - const nsAString& aType, - const nsAString& aNumber, - const nsAString& aName, - bool aIsEmergency, - bool aIsFree); - - already_AddRefed MockProgram(const nsAString& aEventId, - const nsAString& aTitle, - uint64_t aStartTime, - uint64_t aDuration, - const nsAString& aDescription, - const nsAString& aRating, - uint32_t aAudioLanguageCount, - const char** aAudioLanguages, - uint32_t aSubtitleLanguageCount, - const char** aSubtitleLanguages); - - nsCOMPtr mSourceListener; - - // The real implementation may want to use more efficient data structures. - nsTArray> mTuners; - nsTArray> mChannels; - nsTArray> mPrograms; - nsCOMPtr mEITBroadcastedTimer; - nsCOMPtr mScanCompleteTimer; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_FakeTVService_h diff --git a/dom/tv/TVServiceFactory.cpp b/dom/tv/TVServiceFactory.cpp index 70979505b36..2a2fda4463b 100644 --- a/dom/tv/TVServiceFactory.cpp +++ b/dom/tv/TVServiceFactory.cpp @@ -4,7 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/dom/FakeTVService.h" #include "mozilla/dom/TVListeners.h" #include "mozilla/Preferences.h" #include "nsITVService.h" @@ -15,26 +14,14 @@ namespace mozilla { namespace dom { -/* static */ already_AddRefed -TVServiceFactory::CreateFakeTVService() -{ - RefPtr service = new FakeTVService(); - return service.forget(); -} - /* static */ already_AddRefed TVServiceFactory::AutoCreateTVService() { - nsresult rv; + nsresult rv = NS_OK; nsCOMPtr service = do_CreateInstance(TV_SERVICE_CONTRACTID); if (!service) { - if (Preferences::GetBool("dom.ignore_webidl_scope_checks", false)) { - // Fallback to the fake service. - service = do_CreateInstance(FAKE_TV_SERVICE_CONTRACTID, &rv); - } else { - // Fallback to the TV Simulator Service - service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID, &rv); - } + // Fallback to the TV Simulator Service + service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; diff --git a/dom/tv/TVServiceFactory.h b/dom/tv/TVServiceFactory.h index 004bc7ae6f0..93e81a83391 100644 --- a/dom/tv/TVServiceFactory.h +++ b/dom/tv/TVServiceFactory.h @@ -14,13 +14,9 @@ class nsITVService; namespace mozilla { namespace dom { -class FakeTVService; - class TVServiceFactory { public: - static already_AddRefed CreateFakeTVService(); - static already_AddRefed AutoCreateTVService(); }; diff --git a/dom/tv/TVSimulatorService.js b/dom/tv/TVSimulatorService.js index 785e9d8d223..8b641e055fb 100644 --- a/dom/tv/TVSimulatorService.js +++ b/dom/tv/TVSimulatorService.js @@ -13,9 +13,11 @@ const Ci = Components.interfaces; const Cr = Components.returnCode; Cu.importGlobalProperties(["File"]); +Cu.import("resource://gre/modules/Services.jsm"); -const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy"; -const TV_SIMULATOR_DUMMY_FILE = "settings.json"; +const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy"; +const TV_SIMULATOR_DUMMY_FILE = "settings.json"; +const TV_SIMULATOR_MOCK_DATA = Services.prefs.getCharPref("dom.testing.tv_mock_data"); // See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVSourceType const TV_SOURCE_TYPES = ["dvb-t","dvb-t2","dvb-c","dvb-c2","dvb-s", @@ -49,36 +51,16 @@ TVSimulatorService.prototype = { return; } - // Load the setting file from local JSON file. - // Synchrhronous File Reading. - let file = Cc["@mozilla.org/file/local;1"] - .createInstance(Ci.nsILocalFile); - - file.initWithPath(this._getFilePath(TV_SIMULATOR_DUMMY_FILE)); - - let fstream = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"] - .createInstance(Ci.nsIConverterInputStream); - let settingStr = ""; - try { - fstream.init(file, -1, 0, 0); - cstream.init(fstream, - "UTF-8", - 1024, - Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); - - let str = {}; - while (cstream.readString(0xffffffff, str) != 0) { - settingStr += str.value; + if (TV_SIMULATOR_MOCK_DATA) { + settingStr = TV_SIMULATOR_MOCK_DATA; + } else { + settingStr = this._getDummyData(); } } catch(e) { debug("Error occurred : " + e ); return; - } finally { - cstream.close(); } let settingsObj; @@ -281,10 +263,11 @@ TVSimulatorService.prototype = { } this._scanCompleteTimer = null; + let notifyResult = this._sourceListener.notifyChannelScanComplete( + this._scanningWrapTunerData.tuner.id, + this._scanningWrapTunerData.sourceType); this._scanningWrapTunerData = null; - return this._sourceListener.notifyChannelScanComplete( - this._scanningWrapTunerData.tuner.id, - this._scanningWrapTunerData.sourceType); + return notifyResult; }, stopScanningChannels: function TVSimStopScanningChannels(aTunerId, aSourceType, aCallback) { @@ -434,6 +417,41 @@ TVSimulatorService.prototype = { return videoBlobURL; }, + _getDummyData : function TVSimGetDummyData() { + // Load the setting file from local JSON file. + // Synchrhronous File Reading. + let file = Cc["@mozilla.org/file/local;1"] + .createInstance(Ci.nsILocalFile); + + let fstream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"] + .createInstance(Ci.nsIConverterInputStream); + + let settingsStr = ""; + + try { + file.initWithPath(this._getFilePath(TV_SIMULATOR_DUMMY_FILE)); + fstream.init(file, -1, 0, 0); + cstream.init(fstream, + "UTF-8", + 1024, + Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + + let str = {}; + while (cstream.readString(0xffffffff, str) != 0) { + settingsStr += str.value; + } + } catch(e) { + debug("Catch the Exception when reading the dummy file:" + e ); + throw e; + } finally { + cstream.close(); + } + + return settingsStr; + }, + _getTunerMapKey: function TVSimGetTunerMapKey(aTunerId, aSourceType) { return JSON.stringify({'tunerId': aTunerId, 'sourceType': aSourceType}); }, diff --git a/dom/tv/moz.build b/dom/tv/moz.build index 58a9ff9808e..44bd63a03b5 100644 --- a/dom/tv/moz.build +++ b/dom/tv/moz.build @@ -5,7 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.dom += [ - 'FakeTVService.h', 'TVChannel.h', 'TVListeners.h', 'TVManager.h', @@ -20,7 +19,6 @@ EXPORTS.mozilla.dom += [ ] UNIFIED_SOURCES += [ - 'FakeTVService.cpp', 'TVChannel.cpp', 'TVListeners.cpp', 'TVManager.cpp', diff --git a/dom/tv/test/mochitest/head.js b/dom/tv/test/mochitest/head.js index 3afe89296c6..27471e929d1 100644 --- a/dom/tv/test/mochitest/head.js +++ b/dom/tv/test/mochitest/head.js @@ -9,8 +9,20 @@ function setupPrefsAndPermissions(callback) { } function setupPrefs(callback) { - SpecialPowers.pushPrefEnv({"set": [["dom.tv.enabled", true], - ["dom.ignore_webidl_scope_checks", true]]}, function() { + let xhr = new XMLHttpRequest; + let data; + + xhr.open("GET", "./mock_data.json", false); + xhr.send(null); + if (xhr.status == 200) { + data = xhr.responseText; + } + + SpecialPowers.pushPrefEnv({"set": [ + ["dom.tv.enabled", true], + ["dom.ignore_webidl_scope_checks", true], + ["dom.testing.tv_mock_data", data] + ]}, function() { callback(); }); } diff --git a/dom/tv/test/mochitest/mochitest.ini b/dom/tv/test/mochitest/mochitest.ini index 8b58db1f904..60df11a3026 100644 --- a/dom/tv/test/mochitest/mochitest.ini +++ b/dom/tv/test/mochitest/mochitest.ini @@ -1,6 +1,8 @@ [DEFAULT] -support-files = head.js -skip-if = (os == 'mac' && debug) || asan # Bug 1125477 +support-files = + head.js + mock_data.json + [test_tv_non_permitted_app.html] [test_tv_permitted_app.html] [test_tv_get_tuners.html] diff --git a/dom/tv/test/mochitest/mock_data.json b/dom/tv/test/mochitest/mock_data.json new file mode 100644 index 00000000000..b2a4f8e73be --- /dev/null +++ b/dom/tv/test/mochitest/mock_data.json @@ -0,0 +1,99 @@ +{ + "tuners": [ + { + "id":"1", + "supportedType": ["dvb-t"], + "sources": [ + { + "type": "dvb-t", + "channels": [ + { + "networkId": "32112", + "transportStreamId": "32112", + "serviceId": "40960", + "type": "tv", + "name": "TV #1", + "number" : 1, + "isEmergency": false, + "isFree" : true, + "videoFilePath": "tv1.ogv", + "programs": [ + {"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"422158917", "title":"News of Midnight", "startTime":"1431266400", "duration":"3600", "description":"Summary of today news", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]} + ] + }, + { + "_comment": "Channel Data", + "networkId": "32122", + "transportStreamId": "32122", + "serviceId": "40990", + "type": "tv", + "name": "TV #2", + "number" : 2, + "isEmergency": false, + "isFree" : true, + "videoFilePath": "tv2.ogv", + "programs": [ + {"eventId":"931109607","title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Provide news in morning", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"297834220","title":"Weekly News", "startTime":"1431259200", "duration":"10800", "description":"Poopular Music program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"866886159","title":"Weekly news", "startTime":"1431270000", "duration":"7200", "description":"Information program on Monday", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]} + ] + }, + { + "_comment": "Channel Data", + "networkId": "32132", + "transportStreamId": "32132", + "serviceId": "41020", + "type": "tv", + "name": "TV #3", + "number" : 3, + "isEmergency": false, + "isFree" : true, + "videoFilePath": "tv1.ogv", + "programs": [ + {"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"586216742", "title":"Information Program", "startTime":"1430697600", "duration":"7200", "description":"Provide program Information.", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]} + ] + }, + { + "_comment": "Channel Data", + "networkId": "32142", + "transportStreamId": "32142", + "serviceId": "41040", + "type": "tv", + "name": "TV #5", + "number" : 4, + "isEmergency": false, + "isFree" : true, + "videoFilePath": "tv2.ogv", + "programs": [ + {"eventId":"931109607","title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Provide news in morning", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"297834220","title":"Weekly News", "startTime":"1431259200", "duration":"10800", "description":"Poopular Music program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"866886159","title":"Weekly news", "startTime":"1431270000", "duration":"7200", "description":"Information program on Monday", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]} + ] + }, + { + "_comment": "Channel Data", + "networkId": "32152", + "transportStreamId": "32152", + "serviceId": "41060", + "type": "tv", + "name": "TV #5", + "number" : 5, + "isEmergency": false, + "isFree" : true, + "videoFilePath": "tv1.ogv", + "programs": [ + {"eventId":"734475972", "title":"News of Morning", "startTime":"1430686800", "duration":"10800", "description":"Morning News", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"586216742", "title":"Information Program", "startTime":"1430697600", "duration":"7200", "description":"Provide program Information.", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]}, + {"eventId":"533612446", "title":"Entertainment Program", "startTime":"1431270000", "duration":"7200", "description":"Midnight entertainment program", "rating":"0", "audioLanguages":["eng"], "subtitleLanguages":["eng"]} + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 2135a3b0982..93acfacf8a9 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1162,6 +1162,11 @@ public: int32_t limit = 0, int32_t allocLimit = 0); + /** + * Make sure that the given buffer size doesn't exceed the allocation limit. + */ + static bool CheckBufferSize(int32_t bufSize); + /** Make sure the given dimension satisfies the CheckSurfaceSize and is * within 8k limit. The 8k value is chosen a bit randomly. */ diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index f1f38e6a4eb..f9d7e5bca5f 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -333,6 +333,10 @@ GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = false, const IntRect& aSubImage = IntRect()) { + if (!aSurface) { + return nullptr; + } + IntRect subimage = IntRect(IntPoint(), aSurface->GetSize()); if (!aSubImage.IsEmpty()) { MOZ_ASSERT(!aExistingOnly); @@ -792,7 +796,7 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface, return; } - if (!IsValid()) { + if (!IsValid() || !aSurface) { gfxCriticalNote << "DrawSurface with bad surface " << cairo_surface_status(mSurface); return; } diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index f99b3a3d5e8..f2da085d34b 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -264,6 +264,12 @@ Factory::AllowedSurfaceSize(const IntSize &aSize) return CheckSurfaceSize(aSize); } +bool +Factory::CheckBufferSize(int32_t bufSize) +{ + return !sConfig || bufSize < sConfig->mMaxAllocSize; +} + bool Factory::CheckSurfaceSize(const IntSize &sz, int32_t extentLimit, diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index feac536f85b..bd264841197 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -22,6 +22,7 @@ #include "mozilla/layers/AsyncDragMetrics.h" #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/CompositorTypes.h" +#include "ImageTypes.h" #include "FrameMetrics.h" #include "FilterSupport.h" #include "mozilla/layers/GeckoContentController.h" @@ -714,6 +715,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mMaskLayerIndex); WriteParam(aMsg, aParam.mIsLayersIdRoot); WriteParam(aMsg, aParam.mUsesContainerScrolling); + WriteParam(aMsg, aParam.mIsScrollInfoLayer); WriteParam(aMsg, aParam.GetContentDescription()); } @@ -760,6 +762,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mMaskLayerIndex) && ReadParam(aMsg, aIter, &aResult->mIsLayersIdRoot) && ReadParam(aMsg, aIter, &aResult->mUsesContainerScrolling) && + ReadParam(aMsg, aIter, &aResult->mIsScrollInfoLayer) && ReadContentDescription(aMsg, aIter, aResult)); } }; @@ -797,7 +800,7 @@ template<> struct ParamTraits { typedef mozilla::layers::TextureInfo paramType; - + static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.mCompositableType); @@ -827,6 +830,14 @@ struct ParamTraits mozilla::gfx::SurfaceFormat::UNKNOWN> {}; +template <> +struct ParamTraits + : public ContiguousEnumSerializer< + mozilla::StereoMode, + mozilla::StereoMode::MONO, + mozilla::StereoMode::TOP_BOTTOM> +{}; + template <> struct ParamTraits { @@ -847,6 +858,7 @@ struct ParamTraits } }; + template <> struct ParamTraits { diff --git a/gfx/layers/BufferTexture.cpp b/gfx/layers/BufferTexture.cpp index 64c9f07ab29..2702a74e3dc 100644 --- a/gfx/layers/BufferTexture.cpp +++ b/gfx/layers/BufferTexture.cpp @@ -30,10 +30,10 @@ public: virtual void Deallocate(ISurfaceAllocator*) override; - MemoryTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + MemoryTextureData(const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, uint8_t* aBuffer, size_t aBufferSize) - : BufferTextureData(aSize, aFormat, aMoz2DBackend) + : BufferTextureData(aDesc, aMoz2DBackend) , mBuffer(aBuffer) , mBufferSize(aBufferSize) { @@ -67,9 +67,9 @@ public: virtual void Deallocate(ISurfaceAllocator* aAllocator) override; - ShmemTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + ShmemTextureData(const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem) - : BufferTextureData(aSize, aFormat, aMoz2DBackend) + : BufferTextureData(aDesc, aMoz2DBackend) , mShmem(aShmem) { MOZ_ASSERT(mShmem.Size()); @@ -97,43 +97,46 @@ BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } BufferTextureData* -BufferTextureData::CreateWithBufferSize(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - size_t aSize, - TextureFlags aTextureFlags) +BufferTextureData::CreateInternal(ISurfaceAllocator* aAllocator, + const BufferDescriptor& aDesc, + gfx::BackendType aMoz2DBackend, + int32_t aBufferSize, + TextureFlags aTextureFlags) { - if (aSize == 0) { - return nullptr; - } - - BufferTextureData* data; if (!aAllocator || aAllocator->IsSameProcess()) { - uint8_t* buffer = new (fallible) uint8_t[aSize]; + uint8_t* buffer = new (fallible) uint8_t[aBufferSize]; if (!buffer) { return nullptr; } - data = new MemoryTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, buffer, aSize); + return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize); } else { ipc::Shmem shm; - if (!aAllocator->AllocUnsafeShmem(aSize, OptimalShmemType(), &shm)) { + if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) { return nullptr; } - data = new ShmemTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, shm); + return new ShmemTextureData(aDesc, aMoz2DBackend, shm); + } +} + +BufferTextureData* +BufferTextureData::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + gfx::SurfaceFormat aFormat, + int32_t aBufferSize, + TextureFlags aTextureFlags) +{ + if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) { + return nullptr; } // Initialize the metadata with something, even if it will have to be rewritten // afterwards since we don't know the dimensions of the texture at this point. - if (aFormat == gfx::SurfaceFormat::YUV) { - YCbCrImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize()); - serializer.InitializeBufferInfo(gfx::IntSize(0,0), gfx::IntSize(0,0), StereoMode::MONO); - } else { - ImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize()); - serializer.InitializeBufferInfo(gfx::IntSize(0, 0), aFormat); - } + BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(), + 0, 0, 0, StereoMode::MONO); - return data; + return CreateInternal(aAllocator, desc, gfx::BackendType::NONE, aBufferSize, + aTextureFlags); } BufferTextureData* @@ -143,24 +146,41 @@ BufferTextureData::CreateForYCbCr(ISurfaceAllocator* aAllocator, StereoMode aStereoMode, TextureFlags aTextureFlags) { - size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize, aCbCrSize); - BufferTextureData* texture = CreateWithBufferSize(aAllocator, gfx::SurfaceFormat::YUV, - bufSize, aTextureFlags); - if (!texture) { + uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize); + if (bufSize == 0) { return nullptr; } - YCbCrImageDataSerializer serializer(texture->GetBuffer(), texture->GetBufferSize()); - serializer.InitializeBufferInfo(aYSize, aCbCrSize, aStereoMode); - texture->mSize = aYSize; + uint32_t yOffset; + uint32_t cbOffset; + uint32_t crOffset; + ImageDataSerializer::ComputeYCbCrOffsets(aYSize.width, aYSize.height, + aCbCrSize.width, aCbCrSize.height, + yOffset, cbOffset, crOffset); - return texture; + YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset, + crOffset, aStereoMode); + + return CreateInternal(aAllocator, descriptor, gfx::BackendType::NONE, bufSize, + aTextureFlags); +} + +gfx::IntSize +BufferTextureData::GetSize() const +{ + return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor); +} + +gfx::SurfaceFormat +BufferTextureData::GetFormat() const +{ + return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor); } bool BufferTextureData::SupportsMoz2D() const { - switch (mFormat) { + switch (GetFormat()) { case gfx::SurfaceFormat::YUV: case gfx::SurfaceFormat::NV12: case gfx::SurfaceFormat::UNKNOWN: @@ -179,12 +199,17 @@ BufferTextureData::BorrowDrawTarget() return dt.forget(); } - ImageDataSerializer serializer(GetBuffer(), GetBufferSize()); - if (!serializer.IsValid()) { + if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) { return nullptr; } - mDrawTarget = serializer.GetAsDrawTarget(mMoz2DBackend); + const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); + + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend, + GetBuffer(), rgb.size(), + stride, rgb.format()); + if (mDrawTarget) { RefPtr dt = mDrawTarget; return dt.forget(); @@ -192,7 +217,12 @@ BufferTextureData::BorrowDrawTarget() // TODO - should we warn? should we really fallback to cairo? perhaps // at least update mMoz2DBackend... - mDrawTarget = serializer.GetAsDrawTarget(gfx::BackendType::CAIRO); + if (mMoz2DBackend != gfx::BackendType::CAIRO) { + mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, + GetBuffer(), rgb.size(), + stride, rgb.format()); + } + if (!mDrawTarget) { gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend; } @@ -204,19 +234,16 @@ BufferTextureData::BorrowDrawTarget() bool BufferTextureData::BorrowMappedData(MappedTextureData& aData) { - if (mFormat == gfx::SurfaceFormat::YUV) { + if (GetFormat() == gfx::SurfaceFormat::YUV) { return false; } - ImageDataDeserializer view(GetBuffer(), GetBufferSize()); - if (!view.IsValid()) { - return false; - } + gfx::IntSize size = GetSize(); - aData.data = view.GetData(); - aData.size = view.GetSize(); - aData.stride = view.GetStride(); - aData.format = mFormat; + aData.data = GetBuffer(); + aData.size = size; + aData.format = GetFormat(); + aData.stride = ImageDataSerializer::ComputeRGBStride(aData.format, size.width); return true; } @@ -224,31 +251,32 @@ BufferTextureData::BorrowMappedData(MappedTextureData& aData) bool BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) { - if (mFormat != gfx::SurfaceFormat::YUV) { + if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) { return false; } - YCbCrImageDataDeserializer view(GetBuffer(), GetBufferSize()); - if (!view.IsValid()) { - return false; - } + const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); - aMap.stereoMode = view.GetStereoMode(); - aMap.metadata = GetBuffer(); + uint8_t* data = GetBuffer(); + auto ySize = desc.ySize(); + auto cbCrSize = desc.cbCrSize(); - aMap.y.data = view.GetYData(); - aMap.y.size = view.GetYSize(); - aMap.y.stride = view.GetYStride(); + aMap.stereoMode = desc.stereoMode(); + aMap.metadata = nullptr; + + aMap.y.data = data + desc.yOffset(); + aMap.y.size = ySize; + aMap.y.stride = ySize.width; aMap.y.skip = 0; - aMap.cb.data = view.GetCbData(); - aMap.cb.size = view.GetCbCrSize(); - aMap.cb.stride = view.GetCbCrStride(); + aMap.cb.data = data + desc.cbOffset(); + aMap.cb.size = cbCrSize; + aMap.cb.stride = cbCrSize.width; aMap.cb.skip = 0; - aMap.cr.data = view.GetCrData(); - aMap.cr.size = view.GetCbCrSize(); - aMap.cr.stride = view.GetCbCrStride(); + aMap.cr.data = data + desc.crOffset(); + aMap.cr.size = cbCrSize; + aMap.cr.stride = cbCrSize.width; aMap.cr.skip = 0; return true; @@ -257,9 +285,15 @@ BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) bool BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) { - ImageDataSerializer serializer(GetBuffer(), GetBufferSize()); + if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) { + return false; + } + const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); - RefPtr surface = serializer.GetAsSurface(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + RefPtr surface = + gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride, + rgb.size(), rgb.format()); if (!surface) { gfxCriticalError() << "Failed to get serializer as surface!"; @@ -304,6 +338,14 @@ BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) return true; } +void +BufferTextureData::SetDesciptor(const BufferDescriptor& aDescriptor) +{ + MOZ_ASSERT(mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor); + MOZ_ASSERT(mDescriptor.get_YCbCrDescriptor().ySize() == gfx::IntSize()); + mDescriptor = aDescriptor; +} + bool MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) { @@ -312,14 +354,13 @@ MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) return false; } - aOutDescriptor = SurfaceDescriptorMemory(reinterpret_cast(mBuffer), - GetFormat()); + uintptr_t ptr = reinterpret_cast(mBuffer); + aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr)); + return true; } -static bool InitBuffer(uint8_t* buf, size_t bufSize, - gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - TextureAllocationFlags aAllocFlags) +static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags) { if (!buf) { gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes"; @@ -333,8 +374,6 @@ static bool InitBuffer(uint8_t* buf, size_t bufSize, memset(buf, 0xFF, bufSize); } - ImageDataSerializer serializer(buf, bufSize); - serializer.InitializeBufferInfo(aSize, aFormat); return true; } @@ -344,24 +383,29 @@ MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags, ISurfaceAllocator*) { + // Should have used CreateForYCbCr. + MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); + if (aSize.width <= 0 || aSize.height <= 0) { gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height; return nullptr; } - uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat); + uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat); if (!bufSize) { return nullptr; } uint8_t* buf = new (fallible) uint8_t[bufSize]; - - if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) { - GfxMemoryImageReporter::DidAlloc(buf); - return new MemoryTextureData(aSize, aFormat, aMoz2DBackend, buf, bufSize); + if (!InitBuffer(buf, bufSize, aAllocFlags)) { + return nullptr; } - return nullptr; + GfxMemoryImageReporter::DidAlloc(buf); + + BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat); + + return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize); } void @@ -378,7 +422,7 @@ MemoryTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { - return MemoryTextureData::Create(mSize, mFormat, mMoz2DBackend, + return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend, aFlags, aAllocFlags, aAllocator); } @@ -390,7 +434,7 @@ ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) return false; } - aOutDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat()); + aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem)); return true; } @@ -402,6 +446,9 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, ISurfaceAllocator* aAllocator) { MOZ_ASSERT(aAllocator); + // Should have used CreateForYCbCr. + MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); + if (!aAllocator) { return nullptr; } @@ -411,7 +458,7 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, return nullptr; } - uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat); + uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat); if (!bufSize) { return nullptr; } @@ -422,11 +469,14 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } uint8_t* buf = shm.get(); - - if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) { - return new ShmemTextureData(aSize, aFormat, aMoz2DBackend, shm); + if (!InitBuffer(buf, bufSize, aAllocFlags)) { + return nullptr; } + BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat); + + return new ShmemTextureData(descriptor, aMoz2DBackend, shm); + return nullptr; } @@ -435,7 +485,7 @@ ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { - return ShmemTextureData::Create(mSize, mFormat, mMoz2DBackend, + return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend, aFlags, aAllocFlags, aAllocator); } diff --git a/gfx/layers/BufferTexture.h b/gfx/layers/BufferTexture.h index 01996777c54..c22424ca482 100644 --- a/gfx/layers/BufferTexture.h +++ b/gfx/layers/BufferTexture.h @@ -6,8 +6,6 @@ #ifndef MOZILLA_LAYERS_BUFFERETEXTURE #define MOZILLA_LAYERS_BUFFERETEXTURE -#include "mozilla/layers/ImageDataSerializer.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "mozilla/layers/TextureClient.h" #include "mozilla/ipc/SharedMemory.h" #include "mozilla/gfx/Types.h" @@ -25,24 +23,27 @@ public: TextureAllocationFlags aAllocFlags, ISurfaceAllocator* aAllocator); - static BufferTextureData* CreateWithBufferSize(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - size_t aSize, - TextureFlags aTextureFlags); - static BufferTextureData* CreateForYCbCr(ISurfaceAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode, TextureFlags aTextureFlags); + // It is generally better to use CreateForYCbCr instead. + // This creates a half-initialized texture since we don't know the sizes and + // offsets in the buffer. + static BufferTextureData* CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + gfx::SurfaceFormat aFormat, + int32_t aSize, + TextureFlags aTextureFlags); + virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; } virtual void Unlock() override {} - virtual gfx::IntSize GetSize() const override { return mSize; } + virtual gfx::IntSize GetSize() const override; - virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; } + virtual gfx::SurfaceFormat GetFormat() const override; virtual already_AddRefed BorrowDrawTarget() override; @@ -59,19 +60,26 @@ public: // use TextureClient's default implementation virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; + // Don't use this. + void SetDesciptor(const BufferDescriptor& aDesc); + protected: + static BufferTextureData* CreateInternal(ISurfaceAllocator* aAllocator, + const BufferDescriptor& aDesc, + gfx::BackendType aMoz2DBackend, + int32_t aBufferSize, + TextureFlags aTextureFlags); + virtual uint8_t* GetBuffer() = 0; virtual size_t GetBufferSize() = 0; - BufferTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend) - : mSize(aSize) - , mFormat(aFormat) + BufferTextureData(const BufferDescriptor& aDescriptor, gfx::BackendType aMoz2DBackend) + : mDescriptor(aDescriptor) , mMoz2DBackend(aMoz2DBackend) {} RefPtr mDrawTarget; - gfx::IntSize mSize; - gfx::SurfaceFormat mFormat; + BufferDescriptor mDescriptor; gfx::BackendType mMoz2DBackend; }; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index d3eb4c287ec..dcddca5e7a7 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -68,6 +68,7 @@ public: , mAllowVerticalScrollWithWheel(false) , mIsLayersIdRoot(false) , mUsesContainerScrolling(false) + , mIsScrollInfoLayer(false) { } @@ -104,7 +105,8 @@ public: mClipRect == aOther.mClipRect && mMaskLayerIndex == aOther.mMaskLayerIndex && mIsLayersIdRoot == aOther.mIsLayersIdRoot && - mUsesContainerScrolling == aOther.mUsesContainerScrolling; + mUsesContainerScrolling == aOther.mUsesContainerScrolling && + mIsScrollInfoLayer == aOther.mIsScrollInfoLayer; } bool operator!=(const FrameMetrics& aOther) const { @@ -545,6 +547,13 @@ public: return mUsesContainerScrolling; } + void SetIsScrollInfoLayer(bool aIsScrollInfoLayer) { + mIsScrollInfoLayer = aIsScrollInfoLayer; + } + bool IsScrollInfoLayer() const { + return mIsScrollInfoLayer; + } + private: // The pres-shell resolution that has been induced on the document containing @@ -732,6 +741,9 @@ private: // when containerful scrolling is eliminated. bool mUsesContainerScrolling; + // Whether or not this frame has a "scroll info layer" to capture events. + bool mIsScrollInfoLayer; + // WARNING!!!! // // When adding new fields to FrameMetrics, the following places should be diff --git a/gfx/layers/ImageDataSerializer.cpp b/gfx/layers/ImageDataSerializer.cpp index 0ca952c6994..bdda5467157 100644 --- a/gfx/layers/ImageDataSerializer.cpp +++ b/gfx/layers/ImageDataSerializer.cpp @@ -4,70 +4,27 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageDataSerializer.h" +#include // for memcpy #include "gfx2DGlue.h" // for SurfaceFormatToImageFormat #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory #include "mozilla/gfx/Logging.h" // for gfxDebug #include "mozilla/gfx/Tools.h" // for GetAlignedStride, etc +#include "mozilla/gfx/Types.h" #include "mozilla/mozalloc.h" // for operator delete, etc +#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc namespace mozilla { namespace layers { +namespace ImageDataSerializer { using namespace gfx; -// The Data is layed out as follows: -// -// +-------------------+ -++ --+ <-- ImageDataSerializerBase::mData pointer -// | SurfaceBufferInfo | | | -// +-------------------+ --+ | offset -// | ... | | -// +-------------------+ ------+ -// | | -// | data | -// | | -// +-------------------+ +#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) -// Structure written at the beginning of the data blob containing the image -// (as shown in the figure above). It contains the necessary informations to -// read the image in the blob. -namespace { -struct SurfaceBufferInfo -{ - int32_t width; - int32_t height; - SurfaceFormat format; - - static int32_t GetOffset() - { - return GetAlignedStride<16>(sizeof(SurfaceBufferInfo)); - } -}; -} // namespace - -static SurfaceBufferInfo* -GetBufferInfo(uint8_t* aData, size_t aDataSize) -{ - return aDataSize >= sizeof(SurfaceBufferInfo) - ? reinterpret_cast(aData) - : nullptr; -} - -void -ImageDataSerializer::InitializeBufferInfo(IntSize aSize, - SurfaceFormat aFormat) -{ - SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); - MOZ_ASSERT(info); // OK to assert here, this method is client-side-only - info->width = aSize.width; - info->height = aSize.height; - info->format = aFormat; - Validate(); -} - -static inline int32_t -ComputeStride(SurfaceFormat aFormat, int32_t aWidth) +int32_t +ComputeRGBStride(SurfaceFormat aFormat, int32_t aWidth) { CheckedInt size = BytesPerPixel(aFormat); size *= aWidth; @@ -79,9 +36,14 @@ ComputeStride(SurfaceFormat aFormat, int32_t aWidth) return GetAlignedStride<4>(size.value()); } +int32_t +GetRGBStride(const RGBDescriptor& aDescriptor) +{ + return ComputeRGBStride(aDescriptor.format(), aDescriptor.size().width); +} + uint32_t -ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize, - SurfaceFormat aFormat) +ComputeRGBBufferSize(IntSize aSize, SurfaceFormat aFormat) { MOZ_ASSERT(aSize.height >= 0 && aSize.width >= 0); @@ -91,9 +53,8 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize, return 0; } - int32_t bufsize = GetAlignedStride<16>(ComputeStride(aFormat, aSize.width) - * aSize.height) - + SurfaceBufferInfo::GetOffset(); + int32_t bufsize = GetAlignedStride<16>(ComputeRGBStride(aFormat, aSize.width) + * aSize.height); if (bufsize < 0) { // This should not be possible thanks to Factory::AllowedSurfaceSize @@ -103,75 +64,121 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize, return bufsize; } -void -ImageDataSerializerBase::Validate() -{ - mIsValid = false; - if (!mData) { - return; - } - SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); - if (!info) { - return; - } - size_t requiredSize = - ComputeMinBufferSize(IntSize(info->width, info->height), info->format); - mIsValid = !!requiredSize && requiredSize <= mDataSize; + +// Minimum required shmem size in bytes +uint32_t +ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, + const gfx::IntSize& aCbCrSize, int32_t aCbCrStride) +{ + MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0); + + if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 || + aYSize.width > aYStride || aCbCrSize.width > aCbCrStride || + aCbCrStride > aYStride || aCbCrSize.height > aYSize.height || + !gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height))) { + return 0; + } + // Overflow checks are performed in AllowedSurfaceSize + return MOZ_ALIGN_WORD(aYSize.height * aYStride) + + 2 * MOZ_ALIGN_WORD(aCbCrSize.height * aCbCrStride); } -uint8_t* -ImageDataSerializerBase::GetData() +// Minimum required shmem size in bytes +uint32_t +ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize) { - MOZ_ASSERT(IsValid()); - return mData + SurfaceBufferInfo::GetOffset(); + return ComputeYCbCrBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width); } uint32_t -ImageDataSerializerBase::GetStride() const +ComputeYCbCrBufferSize(uint32_t aBufferSize) { - MOZ_ASSERT(IsValid()); - SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); - return ComputeStride(GetFormat(), info->width); + return MOZ_ALIGN_WORD(aBufferSize); } -IntSize -ImageDataSerializerBase::GetSize() const +void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight, + int32_t cbCrStride, int32_t cbCrHeight, + uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset) { - MOZ_ASSERT(IsValid()); - SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); - return IntSize(info->width, info->height); + outYOffset = 0; + outCbOffset = outYOffset + MOZ_ALIGN_WORD(yStride * yHeight); + outCrOffset = outCbOffset + MOZ_ALIGN_WORD(cbCrStride * cbCrHeight); } -SurfaceFormat -ImageDataSerializerBase::GetFormat() const +gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor) { - MOZ_ASSERT(IsValid()); - return GetBufferInfo(mData, mDataSize)->format; -} - -already_AddRefed -ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend) -{ - MOZ_ASSERT(IsValid()); - RefPtr dt = gfx::Factory::CreateDrawTargetForData(aBackend, - GetData(), GetSize(), - GetStride(), GetFormat()); - if (!dt) { - gfxCriticalNote << "Failed GetAsDrawTarget " << IsValid() << ", " << hexa(size_t(mData)) << " + " << SurfaceBufferInfo::GetOffset() << ", " << GetSize() << ", " << GetStride() << ", " << (int)GetFormat(); + switch (aDescriptor.type()) { + case BufferDescriptor::TRGBDescriptor: + return aDescriptor.get_RGBDescriptor().format(); + case BufferDescriptor::TYCbCrDescriptor: + return gfx::SurfaceFormat::YUV; + default: + MOZ_CRASH(); } - return dt.forget(); } -already_AddRefed -ImageDataSerializerBase::GetAsSurface() +gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor) { - MOZ_ASSERT(IsValid()); - return Factory::CreateWrappingDataSourceSurface(GetData(), - GetStride(), - GetSize(), - GetFormat()); + switch (aDescriptor.type()) { + case BufferDescriptor::TRGBDescriptor: + return aDescriptor.get_RGBDescriptor().size(); + case BufferDescriptor::TYCbCrDescriptor: + return aDescriptor.get_YCbCrDescriptor().ySize(); + default: + MOZ_CRASH(); + } } +uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor) +{ + return aBuffer + aDescriptor.yOffset(); +} + +uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor) +{ + return aBuffer + aDescriptor.cbOffset(); +} + +uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor) +{ + return aBuffer + aDescriptor.crOffset(); +} + +already_AddRefed +DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor) +{ + gfx::IntSize ySize = aDescriptor.ySize(); + gfx::IntSize cbCrSize = aDescriptor.cbCrSize(); + int32_t yStride = ySize.width; + int32_t cbCrStride = cbCrSize.width; + + RefPtr result = + Factory::CreateDataSourceSurface(ySize, gfx::SurfaceFormat::B8G8R8X8); + if (NS_WARN_IF(!result)) { + return nullptr; + } + + DataSourceSurface::MappedSurface map; + if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) { + return nullptr; + } + + gfx::YUVType type = TypeFromSize(ySize.width, ySize.height, + cbCrSize.width, cbCrSize.height); + gfx::ConvertYCbCrToRGB32(GetYChannel(aBuffer, aDescriptor), + GetCbChannel(aBuffer, aDescriptor), + GetCrChannel(aBuffer, aDescriptor), + map.mData, + 0, 0, //pic x and y + ySize.width, ySize.height, + yStride, cbCrStride, + map.mStride, type); + result->Unmap(); + return result.forget(); +} + + +} // namespace ImageDataSerializer } // namespace layers } // namespace mozilla diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index ffbf5cfcebc..85afa41975d 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -24,72 +24,49 @@ class DrawTarget; namespace mozilla { namespace layers { -class ImageDataSerializerBase -{ -public: - bool IsValid() const { return mIsValid; } +namespace ImageDataSerializer { - uint8_t* GetData(); - uint32_t GetStride() const; - gfx::IntSize GetSize() const; - gfx::SurfaceFormat GetFormat() const; - already_AddRefed GetAsSurface(); - already_AddRefed GetAsDrawTarget(gfx::BackendType aBackend); +// RGB - static uint32_t ComputeMinBufferSize(gfx::IntSize aSize, - gfx::SurfaceFormat aFormat); +int32_t ComputeRGBStride(gfx::SurfaceFormat aFormat, int32_t aWidth); - size_t GetBufferSize() const { return mDataSize; } +int32_t GetRGBStride(const RGBDescriptor& aDescriptor); -protected: +uint32_t ComputeRGBBufferSize(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); - ImageDataSerializerBase(uint8_t* aData, size_t aDataSize) - : mData(aData) - , mDataSize(aDataSize) - , mIsValid(false) - {} - void Validate(); +// YCbCr - uint8_t* mData; - size_t mDataSize; - bool mIsValid; -}; +///This function is meant as a helper to know how much shared memory we need +///to allocate in a shmem in order to place a shared YCbCr image blob of +///given dimensions. +uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, + int32_t aYStride, + const gfx::IntSize& aCbCrSize, + int32_t aCbCrStride); +uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, + const gfx::IntSize& aCbCrSize); -/** - * A facility to serialize an image into a buffer of memory. - * This is intended for use with the IPC code, in order to copy image data - * into shared memory. - * Note that there is a separate serializer class for YCbCr images - * (see YCbCrImageDataSerializer.h). - */ -class MOZ_STACK_CLASS ImageDataSerializer : public ImageDataSerializerBase -{ -public: - ImageDataSerializer(uint8_t* aData, size_t aDataSize) - : ImageDataSerializerBase(aData, aDataSize) - { - // a serializer needs to be usable before correct buffer info has been written to it - mIsValid = !!mData; - } - void InitializeBufferInfo(gfx::IntSize aSize, - gfx::SurfaceFormat aFormat); -}; +uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize); -/** - * A facility to deserialize image data that has been serialized by an - * ImageDataSerializer. - */ -class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase -{ -public: - ImageDataDeserializer(uint8_t* aData, size_t aDataSize) - : ImageDataSerializerBase(aData, aDataSize) - { - Validate(); - } +void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight, + int32_t cbCrStride, int32_t cbCrHeight, + uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset); -}; +gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor); + +gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor); + +uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); + +uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); + +uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); + +already_AddRefed +DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); + +} // ImageDataSerializer } // namespace layers } // namespace mozilla diff --git a/gfx/layers/YCbCrImageDataSerializer.cpp b/gfx/layers/YCbCrImageDataSerializer.cpp deleted file mode 100644 index a04aa0a3a26..00000000000 --- a/gfx/layers/YCbCrImageDataSerializer.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/layers/YCbCrImageDataSerializer.h" -#include // for memcpy -#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory -#include "mozilla/gfx/BaseSize.h" // for BaseSize -#include "mozilla/gfx/Logging.h" // for gfxDebug -#include "mozilla/gfx/Types.h" -#include "mozilla/mozalloc.h" // for operator delete -#include "nsDebug.h" // for NS_WARN_IF -#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc -#include "nsDebug.h" - -#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) - -namespace mozilla { - -using namespace gfx; - -namespace layers { - -// The Data is layed out as follows: -// -// +-----------------+ -++ --+ --+ <-- Beginning of the buffer -// | YCbCrBufferInfo | | | | -// +-----------------+ --+ | | -// | data | | | YCbCrBufferInfo->[mY/mCb/mCr]Offset -// +-----------------+ ------+ | -// | data | | -// +-----------------+ ----------+ -// | data | -// +-----------------+ -// -// There can be padding between the blocks above to keep word alignment. - -// Structure written at the beginning og the data blob containing the image -// (as shown in the figure above). It contains the necessary informations to -// read the image in the blob. -struct YCbCrBufferInfo -{ - uint32_t mYOffset; - uint32_t mCbOffset; - uint32_t mCrOffset; - uint32_t mYStride; - uint32_t mYWidth; - uint32_t mYHeight; - uint32_t mCbCrStride; - uint32_t mCbCrWidth; - uint32_t mCbCrHeight; - StereoMode mStereoMode; -}; - -static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData, size_t aDataSize) -{ - return aDataSize >= sizeof(YCbCrBufferInfo) - ? reinterpret_cast(aData) - : nullptr; -} - -void YCbCrImageDataDeserializerBase::Validate() -{ - mIsValid = false; - if (!mData) { - return; - } - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - if (!info) { - return; - } - size_t requiredSize = ComputeMinBufferSize( - IntSize(info->mYWidth, info->mYHeight), - info->mYStride, - IntSize(info->mCbCrWidth, info->mCbCrHeight), - info->mCbCrStride); - mIsValid = requiredSize <= mDataSize; - -} - -uint8_t* YCbCrImageDataDeserializerBase::GetYData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return reinterpret_cast(info) + info->mYOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetCbData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return reinterpret_cast(info) + info->mCbOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetCrData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return reinterpret_cast(info) + info->mCrOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return (reinterpret_cast(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo)); -} - -uint32_t YCbCrImageDataDeserializerBase::GetYStride() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return info->mYStride; -} - -uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return info->mCbCrStride; -} - -gfx::IntSize YCbCrImageDataDeserializerBase::GetYSize() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return gfx::IntSize(info->mYWidth, info->mYHeight); -} - -gfx::IntSize YCbCrImageDataDeserializerBase::GetCbCrSize() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return gfx::IntSize(info->mCbCrWidth, info->mCbCrHeight); -} - -StereoMode YCbCrImageDataDeserializerBase::GetStereoMode() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return info->mStereoMode; -} - -// Offset in bytes -static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride) -{ - return MOZ_ALIGN_WORD(aHeight * aStride); -} - -// Minimum required shmem size in bytes -size_t -YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize, - uint32_t aYStride, - const gfx::IntSize& aCbCrSize, - uint32_t aCbCrStride) -{ - MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0); - if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0) { - gfxDebug() << "Non-positive YCbCr buffer size request " << aYSize.height << "x" << aYSize.width << ", " << aCbCrSize.height << "x" << aCbCrSize.width; - return 0; - } - - if (aYSize != IntSize() && - (!gfx::Factory::AllowedSurfaceSize(aYSize) || - aCbCrSize.width > aYSize.width || - aCbCrSize.height > aYSize.height)) { - return 0; - } - - return ComputeOffset(aYSize.height, aYStride) - + 2 * ComputeOffset(aCbCrSize.height, aCbCrStride) - + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo)); -} - -// Minimum required shmem size in bytes -size_t -YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize) -{ - return ComputeMinBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width); -} - -// Offset in bytes -static size_t ComputeOffset(uint32_t aSize) -{ - return MOZ_ALIGN_WORD(aSize); -} - -// Minimum required shmem size in bytes -size_t -YCbCrImageDataDeserializerBase::ComputeMinBufferSize(uint32_t aSize) -{ - return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo)); -} - -void -YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset, - uint32_t aCbOffset, - uint32_t aCrOffset, - uint32_t aYStride, - uint32_t aCbCrStride, - const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode) -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - MOZ_ASSERT(info); // OK to assert here, this method is client-side-only - uint32_t info_size = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo)); - info->mYOffset = info_size + aYOffset; - info->mCbOffset = info_size + aCbOffset; - info->mCrOffset = info_size + aCrOffset; - info->mYStride = aYStride; - info->mYWidth = aYSize.width; - info->mYHeight = aYSize.height; - info->mCbCrStride = aCbCrStride; - info->mCbCrWidth = aCbCrSize.width; - info->mCbCrHeight = aCbCrSize.height; - info->mStereoMode = aStereoMode; - Validate(); -} - -void -YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYStride, - uint32_t aCbCrStride, - const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode) -{ - uint32_t yOffset = 0; - uint32_t cbOffset = yOffset + MOZ_ALIGN_WORD(aYStride * aYSize.height); - uint32_t crOffset = cbOffset + MOZ_ALIGN_WORD(aCbCrStride * aCbCrSize.height); - return InitializeBufferInfo(yOffset, cbOffset, crOffset, - aYStride, aCbCrStride, aYSize, aCbCrSize, aStereoMode); -} - -void -YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode) -{ - return InitializeBufferInfo(aYSize.width, aCbCrSize.width, aYSize, aCbCrSize, aStereoMode); -} - -static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) { - for (uint32_t i = 0; i < len; ++i) { - *dst = *src; - src += 1 + skip; - ++dst; - } -} - -bool -YCbCrImageDataSerializer::CopyData(const uint8_t* aYData, - const uint8_t* aCbData, const uint8_t* aCrData, - gfx::IntSize aYSize, uint32_t aYStride, - gfx::IntSize aCbCrSize, uint32_t aCbCrStride, - uint32_t aYSkip, uint32_t aCbCrSkip) -{ - if (!IsValid() || GetYSize() != aYSize || GetCbCrSize() != aCbCrSize) { - return false; - } - for (int i = 0; i < aYSize.height; ++i) { - if (aYSkip == 0) { - // fast path - memcpy(GetYData() + i * GetYStride(), - aYData + i * aYStride, - aYSize.width); - } else { - // slower path - CopyLineWithSkip(aYData + i * aYStride, - GetYData() + i * GetYStride(), - aYSize.width, aYSkip); - } - } - for (int i = 0; i < aCbCrSize.height; ++i) { - if (aCbCrSkip == 0) { - // fast path - memcpy(GetCbData() + i * GetCbCrStride(), - aCbData + i * aCbCrStride, - aCbCrSize.width); - memcpy(GetCrData() + i * GetCbCrStride(), - aCrData + i * aCbCrStride, - aCbCrSize.width); - } else { - // slower path - CopyLineWithSkip(aCbData + i * aCbCrStride, - GetCbData() + i * GetCbCrStride(), - aCbCrSize.width, aCbCrSkip); - CopyLineWithSkip(aCrData + i * aCbCrStride, - GetCrData() + i * GetCbCrStride(), - aCbCrSize.width, aCbCrSkip); - } - } - return true; -} - -already_AddRefed -YCbCrImageDataDeserializer::ToDataSourceSurface() -{ - RefPtr result = - Factory::CreateDataSourceSurface(GetYSize(), gfx::SurfaceFormat::B8G8R8X8); - if (NS_WARN_IF(!result)) { - return nullptr; - } - - DataSourceSurface::MappedSurface map; - if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) { - return nullptr; - } - - gfx::YUVType type = TypeFromSize(GetYSize().width, GetYSize().height, - GetCbCrSize().width, GetCbCrSize().height); - gfx::ConvertYCbCrToRGB32(GetYData(), GetCbData(), GetCrData(), - map.mData, - 0, 0, //pic x and y - GetYSize().width, GetYSize().height, - GetYStride(), GetCbCrStride(), - map.mStride, type); - result->Unmap(); - return result.forget(); -} - - -} // namespace layers -} // namespace mozilla diff --git a/gfx/layers/YCbCrImageDataSerializer.h b/gfx/layers/YCbCrImageDataSerializer.h deleted file mode 100644 index ec55a85c5d6..00000000000 --- a/gfx/layers/YCbCrImageDataSerializer.h +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef MOZILLA_LAYERS_BLOBYCBCRSURFACE_H -#define MOZILLA_LAYERS_BLOBYCBCRSURFACE_H - -#include // for size_t -#include // for uint8_t, uint32_t -#include "ImageTypes.h" // for StereoMode -#include "mozilla/Attributes.h" // for MOZ_STACK_CLASS -#include "mozilla/RefPtr.h" // for already_AddRefed -#include "mozilla/gfx/Point.h" // for IntSize - -namespace mozilla { -namespace gfx { -class DataSourceSurface; -} // namespace gfx - -namespace layers { - -class Image; - -/** - * Convenience class to share code between YCbCrImageDataSerializer - * and YCbCrImageDataDeserializer. - * Do not use it. - */ -class YCbCrImageDataDeserializerBase -{ -public: - bool IsValid() const { return mIsValid; } - - /** - * Returns the Y channel data pointer. - */ - uint8_t* GetYData(); - /** - * Returns the Cb channel data pointer. - */ - uint8_t* GetCbData(); - /** - * Returns the Cr channel data pointer. - */ - uint8_t* GetCrData(); - - /** - * Returns the Y channel stride. - */ - uint32_t GetYStride(); - /** - * Returns the stride of the Cb and Cr channels. - */ - uint32_t GetCbCrStride(); - - /** - * Returns the dimensions of the Y Channel. - */ - gfx::IntSize GetYSize(); - - /** - * Returns the dimensions of the Cb and Cr Channel. - */ - gfx::IntSize GetCbCrSize(); - - /** - * Stereo mode for the image. - */ - StereoMode GetStereoMode(); - - /** - * Return a pointer to the begining of the data buffer. - */ - uint8_t* GetData(); - - /** - * This function is meant as a helper to know how much shared memory we need - * to allocate in a shmem in order to place a shared YCbCr image blob of - * given dimensions. - */ - static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize, - uint32_t aYStride, - const gfx::IntSize& aCbCrSize, - uint32_t aCbCrStride); - static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize); - static size_t ComputeMinBufferSize(uint32_t aSize); - -protected: - YCbCrImageDataDeserializerBase(uint8_t* aData, size_t aDataSize) - : mData (aData) - , mDataSize(aDataSize) - , mIsValid(false) - {} - - void Validate(); - - uint8_t* mData; - size_t mDataSize; - bool mIsValid; -}; - -/** - * A view on a YCbCr image stored with its metadata in a blob of memory. - * It is only meant as a convenience to access the image data, and does not own - * the data. The instance can live on the stack and used as follows: - * - * const YCbCrImage& yuv = sharedImage.get_YCbCrImage(); - * YCbCrImageDataDeserializer deserializer(yuv.data().get()); - * if (!deserializer.IsValid()) { - * // handle error - * } - * size = deserializer.GetYSize(); // work with the data, etc... - */ -class MOZ_STACK_CLASS YCbCrImageDataSerializer : public YCbCrImageDataDeserializerBase -{ -public: - YCbCrImageDataSerializer(uint8_t* aData, size_t aDataSize) - : YCbCrImageDataDeserializerBase(aData, aDataSize) - { - // a serializer needs to be usable before correct buffer info has been written to it - mIsValid = !!mData; - } - - /** - * Write the image informations in the buffer for given dimensions. - * The provided pointer should point to the beginning of the (chunk of) - * buffer on which we want to store the image. - */ - void InitializeBufferInfo(uint32_t aYOffset, - uint32_t aCbOffset, - uint32_t aCrOffset, - uint32_t aYStride, - uint32_t aCbCrStride, - const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode); - void InitializeBufferInfo(uint32_t aYStride, - uint32_t aCbCrStride, - const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode); - void InitializeBufferInfo(const gfx::IntSize& aYSize, - const gfx::IntSize& aCbCrSize, - StereoMode aStereoMode); - bool CopyData(const uint8_t* aYData, - const uint8_t* aCbData, const uint8_t* aCrData, - gfx::IntSize aYSize, uint32_t aYStride, - gfx::IntSize aCbCrSize, uint32_t aCbCrStride, - uint32_t aYSkip, uint32_t aCbCrSkip); -}; - -/** - * A view on a YCbCr image stored with its metadata in a blob of memory. - * It is only meant as a convenience to access the image data, and does not own - * the data. The instance can live on the stack and used as follows: - * - * const YCbCrImage& yuv = sharedImage.get_YCbCrImage(); - * YCbCrImageDataDeserializer deserializer(yuv.data().get()); - * if (!deserializer.IsValid()) { - * // handle error - * } - * size = deserializer.GetYSize(); // work with the data, etc... - */ -class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase -{ -public: - YCbCrImageDataDeserializer(uint8_t* aData, size_t aDataSize) - : YCbCrImageDataDeserializerBase(aData, aDataSize) - { - Validate(); - } - - /** - * Convert the YCbCr data into RGB and return a DataSourceSurface. - * This is a costly operation, so use it only when YCbCr compositing is - * not supported. - */ - already_AddRefed ToDataSourceSurface(); -}; - -} // namespace layers -} // namespace mozilla - -#endif diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index c2b071afcb0..42f3cdbf924 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -28,7 +28,6 @@ #include "nsPoint.h" // for nsIntPoint #include "nsThreadUtils.h" // for NS_IsMainThread #include "OverscrollHandoffState.h" // for OverscrollHandoffState -#include "TaskThrottler.h" // for TaskThrottler #include "TreeTraversal.h" // for generic tree traveral algorithms #include "LayersLogging.h" // for Stringify #include "Units.h" // for ParentlayerPixel @@ -86,11 +85,10 @@ struct APZCTreeManager::TreeBuildingState { /*static*/ const ScreenMargin APZCTreeManager::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, - double aEstimatedPaintDuration) + const ParentLayerPoint& aVelocity) { return AsyncPanZoomController::CalculatePendingDisplayPort( - aFrameMetrics, aVelocity, aEstimatedPaintDuration); + aFrameMetrics, aVelocity); } APZCTreeManager::APZCTreeManager() @@ -111,11 +109,10 @@ APZCTreeManager::~APZCTreeManager() AsyncPanZoomController* APZCTreeManager::NewAPZCInstance(uint64_t aLayersId, - GeckoContentController* aController, - TaskThrottler* aPaintThrottler) + GeckoContentController* aController) { return new AsyncPanZoomController(aLayersId, this, mInputQueue, - aController, aPaintThrottler, AsyncPanZoomController::USE_GESTURE_DETECTOR); + aController, AsyncPanZoomController::USE_GESTURE_DETECTOR); } TimeStamp @@ -201,32 +198,6 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor, #endif } -void -APZCTreeManager::InitializeForLayersId(uint64_t aLayersId) -{ - MOZ_ASSERT(NS_IsMainThread()); - auto throttlerInsertResult = mPaintThrottlerMap.insert( - std::make_pair(aLayersId, RefPtr())); - if (throttlerInsertResult.second) { - throttlerInsertResult.first->second = new TaskThrottler( - GetFrameTime(), TimeDuration::FromMilliseconds(500)); - } -} - -void -APZCTreeManager::AdoptLayersId(uint64_t aLayersId, APZCTreeManager* aOldManager) -{ - MOZ_ASSERT(aOldManager); - if (aOldManager == this) { - return; - } - auto iter = aOldManager->mPaintThrottlerMap.find(aLayersId); - if (iter != aOldManager->mPaintThrottlerMap.end()) { - mPaintThrottlerMap[aLayersId] = iter->second; - aOldManager->mPaintThrottlerMap.erase(iter); - } -} - // Compute the clip region to be used for a layer with an APZC. This function // is only called for layers which actually have scrollable metrics and an APZC. static ParentLayerIntRegion @@ -462,12 +433,7 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, // a destroyed APZC and so we need to throw that out and make a new one. bool newApzc = (apzc == nullptr || apzc->IsDestroyed()); if (newApzc) { - // Look up the paint throttler for this layers id, or create it if - // this is the first APZC for this layers id. - RefPtr throttler = mPaintThrottlerMap[aLayersId]; - MOZ_ASSERT(throttler); - - apzc = NewAPZCInstance(aLayersId, state->mController, throttler); + apzc = NewAPZCInstance(aLayersId, state->mController); apzc->SetCompositorParent(aState.mCompositor); if (state->mCrossProcessParent != nullptr) { apzc->ShareFrameMetricsAcrossProcesses(); @@ -657,23 +623,10 @@ WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput) void APZCTreeManager::FlushApzRepaints(uint64_t aLayersId) { + // Previously, paints were throttled and therefore this method was used to + // ensure any pending paints were flushed. Now, paints are flushed + // immediately, so it is safe to simply send a notification now. APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId); - { // scope lock - MonitorAutoLock lock(mTreeLock); - mTreeLock.AssertCurrentThreadOwns(); - - ForEachNode(mRootNode.get(), - [aLayersId](HitTestingTreeNode* aNode) - { - if (aNode->IsPrimaryHolder()) { - AsyncPanZoomController* apzc = aNode->GetApzc(); - MOZ_ASSERT(apzc); - if (apzc->GetGuid().mLayersId == aLayersId) { - apzc->FlushRepaintIfPending(); - } - } - }); - } const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); MOZ_ASSERT(state && state->mController); NS_DispatchToMainThread(NS_NewRunnableMethod( diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index e42faa95efb..f6b9fd4b633 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -52,7 +52,6 @@ class LayerMetricsWrapper; class InputQueue; class GeckoContentController; class HitTestingTreeNode; -class TaskThrottler; /** * ****************** NOTE ON LOCK ORDERING IN APZ ************************** @@ -137,17 +136,6 @@ public: uint64_t aOriginatingLayersId, uint32_t aPaintSequenceNumber); - /** - * Do any per-layers-id setup needed. This will be called on the main thread, - * and may be called multiple times for the same layers id. - */ - void InitializeForLayersId(uint64_t aLayersId); - - /** - * Move any per-layers-id state from the old APZCTreeManager to this one. - */ - void AdoptLayersId(uint64_t aLayersId, APZCTreeManager* aOldManager); - /** * Walk the tree of APZCs and flushes the repaint requests for all the APZCS * corresponding to the given layers id. Finally, sends a flush complete @@ -286,8 +274,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, - double aEstimatedPaintDuration); + const ParentLayerPoint& aVelocity); /** * Set the dpi value used by all AsyncPanZoomControllers. @@ -420,8 +407,7 @@ protected: // Protected hooks for gtests subclass virtual AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId, - GeckoContentController* aController, - TaskThrottler* aPaintThrottler); + GeckoContentController* aController); public: // Public hooks for gtests subclass virtual TimeStamp GetFrameTime(); @@ -536,10 +522,6 @@ private: /* Holds the zoom constraints for scrollable layers, as determined by the * the main-thread gecko code. */ std::map mZoomConstraints; - /* Stores a paint throttler for each layers id. There is one for each layers - * id to ensure that one child process painting slowly doesn't hold up - * another. */ - std::map> mPaintThrottlerMap; /* This tracks the APZC that should receive all inputs for the current input event block. * This allows touch points to move outside the thing they started on, but still have the * touch events delivered to the same initial APZC. This will only ever be touched on the diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index ae69361b36a..a4424c13e48 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -18,7 +18,6 @@ #include "InputBlockState.h" // for InputBlockState, TouchBlockState #include "InputQueue.h" // for InputQueue #include "OverscrollHandoffState.h" // for OverscrollHandoffState -#include "TaskThrottler.h" // for TaskThrottler #include "Units.h" // for CSSRect, CSSPoint, etc #include "UnitTransforms.h" // for TransformTo #include "base/message_loop.h" // for MessageLoop @@ -239,9 +238,6 @@ using mozilla::gfx::PointTyped; * rather than using the "stationary" multipliers.\n * Units: CSS pixels per millisecond * - * \li\b apz.num_paint_duration_samples - * Number of samples to store of how long it took to paint after the previous - * * \li\b apz.overscroll.enabled * Pref that enables overscrolling. If this is disabled, excess scroll that * cannot be handed off is discarded. @@ -303,12 +299,6 @@ using mozilla::gfx::PointTyped; * within this distance on scrollable frames.\n * Units: (real-world, i.e. screen) inches * - * \li\b apz.use_paint_duration - * Whether or not to use the estimated paint duration as a factor when projecting - * the displayport in the direction of scrolling. If this value is set to false, - * a constant 50ms paint time is used; the projection can be scaled as desired - * using the \b apz.velocity_bias pref below. - * * \li\b apz.velocity_bias * How much to adjust the displayport in the direction of scrolling. This value * is multiplied by the velocity and added to the displayport offset. @@ -356,6 +346,12 @@ StaticAutoPtr gZoomAnimationFunction; */ StaticAutoPtr gVelocityCurveFunction; +/** + * The estimated duration of a paint for the purposes of calculating a new + * displayport, in milliseconds. + */ +static const double kDefaultEstimatedPaintDurationMs = 50; + /** * Returns true if this is a high memory system and we can use * extra memory for a larger displayport to reduce checkerboarding. @@ -851,10 +847,8 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, APZCTreeManager* aTreeManager, const RefPtr& aInputQueue, GeckoContentController* aGeckoContentController, - TaskThrottler* aPaintThrottler, GestureBehavior aGestures) : mLayersId(aLayersId), - mPaintThrottler(aPaintThrottler), mGeckoContentController(aGeckoContentController), mRefPtrMonitor("RefPtrMonitor"), // mTreeManager must be initialized before GetFrameTime() is called @@ -2695,9 +2689,14 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, /* static */ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, - double aEstimatedPaintDuration) + const ParentLayerPoint& aVelocity) { + if (aFrameMetrics.IsScrollInfoLayer()) { + // Don't compute margins. Since we can't asynchronously scroll this frame, + // we don't want to paint anything more than the composition bounds. + return ScreenMargin(); + } + CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels(); CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom(); CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset(); @@ -2712,8 +2711,7 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( // Offset the displayport, depending on how fast we're moving and the // estimated time it takes to paint, to try to minimise checkerboarding. - float estimatedPaintDurationMillis = (float)(aEstimatedPaintDuration * 1000.0); - float paintFactor = (gfxPrefs::APZUsePaintDuration() ? estimatedPaintDurationMillis : 50.0f); + float paintFactor = kDefaultEstimatedPaintDurationMs; CSSRect displayPort = CSSRect(scrollOffset + (velocity * paintFactor * gfxPrefs::APZVelocityBias()), displayPortSize); @@ -2746,11 +2744,7 @@ void AsyncPanZoomController::ScheduleComposite() { void AsyncPanZoomController::ScheduleCompositeAndMaybeRepaint() { ScheduleComposite(); - - TimeDuration timePaintDelta = mPaintThrottler->TimeSinceLastRequest(GetFrameTime()); - if (timePaintDelta.ToMilliseconds() > gfxPrefs::APZPanRepaintInterval()) { - RequestContentRepaint(); - } + RequestContentRepaint(); } void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() { @@ -2763,25 +2757,10 @@ void AsyncPanZoomController::FlushRepaintForNewInputBlock() { APZC_LOG("%p flushing repaint for new input block\n", this); ReentrantMonitorAutoEnter lock(mMonitor); - // We need to send a new repaint request unthrottled, but that - // will obsolete any pending repaint request in the paint throttler. - // Therefore we should clear out the pending task and restore the - // state of mLastPaintRequestMetrics to what it was before the - // pending task was queued. - mPaintThrottler->CancelPendingTask(); - mLastPaintRequestMetrics = mLastDispatchedPaintMetrics; - - RequestContentRepaint(mFrameMetrics, false /* not throttled */); + RequestContentRepaint(mFrameMetrics); UpdateSharedCompositorFrameMetrics(); } -void AsyncPanZoomController::FlushRepaintIfPending() { - // Just tell the paint throttler to send the pending repaint request if - // there is one. - ReentrantMonitorAutoEnter lock(mMonitor); - mPaintThrottler->TaskComplete(GetFrameTime()); -} - bool AsyncPanZoomController::SnapBackIfOverscrolled() { ReentrantMonitorAutoEnter lock(mMonitor); // It's possible that we're already in the middle of an overscroll @@ -2824,11 +2803,8 @@ void AsyncPanZoomController::RequestContentRepaint() { RequestContentRepaint(mFrameMetrics); } -void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled) { - aFrameMetrics.SetDisplayPortMargins( - CalculatePendingDisplayPort(aFrameMetrics, - GetVelocityVector(), - mPaintThrottler->AverageDuration().ToSeconds())); +void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics) { + aFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(aFrameMetrics, GetVelocityVector())); aFrameMetrics.SetUseDisplayPortMargins(); // If we're trying to paint what we already think is painted, discard this @@ -2852,19 +2828,8 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, return; } - if (aThrottled) { - mPaintThrottler->PostTask( - FROM_HERE, - UniquePtr(NewRunnableMethod(this, - &AsyncPanZoomController::DispatchRepaintRequest, - aFrameMetrics)), - GetFrameTime()); - } else { - DispatchRepaintRequest(aFrameMetrics); - } - + DispatchRepaintRequest(aFrameMetrics); aFrameMetrics.SetPresShellId(mLastContentPaintMetrics.GetPresShellId()); - mLastPaintRequestMetrics = aFrameMetrics; } /*static*/ CSSRect @@ -2881,18 +2846,21 @@ GetDisplayPortRect(const FrameMetrics& aFrameMetrics) void AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics) { RefPtr controller = GetGeckoContentController(); - if (controller) { - APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this); - LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics)); - - if (NS_IsMainThread()) { - controller->RequestContentRepaint(aFrameMetrics); - } else { - NS_DispatchToMainThread(NS_NewRunnableMethodWithArg( - controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics)); - } - mLastDispatchedPaintMetrics = aFrameMetrics; + if (!controller) { + return; } + + APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this); + LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics)); + + if (NS_IsMainThread()) { + controller->RequestContentRepaint(aFrameMetrics); + } else { + NS_DispatchToMainThread(NS_NewRunnableMethodWithArg( + controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics)); + } + mExpectedGeckoMetrics = aFrameMetrics; + mLastPaintRequestMetrics = aFrameMetrics; } bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, @@ -2913,16 +2881,11 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, if (mAnimation) { bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta); *aOutDeferredTasks = mAnimation->TakeDeferredTasks(); - if (continueAnimation) { - if (mPaintThrottler->TimeSinceLastRequest(aSampleTime) > - mAnimation->mRepaintInterval) { - RequestContentRepaint(); - } - } else { + if (!continueAnimation) { mAnimation = nullptr; SetState(NOTHING); - RequestContentRepaint(); } + RequestContentRepaint(); UpdateSharedCompositorFrameMetrics(); return true; } @@ -3071,7 +3034,7 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); LayerPoint scrollChange = - (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) + (mLastContentPaintMetrics.GetScrollOffset() - mExpectedGeckoMetrics.GetScrollOffset()) * mLastContentPaintMetrics.GetDevPixelsPerCSSPixel() * mLastContentPaintMetrics.GetCumulativeResolution(); @@ -3081,7 +3044,7 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { LayoutDeviceToParentLayerScale2D lastContentZoom = mLastContentPaintMetrics.GetZoom() / mLastContentPaintMetrics.GetDevPixelsPerCSSPixel(); LayoutDeviceToParentLayerScale2D lastDispatchedZoom = - mLastDispatchedPaintMetrics.GetZoom() / mLastDispatchedPaintMetrics.GetDevPixelsPerCSSPixel(); + mExpectedGeckoMetrics.GetZoom() / mExpectedGeckoMetrics.GetDevPixelsPerCSSPixel(); gfxSize zoomChange = lastContentZoom / lastDispatchedZoom; return Matrix4x4::Translation(scrollChange.x, scrollChange.y, 0). @@ -3159,7 +3122,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset()); } - mPaintThrottler->TaskComplete(GetFrameTime()); bool needContentRepaint = false; bool viewportUpdated = false; if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().width, mFrameMetrics.GetCompositionBounds().width) && @@ -3190,16 +3152,13 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri if (aIsFirstPaint || isDefault) { // Initialize our internal state to something sane when the content // that was just painted is something we knew nothing about previously - mPaintThrottler->ClearHistory(); - mPaintThrottler->SetMaxDurations(gfxPrefs::APZNumPaintDurationSamples()); - CancelAnimation(); mFrameMetrics = aLayerMetrics; if (scrollOffsetUpdated) { AcknowledgeScrollUpdate(); } - mLastDispatchedPaintMetrics = aLayerMetrics; + mExpectedGeckoMetrics = aLayerMetrics; ShareCompositorFrameMetrics(); if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) { @@ -3252,6 +3211,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri mFrameMetrics.SetMaskLayerIndex(aLayerMetrics.GetMaskLayerIndex()); mFrameMetrics.SetIsLayersIdRoot(aLayerMetrics.IsLayersIdRoot()); mFrameMetrics.SetUsesContainerScrolling(aLayerMetrics.UsesContainerScrolling()); + mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer()); if (scrollOffsetUpdated) { APZC_LOG("%p updating scroll offset from %s to %s\n", this, @@ -3261,13 +3221,13 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri // Send an acknowledgement with the new scroll generation so that any // repaint requests later in this function go through. // Because of the scroll generation update, any inflight paint requests are - // going to be ignored by layout, and so mLastDispatchedPaintMetrics + // going to be ignored by layout, and so mExpectedGeckoMetrics // becomes incorrect for the purposes of calculating the LD transform. To - // correct this we need to update mLastDispatchedPaintMetrics to be the + // correct this we need to update mExpectedGeckoMetrics to be the // last thing we know was painted by Gecko. mFrameMetrics.CopyScrollInfoFrom(aLayerMetrics); AcknowledgeScrollUpdate(); - mLastDispatchedPaintMetrics = aLayerMetrics; + mExpectedGeckoMetrics = aLayerMetrics; // Cancel the animation (which might also trigger a repaint request) // after we update the scroll offset above. Otherwise we can be left @@ -3299,7 +3259,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri // above. mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics); AcknowledgeScrollUpdate(); - mLastDispatchedPaintMetrics = aLayerMetrics; + mExpectedGeckoMetrics = aLayerMetrics; if (mState == SMOOTH_SCROLL && mAnimation) { APZC_LOG("%p updating destination on existing animation\n", this); @@ -3438,9 +3398,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { endZoomToMetrics.SetScrollOffset(aRect.TopLeft()); endZoomToMetrics.SetDisplayPortMargins( - CalculatePendingDisplayPort(endZoomToMetrics, - ParentLayerPoint(0,0), - 0)); + CalculatePendingDisplayPort(endZoomToMetrics, ParentLayerPoint(0,0))); endZoomToMetrics.SetUseDisplayPortMargins(); StartAnimation(new ZoomAnimation( diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 0083ec91235..ad968c878b8 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -24,7 +24,6 @@ #include "APZUtils.h" #include "Layers.h" // for Layer::ScrollDirection #include "LayersTypes.h" -#include "TaskThrottler.h" #include "mozilla/gfx/Matrix.h" #include "nsRegion.h" @@ -104,7 +103,6 @@ public: APZCTreeManager* aTreeManager, const RefPtr& aInputQueue, GeckoContentController* aController, - TaskThrottler* aPaintThrottler, GestureBehavior aGestures = DEFAULT_GESTURES); // -------------------------------------------------------------------------- @@ -186,11 +184,6 @@ public: */ void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint); - /** - * Flush any pending repaint request. - */ - void FlushRepaintIfPending(); - /** * The platform implementation must set the compositor parent so that we can * request composites. @@ -269,8 +262,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, - double aEstimatedPaintDuration); + const ParentLayerPoint& aVelocity); nsEventStatus HandleDragEvent(const MouseInput& aEvent, const AsyncDragMetrics& aDragMetrics); @@ -597,7 +589,7 @@ protected: * the paint throttler. In particular, the GeckoContentController::RequestContentRepaint * function will be invoked before this function returns. */ - void RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled = true); + void RequestContentRepaint(FrameMetrics& aFrameMetrics); /** * Actually send the next pending paint request to gecko. @@ -651,7 +643,6 @@ protected: uint64_t mLayersId; RefPtr mCompositorParent; - RefPtr mPaintThrottler; /* Access to the following two fields is protected by the mRefPtrMonitor, since they are accessed on the UI thread but can be cleared on the @@ -699,15 +690,12 @@ private: // the Gecko state, it should be used as a basis for untransformation when // sending messages back to Gecko. FrameMetrics mLastContentPaintMetrics; - // The last metrics that we requested a paint for. These are used to make sure - // that we're not requesting a paint of the same thing that's already drawn. - // If we don't do this check, we don't get a ShadowLayersUpdated back. + // The last metrics used for a content repaint request. FrameMetrics mLastPaintRequestMetrics; - // The last metrics that we actually sent to Gecko. This allows us to transform - // inputs into a coordinate space that Gecko knows about. This assumes the pipe - // through which input events and repaint requests are sent to Gecko operates - // in a FIFO manner. - FrameMetrics mLastDispatchedPaintMetrics; + // The metrics that we expect content to have. This is updated when we + // request a content repaint, and when we receive a shadow layers update. + // This allows us to transform events into Gecko's coordinate space. + FrameMetrics mExpectedGeckoMetrics; AxisX mX; AxisY mY; diff --git a/gfx/layers/apz/src/TaskThrottler.cpp b/gfx/layers/apz/src/TaskThrottler.cpp deleted file mode 100644 index 415bf984d96..00000000000 --- a/gfx/layers/apz/src/TaskThrottler.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */ -/* vim: set sw=2 sts=2 ts=8 et tw=80 : */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TaskThrottler.h" - -#include "mozilla/layers/APZThreadUtils.h" - -#define TASK_LOG(...) -// #define TASK_LOG(...) printf_stderr("TASK: " __VA_ARGS__) - -namespace mozilla { -namespace layers { - -TaskThrottler::TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait) - : mMonitor("TaskThrottler") - , mOutstanding(false) - , mQueuedTask(nullptr) - , mStartTime(aTimeStamp) - , mMaxWait(aMaxWait) - , mMean(1) - , mTimeoutTask(nullptr) -{ -} - -TaskThrottler::~TaskThrottler() -{ - // The timeout task holds a strong reference to the TaskThrottler, so if the - // TaskThrottler is being destroyed, there's no need to cancel the task. -} - -void -TaskThrottler::PostTask(const tracked_objects::Location& aLocation, - UniquePtr aTask, const TimeStamp& aTimeStamp) -{ - MonitorAutoLock lock(mMonitor); - - TASK_LOG("%p got a task posted; mOutstanding=%d\n", this, mOutstanding); - aTask->SetBirthPlace(aLocation); - - if (mOutstanding) { - CancelPendingTask(lock); - if (TimeSinceLastRequest(aTimeStamp, lock) < mMaxWait) { - mQueuedTask = Move(aTask); - TASK_LOG("%p queued task %p\n", this, mQueuedTask.get()); - // Make sure the queued task is sent after mMaxWait time elapses, - // even if we don't get a TaskComplete() until then. - TimeDuration timeout = mMaxWait - TimeSinceLastRequest(aTimeStamp, lock); - mTimeoutTask = NewRunnableMethod(this, &TaskThrottler::OnTimeout); - APZThreadUtils::RunDelayedTaskOnCurrentThread(mTimeoutTask, timeout); - return; - } - // we've been waiting for more than the max-wait limit, so just fall through - // and send the new task already. - } - - mStartTime = aTimeStamp; - aTask->Run(); - mOutstanding = true; -} - -void -TaskThrottler::OnTimeout() -{ - MonitorAutoLock lock(mMonitor); - if (mQueuedTask) { - RunQueuedTask(TimeStamp::Now(), lock); - } - // The message loop will delete the posted timeout task. Make sure we don't - // keep a dangling pointer to it. - mTimeoutTask = nullptr; -} - -void -TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp) -{ - MonitorAutoLock lock(mMonitor); - - if (!mOutstanding) { - return; - } - - mMean.insert(aTimeStamp - mStartTime); - - if (mQueuedTask) { - RunQueuedTask(aTimeStamp, lock); - CancelTimeoutTask(lock); - } else { - mOutstanding = false; - } -} - -TimeDuration -TaskThrottler::AverageDuration() -{ - MonitorAutoLock lock(mMonitor); - - return mMean.empty() ? TimeDuration() : mMean.mean(); -} - -void -TaskThrottler::RunQueuedTask(const TimeStamp& aTimeStamp, - const MonitorAutoLock& aProofOfLock) -{ - TASK_LOG("%p running task %p\n", this, mQueuedTask.get()); - mStartTime = aTimeStamp; - mQueuedTask->Run(); - mQueuedTask = nullptr; -} - -void -TaskThrottler::CancelPendingTask() -{ - MonitorAutoLock lock(mMonitor); - CancelPendingTask(lock); -} - -void -TaskThrottler::CancelPendingTask(const MonitorAutoLock& aProofOfLock) -{ - if (mQueuedTask) { - TASK_LOG("%p cancelling task %p\n", this, mQueuedTask.get()); - mQueuedTask->Cancel(); - mQueuedTask = nullptr; - CancelTimeoutTask(aProofOfLock); - } -} - -void -TaskThrottler::CancelTimeoutTask(const MonitorAutoLock& aProofOfLock) -{ - if (mTimeoutTask) { - mTimeoutTask->Cancel(); - mTimeoutTask = nullptr; // the MessageLoop will destroy it - } -} - -TimeDuration -TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp) -{ - MonitorAutoLock lock(mMonitor); - return TimeSinceLastRequest(aTimeStamp, lock); -} - -TimeDuration -TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp, - const MonitorAutoLock& aProofOfLock) -{ - return aTimeStamp - mStartTime; -} - -void -TaskThrottler::ClearHistory() -{ - MonitorAutoLock lock(mMonitor); - - mMean.clear(); -} - -void -TaskThrottler::SetMaxDurations(uint32_t aMaxDurations) -{ - MonitorAutoLock lock(mMonitor); - - if (aMaxDurations != mMean.maxValues()) { - mMean = RollingMean(aMaxDurations); - } -} - -} // namespace layers -} // namespace mozilla diff --git a/gfx/layers/apz/src/TaskThrottler.h b/gfx/layers/apz/src/TaskThrottler.h deleted file mode 100644 index 50a799bb6ab..00000000000 --- a/gfx/layers/apz/src/TaskThrottler.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */ -/* vim: set sw=4 ts=8 et tw=80 : */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TaskThrottler_h -#define mozilla_dom_TaskThrottler_h - -#include // for uint32_t -#include "base/task.h" // for CancelableTask -#include "mozilla/Monitor.h" // for Monitor -#include "mozilla/mozalloc.h" // for operator delete -#include "mozilla/RollingMean.h" // for RollingMean -#include "mozilla/TimeStamp.h" // for TimeDuration, TimeStamp -#include "mozilla/UniquePtr.h" // for UniquePtr -#include "nsCOMPtr.h" // for nsCOMPtr -#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING -#include "nsTArray.h" // for nsTArray - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace mozilla { -namespace layers { - -/** The TaskThrottler prevents update event overruns. It is used in cases where - * you're sending an async message and waiting for a reply. You need to call - * PostTask to queue a task and TaskComplete when you get a response. - * - * The call to TaskComplete will run the most recent task posted since the last - * request was sent, if any. This means that at any time there can be at most 1 - * outstanding request being processed and at most 1 queued behind it. - * - * However, to guard against task runs that error out and fail to call TaskComplete, - * the TaskThrottler also has a max-wait timeout. If the caller requests a new - * task be posted, and it has been greater than the max-wait timeout since the - * last one was sent, then we send the new one regardless of whether or not the - * last one was marked as completed. - * - * This is used in the context of repainting a scrollable region. While another - * process is painting you might get several updates from the UI thread but when - * the paint is complete you want to send the most recent. - */ - -class TaskThrottler { -public: - TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait); - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TaskThrottler) - - /** Post a task to be run as soon as there are no outstanding tasks, or - * post it immediately if it has been more than the max-wait time since - * the last task was posted. - * - * @param aLocation Use the macro FROM_HERE - * @param aTask Ownership of this object is transferred to TaskThrottler - * which will delete it when it is either run or becomes - * obsolete or the TaskThrottler is destructed. - */ - void PostTask(const tracked_objects::Location& aLocation, - UniquePtr aTask, const TimeStamp& aTimeStamp); - /** - * Mark the task as complete and process the next queued task. - */ - void TaskComplete(const TimeStamp& aTimeStamp); - - /** - * Calculate the average time between processing the posted task and getting - * the TaskComplete() call back. - */ - TimeDuration AverageDuration(); - - /** - * Cancel the queued task if there is one. - */ - void CancelPendingTask(); - - /** - * Return the time elapsed since the last request was processed - */ - TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp); - - /** - * Clear average history. - */ - void ClearHistory(); - - /** - * @param aMaxDurations The maximum number of durations to measure. - */ - - void SetMaxDurations(uint32_t aMaxDurations); - -private: - mutable Monitor mMonitor; - bool mOutstanding; - UniquePtr mQueuedTask; - TimeStamp mStartTime; - TimeDuration mMaxWait; - RollingMean mMean; - CancelableTask* mTimeoutTask; // not owned because it's posted to a MessageLoop - // which deletes it - - ~TaskThrottler(); - void RunQueuedTask(const TimeStamp& aTimeStamp, - const MonitorAutoLock& aProofOfLock); - void CancelPendingTask(const MonitorAutoLock& aProofOfLock); - TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp, - const MonitorAutoLock& aProofOfLock); - void OnTimeout(); - void CancelTimeoutTask(const MonitorAutoLock& aProofOfLock); -}; - -} // namespace layers -} // namespace mozilla - -#endif // mozilla_dom_TaskThrottler_h diff --git a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp index f5bd514d0a0..602dccc7587 100644 --- a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp @@ -154,8 +154,7 @@ public: protected: AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId, - GeckoContentController* aController, - TaskThrottler* aPaintThrottler) override; + GeckoContentController* aController) override; TimeStamp GetFrameTime() override { return mcc->Time(); @@ -169,10 +168,9 @@ class TestAsyncPanZoomController : public AsyncPanZoomController { public: TestAsyncPanZoomController(uint64_t aLayersId, MockContentControllerDelayed* aMcc, TestAPZCTreeManager* aTreeManager, - TaskThrottler* aPaintThrottler, GestureBehavior aBehavior = DEFAULT_GESTURES) : AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(), - aMcc, aPaintThrottler, aBehavior) + aMcc, aBehavior) , mWaitForMainThread(false) , mcc(aMcc) {} @@ -261,11 +259,10 @@ private: AsyncPanZoomController* TestAPZCTreeManager::NewAPZCInstance(uint64_t aLayersId, - GeckoContentController* aController, - TaskThrottler* aPaintThrottler) + GeckoContentController* aController) { MockContentControllerDelayed* mcc = static_cast(aController); - return new TestAsyncPanZoomController(aLayersId, mcc, this, aPaintThrottler, + return new TestAsyncPanZoomController(aLayersId, mcc, this, AsyncPanZoomController::USE_GESTURE_DETECTOR); } @@ -297,9 +294,8 @@ protected: APZThreadUtils::SetControllerThread(MessageLoop::current()); mcc = new NiceMock(); - mPaintThrottler = new TaskThrottler(mcc->Time(), TimeDuration::FromMilliseconds(500)); tm = new TestAPZCTreeManager(mcc); - apzc = new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler, mGestureBehavior); + apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior); apzc->SetFrameMetrics(TestFrameMetrics()); } @@ -382,7 +378,6 @@ protected: AsyncPanZoomController::GestureBehavior mGestureBehavior; RefPtr mcc; - RefPtr mPaintThrottler; RefPtr tm; RefPtr apzc; }; @@ -819,7 +814,8 @@ protected: MakeApzcZoomable(); if (aShouldTriggerPinch) { - EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); + // One repaint request for each gesture. + EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(2); } else { EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); } @@ -1141,7 +1137,7 @@ TEST_F(APZCBasicTester, ComplexTransform) { // sides. RefPtr childApzc = - new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler); + new TestAsyncPanZoomController(0, mcc, tm); const char* layerTreeSyntax = "c(c)"; // LayerID 0 1 @@ -1248,7 +1244,8 @@ protected: void DoPanTest(bool aShouldTriggerScroll, bool aShouldBeConsumed, uint32_t aBehavior) { if (aShouldTriggerScroll) { - EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); + // One repaint request for each pan. + EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(2); } else { EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); } @@ -1357,8 +1354,6 @@ TEST_F(APZCPanningTester, PanWithPreventDefault) { } TEST_F(APZCBasicTester, Fling) { - EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); - int touchStart = 50; int touchEnd = 10; ParentLayerPoint pointOut; @@ -2422,10 +2417,8 @@ TEST_F(APZHitTestingTester, HitTesting2) { // because we have already issued a paint request with it. EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(12.5, 75)); - // This second pan will move the APZC by another 50 pixels but since the paint - // request dispatched above has not "completed", we will not dispatch another - // one yet. Now we have an async transform on top of the pending paint request - // transform. + // This second pan will move the APZC by another 50 pixels. + EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); ApzcPanNoFling(apzcroot, mcc, 100, 50); // Hit where layers[3] used to be. It should now hit the root. @@ -2433,18 +2426,16 @@ TEST_F(APZHitTestingTester, HitTesting2) { EXPECT_EQ(apzcroot, hit.get()); // transformToApzc doesn't unapply the root's own async transform EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc * ScreenPoint(75, 75)); - // transformToGecko unapplies the full async transform of -100 pixels, and then - // reapplies the "D" transform of -50 leading to an overall adjustment of +50 - EXPECT_EQ(ScreenPoint(75, 125), transformToGecko * ParentLayerPoint(75, 75)); + // transformToGecko unapplies the full async transform of -100 pixels + EXPECT_EQ(ScreenPoint(75, 75), transformToGecko * ParentLayerPoint(75, 75)); // Hit where layers[1] used to be. It should now hit the root. hit = GetTargetAPZC(ScreenPoint(25, 25)); EXPECT_EQ(apzcroot, hit.get()); // transformToApzc doesn't unapply the root's own async transform EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc * ScreenPoint(25, 25)); - // transformToGecko unapplies the full async transform of -100 pixels, and then - // reapplies the "D" transform of -50 leading to an overall adjustment of +50 - EXPECT_EQ(ScreenPoint(25, 75), transformToGecko * ParentLayerPoint(25, 25)); + // transformToGecko unapplies the full async transform of -100 pixels + EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(25, 25)); } TEST_F(APZCTreeManagerTester, ScrollablePaintedLayers) { @@ -3497,89 +3488,3 @@ public: private: TaskRunMetrics& mMetrics; }; - -class APZTaskThrottlerTester : public ::testing::Test { -public: - APZTaskThrottlerTester() - { - now = TimeStamp::Now(); - throttler = new TaskThrottler(now, TimeDuration::FromMilliseconds(100)); - } - -protected: - TimeStamp Advance(int aMillis = 5) - { - now = now + TimeDuration::FromMilliseconds(aMillis); - return now; - } - - UniquePtr NewTask() - { - return MakeUnique(metrics); - } - - TimeStamp now; - RefPtr throttler; - TaskRunMetrics metrics; -}; - -TEST_F(APZTaskThrottlerTester, BasicTest) { - // Check that posting the first task runs right away - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 1 - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - - // Check that posting the second task doesn't run until the first one is done - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 2 - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - throttler->TaskComplete(Advance()); // for task 1 - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - EXPECT_EQ(0, metrics.GetAndClearCancelCount()); - - // Check that tasks are coalesced: dispatch 5 tasks - // while there is still one outstanding, and ensure - // that only one of the 5 runs - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 3 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 4 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 5 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 6 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 7 - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - EXPECT_EQ(4, metrics.GetAndClearCancelCount()); - - throttler->TaskComplete(Advance()); // for task 2 - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - throttler->TaskComplete(Advance()); // for task 7 (tasks 3..6 were cancelled) - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - EXPECT_EQ(0, metrics.GetAndClearCancelCount()); -} - -TEST_F(APZTaskThrottlerTester, TimeoutTest) { - // Check that posting the first task runs right away - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 1 - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - - // Because we let 100ms pass, the second task should - // run immediately even though the first one isn't - // done yet - throttler->PostTask(FROM_HERE, NewTask(), Advance(100)); // task 2; task 1 is assumed lost - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - throttler->TaskComplete(Advance()); // for task 1, but TaskThrottler thinks it's for task 2 - throttler->TaskComplete(Advance()); // for task 2, TaskThrottler ignores it - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - EXPECT_EQ(0, metrics.GetAndClearCancelCount()); - - // This time queue up a few tasks before the timeout expires - // and ensure cancellation still works as expected - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 3 - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 4 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 5 - throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 6 - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - throttler->PostTask(FROM_HERE, NewTask(), Advance(100)); // task 7; task 3 is assumed lost - EXPECT_EQ(1, metrics.GetAndClearRunCount()); - EXPECT_EQ(3, metrics.GetAndClearCancelCount()); // tasks 4..6 should have been cancelled - throttler->TaskComplete(Advance()); // for task 7 - EXPECT_EQ(0, metrics.GetAndClearRunCount()); - EXPECT_EQ(0, metrics.GetAndClearCancelCount()); -} diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 43b95985419..f9fd0706a47 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -41,26 +41,26 @@ static void AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, const CSSPoint& aActualScrollOffset) { - // Correct the display-port by the difference between the requested scroll - // offset and the resulting scroll offset after setting the requested value. - ScreenPoint shift = - (aFrameMetrics.GetScrollOffset() - aActualScrollOffset) * - aFrameMetrics.DisplayportPixelsPerCSSPixel(); - ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); - margins.left -= shift.x; - margins.right += shift.x; - margins.top -= shift.y; - margins.bottom += shift.y; - aFrameMetrics.SetDisplayPortMargins(margins); + // Correct the display-port by the difference between the requested scroll + // offset and the resulting scroll offset after setting the requested value. + ScreenPoint shift = + (aFrameMetrics.GetScrollOffset() - aActualScrollOffset) * + aFrameMetrics.DisplayportPixelsPerCSSPixel(); + ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); + margins.left -= shift.x; + margins.right += shift.x; + margins.top -= shift.y; + margins.bottom += shift.y; + aFrameMetrics.SetDisplayPortMargins(margins); } static void RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics) { - ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); - margins.right = margins.left = margins.LeftRight() / 2; - margins.top = margins.bottom = margins.TopBottom() / 2; - aFrameMetrics.SetDisplayPortMargins(margins); + ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); + margins.right = margins.left = margins.LeftRight() / 2; + margins.top = margins.bottom = margins.TopBottom() / 2; + aFrameMetrics.SetDisplayPortMargins(margins); } static CSSPoint @@ -128,9 +128,20 @@ ScrollFrame(nsIContent* aContent, CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated); if (scrollUpdated) { - // Correct the display port due to the difference between mScrollOffset and the - // actual scroll offset. - AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset); + if (aMetrics.IsScrollInfoLayer()) { + // In cases where the APZ scroll offset is different from the content scroll + // offset, we want to interpret the margins as relative to the APZ scroll + // offset except when the frame is not scrollable by APZ. Therefore, if the + // layer is a scroll info layer, we leave the margins as-is and they will + // be interpreted as relative to the content scroll offset. + if (nsIFrame* frame = aContent->GetPrimaryFrame()) { + frame->SchedulePaint(); + } + } else { + // Correct the display port due to the difference between mScrollOffset and the + // actual scroll offset. + AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset); + } } else { // For whatever reason we couldn't update the scroll offset on the scroll frame, // which means the data APZ used for its displayport calculation is stale. Fall diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 3cec256efd8..f2fc53ac1fb 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -7,7 +7,6 @@ #include "BasicLayersImpl.h" // for FillRectWithMask #include "TextureHostBasic.h" #include "mozilla/layers/Effects.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "nsIWidget.h" #include "gfx2DGlue.h" #include "mozilla/gfx/2D.h" diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 81c3ef8f9c6..6bb29cb9e17 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -15,7 +15,6 @@ #include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/TextureClientRecycleAllocator.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "ImageContainer.h" // for PlanarYCbCrData, etc @@ -838,10 +837,10 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator, // static already_AddRefed -TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - size_t aSize, - TextureFlags aTextureFlags) +TextureClient::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + gfx::SurfaceFormat aFormat, + size_t aSize, + TextureFlags aTextureFlags) { // also test the validity of aAllocator MOZ_ASSERT(aAllocator && aAllocator->IPCOpen()); @@ -849,8 +848,9 @@ TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator, return nullptr; } - TextureData* data = BufferTextureData::CreateWithBufferSize(aAllocator, aFormat, aSize, - aTextureFlags); + TextureData* data = + BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aFormat, aSize, + aTextureFlags); if (!data) { return nullptr; } diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index d710d395608..691f21c231c 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -297,10 +297,10 @@ public: // pointers) with a certain buffer size. It's unfortunate that we need this. // providing format and sizes could let us do more optimization. static already_AddRefed - CreateWithBufferSize(ISurfaceAllocator* aAllocator, - gfx::SurfaceFormat aFormat, - size_t aSize, - TextureFlags aTextureFlags); + CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + gfx::SurfaceFormat aFormat, + size_t aSize, + TextureFlags aTextureFlags); // Creates and allocates a TextureClient of the same type. already_AddRefed diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index d82a0f9c19a..5f520327cdd 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -13,10 +13,9 @@ #include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator -#include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL -#include "mozilla/layers/YCbCrImageDataSerializer.h" +#include "mozilla/layers/ImageDataSerializer.h" #include "nsAString.h" #include "mozilla/RefPtr.h" // for nsRefPtr #include "nsPrintfCString.h" // for nsPrintfCString @@ -95,7 +94,8 @@ TextureHost::CreateIPDLActor(CompositableParentManager* aManager, LayersBackend aLayersBackend, TextureFlags aFlags) { - if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory && + if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer && + aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t && !aManager->IsSameProcess()) { NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!"); @@ -202,8 +202,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc, TextureFlags aFlags) { switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: + case SurfaceDescriptor::TSurfaceDescriptorBuffer: case SurfaceDescriptor::TSurfaceDescriptorDIB: case SurfaceDescriptor::TSurfaceDescriptorFileMapping: return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); @@ -252,19 +251,26 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, { RefPtr result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: { - const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem(); - result = new ShmemTextureHost(descriptor.data(), - descriptor.format(), - aDeallocator, - aFlags); - break; - } - case SurfaceDescriptor::TSurfaceDescriptorMemory: { - const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory(); - result = new MemoryTextureHost(reinterpret_cast(descriptor.data()), - descriptor.format(), - aFlags); + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { + const SurfaceDescriptorBuffer& bufferDesc = aDesc.get_SurfaceDescriptorBuffer(); + const MemoryOrShmem& data = bufferDesc.data(); + switch (data.type()) { + case MemoryOrShmem::TShmem: { + result = new ShmemTextureHost(data.get_Shmem(), + bufferDesc.desc(), + aDeallocator, + aFlags); + break; + } + case MemoryOrShmem::Tuintptr_t: { + result = new MemoryTextureHost(reinterpret_cast(data.get_uintptr_t()), + bufferDesc.desc(), + aFlags); + break; + } + default: + MOZ_CRASH(); + } break; } #ifdef XP_WIN @@ -368,15 +374,30 @@ TextureSource::~TextureSource() MOZ_COUNT_DTOR(TextureSource); } -BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat, +BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc, TextureFlags aFlags) : TextureHost(aFlags) , mCompositor(nullptr) -, mFormat(aFormat) , mUpdateSerial(1) , mLocked(false) , mNeedsFullUpdate(false) { + mDescriptor = aDesc; + switch (mDescriptor.type()) { + case BufferDescriptor::TYCbCrDescriptor: { + const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor(); + mSize = ycbcr.ySize(); + mFormat = gfx::SurfaceFormat::YUV; + break; + } + case BufferDescriptor::TRGBDescriptor: { + const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); + mSize = rgb.size(); + mFormat = rgb.format(); + break; + } + default: MOZ_CRASH(); + } if (aFlags & TextureFlags::COMPONENT_ALPHA) { // One texture of a component alpha texture pair will start out all white. // This hack allows us to easily make sure that white will be uploaded. @@ -385,22 +406,6 @@ BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat, } } -void -BufferTextureHost::InitSize() -{ - if (mFormat == gfx::SurfaceFormat::YUV) { - YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); - if (yuvDeserializer.IsValid()) { - mSize = yuvDeserializer.GetYSize(); - } - } else if (mFormat != gfx::SurfaceFormat::UNKNOWN) { - ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); - if (deserializer.IsValid()) { - mSize = deserializer.GetSize(); - } - } -} - BufferTextureHost::~BufferTextureHost() {} @@ -512,7 +517,8 @@ BufferTextureHost::MaybeUpload(nsIntRegion *aRegion) bool BufferTextureHost::Upload(nsIntRegion *aRegion) { - if (!GetBuffer()) { + uint8_t* buf = GetBuffer(); + if (!buf) { // We don't have a buffer; a possible cause is that the IPDL actor // is already dead. This inevitably happens as IPDL actors can die // at any time, so we want to silently return in this case. @@ -527,11 +533,11 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) NS_WARNING("BufferTextureHost: unsupported format!"); return false; } else if (mFormat == gfx::SurfaceFormat::YUV) { - YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); - MOZ_ASSERT(yuvDeserializer.IsValid()); + const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) { - RefPtr surf = yuvDeserializer.ToDataSourceSurface(); + RefPtr surf = + ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor()); if (NS_WARN_IF(!surf)) { return false; } @@ -565,21 +571,20 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); } - RefPtr tempY = - gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), - yuvDeserializer.GetYStride(), - yuvDeserializer.GetYSize(), + gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc), + desc.ySize().width, + desc.ySize(), gfx::SurfaceFormat::A8); RefPtr tempCb = - gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), - yuvDeserializer.GetCbCrStride(), - yuvDeserializer.GetCbCrSize(), + gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc), + desc.cbCrSize().width, + desc.cbCrSize(), gfx::SurfaceFormat::A8); RefPtr tempCr = - gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), - yuvDeserializer.GetCbCrStride(), - yuvDeserializer.GetCbCrSize(), + gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc), + desc.cbCrSize().width, + desc.cbCrSize(), gfx::SurfaceFormat::A8); // We don't support partial updates for Y U V textures NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); @@ -602,13 +607,10 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) regionToUpdate = nullptr; } } - ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); - if (!deserializer.IsValid()) { - NS_ERROR("Failed to deserialize image!"); - return false; - } - RefPtr surf = deserializer.GetAsSurface(); + RefPtr surf = + gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), + ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat); if (!surf) { return false; } @@ -630,35 +632,29 @@ BufferTextureHost::GetAsSurface() NS_WARNING("BufferTextureHost: unsupported format!"); return nullptr; } else if (mFormat == gfx::SurfaceFormat::YUV) { - YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); - if (!yuvDeserializer.IsValid()) { - return nullptr; - } - result = yuvDeserializer.ToDataSourceSurface(); + result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor( + GetBuffer(), mDescriptor.get_YCbCrDescriptor()); if (NS_WARN_IF(!result)) { return nullptr; } } else { - ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); - if (!deserializer.IsValid()) { - NS_ERROR("Failed to deserialize image!"); - return nullptr; - } - result = deserializer.GetAsSurface(); + RefPtr surf = + gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), + ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()), + mSize, mFormat); } return result.forget(); } ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem, - gfx::SurfaceFormat aFormat, + const BufferDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) -: BufferTextureHost(aFormat, aFlags) +: BufferTextureHost(aDesc, aFlags) , mShmem(MakeUnique(aShmem)) , mDeallocator(aDeallocator) { MOZ_COUNT_CTOR(ShmemTextureHost); - InitSize(); } ShmemTextureHost::~ShmemTextureHost() @@ -705,13 +701,12 @@ size_t ShmemTextureHost::GetBufferSize() } MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer, - gfx::SurfaceFormat aFormat, + const BufferDescriptor& aDesc, TextureFlags aFlags) -: BufferTextureHost(aFormat, aFlags) +: BufferTextureHost(aDesc, aFlags) , mBuffer(aBuffer) { MOZ_COUNT_CTOR(MemoryTextureHost); - InitSize(); } MemoryTextureHost::~MemoryTextureHost() diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 22c9685ece2..dadde7d5531 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -19,6 +19,7 @@ #include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc #include "mozilla/layers/FenceUtils.h" // for FenceHandle #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc +#include "mozilla/layers/LayersSurfaces.h" #include "mozilla/mozalloc.h" // for operator delete #include "mozilla/UniquePtr.h" // for UniquePtr #include "nsCOMPtr.h" // for already_AddRefed @@ -37,6 +38,7 @@ class Shmem; namespace layers { +class BufferDescriptor; class Compositor; class CompositableParentManager; class SurfaceDescriptor; @@ -567,8 +569,7 @@ protected: class BufferTextureHost : public TextureHost { public: - BufferTextureHost(gfx::SurfaceFormat aFormat, - TextureFlags aFlags); + BufferTextureHost(const BufferDescriptor& aDescriptor, TextureFlags aFlags); ~BufferTextureHost(); @@ -605,15 +606,13 @@ protected: bool Upload(nsIntRegion *aRegion = nullptr); bool MaybeUpload(nsIntRegion *aRegion = nullptr); - void InitSize(); - virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override; + BufferDescriptor mDescriptor; RefPtr mCompositor; RefPtr mFirstSource; nsIntRegion mMaybeUpdatedRegion; gfx::IntSize mSize; - // format of the data that is shared with the content process. gfx::SurfaceFormat mFormat; uint32_t mUpdateSerial; bool mLocked; @@ -629,7 +628,7 @@ class ShmemTextureHost : public BufferTextureHost { public: ShmemTextureHost(const mozilla::ipc::Shmem& aShmem, - gfx::SurfaceFormat aFormat, + const BufferDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); @@ -664,7 +663,7 @@ class MemoryTextureHost : public BufferTextureHost { public: MemoryTextureHost(uint8_t* aBuffer, - gfx::SurfaceFormat aFormat, + const BufferDescriptor& aDesc, TextureFlags aFlags); protected: diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 50ef9abde6c..abde07ae723 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -7,7 +7,6 @@ #include "CompositorD3D11.h" #include "gfxContext.h" #include "Effects.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "gfxWindowsPlatform.h" #include "gfx2DGlue.h" #include "gfxPrefs.h" @@ -665,8 +664,7 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, { RefPtr result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: { + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); break; } diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index 82f69c51616..169d9d9c33e 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -8,7 +8,6 @@ #include "gfxContext.h" #include "gfxImageSurface.h" #include "Effects.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "gfxWindowsPlatform.h" #include "gfx2DGlue.h" #include "gfxUtils.h" @@ -53,8 +52,7 @@ CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, { RefPtr result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: { + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); break; } @@ -192,7 +190,7 @@ TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager, } tmpTexture->GetSurfaceLevel(0, getter_AddRefs(aSurface)); - + HRESULT hr = aSurface->LockRect(&aLockedRect, nullptr, 0); if (FAILED(hr) || !aLockedRect.pBits) { gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index a6b0809d708..484ba4e48e9 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -1546,10 +1546,6 @@ CompositorParent::RecvNotifyChildCreated(const uint64_t& child) void CompositorParent::NotifyChildCreated(const uint64_t& aChild) { - if (mApzcTreeManager) { - NS_DispatchToMainThread(NS_NewRunnableMethodWithArg( - mApzcTreeManager, &APZCTreeManager::InitializeForLayersId, aChild)); - } sIndirectLayerTreesLock->AssertCurrentThreadOwns(); sIndirectLayerTrees[aChild].mParent = this; sIndirectLayerTrees[aChild].mLayerManager = mLayerManager; @@ -1559,9 +1555,6 @@ bool CompositorParent::RecvAdoptChild(const uint64_t& child) { MonitorAutoLock lock(*sIndirectLayerTreesLock); - if (mApzcTreeManager) { - mApzcTreeManager->AdoptLayersId(child, sIndirectLayerTrees[child].mParent->mApzcTreeManager.get()); - } NotifyChildCreated(child); if (sIndirectLayerTrees[child].mLayerTree) { sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager; @@ -1633,7 +1626,6 @@ ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(APZCTreeManager* aApzct : mLayersId(aLayersId) { EnsureLayerTreeMapReady(); - aApzctm->InitializeForLayersId(aLayersId); MonitorAutoLock lock(*sIndirectLayerTreesLock); sIndirectLayerTrees[aLayersId].mRoot = aRoot; sIndirectLayerTrees[aLayersId].mController = aController; @@ -1649,9 +1641,6 @@ ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration() CompositorParent::SetControllerForLayerTree(uint64_t aLayersId, GeckoContentController* aController) { - if (APZCTreeManager* apzctm = GetAPZCTreeManager(aLayersId)) { - apzctm->InitializeForLayersId(aLayersId); - } // This ref is adopted by UpdateControllerForLayersId(). aController->AddRef(); CompositorLoop()->PostTask(FROM_HERE, diff --git a/gfx/layers/ipc/ISurfaceAllocator.cpp b/gfx/layers/ipc/ISurfaceAllocator.cpp index c22726b4186..34003e1c66b 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.cpp +++ b/gfx/layers/ipc/ISurfaceAllocator.cpp @@ -60,38 +60,38 @@ ISurfaceAllocator::Finalize() } static inline uint8_t* -GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor, size_t& aSize) +GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor) { MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor)); - MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem || - aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorMemory); - if (aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem) { - Shmem shmem(aDescriptor.get_SurfaceDescriptorShmem().data()); - aSize = shmem.Size(); - return shmem.get(); + MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer); + + auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data(); + if (memOrShmem.type() == MemoryOrShmem::TShmem) { + return memOrShmem.get_Shmem().get(); } else { - const SurfaceDescriptorMemory& image = aDescriptor.get_SurfaceDescriptorMemory(); - aSize = std::numeric_limits::max(); - return reinterpret_cast(image.data()); + return reinterpret_cast(memOrShmem.get_uintptr_t()); } } already_AddRefed GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend) { - size_t size; - uint8_t* data = GetAddressFromDescriptor(aDescriptor, size); - ImageDataDeserializer image(data, size); - return image.GetAsDrawTarget(aBackend); + uint8_t* data = GetAddressFromDescriptor(aDescriptor); + auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + return gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, + data, rgb.size(), + stride, rgb.format()); } already_AddRefed GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor) { - size_t size; - uint8_t* data = GetAddressFromDescriptor(aDescriptor, size); - ImageDataDeserializer image(data, size); - return image.GetAsSurface(); + uint8_t* data = GetAddressFromDescriptor(aDescriptor); + auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(), + rgb.format()); } bool @@ -116,12 +116,14 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, } gfx::SurfaceFormat format = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent); - size_t size = ImageDataSerializer::ComputeMinBufferSize(aSize, format); + size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format); if (!size) { return false; } + + MemoryOrShmem bufferDesc; if (IsSameProcess()) { - uint8_t *data = new (std::nothrow) uint8_t[size]; + uint8_t* data = new (std::nothrow) uint8_t[size]; if (!data) { return false; } @@ -133,7 +135,7 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, memset(data, 0, size); } #endif - *aBuffer = SurfaceDescriptorMemory((uintptr_t)data, format); + bufferDesc = reinterpret_cast(data); } else { mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType(); @@ -142,19 +144,19 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, return false; } - *aBuffer = SurfaceDescriptorShmem(shmem, format); + bufferDesc = shmem; } - - uint8_t* data = GetAddressFromDescriptor(*aBuffer, size); - ImageDataSerializer serializer(data, size); - serializer.InitializeBufferInfo(aSize, format); + + *aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format), bufferDesc); + return true; } /* static */ bool ISurfaceAllocator::IsShmem(SurfaceDescriptor* aSurface) { - return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorShmem); + return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) + && (aSurface->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem); } void @@ -172,17 +174,18 @@ ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface) if (!IPCOpen()) { return; } - switch (aSurface->type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - DeallocShmem(aSurface->get_SurfaceDescriptorShmem().data()); + SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer(); + switch (desc.data().type()) { + case MemoryOrShmem::TShmem: { + DeallocShmem(desc.data().get_Shmem()); break; - case SurfaceDescriptor::TSurfaceDescriptorMemory: - GfxMemoryImageReporter::WillFree((uint8_t*)aSurface->get_SurfaceDescriptorMemory().data()); - delete [] (uint8_t*)aSurface->get_SurfaceDescriptorMemory().data(); - break; - case SurfaceDescriptor::Tnull_t: - case SurfaceDescriptor::T__None: + } + case MemoryOrShmem::Tuintptr_t: { + uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t(); + GfxMemoryImageReporter::WillFree(ptr); + delete [] ptr; break; + } default: NS_RUNTIMEABORT("surface type not implemented!"); } diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 4d0f5203359..bef26df3fe9 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -7,6 +7,7 @@ using nsIntRegion from "nsRegion.h"; using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerUtils.h"; using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h"; using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h"; +using mozilla::StereoMode from "ImageTypes.h"; using struct mozilla::null_t from "ipc/IPCMessageUtils.h"; using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h"; using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h"; @@ -95,25 +96,37 @@ struct SurfaceDescriptorGralloc { bool isOpaque; }; -/** - * Used for shmem-backed YCbCr and (flavors of) RGBA textures - */ -struct SurfaceDescriptorShmem { - Shmem data; +struct RGBDescriptor { + IntSize size; SurfaceFormat format; }; -/** - * Used for "raw memory"-backed YCbCr and (flavors of) RGBA textures - */ -struct SurfaceDescriptorMemory { - uintptr_t data; - SurfaceFormat format; +struct YCbCrDescriptor { + IntSize ySize; + IntSize cbCrSize; + uint32_t yOffset; + uint32_t cbOffset; + uint32_t crOffset; + StereoMode stereoMode; +}; + +union BufferDescriptor { + RGBDescriptor; + YCbCrDescriptor; +}; + +union MemoryOrShmem { + uintptr_t; + Shmem; +}; + +struct SurfaceDescriptorBuffer { + BufferDescriptor desc; + MemoryOrShmem data; }; union SurfaceDescriptor { - SurfaceDescriptorShmem; - SurfaceDescriptorMemory; + SurfaceDescriptorBuffer; SurfaceDescriptorD3D9; SurfaceDescriptorDIB; SurfaceDescriptorD3D10; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index d07e9dbf818..6fd94ee82f4 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -319,11 +319,12 @@ ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescripto return; } - if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorShmem) { - const SurfaceDescriptorShmem& shmem = aDescriptor->get_SurfaceDescriptorShmem(); - shmem.data().AssertInvariants(); + if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer && + aDescriptor->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem) { + const Shmem& shmem = aDescriptor->get_SurfaceDescriptorBuffer().data().get_Shmem(); + shmem.AssertInvariants(); MOZ_ASSERT(mShadowManager && - mShadowManager->IsTrackingSharedMemory(shmem.data().mSegment)); + mShadowManager->IsTrackingSharedMemory(shmem.mSegment)); } } #endif diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index ec4859302fe..aa2c3bbe698 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -15,7 +15,7 @@ #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc #include "mozilla/layers/TextureClient.h" #include "mozilla/layers/BufferTexture.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" +#include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild #include "mozilla/mozalloc.h" // for operator delete #include "nsISupportsImpl.h" // for Image::AddRef @@ -112,14 +112,14 @@ uint8_t* SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize) { MOZ_ASSERT(!mTextureClient, "This image already has allocated data"); - size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize); + size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize); if (!size) { return nullptr; } - mTextureClient = TextureClient::CreateWithBufferSize(mCompositable->GetForwarder(), - gfx::SurfaceFormat::YUV, size, - mCompositable->GetTextureFlags()); + mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(), + gfx::SurfaceFormat::YUV, size, + mCompositable->GetTextureFlags()); // get new buffer _without_ setting mBuffer. if (!mTextureClient) { @@ -132,11 +132,7 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize) MappedYCbCrTextureData mapped; if (mTextureClient->BorrowMappedYCbCrData(mapped)) { // The caller expects a pointer to the beginning of the writable part of the - // buffer (after the metadata) which is where the y channel starts by default. - // The caller might choose to write the y channel at a different offset and - // if it does so, it will also update the metadata. - // Anyway, we return the y channel here but the intent is to obtain the start of - // the writable part of the buffer. + // buffer which is where the y channel starts by default. return mapped.y.data; } else { MOZ_CRASH(); @@ -146,35 +142,26 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize) bool SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData) { + // SetDataNoCopy is used to update YUV plane offsets without (re)allocating + // memory previously allocated with AllocateAndGetNewBuffer(). + MOZ_ASSERT(mTextureClient, "This Image should have already allocated data"); if (!mTextureClient) { return false; } mData = aData; mSize = aData.mPicSize; - /* SetDataNoCopy is used to update YUV plane offsets without (re)allocating - * memory previously allocated with AllocateAndGetNewBuffer(). - * serializer.GetData() returns the address of the memory previously allocated - * with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr - * channels to compute 0-based offsets to pass to InitializeBufferInfo. - */ - MappedYCbCrTextureData mapped; - if(!mTextureClient->BorrowMappedYCbCrData(mapped)) { - MOZ_CRASH(); - } - YCbCrImageDataSerializer serializer(mapped.metadata, mBufferSize); - uint8_t *base = serializer.GetData(); + + uint8_t *base = GetBuffer(); uint32_t yOffset = aData.mYChannel - base; uint32_t cbOffset = aData.mCbChannel - base; uint32_t crOffset = aData.mCrChannel - base; - serializer.InitializeBufferInfo(yOffset, - cbOffset, - crOffset, - aData.mYStride, - aData.mCbCrStride, - aData.mYSize, - aData.mCbCrSize, - aData.mStereoMode); + + static_cast(mTextureClient->GetInternalData())->SetDesciptor( + YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset, + aData.mStereoMode) + ); + return true; } @@ -232,8 +219,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) // do not set mBuffer like in PlanarYCbCrImage because the later // will try to manage this memory without knowing it belongs to a // shmem. - mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize, - mData.mCbCrSize); + mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize); mSize = mData.mPicSize; mTextureClient->Unlock(); diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 6918275ee0d..9858f53ea9a 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -180,7 +180,6 @@ EXPORTS.mozilla.layers += [ 'RenderTrace.h', 'TextureWrapperImage.h', 'TransactionIdAllocator.h', - 'YCbCrImageDataSerializer.h', ] if CONFIG['MOZ_X11']: @@ -250,7 +249,6 @@ UNIFIED_SOURCES += [ 'apz/src/InputBlockState.cpp', 'apz/src/InputQueue.cpp', 'apz/src/OverscrollHandoffState.cpp', - 'apz/src/TaskThrottler.cpp', 'apz/src/TouchCounter.cpp', 'apz/src/WheelScrollAnimation.cpp', 'apz/testutil/APZTestData.cpp', @@ -352,7 +350,6 @@ UNIFIED_SOURCES += [ 'RenderTrace.cpp', 'RotatedBuffer.cpp', 'TextureWrapperImage.cpp', - 'YCbCrImageDataSerializer.cpp', ] SOURCES += [ diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index f41113cc41a..d4006bb8313 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -16,7 +16,6 @@ #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Logging.h" // for gfxCriticalError #include "mozilla/layers/ISurfaceAllocator.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "mozilla/layers/GrallocTextureHost.h" #include "nsRegion.h" // for nsIntRegion #include "AndroidSurfaceTexture.h" @@ -52,8 +51,7 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc, { RefPtr result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: { + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); break; diff --git a/gfx/tests/gtest/TestTextures.cpp b/gfx/tests/gtest/TestTextures.cpp index cf97cc6da31..c2cde0c452f 100644 --- a/gfx/tests/gtest/TestTextures.cpp +++ b/gfx/tests/gtest/TestTextures.cpp @@ -16,7 +16,7 @@ #include "gfxImageSurface.h" #include "gfxTypes.h" #include "ImageContainer.h" -#include "mozilla/layers/YCbCrImageDataSerializer.h" +#include "mozilla/layers/ImageDataSerializer.h" using namespace mozilla; using namespace mozilla::gfx; @@ -119,31 +119,6 @@ void AssertSurfacesEqual(SourceSurface* surface1, dataSurface2->Unmap(); } -// Same as above, for YCbCr surfaces -void AssertYCbCrSurfacesEqual(PlanarYCbCrData* surface1, - PlanarYCbCrData* surface2) -{ - ASSERT_EQ(surface1->mYSize, surface2->mYSize); - ASSERT_EQ(surface1->mCbCrSize, surface2->mCbCrSize); - ASSERT_EQ(surface1->mStereoMode, surface2->mStereoMode); - ASSERT_EQ(surface1->mPicSize, surface2->mPicSize); - - for (int y = 0; y < surface1->mYSize.height; ++y) { - for (int x = 0; x < surface1->mYSize.width; ++x) { - ASSERT_EQ(surface1->mYChannel[y*surface1->mYStride + x*(1+surface1->mYSkip)], - surface2->mYChannel[y*surface2->mYStride + x*(1+surface2->mYSkip)]); - } - } - for (int y = 0; y < surface1->mCbCrSize.height; ++y) { - for (int x = 0; x < surface1->mCbCrSize.width; ++x) { - ASSERT_EQ(surface1->mCbChannel[y*surface1->mCbCrStride + x*(1+surface1->mCbSkip)], - surface2->mCbChannel[y*surface2->mCbCrStride + x*(1+surface2->mCbSkip)]); - ASSERT_EQ(surface1->mCrChannel[y*surface1->mCbCrStride + x*(1+surface1->mCrSkip)], - surface2->mCrChannel[y*surface2->mCbCrStride + x*(1+surface2->mCrSkip)]); - } - } -} - // Run the test for a texture client and a surface void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) { @@ -206,7 +181,13 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) { SurfaceDescriptor descriptor; ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor)); - ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t); + ASSERT_EQ(descriptor.type(), SurfaceDescriptor::TSurfaceDescriptorBuffer); + auto bufferDesc = descriptor.get_SurfaceDescriptorBuffer(); + ASSERT_EQ(bufferDesc.desc().type(), BufferDescriptor::TYCbCrDescriptor); + auto ycbcrDesc = bufferDesc.desc().get_YCbCrDescriptor(); + ASSERT_EQ(ycbcrDesc.ySize(), ycbcrData.mYSize); + ASSERT_EQ(ycbcrDesc.cbCrSize(), ycbcrData.mCbCrSize); + ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode); // host deserialization RefPtr textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr, @@ -222,26 +203,6 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) { if (host->Lock()) { // This will work iff the compositor is not BasicCompositor ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV); - - YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer(), host->GetBufferSize()); - ASSERT_TRUE(yuvDeserializer.IsValid()); - PlanarYCbCrData data; - data.mYChannel = yuvDeserializer.GetYData(); - data.mCbChannel = yuvDeserializer.GetCbData(); - data.mCrChannel = yuvDeserializer.GetCrData(); - data.mYStride = yuvDeserializer.GetYStride(); - data.mCbCrStride = yuvDeserializer.GetCbCrStride(); - data.mStereoMode = yuvDeserializer.GetStereoMode(); - data.mYSize = yuvDeserializer.GetYSize(); - data.mCbCrSize = yuvDeserializer.GetCbCrSize(); - data.mYSkip = 0; - data.mCbSkip = 0; - data.mCrSkip = 0; - data.mPicSize = data.mYSize; - data.mPicX = 0; - data.mPicY = 0; - - AssertYCbCrSurfacesEqual(&ycbcrData, &data); host->Unlock(); } } diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index bde9f242fae..3c245fdc3cf 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -167,7 +167,6 @@ private: DECL_GFX_PREF(Once, "apz.max_velocity_queue_size", APZMaxVelocityQueueSize, uint32_t, 5); DECL_GFX_PREF(Live, "apz.min_skate_speed", APZMinSkateSpeed, float, 1.0f); DECL_GFX_PREF(Live, "apz.minimap.enabled", APZMinimap, bool, false); - DECL_GFX_PREF(Live, "apz.num_paint_duration_samples", APZNumPaintDurationSamples, int32_t, 3); DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false); DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f); DECL_GFX_PREF(Live, "apz.overscroll.spring_friction", APZOverscrollSpringFriction, float, 0.015f); @@ -181,7 +180,6 @@ private: DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false); DECL_GFX_PREF(Live, "apz.touch_move_tolerance", APZTouchMoveTolerance, float, 0.0); DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f); - DECL_GFX_PREF(Live, "apz.use_paint_duration", APZUsePaintDuration, bool, true); DECL_GFX_PREF(Live, "apz.velocity_bias", APZVelocityBias, float, 1.0f); DECL_GFX_PREF(Live, "apz.velocity_relevance_time_ms", APZVelocityRelevanceTime, uint32_t, 150); DECL_GFX_PREF(Live, "apz.x_skate_highmem_adjust", APZXSkateHighMemAdjust, float, 0.0f); diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 0fd42c3a706..60464734913 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -6870,7 +6870,7 @@ Warn(AsmJSParser& parser, int errorNumber, const char* str) static bool EstablishPreconditions(ExclusiveContext* cx, AsmJSParser& parser) { -#ifdef JS_CODEGEN_NONE +#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by lack of a JIT compiler"); #endif @@ -6980,7 +6980,7 @@ js::IsAsmJSCompilationAvailable(JSContext* cx, unsigned argc, Value* vp) CallArgs args = CallArgsFromVp(argc, vp); // See EstablishPreconditions. -#ifdef JS_CODEGEN_NONE +#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) bool available = false; #else bool available = cx->jitSupportsFloatingPoint() && diff --git a/js/src/asmjs/WasmIonCompile.cpp b/js/src/asmjs/WasmIonCompile.cpp index 25be1f4da6e..daa239ad0bb 100644 --- a/js/src/asmjs/WasmIonCompile.cpp +++ b/js/src/asmjs/WasmIonCompile.cpp @@ -2946,7 +2946,7 @@ wasm::CompileFunction(CompileTask* task) MIRGraph graph(&results.alloc()); CompileInfo compileInfo(func.numLocals()); MIRGenerator mir(nullptr, options, &results.alloc(), &graph, &compileInfo, - IonOptimizations.get(Optimization_AsmJS), + IonOptimizations.get(OptimizationLevel::AsmJS), args.usesSignalHandlersForOOB); // Build MIR graph diff --git a/js/src/builtin/Reflect.cpp b/js/src/builtin/Reflect.cpp index 37e4454f98c..7bdfa84e032 100644 --- a/js/src/builtin/Reflect.cpp +++ b/js/src/builtin/Reflect.cpp @@ -199,11 +199,7 @@ Reflect_enumerate(JSContext* cx, unsigned argc, Value* vp) } #endif -/* - * ES6 26.1.6 Reflect.get(target, propertyKey [, receiver]) - * - * Primitive receivers are not supported yet (see bug 603201). - */ +/* ES6 26.1.6 Reflect.get(target, propertyKey [, receiver]) */ static bool Reflect_get(JSContext* cx, unsigned argc, Value* vp) { @@ -221,16 +217,10 @@ Reflect_get(JSContext* cx, unsigned argc, Value* vp) return false; // Step 4. - RootedValue receiver(cx, argc > 2 ? args[2] : args.get(0)); - - // Non-standard hack: Throw a TypeError if the receiver isn't an object. - // See bug 603201. - RootedObject receiverObj(cx, NonNullObject(cx, receiver)); - if (!receiverObj) - return false; + RootedValue receiver(cx, args.length() > 2 ? args[2] : args.get(0)); // Step 5. - return GetProperty(cx, obj, receiverObj, key, args.rval()); + return GetProperty(cx, obj, receiver, key, args.rval()); } /* ES6 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey) */ @@ -336,7 +326,7 @@ Reflect_set(JSContext* cx, unsigned argc, Value* vp) return false; // Step 4. - RootedValue receiver(cx, argc > 3 ? args[3] : args.get(0)); + RootedValue receiver(cx, args.length() > 3 ? args[3] : args.get(0)); // Step 5. ObjectOpResult result; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index ffd26a6bbaf..ae0ca9e5c0b 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -306,8 +306,8 @@ GC(JSContext* cx, unsigned argc, Value* vp) char buf[256] = { '\0' }; #ifndef JS_MORE_DETERMINISTIC - JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n", - (unsigned long)preBytes, (unsigned long)cx->runtime()->gc.usage.gcBytes()); + JS_snprintf(buf, sizeof(buf), "before %" PRIuSIZE ", after %" PRIuSIZE "\n", + preBytes, cx->runtime()->gc.usage.gcBytes()); #endif JSString* str = JS_NewStringCopyZ(cx, buf); if (!str) diff --git a/js/src/configure.in b/js/src/configure.in index 25b4ae847e5..023086bcc1a 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -73,8 +73,8 @@ _PTHREAD_LDFLAGS="" dnl Do not allow objdir == srcdir builds dnl ============================================================== -_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd` -_objdir=`pwd` +_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd -P` +_objdir=`pwd -P` if test "$_topsrcdir" = "$_objdir" then @@ -112,7 +112,7 @@ if test "$_conflict_files"; then exit 1 break fi -MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd` +MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P` MOZ_BUILD_BACKEND diff --git a/js/src/devtools/automation/arm64-jstests-slow.txt b/js/src/devtools/automation/arm64-jstests-slow.txt new file mode 100644 index 00000000000..8f1068d541a --- /dev/null +++ b/js/src/devtools/automation/arm64-jstests-slow.txt @@ -0,0 +1,52 @@ +ecma/Date/15.9.5.10-2.js +ecma/Date/15.9.5.11-2.js +ecma/Date/15.9.5.12-2.js +ecma/Date/15.9.5.8.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-01-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-02-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-03-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-04-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-05-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-06-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-07-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-08-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-09-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-10-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-11-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-12-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-13-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-14-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-15-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-16-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-17-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-18-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-19-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-20-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-21-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-22-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-23-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-24-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-25-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-26-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-27-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-30-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-31-of-32.js +ecma_5/Object/15.2.3.6-dictionary-redefinition-32-of-32.js +ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js +ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js +ecma_5/Object/15.2.3.6-redefinition-1-of-4.js +ecma_5/Object/15.2.3.6-redefinition-2-of-4.js +ecma_5/Object/15.2.3.6-redefinition-3-of-4.js +ecma_5/Object/15.2.3.6-redefinition-4-of-4.js +ecma_6/Comprehensions/sudoku.js +js1_8/extensions/regress-476427.js +js1_8_5/extensions/clone-complex-object.js +js1_8_5/reflect-parse/classes.js +js1_8_5/reflect-parse/destructuring-variable-declarations.js +js1_8_5/regress/no-array-comprehension-length-limit.js diff --git a/js/src/devtools/automation/autospider.sh b/js/src/devtools/automation/autospider.sh index 4481843d28d..c93dbb7dfe3 100755 --- a/js/src/devtools/automation/autospider.sh +++ b/js/src/devtools/automation/autospider.sh @@ -217,10 +217,10 @@ elif [[ "$VARIANT" = "arm-sim" || "$VARIANT" = "plaindebug" ]]; then export JSTESTS_EXTRA_ARGS=--jitflags=debug elif [[ "$VARIANT" = arm64* ]]; then - # The ARM64 JIT is not yet fully functional, and asm.js does not work. - # Just run "make check" and jsapi-tests. - RUN_JITTEST=false - RUN_JSTESTS=false + # The ARM64 simulator is slow, so some tests are timing out. + # Run a reduced set of test cases so this doesn't take hours. + export JSTESTS_EXTRA_ARGS="--exclude-file=$ABSDIR/arm64-jstests-slow.txt" + export JITTEST_EXTRA_ARGS="--jitflags=none --args=--baseline-eager -x ion/ -x asm.js/" fi $COMMAND_PREFIX $MAKE check || exit 1 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 746a24af9b3..5919c40063c 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -6780,6 +6780,13 @@ Parser::classDefinition(YieldHandling yieldHandling, if (tt == TOK_NAME && tokenStream.currentName() == context->names().static_) { if (!tokenStream.peekToken(&tt, TokenStream::KeywordIsName)) return null(); + if (tt == TOK_RC) { + tokenStream.consumeKnownToken(tt, TokenStream::KeywordIsName); + report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN, + "property name", TokenKindToDesc(tt)); + return null(); + } + if (tt != TOK_LP) { if (!checkUnescapedName()) return null(); @@ -9249,8 +9256,7 @@ Parser::propertyName(YieldHandling yieldHandling, Node propList, if (!tokenStream.getToken(<ok, TokenStream::KeywordIsName)) return null(); - // TOK_RC should be handled in caller. - MOZ_ASSERT(ltok != TOK_RC); + MOZ_ASSERT(ltok != TOK_RC, "caller should have handled TOK_RC"); bool isGenerator = false; if (ltok == TOK_MUL) { diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 3732767f885..da90d4c356d 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -501,15 +501,15 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing, bool willFit = str->length() + strlen(" ") + CountDecimalDigits(str->length()) < bufsize; - n = JS_snprintf(buf, bufsize, " ", - (int)str->length(), + n = JS_snprintf(buf, bufsize, " ", + str->length(), willFit ? "" : " (truncated)"); buf += n; bufsize -= n; PutEscapedString(buf, bufsize, &str->asLinear(), 0); } else { - JS_snprintf(buf, bufsize, "", (int)str->length()); + JS_snprintf(buf, bufsize, "", str->length()); } break; } diff --git a/js/src/irregexp/NativeRegExpMacroAssembler.cpp b/js/src/irregexp/NativeRegExpMacroAssembler.cpp index d0b47f7fb82..9cf9bfe5344 100644 --- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp +++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp @@ -122,8 +122,7 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only) #ifdef JS_CODEGEN_ARM64 // ARM64 communicates stack address via sp, but uses a pseudo-sp for addressing. - MOZ_ASSERT(!masm.GetStackPointer64().Is(sp)); - masm.Mov(masm.GetStackPointer64(), sp); + masm.initStackPtr(); #endif // Push non-volatile registers which might be modified by jitcode. diff --git a/js/src/jit-test/lib/jitopts.js b/js/src/jit-test/lib/jitopts.js index 587e56d44dc..0d35a9e02cf 100644 --- a/js/src/jit-test/lib/jitopts.js +++ b/js/src/jit-test/lib/jitopts.js @@ -9,6 +9,12 @@ function jitTogglesMatch(opts) { if (k.indexOf(".enable") > 0 && opts[k] != currentOpts[k]) return false; } + + // ARM64 does not yet have an Ion code generator, so return false if + // ion.enable is requested. + if (getBuildConfiguration()['arm64-simulator'] && opts['ion.enable']) + return false; + return true; } diff --git a/js/src/jit-test/tests/debug/Debugger-allowUnobservedAsmJS-02.js b/js/src/jit-test/tests/debug/Debugger-allowUnobservedAsmJS-02.js index 1af32f6cab5..bfabb85c4ff 100644 --- a/js/src/jit-test/tests/debug/Debugger-allowUnobservedAsmJS-02.js +++ b/js/src/jit-test/tests/debug/Debugger-allowUnobservedAsmJS-02.js @@ -19,5 +19,7 @@ runOffThreadScript(); var msg = getLastWarning().message; assertEq(msg === "asm.js type error: Disabled by debugger" || + msg === "asm.js type error: Disabled by lack of a JIT compiler" || + msg === "asm.js type error: Disabled by javascript.options.asmjs in about:config" || msg === "asm.js type error: Disabled by lack of floating point support", true); diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index d42be8e7bfe..74b0e4bb0da 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -2108,8 +2108,6 @@ IonCompile(JSContext* cx, JSScript* script, AutoTraceLog logScript(logger, event); AutoTraceLog logCompile(logger, TraceLogger_IonCompilation); - MOZ_ASSERT(optimizationLevel > Optimization_DontCompile); - // Make sure the script's canonical function isn't lazy. We can't de-lazify // it in a helper thread. script->ensureNonLazyCanonicalFunction(cx); @@ -2396,7 +2394,7 @@ Compile(JSContext* cx, HandleScript script, BaselineFrame* osrFrame, jsbytecode* bool recompile = false; OptimizationLevel optimizationLevel = GetOptimizationLevel(script, osrPc); - if (optimizationLevel == Optimization_DontCompile) + if (optimizationLevel == OptimizationLevel::DontCompile) return Method_Skipped; if (script->hasIonScript()) { diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index eb709c6502a..013f07c7469 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -3683,7 +3683,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun, script->needsArgsObj(), inlineScriptTree); - const OptimizationInfo* optimizationInfo = IonOptimizations.get(Optimization_Normal); + const OptimizationInfo* optimizationInfo = IonOptimizations.get(OptimizationLevel::Normal); CompilerConstraintList* constraints = NewCompilerConstraintList(temp); if (!constraints) { @@ -3904,7 +3904,7 @@ jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg) /* needsArgsObj = */ true, inlineScriptTree); - const OptimizationInfo* optimizationInfo = IonOptimizations.get(Optimization_Normal); + const OptimizationInfo* optimizationInfo = IonOptimizations.get(OptimizationLevel::Normal); CompilerConstraintList* constraints = NewCompilerConstraintList(temp); if (!constraints) { diff --git a/js/src/jit/IonOptimizationLevels.cpp b/js/src/jit/IonOptimizationLevels.cpp index 5143c1411a5..e8a11a9452a 100644 --- a/js/src/jit/IonOptimizationLevels.cpp +++ b/js/src/jit/IonOptimizationLevels.cpp @@ -16,27 +16,28 @@ using namespace js::jit; namespace js { namespace jit { -OptimizationInfos IonOptimizations; +OptimizationLevelInfo IonOptimizations; void OptimizationInfo::initNormalOptimizationInfo() { - level_ = Optimization_Normal; + level_ = OptimizationLevel::Normal; + autoTruncate_ = true; eaa_ = true; + eagerSimdUnbox_ = true; edgeCaseAnalysis_ = true; eliminateRedundantChecks_ = true; inlineInterpreted_ = true; inlineNative_ = true; - eagerSimdUnbox_ = true; - gvn_ = true; licm_ = true; - rangeAnalysis_ = true; loopUnrolling_ = true; + gvn_ = true; + rangeAnalysis_ = true; reordering_ = true; - autoTruncate_ = true; sincos_ = true; sink_ = true; + registerAllocator_ = RegisterAllocator_Backtracking; inlineMaxBytecodePerCallSiteMainThread_ = 500; @@ -61,16 +62,16 @@ OptimizationInfo::initAsmjsOptimizationInfo() // Take normal option values for not specified values. initNormalOptimizationInfo(); + level_ = OptimizationLevel::AsmJS; + ama_ = true; - level_ = Optimization_AsmJS; + autoTruncate_ = false; eagerSimdUnbox_ = false; // AsmJS has no boxing / unboxing. edgeCaseAnalysis_ = false; eliminateRedundantChecks_ = false; - autoTruncate_ = false; + scalarReplacement_ = false; // AsmJS has no objects. sincos_ = false; sink_ = false; - registerAllocator_ = RegisterAllocator_Backtracking; - scalarReplacement_ = false; // AsmJS has no objects. } uint32_t @@ -108,49 +109,51 @@ OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) cons return warmUpThreshold + loopDepth * 100; } -OptimizationInfos::OptimizationInfos() +OptimizationLevelInfo::OptimizationLevelInfo() { - infos_[Optimization_Normal - 1].initNormalOptimizationInfo(); - infos_[Optimization_AsmJS - 1].initAsmjsOptimizationInfo(); + infos_[OptimizationLevel::Normal].initNormalOptimizationInfo(); + infos_[OptimizationLevel::AsmJS].initAsmjsOptimizationInfo(); #ifdef DEBUG OptimizationLevel level = firstLevel(); while (!isLastLevel(level)) { OptimizationLevel next = nextLevel(level); - MOZ_ASSERT(level < next); + MOZ_ASSERT_IF(level != OptimizationLevel::DontCompile, level < next); level = next; } #endif } OptimizationLevel -OptimizationInfos::nextLevel(OptimizationLevel level) const +OptimizationLevelInfo::nextLevel(OptimizationLevel level) const { MOZ_ASSERT(!isLastLevel(level)); switch (level) { - case Optimization_DontCompile: - return Optimization_Normal; - default: - MOZ_CRASH("Unknown optimization level."); + case OptimizationLevel::DontCompile: + return OptimizationLevel::Normal; + case OptimizationLevel::Normal: + case OptimizationLevel::AsmJS: + case OptimizationLevel::Count:; } + MOZ_CRASH("Unknown optimization level."); } OptimizationLevel -OptimizationInfos::firstLevel() const +OptimizationLevelInfo::firstLevel() const { - return nextLevel(Optimization_DontCompile); + return nextLevel(OptimizationLevel::DontCompile); } bool -OptimizationInfos::isLastLevel(OptimizationLevel level) const +OptimizationLevelInfo::isLastLevel(OptimizationLevel level) const { - return level == Optimization_Normal; + return level == OptimizationLevel::Normal; } OptimizationLevel -OptimizationInfos::levelForScript(JSScript* script, jsbytecode* pc) const +OptimizationLevelInfo::levelForScript(JSScript* script, jsbytecode* pc) const { - OptimizationLevel prev = Optimization_DontCompile; + OptimizationLevel prev = OptimizationLevel::DontCompile; while (!isLastLevel(prev)) { OptimizationLevel level = nextLevel(prev); diff --git a/js/src/jit/IonOptimizationLevels.h b/js/src/jit/IonOptimizationLevels.h index 0ca81822a91..df6d3211e7b 100644 --- a/js/src/jit/IonOptimizationLevels.h +++ b/js/src/jit/IonOptimizationLevels.h @@ -7,6 +7,8 @@ #ifndef jit_IonOptimizationLevels_h #define jit_IonOptimizationLevels_h +#include "mozilla/EnumeratedArray.h" + #include "jsbytecode.h" #include "jstypes.h" @@ -16,12 +18,12 @@ namespace js { namespace jit { -enum OptimizationLevel +enum class OptimizationLevel : uint8_t { - Optimization_DontCompile, - Optimization_Normal, - Optimization_AsmJS, - Optimization_Count + Normal, + AsmJS, + Count, + DontCompile }; #ifdef JS_JITSPEW @@ -29,15 +31,15 @@ inline const char* OptimizationLevelString(OptimizationLevel level) { switch (level) { - case Optimization_DontCompile: + case OptimizationLevel::DontCompile: return "Optimization_DontCompile"; - case Optimization_Normal: + case OptimizationLevel::Normal: return "Optimization_Normal"; - case Optimization_AsmJS: + case OptimizationLevel::AsmJS: return "Optimization_AsmJS"; - default: - MOZ_CRASH("Invalid OptimizationLevel"); + case OptimizationLevel::Count:; } + MOZ_CRASH("Invalid OptimizationLevel"); } #endif @@ -263,19 +265,16 @@ class OptimizationInfo } }; -class OptimizationInfos +class OptimizationLevelInfo { private: - OptimizationInfo infos_[Optimization_Count - 1]; + mozilla::EnumeratedArray infos_; public: - OptimizationInfos(); + OptimizationLevelInfo(); const OptimizationInfo* get(OptimizationLevel level) const { - MOZ_ASSERT(level < Optimization_Count); - MOZ_ASSERT(level != Optimization_DontCompile); - - return &infos_[level - 1]; + return &infos_[level]; } OptimizationLevel nextLevel(OptimizationLevel level) const; @@ -284,7 +283,7 @@ class OptimizationInfos OptimizationLevel levelForScript(JSScript* script, jsbytecode* pc = nullptr) const; }; -extern OptimizationInfos IonOptimizations; +extern OptimizationLevelInfo IonOptimizations; } // namespace jit } // namespace js diff --git a/js/src/jit/arm/MacroAssembler-arm-inl.h b/js/src/jit/arm/MacroAssembler-arm-inl.h index 61edf6d9e47..e2c104c8eda 100644 --- a/js/src/jit/arm/MacroAssembler-arm-inl.h +++ b/js/src/jit/arm/MacroAssembler-arm-inl.h @@ -407,13 +407,6 @@ MacroAssemblerARMCompat::incrementInt32Value(const Address& addr) asMasm().add32(Imm32(1), ToPayload(addr)); } -void -MacroAssemblerARMCompat::decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) -{ - asMasm().subPtr(imm, lhs); - branch32(cond, lhs, Imm32(0), label); -} - } // namespace jit } // namespace js diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index f563ef05a6f..e2505f7259a 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -971,7 +971,10 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { branch32(cond, lhs, imm, label); } - inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label); + void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { + ma_sub(imm, lhs, SetCC); + as_b(label, cond); + } void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label); void moveValue(const Value& val, Register type, Register data); diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index da13c0bc803..69e48e78ece 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -1346,8 +1346,8 @@ class MacroAssemblerCompat : public vixl::MacroAssembler } void branch(JitCode* target) { syncStackPtr(); - addPendingJump(nextOffset(), ImmPtr(target->raw()), Relocation::JITCODE); - b(-1); // The jump target will be patched by executableCopy(). + BufferOffset loc = b(-1); // The jump target will be patched by executableCopy(). + addPendingJump(loc, ImmPtr(target->raw()), Relocation::JITCODE); } void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) { diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp index 74566d9451f..90822c3b71e 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp @@ -1564,11 +1564,14 @@ void MacroAssembler::Claim(const Operand& size) { } } - if (!sp.Is(GetStackPointer64())) { - BumpSystemStackPointer(size); - } - Sub(GetStackPointer64(), GetStackPointer64(), size); + + // Make sure the real stack pointer reflects the claimed stack space. + // We can't use stack memory below the stack pointer, it could be clobbered by + // interupts and signal handlers. + if (!sp.Is(GetStackPointer64())) { + Mov(sp, GetStackPointer64()); + } } diff --git a/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h b/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h index c3e1e933271..d079340fcfb 100644 --- a/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h +++ b/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h @@ -206,11 +206,6 @@ class MozBaseAssembler : public js::jit::AssemblerShared { protected: // The buffer into which code and relocation info are generated. ARMBuffer armbuffer_; - - js::jit::CompactBufferWriter jumpRelocations_; - js::jit::CompactBufferWriter dataRelocations_; - js::jit::CompactBufferWriter relocations_; - js::jit::CompactBufferWriter preBarriers_; }; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 415e4566888..60d93ef26a7 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3107,9 +3107,9 @@ SliceBudget::describe(char* buffer, size_t maxlen) const if (isUnlimited()) return JS_snprintf(buffer, maxlen, "unlimited"); else if (isWorkBudget()) - return JS_snprintf(buffer, maxlen, "work(%lld)", workBudget.budget); + return JS_snprintf(buffer, maxlen, "work(%" PRId64 ")", workBudget.budget); else - return JS_snprintf(buffer, maxlen, "%lldms", timeBudget.budget); + return JS_snprintf(buffer, maxlen, "%" PRId64 "ms", timeBudget.budget); } bool diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a03ee8b636b..5bc6dd39fcb 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3303,12 +3303,12 @@ GetObjectSlotNameFunctor::operator()(JS::CallbackTracer* trc, char* buf, size_t if (slotname) JS_snprintf(buf, bufsize, pattern, slotname); else - JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot); + JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %" PRIu32 "**", slot); } while (false); } else { jsid propid = shape->propid(); if (JSID_IS_INT(propid)) { - JS_snprintf(buf, bufsize, "%ld", (long)JSID_TO_INT(propid)); + JS_snprintf(buf, bufsize, "%" PRId32 "", JSID_TO_INT(propid)); } else if (JSID_IS_ATOM(propid)) { PutEscapedString(buf, bufsize, JSID_TO_ATOM(propid), 0); } else if (JSID_IS_SYMBOL(propid)) { diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 30e19c92a66..f55cbf35324 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -973,7 +973,7 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc, default: { char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format); + JS_snprintf(numBuf, sizeof numBuf, "%x", cs->format); JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNKNOWN_FORMAT, numBuf); return 0; diff --git a/js/src/jsprf.h b/js/src/jsprf.h index 4847b52b781..4c3ffde822d 100644 --- a/js/src/jsprf.h +++ b/js/src/jsprf.h @@ -25,6 +25,9 @@ ** %g - float */ +#include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/SizePrintfMacros.h" + #include #include "jstypes.h" diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index dd33a7ca0ed..bce8129bc88 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -12,6 +12,7 @@ #include "mozilla/GuardObjects.h" #include "mozilla/mozalloc.h" #include "mozilla/PodOperations.h" +#include "mozilla/SizePrintfMacros.h" #ifdef XP_WIN # include @@ -1420,9 +1421,9 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp) if (loadBytecode && assertEqBytecode) { if (saveLength != loadLength) { char loadLengthStr[16]; - JS_snprintf(loadLengthStr, sizeof(loadLengthStr), "%u", loadLength); + JS_snprintf(loadLengthStr, sizeof(loadLengthStr), "%" PRIu32, loadLength); char saveLengthStr[16]; - JS_snprintf(saveLengthStr, sizeof(saveLengthStr), "%u", saveLength); + JS_snprintf(saveLengthStr, sizeof(saveLengthStr), "%" PRIu32, saveLength); JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_CACHE_EQ_SIZE_FAILED, loadLengthStr, saveLengthStr); diff --git a/js/src/tests/ecma_5/strict/primitive-this-getter.js b/js/src/tests/ecma_5/strict/primitive-this-getter.js new file mode 100644 index 00000000000..55fd79d9df4 --- /dev/null +++ b/js/src/tests/ecma_5/strict/primitive-this-getter.js @@ -0,0 +1,56 @@ +let primitives = [ + 10, + false, + "test", + Symbol() +] + +let getter = "getter"; +let getter2 = "getter2"; +let key = "key"; + +for (let value of primitives) { + let prototype = Object.getPrototypeOf(value); + + // Strict getters receive a primitive this value. + Object.defineProperty(prototype, "getter", {get: function() { + "use strict"; + assertEq(this, value); + return "getter"; + }}) + + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); + + // The proxy's [[Get]] trap is also invoked with primitive receiver values. + let proxy = new Proxy({}, { + get(target, property, receiver) { + assertEq(property, "key"); + assertEq(receiver, value); + return "get"; + } + }); + + Object.setPrototypeOf(prototype, proxy); + assertEq(value.key, "get"); + assertEq(value[key], "get"); + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); + + // A getter still gets a primitive this value even after going through a proxy. + proxy = new Proxy({ + get getter2() { + "use strict"; + assertEq(this, value); + return "getter2"; + } + }, {}); + + Object.setPrototypeOf(prototype, proxy); + assertEq(value.getter2, "getter2"); + assertEq(value[getter2], "getter2"); + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); +} + +reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Array/toLocaleString.js b/js/src/tests/ecma_6/Array/toLocaleString.js index 5bc19a839f2..4a16cb4a497 100644 --- a/js/src/tests/ecma_6/Array/toLocaleString.js +++ b/js/src/tests/ecma_6/Array/toLocaleString.js @@ -2,9 +2,7 @@ Object.defineProperty(String.prototype, "toLocaleString", { get() { - // Congratulations! You probably fixed primitive-this getters. - // Change "object" to "string". - assertEq(typeof this, "object"); + assertEq(typeof this, "string"); return function() { return typeof this; }; } diff --git a/js/src/tests/ecma_6/Object/toLocaleString.js b/js/src/tests/ecma_6/Object/toLocaleString.js index bc5a96ea0ab..3fa2acc7460 100644 --- a/js/src/tests/ecma_6/Object/toLocaleString.js +++ b/js/src/tests/ecma_6/Object/toLocaleString.js @@ -2,9 +2,7 @@ Object.defineProperty(String.prototype, "toString", { get() { - // Congratulations! You probably fixed primitive-this getters. - // Change "object" to "string". - assertEq(typeof this, "object"); + assertEq(typeof this, "string"); return function() { return typeof this; }; } diff --git a/js/src/tests/ecma_6/Reflect/get.js b/js/src/tests/ecma_6/Reflect/get.js index 357e9b087a4..b38b188b03c 100644 --- a/js/src/tests/ecma_6/Reflect/get.js +++ b/js/src/tests/ecma_6/Reflect/get.js @@ -64,21 +64,8 @@ assertEq(Reflect.get(obj, "itself"), obj); assertEq(Reflect.get(obj, "itself", Math), Math); assertEq(Reflect.get(Object.create(obj), "itself", Math), Math); -// The receiver shouldn't have to be an object---but we do not implement that -// correctly yet (bug 603201). For now, test the wrong behavior just to make -// sure we don't crash. -var result; -try { - result = Reflect.get(obj, "x", 37.2); -} catch (exc) { - result = exc; -} -if (result === 37.2) { - throw new Error("Congratulations on fixing bug 603201! " + - "Please update this test for 1 karma point."); -} -assertEq(result instanceof TypeError, true); - +// The receiver shouldn't have to be an object +assertEq(Reflect.get(obj, "itself", 37.2), 37.2); // For more Reflect.get tests, see target.js and propertyKeys.js. diff --git a/js/src/tests/ecma_6/Symbol/as-base-value.js b/js/src/tests/ecma_6/Symbol/as-base-value.js index c8880f653b0..4b2ec126bb9 100644 --- a/js/src/tests/ecma_6/Symbol/as-base-value.js +++ b/js/src/tests/ecma_6/Symbol/as-base-value.js @@ -20,9 +20,8 @@ Object.defineProperty(Symbol.prototype, "prop", { get: function () { "use strict"; gets++; - assertEq(typeof this, "object"); - assertEq(this instanceof Symbol, true); - assertEq(this.valueOf(), sym); + assertEq(typeof this, "symbol"); + assertEq(this, sym); return "got"; }, set: function (v) { diff --git a/js/src/tests/js1_8_5/reflect-parse/classes.js b/js/src/tests/js1_8_5/reflect-parse/classes.js index d94ce9efb1b..d479f56fc86 100644 --- a/js/src/tests/js1_8_5/reflect-parse/classes.js +++ b/js/src/tests/js1_8_5/reflect-parse/classes.js @@ -479,6 +479,8 @@ function testClasses() { assertClassError("class NAME { static *y", SyntaxError); assertClassError("class NAME { static get", SyntaxError); assertClassError("class NAME { static get y", SyntaxError); + assertClassError("class NAME { static }", SyntaxError); + assertClassError("class NAME { static ;", SyntaxError); assertClassError("class NAME extends", SyntaxError); assertClassError("class NAME { constructor() { super", SyntaxError); assertClassError("class NAME { constructor() { super.", SyntaxError); diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list index 26861ed683f..c7a1a4c18df 100644 --- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -34,13 +34,6 @@ skip script test262/intl402/ch12/12.2/12.2.2_L15.js skip script test262/ch13/13.2/13.2-15-1.js skip script test262/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js -################################################## -# Test262 tests skipped due to SpiderMonkey bugs # -################################################## - -skip script test262/ch10/10.4/10.4.3/10.4.3-1-104.js # bug 603201 -skip script test262/ch10/10.4/10.4.3/10.4.3-1-106.js # bug 603201 - ####################################################################### # Tests disabled due to jstest limitations wrt imported test262 tests # ####################################################################### diff --git a/js/src/vm/CharacterEncoding.cpp b/js/src/vm/CharacterEncoding.cpp index c33d7000654..cb7bb8ad86f 100644 --- a/js/src/vm/CharacterEncoding.cpp +++ b/js/src/vm/CharacterEncoding.cpp @@ -203,7 +203,7 @@ static void ReportInvalidCharacter(JSContext* cx, uint32_t offset) { char buffer[10]; - JS_snprintf(buffer, 10, "%d", offset); + JS_snprintf(buffer, 10, "%u", offset); JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, GetErrorMessage, nullptr, JSMSG_MALFORMED_UTF8_CHAR, buffer); } diff --git a/js/src/vm/CodeCoverage.cpp b/js/src/vm/CodeCoverage.cpp index f5d628edf39..70225e3bbd1 100644 --- a/js/src/vm/CodeCoverage.cpp +++ b/js/src/vm/CodeCoverage.cpp @@ -535,8 +535,8 @@ LCovRuntime::fillWithFilename(char *name, size_t length) static mozilla::Atomic globalRuntimeId(0); size_t rid = globalRuntimeId++; - size_t len = JS_snprintf(name, length, "%s/%" PRId64 "-%d-%d.info", - outDir, timestamp, size_t(pid_), rid); + size_t len = JS_snprintf(name, length, "%s/%" PRId64 "-%" PRIuSIZE "-%" PRIuSIZE ".info", + outDir, timestamp, pid_, rid); if (length <= len) { fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name."); return false; diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index 0ac4c01ceae..cbf30c2a8d6 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -455,17 +455,15 @@ GetObjectElementOperation(JSContext* cx, JSOp op, JS::HandleObject obj, JS::Hand } static MOZ_ALWAYS_INLINE bool -GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver_, +GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver, HandleValue key, MutableHandleValue res) { MOZ_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM); - // FIXME: We shouldn't be boxing here or exposing the boxed object as - // receiver anywhere below (bug 603201). - RootedObject boxed(cx, ToObjectFromStack(cx, receiver_)); + // FIXME: Bug 1234324 We shouldn't be boxing here. + RootedObject boxed(cx, ToObjectFromStack(cx, receiver)); if (!boxed) return false; - RootedValue receiver(cx, ObjectValue(*boxed)); do { uint32_t index; @@ -495,7 +493,7 @@ GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver_, RootedId id(cx); if (!ToPropertyKey(cx, key, &id)) return false; - if (!GetProperty(cx, boxed, boxed, id, res)) + if (!GetProperty(cx, boxed, receiver, id, res)) return false; } while (false); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 503d7fe6998..3d399610ff2 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -4036,12 +4036,11 @@ js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, MutableHa return true; } + RootedValue receiver(cx, v); RootedObject obj(cx, ToObjectFromStack(cx, v)); if (!obj) return false; - // Bug 603201: Pass primitive receiver here. - RootedValue receiver(cx, ObjectValue(*obj)); return GetProperty(cx, obj, receiver, name, vp); } diff --git a/js/src/vm/JSONParser.cpp b/js/src/vm/JSONParser.cpp index 4ac4d254557..2bc07fadb90 100644 --- a/js/src/vm/JSONParser.cpp +++ b/js/src/vm/JSONParser.cpp @@ -90,9 +90,9 @@ JSONParser::error(const char* msg) const size_t MaxWidth = sizeof("4294967295"); char columnNumber[MaxWidth]; - JS_snprintf(columnNumber, sizeof columnNumber, "%lu", column); + JS_snprintf(columnNumber, sizeof columnNumber, "%" PRIu32, column); char lineNumber[MaxWidth]; - JS_snprintf(lineNumber, sizeof lineNumber, "%lu", line); + JS_snprintf(lineNumber, sizeof lineNumber, "%" PRIu32, line); JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_JSON_BAD_PARSE, msg, lineNumber, columnNumber); diff --git a/js/src/vm/SPSProfiler.cpp b/js/src/vm/SPSProfiler.cpp index db84ac24fd2..6979d26991f 100644 --- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -353,9 +353,9 @@ SPSProfiler::allocProfileString(JSScript* script, JSFunction* maybeFun) : JS::CharsToNewUTF8CharsZ(nullptr, atom->twoByteRange(nogc)).c_str()); if (!atomStr) return nullptr; - ret = JS_snprintf(cstr, len + 1, "%s (%s:%llu)", atomStr.get(), filename, lineno); + ret = JS_snprintf(cstr, len + 1, "%s (%s:%" PRIu64 ")", atomStr.get(), filename, lineno); } else { - ret = JS_snprintf(cstr, len + 1, "%s:%llu", filename, lineno); + ret = JS_snprintf(cstr, len + 1, "%s:%" PRIu64, filename, lineno); } MOZ_ASSERT(ret == len, "Computed length should match actual length!"); diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index 97a1491c38c..f3bd04cb07e 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -1120,7 +1120,7 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram } } - AutoLocationValueRooter location(cx); + Rooted location(cx); { AutoCompartment ac(cx, iter.compartment()); if (!cx->compartment()->savedStacks().getLocation(cx, iter, &location)) @@ -1133,9 +1133,9 @@ SavedStacks::insertFrames(JSContext* cx, FrameIter& iter, MutableHandleSavedFram parentIsInCache = iter.hasCachedSavedFrame(); auto displayAtom = iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr; - if (!stackChain->emplaceBack(location->source, - location->line, - location->column, + if (!stackChain->emplaceBack(location.source(), + location.line(), + location.column(), displayAtom, nullptr, nullptr, @@ -1323,7 +1323,8 @@ SavedStacks::sweepPCLocationMap() } bool -SavedStacks::getLocation(JSContext* cx, const FrameIter& iter, MutableHandleLocationValue locationp) +SavedStacks::getLocation(JSContext* cx, const FrameIter& iter, + MutableHandle locationp) { // We should only ever be caching location values for scripts in this // compartment. Otherwise, we would get dead cross-compartment scripts in @@ -1338,19 +1339,20 @@ SavedStacks::getLocation(JSContext* cx, const FrameIter& iter, MutableHandleLoca if (!iter.hasScript()) { if (const char16_t* displayURL = iter.scriptDisplayURL()) { - locationp->source = AtomizeChars(cx, displayURL, js_strlen(displayURL)); + locationp.setSource(AtomizeChars(cx, displayURL, js_strlen(displayURL))); } else { const char* filename = iter.scriptFilename() ? iter.scriptFilename() : ""; - locationp->source = Atomize(cx, filename, strlen(filename)); + locationp.setSource(Atomize(cx, filename, strlen(filename))); } - if (!locationp->source) + if (!locationp.source()) return false; - locationp->line = iter.computeLine(&locationp->column); + uint32_t column = 0; + locationp.setLine(iter.computeLine(&column)); // XXX: Make the column 1-based as in other browsers, instead of 0-based // which is how SpiderMonkey stores it internally. This will be // unnecessary once bug 1144340 is fixed. - locationp->column++; + locationp.setColumn(column + 1); return true; } diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h index 3c8e7770052..3e26b3fc58d 100644 --- a/js/src/vm/SavedStacks.h +++ b/js/src/vm/SavedStacks.h @@ -224,7 +224,8 @@ class SavedStacks { jsbytecode* pc; }; - struct LocationValue { + public: + struct LocationValue : public JS::Traceable { LocationValue() : source(nullptr), line(0), column(0) { } LocationValue(JSAtom* source, size_t line, uint32_t column) : source(source), @@ -232,6 +233,7 @@ class SavedStacks { column(column) { } + static void trace(LocationValue* self, JSTracer* trc) { self->trace(trc); } void trace(JSTracer* trc) { if (source) TraceEdge(trc, &source, "SavedStacks::LocationValue::source"); @@ -242,38 +244,25 @@ class SavedStacks { uint32_t column; }; - class MOZ_STACK_CLASS AutoLocationValueRooter : public JS::CustomAutoRooter - { - public: - explicit AutoLocationValueRooter(JSContext* cx) - : JS::CustomAutoRooter(cx), - value() {} - - inline LocationValue* operator->() { return &value; } - void set(LocationValue& loc) { value = loc; } - LocationValue& get() { return value; } - + template + struct LocationValueOperations { + JSAtom* source() const { return loc().source; } + size_t line() const { return loc().line; } + uint32_t column() const { return loc().column; } private: - virtual void trace(JSTracer* trc) { - value.trace(trc); - } - - SavedStacks::LocationValue value; + const LocationValue& loc() const { return static_cast(this)->get(); } }; - class MOZ_STACK_CLASS MutableHandleLocationValue - { - public: - inline MOZ_IMPLICIT MutableHandleLocationValue(AutoLocationValueRooter* location) - : location(location) {} - - inline LocationValue* operator->() { return &location->get(); } - void set(LocationValue& loc) { location->set(loc); } - + template + struct MutableLocationValueOperations : public LocationValueOperations { + void setSource(JSAtom* v) { loc().source = v; } + void setLine(size_t v) { loc().line = v; } + void setColumn(uint32_t v) { loc().column = v; } private: - AutoLocationValueRooter* location; + LocationValue& loc() { return static_cast(this)->get(); } }; + private: struct PCLocationHasher : public DefaultHasher { typedef PointerHasher ScriptPtrHasher; typedef PointerHasher BytecodePtrHasher; @@ -293,11 +282,21 @@ class SavedStacks { PCLocationMap pcLocationMap; void sweepPCLocationMap(); - bool getLocation(JSContext* cx, const FrameIter& iter, MutableHandleLocationValue locationp); + bool getLocation(JSContext* cx, const FrameIter& iter, MutableHandle locationp); }; JSObject* SavedStacksMetadataCallback(JSContext* cx, JSObject* target); +template <> +class RootedBase + : public SavedStacks::MutableLocationValueOperations> +{}; + +template <> +class MutableHandleBase + : public SavedStacks::MutableLocationValueOperations> +{}; + } /* namespace js */ #endif /* vm_SavedStacks_h */ diff --git a/js/src/vm/TraceLogging.cpp b/js/src/vm/TraceLogging.cpp index ce7acc6e98a..315446c32fb 100644 --- a/js/src/vm/TraceLogging.cpp +++ b/js/src/vm/TraceLogging.cpp @@ -439,7 +439,7 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f return nullptr; DebugOnly ret = - JS_snprintf(str, len + 1, "script %s:%u:%u", filename, lineno, colno); + JS_snprintf(str, len + 1, "script %s:%" PRIuSIZE ":%" PRIuSIZE, filename, lineno, colno); MOZ_ASSERT(ret == len); MOZ_ASSERT(strlen(str) == len); diff --git a/js/src/vm/TypedArrayCommon.h b/js/src/vm/TypedArrayCommon.h index 393e0d64f74..3cc826c0115 100644 --- a/js/src/vm/TypedArrayCommon.h +++ b/js/src/vm/TypedArrayCommon.h @@ -349,7 +349,7 @@ class ElementSpecific MOZ_ASSERT(SpecificArray::ArrayTypeID() == target->type(), "calling wrong setFromTypedArray specialization"); MOZ_ASSERT(SomeTypedArray::sameBuffer(target, source), - "provided arrays don't actually overlap, so it's " + "the provided arrays don't actually overlap, so it's " "undesirable to use this method"); MOZ_ASSERT(offset <= target->length()); diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 018060140b1..354368956ff 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -69,6 +69,16 @@ class TypedArrayObject : public NativeObject template struct OfType; static bool sameBuffer(Handle a, Handle b) { + // Inline buffers. + if (!a->hasBuffer() || !b->hasBuffer()) + return a.get() == b.get(); + + // Shared buffers. + if (a->isSharedMemory() && b->isSharedMemory()) { + return (a->bufferObject()->as().globalID() == + b->bufferObject()->as().globalID()); + } + return a->bufferObject() == b->bufferObject(); } diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 1961ec82afb..4eac22be800 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -105,6 +105,11 @@ UnboxedLayout::makeConstructorCode(JSContext* cx, HandleObjectGroup group) newKindReg = IntArgReg1; #endif +#ifdef JS_CODEGEN_ARM64 + // ARM64 communicates stack address via sp, but uses a pseudo-sp for addressing. + masm.initStackPtr(); +#endif + MOZ_ASSERT(propertiesReg.volatile_()); MOZ_ASSERT(newKindReg.volatile_()); diff --git a/js/src/vm/make_opcode_doc.py b/js/src/vm/make_opcode_doc.py index 8e3be00b3fc..321c4527eb3 100755 --- a/js/src/vm/make_opcode_doc.py +++ b/js/src/vm/make_opcode_doc.py @@ -333,8 +333,27 @@ def print_opcode(opcode): stack_defs=escape(opcode.stack_defs) or " ", desc=opcode.desc)) # desc is already escaped -def make_element_id(name): - return name.replace(' ', '-') +id_cache = dict() +id_count = dict() + +def make_element_id(category, type=''): + key = '{}:{}'.format(category, type) + if key in id_cache: + return id_cache[key] + + if type == '': + id = category.replace(' ', '_') + else: + id = type.replace(' ', '_') + + if id in id_count: + id_count[id] += 1 + id = '{}_{}'.format(id, id_count[id]) + else: + id_count[id] = 1 + + id_cache[key] = id + return id def print_doc(version, index): print("""
{{{{SpiderMonkeySidebar("Internals")}}}}
@@ -358,7 +377,7 @@ def print_doc(version, index): for (type_name, opcodes) in types: if type_name: print('

{name}

'.format(name=type_name, - id=make_element_id(type_name))) + id=make_element_id(category_name, type_name))) print('
') for opcode in sorted(opcodes, key=lambda opcode: opcode.sort_key): diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e50a12f8bde..176fd430946 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -4758,11 +4758,13 @@ nsDisplayScrollInfoLayer::ComputeFrameMetrics(Layer* aLayer, mScrollFrame->GetPosition() + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame()); - return UniquePtr(new FrameMetrics( - nsLayoutUtils::ComputeFrameMetrics( + FrameMetrics metrics = nsLayoutUtils::ComputeFrameMetrics( mScrolledFrame, mScrollFrame, mScrollFrame->GetContent(), ReferenceFrame(), aLayer, - mScrollParentId, viewport, Nothing(), false, params))); + mScrollParentId, viewport, Nothing(), false, params); + metrics.SetIsScrollInfoLayer(true); + + return UniquePtr(new FrameMetrics(metrics)); } void diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index d67cbcab316..dc07348e300 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3000,7 +3000,7 @@ nsLayoutUtils::CalculateAndSetDisplayPortMargins(nsIScrollableFrame* aScrollFram FrameMetrics metrics = CalculateBasicFrameMetrics(aScrollFrame); ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( - metrics, ParentLayerPoint(0.0f, 0.0f), 0.0); + metrics, ParentLayerPoint(0.0f, 0.0f)); nsIPresShell* presShell = frame->PresContext()->GetPresShell(); return nsLayoutUtils::SetDisplayPortMargins( content, presShell, displayportMargins, 0, aRepaintMode); diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index cc6a875f07b..43a67b3bd48 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -241,7 +241,6 @@ static void Shutdown(); #include "nsITelephonyService.h" #include "nsIVoicemailService.h" -#include "mozilla/dom/FakeTVService.h" #include "mozilla/dom/TVServiceFactory.h" #include "mozilla/dom/TVTypes.h" #include "nsITVService.h" @@ -389,8 +388,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService, NS_CreateTelephonyService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIVoicemailService, NS_CreateVoicemailService) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FakeTVService, - TVServiceFactory::CreateFakeTVService) NS_GENERIC_FACTORY_CONSTRUCTOR(TVTunerData) NS_GENERIC_FACTORY_CONSTRUCTOR(TVChannelData) NS_GENERIC_FACTORY_CONSTRUCTOR(TVProgramData) @@ -850,7 +847,6 @@ NS_DEFINE_NAMED_CID(NS_SYNTHVOICEREGISTRY_CID); #ifdef ACCESSIBILITY NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID); #endif -NS_DEFINE_NAMED_CID(FAKE_TV_SERVICE_CID); NS_DEFINE_NAMED_CID(TV_TUNER_DATA_CID); NS_DEFINE_NAMED_CID(TV_CHANNEL_DATA_CID); NS_DEFINE_NAMED_CID(TV_PROGRAM_DATA_CID); @@ -1154,7 +1150,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor }, { &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor }, { &kNS_VOICEMAIL_SERVICE_CID, false, nullptr, nsIVoicemailServiceConstructor }, - { &kFAKE_TV_SERVICE_CID, false, nullptr, FakeTVServiceConstructor }, { &kTV_TUNER_DATA_CID, false, nullptr, TVTunerDataConstructor }, { &kTV_CHANNEL_DATA_CID, false, nullptr, TVChannelDataConstructor }, { &kTV_PROGRAM_DATA_CID, false, nullptr, TVProgramDataConstructor }, @@ -1319,7 +1314,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID }, #endif { TELEPHONY_SERVICE_CONTRACTID, &kTELEPHONY_SERVICE_CID }, - { FAKE_TV_SERVICE_CONTRACTID, &kFAKE_TV_SERVICE_CID }, { TV_TUNER_DATA_CONTRACTID, &kTV_TUNER_DATA_CID }, { TV_CHANNEL_DATA_CONTRACTID, &kTV_CHANNEL_DATA_CID }, { TV_PROGRAM_DATA_CONTRACTID, &kTV_PROGRAM_DATA_CID }, diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index fe73db6afb3..ec3363785b1 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -4228,12 +4228,14 @@ void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent) ScrollFrameHelper::ScrollEvent::ScrollEvent(ScrollFrameHelper* aHelper) : mHelper(aHelper) { - mHelper->mOuter->PresContext()->RefreshDriver()->AddRefreshObserver(this, Flush_Style); + mDriver = mHelper->mOuter->PresContext()->RefreshDriver(); + mDriver->AddRefreshObserver(this, Flush_Style); } ScrollFrameHelper::ScrollEvent::~ScrollEvent() { - mHelper->mOuter->PresContext()->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style); + mDriver->RemoveRefreshObserver(this, Flush_Style); + mDriver = nullptr; } void diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 5ee4f1195fa..2075921b8a9 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -111,6 +111,7 @@ public: virtual ~ScrollEvent(); private: ScrollFrameHelper *mHelper; + RefPtr mDriver; }; class AsyncScrollPortEvent : public nsRunnable { diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index 0c6b85b77e9..1a3a7075f0b 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -1469,6 +1469,13 @@ Declaration::ToString(nsAString& aString) const /* virtual */ void Declaration::List(FILE* out, int32_t aIndent) const { + const Rule* owningRule = GetOwningRule(); + if (owningRule) { + // More useful to print the selector and sheet URI too. + owningRule->List(out, aIndent); + return; + } + nsAutoCString str; for (int32_t index = aIndent; --index >= 0; ) { str.AppendLiteral(" "); diff --git a/layout/style/Declaration.h b/layout/style/Declaration.h index 6b93a4a43cf..b044c539436 100644 --- a/layout/style/Declaration.h +++ b/layout/style/Declaration.h @@ -325,7 +325,7 @@ public: mContainer.mOwningRule = aRule; } - Rule* GetOwningRule() { + Rule* GetOwningRule() const { if (mContainer.mRaw & 0x1) { return nullptr; } @@ -341,7 +341,7 @@ public: } } - nsHTMLCSSStyleSheet* GetHTMLCSSStyleSheet() { + nsHTMLCSSStyleSheet* GetHTMLCSSStyleSheet() const { if (!(mContainer.mRaw & 0x1)) { return nullptr; } diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 91c4c7e51f0..1afbaa9eec1 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -386,6 +386,26 @@ nsAnimationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } +void +nsAnimationManager::CopyIsRunningOnCompositor( + KeyframeEffectReadOnly& aSourceEffect, + KeyframeEffectReadOnly& aDestEffect) +{ + nsCSSPropertySet sourceProperties; + + for (AnimationProperty& property : aSourceEffect.Properties()) { + if (property.mIsRunningOnCompositor) { + sourceProperties.AddProperty(property.mProperty); + } + } + + for (AnimationProperty& property : aDestEffect.Properties()) { + if (sourceProperties.HasProperty(property.mProperty)) { + property.mIsRunningOnCompositor = true; + } + } +} + nsIStyleRule* nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, mozilla::dom::Element* aElement) @@ -493,6 +513,12 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, oldEffect->Timing() != newEffect->Timing() || oldEffect->Properties() != newEffect->Properties(); oldEffect->SetTiming(newEffect->Timing()); + + // To preserve the mIsRunningOnCompositor value on each property, + // we copy it from the old effect to the new effect since, in the + // following step, we will completely clobber the properties on the + // old effect with the values on the new effect. + CopyIsRunningOnCompositor(*oldEffect, *newEffect); oldEffect->Properties() = newEffect->Properties(); } @@ -789,7 +815,6 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, AnimationProperty &propData = *destEffect->Properties().AppendElement(); propData.mProperty = prop; - propData.mWinsInCascade = true; KeyframeData *fromKeyframe = nullptr; RefPtr fromContext; diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 2ffc09a0564..faa8830b032 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -22,6 +22,7 @@ namespace css { class Declaration; } /* namespace css */ namespace dom { +class KeyframeEffectReadOnly; class Promise; } /* namespace dom */ @@ -373,6 +374,9 @@ private: static void UpdateCascadeResults(nsStyleContext* aStyleContext, mozilla::AnimationCollection* aElementAnimations); + static void CopyIsRunningOnCompositor( + mozilla::dom::KeyframeEffectReadOnly& aSourceEffect, + mozilla::dom::KeyframeEffectReadOnly& aDestEffect); }; #endif /* !defined(nsAnimationManager_h_) */ diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index bf036c3d378..da7f925f8ee 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -679,7 +679,6 @@ nsTransitionManager::ConsiderStartingTransition( AnimationProperty& prop = *pt->Properties().AppendElement(); prop.mProperty = aProperty; - prop.mWinsInCascade = true; AnimationPropertySegment& segment = *prop.mSegments.AppendElement(); segment.mFromValue = startValue; diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index c45ecde6578..5ab3d717e38 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -131,6 +131,7 @@ support-files = file_bug1055933_circle-xxl.png support-files = file_bug1089417_iframe.html [test_bug1112014.html] [test_bug1203766.html] +[test_bug1232829.html] [test_cascade.html] [test_ch_ex_no_infloops.html] [test_compute_data_with_start_struct.html] diff --git a/layout/style/test/test_bug1232829.html b/layout/style/test/test_bug1232829.html new file mode 100644 index 00000000000..8981d56e073 --- /dev/null +++ b/layout/style/test/test_bug1232829.html @@ -0,0 +1,38 @@ + + + + + +Test for Bug 1232829 + + + + + + + + diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index 3e19d96ee8f..560a0f27fea 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -472,6 +472,9 @@ @BINPATH@/components/PACGenerator.js @BINPATH@/components/PACGenerator.manifest +@BINPATH@/components/TVSimulatorService.js +@BINPATH@/components/TVSimulatorService.manifest + ; Modules @BINPATH@/modules/* diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 8df6564dc37..60ee556daad 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -10,6 +10,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" #include "mozilla/HashFunctions.h" +#include "mozilla/UniquePtrExtensions.h" #include "nsXULAppAPI.h" @@ -937,25 +938,23 @@ Preferences::WritePrefFile(nsIFile* aFile) if (NS_FAILED(rv)) return rv; - nsAutoArrayPtr valueArray(new char*[gHashTable->EntryCount()]); - memset(valueArray, 0, gHashTable->EntryCount() * sizeof(char*)); - // get the lines that we're supposed to be writing to the file - pref_savePrefs(gHashTable, valueArray); + UniquePtr valueArray = pref_savePrefs(gHashTable); /* Sort the preferences to make a readable file on disk */ - NS_QuickSort(valueArray, gHashTable->EntryCount(), sizeof(char *), + NS_QuickSort(valueArray.get(), gHashTable->EntryCount(), sizeof(char *), pref_CompareStrings, nullptr); // write out the file header outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount); - char** walker = valueArray; - for (uint32_t valueIdx = 0; valueIdx < gHashTable->EntryCount(); valueIdx++, walker++) { - if (*walker) { - outStream->Write(*walker, strlen(*walker), &writeAmount); + for (uint32_t valueIdx = 0; valueIdx < gHashTable->EntryCount(); valueIdx++) { + char*& pref = valueArray[valueIdx]; + if (pref) { + outStream->Write(pref, strlen(pref), &writeAmount); outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount); - free(*walker); + free(pref); + pref = nullptr; } } @@ -990,7 +989,7 @@ static nsresult openPrefFile(nsIFile* aFile) NS_ENSURE_TRUE(fileSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG); uint32_t fileSize = (uint32_t)fileSize64; - nsAutoArrayPtr fileBuffer(new char[fileSize]); + auto fileBuffer = MakeUniqueFallible(fileSize); if (fileBuffer == nullptr) return NS_ERROR_OUT_OF_MEMORY; @@ -1003,10 +1002,10 @@ static nsresult openPrefFile(nsIFile* aFile) uint32_t offset = 0; for (;;) { uint32_t amtRead = 0; - rv = inStr->Read((char*)fileBuffer, fileSize, &amtRead); + rv = inStr->Read(fileBuffer.get(), fileSize, &amtRead); if (NS_FAILED(rv) || amtRead == 0) break; - if (!PREF_ParseBuf(&ps, fileBuffer, amtRead)) + if (!PREF_ParseBuf(&ps, fileBuffer.get(), amtRead)) rv2 = NS_ERROR_FILE_CORRUPTED; offset += amtRead; if (offset == fileSize) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 510d1e6833c..56ef23022b8 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -335,15 +335,12 @@ pref("media.raw.enabled", true); #endif pref("media.ogg.enabled", true); pref("media.opus.enabled", true); -#ifdef MOZ_WAVE pref("media.wave.enabled", true); -#endif -#ifdef MOZ_WEBM pref("media.webm.enabled", true); #if defined(MOZ_FMP4) && defined(MOZ_WMF) pref("media.webm.intel_decoder.enabled", false); #endif -#endif + #ifdef MOZ_GSTREAMER pref("media.gstreamer.enabled", true); pref("media.gstreamer.enable-blacklist", true); @@ -576,7 +573,6 @@ pref("apz.max_velocity_inches_per_ms", "-1.0"); pref("apz.max_velocity_queue_size", 5); pref("apz.min_skate_speed", "1.0"); pref("apz.minimap.enabled", false); -pref("apz.num_paint_duration_samples", 3); pref("apz.overscroll.enabled", false); pref("apz.overscroll.min_pan_distance_ratio", "1.0"); pref("apz.overscroll.spring_friction", "0.015"); @@ -593,7 +589,6 @@ pref("apz.smooth_scroll_repaint_interval", 16); pref("apz.test.logging_enabled", false); pref("apz.touch_start_tolerance", "0.1"); pref("apz.touch_move_tolerance", "0.03"); -pref("apz.use_paint_duration", true); pref("apz.velocity_bias", "1.0"); pref("apz.velocity_relevance_time_ms", 150); pref("apz.x_skate_highmem_adjust", "0.0"); diff --git a/modules/libpref/prefapi.cpp b/modules/libpref/prefapi.cpp index dd2776987ef..1caa0538614 100644 --- a/modules/libpref/prefapi.cpp +++ b/modules/libpref/prefapi.cpp @@ -318,9 +318,12 @@ pref_SetPref(const dom::PrefSetting& aPref) return rv; } -void -pref_savePrefs(PLDHashTable* aTable, char** aPrefArray) +UniquePtr +pref_savePrefs(PLDHashTable* aTable) { + auto savedPrefs = MakeUnique(aTable->EntryCount()); + memset(savedPrefs.get(), 0, aTable->EntryCount() * sizeof(char*)); + int32_t j = 0; for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) { auto pref = static_cast(iter.Get()); @@ -360,12 +363,14 @@ pref_savePrefs(PLDHashTable* aTable, char** aPrefArray) nsAutoCString prefName; str_escape(pref->key, prefName); - aPrefArray[j++] = ToNewCString(prefPrefix + + savedPrefs[j++] = ToNewCString(prefPrefix + prefName + NS_LITERAL_CSTRING("\", ") + prefValue + NS_LITERAL_CSTRING(");")); } + + return savedPrefs; } static void diff --git a/modules/libpref/prefapi_private_data.h b/modules/libpref/prefapi_private_data.h index 45b6a4d7338..f91b0d6c749 100644 --- a/modules/libpref/prefapi_private_data.h +++ b/modules/libpref/prefapi_private_data.h @@ -9,6 +9,7 @@ #define prefapi_private_data_h #include "mozilla/MemoryReporting.h" +#include "mozilla/UniquePtr.h" extern PLDHashTable* gHashTable; extern bool gDirty; @@ -19,8 +20,8 @@ class PrefSetting; } // namespace dom } // namespace mozilla -void -pref_savePrefs(PLDHashTable* aTable, char** aPrefArray); +mozilla::UniquePtr +pref_savePrefs(PLDHashTable* aTable); nsresult pref_SetPref(const mozilla::dom::PrefSetting& aPref); diff --git a/netwerk/base/nsFileStreams.cpp b/netwerk/base/nsFileStreams.cpp index 17a87a76b27..31f1cca1d29 100644 --- a/netwerk/base/nsFileStreams.cpp +++ b/netwerk/base/nsFileStreams.cpp @@ -21,6 +21,8 @@ #include "nsReadLine.h" #include "nsIClassInfoImpl.h" #include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/unused.h" +#include "mozilla/FileUtils.h" #include "nsNetCID.h" #include "nsXULAppAPI.h" @@ -866,6 +868,20 @@ nsFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm, mBehaviorFlags & nsIFileOutputStream::DEFER_OPEN); } +NS_IMETHODIMP +nsFileOutputStream::Preallocate(int64_t aLength) +{ + if (!mFD) { + return NS_ERROR_NOT_INITIALIZED; + } + + if (!mozilla::fallocate(mFD, aLength)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// // nsAtomicFileOutputStream diff --git a/netwerk/base/nsIFileStreams.idl b/netwerk/base/nsIFileStreams.idl index 7c10d291f72..3b74a736fc8 100644 --- a/netwerk/base/nsIFileStreams.idl +++ b/netwerk/base/nsIFileStreams.idl @@ -87,7 +87,7 @@ interface nsIFileInputStream : nsIInputStream /** * An output stream that lets you stream to a file. */ -[scriptable, uuid(e6f68040-c7ec-11d3-8cda-0060b0fc14a3)] +[scriptable, uuid(e734cac9-1295-4e6f-9684-3ac4e1f91063)] interface nsIFileOutputStream : nsIOutputStream { /** @@ -104,6 +104,15 @@ interface nsIFileOutputStream : nsIOutputStream void init(in nsIFile file, in long ioFlags, in long perm, in long behaviorFlags); + /** + * @param length asks the operating system to allocate storage for + * this file of at least |length| bytes long, and + * set the file length to the corresponding size. + * @throws NS_ERROR_FAILURE if the preallocation fails. + * @throws NS_ERROR_NOT_INITIALIZED if the file is not opened. + */ + [noscript] void preallocate(in long long length); + /** * See the same constant in nsIFileInputStream. The deferred open will * be performed when one of the following is called: diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 0389e94cc98..a1a7025b802 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -1126,6 +1126,22 @@ NS_BufferOutputStream(nsIOutputStream *aOutputStream, return bos.forget(); } +already_AddRefed +NS_BufferInputStream(nsIInputStream *aInputStream, + uint32_t aBufferSize) +{ + NS_ASSERTION(aInputStream, "No input stream given!"); + + nsCOMPtr bis; + nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bis), aInputStream, + aBufferSize); + if (NS_SUCCEEDED(rv)) + return bis.forget(); + + bis = aInputStream; + return bis.forget(); +} + nsresult NS_ReadInputStreamToBuffer(nsIInputStream *aInputStream, void **aDest, diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h index c001c2e1e7e..d512ce2f4b5 100644 --- a/netwerk/base/nsNetUtil.h +++ b/netwerk/base/nsNetUtil.h @@ -572,8 +572,8 @@ nsresult NS_NewBufferedOutputStream(nsIOutputStream **result, uint32_t bufferSize); /** - * Attempts to buffer a given output stream. If this fails, it returns the - * passed-in output stream. + * Attempts to buffer a given stream. If this fails, it returns the + * passed-in stream. * * @param aOutputStream * The output stream we want to buffer. This cannot be null. @@ -585,6 +585,9 @@ nsresult NS_NewBufferedOutputStream(nsIOutputStream **result, already_AddRefed NS_BufferOutputStream(nsIOutputStream *aOutputStream, uint32_t aBufferSize); +already_AddRefed +NS_BufferInputStream(nsIInputStream *aInputStream, + uint32_t aBufferSize); // returns an input stream compatible with nsIUploadChannel::SetUploadStream() nsresult NS_NewPostDataStream(nsIInputStream **result, diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index 075ddb29c47..8e08e9581be 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -183,7 +183,6 @@ private: nsCOMPtr mRedirectChannelChild; RefPtr mInterceptListener; RefPtr mSynthesizedResponsePump; - nsAutoPtr mSynthesizedResponseHead; nsCOMPtr mSynthesizedInput; int64_t mSynthesizedStreamLength; diff --git a/netwerk/test/mochitests/mochitest.ini b/netwerk/test/mochitests/mochitest.ini index 13f28c8d81f..ecadbe7120a 100644 --- a/netwerk/test/mochitests/mochitest.ini +++ b/netwerk/test/mochitests/mochitest.ini @@ -9,6 +9,7 @@ support-files = user_agent_update.sjs web_packaged_app.sjs signed_web_packaged_app.sjs + signed_web_packaged_app_random.sjs file_loadinfo_redirectchain.sjs redirect_idn.html^headers^ redirect_idn.html @@ -29,6 +30,8 @@ skip-if = e10s skip-if = e10s || buildapp != 'browser' [test_signed_web_packaged_app_origin.html] skip-if = e10s || buildapp != 'browser' +[test_signed_to_signed_web_packaged_app.html] +skip-if = e10s || buildapp != 'browser' [test_web_packaged_app.html] [test_loadinfo_redirectchain.html] skip-if = buildapp == 'b2g' #no ssl support diff --git a/netwerk/test/mochitests/signed_web_packaged_app_random.sjs b/netwerk/test/mochitests/signed_web_packaged_app_random.sjs new file mode 100644 index 00000000000..f3773ac4496 --- /dev/null +++ b/netwerk/test/mochitests/signed_web_packaged_app_random.sjs @@ -0,0 +1,92 @@ +// Same as signed_web_packaged_app.sjs except this one would return a random +// package-identifer. + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; + +var uuid = Cc["@mozilla.org/uuid-generator;1"]. + getService(Ci.nsIUUIDGenerator). + generateUUID(). + toString().replace(/[{}]/g, ""); + +function handleRequest(request, response) +{ + response.setHeader("Content-Type", "application/package", false); + response.write(signedPackage); + return; +} + +// The package content +// getData formats it as described at http://www.w3.org/TR/web-packaging/#streamable-package-format +var signedPackage = `manifest-signature: MIIF1AYJKoZIhvcNAQcCoIIFxTCCBcECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCCA54wggOaMIICgqADAgECAgECMA0GCSqGSIb3DQEBCwUAMHMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEkMCIGA1UEChMbRXhhbXBsZSBUcnVzdGVkIENvcnBvcmF0aW9uMRkwFwYDVQQDExBUcnVzdGVkIFZhbGlkIENBMB4XDTE1MDkxMDA4MDQzNVoXDTM1MDkxMDA4MDQzNVowdDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MSQwIgYDVQQKExtFeGFtcGxlIFRydXN0ZWQgQ29ycG9yYXRpb24xGjAYBgNVBAMTEVRydXN0ZWQgQ29ycCBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAts8whjOzEbn/w1xkFJ67af7F/JPujBK91oyJekh2schIMzFau9pY8S1AiJQoJCulOJCJfUc8hBLKBZiGAkii+4Gpx6cVqMLe6C22MdD806Soxn8Dg4dQqbIvPuI4eeVKu5CEk80PW/BaFMmRvRHO62C7PILuH6yZeGHC4P7dTKpsk4CLxh/jRGXLC8jV2BCW0X+3BMbHBg53NoI9s1Gs7KGYnfOHbBP5wEFAa00RjHnubUaCdEBlC8Kl4X7p0S4RGb3rsB08wgFe9EmSZHIgcIm+SuVo7N4qqbI85qo2ulU6J8NN7ZtgMPHzrMhzgAgf/KnqPqwDIxnNmRNJmHTUYwIDAQABozgwNjAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAukH6cJUUj5faa8CuPCqrEa0PoLY4SYNnff9NI+TTAHkB9l+kOcFl5eo2EQOcWmZKYi7QLlWC4jy/KQYattO9FMaxiOQL4FAc6ZIbNyfwWBzZWyr5syYJTTTnkLq8A9pCKarN49+FqhJseycU+8EhJEJyP5pv5hLvDNTTHOQ6SXhASsiX8cjo3AY4bxA5pWeXuTZ459qDxOnQd+GrOe4dIeqflk0hA2xYKe3SfF+QlK8EO370B8Dj8RX230OATM1E3OtYyALe34KW3wM9Qm9rb0eViDnVyDiCWkhhQnw5yPg/XQfloug2itRYuCnfUoRt8xfeHgwz2Ymz8cUADn3KpTGCAf4wggH6AgEBMHgwczELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MSQwIgYDVQQKExtFeGFtcGxlIFRydXN0ZWQgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFRydXN0ZWQgVmFsaWQgQ0ECAQIwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE1MTAyODExMTIwMlowIwYJKoZIhvcNAQkEMRYEFENKTXRUkdej+EPd/oKRhz0Cp13zMA0GCSqGSIb3DQEBAQUABIIBAFCr+i8cwTiwzzCVjzZZI2NAqu8dnYOAJjkhD02tJjBCbvehEhXW6pP/Gk8+oyx2zoV87zbw9xBGcEU9b3ulbggdFR56S3C3w+eTbeOXMcx7A8mn9vvsoMJm+/rkT4DgEUU1iaM7pdwH48CKJOnAZP5FkjRvpRBh8TgfcDbusXveYTwG5LVpDp8856+9FBzvZ7wLz9iWDvlT/EFxfWOnGduAJunQ9qQm+pWu5cvSTwWasCMYmiPRlsuBhU9Fx7LtlXIHtE2nYYQVMTMDE58z/mzT34W0bnneecrghHREhb90UvdlUZJ2q3Jahsa3718WUGPTp7ZYwYaPBy7ryoOoWSA=\r +--7IYGY9UDJB\r +Content-Location: manifest.webapp\r +Content-Type: application/x-web-app-manifest+json\r +\r +{ + "moz-package-origin": "http://mochi.test:8888", + "name": "My App", + "moz-resources": [ + { + "src": "page2.html", + "integrity": "JREF3JbXGvZ+I1KHtoz3f46ZkeIPrvXtG4VyFQrJ7II=" + }, + { + "src": "index.html", + "integrity": "IjQ2S/V9qsC7wW5uv/Niq40M1aivvqH5+1GKRwUnyRg=" + }, + { + "src": "scripts/script.js", + "integrity": "6TqtNArQKrrsXEQWu3D9ZD8xvDRIkhyV6zVdTcmsT5Q=" + }, + { + "src": "scripts/library.js", + "integrity": "TN2ByXZiaBiBCvS4MeZ02UyNi44vED+KjdjLInUl4o8=" + } + ], + "moz-permissions": [ + { + "systemXHR": { + "description": "Needed to download stuff" + }, + "devicestorage:pictures": { + "description": "Need to load pictures" + } + } + ], + +` + + ' "package-identifier": "' + uuid + '",\n\r' + +` + "description": "A great app!" +}\r +--7IYGY9UDJB\r +Content-Location: page2.html\r +Content-Type: text/html\r +\r + + page2.html + +\r +--7IYGY9UDJB\r +Content-Location: index.html\r +Content-Type: text/html\r +\r + + Last updated: 2015/10/28 + +\r +--7IYGY9UDJB\r +Content-Location: scripts/script.js\r +Content-Type: text/javascript\r +\r +// script.js +\r +--7IYGY9UDJB\r +Content-Location: scripts/library.js\r +Content-Type: text/javascript\r +\r +// library.js +\r +--7IYGY9UDJB--`; diff --git a/netwerk/test/mochitests/test_signed_to_signed_web_packaged_app.html b/netwerk/test/mochitests/test_signed_to_signed_web_packaged_app.html new file mode 100644 index 00000000000..d57ff08af7a --- /dev/null +++ b/netwerk/test/mochitests/test_signed_to_signed_web_packaged_app.html @@ -0,0 +1,83 @@ + + + + Web packaged app + + + + + +

+ +
+
+
+ + diff --git a/netwerk/test/unit/test_304_responses.js b/netwerk/test/unit/test_304_responses.js index ace151b2ff3..033c337b7fe 100644 --- a/netwerk/test/unit/test_304_responses.js +++ b/netwerk/test/unit/test_304_responses.js @@ -2,7 +2,7 @@ // https://bugzilla.mozilla.org/show_bug.cgi?id=761228 Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -26,16 +26,8 @@ function make_uri(url) { } function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER).QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } function clearCache() { @@ -76,7 +68,7 @@ function consume304(request, buffer) { // a 304 response (i.e. when the server shouldn't have sent us one). add_test(function test_unexpected_304() { var chan = make_channel(baseURI + unexpected304); - chan.asyncOpen(new ChannelListener(consume304, null), null); + chan.asyncOpen2(new ChannelListener(consume304, null)); }); // Test that we can cope with a 304 response that was (erroneously) stored in @@ -98,6 +90,6 @@ add_test(function test_304_stored_in_cache() { chan.QueryInterface(Components.interfaces.nsIHttpChannel); chan.setRequestHeader("If-None-Match", '"foo"', false); - chan.asyncOpen(new ChannelListener(consume304, null), null); + chan.asyncOpen2(new ChannelListener(consume304, null)); }); }); diff --git a/netwerk/test/unit/test_bug1064258.js b/netwerk/test/unit/test_bug1064258.js index e7b6bdc56d2..3f76837ae93 100644 --- a/netwerk/test/unit/test_bug1064258.js +++ b/netwerk/test/unit/test_bug1064258.js @@ -11,7 +11,7 @@ */ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -20,16 +20,7 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() { var httpServer = null; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const responseBody1 = "response body 1"; @@ -81,7 +72,7 @@ function run_test_content1a() var chan = make_channel(URL + "/content1"); caching = chan.QueryInterface(Ci.nsICachingChannel); caching.cacheOnlyMetadata = true; - chan.asyncOpen(new ChannelListener(contentListener1a, null), null); + chan.asyncOpen2(new ChannelListener(contentListener1a, null)); } function contentListener1a(request, buffer) @@ -105,7 +96,7 @@ function cacheCheck1(status, entry) var chan = make_channel(URL + "/content1"); caching = chan.QueryInterface(Ci.nsICachingChannel); caching.cacheOnlyMetadata = true; - chan.asyncOpen(new ChannelListener(contentListener1b, null, CL_IGNORE_CL), null); + chan.asyncOpen2(new ChannelListener(contentListener1b, null, CL_IGNORE_CL)); } function contentListener1b(request, buffer) @@ -126,7 +117,7 @@ function run_test_content2a() var chan = make_channel(URL + "/content2"); caching = chan.QueryInterface(Ci.nsICachingChannel); caching.cacheOnlyMetadata = true; - chan.asyncOpen(new ChannelListener(contentListener2a, null), null); + chan.asyncOpen2(new ChannelListener(contentListener2a, null)); } function contentListener2a(request, buffer) @@ -151,7 +142,7 @@ function cacheCheck2(status, entry) var chan = make_channel(URL + "/content2"); caching = chan.QueryInterface(Ci.nsICachingChannel); caching.cacheOnlyMetadata = true; - chan.asyncOpen(new ChannelListener(contentListener2b, null), null); + chan.asyncOpen2(new ChannelListener(contentListener2b, null)); } function contentListener2b(request, buffer) diff --git a/netwerk/test/unit/test_bug248970_cookie.js b/netwerk/test/unit/test_bug248970_cookie.js index c4e6da15331..41c45e10593 100644 --- a/netwerk/test/unit/test_bug248970_cookie.js +++ b/netwerk/test/unit/test_bug248970_cookie.js @@ -4,6 +4,7 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver; @@ -13,23 +14,16 @@ function inChildProcess() { .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; } function makeChan(path) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + httpserver.identity.primaryPort + "/" + path, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + "/" + path, + loadUsingSystemPrincipal: true + }).QueryInterface(Ci.nsIHttpChannel); } function setup_chan(path, isPrivate, callback) { var chan = makeChan(path); chan.QueryInterface(Ci.nsIPrivateBrowsingChannel).setPrivate(isPrivate); - chan.asyncOpen(new ChannelListener(callback), null); + chan.asyncOpen2(new ChannelListener(callback)); } function set_cookie(value, callback) { diff --git a/netwerk/test/unit/test_bug263127.js b/netwerk/test/unit/test_bug263127.js index 91949d76401..8262c07e844 100644 --- a/netwerk/test/unit/test_bug263127.js +++ b/netwerk/test/unit/test_bug263127.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var server; const BUGID = "263127"; @@ -39,18 +39,10 @@ function run_test() { server.start(-1); // Initialize downloader - var channel = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .newChannel2("http://localhost:" + - server.identity.primaryPort + "/", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - + var channel = NetUtil.newChannel({ + uri: "http://localhost:" + server.identity.primaryPort + "/", + loadUsingSystemPrincipal: true + }); var targetFile = Cc["@mozilla.org/file/directory_service;1"] .getService(Ci.nsIProperties) .get("TmpD", Ci.nsIFile); @@ -63,7 +55,7 @@ function run_test() { downloader.init(listener, targetFile); // Start download - channel.asyncOpen(downloader, null); + channel.asyncOpen2(downloader); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug282432.js b/netwerk/test/unit/test_bug282432.js index 9d294e5a088..f8da54356ad 100644 --- a/netwerk/test/unit/test_bug282432.js +++ b/netwerk/test/unit/test_bug282432.js @@ -1,4 +1,4 @@ -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); function run_test() { do_test_pending(); @@ -34,12 +34,9 @@ function run_test() { // This file does not exist. let file = do_get_file("_NOT_EXIST_.txt", true); do_check_false(file.exists()); - - let channel = ios.newChannelFromURI2(ios.newFileURI(file), - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - channel.asyncOpen(listener, null); + let channel = NetUtil.newChannel({ + uri: ios.newFileURI(file), + loadUsingSystemPrincipal: true + }); + channel.asyncOpen2(listener); } diff --git a/netwerk/test/unit/test_bug369787.js b/netwerk/test/unit/test_bug369787.js index 32e682a3406..d59bef005c7 100644 --- a/netwerk/test/unit/test_bug369787.js +++ b/netwerk/test/unit/test_bug369787.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); const BUGID = "369787"; var server = null; @@ -55,21 +55,12 @@ function run_test() { server.start(-1); // make request - channel = - Components.classes["@mozilla.org/network/io-service;1"]. - getService(Components.interfaces.nsIIOService). - newChannel2("http://localhost:" + - server.identity.primaryPort + "/bug" + BUGID, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - + channel = NetUtil.newChannel({ + uri: "http://localhost:" + server.identity.primaryPort + "/bug" + BUGID, + loadUsingSystemPrincipal: true + }); channel.QueryInterface(Components.interfaces.nsIHttpChannel); - channel.asyncOpen(new TestListener(), null); + channel.asyncOpen2(new TestListener()); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug376660.js b/netwerk/test/unit/test_bug376660.js index bdc30aff973..8208eef6a6c 100644 --- a/netwerk/test/unit/test_bug376660.js +++ b/netwerk/test/unit/test_bug376660.js @@ -1,4 +1,4 @@ -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var Cc = Components.classes; var Ci = Components.interfaces; @@ -45,17 +45,11 @@ function test1() { createInstance(Ci.nsIUnicharStreamLoader); f.init(listener); - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var chan = ios.newChannel2("data:text/plain,", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - chan.asyncOpen(f, null); + var chan = NetUtil.newChannel({ + uri: "data:text/plain,", + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(f); do_test_pending(); } @@ -65,18 +59,12 @@ function test2() { createInstance(Ci.nsIUnicharStreamLoader); f.init(listener); - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var chan = ios.newChannel2("http://localhost:0/", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:0/", + loadUsingSystemPrincipal: true + }); listener.expect_failure = true; - chan.asyncOpen(f, null); + chan.asyncOpen2(f); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug412945.js b/netwerk/test/unit/test_bug412945.js index da1e22cbdd3..e8b39774b35 100644 --- a/netwerk/test/unit/test_bug412945.js +++ b/netwerk/test/unit/test_bug412945.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserv; @@ -21,22 +21,14 @@ function run_test() { httpserv.start(-1); // make request - var channel = - Components.classes["@mozilla.org/network/io-service;1"]. - getService(Components.interfaces.nsIIOService). - newChannel2("http://localhost:" + httpserv.identity.primaryPort + - "/bug412945", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var channel = NetUtil.newChannel({ + uri: "http://localhost:" + httpserv.identity.primaryPort + "/bug412945", + loadUsingSystemPrincipal: true + }); channel.QueryInterface(Components.interfaces.nsIHttpChannel); channel.requestMethod = "POST"; - channel.asyncOpen(new TestListener(), null); + channel.asyncOpen2(new TestListener(), null); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug468594.js b/netwerk/test/unit/test_bug468594.js index 81c333ae1dd..66d463190e0 100644 --- a/netwerk/test/unit/test_bug468594.js +++ b/netwerk/test/unit/test_bug468594.js @@ -14,7 +14,7 @@ // definition of "explicit expiration time" being used here. Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var index = 0; @@ -57,16 +57,10 @@ function logit(i, data) { } function setupChannel(suffix, value) { - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + httpserver.identity.primaryPort + suffix, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + suffix, + loadUsingSystemPrincipal: true + }); var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); httpChan.requestMethod = "GET"; httpChan.setRequestHeader("x-request", value, false); @@ -75,7 +69,7 @@ function setupChannel(suffix, value) { function triggerNextTest() { var channel = setupChannel(tests[index].url, tests[index].server); - channel.asyncOpen(new ChannelListener(checkValueAndTrigger, null),null); + channel.asyncOpen2(new ChannelListener(checkValueAndTrigger, null)); } function checkValueAndTrigger(request, data, ctx) { diff --git a/netwerk/test/unit/test_bug482601.js b/netwerk/test/unit/test_bug482601.js index 20089a34f3d..fde70f005e4 100644 --- a/netwerk/test/unit/test_bug482601.js +++ b/netwerk/test/unit/test_bug482601.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserv = null; var test_nr = 0; @@ -80,16 +80,8 @@ var results = ["http-on-examine-response", "http-on-examine-cached-response"]; function makeChan(url) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER).QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } function storeCache(aCacheEntry, aResponseHeads, aContent) { @@ -113,7 +105,7 @@ function test_nocache() { var chan = makeChan("http://localhost:" + httpserv.identity.primaryPort + "/bug482601/nocache"); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function test_partial() { @@ -139,7 +131,7 @@ function test_partial2(status, entry) { var chan = makeChan("http://localhost:" + httpserv.identity.primaryPort + "/bug482601/partial"); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function test_cached() { @@ -166,7 +158,7 @@ function test_cached2(status, entry) { var chan = makeChan("http://localhost:" + httpserv.identity.primaryPort + "/bug482601/cached"); chan.loadFlags = Ci.nsIRequest.VALIDATE_ALWAYS; - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function test_only_from_cache() { @@ -193,7 +185,7 @@ function test_only_from_cache2(status, entry) { var chan = makeChan("http://localhost:" + httpserv.identity.primaryPort + "/bug482601/only_from_cache"); chan.loadFlags = Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE; - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } diff --git a/netwerk/test/unit/test_bug490095.js b/netwerk/test/unit/test_bug490095.js index f75d26c9efa..8b588b1a8a7 100644 --- a/netwerk/test/unit/test_bug490095.js +++ b/netwerk/test/unit/test_bug490095.js @@ -4,7 +4,7 @@ // Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var index = 0; @@ -40,18 +40,10 @@ function logit(i, data) { } function setupChannel(suffix, value) { - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + - suffix, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + suffix, + loadUsingSystemPrincipal: true + }); var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); httpChan.requestMethod = "GET"; httpChan.setRequestHeader("x-request", value, false); @@ -62,7 +54,7 @@ function triggerNextTest() { var test = tests[index]; var channel = setupChannel(test.url, test.server); if (test.flags) channel.loadFlags = test.flags; - channel.asyncOpen(new ChannelListener(checkValueAndTrigger, null), null); + channel.asyncOpen2(new ChannelListener(checkValueAndTrigger, null)); } function checkValueAndTrigger(request, data, ctx) { diff --git a/netwerk/test/unit/test_bug536324_64bit_content_length.js b/netwerk/test/unit/test_bug536324_64bit_content_length.js index dea7e52f779..1dcb475be75 100644 --- a/netwerk/test/unit/test_bug536324_64bit_content_length.js +++ b/netwerk/test/unit/test_bug536324_64bit_content_length.js @@ -2,7 +2,7 @@ a simple HTTP case */ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); // This C-L is significantly larger than (U)INT32_MAX, to make sure we do // 64-bit properly. @@ -47,18 +47,11 @@ function hugeContentLength(metadata, response) { } function test_hugeContentLength() { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpServer.identity.primaryPort + "/", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); - chan.asyncOpen(listener, null); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpServer.identity.primaryPort + "/", + loadUsingSystemPrincipal: true + }).QueryInterface(Ci.nsIHttpChannel); + chan.asyncOpen2(listener); } add_test(test_hugeContentLength); diff --git a/netwerk/test/unit/test_bug561276.js b/netwerk/test/unit/test_bug561276.js index ca62f1f9efc..fd67d24dc61 100644 --- a/netwerk/test/unit/test_bug561276.js +++ b/netwerk/test/unit/test_bug561276.js @@ -4,25 +4,17 @@ // Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var iteration = 0; function setupChannel(suffix) { - var ios = - Components.classes["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + suffix, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + suffix, + loadUsingSystemPrincipal: true + }); var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); httpChan.requestMethod = "GET"; return httpChan; @@ -45,7 +37,7 @@ function run_test() // load first time var channel = setupChannel("/redirect1"); - channel.asyncOpen(new ChannelListener(checkValueAndTrigger, null), null); + channel.asyncOpen2(new ChannelListener(checkValueAndTrigger, null)); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug596443.js b/netwerk/test/unit/test_bug596443.js index 731534066d9..e86bdf817b7 100644 --- a/netwerk/test/unit/test_bug596443.js +++ b/netwerk/test/unit/test_bug596443.js @@ -1,23 +1,15 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var expectedOnStopRequests = 3; function setupChannel(suffix, xRequest, flags) { - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + - suffix, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + suffix, + loadUsingSystemPrincipal: true + }); if (flags) chan.loadFlags |= flags; @@ -68,13 +60,13 @@ function run_test() { evict_cache_entries(); var ch0 = setupChannel("/bug596443", "Response0", Ci.nsIRequest.LOAD_BYPASS_CACHE); - ch0.asyncOpen(new Listener("Response0"), null); + ch0.asyncOpen2(new Listener("Response0")); var ch1 = setupChannel("/bug596443", "Response1", Ci.nsIRequest.LOAD_BYPASS_CACHE); - ch1.asyncOpen(new Listener("Response1"), null); + ch1.asyncOpen2(new Listener("Response1")); var ch2 = setupChannel("/bug596443", "Should not be used"); - ch2.asyncOpen(new Listener("Response1"), null); // Note param: we expect this to come from cache + ch2.asyncOpen2(new Listener("Response1")); // Note param: we expect this to come from cache do_test_pending(); } diff --git a/netwerk/test/unit/test_bug618835.js b/netwerk/test/unit/test_bug618835.js index 423858f7b2e..811608a6197 100644 --- a/netwerk/test/unit/test_bug618835.js +++ b/netwerk/test/unit/test_bug618835.js @@ -12,22 +12,13 @@ // Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserv; function setupChannel(path) { - var ios = - Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return chan = ios.newChannel2(path, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); + return NetUtil.newChannel({uri: path, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } // Verify that Content-Location-URI has been loaded once, load post_target @@ -40,7 +31,7 @@ InitialListener.prototype = { var channel = setupChannel("http://localhost:" + httpserv.identity.primaryPort + "/post"); channel.requestMethod = "POST"; - channel.asyncOpen(new RedirectingListener(), null); + channel.asyncOpen2(new RedirectingListener()); }); } }; @@ -55,7 +46,7 @@ RedirectingListener.prototype = { var channel = setupChannel("http://localhost:" + httpserv.identity.primaryPort + "/post"); channel.requestMethod = "POST"; - channel.asyncOpen(new VerifyingListener(), null); + channel.asyncOpen2(new VerifyingListener()); }); } }; @@ -69,7 +60,7 @@ VerifyingListener.prototype = { do_check_eq(2, numberOfHandlerCalls); var channel = setupChannel("http://localhost:" + httpserv.identity.primaryPort + "/cl"); - channel.asyncOpen(new FinalListener(), null); + channel.asyncOpen2(new FinalListener()); } }; @@ -97,7 +88,7 @@ function run_test() { // Load Content-Location URI into cache and start the chain of loads var channel = setupChannel("http://localhost:" + httpserv.identity.primaryPort + "/cl"); - channel.asyncOpen(new InitialListener(), null); + channel.asyncOpen2(new InitialListener()); do_test_pending(); } diff --git a/netwerk/test/unit/test_bug669001.js b/netwerk/test/unit/test_bug669001.js index a0a038d132f..bbb376f8f60 100644 --- a/netwerk/test/unit/test_bug669001.js +++ b/netwerk/test/unit/test_bug669001.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; var path = "/bug699001"; @@ -9,16 +9,7 @@ XPCOMUtils.defineLazyGetter(this, "URI", function() { }); function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } var fetched; @@ -117,7 +108,7 @@ function nextTest() // Give the old channel a chance to close the cache entry first. // XXX This is actually a race condition that might be considered a bug... do_execute_soon(function() { - chan.asyncOpen(new ChannelListener(checkAndShiftTest, null), null); + chan.asyncOpen2(new ChannelListener(checkAndShiftTest, null)); }); } diff --git a/netwerk/test/unit/test_bug770243.js b/netwerk/test/unit/test_bug770243.js index 389e8e5ce5b..8fd7abcea42 100644 --- a/netwerk/test/unit/test_bug770243.js +++ b/netwerk/test/unit/test_bug770243.js @@ -8,7 +8,7 @@ */ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserv; @@ -28,19 +28,10 @@ function clearCreds() } function makeChan() { - var ios = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserv.identity.primaryPort + "/", - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({ + uri: "http://localhost:" + httpserv.identity.primaryPort + "/", + loadUsingSystemPrincipal: true + }).QueryInterface(Ci.nsIHttpChannel); } // Array of handlers that are called one by one in response to expected requests @@ -148,46 +139,46 @@ var tests = [ // Test 1: 200 (cacheable) function() { var ch = makeChan(); - ch.asyncOpen(new ChannelListener(function(req, body) { + ch.asyncOpen2(new ChannelListener(function(req, body) { do_check_eq(body, "Response body 1"); sync_and_run_next_test(); - }, null, CL_NOT_FROM_CACHE), null); + }, null, CL_NOT_FROM_CACHE)); }, // Test 2: 401 and 200 + new content function() { var ch = makeChan(); - ch.asyncOpen(new ChannelListener(function(req, body) { + ch.asyncOpen2(new ChannelListener(function(req, body) { do_check_eq(body, "Response body 2"); sync_and_run_next_test(); - }, null, CL_NOT_FROM_CACHE), null); + }, null, CL_NOT_FROM_CACHE)); }, // Test 3: 401 and 304 function() { var ch = makeChan(); - ch.asyncOpen(new ChannelListener(function(req, body) { + ch.asyncOpen2(new ChannelListener(function(req, body) { do_check_eq(body, "Response body 2"); sync_and_run_next_test(); - }, null, CL_FROM_CACHE), null); + }, null, CL_FROM_CACHE)); }, // Test 4: 407 and 200 + new content function() { var ch = makeChan(); - ch.asyncOpen(new ChannelListener(function(req, body) { + ch.asyncOpen2(new ChannelListener(function(req, body) { do_check_eq(body, "Response body 3"); sync_and_run_next_test(); - }, null, CL_NOT_FROM_CACHE), null); + }, null, CL_NOT_FROM_CACHE)); }, // Test 5: 407 and 304 function() { var ch = makeChan(); - ch.asyncOpen(new ChannelListener(function(req, body) { + ch.asyncOpen2(new ChannelListener(function(req, body) { do_check_eq(body, "Response body 3"); sync_and_run_next_test(); - }, null, CL_FROM_CACHE), null); + }, null, CL_FROM_CACHE)); }, // End of test run diff --git a/netwerk/test/unit/test_bug856978.js b/netwerk/test/unit/test_bug856978.js index f8408a79e3b..9624ef64e15 100644 --- a/netwerk/test/unit/test_bug856978.js +++ b/netwerk/test/unit/test_bug856978.js @@ -10,7 +10,7 @@ // passes iff both succeeds. Components.utils.import("resource://testing-common/httpd.js"); -Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/NetUtil.jsm"); var notification = "http-on-modify-request"; @@ -97,16 +97,8 @@ var listener = { }; function makeChan(url) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER).QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } var tests = [startAuthHeaderTest, removeAuthHeaderTest]; @@ -125,7 +117,7 @@ function run_test() { function startAuthHeaderTest() { var chan = makeChan(authCredsURL); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } @@ -137,7 +129,7 @@ function removeAuthHeaderTest() { var chan = makeChan(authURL); // Indicating that the request is coming from the second test. chan.setRequestHeader("Test", "1", false); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } diff --git a/netwerk/test/unit/test_cacheForOfflineUse_no-store.js b/netwerk/test/unit/test_cacheForOfflineUse_no-store.js index e6a7884ca3a..8a49242eee9 100644 --- a/netwerk/test/unit/test_cacheForOfflineUse_no-store.js +++ b/netwerk/test/unit/test_cacheForOfflineUse_no-store.js @@ -2,7 +2,7 @@ // https://bugzilla.mozilla.org/show_bug.cgi?id=760955 Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; const testFileName = "test_nsHttpChannel_CacheForOfflineUse-no-store"; @@ -20,17 +20,8 @@ var cacheUpdateObserver = null; var appCache = null; function make_channel_for_offline_use(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - + var chan = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); + var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"]. getService(Components.interfaces.nsIApplicationCacheService); appCache = cacheService.getApplicationCache(cacheClientID); @@ -62,7 +53,7 @@ function checkNormal(request, buffer) } add_test(function test_normal() { var chan = make_channel_for_offline_use(baseURI + normalEntry); - chan.asyncOpen(new ChannelListener(checkNormal, chan), null); + chan.asyncOpen2(new ChannelListener(checkNormal, chan)); }); // An HTTP channel for updating the offline cache should fail when it gets a @@ -82,8 +73,7 @@ function checkNoStore(request, buffer) add_test(function test_noStore() { var chan = make_channel_for_offline_use(baseURI + noStoreEntry); // The no-store should cause the channel to fail to load. - chan.asyncOpen(new ChannelListener(checkNoStore, chan, CL_EXPECT_FAILURE), - null); + chan.asyncOpen2(new ChannelListener(checkNoStore, chan, CL_EXPECT_FAILURE)); }); function run_test() diff --git a/netwerk/test/unit/test_cache_jar.js b/netwerk/test/unit/test_cache_jar.js index e8fddfc4880..df16c8b2a46 100644 --- a/netwerk/test/unit/test_cache_jar.js +++ b/netwerk/test/unit/test_cache_jar.js @@ -1,5 +1,6 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { @@ -19,15 +20,8 @@ function cached_handler(metadata, response) { } function makeChan(url, appId, inBrowser) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER).QueryInterface(Ci.nsIHttpChannel); + var chan = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); chan.notificationCallbacks = { appId: appId, isInBrowserElement: inBrowser, @@ -53,7 +47,7 @@ function run_all_tests() { for (let test of firstTests) { handlers_called = 0; var chan = makeChan(URL, test[0], test[1]); - chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null); + chan.asyncOpen2(new ChannelListener(doneFirstLoad, test[2])); yield undefined; } @@ -71,7 +65,7 @@ function run_all_tests() { for (let test of secondTests) { handlers_called = 0; var chan = makeChan(URL, test[0], test[1]); - chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null); + chan.asyncOpen2(new ChannelListener(doneFirstLoad, test[2])); yield undefined; } @@ -81,7 +75,7 @@ function run_all_tests() { for (let test of thirdTests) { handlers_called = 0; var chan = makeChan(URL, test[0], test[1]); - chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null); + chan.asyncOpen2(new ChannelListener(doneFirstLoad, test[2])); yield undefined; } } @@ -105,7 +99,7 @@ function doneFirstLoad(req, buffer, expected) { // Load it again, make sure it hits the cache var nc = req.notificationCallbacks.getInterface(Ci.nsILoadContext); var chan = makeChan(URL, nc.appId, nc.isInBrowserElement); - chan.asyncOpen(new ChannelListener(doneSecondLoad, expected), null); + chan.asyncOpen2(new ChannelListener(doneSecondLoad, expected)); } function doneSecondLoad(req, buffer, expected) { diff --git a/netwerk/test/unit/test_cacheflags.js b/netwerk/test/unit/test_cacheflags.js index 84e9362a151..079c5484a66 100644 --- a/netwerk/test/unit/test_cacheflags.js +++ b/netwerk/test/unit/test_cacheflags.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); httpserver.start(-1); @@ -42,16 +42,7 @@ LoadContext.prototype = { PrivateBrowsingLoadContext = new LoadContext(true); function make_channel(url, flags, usePrivateBrowsing) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var req = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var req = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); req.loadFlags = flags; if (usePrivateBrowsing) { req.notificationCallbacks = PrivateBrowsingLoadContext; @@ -112,7 +103,7 @@ Test.prototype = { "\n " + this.hitServer + "\n"); gHitServer = false; var channel = make_channel(this.path, this.flags, this.usePrivateBrowsing); - channel.asyncOpen(this, null); + channel.asyncOpen2(this); } }; diff --git a/netwerk/test/unit/test_content_encoding_gzip.js b/netwerk/test/unit/test_content_encoding_gzip.js index e4fe346a7c1..165080b4348 100644 --- a/netwerk/test/unit/test_content_encoding_gzip.js +++ b/netwerk/test/unit/test_content_encoding_gzip.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var index = 0; @@ -52,18 +52,10 @@ var tests = [ ]; function setupChannel(url) { - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - return chan; + return NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + url, + loadUsingSystemPrincipal: true + }); } function startIter() { @@ -72,7 +64,7 @@ function startIter() { prefs.setCharPref("network.http.accept-encoding", "gzip, deflate"); } var channel = setupChannel(tests[index].url); - channel.asyncOpen(new ChannelListener(completeIter, channel, tests[index].flags), null); + channel.asyncOpen2(new ChannelListener(completeIter, channel, tests[index].flags)); } function completeIter(request, data, ctx) { diff --git a/netwerk/test/unit/test_content_sniffer.js b/netwerk/test/unit/test_content_sniffer.js index f87c402f517..c422e0497c6 100644 --- a/netwerk/test/unit/test_content_sniffer.js +++ b/netwerk/test/unit/test_content_sniffer.js @@ -1,7 +1,7 @@ // This file tests nsIContentSniffer, introduced in bug 324985 Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); const unknownType = "application/x-unknown-content-type"; const sniffedType = "application/x-sniffed"; @@ -71,16 +71,7 @@ var listener = { }; function makeChan(url) { - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true}); if (sniffing_enabled) chan.loadFlags |= Components.interfaces.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; @@ -133,7 +124,7 @@ function run_test_iteration(index) { var chan = makeChan(urls[index - 1]); listener._iteration++; - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } diff --git a/netwerk/test/unit/test_data_protocol.js b/netwerk/test/unit/test_data_protocol.js index a8bac95fcf2..5d92c2f9a83 100644 --- a/netwerk/test/unit/test_data_protocol.js +++ b/netwerk/test/unit/test_data_protocol.js @@ -1,5 +1,5 @@ /* run some tests on the data: protocol handler */ -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); // The behaviour wrt spaces is: // - Textual content keeps all spaces @@ -40,16 +40,12 @@ function run_test() { for (var i = 0; i < urls.length; ++i) { dump("*** opening channel " + i + "\n"); do_test_pending(); - var chan = ios.newChannel2(urls[i][0], - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: urls[i][0], + loadUsingSystemPrincipal: true + }); chan.contentType = "foo/bar"; // should be ignored - chan.asyncOpen(new ChannelListener(on_read_complete, i), null); + chan.asyncOpen2(new ChannelListener(on_read_complete, i)); } } diff --git a/netwerk/test/unit/test_duplicate_headers.js b/netwerk/test/unit/test_duplicate_headers.js index 0bf406e91c2..80c1708871e 100644 --- a/netwerk/test/unit/test_duplicate_headers.js +++ b/netwerk/test/unit/test_duplicate_headers.js @@ -7,7 +7,7 @@ // Test infrastructure Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpserver.identity.primaryPort; @@ -33,22 +33,16 @@ function run_test_number(num) var channel = setupChannel(testPath); flags = test_flags[num]; // OK if flags undefined for test - channel.asyncOpen(new ChannelListener(eval("completeTest" + num), - channel, flags), null); + channel.asyncOpen2(new ChannelListener(eval("completeTest" + num), + channel, flags)); } function setupChannel(url) { - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2(URL + url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: URL + url, + loadUsingSystemPrincipal: true + }); var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); return httpChan; } diff --git a/netwerk/test/unit/test_event_sink.js b/netwerk/test/unit/test_event_sink.js index 691dced70d6..45c01683a79 100644 --- a/netwerk/test/unit/test_event_sink.js +++ b/netwerk/test/unit/test_event_sink.js @@ -1,7 +1,7 @@ // This file tests channel event sinks (bug 315598 et al) Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpserv.identity.primaryPort; @@ -97,19 +97,7 @@ var listener = { }; function makeChan(url) { - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Components.interfaces.nsIHttpChannel); - - return chan; + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } var httpserv = null; @@ -127,7 +115,7 @@ function run_test() { var chan = makeChan(URL + "/redirect"); chan.notificationCallbacks = eventsink; - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } @@ -153,7 +141,7 @@ function run_test_continued() { } listener._iteration++; - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } diff --git a/netwerk/test/unit/test_fallback_no-cache-entry_canceled.js b/netwerk/test/unit/test_fallback_no-cache-entry_canceled.js index 20380d8f60f..5f06b296082 100644 --- a/netwerk/test/unit/test_fallback_no-cache-entry_canceled.js +++ b/netwerk/test/unit/test_fallback_no-cache-entry_canceled.js @@ -1,10 +1,11 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + var httpServer = null; // Need to randomize, because apparently no one clears our cache var randomPath = "/redirect/" + Math.random(); -var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); XPCOMUtils.defineLazyGetter(this, "randomURI", function() { return "http://localhost:" + httpServer.identity.primaryPort + randomPath; @@ -13,16 +14,7 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { var cacheUpdateObserver = null; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - systemPrincipal, - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function make_uri(url) { @@ -100,7 +92,7 @@ function run_test() chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT); var chanac = chan.QueryInterface(Ci.nsIApplicationCacheChannel); chanac.chooseApplicationCache = true; - chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE)); }} var os = Cc["@mozilla.org/observer-service;1"]. @@ -113,7 +105,7 @@ function run_test() httpServer.identity.primaryPort + "/manifest"), make_uri("http://localhost:" + httpServer.identity.primaryPort + "/masterEntry"), - systemPrincipal, + Services.scriptSecurityManager.getSystemPrincipal(), null); do_test_pending(); diff --git a/netwerk/test/unit/test_fallback_no-cache-entry_passing.js b/netwerk/test/unit/test_fallback_no-cache-entry_passing.js index 955967bf360..cd389421b88 100644 --- a/netwerk/test/unit/test_fallback_no-cache-entry_passing.js +++ b/netwerk/test/unit/test_fallback_no-cache-entry_passing.js @@ -1,5 +1,6 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; // Need to randomize, because apparently no one clears our cache @@ -10,19 +11,9 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); var cacheUpdateObserver = null; -var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - systemPrincipal, - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function make_uri(url) { @@ -99,7 +90,7 @@ function run_test() Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE); var chanac = chan.QueryInterface(Ci.nsIApplicationCacheChannel); chanac.chooseApplicationCache = true; - chan.asyncOpen(new ChannelListener(finish_test), null); + chan.asyncOpen2(new ChannelListener(finish_test)); }} var os = Cc["@mozilla.org/observer-service;1"]. @@ -112,7 +103,7 @@ function run_test() httpServer.identity.primaryPort + "/manifest"), make_uri("http://localhost:" + httpServer.identity.primaryPort + "/masterEntry"), - systemPrincipal, + Services.scriptSecurityManager.getSystemPrincipal(), null); do_test_pending(); diff --git a/netwerk/test/unit/test_fallback_redirect-to-different-origin_canceled.js b/netwerk/test/unit/test_fallback_redirect-to-different-origin_canceled.js index f1454d5a05e..eddfcbec0fe 100644 --- a/netwerk/test/unit/test_fallback_redirect-to-different-origin_canceled.js +++ b/netwerk/test/unit/test_fallback_redirect-to-different-origin_canceled.js @@ -1,5 +1,6 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; // Need to randomize, because apparently no one clears our cache @@ -10,19 +11,9 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); var cacheUpdateObserver = null; -var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - systemPrincipal, - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function make_uri(url) { @@ -104,7 +95,7 @@ function run_test() chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT); var chanac = chan.QueryInterface(Ci.nsIApplicationCacheChannel); chanac.chooseApplicationCache = true; - chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE)); }} var os = Cc["@mozilla.org/observer-service;1"]. @@ -117,7 +108,7 @@ function run_test() httpServer.identity.primaryPort + "/manifest"), make_uri("http://localhost:" + httpServer.identity.primaryPort + "/masterEntry"), - systemPrincipal, + Services.scriptSecurityManager.getSystemPrincipal(), null); do_test_pending(); diff --git a/netwerk/test/unit/test_fallback_redirect-to-different-origin_passing.js b/netwerk/test/unit/test_fallback_redirect-to-different-origin_passing.js index e720cacad12..a725161efcf 100644 --- a/netwerk/test/unit/test_fallback_redirect-to-different-origin_passing.js +++ b/netwerk/test/unit/test_fallback_redirect-to-different-origin_passing.js @@ -1,5 +1,6 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; // Need to randomize, because apparently no one clears our cache @@ -10,19 +11,9 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); var cacheUpdateObserver = null; -var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - systemPrincipal, - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function make_uri(url) { @@ -103,7 +94,7 @@ function run_test() var chan = make_channel(randomURI); var chanac = chan.QueryInterface(Ci.nsIApplicationCacheChannel); chanac.chooseApplicationCache = true; - chan.asyncOpen(new ChannelListener(finish_test), null); + chan.asyncOpen2(new ChannelListener(finish_test)); }} var os = Cc["@mozilla.org/observer-service;1"]. @@ -116,7 +107,7 @@ function run_test() httpServer.identity.primaryPort + "/manifest"), make_uri("http://localhost:" + httpServer.identity.primaryPort + "/masterEntry"), - systemPrincipal, + Services.scriptSecurityManager.getSystemPrincipal(), null); do_test_pending(); diff --git a/netwerk/test/unit/test_fallback_request-error_canceled.js b/netwerk/test/unit/test_fallback_request-error_canceled.js index 2f7c4029553..02129e6b4e1 100644 --- a/netwerk/test/unit/test_fallback_request-error_canceled.js +++ b/netwerk/test/unit/test_fallback_request-error_canceled.js @@ -1,5 +1,6 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; // Need to randomize, because apparently no one clears our cache @@ -10,19 +11,9 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); var cacheUpdateObserver = null; -var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - systemPrincipal, - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function make_uri(url) { @@ -108,7 +99,7 @@ function run_test() chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT); var chanac = chan.QueryInterface(Ci.nsIApplicationCacheChannel); chanac.chooseApplicationCache = true; - chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE)); }); }} @@ -123,7 +114,7 @@ function run_test() httpServer.identity.primaryPort + "/manifest"), make_uri("http://localhost:" + httpServer.identity.primaryPort + "/masterEntry"), - systemPrincipal, + Services.scriptSecurityManager.getSystemPrincipal(), null); do_test_pending(); diff --git a/netwerk/test/unit/test_gzipped_206.js b/netwerk/test/unit/test_gzipped_206.js index c541d0eb5ee..8e4eaa4c765 100644 --- a/netwerk/test/unit/test_gzipped_206.js +++ b/netwerk/test/unit/test_gzipped_206.js @@ -1,5 +1,7 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + var httpserver = null; @@ -10,16 +12,7 @@ const responseBody = [0x1f, 0x8b, 0x08, 0x08, 0xef, 0x70, 0xe6, 0x4c, 0x00, 0x03 0x92, 0xd4, 0xe2, 0x12, 0x2e, 0x2e, 0x00, 0x00, 0xe5, 0xe6, 0xf0, 0x20, 0x00, 0x00, 0x00]; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } var doRangeResponse = false; @@ -68,7 +61,7 @@ function continue_test(request, data) { do_check_eq(17, data.length); var chan = make_channel("http://localhost:" + httpserver.identity.primaryPort + "/cached/test.gz"); - chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_GZIP), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, CL_EXPECT_GZIP)); } var enforcePref; @@ -96,6 +89,6 @@ function run_test() { var chan = make_channel("http://localhost:" + httpserver.identity.primaryPort + "/cached/test.gz"); - chan.asyncOpen(new ChannelListener(continue_test, null, CL_EXPECT_GZIP | CL_IGNORE_CL), null); + chan.asyncOpen2(new ChannelListener(continue_test, null, CL_EXPECT_GZIP | CL_IGNORE_CL)); do_test_pending(); } diff --git a/netwerk/test/unit/test_httpResponseTimeout.js b/netwerk/test/unit/test_httpResponseTimeout.js index c676ac2f7ea..3a40b0a0899 100644 --- a/netwerk/test/unit/test_httpResponseTimeout.js +++ b/netwerk/test/unit/test_httpResponseTimeout.js @@ -7,7 +7,7 @@ "use strict"; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var baseURL; const kResponseTimeoutPref = "network.http.response.timeout"; @@ -56,19 +56,10 @@ function testTimeout(timeoutEnabled, expectResponse) { prefService.setIntPref(kResponseTimeoutPref, 0); } - var ios = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService); - var chan = ios.newChannel2(baseURL, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); + var chan = NetUtil.newChannel({uri: baseURL, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); var listener = new TimeoutListener(expectResponse); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function testTimeoutEnabled() { diff --git a/netwerk/test/unit/test_httpcancel.js b/netwerk/test/unit/test_httpcancel.js index 5aed9001735..49188ca1ee2 100644 --- a/netwerk/test/unit/test_httpcancel.js +++ b/netwerk/test/unit/test_httpcancel.js @@ -5,7 +5,7 @@ // expected: see comments that start with ENSURE_CALLED_BEFORE_CONNECT: Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var ios = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); @@ -73,15 +73,8 @@ var listener = { }; function makeChan(url) { - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Components.interfaces.nsIHttpChannel); + var chan = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Components.interfaces.nsIHttpChannel); // ENSURE_CALLED_BEFORE_CONNECT: set original value var uri = ios.newURI("http://site1.com", null, null); @@ -100,7 +93,7 @@ function execute_test() { obs = obs.QueryInterface(Components.interfaces.nsIObserverService); obs.addObserver(observer, "http-on-modify-request", false); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function run_test() { diff --git a/netwerk/test/unit/test_mismatch_last-modified.js b/netwerk/test/unit/test_mismatch_last-modified.js index 6c3489a3513..f675a123fbb 100644 --- a/netwerk/test/unit/test_mismatch_last-modified.js +++ b/netwerk/test/unit/test_mismatch_last-modified.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var ios; @@ -69,18 +69,11 @@ XPCOMUtils.defineLazyGetter(this, "listener_2", function() { onStopRequest: function test_onStopR(request, ctx, status) { var channel = request.QueryInterface(Ci.nsIHttpChannel); - - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + - "/test1", - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - chan.asyncOpen(listener_3, null); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + "/test1", + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(listener_3); } }; }); @@ -107,19 +100,12 @@ XPCOMUtils.defineLazyGetter(this, "listener_1", function() { }, onStopRequest: function test_onStopR(request, ctx, status) { - var channel = request.QueryInterface(Ci.nsIHttpChannel); - - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + - "/test1", - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - chan.asyncOpen(listener_2, null); + var channel = request.QueryInterface(Ci.nsIHttpChannel); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + "/test1", + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(listener_2); } }; }); @@ -135,16 +121,11 @@ function run_test() { httpserver.start(-1); var port = httpserver.identity.primaryPort; - - var chan = ios.newChannel2("http://localhost:" + port + "/test1", - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - chan.asyncOpen(listener_1, null); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + port + "/test1", + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(listener_1); do_test_pending(); } diff --git a/netwerk/test/unit/test_multipart_byteranges.js b/netwerk/test/unit/test_multipart_byteranges.js index 0a6ee48d93f..367615fff9f 100644 --- a/netwerk/test/unit/test_multipart_byteranges.js +++ b/netwerk/test/unit/test_multipart_byteranges.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = null; @@ -8,16 +8,7 @@ XPCOMUtils.defineLazyGetter(this, "uri", function() { }); function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } var multipartBody = "--boundary\r\n"+ @@ -39,19 +30,6 @@ var multipartBody = "--boundary\r\n"+ "\r\n"+ "--boundary--"; -function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); -} - function contentHandler(metadata, response) { response.setHeader("Content-Type", 'multipart/byteranges; boundary="boundary"'); @@ -130,6 +108,6 @@ function run_test() null); var chan = make_channel(uri); - chan.asyncOpen(conv, null); + chan.asyncOpen2(conv, null); do_test_pending(); } diff --git a/netwerk/test/unit/test_multipart_streamconv.js b/netwerk/test/unit/test_multipart_streamconv.js index 119207b5bda..c35628faa4b 100644 --- a/netwerk/test/unit/test_multipart_streamconv.js +++ b/netwerk/test/unit/test_multipart_streamconv.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = null; @@ -8,33 +8,11 @@ XPCOMUtils.defineLazyGetter(this, "uri", function() { }); function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } var multipartBody = "--boundary\r\n\r\nSome text\r\n--boundary\r\n\r\n\r\n--boundary--"; -function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); -} - function contentHandler(metadata, response) { response.setHeader("Content-Type", 'multipart/mixed; boundary="boundary"'); @@ -110,6 +88,6 @@ function run_test() null); var chan = make_channel(uri); - chan.asyncOpen(conv, null); + chan.asyncOpen2(conv); do_test_pending(); } diff --git a/netwerk/test/unit/test_nojsredir.js b/netwerk/test/unit/test_nojsredir.js index 5a15835ad5a..d61c41a1838 100644 --- a/netwerk/test/unit/test_nojsredir.js +++ b/netwerk/test/unit/test_nojsredir.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var index = 0; @@ -16,23 +16,15 @@ var tests = [ ]; function setupChannel(url) { - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - return chan; + return NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + url, + loadUsingSystemPrincipal: true + }); } function startIter() { var channel = setupChannel(tests[index].url); - channel.asyncOpen(new ChannelListener(completeIter, channel, tests[index].flags), null); + channel.asyncOpen2(new ChannelListener(completeIter, channel, tests[index].flags)); } function completeIter(request, data, ctx) { diff --git a/netwerk/test/unit/test_packaged_app_channel.js b/netwerk/test/unit/test_packaged_app_channel.js index bc399f9de76..b7740db826b 100644 --- a/netwerk/test/unit/test_packaged_app_channel.js +++ b/netwerk/test/unit/test_packaged_app_channel.js @@ -6,6 +6,8 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + XPCOMUtils.defineLazyGetter(this, "uri", function() { return "http://localhost:" + httpserver.identity.primaryPort; @@ -18,16 +20,7 @@ const nsIBinaryInputStream = Components.Constructor("@mozilla.org/binaryinputstr function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function Listener(callback) { @@ -231,10 +224,10 @@ function run_test() function test_channel_with_bad_signature() { var channel = make_channel(uri+"/package_with_bad_signature!//index.html"); channel.notificationCallbacks = new LoadContextCallback(1024, false, false, false); - channel.asyncOpen(new Listener(function(l) { + channel.asyncOpen2(new Listener(function(l) { do_check_true(l.gotFileNotFound); run_next_test(); - }), null); + })); } function test_channel_with_bad_signature_from_trusted_origin() { @@ -245,20 +238,20 @@ function test_channel_with_bad_signature_from_trusted_origin() { Services.prefs.setComplexValue(pref, Ci.nsISupportsString, origin); var channel = make_channel(uri+"/package_with_bad_signature!//index.html"); channel.notificationCallbacks = new LoadContextCallback(1024, false, false, false); - channel.asyncOpen(new Listener(function(l) { + channel.asyncOpen2(new Listener(function(l) { do_check_true(l.gotStopRequestOK); Services.prefs.clearUserPref(pref); run_next_test(); - }), null); + })); } function test_channel_with_good_signature() { var channel = make_channel(uri+"/package_with_good_signature!//index.html"); channel.notificationCallbacks = new LoadContextCallback(1024, false, false, false); - channel.asyncOpen(new Listener(function(l) { + channel.asyncOpen2(new Listener(function(l) { do_check_true(l.gotStopRequestOK); run_next_test(); - }), null); + })); } function test_channel(aNullNotificationCallbacks) { @@ -268,13 +261,13 @@ function test_channel(aNullNotificationCallbacks) { channel.notificationCallbacks = new LoadContextCallback(1024, false, false, false); } - channel.asyncOpen(new Listener(function(l) { + channel.asyncOpen2(new Listener(function(l) { // XXX: no content length available for this resource //do_check_true(channel.contentLength > 0); do_check_true(l.gotStartRequest); do_check_true(l.gotStopRequestOK); run_next_test(); - }), null); + })); } function test_channel_no_notificationCallbacks() { @@ -284,7 +277,7 @@ function test_channel_no_notificationCallbacks() { function test_channel_uris() { // A `!//` in the query or ref should not be handled as a packaged app resource var channel = make_channel(uri+"/regular?bla!//bla#bla!//bla"); - channel.asyncOpen(new ChannelListener(check_regular_response, null), null); + channel.asyncOpen2(new ChannelListener(check_regular_response, null)); } function check_regular_response(request, buffer) { diff --git a/netwerk/test/unit/test_partial_response_entry_size_smart_shrink.js b/netwerk/test/unit/test_partial_response_entry_size_smart_shrink.js index ff4335a9c0f..fed8094834a 100644 --- a/netwerk/test/unit/test_partial_response_entry_size_smart_shrink.js +++ b/netwerk/test/unit/test_partial_response_entry_size_smart_shrink.js @@ -9,6 +9,7 @@ Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -17,16 +18,7 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() { var httpServer = null; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } // Have 2kb response (8 * 2 ^ 8) @@ -71,7 +63,7 @@ function run_test() httpServer.start(-1); var chan = make_channel(URL + "/content"); - chan.asyncOpen(new ChannelListener(firstTimeThrough, null, CL_IGNORE_CL), null); + chan.asyncOpen2(new ChannelListener(firstTimeThrough, null, CL_IGNORE_CL)); do_test_pending(); } @@ -81,7 +73,7 @@ function firstTimeThrough(request, buffer) Services.prefs.setIntPref("browser.cache.disk.max_entry_size", 1); var chan = make_channel(URL + "/content"); - chan.asyncOpen(new ChannelListener(finish_test, null), null); + chan.asyncOpen2(new ChannelListener(finish_test, null)); } function finish_test(request, buffer) diff --git a/netwerk/test/unit/test_plaintext_sniff.js b/netwerk/test/unit/test_plaintext_sniff.js index 2fc572343f5..9955a86b9e0 100644 --- a/netwerk/test/unit/test_plaintext_sniff.js +++ b/netwerk/test/unit/test_plaintext_sniff.js @@ -1,6 +1,7 @@ // Test the plaintext-or-binary sniffer Cu.import("resource://testing-common/httpd.js"); +Cu.import("resource://gre/modules/NetUtil.jsm"); // List of Content-Type headers to test. For each header we have an array. // The first element in the array is the Content-Type header string. The @@ -73,19 +74,11 @@ for (i = 0; i <= 127; ++i) { } function makeChan(headerIdx, bodyIdx) { - var ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var chan = - ios.newChannel2("http://localhost:" + httpserv.identity.primaryPort + - "/" + headerIdx + "/" + bodyIdx, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Components.interfaces.nsIHttpChannel); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserv.identity.primaryPort + + "/" + headerIdx + "/" + bodyIdx, + loadUsingSystemPrincipal: true + }).QueryInterface(Components.interfaces.nsIHttpChannel); chan.loadFlags |= Components.interfaces.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; @@ -156,7 +149,7 @@ function doTest(headerIdx, bodyIdx) { var listener = makeListener(headerIdx, bodyIdx); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); do_test_pending(); } diff --git a/netwerk/test/unit/test_post.js b/netwerk/test/unit/test_post.js index 687a2ea7b50..934719e7dfb 100644 --- a/netwerk/test/unit/test_post.js +++ b/netwerk/test/unit/test_post.js @@ -3,7 +3,7 @@ // Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpserver.identity.primaryPort; @@ -89,21 +89,13 @@ function run_test() { .setUploadStream(mime, "", mime.available()); channel.requestMethod = "POST"; channel.notificationCallbacks = listenerCallback; - channel.asyncOpen(new ChannelListener(checkRequest, channel), null); + channel.asyncOpen2(new ChannelListener(checkRequest, channel)); do_test_pending(); } function setupChannel(path) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return chan = ios.newChannel2(URL + path, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); + return NetUtil.newChannel({uri: URL + path, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } function serverHandler(metadata, response) { diff --git a/netwerk/test/unit/test_private_necko_channel.js b/netwerk/test/unit/test_private_necko_channel.js index 88da76a0165..530d4e7e660 100644 --- a/netwerk/test/unit/test_private_necko_channel.js +++ b/netwerk/test/unit/test_private_necko_channel.js @@ -3,7 +3,7 @@ // Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var testpath = "/simple"; @@ -25,23 +25,16 @@ function run_test() { channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); channel.setPrivate(true); - channel.asyncOpen(new ChannelListener(checkRequest, channel), null); + channel.asyncOpen2(new ChannelListener(checkRequest, channel)); do_test_pending(); } function setupChannel(path) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + path, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Ci.nsIHttpChannel); + return NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + path, + loadUsingSystemPrincipal: true + }).QueryInterface(Ci.nsIHttpChannel); } function serverHandler(metadata, response) { diff --git a/netwerk/test/unit/test_progress.js b/netwerk/test/unit/test_progress.js index 97a7b2e7317..e2dae9c09b8 100644 --- a/netwerk/test/unit/test_progress.js +++ b/netwerk/test/unit/test_progress.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpserver.identity.primaryPort; @@ -100,21 +100,15 @@ function run_test() { httpserver.registerPathHandler(testpath, serverHandler); httpserver.start(-1); var channel = setupChannel(testpath); - channel.asyncOpen(progressCallback, null); + channel.asyncOpen2(progressCallback); do_test_pending(); } function setupChannel(path) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2(URL + path, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: URL + path, + loadUsingSystemPrincipal: true + }); chan.QueryInterface(Ci.nsIHttpChannel); chan.requestMethod = "GET"; chan.notificationCallbacks = progressCallback; diff --git a/netwerk/test/unit/test_proxy-failover_passing.js b/netwerk/test/unit/test_proxy-failover_passing.js index 1eb41f51d29..b2bf198dd78 100644 --- a/netwerk/test/unit/test_proxy-failover_passing.js +++ b/netwerk/test/unit/test_proxy-failover_passing.js @@ -1,19 +1,10 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpServer = null; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const responseBody = "response body"; @@ -47,6 +38,6 @@ function run_test() var chan = make_channel("http://localhost:" + httpServer.identity.primaryPort + "/content"); - chan.asyncOpen(new ChannelListener(finish_test, null), null); + chan.asyncOpen2(new ChannelListener(finish_test, null)); do_test_pending(); } diff --git a/netwerk/test/unit/test_redirect-caching_canceled.js b/netwerk/test/unit/test_redirect-caching_canceled.js index 668bc28bc96..23710786543 100644 --- a/netwerk/test/unit/test_redirect-caching_canceled.js +++ b/netwerk/test/unit/test_redirect-caching_canceled.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -14,16 +14,7 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const responseBody = "response body"; @@ -46,7 +37,7 @@ function firstTimeThrough(request, buffer) { do_check_eq(buffer, responseBody); var chan = make_channel(randomURI); - chan.asyncOpen(new ChannelListener(secondTimeThrough, null), null); + chan.asyncOpen2(new ChannelListener(secondTimeThrough, null)); } function secondTimeThrough(request, buffer) @@ -55,7 +46,7 @@ function secondTimeThrough(request, buffer) var chan = make_channel(randomURI); chan.loadFlags |= Ci.nsIRequest.LOAD_FROM_CACHE; chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT); - chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE)); } function finish_test(request, buffer) @@ -72,6 +63,6 @@ function run_test() httpServer.start(-1); var chan = make_channel(randomURI); - chan.asyncOpen(new ChannelListener(firstTimeThrough, null), null); + chan.asyncOpen2(new ChannelListener(firstTimeThrough, null)); do_test_pending(); } diff --git a/netwerk/test/unit/test_redirect_different-protocol.js b/netwerk/test/unit/test_redirect_different-protocol.js index 89114d686c0..73aea57ca12 100644 --- a/netwerk/test/unit/test_redirect_different-protocol.js +++ b/netwerk/test/unit/test_redirect_different-protocol.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -20,16 +20,7 @@ function inChildProcess() { } function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const redirectTargetBody = "response body"; @@ -55,6 +46,6 @@ function run_test() httpServer.start(-1); var chan = make_channel(randomURI); - chan.asyncOpen(new ChannelListener(finish_test, null, 0), null); + chan.asyncOpen2(new ChannelListener(finish_test, null, 0)); do_test_pending(); } diff --git a/netwerk/test/unit/test_redirect_history.js b/netwerk/test/unit/test_redirect_history.js index d56691cec84..07da064787a 100644 --- a/netwerk/test/unit/test_redirect_history.js +++ b/netwerk/test/unit/test_redirect_history.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -11,16 +11,7 @@ var redirects = []; const numRedirects = 10; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const responseBody = "response body"; @@ -68,6 +59,6 @@ function run_test() httpServer.start(-1); var chan = make_channel(URL + redirects[0]); - chan.asyncOpen(new ChannelListener(finish_test, null), null); + chan.asyncOpen2(new ChannelListener(finish_test, null)); do_test_pending(); } diff --git a/netwerk/test/unit/test_redirect_loop.js b/netwerk/test/unit/test_redirect_loop.js index e0ffbbd511a..9efcecadb8c 100644 --- a/netwerk/test/unit/test_redirect_loop.js +++ b/netwerk/test/unit/test_redirect_loop.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); /* * This xpcshell test checks whether we detect infinite HTTP redirect loops. @@ -23,16 +23,7 @@ var emptyLoopPath = "/empty/"; var emptyLoopURI = "http://localhost:" + PORT + emptyLoopPath; function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } function fullLoopHandler(metadata, response) @@ -65,8 +56,7 @@ function testFullLoop(request, buffer) do_check_eq(request.status, Components.results.NS_ERROR_REDIRECT_LOOP); var chan = make_channel(relativeLoopURI); - chan.asyncOpen(new ChannelListener(testRelativeLoop, null, CL_EXPECT_FAILURE), - null); + chan.asyncOpen2(new ChannelListener(testRelativeLoop, null, CL_EXPECT_FAILURE)); } function testRelativeLoop(request, buffer) @@ -74,8 +64,7 @@ function testRelativeLoop(request, buffer) do_check_eq(request.status, Components.results.NS_ERROR_REDIRECT_LOOP); var chan = make_channel(emptyLoopURI); - chan.asyncOpen(new ChannelListener(testEmptyLoop, null, CL_EXPECT_FAILURE), - null); + chan.asyncOpen2(new ChannelListener(testEmptyLoop, null, CL_EXPECT_FAILURE)); } function testEmptyLoop(request, buffer) @@ -92,7 +81,6 @@ function run_test() httpServer.registerPathHandler(emptyLoopPath, emptyLoopHandler); var chan = make_channel(fullLoopURI); - chan.asyncOpen(new ChannelListener(testFullLoop, null, CL_EXPECT_FAILURE), - null); + chan.asyncOpen2(new ChannelListener(testFullLoop, null, CL_EXPECT_FAILURE)); do_test_pending(); } diff --git a/netwerk/test/unit/test_redirect_passing.js b/netwerk/test/unit/test_redirect_passing.js index 7f38a161cb7..a9a515b5eb9 100644 --- a/netwerk/test/unit/test_redirect_passing.js +++ b/netwerk/test/unit/test_redirect_passing.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpServer.identity.primaryPort; @@ -14,16 +14,7 @@ XPCOMUtils.defineLazyGetter(this, "randomURI", function() { }); function make_channel(url, callback, ctx) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); } const responseBody = "response body"; @@ -44,7 +35,7 @@ function firstTimeThrough(request, buffer) { do_check_eq(buffer, responseBody); var chan = make_channel(randomURI); - chan.asyncOpen(new ChannelListener(finish_test, null), null); + chan.asyncOpen2(new ChannelListener(finish_test, null)); } function finish_test(request, buffer) @@ -61,6 +52,6 @@ function run_test() httpServer.start(-1); var chan = make_channel(randomURI); - chan.asyncOpen(new ChannelListener(firstTimeThrough, null), null); + chan.asyncOpen2(new ChannelListener(firstTimeThrough, null)); do_test_pending(); } diff --git a/netwerk/test/unit/test_reentrancy.js b/netwerk/test/unit/test_reentrancy.js index b7b1ecb69b0..2f8eec30f5b 100644 --- a/netwerk/test/unit/test_reentrancy.js +++ b/netwerk/test/unit/test_reentrancy.js @@ -1,5 +1,5 @@ Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyGetter(this, "URL", function() { return "http://localhost:" + httpserver.identity.primaryPort; @@ -77,23 +77,15 @@ var listener = { }; function makeChan(url) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - var chan = ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER).QueryInterface(Ci.nsIHttpChannel); - return chan; + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Ci.nsIHttpChannel); } function next_test() { var chan = makeChan(URL + testpath); chan.QueryInterface(Ci.nsIRequest); - chan.asyncOpen(listener, null); + chan.asyncOpen2(listener); } function run_test() diff --git a/netwerk/test/unit/test_reply_without_content_type.js b/netwerk/test/unit/test_reply_without_content_type.js index 09c88db2286..7fda87209c9 100644 --- a/netwerk/test/unit/test_reply_without_content_type.js +++ b/netwerk/test/unit/test_reply_without_content_type.js @@ -5,7 +5,7 @@ // Note: sets Cc and Ci variables Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); var testpath = "/simple_plainText"; @@ -29,7 +29,7 @@ add_test(function test_plainText() { httpserver.start(-1); var channel = setupChannel(testpath); // ChannelListener defined in head_channels.js - channel.asyncOpen(new ChannelListener(checkRequest, channel), null); + channel.asyncOpen2(new ChannelListener(checkRequest, channel)); do_test_pending(); if (dbg) { print("============== test_plainText: out"); } }); @@ -40,25 +40,18 @@ add_test(function test_GZip() { httpserver.start(-1); var channel = setupChannel(testpathGZip); // ChannelListener defined in head_channels.js - channel.asyncOpen(new ChannelListener(checkRequest, channel, - CL_EXPECT_GZIP), null); + channel.asyncOpen2(new ChannelListener(checkRequest, channel, + CL_EXPECT_GZIP)); do_test_pending(); if (dbg) { print("============== test_GZip: out"); } }); function setupChannel(path) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var chan = ios.newChannel2("http://localhost:" + - httpserver.identity.primaryPort + path, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); + var chan = NetUtil.newChannel({ + uri: "http://localhost:" + httpserver.identity.primaryPort + path, + loadUsingSystemPrincipal: true + }); chan.QueryInterface(Ci.nsIHttpChannel); chan.requestMethod = "GET"; return chan; diff --git a/netwerk/test/unit/test_suspend_channel_before_connect.js b/netwerk/test/unit/test_suspend_channel_before_connect.js index 9d519d49aa3..f41932a4670 100644 --- a/netwerk/test/unit/test_suspend_channel_before_connect.js +++ b/netwerk/test/unit/test_suspend_channel_before_connect.js @@ -1,7 +1,7 @@ var CC = Components.Constructor; -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); const ServerSocket = CC("@mozilla.org/network/server-socket;1", "nsIServerSocket", @@ -88,17 +88,11 @@ add_test(function testNoConnectChannelCanceledEarly() { serv = new TestServer(); obs.addObserver(requestListenerObserver, "http-on-modify-request", false); - - var chan = ios.newChannel2("http://localhost:" + serv.port, - "", - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER); - - chan.asyncOpen(listener, chan); + var chan = NetUtil.newChannel({ + uri:"http://localhost:" + serv.port, + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(listener); do_register_cleanup(function(){ serv.stop(); }); }); diff --git a/netwerk/test/unit/test_traceable_channel.js b/netwerk/test/unit/test_traceable_channel.js index b9bf1fb022e..00ccbb12775 100644 --- a/netwerk/test/unit/test_traceable_channel.js +++ b/netwerk/test/unit/test_traceable_channel.js @@ -4,7 +4,7 @@ // is correctly modified. Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); var httpserver = new HttpServer(); httpserver.start(-1); @@ -129,17 +129,8 @@ function test_handler(metadata, response) { } function make_channel(url) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ios.newChannel2(url, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) - .QueryInterface(Components.interfaces.nsIHttpChannel); + return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}) + .QueryInterface(Components.interfaces.nsIHttpChannel); } // Check if received body is correctly modified. @@ -154,6 +145,6 @@ function run_test() { httpserver.registerPathHandler("/testdir", test_handler); var channel = make_channel("http://localhost:" + PORT + "/testdir"); - channel.asyncOpen(new ChannelListener(channel_finished), null); + channel.asyncOpen2(new ChannelListener(channel_finished)); do_test_pending(); } diff --git a/python/mozbuild/mozbuild/mozinfo.py b/python/mozbuild/mozbuild/mozinfo.py index 09a87c39fa3..1a6ee3b1819 100755 --- a/python/mozbuild/mozbuild/mozinfo.py +++ b/python/mozbuild/mozbuild/mozinfo.py @@ -92,10 +92,6 @@ def build_dict(config, env=os.environ): d['tests_enabled'] = substs.get('ENABLE_TESTS') == "1" d['bin_suffix'] = substs.get('BIN_SUFFIX', '') d['addon_signing'] = substs.get('MOZ_ADDON_SIGNING') == '1' - - d['webm'] = bool(substs.get('MOZ_WEBM')) - d['wave'] = bool(substs.get('MOZ_WAVE')) - d['official'] = bool(substs.get('MOZILLA_OFFICIAL')) def guess_platform(): diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js index bf144cc3840..5ff7ca9d0b5 100644 --- a/security/manager/tools/genHPKPStaticPins.js +++ b/security/manager/tools/genHPKPStaticPins.js @@ -10,6 +10,7 @@ // [absolute path to]/PreloadedHPKPins.json \ // [an unused argument - see bug 1205406] \ // [absolute path to]/StaticHPKPins.h +"use strict"; if (arguments.length != 3) { throw "Usage: genHPKPStaticPins.js " + @@ -28,7 +29,6 @@ var gCertDB = Cc["@mozilla.org/security/x509certdb;1"] .getService(Ci.nsIX509CertDB); const BUILT_IN_NICK_PREFIX = "Builtin Object Token:"; -const SHA1_PREFIX = "sha1/"; const SHA256_PREFIX = "sha256/"; const GOOGLE_PIN_PREFIX = "GOOGLE_PIN_"; @@ -53,7 +53,7 @@ const DOMAINHEADER = "/* Domainlist */\n" + " const bool mTestMode;\n" + " const bool mIsMoz;\n" + " const int32_t mId;\n" + - " const StaticPinset *pinset;\n" + + " const StaticPinset* pinset;\n" + "};\n\n"; const PINSETDEF = "/* Pinsets are each an ordered list by the actual value of the fingerprint */\n" + @@ -164,13 +164,13 @@ function getSKDFromPem(pem) { } /** - * Hashes |input| using the SHA1 algorithm in the following manner: - * btoa(sha1(atob(input))) + * Hashes |input| using the SHA-256 algorithm in the following manner: + * btoa(sha256(atob(input))) * * @argument {String} input Base64 string to decode and return the hash of. - * @returns {String} Base64 encoded SHA1 hash. + * @returns {String} Base64 encoded SHA-256 hash. */ -function sha1Base64(input) { +function sha256Base64(input) { let decodedValue; try { decodedValue = atob(input); @@ -191,7 +191,7 @@ function sha1Base64(input) { let hasher = Cc["@mozilla.org/security/hash;1"] .createInstance(Ci.nsICryptoHash); - hasher.init(hasher.SHA1); + hasher.init(hasher.SHA256); hasher.update(data, data.length); // true is passed so that the hasher returns a Base64 encoded string. @@ -201,11 +201,11 @@ function sha1Base64(input) { // Downloads the static certs file and tries to map Google Chrome nicknames // to Mozilla nicknames, as well as storing any hashes for pins for which we // don't have root PEMs. Each entry consists of a line containing the name of -// the pin followed either by a hash in the format "sha1/" + base64(hash), a -// hash in the format "sha256/" + base64(hash), a PEM encoded public key, or -// a PEM encoded certificate. For certificates that we have in our database, +// the pin followed either by a hash in the format "sha256/" + base64(hash), +// a PEM encoded public key, or a PEM encoded certificate. +// For certificates that we have in our database, // return a map of Google's nickname to ours. For ones that aren't return a -// map of Google's nickname to sha1 values. This code is modeled after agl's +// map of Google's nickname to SHA-256 values. This code is modeled after agl's // https://github.com/agl/transport-security-state-generate, which doesn't // live in the Chromium repo because go is not an official language in // Chromium. @@ -216,7 +216,7 @@ function sha1Base64(input) { // and stick the hash in certSKDToName // We MUST be able to find a corresponding cert nickname for the Chrome names, // otherwise we skip all pinsets referring to that Chrome name. -function downloadAndParseChromeCerts(filename, certSKDToName) { +function downloadAndParseChromeCerts(filename, certNameToSKD, certSKDToName) { // Prefixes that we care about. const BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; const END_CERT = "-----END CERTIFICATE-----"; @@ -238,8 +238,7 @@ function downloadAndParseChromeCerts(filename, certSKDToName) { let chromeNameToHash = {}; let chromeNameToMozName = {}; let chromeName; - for (let i = 0; i < lines.length; ++i) { - let line = lines[i]; + for (let line of lines) { // Skip comments and newlines. if (line.length == 0 || line[0] == '#') { continue; @@ -250,18 +249,9 @@ function downloadAndParseChromeCerts(filename, certSKDToName) { state = POST_NAME; break; case POST_NAME: - // TODO(bug 1229284): Chromium no longer uses SHA1 hashes, so remove - // code like this supporting SHA1. - if (line.startsWith(SHA1_PREFIX) || - line.startsWith(SHA256_PREFIX)) { - if (line.startsWith(SHA1_PREFIX)) { - hash = line.substring(SHA1_PREFIX.length); - } else if (line.startsWith(SHA256_PREFIX)) { - hash = line.substring(SHA256_PREFIX.length); - } - // Store the entire prefixed hash, so we can disambiguate sha1 from - // sha256 later. - chromeNameToHash[chromeName] = line; + if (line.startsWith(SHA256_PREFIX)) { + hash = line.substring(SHA256_PREFIX.length); + chromeNameToHash[chromeName] = hash; certNameToSKD[chromeName] = hash; certSKDToName[hash] = chromeName; state = PRE_NAME; @@ -298,12 +288,9 @@ function downloadAndParseChromeCerts(filename, certSKDToName) { case IN_PUB_KEY: if (line.startsWith(END_PUB_KEY)) { state = PRE_NAME; - // TODO(bug 1229284): Switch to SHA-256 instead. SHA1 is used here - // mainly to confirm that the changes made to support public keys are - // correct and don't change any hashes. - hash = sha1Base64(pemPubKey); + hash = sha256Base64(pemPubKey); pemPubKey = ""; - chromeNameToHash[chromeName] = SHA1_PREFIX + hash; + chromeNameToHash[chromeName] = hash; certNameToSKD[chromeName] = hash; certSKDToName[hash] = chromeName; } else { @@ -325,7 +312,6 @@ function downloadAndParseChromeCerts(filename, certSKDToName) { // { // pinset_name : { // // Array of names with entries in certNameToSKD -// sha1_hashes: [], // sha256_hashes: [] // } // } @@ -344,20 +330,13 @@ function downloadAndParseChromePins(filename, chromePins.forEach(function(pin) { let valid = true; - let pinset = { name: pin.name, sha1_hashes: [], sha256_hashes: [] }; + let pinset = { name: pin.name, sha256_hashes: [] }; // Translate the Chrome pinset format to ours pin.static_spki_hashes.forEach(function(name) { if (name in chromeNameToHash) { let hash = chromeNameToHash[name]; - if (hash.startsWith(SHA1_PREFIX)) { - hash = hash.substring(SHA1_PREFIX.length); - pinset.sha1_hashes.push(certSKDToName[hash]); - } else if (hash.startsWith(SHA256_PREFIX)) { - hash = hash.substring(SHA256_PREFIX.length); - pinset.sha256_hashes.push(certSKDToName[hash]); - } else { - throw("Unsupported hash type: " + chromeNameToHash[name]); - } + pinset.sha256_hashes.push(certSKDToName[hash]); + // We should have already added hashes for all of these when we // imported the certificate file. if (!certNameToSKD[name]) { @@ -473,26 +452,18 @@ function genExpirationTime() { } function writeFullPinset(certNameToSKD, certSKDToName, pinset) { - // We aren't guaranteed to have sha1 hashes in our own imported pins. let prefix = "kPinset_" + pinset.name; - let sha1Name = "nullptr"; - let sha256Name = "nullptr"; - if (pinset.sha1_hashes && pinset.sha1_hashes.length > 0) { - writeFingerprints(certNameToSKD, certSKDToName, pinset.name, - pinset.sha1_hashes, "sha1"); - sha1Name = "&" + prefix + "_sha1"; - } - if (pinset.sha256_hashes && pinset.sha256_hashes.length > 0) { - writeFingerprints(certNameToSKD, certSKDToName, pinset.name, - pinset.sha256_hashes, "sha256"); - sha256Name = "&" + prefix + "_sha256"; + if (!pinset.sha256_hashes || pinset.sha256_hashes.length == 0) { + throw `ERROR: Pinset ${pinset.name} does not contain any hashes.`; } + writeFingerprints(certNameToSKD, certSKDToName, pinset.name, + pinset.sha256_hashes); writeString("static const StaticPinset " + prefix + " = {\n" + - " " + sha1Name + ",\n " + sha256Name + "\n};\n\n"); + " nullptr,\n &" + prefix + "_sha256\n};\n\n"); } -function writeFingerprints(certNameToSKD, certSKDToName, name, hashes, type) { - let varPrefix = "kPinset_" + name + "_" + type; +function writeFingerprints(certNameToSKD, certSKDToName, name, hashes) { + let varPrefix = "kPinset_" + name + "_sha256"; writeString("static const char* " + varPrefix + "_Data[] = {\n"); let SKDList = []; for (let certName of hashes) { @@ -590,23 +561,12 @@ function writeFile(certNameToSKD, certSKDToName, let mozillaPins = {}; gStaticPins.pinsets.forEach(function(pinset) { mozillaPins[pinset.name] = true; - // We aren't guaranteed to have sha1_hashes in our own JSON. - if (pinset.sha1_hashes) { - pinset.sha1_hashes.forEach(function(name) { - usedFingerprints[name] = true; - }); - } - if (pinset.sha256_hashes) { - pinset.sha256_hashes.forEach(function(name) { - usedFingerprints[name] = true; - }); - } + pinset.sha256_hashes.forEach(function (name) { + usedFingerprints[name] = true; + }); }); for (let key in chromeImportedPinsets) { let pinset = chromeImportedPinsets[key]; - pinset.sha1_hashes.forEach(function(name) { - usedFingerprints[name] = true; - }); pinset.sha256_hashes.forEach(function(name) { usedFingerprints[name] = true; }); @@ -658,7 +618,7 @@ function loadExtraCertificates(certStringList) { var extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates); var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(extraCertificates); var [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts( - gStaticPins.chromium_data.cert_file_url, certSKDToName); + gStaticPins.chromium_data.cert_file_url, certNameToSKD, certSKDToName); var [ chromeImportedPinsets, chromeImportedEntries ] = downloadAndParseChromePins(gStaticPins.chromium_data.json_file_url, chromeNameToHash, chromeNameToMozName, certNameToSKD, certSKDToName); diff --git a/testing/marionette/driver/marionette_driver/marionette.py b/testing/marionette/driver/marionette_driver/marionette.py index a0593b98d77..7512011157b 100644 --- a/testing/marionette/driver/marionette_driver/marionette.py +++ b/testing/marionette/driver/marionette_driver/marionette.py @@ -598,7 +598,7 @@ class Marionette(object): addons=self.addons, workspace=workspace) self.instance.start() - assert(self.wait_for_port(timeout=startup_timeout)), "Timed out waiting for port!" + self.raise_for_port(self.wait_for_port(timeout=startup_timeout)) if emulator: self.runner = B2GEmulatorRunner(b2g_home=homedir, @@ -617,7 +617,7 @@ class Marionette(object): self.emulator = self.runner.device self.emulator.start() self.port = self.emulator.setup_port_forwarding(remote_port=self.port) - assert(self.emulator.wait_for_port(self.port)), "Timed out waiting for port!" + self.raise_for_port(self.emulator.wait_for_port(self.port)) if connect_to_running_emulator: self.runner = B2GEmulatorRunner(b2g_home=homedir, @@ -626,7 +626,7 @@ class Marionette(object): self.emulator = self.runner.device self.emulator.connect() self.port = self.emulator.setup_port_forwarding(remote_port=self.port) - assert(self.emulator.wait_for_port(self.port)), "Timed out waiting for port!" + self.raise_for_port(self.emulator.wait_for_port(self.port)) if emulator: if busybox: @@ -673,6 +673,12 @@ class Marionette(object): def wait_for_port(self, timeout=60): return transport.wait_for_port(self.host, self.port, timeout=timeout) + @do_crash_check + def raise_for_port(self, port_obtained): + if not port_obtained: + raise IOError("Timed out waiting for port!") + + @do_crash_check def _send_message(self, name, params=None, key=None): """Send a blocking message to the server. @@ -1097,7 +1103,7 @@ class Marionette(object): if not pref_exists: self.delete_session() self.instance.restart(prefs) - assert(self.wait_for_port()), "Timed out waiting for port!" + self.raise_for_port(self.wait_for_port()) self.start_session() self._reset_timeouts() @@ -1134,7 +1140,7 @@ class Marionette(object): else: self.delete_session() self.instance.restart(clean=clean) - assert(self.wait_for_port()), "Timed out waiting for port!" + self.raise_for_port(self.wait_for_port()) self.start_session(session_id=self.session_id) self._reset_timeouts() diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py index 1d01fd31b7a..908f6f26f7b 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py @@ -472,8 +472,9 @@ class DeviceManagerADB(DeviceManager): # we must determine the device root ourselves paths = [('/storage/sdcard0', 'tests'), ('/storage/sdcard1', 'tests'), - ('/sdcard', 'tests'), + ('/storage/sdcard', 'tests'), ('/mnt/sdcard', 'tests'), + ('/sdcard', 'tests'), ('/data/local', 'tests')] for (basePath, subPath) in paths: if self.dirExists(basePath): diff --git a/testing/mozharness/configs/android/androidx86.py b/testing/mozharness/configs/android/androidx86.py index a6f432a541b..8627396e0d2 100644 --- a/testing/mozharness/configs/android/androidx86.py +++ b/testing/mozharness/configs/android/androidx86.py @@ -5,8 +5,6 @@ config = { "host_utils_url": "http://talos-remote.pvt.build.mozilla.org/tegra/tegra-host-utils.Linux.1109310.2.zip", "robocop_package_name": "org.mozilla.roboexample.test", "device_ip": "127.0.0.1", - "default_sut_port1": "20701", - "default_sut_port2": "20700", # does not prompt for commands "tooltool_manifest_path": "testing/config/tooltool-manifests/androidx86/releng.manifest", "tooltool_cache": "/builds/tooltool_cache", "emulator_manifest": """ @@ -21,7 +19,7 @@ config = { ] """, "emulator_process_name": "emulator64-x86", "emulator_extra_args": "-debug init,console,gles,memcheck,adbserver,adbclient,adb,avd_config,socket -qemu -m 1024 -enable-kvm", - "device_manager": "sut", + "device_manager": "adb", "exes": { 'adb': '%(abs_work_dir)s/android-sdk18/platform-tools/adb', 'python': '/tools/buildbot/bin/python', @@ -50,8 +48,6 @@ config = { "http_port": "8854", # starting http port to use for the mochitest server "ssl_port": "4454", # starting ssl port to use for the server "emulator_port": 5554, - "sut_port1": 20701, - "sut_port2": 20700 }, { "name": "test-2", @@ -59,8 +55,6 @@ config = { "http_port": "8856", # starting http port to use for the mochitest server "ssl_port": "4456", # starting ssl port to use for the server "emulator_port": 5556, - "sut_port1": 20703, - "sut_port2": 20702 }, { "name": "test-3", @@ -68,8 +62,6 @@ config = { "http_port": "8858", # starting http port to use for the mochitest server "ssl_port": "4458", # starting ssl port to use for the server "emulator_port": 5558, - "sut_port1": 20705, - "sut_port2": 20704 }, { "name": "test-4", @@ -77,20 +69,15 @@ config = { "http_port": "8860", # starting http port to use for the mochitest server "ssl_port": "4460", # starting ssl port to use for the server "emulator_port": 5560, - "sut_port1": 20707, - "sut_port2": 20706 } ], "suite_definitions": { "mochitest": { "run_filename": "runtestsremote.py", - "options": ["--dm_trans=sut", - "--app=%(app)s", + "options": ["--app=%(app)s", "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s", - "--deviceIP=%(device_ip)s", - "--devicePort=%(device_port)s", "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s", "--certificate-path=%(certs_path)s", @@ -109,8 +96,6 @@ config = { "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s", - "--deviceIP=%(device_ip)s", - "--devicePort=%(device_port)s", "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s", @@ -119,10 +104,7 @@ config = { }, "xpcshell": { "run_filename": "remotexpcshelltests.py", - "options": ["--dm_trans=sut", - "--deviceIP=%(device_ip)s", - "--devicePort=%(device_port)s", - "--xre-path=%(xre_path)s", + "options": ["--xre-path=%(xre_path)s", "--testing-modules-dir=%(modules_dir)s", "--apk=%(installer_path)s", "--no-logfiles", diff --git a/testing/mozharness/scripts/release/antivirus.py b/testing/mozharness/scripts/release/antivirus.py index d96b461da70..0d044c5d98e 100644 --- a/testing/mozharness/scripts/release/antivirus.py +++ b/testing/mozharness/scripts/release/antivirus.py @@ -155,7 +155,7 @@ class AntivirusScan(BaseScript, VirtualenvMixin): key = bucket.get_key(source) return retry(key.get_contents_to_filename, args=(destination, ), - sleeptime=5, max_sleeptime=60, + sleeptime=30, max_sleeptime=150, retry_exceptions=(S3CopyError, S3ResponseError, IOError, HTTPException)) diff --git a/testing/taskcluster/tasks/branches/base_jobs.yml b/testing/taskcluster/tasks/branches/base_jobs.yml index 3e77cb37657..5bffe59128e 100644 --- a/testing/taskcluster/tasks/branches/base_jobs.yml +++ b/testing/taskcluster/tasks/branches/base_jobs.yml @@ -191,7 +191,7 @@ tests: tasks/builds/b2g_emulator_x86_kk_opt.yml: task: tasks/tests/b2g_emulator_crashtest.yml tasks/builds/dbg_linux64.yml: - task: tasks/tests/fx_linux64_cppunit.yml + task: tasks/tests/fx_linux64_crashtest.yml gaia-build: allowed_build_tasks: tasks/builds/b2g_desktop_opt.yml: diff --git a/testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html.ini b/testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html.ini new file mode 100644 index 00000000000..648a7ef3822 --- /dev/null +++ b/testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html.ini @@ -0,0 +1,3 @@ +[attached-callback-test.html] + type: testharness + disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1221424 diff --git a/testing/xpcshell/remotexpcshelltests.py b/testing/xpcshell/remotexpcshelltests.py index a63c4526878..f221386e07b 100644 --- a/testing/xpcshell/remotexpcshelltests.py +++ b/testing/xpcshell/remotexpcshelltests.py @@ -231,7 +231,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object): self.options = options self.device = devmgr self.pathMapping = [] - self.remoteTestRoot = "%s/xpcshell" % self.device.deviceRoot + self.remoteTestRoot = "%s/xpc" % self.device.deviceRoot # remoteBinDir contains xpcshell and its wrapper script, both of which must # be executable. Since +x permissions cannot usually be set on /mnt/sdcard, # and the test root may be on /mnt/sdcard, remoteBinDir is set to be on diff --git a/toolkit/components/mediasniffer/nsMediaSniffer.cpp b/toolkit/components/mediasniffer/nsMediaSniffer.cpp index cd1e585b5aa..fa21493164e 100644 --- a/toolkit/components/mediasniffer/nsMediaSniffer.cpp +++ b/toolkit/components/mediasniffer/nsMediaSniffer.cpp @@ -11,9 +11,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/ModuleUtils.h" #include "mp3sniff.h" -#ifdef MOZ_WEBM #include "nestegg/nestegg.h" -#endif #include "nsIClassInfoImpl.h" #include @@ -107,11 +105,7 @@ static bool MatchesMP4(const uint8_t* aData, const uint32_t aLength, nsACString& static bool MatchesWebM(const uint8_t* aData, const uint32_t aLength) { -#ifdef MOZ_WEBM return nestegg_sniff((uint8_t*)aData, aLength) ? true : false; -#else - return false; -#endif } // This function implements mp3 sniffing based on parsing diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index e8315607c41..d2396cdea30 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -4216,7 +4216,7 @@ "high": "10000", "n_buckets": 20, "extended_statistics_ok": true, - "description": "Firefox: Time taken to load a page (ms)" + "description": "Firefox: Time taken to load a page (ms). This includes all static contents, no dynamic content. Loading of about: pages is not counted." }, "FX_TOTAL_TOP_VISITS": { "expires_in_version": "default", diff --git a/toolkit/components/url-classifier/HashStore.cpp b/toolkit/components/url-classifier/HashStore.cpp index 935644da91b..cc87dbdb906 100644 --- a/toolkit/components/url-classifier/HashStore.cpp +++ b/toolkit/components/url-classifier/HashStore.cpp @@ -256,10 +256,7 @@ HashStore::Open() } uint32_t fileSize32 = static_cast(fileSize); - - rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream), origStream, - fileSize32); - NS_ENSURE_SUCCESS(rv, rv); + mInputStream = NS_BufferInputStream(origStream, fileSize32); rv = CheckChecksum(storeFile, fileSize32); SUCCESS_OR_RESET(rv); diff --git a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp index 07569139667..296d095abd4 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp @@ -4,21 +4,26 @@ * 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 "nsUrlClassifierPrefixSet.h" +#include "nsIUrlClassifierPrefixSet.h" #include "nsCOMPtr.h" #include "nsDebug.h" #include "nsPrintfCString.h" #include "nsTArray.h" #include "nsString.h" -#include "nsUrlClassifierPrefixSet.h" -#include "nsIUrlClassifierPrefixSet.h" #include "nsIFile.h" #include "nsToolkitCompsCID.h" #include "nsTArray.h" #include "nsThreadUtils.h" +#include "nsNetUtil.h" +#include "nsISeekableStream.h" +#include "nsIBufferedStreams.h" +#include "nsIFileStreams.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Telemetry.h" #include "mozilla/FileUtils.h" #include "mozilla/Logging.h" +#include "mozilla/unused.h" using namespace mozilla; @@ -277,23 +282,37 @@ nsUrlClassifierPrefixSet::IsEmpty(bool * aEmpty) return NS_OK; } -nsresult -nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose& fileFd) +NS_IMETHODIMP +nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile) { - uint32_t magic; - int32_t read; + Telemetry::AutoTimer timer; - read = PR_Read(fileFd, &magic, sizeof(uint32_t)); + nsCOMPtr localInFile; + nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(localInFile), aFile, + PR_RDONLY | nsIFile::OS_READAHEAD); + NS_ENSURE_SUCCESS(rv, rv); + + // Convert to buffered stream + nsCOMPtr in = NS_BufferInputStream(localInFile, BUFFER_SIZE); + + uint32_t magic; + uint32_t read; + + rv = in->Read(reinterpret_cast(&magic), sizeof(uint32_t), &read); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(read == sizeof(uint32_t), NS_ERROR_FAILURE); if (magic == PREFIXSET_VERSION_MAGIC) { uint32_t indexSize; uint32_t deltaSize; - read = PR_Read(fileFd, &indexSize, sizeof(uint32_t)); - NS_ENSURE_TRUE(read == sizeof(uint32_t), NS_ERROR_FILE_CORRUPTED); - read = PR_Read(fileFd, &deltaSize, sizeof(uint32_t)); - NS_ENSURE_TRUE(read == sizeof(uint32_t), NS_ERROR_FILE_CORRUPTED); + rv = in->Read(reinterpret_cast(&indexSize), sizeof(uint32_t), &read); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(read == sizeof(uint32_t), NS_ERROR_FAILURE); + + rv = in->Read(reinterpret_cast(&deltaSize), sizeof(uint32_t), &read); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(read == sizeof(uint32_t), NS_ERROR_FAILURE); if (indexSize == 0) { LOG(("stored PrefixSet is empty!")); @@ -311,11 +330,15 @@ nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose& fileFd) mTotalPrefixes = indexSize; - int32_t toRead = indexSize*sizeof(uint32_t); - read = PR_Read(fileFd, mIndexPrefixes.Elements(), toRead); - NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED); - read = PR_Read(fileFd, indexStarts.Elements(), toRead); - NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED); + uint32_t toRead = indexSize*sizeof(uint32_t); + rv = in->Read(reinterpret_cast(mIndexPrefixes.Elements()), toRead, &read); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(read == toRead, NS_ERROR_FAILURE); + + rv = in->Read(reinterpret_cast(indexStarts.Elements()), toRead, &read); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(read == toRead, NS_ERROR_FAILURE); + if (indexSize != 0 && indexStarts[0] != 0) { return NS_ERROR_FILE_CORRUPTED; } @@ -329,8 +352,9 @@ nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose& fileFd) mIndexDeltas[i].SetLength(numInDelta); mTotalPrefixes += numInDelta; toRead = numInDelta * sizeof(uint16_t); - read = PR_Read(fileFd, mIndexDeltas[i].Elements(), toRead); - NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED); + rv = in->Read(reinterpret_cast(mIndexDeltas[i].Elements()), toRead, &read); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(read == toRead, NS_ERROR_FAILURE); } } } else { @@ -341,43 +365,41 @@ nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose& fileFd) MOZ_ASSERT(mIndexPrefixes.Length() == mIndexDeltas.Length()); LOG(("Loading PrefixSet successful")); + mMemoryInUse = SizeOfIncludingThis(UrlClassifierMallocSizeOf); + return NS_OK; } NS_IMETHODIMP -nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile) +nsUrlClassifierPrefixSet::StoreToFile(nsIFile* aFile) { - Telemetry::AutoTimer timer; + nsCOMPtr localOutFile; + nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(localOutFile), aFile, + PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE); + NS_ENSURE_SUCCESS(rv, rv); - nsresult rv; - AutoFDClose fileFd; - rv = aFile->OpenNSPRFileDesc(PR_RDONLY | nsIFile::OS_READAHEAD, - 0, &fileFd.rwget()); - if (!NS_FAILED(rv)) { - rv = LoadFromFd(fileFd); - mMemoryInUse = SizeOfIncludingThis(UrlClassifierMallocSizeOf); - } - - return rv; -} - -nsresult -nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose& fileFd) -{ + // Preallocate the file storage { - Telemetry::AutoTimer timer; - int64_t size = 4 * sizeof(uint32_t); - uint32_t deltas = mTotalPrefixes - mIndexPrefixes.Length(); - size += 2 * mIndexPrefixes.Length() * sizeof(uint32_t); - size += deltas * sizeof(uint16_t); + nsCOMPtr fos(do_QueryInterface(localOutFile)); + Telemetry::AutoTimer timer; + int64_t size = 4 * sizeof(uint32_t); + uint32_t deltas = mTotalPrefixes - mIndexPrefixes.Length(); + size += 2 * mIndexPrefixes.Length() * sizeof(uint32_t); + size += deltas * sizeof(uint16_t); - mozilla::fallocate(fileFd, size); + // Ignore failure, the preallocation is a hint and we write out the entire + // file later on + Unused << fos->Preallocate(size); } - int32_t written; - int32_t writelen = sizeof(uint32_t); + // Convert to buffered stream + nsCOMPtr out = NS_BufferOutputStream(localOutFile, BUFFER_SIZE); + + uint32_t written; + uint32_t writelen = sizeof(uint32_t); uint32_t magic = PREFIXSET_VERSION_MAGIC; - written = PR_Write(fileFd, &magic, writelen); + rv = out->Write(reinterpret_cast(&magic), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); uint32_t indexSize = mIndexPrefixes.Length(); @@ -398,20 +420,28 @@ nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose& fileFd) indexStarts.AppendElement(totalDeltas); } - written = PR_Write(fileFd, &indexSize, writelen); + rv = out->Write(reinterpret_cast(&indexSize), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); - written = PR_Write(fileFd, &totalDeltas, writelen); + + rv = out->Write(reinterpret_cast(&totalDeltas), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); writelen = indexSize * sizeof(uint32_t); - written = PR_Write(fileFd, mIndexPrefixes.Elements(), writelen); + rv = out->Write(reinterpret_cast(mIndexPrefixes.Elements()), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); - written = PR_Write(fileFd, indexStarts.Elements(), writelen); + + rv = out->Write(reinterpret_cast(indexStarts.Elements()), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); + if (totalDeltas > 0) { for (uint32_t i = 0; i < indexDeltaSize; i++) { writelen = mIndexDeltas[i].Length() * sizeof(uint16_t); - written = PR_Write(fileFd, mIndexDeltas[i].Elements(), writelen); + rv = out->Write(reinterpret_cast(mIndexDeltas[i].Elements()), writelen, &written); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE); } } @@ -420,14 +450,3 @@ nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose& fileFd) return NS_OK; } - -NS_IMETHODIMP -nsUrlClassifierPrefixSet::StoreToFile(nsIFile* aFile) -{ - AutoFDClose fileFd; - nsresult rv = aFile->OpenNSPRFileDesc(PR_RDWR | PR_TRUNCATE | PR_CREATE_FILE, - 0644, &fileFd.rwget()); - NS_ENSURE_SUCCESS(rv, rv); - - return StoreToFd(fileFd); -} diff --git a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h index bd476a79cfa..c701891e746 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h +++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h @@ -43,14 +43,13 @@ public: protected: virtual ~nsUrlClassifierPrefixSet(); + static const uint32_t BUFFER_SIZE = 64 * 1024; static const uint32_t DELTAS_LIMIT = 120; static const uint32_t MAX_INDEX_DIFF = (1 << 16); static const uint32_t PREFIXSET_VERSION_MAGIC = 1; nsresult MakePrefixSet(const uint32_t* aArray, uint32_t aLength); uint32_t BinSearch(uint32_t start, uint32_t end, uint32_t target); - nsresult LoadFromFd(mozilla::AutoFDClose& fileFd); - nsresult StoreToFd(mozilla::AutoFDClose& fileFd); // Return the estimated size of the set on disk and in memory, in bytes. size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); diff --git a/toolkit/content/aboutProfiles.js b/toolkit/content/aboutProfiles.js index 8ce11b1e7f1..f4a823a4e89 100644 --- a/toolkit/content/aboutProfiles.js +++ b/toolkit/content/aboutProfiles.js @@ -99,9 +99,33 @@ function display(profileData) { let div = document.createElement('div'); parent.appendChild(div); - let name = document.createElement('h2'); let nameStr = bundle.formatStringFromName('name', [profileData.profile.name], 1); - name.appendChild(document.createTextNode(nameStr)); + + let name = document.createElement('h2'); + + if (gManage) { + let checkBox = document.createElement('input'); + checkBox.setAttribute('type', 'radio'); + checkBox.setAttribute('name', 'profile'); + checkBox.setAttribute('id', profileData.profile.name); + if (profileData.isCurrentProfile) { + checkBox.setAttribute('checked', 'checked'); + } + name.appendChild(checkBox); + + checkBox.addEventListener('change', function() { + ProfileService.selectedProfile = profileData.profile; + ProfileService.flush(); + }); + + let label = document.createElement('label'); + label.appendChild(document.createTextNode(nameStr)); + label.setAttribute('for', profileData.profile.name); + name.appendChild(label); + } else { + name.appendChild(document.createTextNode(nameStr)); + } + div.appendChild(name); if (!gManage && profileData.isCurrentProfile) { @@ -186,20 +210,12 @@ function display(profileData) { div.appendChild(defaultButton); } - if (gManage) { - let openButton = document.createElement('button'); - openButton.appendChild(document.createTextNode(bundle.GetStringFromName('open'))); - openButton.onclick = function() { - openProfile(profileData.profile); - }; - div.appendChild(openButton); - } - let sep = document.createElement('hr'); div.appendChild(sep); } function CreateProfile(profile) { + ProfileService.selectedProfile = profile; ProfileService.flush(); refreshUI(); } @@ -274,13 +290,6 @@ function defaultProfile(profile) { refreshUI(); } -function openProfile(profile) { - ProfileService.selectedProfile = profile; - ProfileService.flush(); - - dispatchEvent(new CustomEvent("startbrowser")); -} - function restart(safeMode) { let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] .createInstance(Ci.nsISupportsPRBool); diff --git a/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in b/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in index 4631874dcbd..eef3c3a6ed3 100644 --- a/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in +++ b/toolkit/mozapps/update/updater/updater-xpcshell/Makefile.in @@ -33,7 +33,7 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) mv $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/updater-xpcshell $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/updater # Copy for mochitest chrome tests - rsync -a -C $(XPCSHELLTESTROOT)/data/updater.app $(MOCHITESTROOT)/data/updater.app + rsync -a -C $(XPCSHELLTESTROOT)/data/updater.app $(MOCHITESTROOT)/data/ else cp $(PROGRAM) $(XPCSHELLTESTROOT)/data/updater$(BIN_SUFFIX) cp $(PROGRAM) $(MOCHITESTROOT)/data/updater$(BIN_SUFFIX) diff --git a/toolkit/profile/content/profileSelection.js b/toolkit/profile/content/profileSelection.js index 898d5ef2980..bcafb1a830d 100644 --- a/toolkit/profile/content/profileSelection.js +++ b/toolkit/profile/content/profileSelection.js @@ -26,14 +26,6 @@ function startup() gBrandBundle = document.getElementById("bundle_brand"); document.documentElement.centerWindowOnScreen(); - - var browser = document.getElementById("browser"); - browser.frameLoader.docShell.contentViewer.DOMDocument.defaultView - .addEventListener('startbrowser', function() { - if (acceptDialog()) { - this.close(); - } - }.bind(this), false); } function acceptDialog() diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index e44c6552ac5..9a1802a30dd 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -416,12 +416,12 @@ static nsresult GetDownloadDirectory(nsIFile **_directory, const char* userName = PR_GetEnv("USERNAME"); if (!userName || !*userName) { userName = PR_GetEnv("USER"); - if (!userName || !*userName) { - userName = PR_GetEnv("LOGNAME"); - } - else { - userName = "mozillaUser"; - } + } + if (!userName || !*userName) { + userName = PR_GetEnv("LOGNAME"); + } + if (!userName || !*userName) { + userName = "mozillaUser"; } nsAutoString userDir; @@ -447,7 +447,12 @@ static nsresult GetDownloadDirectory(nsIFile **_directory, rv = finalPath->GetPermissions(&permissions); NS_ENSURE_SUCCESS(rv, rv); - if (permissions == PR_IRWXU) { + // Ensuring the path is writable by the current user. + bool isWritable; + rv = finalPath->IsWritable(&isWritable); + NS_ENSURE_SUCCESS(rv, rv); + + if (permissions == PR_IRWXU && isWritable) { dir = finalPath; break; } @@ -513,10 +518,8 @@ static nsDefaultMimeTypeEntry defaultMimeEntries [] = { APPLICATION_OGG, "ogg" }, { AUDIO_OGG, "oga" }, { AUDIO_OGG, "opus" }, -#ifdef MOZ_WEBM { VIDEO_WEBM, "webm" }, { AUDIO_WEBM, "webm" }, -#endif #if defined(MOZ_GSTREAMER) || defined(MOZ_WMF) { VIDEO_MP4, "mp4" }, { AUDIO_MP4, "m4a" }, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index e4ebe97c9f9..4ef4c9aa8a4 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -250,6 +250,12 @@ int nsWindow::sTrimOnMinimize = 2; TriStateBool nsWindow::sHasBogusPopupsDropShadowOnMultiMonitor = TRI_UNKNOWN; +static SystemTimeConverter& +TimeConverter() { + static SystemTimeConverter timeConverterSingleton; + return timeConverterSingleton; +} + namespace mozilla { class CurrentWindowsTimeGetter { @@ -261,18 +267,14 @@ public: void GetTimeAsyncForPossibleBackwardsSkew(const TimeStamp& aNow) { - // FIXME: Get time async + NS_DispatchToMainThread(NS_NewRunnableFunction([aNow]() { + TimeConverter().CompensateForBackwardsSkew(::GetMessageTime(), aNow); + })); } }; } // namespace mozilla -static SystemTimeConverter& -TimeConverter() { - static SystemTimeConverter timeConverterSingleton; - return timeConverterSingleton; -} - /************************************************************** * * SECTION: globals variables diff --git a/xpcom/tests/unit/xpcshell.ini b/xpcom/tests/unit/xpcshell.ini index e340e3e850f..8137a26b024 100644 --- a/xpcom/tests/unit/xpcshell.ini +++ b/xpcom/tests/unit/xpcshell.ini @@ -33,8 +33,6 @@ fail-if = os == "android" fail-if = os == "android" [test_file_createUnique.js] [test_file_equality.js] -# Bug 1144393: fails consistently on Android 4.3 emulator -fail-if = android_version == "18" [test_hidden_files.js] [test_home.js] # Bug 676998: test fails consistently on Android diff --git a/xulrunner/tools/redit/redit.cpp b/xulrunner/tools/redit/redit.cpp index 5fdb7f7b5dc..8a96358b22e 100644 --- a/xulrunner/tools/redit/redit.cpp +++ b/xulrunner/tools/redit/redit.cpp @@ -15,7 +15,7 @@ // Mozilla headers (alphabetical) #include "mozilla/FileUtils.h" // ScopedClose -#include "nsAutoPtr.h" // nsAutoArrayPtr +#include "mozilla/UniquePtrExtensions.h" /* Icon files are made up of: @@ -120,12 +120,12 @@ wmain(int argc, wchar_t** argv) // Load all the data from the icon file long filesize = _filelength(file); - nsAutoArrayPtr data(new BYTE[filesize]); + auto data = MakeUniqueFallible(filesize); if(!data) { fprintf(stderr, "Failed to allocate memory for icon file.\n"); return 1; } - _read(file, data, filesize); + _read(file, data.get(), filesize); IconHeader* header = reinterpret_cast(data.get()); @@ -139,18 +139,18 @@ wmain(int argc, wchar_t** argv) // Allocate the group resource entry long groupSize = sizeof(IconHeader) + header->ImageCount * sizeof(IconResEntry); - nsAutoArrayPtr group(new BYTE[groupSize]); + auto group = MakeUniqueFallible(groupSize); if(!group) { fprintf(stderr, "Failed to allocate memory for new images.\n"); return 1; } - memcpy(group, data, sizeof(IconHeader)); + memcpy(group.get(), data.get(), sizeof(IconHeader)); IconDirEntry* sourceIcon = - reinterpret_cast(data + reinterpret_cast(data.get() + sizeof(IconHeader)); IconResEntry* targetIcon = - reinterpret_cast(group + reinterpret_cast(group.get() + sizeof(IconHeader)); for (int id = 1; id <= header->ImageCount; id++) {