author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Tue, 18 Nov 2014 17:34:34 +0100 | |
changeset 216370 | a8a9d42356c8bdf21f91432d28a0999b59a44057 |
parent 216369 | 2ca6377a2a16f31241bb8a34de936619072c961a (current diff) |
parent 216266 | 084441e904d1225f15d5f641cc0efb82d4ead4cd (diff) |
child 216371 | 121a5cc63382816393d515993817925c41c1f2f7 |
push id | 52026 |
push user | kwierso@gmail.com |
push date | Wed, 19 Nov 2014 02:37:17 +0000 |
treeherder | mozilla-inbound@d197d16c0caa [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/jsat/Presentation.jsm +++ b/accessible/jsat/Presentation.jsm @@ -446,16 +446,28 @@ AndroidPresenter.prototype.announce = AndroidPresenter.prototype.liveRegion = function AndroidPresenter_liveRegion(aContext, aIsPolite, aIsHide, aModifiedText) { return this.announce( UtteranceGenerator.genForLiveRegion(aContext, aIsHide, aModifiedText)); }; +AndroidPresenter.prototype.noMove = + function AndroidPresenter_noMove(aMoveMethod) { + return { + type: this.type, + details: [ + { eventType: this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED, + exitView: aMoveMethod, + text: [''] + }] + }; + }; + /** * A B2G presenter for Gaia. */ function B2GPresenter() {} B2GPresenter.prototype = Object.create(Presenter.prototype); B2GPresenter.prototype.type = 'B2G';
--- a/accessible/tests/mochitest/textattrs/test_general.html +++ b/accessible/tests/mochitest/textattrs/test_general.html @@ -704,22 +704,22 @@ <span style="font-family: monospace;">text</span>text <span style="font-family: serif;">text</span>text <span style="font-family: BodoniThatDoesntExist;">text</span>text <span style="font-family: Comic Sans MS, cursive;">text</span>text <span style="font-family: sans-serif, fantasy;">text</span>text </p> <p id="area17"> - <span style="-moz-text-decoration-line: underline;">underline - </span><span style="text-decoration: underline; -moz-text-decoration-color: blue;">blue - </span><span style="text-decoration: underline; -moz-text-decoration-style: dotted;">dotted - </span><span style="-moz-text-decoration-line: line-through;">linethrough - </span><span style="text-decoration: line-through; -moz-text-decoration-color: blue;">blue - </span><span style="text-decoration: line-through; -moz-text-decoration-style: wavy;">wavy + <span style="text-decoration-line: underline;">underline + </span><span style="text-decoration: underline; text-decoration-color: blue;">blue + </span><span style="text-decoration: underline; text-decoration-style: dotted;">dotted + </span><span style="text-decoration-line: line-through;">linethrough + </span><span style="text-decoration: line-through; text-decoration-color: blue;">blue + </span><span style="text-decoration: line-through; text-decoration-style: wavy;">wavy </span> </p> <ul> <li id="area18" class="gencontent">item</li> </ul> <p id="area19">uncolored
--- a/b2g/components/LogCapture.jsm +++ b/b2g/components/LogCapture.jsm @@ -3,89 +3,157 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* jshint moz: true */ /* global Uint8Array, Components, dump */ 'use strict'; this.EXPORTED_SYMBOLS = ['LogCapture']; -/** - * readLogFile - * Read in /dev/log/{{log}} in nonblocking mode, which will return -1 if - * reading would block the thread. - * - * @param log {String} The log from which to read. Must be present in /dev/log - * @return {Uint8Array} Raw log data - */ -let readLogFile = function(logLocation) { - if (!this.ctypes) { +const SYSTEM_PROPERTY_KEY_MAX = 32; +const SYSTEM_PROPERTY_VALUE_MAX = 92; + +function debug(msg) { + dump('LogCapture.jsm: ' + msg + '\n'); +} + +let LogCapture = { + ensureLoaded: function() { + if (!this.ctypes) { + this.load(); + } + }, + + load: function() { // load in everything on first use Components.utils.import('resource://gre/modules/ctypes.jsm', this); - this.lib = this.ctypes.open(this.ctypes.libraryName('c')); + this.libc = this.ctypes.open(this.ctypes.libraryName('c')); - this.read = this.lib.declare('read', + this.read = this.libc.declare('read', this.ctypes.default_abi, this.ctypes.int, // bytes read (out) this.ctypes.int, // file descriptor (in) this.ctypes.voidptr_t, // buffer to read into (in) this.ctypes.size_t // size_t size of buffer (in) ); - this.open = this.lib.declare('open', + this.open = this.libc.declare('open', this.ctypes.default_abi, this.ctypes.int, // file descriptor (returned) this.ctypes.char.ptr, // path this.ctypes.int // flags ); - this.close = this.lib.declare('close', + this.close = this.libc.declare('close', this.ctypes.default_abi, this.ctypes.int, // error code (returned) this.ctypes.int // file descriptor ); - } + + this.property_find_nth = + this.libc.declare("__system_property_find_nth", + this.ctypes.default_abi, + this.ctypes.voidptr_t, // return value: nullable prop_info* + this.ctypes.unsigned_int); // n: the index of the property to return - const O_READONLY = 0; - const O_NONBLOCK = 1 << 11; + this.property_read = + this.libc.declare("__system_property_read", + this.ctypes.default_abi, + this.ctypes.void_t, // return: none + this.ctypes.voidptr_t, // non-null prop_info* + this.ctypes.char.ptr, // key + this.ctypes.char.ptr); // value - const BUF_SIZE = 2048; + this.key_buf = this.ctypes.char.array(SYSTEM_PROPERTY_KEY_MAX)(); + this.value_buf = this.ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)(); + }, + + cleanup: function() { + this.libc.close(); - let BufType = this.ctypes.ArrayType(this.ctypes.char); - let buf = new BufType(BUF_SIZE); - let logArray = []; + this.read = null; + this.open = null; + this.close = null; + this.property_find_nth = null; + this.property_read = null; + this.key_buf = null; + this.value_buf = null; + + this.libc = null; + this.ctypes = null; + }, - let logFd = this.open(logLocation, O_READONLY | O_NONBLOCK); - if (logFd === -1) { - return null; - } + /** + * readLogFile + * Read in /dev/log/{{log}} in nonblocking mode, which will return -1 if + * reading would block the thread. + * + * @param log {String} The log from which to read. Must be present in /dev/log + * @return {Uint8Array} Raw log data + */ + readLogFile: function(logLocation) { + this.ensureLoaded(); + + const O_READONLY = 0; + const O_NONBLOCK = 1 << 11; + + const BUF_SIZE = 2048; - let readStart = Date.now(); - let readCount = 0; - while (true) { - let count = this.read(logFd, buf, BUF_SIZE); - readCount += 1; + let BufType = this.ctypes.ArrayType(this.ctypes.char); + let buf = new BufType(BUF_SIZE); + let logArray = []; + + let logFd = this.open(logLocation, O_READONLY | O_NONBLOCK); + if (logFd === -1) { + return null; + } - if (count <= 0) { - // log has return due to being nonblocking or running out of things - break; + let readStart = Date.now(); + let readCount = 0; + while (true) { + let count = this.read(logFd, buf, BUF_SIZE); + readCount += 1; + + if (count <= 0) { + // log has return due to being nonblocking or running out of things + break; + } + for(let i = 0; i < count; i++) { + logArray.push(buf[i]); + } } - for(let i = 0; i < count; i++) { - logArray.push(buf[i]); - } - } + + let logTypedArray = new Uint8Array(logArray); + + this.close(logFd); + + return logTypedArray; + }, + + /** + * Get all system properties as a dict with keys mapping to values + */ + readProperties: function() { + this.ensureLoaded(); + let n = 0; + let propertyDict = {}; - let logTypedArray = new Uint8Array(logArray); + while(true) { + let prop_info = this.property_find_nth(n); + if(prop_info.isNull()) { + break; + } - this.close(logFd); + // read the prop_info into the key and value buffers + this.property_read(prop_info, this.key_buf, this.value_buf); + let key = this.key_buf.readString();; + let value = this.value_buf.readString() - return logTypedArray; + propertyDict[key] = value; + n++; + } + + return propertyDict; + } }; -let cleanup = function() { - this.lib.close(); - this.read = this.open = this.close = null; - this.lib = null; - this.ctypes = null; -}; - -this.LogCapture = { readLogFile: readLogFile, cleanup: cleanup }; +this.LogCapture = LogCapture;
--- a/b2g/components/LogParser.jsm +++ b/b2g/components/LogParser.jsm @@ -210,92 +210,34 @@ function formatLogMessage(logMessage) { * @return {String} Pretty-printed log */ function prettyPrintLogArray(array) { let logMessages = parseLogArray(array); return logMessages.map(formatLogMessage).join(""); } /** - * Parse an array of bytes as a properties file. The structure of the - * properties file is derived from bionic/libc/bionic/system_properties.c - * @param array {Uint8Array} Array containing property data - * @return {Object} Map from property name to property value, both strings - */ -function parsePropertiesArray(array) { - let data = new DataView(array.buffer); - let byteString = String.fromCharCode.apply(null, array); - - let properties = {}; - - let propIndex = 0; - let propCount = data.getUint32(0, true); - - // first TOC entry is at 32 - let tocOffset = 32; - - const PROP_NAME_MAX = 32; - const PROP_VALUE_MAX = 92; - - while (propIndex < propCount) { - // Retrieve offset from file start - let infoOffset = data.getUint32(tocOffset, true) & 0xffffff; - - // Now read the name, integer serial, and value - let propName = ""; - let nameOffset = infoOffset; - while (byteString[nameOffset] != "\0" && - (nameOffset - infoOffset) < PROP_NAME_MAX) { - propName += byteString[nameOffset]; - nameOffset ++; - } - - infoOffset += PROP_NAME_MAX; - // Skip serial number - infoOffset += 4; - - let propValue = ""; - nameOffset = infoOffset; - while (byteString[nameOffset] != "\0" && - (nameOffset - infoOffset) < PROP_VALUE_MAX) { - propValue += byteString[nameOffset]; - nameOffset ++; - } - - // Move to next table of contents entry - tocOffset += 4; - - properties[propName] = propValue; - propIndex += 1; - } - - return properties; -} - -/** - * Pretty-print an array read from the /dev/__properties__ file. - * @param array {Uint8Array} File data array + * Pretty-print an array read from the list of propreties. + * @param {Object} Object representing the properties * @return {String} Human-readable string of property name: property value */ -function prettyPrintPropertiesArray(array) { - let properties = parsePropertiesArray(array); +function prettyPrintPropertiesArray(properties) { let propertiesString = ""; for(let propName in properties) { - propertiesString += propName + ": " + properties[propName] + "\n"; + propertiesString += "[" + propName + "]: [" + properties[propName] + "]\n"; } return propertiesString; } /** * Pretty-print a normal array. Does nothing. * @param array {Uint8Array} Input array */ function prettyPrintArray(array) { return array; } this.LogParser = { parseLogArray: parseLogArray, - parsePropertiesArray: parsePropertiesArray, prettyPrintArray: prettyPrintArray, prettyPrintLogArray: prettyPrintLogArray, prettyPrintPropertiesArray: prettyPrintPropertiesArray };
--- a/b2g/components/LogShake.jsm +++ b/b2g/components/LogShake.jsm @@ -74,17 +74,16 @@ let LogShake = { * debouncing. */ captureRequested: false, /** * Map of files which have log-type information to their parsers */ LOGS_WITH_PARSERS: { - '/dev/__properties__': LogParser.prettyPrintPropertiesArray, '/dev/log/main': LogParser.prettyPrintLogArray, '/dev/log/system': LogParser.prettyPrintLogArray, '/dev/log/radio': LogParser.prettyPrintLogArray, '/dev/log/events': LogParser.prettyPrintLogArray, '/proc/cmdline': LogParser.prettyPrintArray, '/proc/kmsg': LogParser.prettyPrintArray, '/proc/meminfo': LogParser.prettyPrintArray, '/proc/uptime': LogParser.prettyPrintArray, @@ -205,16 +204,24 @@ let LogShake = { return saveLogs(logArrays); }, /** * Read in all log files, returning their formatted contents */ readLogs: function() { let logArrays = {}; + + try { + logArrays["properties"] = + LogParser.prettyPrintPropertiesArray(LogCapture.readProperties()); + } catch (ex) { + Cu.reportError("Unable to get device properties: " + ex); + } + for (let loc in this.LOGS_WITH_PARSERS) { let logArray; try { logArray = LogCapture.readLogFile(loc); if (!logArray) { continue; } } catch (ex) {
deleted file mode 100644 index a8254853738e2083fbea3c659e4346c141214f2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
--- a/b2g/components/test/unit/test_logcapture.js +++ b/b2g/components/test/unit/test_logcapture.js @@ -3,23 +3,28 @@ /** * Test that LogCapture successfully reads from the /dev/log devices, returning * a Uint8Array of some length, including zero. This tests a few standard * log devices */ function run_test() { - Components.utils.import('resource:///modules/LogCapture.jsm'); + Components.utils.import("resource:///modules/LogCapture.jsm"); function verifyLog(log) { // log exists notEqual(log, null); // log has a length and it is non-negative (is probably array-like) ok(log.length >= 0); } - let mainLog = LogCapture.readLogFile('/dev/log/main'); + let propertiesLog = LogCapture.readProperties(); + notEqual(propertiesLog, null, "Properties should not be null"); + notEqual(propertiesLog, undefined, "Properties should not be undefined"); + equal(propertiesLog["ro.kernel.qemu"], "1", "QEMU property should be 1"); + + let mainLog = LogCapture.readLogFile("/dev/log/main"); verifyLog(mainLog); - let meminfoLog = LogCapture.readLogFile('/proc/meminfo'); + let meminfoLog = LogCapture.readLogFile("/proc/meminfo"); verifyLog(meminfoLog); }
--- a/b2g/components/test/unit/test_logparser.js +++ b/b2g/components/test/unit/test_logparser.js @@ -1,49 +1,74 @@ /* jshint moz: true */ const {utils: Cu, classes: Cc, interfaces: Ci} = Components; +function debug(msg) { + var timestamp = Date.now(); + dump("LogParser: " + timestamp + ": " + msg + "\n"); +} + function run_test() { - Cu.import('resource:///modules/LogParser.jsm'); + Cu.import("resource:///modules/LogParser.jsm"); + debug("Starting"); + run_next_test(); +} - let propertiesFile = do_get_file('data/test_properties'); - let loggerFile = do_get_file('data/test_logger_file'); +function makeStream(file) { + var fileStream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + fileStream.init(file, -1, -1, 0); + var bis = Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(fileStream); + return bis; +} - let propertiesStream = makeStream(propertiesFile); +add_test(function test_parse_logfile() { + let loggerFile = do_get_file("data/test_logger_file"); + let loggerStream = makeStream(loggerFile); // Initialize arrays to hold the file contents (lengths are hardcoded) - let propertiesArray = new Uint8Array(propertiesStream.readByteArray(65536)); let loggerArray = new Uint8Array(loggerStream.readByteArray(4037)); - propertiesStream.close(); loggerStream.close(); - let properties = LogParser.parsePropertiesArray(propertiesArray); let logMessages = LogParser.parseLogArray(loggerArray); - // Test arbitrary property entries for correctness - equal(properties['ro.boot.console'], 'ttyHSL0'); - equal(properties['net.tcp.buffersize.lte'], - '524288,1048576,2097152,262144,524288,1048576'); - - ok(logMessages.length === 58, 'There should be 58 messages in the log'); + ok(logMessages.length === 58, "There should be 58 messages in the log"); let expectedLogEntry = { processId: 271, threadId: 271, seconds: 790796, nanoseconds: 620000001, time: 790796620.000001, - priority: 4, tag: 'Vold', - message: 'Vold 2.1 (the revenge) firing up\n' + priority: 4, tag: "Vold", + message: "Vold 2.1 (the revenge) firing up\n" }; deepEqual(expectedLogEntry, logMessages[0]); -} + run_next_test(); +}); + +add_test(function test_print_properties() { + let properties = { + "ro.secure": "1", + "sys.usb.state": "diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb" + }; + + let logMessages = LogParser.prettyPrintPropertiesArray(properties); + let logMessagesArray = logMessages.split("\n"); -function makeStream(file) { - var fileStream = Cc['@mozilla.org/network/file-input-stream;1'] - .createInstance(Ci.nsIFileInputStream); - fileStream.init(file, -1, -1, 0); - var bis = Cc['@mozilla.org/binaryinputstream;1'] - .createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(fileStream); - return bis; -} + ok(logMessagesArray.length === 3, "There should be 3 lines in the log."); + notEqual(logMessagesArray[0], "", "First line should not be empty"); + notEqual(logMessagesArray[1], "", "Second line should not be empty"); + equal(logMessagesArray[2], "", "Last line should be empty"); + + let expectedLog = [ + "[ro.secure]: [1]", + "[sys.usb.state]: [diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb]", + "" + ].join("\n"); + + deepEqual(expectedLog, logMessages); + + run_next_test(); +});
--- a/b2g/components/test/unit/test_logshake.js +++ b/b2g/components/test/unit/test_logshake.js @@ -3,70 +3,70 @@ */ /* jshint moz: true */ /* global Components, LogCapture, LogShake, ok, add_test, run_next_test, dump */ /* exported run_test */ /* disable use strict warning */ /* jshint -W097 */ -'use strict'; +"use strict"; const Cu = Components.utils; -Cu.import('resource://gre/modules/LogCapture.jsm'); -Cu.import('resource://gre/modules/LogShake.jsm'); +Cu.import("resource://gre/modules/LogCapture.jsm"); +Cu.import("resource://gre/modules/LogShake.jsm"); // Force logshake to handle a device motion event with given components // Does not use SystemAppProxy because event needs special // accelerationIncludingGravity property function sendDeviceMotionEvent(x, y, z) { let event = { - type: 'devicemotion', + type: "devicemotion", accelerationIncludingGravity: { x: x, y: y, z: z } }; LogShake.handleEvent(event); } // Send a screen change event directly, does not use SystemAppProxy due to race // conditions. function sendScreenChangeEvent(screenEnabled) { let event = { - type: 'screenchange', + type: "screenchange", detail: { screenEnabled: screenEnabled } }; LogShake.handleEvent(event); } function debug(msg) { var timestamp = Date.now(); - dump('LogShake: ' + timestamp + ': ' + msg); + dump("LogShake: " + timestamp + ": " + msg); } add_test(function test_do_log_capture_after_shaking() { // Enable LogShake LogShake.init(); let readLocations = []; LogCapture.readLogFile = function(loc) { readLocations.push(loc); return null; // we don't want to provide invalid data to a parser }; // Fire a devicemotion event that is of shake magnitude sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); }); add_test(function test_do_nothing_when_resting() { // Enable LogShake LogShake.init(); @@ -76,39 +76,39 @@ add_test(function test_do_nothing_when_r readLocations.push(loc); return null; // we don't want to provide invalid data to a parser }; // Fire a devicemotion event that is relatively tiny sendDeviceMotionEvent(0, 9.8, 9.8); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); - debug('test_do_nothing_when_resting: stop'); + debug("test_do_nothing_when_resting: stop"); LogShake.uninit(); run_next_test(); }); add_test(function test_do_nothing_when_disabled() { - debug('test_do_nothing_when_disabled: start'); + debug("test_do_nothing_when_disabled: start"); // Disable LogShake LogShake.uninit(); let readLocations = []; LogCapture.readLogFile = function(loc) { readLocations.push(loc); return null; // we don't want to provide invalid data to a parser }; // Fire a devicemotion event that would normally be a shake sendDeviceMotionEvent(0, 9001, 9001); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); run_next_test(); }); add_test(function test_do_nothing_when_screen_off() { // Enable LogShake LogShake.init(); @@ -121,17 +121,17 @@ add_test(function test_do_nothing_when_s readLocations.push(loc); return null; // we don't want to provide invalid data to a parser }; // Fire a devicemotion event that would normally be a shake sendDeviceMotionEvent(0, 9001, 9001); ok(readLocations.length === 0, - 'LogShake should not read any logs'); + "LogShake should not read any logs"); // Restore the screen sendScreenChangeEvent(true); LogShake.uninit(); run_next_test(); }); @@ -144,17 +144,17 @@ add_test(function test_do_log_capture_re readLocations.push(loc); throw new Error("Exception during readLogFile for: " + loc); }; // Fire a devicemotion event that is of shake magnitude sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); }); add_test(function test_do_log_capture_resilient_parseLog() { // Enable LogShake LogShake.init(); @@ -167,18 +167,18 @@ add_test(function test_do_log_capture_re }; return null; }; // Fire a devicemotion event that is of shake magnitude sendDeviceMotionEvent(9001, 9001, 9001); ok(readLocations.length > 0, - 'LogShake should attempt to read at least one log'); + "LogShake should attempt to read at least one log"); LogShake.uninit(); run_next_test(); }); function run_test() { - debug('Starting'); + debug("Starting"); run_next_test(); }
--- a/b2g/components/test/unit/xpcshell.ini +++ b/b2g/components/test/unit/xpcshell.ini @@ -1,15 +1,14 @@ [DEFAULT] head = tail = support-files = data/test_logger_file - data/test_properties [test_bug793310.js] [test_bug832946.js] [test_fxaccounts.js] [test_signintowebsite.js] head = head_identity.js
--- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/>
--- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -14,21 +14,21 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> - <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/> - <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="67f2907bc340bad250b4ea6ce2902b52896c9ef0"/> + <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/> + <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/> <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/> <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/> <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/>
--- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -14,21 +14,21 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> - <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/> - <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="67f2907bc340bad250b4ea6ce2902b52896c9ef0"/> + <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/> + <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/> <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/> <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/> <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/>
--- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { "git_revision": "", "remote": "", "branch": "" }, - "revision": "587d98bf26625137015c17d5b937bf06bd055dd0", + "revision": "67a3857cc29aaa2b2f890b4ed575065f6e5a7691", "repo_path": "integration/gaia-central" }
--- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug @@ -5,17 +5,16 @@ mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/ob ac_add_options --enable-application=b2g ac_add_options --enable-b2g-camera ac_add_options --target=arm-linux-androideabi ac_add_options --with-gonk="$topsrcdir/gonk-toolchain" export TOOLCHAIN_HOST=linux-x86 export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" -ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols ac_add_options --enable-debug #. "$topsrcdir/build/mozconfig.cache" ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h"
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly @@ -6,17 +6,16 @@ ac_add_options --enable-application=b2g ac_add_options --enable-b2g-camera ac_add_options --enable-updater ac_add_options --target=arm-linux-androideabi ac_add_options --with-gonk="$topsrcdir/gonk-toolchain" export TOOLCHAIN_HOST=linux-x86 export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" -ac_add_options --disable-elf-hack ac_add_options --enable-debug-symbols # ac_add_options --enable-profiling #. "$topsrcdir/build/mozconfig.cache" ENABLE_MARIONETTE=1 # Enable dump() from JS. export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h"
--- a/b2g/config/mozconfigs/linux32_gecko/debug +++ b/b2g/config/mozconfigs/linux32_gecko/debug @@ -24,17 +24,16 @@ export MOZ_TELEMETRY_REPORTING=1 # Use sccache no_sccache= . "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. MOZTTDIR=$topsrcdir/moztt . "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux32_gecko/nightly +++ b/b2g/config/mozconfigs/linux32_gecko/nightly @@ -22,17 +22,16 @@ export MOZ_TELEMETRY_REPORTING=1 # DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= . "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. MOZTTDIR=$topsrcdir/moztt # Build simulator xpi and phone tweaks for b2g-desktop
--- a/b2g/config/mozconfigs/linux64_gecko/debug +++ b/b2g/config/mozconfigs/linux64_gecko/debug @@ -24,17 +24,16 @@ export MOZ_TELEMETRY_REPORTING=1 # Use sccache no_sccache= . "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g ENABLE_MARIONETTE=1 -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. MOZTTDIR=$topsrcdir/moztt . "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux64_gecko/nightly +++ b/b2g/config/mozconfigs/linux64_gecko/nightly @@ -22,17 +22,16 @@ export MOZ_TELEMETRY_REPORTING=1 # DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= . "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g -ac_add_options --disable-elf-hack export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. MOZTTDIR=$topsrcdir/moztt # Build simulator xpi and phone tweaks for b2g-desktop
--- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae3a84acaab80a5b35d5542d63e68462273c8a1b"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4aee256937afe9db2520752650685ba61ce6097d"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="11ad0ea69796915552c9bae148d81fddf9856ddb"/> <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/installer/Makefile.in +++ b/b2g/installer/Makefile.in @@ -78,19 +78,16 @@ endif ifneq (,$(filter rtsp,$(NECKO_PROTOCOLS))) DEFINES += -DMOZ_RTSP endif ifdef GKMEDIAS_SHARED_LIBRARY DEFINES += -DGKMEDIAS_SHARED_LIBRARY endif -ifdef MOZ_REPLACE_MALLOC -DEFINES += -DMOZ_REPLACE_MALLOC -endif ifdef MOZ_JEMALLOC3 DEFINES += -DMOZ_JEMALLOC3 endif ifdef MOZ_WIDGET_GTK DEFINES += -DMOZ_GTK=1 ifdef MOZ_ENABLE_GTK3 DEFINES += -DMOZ_GTK3=1
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -127,17 +127,16 @@ #endif @BINPATH@/components/accessibility.xpt #endif @BINPATH@/components/appshell.xpt @BINPATH@/components/appstartup.xpt @BINPATH@/components/autocomplete.xpt @BINPATH@/components/autoconfig.xpt @BINPATH@/components/browsercompsbase.xpt -@BINPATH@/components/browser-element.xpt @BINPATH@/components/browser-feeds.xpt @BINPATH@/components/caps.xpt @BINPATH@/components/chardet.xpt @BINPATH@/components/chrome.xpt @BINPATH@/components/commandhandler.xpt @BINPATH@/components/commandlines.xpt @BINPATH@/components/composer.xpt @BINPATH@/components/content_events.xpt
--- a/browser/base/content/test/newtab/browser.ini +++ b/browser/base/content/test/newtab/browser.ini @@ -16,16 +16,17 @@ skip-if = os == "mac" # Intermittent fai [browser_newtab_bug752841.js] [browser_newtab_bug765628.js] [browser_newtab_bug876313.js] [browser_newtab_bug991111.js] [browser_newtab_bug991210.js] [browser_newtab_bug998387.js] [browser_newtab_disable.js] [browser_newtab_drag_drop.js] +skip-if = os == "win" && debug # bug 1097056; test fails in --run-by-dir mode on win8 x64 debug [browser_newtab_drag_drop_ext.js] [browser_newtab_drop_preview.js] [browser_newtab_enhanced.js] [browser_newtab_focus.js] [browser_newtab_intro.js] [browser_newtab_perwindow_private_browsing.js] [browser_newtab_reportLinkAction.js] [browser_newtab_reflow_load.js]
--- a/browser/components/search/test/browser.ini +++ b/browser/components/search/test/browser.ini @@ -31,9 +31,9 @@ skip-if = e10s # Bug ?????? - some issue skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}] [browser_healthreport.js] [browser_private_search_perwindowpb.js] skip-if = e10s # Bug ?????? - Test uses load event and checks event.target. [browser_yahoo.js] [browser_yahoo_behavior.js] skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}] [browser_abouthome_behavior.js] -skip-if = e10s # Bug ??????? +skip-if = e10s || true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
--- a/browser/components/tabview/test/browser.ini +++ b/browser/components/tabview/test/browser.ini @@ -14,17 +14,17 @@ support-files = [browser_tabview_alltabs.js] [browser_tabview_apptabs.js] [browser_tabview_bug580412.js] [browser_tabview_bug586553.js] [browser_tabview_bug587043.js] [browser_tabview_bug587231.js] skip-if = buildapp == 'mulet' [browser_tabview_bug587276.js] -skip-if = e10s # Bug 1091200 +skip-if = e10s || true # Bug 1091200, bug 1096285 [browser_tabview_bug587351.js] [browser_tabview_bug587503.js] [browser_tabview_bug587990.js] [browser_tabview_bug588265.js] [browser_tabview_bug589324.js] skip-if = e10s # Bug 1086190 [browser_tabview_bug590606.js] [browser_tabview_bug591706.js]
--- a/browser/config/mozconfigs/linux32/nightly +++ b/browser/config/mozconfigs/linux32/nightly @@ -1,13 +1,12 @@ . "$topsrcdir/browser/config/mozconfigs/linux32/common-opt" ac_add_options --enable-signmar ac_add_options --enable-profiling -ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. STRIP_FLAGS="--strip-debug"
--- a/browser/config/mozconfigs/linux32/valgrind +++ b/browser/config/mozconfigs/linux32/valgrind @@ -1,14 +1,13 @@ no_tooltool=1 no_sccache=1 . $topsrcdir/browser/config/mozconfigs/linux32/nightly ac_add_options --enable-valgrind ac_add_options --disable-jemalloc -ac_add_options --disable-elf-hack ac_add_options --enable-optimize="-g -O -freorder-blocks" ac_add_options --disable-install-strip # Include the override mozconfig again (even though the above includes it) # since it's supposed to override everything. . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/nightly +++ b/browser/config/mozconfigs/linux64/nightly @@ -1,13 +1,12 @@ . "$topsrcdir/browser/config/mozconfigs/linux64/common-opt" ac_add_options --enable-signmar ac_add_options --enable-profiling -ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. STRIP_FLAGS="--strip-debug"
--- a/browser/config/mozconfigs/linux64/valgrind +++ b/browser/config/mozconfigs/linux64/valgrind @@ -1,14 +1,13 @@ no_tooltool=1 no_sccache=1 . $topsrcdir/browser/config/mozconfigs/linux64/nightly ac_add_options --enable-valgrind ac_add_options --disable-jemalloc -ac_add_options --disable-elf-hack ac_add_options --enable-optimize="-g -O -freorder-blocks" ac_add_options --disable-install-strip # Include the override mozconfig again (even though the above includes it) # since it's supposed to override everything. . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/whitelist +++ b/browser/config/mozconfigs/whitelist @@ -29,27 +29,25 @@ whitelist['nightly']['linux32'] += [ 'CC="ccache $REAL_CC"', 'mk_add_options PROFILE_GEN_SCRIPT=@TOPSRCDIR@/build/profile_pageloader.pl', 'ac_add_options --with-ccache=/usr/bin/ccache', '. "$topsrcdir/build/mozconfig.cache"', 'export MOZILLA_OFFICIAL=1', 'export MOZ_TELEMETRY_REPORTING=1', "mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'", 'STRIP_FLAGS="--strip-debug"', - 'ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling', ] whitelist['nightly']['linux64'] += [ 'export MOZILLA_OFFICIAL=1', 'export MOZ_TELEMETRY_REPORTING=1', "mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'", 'STRIP_FLAGS="--strip-debug"', 'ac_add_options --with-ccache=/usr/bin/ccache', '. "$topsrcdir/build/mozconfig.cache"', - 'ac_add_options --disable-elf-hack # --enable-elf-hack conflicts with --enable-profiling', ] whitelist['nightly']['macosx-universal'] += [ 'if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then', 'ac_add_options --with-macbundlename-prefix=Firefox', 'fi', 'mk_add_options MOZ_MAKE_FLAGS="-j12"', 'ac_add_options --with-ccache',
--- a/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -349,53 +349,53 @@ skip-if = e10s skip-if = e10s [browser_dbg_scripts-switching-01.js] skip-if = e10s [browser_dbg_scripts-switching-02.js] skip-if = e10s [browser_dbg_scripts-switching-03.js] skip-if = e10s [browser_dbg_search-autofill-identifier.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-basic-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-03.js] -skip-if = e10s +skip-if = e10s # Bug 1093535 [browser_dbg_search-global-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-global-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-popup-jank.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-sources-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_search-symbols.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-help-popup-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-help-popup-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_searchbox-parse.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_source-maps-01.js] skip-if = e10s && debug [browser_dbg_source-maps-02.js] skip-if = e10s && debug [browser_dbg_source-maps-03.js] skip-if = e10s && debug [browser_dbg_source-maps-04.js] skip-if = e10s # Bug 1093535
--- a/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js +++ b/browser/devtools/debugger/test/browser_dbg_search-autofill-identifier.js @@ -5,17 +5,17 @@ * Tests that Debugger Search uses the identifier under cursor if nothing is * selected or manually passed and searching using certain operators. */ "use strict"; function test() { const TAB_URL = EXAMPLE_URL + "doc_function-search.html"; - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let Source = 'code_function-search-01.js'; let Debugger = aPanel.panelWin; let Editor = Debugger.DebuggerView.editor; let Filtering = Debugger.DebuggerView.Filtering; function doSearch(aOperator) { Editor.dropSelection(); Filtering._doSearch(aOperator);
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-01.js +++ b/browser/devtools/debugger/test/browser_dbg_search-basic-01.js @@ -2,23 +2,22 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests basic search functionality (find token and jump to line). */ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gFiltering, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gFiltering = gDebugger.DebuggerView.Filtering; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceShown(gPanel, ".html").then(performTest); @@ -304,16 +303,15 @@ function performTest() { "The search field has the right initial value (2)."); closeDebuggerAndFinish(gPanel); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gFiltering = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-02.js +++ b/browser/devtools/debugger/test/browser_dbg_search-basic-02.js @@ -2,23 +2,22 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests basic file search functionality. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(performSimpleSearch) .then(() => verifySourceAndCaret("-01.js", 1, 1, [1, 1])) @@ -28,17 +27,17 @@ function test() { .then(() => verifySourceAndCaret("-01.js", 2, 48, [96, 100])) .then(combineWithTokenColonSearch) .then(() => verifySourceAndCaret("-01.js", 2, 11, [56, 63])) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function performSimpleSearch() { let finished = promise.all([ ensureSourceIs(gPanel, "-02.js"), ensureCaretAt(gPanel, 1), waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FILE_SEARCH_MATCH_FOUND), @@ -111,14 +110,13 @@ function verifySourceAndCaret(aUrl, aLin ok(isCaretPos(gPanel, aLine, aColumn), "The current caret position appears to be correct."); ok(isEditorSel(gPanel, aSelection), "The current editor selection appears to be correct."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-03.js +++ b/browser/devtools/debugger/test/browser_dbg_search-basic-03.js @@ -3,23 +3,22 @@ /** * Tests that searches which cause a popup to be shown properly handle the * ESCAPE key. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(performFileSearch) .then(escapeAndHide) @@ -32,17 +31,17 @@ function test() { .then(performGlobalSearch) .then(escapeAndClear) .then(() => verifySourceAndCaret("-01.js", 4, 10)) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function performFileSearch() { let finished = promise.all([ ensureSourceIs(gPanel, "-02.js"), ensureCaretAt(gPanel, 1), once(gDebugger, "popupshown"), @@ -107,14 +106,13 @@ function verifySourceAndCaret(aUrl, aLin ok(gSources.selectedItem.value.contains(aUrl), "The selected item's value appears to be correct."); ok(isCaretPos(gPanel, aLine, aColumn), "The current caret position appears to be correct."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-04.js +++ b/browser/devtools/debugger/test/browser_dbg_search-basic-04.js @@ -3,23 +3,22 @@ /** * Tests that the selection is dropped for line and token searches, after * pressing backspace enough times. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceShown(gPanel, "-01.js") .then(testLineSearch) @@ -118,15 +117,14 @@ function testTokenSearch() { is(gEditor.getSelection(), "", "The editor selected text appears to be correct (2.5)."); is(gSearchBox.value, "", "The searchbox should have been cleared."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-01.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-01.js @@ -3,40 +3,39 @@ /** * Tests basic functionality of global search (lowercase + upper case, expected * UI behavior, number of results found etc.) */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(firstSearch) .then(secondSearch) .then(clearSearch) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function firstSearch() { let deferred = promise.defer(); is(gSearchView.itemCount, 0, "The global search pane shouldn't have any entries yet."); @@ -259,16 +258,15 @@ function clearSearch() { is(gSearchView.widget._parent.hidden, true, "The global search pane shouldn't be visible after clearing."); is(gSearchView._splitter.hidden, true, "The global search pane splitter shouldn't be visible after clearing."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-02.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-02.js @@ -3,23 +3,22 @@ /** * Tests if the global search results switch back and forth, and wrap around * when switching between them. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) @@ -29,17 +28,17 @@ function test() { .then(doWrapAroundJump) .then(doBackwardsWrapAroundJump) .then(testSearchTokenEmpty) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function firstSearch() { let deferred = promise.defer(); is(gSearchView.itemCount, 0, "The global search pane shouldn't have any entries yet."); @@ -203,16 +202,15 @@ function testSearchTokenEmpty() { is(gSearchView.widget._parent.hidden, true, "The global search pane shouldn't be visible after clearing."); is(gSearchView._splitter.hidden, true, "The global search pane splitter shouldn't be visible after clearing."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-03.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-03.js @@ -3,39 +3,38 @@ /** * Tests if the global search results are cleared on location changes, and * the expected UI behaviors are triggered. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(firstSearch) .then(performTest) .then(() => closeDebuggerAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function firstSearch() { let deferred = promise.defer(); is(gSearchView.itemCount, 0, "The global search pane shouldn't have any entries yet."); @@ -91,16 +90,15 @@ function performTest() { deferred.resolve(); }); return deferred.promise; } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-04.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-04.js @@ -3,39 +3,38 @@ /** * Tests if the global search results trigger MatchFound and NoMatchFound events * properly, and triggers the expected UI behavior. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(firstSearch) .then(secondSearch) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function firstSearch() { let deferred = promise.defer(); gDebugger.once(gDebugger.EVENTS.GLOBAL_SEARCH_MATCH_FOUND, () => { // Some operations are synchronously dispatched on the main thread, @@ -79,16 +78,15 @@ function secondSearch() { typeText(gSearchBox, "/"); return deferred.promise; } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-05.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-05.js @@ -4,23 +4,22 @@ /** * Tests if the global search results are expanded/collapsed on click, and * clicking matches makes the source editor shows the correct source and * makes a selection based on the match. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) @@ -28,17 +27,17 @@ function test() { .then(testExpandCollapse) .then(testClickLineToJump) .then(testClickMatchToJump) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function doSearch() { let deferred = promise.defer(); gDebugger.once(gDebugger.EVENTS.GLOBAL_SEARCH_MATCH_FOUND, () => { // Some operations are synchronously dispatched on the main thread, @@ -141,16 +140,15 @@ function testClickMatchToJump() { EventUtils.sendMouseEvent({ type: "click" }, lastMatch); return deferred.promise; } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-global-06.js +++ b/browser/devtools/debugger/test/browser_dbg_search-global-06.js @@ -3,23 +3,22 @@ /** * Tests if the global search results are hidden when they're supposed to * (after a focus lost, or when ESCAPE is pressed). */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchView, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.GlobalSearch; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) @@ -27,17 +26,17 @@ function test() { .then(testFocusLost) .then(doSearch) .then(testEscape) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function doSearch() { let deferred = promise.defer(); is(gSearchView.itemCount, 0, "The global search pane shouldn't have any entries yet."); @@ -106,16 +105,15 @@ function testEscape() { is(gSearchView.widget._parent.hidden, true, "The global search pane shouldn't be visible after clearing."); is(gSearchView._splitter.hidden, true, "The global search pane splitter shouldn't be visible after clearing."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js +++ b/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js @@ -2,23 +2,22 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that sources aren't selected by default when finding a match. */ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; gDebugger.DebuggerView.FilteredSources._autoSelectFirstItem = false; gDebugger.DebuggerView.FilteredFunctions._autoSelectFirstItem = false; waitForSourceShown(gPanel, "-01.js") @@ -106,13 +105,12 @@ function pressKey(aKey) { function pressKeyToHide(aKey) { let finished = waitForResultsHidden(); EventUtils.sendKey(aKey, gDebugger); return finished; } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-sources-01.js +++ b/browser/devtools/debugger/test/browser_dbg_search-sources-01.js @@ -2,26 +2,25 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests basic functionality of sources filtering (file search). */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchView, gSearchBox; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(3); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gSearchView = gDebugger.DebuggerView.FilteredSources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceShown(gPanel, "-01.js") .then(bogusSearch) @@ -221,15 +220,14 @@ function verifyContents(aArgs) { is(gSearchView.itemCount, aArgs.itemCount, "No sources should be displayed in the sources container after a bogus search."); is(gSearchView.hidden, aArgs.hidden, "No sources should be displayed in the sources container after a bogus search."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-sources-02.js +++ b/browser/devtools/debugger/test/browser_dbg_search-sources-02.js @@ -2,26 +2,25 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests more complex functionality of sources filtering (file search). */ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSourceUtils, gSearchView, gSearchBox; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(3); - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gSourceUtils = gDebugger.SourceUtils; gSearchView = gDebugger.DebuggerView.FilteredSources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceShown(gPanel, "-01.js") @@ -263,16 +262,15 @@ function verifyContents(aMatches) { "The filtered sources view should have the correct source labels."); ok(gSearchView.widget._parent.querySelector(".results-panel-item-label-below[value=\"" + trimmedLocation + "\"]"), "The filtered sources view should have the correct source locations."); } } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; gSourceUtils = null; gSearchView = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-sources-03.js +++ b/browser/devtools/debugger/test/browser_dbg_search-sources-03.js @@ -2,23 +2,22 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that while searching for files, the sources list remains unchanged. */ const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSources, gSearchBox; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; waitForSourceShown(gPanel, "-01.js") .then(superGenericSearch) .then(verifySourcesPane) @@ -87,14 +86,13 @@ function verifySourcesPane() { ok(gSources.getItemForAttachment(e => e.label == "code_test-editor-mode"), "The second source's label should be correct."); ok(gSources.getItemForAttachment(e => e.label == "doc_editor-mode.html"), "The third source's label should be correct."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSources = null; gSearchBox = null; });
--- a/browser/devtools/debugger/test/browser_dbg_search-symbols.js +++ b/browser/devtools/debugger/test/browser_dbg_search-symbols.js @@ -2,23 +2,22 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests if the function searching works properly. */ const TAB_URL = EXAMPLE_URL + "doc_function-search.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSources, gSearchBox, gFilteredFunctions; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSources = gDebugger.DebuggerView.Sources; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; gFilteredFunctions = gDebugger.DebuggerView.FilteredFunctions; waitForSourceShown(gPanel, "-01.js") @@ -454,16 +453,15 @@ function saveSearch() { function writeInfo() { info("Current source url:\n" + gSources.selectedValue); info("Debugger editor text:\n" + gEditor.getText()); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSources = null; gSearchBox = null; gFilteredFunctions = null; });
--- a/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js +++ b/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-01.js @@ -3,37 +3,36 @@ /** * Make sure that the searchbox popup is displayed when focusing the searchbox, * and hidden when the user starts typing. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gSearchBox, gSearchBoxPanel; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; gSearchBoxPanel = gDebugger.DebuggerView.Filtering._searchboxHelpPanel; waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1) .then(showPopup) .then(hidePopup) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function showPopup() { is(gSearchBoxPanel.state, "closed", "The search box panel shouldn't be visible yet."); let finished = once(gSearchBoxPanel, "popupshown"); @@ -47,14 +46,13 @@ function hidePopup() { let finished = once(gSearchBoxPanel, "popuphidden"); setText(gSearchBox, "#"); return finished; } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gSearchBox = null; gSearchBoxPanel = null; });
--- a/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js +++ b/browser/devtools/debugger/test/browser_dbg_searchbox-help-popup-02.js @@ -3,23 +3,22 @@ /** * Make sure that the searchbox popup isn't displayed when there's some text * already present. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gEditor, gSearchBox, gSearchBoxPanel; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gEditor = gDebugger.DebuggerView.editor; gSearchBox = gDebugger.DebuggerView.Filtering._searchbox; gSearchBoxPanel = gDebugger.DebuggerView.Filtering._searchboxHelpPanel; once(gSearchBoxPanel, "popupshown").then(() => { ok(false, "Damn it, this shouldn't have happened."); @@ -29,17 +28,17 @@ function test() { .then(tryShowPopup) .then(focusEditor) .then(testFocusLost) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); - gDebuggee.firstCall(); + callInTab(gTab, "firstCall"); }); } function tryShowPopup() { setText(gSearchBox, "#call()"); ok(isCaretPos(gPanel, 4, 22), "The editor caret position appears to be correct."); ok(isEditorSel(gPanel, [125, 131]), @@ -72,15 +71,14 @@ function testFocusLost() { "The editor selected text appears to be correct after gaining focus."); is(gSearchBoxPanel.state, "closed", "The search box panel should still not be visible."); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gEditor = null; gSearchBox = null; gSearchBoxPanel = null; });
--- a/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js +++ b/browser/devtools/debugger/test/browser_dbg_searchbox-parse.js @@ -1,17 +1,17 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that text entered in the debugger's searchbox is properly parsed. */ function test() { - initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => { + initDebugger("about:blank").then(([aTab,, aPanel]) => { let filterView = aPanel.panelWin.DebuggerView.Filtering; let searchbox = aPanel.panelWin.DebuggerView.Filtering._searchbox; setText(searchbox, ""); is(filterView.searchData.toSource(), '["", [""]]', "The searchbox data wasn't parsed correctly (1)."); setText(searchbox, "#token");
--- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -125,19 +125,16 @@ DEFINES += -DAB=$(AB) DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_VERSION) ifdef MOZ_NATIVE_ICU DEFINES += -DMOZ_NATIVE_ICU endif ifdef MOZ_SHARED_ICU DEFINES += -DMOZ_SHARED_ICU endif -ifdef MOZ_REPLACE_MALLOC -DEFINES += -DMOZ_REPLACE_MALLOC -endif ifdef MOZ_JEMALLOC3 DEFINES += -DMOZ_JEMALLOC3 endif DEFINES += -DMOZ_ICU_DBG_SUFFIX=$(MOZ_ICU_DBG_SUFFIX) ifdef CLANG_CXX DEFINES += -DCLANG_CXX endif ifdef CLANG_CL
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -172,17 +172,16 @@ @BINPATH@/AccessibleMarshal.dll #endif @BINPATH@/components/accessibility.xpt #endif @BINPATH@/components/appshell.xpt @BINPATH@/components/appstartup.xpt @BINPATH@/components/autocomplete.xpt @BINPATH@/components/autoconfig.xpt -@BINPATH@/components/browser-element.xpt @BINPATH@/browser/components/browsercompsbase.xpt @BINPATH@/browser/components/browser-feeds.xpt @BINPATH@/components/caps.xpt @BINPATH@/components/chrome.xpt @BINPATH@/components/commandhandler.xpt @BINPATH@/components/commandlines.xpt @BINPATH@/components/composer.xpt @BINPATH@/components/content_events.xpt
--- a/browser/themes/shared/devtools/dark-theme.css +++ b/browser/themes/shared/devtools/dark-theme.css @@ -98,17 +98,17 @@ } .CodeMirror-Tern-completion-object:before { background-color: #3689b2; } .cm-s-mozilla .cm-unused-line { text-decoration: line-through; - -moz-text-decoration-color: #5f88b0; + text-decoration-color: #5f88b0; } .cm-s-mozilla .cm-executed-line { background-color: #133c26; } .theme-fg-color3, .cm-s-mozilla .cm-builtin,
--- a/browser/themes/shared/devtools/light-theme.css +++ b/browser/themes/shared/devtools/light-theme.css @@ -71,17 +71,17 @@ } .theme-separator { /* grey */ border-color: #cddae5; } .cm-s-mozilla .cm-unused-line { text-decoration: line-through; - -moz-text-decoration-color: #5f88b0; + text-decoration-color: #5f88b0; } .cm-s-mozilla .cm-executed-line { background-color: #fcfffc; } .theme-fg-color1, .cm-s-mozilla .cm-number,
--- a/browser/themes/shared/devtools/ruleview.css +++ b/browser/themes/shared/devtools/ruleview.css @@ -193,17 +193,17 @@ } } .ruleview-overridden { text-decoration: line-through; } .theme-light .ruleview-overridden { - -moz-text-decoration-color: #667380; /* Content (Text) - Dark Grey */ + text-decoration-color: #667380; /* Content (Text) - Dark Grey */ } .styleinspector-propertyeditor { border: 1px solid #CCC; padding: 0; } .ruleview-property {
--- a/configure.in +++ b/configure.in @@ -7156,16 +7156,17 @@ if test "$NS_TRACE_MALLOC" -a "$MOZ_REPL AC_MSG_ERROR([--enable-trace-malloc and --enable-replace-malloc are conflicting options]) fi if test -n "$MOZ_REPLACE_MALLOC" -a -z "$MOZ_MEMORY"; then dnl We don't want to enable jemalloc unconditionally because it may be a dnl deliberate choice not to enable it (bug 702250, for instance) AC_MSG_ERROR([--enable-replace-malloc requires --enable-jemalloc]) elif test -n "$MOZ_REPLACE_MALLOC"; then + AC_DEFINE(MOZ_REPLACE_MALLOC) MOZ_NATIVE_JEMALLOC= dnl Replace-malloc Mac linkage quirks if test -n "$MACOSX_DEPLOYMENT_TARGET"; then AC_CACHE_CHECK([how to do weak dynamic linking], ac_cv_weak_dynamic_linking, [echo 'extern void foo() __attribute__((weak_import));int bar() { if (foo) foo(); return 0; }' > conftest.c if AC_TRY_COMMAND([${CC-cc} -o conftest${DLL_SUFFIX} $CFLAGS -dynamiclib $LDFLAGS -Wl,-U,_foo conftest.c $LIBS 1>&5]) && @@ -7378,27 +7379,17 @@ MOZ_ARG_ENABLE_BOOL(install-strip, dnl ======================================================== dnl = --disable-elf-hack dnl ======================================================== USE_ELF_HACK=1 MOZ_ARG_DISABLE_BOOL(elf-hack, [ --disable-elf-hack Disable elf hacks], [USE_ELF_HACK=], - [USE_ELF_HACK=F # Force enable elf-hack]) - -# Disable elf hack for profiling because the built in profiler -# doesn't read the segments properly with elf hack. This is -# temporary and should be fixed soon in the profiler. -if test "$MOZ_PROFILING" = 1; then - if test "$USE_ELF_HACK" = F; then - AC_ERROR([--enable-elf-hack is not compatible with --enable-profiling]) - fi - USE_ELF_HACK= -fi + [USE_ELF_HACK=1]) # Only enable elfhack where supported if test "$USE_ELF_HACK" = 1; then case "${HOST_OS_ARCH},${OS_ARCH}" in Linux,Linux) case "${CPU_ARCH}" in arm | x86 | x86_64) USE_ELF_HACK=1
deleted file mode 100644 --- a/dom/apps/tests/file_test_widget.js +++ /dev/null @@ -1,231 +0,0 @@ -var gWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=widget&getmanifest=true'; -var gInvalidWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=invalidWidget&getmanifest=true'; -var gApp; -var gHasBrowserPermission; - -function onError() { - ok(false, "Error callback invoked"); - finish(); -} - -function installApp(path) { - var request = navigator.mozApps.install(path); - request.onerror = onError; - request.onsuccess = function() { - gApp = request.result; - - runTest(); - } -} - -function uninstallApp() { - // Uninstall the app. - var request = navigator.mozApps.mgmt.uninstall(gApp); - request.onerror = onError; - request.onsuccess = function() { - // All done. - info("All done"); - - runTest(); - } -} - -function testApp(isValidWidget) { - info("Test widget feature. IsValidWidget: " + isValidWidget); - - var ifr = document.createElement('iframe'); - ifr.setAttribute('mozbrowser', 'true'); - ifr.setAttribute('mozwidget', gApp.manifestURL); - ifr.setAttribute('src', gApp.origin+gApp.manifest.launch_path); - - var domParent = document.getElementById('container'); - domParent.appendChild(ifr); - - var mm = SpecialPowers.getBrowserFrameMessageManager(ifr); - mm.addMessageListener('OK', function(msg) { - ok(isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json); - }); - mm.addMessageListener('KO', function(msg) { - ok(!isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json); - }); - mm.addMessageListener('DONE', function(msg) { - ok(true, "Message from widget complete: "+SpecialPowers.wrap(msg).json); - domParent.removeChild(ifr); - runTest(); - }); - - ifr.addEventListener('mozbrowserloadend', function() { - ok(true, "receive mozbrowserloadend"); - - // Test limited browser API feature only for valid widget case - if (isValidWidget) { - testLimitedBrowserAPI(ifr); - } - SimpleTest.executeSoon(()=>loadFrameScript(mm)); - }, false); - - // Test limited browser API feature only for valid widget case - if (!isValidWidget) { - return; - } - - [ - 'mozbrowsertitlechange', - 'mozbrowseropenwindow', - 'mozbrowserscroll', - 'mozbrowserasyncscroll' - ].forEach( function(topic) { - ifr.addEventListener(topic, function() { - ok(false, topic + " should be hidden"); - }, false); - }); -} - -function testLimitedBrowserAPI(ifr) { - var securitySensitiveCalls = [ - { api: 'sendMouseEvent' , args: ['mousedown', 0, 0, 0, 0, 0] }, - { api: 'sendTouchEvent' , args: ['touchstart', [0], [0], [0], [1], [1], [0], [1], 1, 0] }, - { api: 'goBack' , args: [] }, - { api: 'goForward' , args: [] }, - { api: 'reload' , args: [] }, - { api: 'stop' , args: [] }, - { api: 'download' , args: ['http://example.org'] }, - { api: 'purgeHistory' , args: [] }, - { api: 'getScreenshot' , args: [0, 0] }, - { api: 'zoom' , args: [0.1] }, - { api: 'getCanGoBack' , args: [] }, - { api: 'getCanGoForward' , args: [] }, - { api: 'getContentDimensions', args: [] } - ]; - securitySensitiveCalls.forEach( function(call) { - if (gHasBrowserPermission) { - isnot(typeof ifr[call.api], "undefined", call.api + " should be defined"); - var didThrow; - try { - ifr[call.api].apply(ifr, call.args); - } catch (e) { - ok(e instanceof DOMException, "throw right exception type"); - didThrow = e.code; - } - is(didThrow, DOMException.INVALID_NODE_TYPE_ERR, "call " + call.api + " should throw exception"); - } else { - is(typeof ifr[call.api], "undefined", call.api + " should be hidden for widget"); - } - }); -} - -function loadFrameScript(mm) { - var script = 'data:,\ - function ok(p, msg) { \ - if (p) { \ - sendAsyncMessage("OK", msg); \ -} else { \ - sendAsyncMessage("KO", msg); \ -} \ -} \ - \ - function is(a, b, msg) { \ - if (a == b) { \ - sendAsyncMessage("OK", a + " == " + b + " - " + msg); \ -} else { \ - sendAsyncMessage("KO", a + " != " + b + " - " + msg); \ -} \ -} \ - \ - function finish() { \ - sendAsyncMessage("DONE",""); \ -} \ - \ - function onError() { \ - ok(false, "Error callback invoked"); \ - finish(); \ -} \ - \ - function checkWidget(widget) { \ - /*For invalid widget case, ignore the following check*/\ - if (widget) { \ - var widgetName = "Really Rapid Release (APPTYPETOKEN)"; \ - is(widget.origin, "http://test", "Widget origin should be correct"); \ - is(widget.installOrigin, "http://mochi.test:8888", "Install origin should be correct"); \ -} \ - finish(); \ -} \ - \ - var request = content.window.navigator.mozApps.getSelf(); \ - request.onsuccess = function() { \ - var widget = request.result; \ - ok(widget,"Should be a widget"); \ - checkWidget(widget); \ -}; \ - request.onerror = onError; \ - content.window.open("about:blank"); /*test mozbrowseropenwindow*/ \ - content.window.scrollTo(4000, 4000); /*test mozbrowser(async)scroll*/ \ - '; - mm.loadFrameScript(script, /* allowDelayedLoad = */ false); -} - -var tests = [ - // Permissions - function() { - SpecialPowers.pushPermissions( - [{ "type": "browser", "allow": gHasBrowserPermission ? 1 : 0, "context": document }, - { "type": "embed-widgets", "allow": 1, "context": document }, - { "type": "webapps-manage", "allow": 1, "context": document }], runTest); - }, - - // Preferences - function() { - SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true], - ["dom.enable_widgets", true], - ["dom.datastore.sysMsgOnChangeShortTimeoutSec", 1], - ["dom.datastore.sysMsgOnChangeLongTimeoutSec", 3]]}, runTest); - }, - - function() { - if (SpecialPowers.isMainProcess()) { - SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm"); - } - - SpecialPowers.setAllAppsLaunchable(true); - runTest(); - }, - - // No confirmation needed when an app is installed - function() { - SpecialPowers.autoConfirmAppInstall(() => { - SpecialPowers.autoConfirmAppUninstall(runTest); - }); - }, - - // Installing the app - ()=>installApp(gWidgetManifestURL), - - // Run tests in app - ()=>testApp(true), - - // Uninstall the app - uninstallApp, - - // Installing the app for invalid widget case - ()=>installApp(gInvalidWidgetManifestURL), - - // Run tests in app for invalid widget case - ()=>testApp(false), - - // Uninstall the app - uninstallApp -]; - -function runTest() { - if (!tests.length) { - finish(); - return; - } - - var test = tests.shift(); - test(); -} - -function finish() { - SimpleTest.finish(); -}
--- a/dom/apps/tests/mochitest.ini +++ b/dom/apps/tests/mochitest.ini @@ -12,17 +12,16 @@ support-files = file_manifest.json^headers^ file_trusted_app.template.webapp file_invalidWidget_app.template.webapp file_packaged_app.sjs file_packaged_app.template.html file_packaged_app.template.webapp file_widget_app.template.webapp file_widget_app.template.html - file_test_widget.js signed_app.sjs signed_app_template.webapp signed/* test_packaged_app_common.js marketplace/* pkg_install_iframe.html [test_app_enabled.html] @@ -40,10 +39,8 @@ skip-if = (toolkit == 'android' && proce skip-if = (toolkit == 'android' && processor == 'x86') #x86 only [test_receipt_operations.html] [test_signed_pkg_install.html] [test_uninstall_errors.html] [test_theme_role.html] [test_web_app_install.html] [test_widget.html] skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app -[test_widget_browser.html] -skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
--- a/dom/apps/tests/test_widget.html +++ b/dom/apps/tests/test_widget.html @@ -1,18 +1,235 @@ <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Test for DataStore - basic operation on a readonly db</title> <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript" src="file_test_widget.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <body> <div id="container"></div> <script type="application/javascript;version=1.7"> + + var gWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=widget&getmanifest=true'; + var gInvalidWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=invalidWidget&getmanifest=true'; + var gApp; + + function onError() { + ok(false, "Error callback invoked"); + finish(); + } + + function installApp(path) { + var request = navigator.mozApps.install(path); + request.onerror = onError; + request.onsuccess = function() { + gApp = request.result; + + runTest(); + } + } + + function uninstallApp() { + // Uninstall the app. + var request = navigator.mozApps.mgmt.uninstall(gApp); + request.onerror = onError; + request.onsuccess = function() { + // All done. + info("All done"); + + runTest(); + } + } + + function testApp(isValidWidget) { + info("Test widget feature. IsValidWidget: " + isValidWidget); + + var ifr = document.createElement('iframe'); + ifr.setAttribute('mozbrowser', 'true'); + ifr.setAttribute('mozwidget', gApp.manifestURL); + ifr.setAttribute('src', gApp.origin+gApp.manifest.launch_path); + + var domParent = document.getElementById('container'); + domParent.appendChild(ifr); + + var mm = SpecialPowers.getBrowserFrameMessageManager(ifr); + mm.addMessageListener('OK', function(msg) { + ok(isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json); + }); + mm.addMessageListener('KO', function(msg) { + ok(!isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json); + }); + mm.addMessageListener('DONE', function(msg) { + ok(true, "Message from widget complete: "+SpecialPowers.wrap(msg).json); + domParent.removeChild(ifr); + runTest(); + }); + + ifr.addEventListener('mozbrowserloadend', function() { + ok(true, "receive mozbrowserloadend"); + + // Test limited browser API feature only for valid widget case + if (isValidWidget) { + testLimitedBrowserAPI(ifr); + } + SimpleTest.executeSoon(()=>loadFrameScript(mm)); + }, false); + + // Test limited browser API feature only for valid widget case + if (!isValidWidget) { + return; + } + + [ + 'mozbrowsertitlechange', + 'mozbrowseropenwindow', + 'mozbrowserscroll', + 'mozbrowserasyncscroll' + ].forEach( function(topic) { + ifr.addEventListener(topic, function() { + ok(false, topic + " should be hidden"); + }, false); + }); + } + + function testLimitedBrowserAPI(ifr) { + var securitySensitiveCalls = [ + 'sendMouseEvent', + 'sendTouchEvent', + 'goBack', + 'goForward', + 'reload', + 'stop', + 'download', + 'purgeHistory', + 'getScreenshot', + 'zoom', + 'getCanGoBack', + 'getCanGoForward' + ]; + securitySensitiveCalls.forEach( function(call) { + is(typeof ifr[call], "undefined", call + " should be hidden for widget"); + }); + } + + function loadFrameScript(mm) { + var script = 'data:,\ + function ok(p, msg) { \ + if (p) { \ + sendAsyncMessage("OK", msg); \ + } else { \ + sendAsyncMessage("KO", msg); \ + } \ + } \ + \ + function is(a, b, msg) { \ + if (a == b) { \ + sendAsyncMessage("OK", a + " == " + b + " - " + msg); \ + } else { \ + sendAsyncMessage("KO", a + " != " + b + " - " + msg); \ + } \ + } \ + \ + function finish() { \ + sendAsyncMessage("DONE",""); \ + } \ + \ + function onError() { \ + ok(false, "Error callback invoked"); \ + finish(); \ + } \ + \ + function checkWidget(widget) { \ + /*For invalid widget case, ignore the following check*/\ + if (widget) { \ + var widgetName = "Really Rapid Release (APPTYPETOKEN)"; \ + is(widget.origin, "http://test", "Widget origin should be correct"); \ + is(widget.installOrigin, "http://mochi.test:8888", "Install origin should be correct"); \ + } \ + finish(); \ + } \ + \ + var request = content.window.navigator.mozApps.getSelf(); \ + request.onsuccess = function() { \ + var widget = request.result; \ + ok(widget,"Should be a widget"); \ + checkWidget(widget); \ + }; \ + request.onerror = onError; \ + content.window.open("about:blank"); /*test mozbrowseropenwindow*/ \ + content.window.scrollTo(4000, 4000); /*test mozbrowser(async)scroll*/ \ + '; + mm.loadFrameScript(script, /* allowDelayedLoad = */ false); + } + + var tests = [ + // Permissions + function() { + SpecialPowers.pushPermissions( + [{ "type": "browser", "allow": 1, "context": document }, + { "type": "embed-widgets", "allow": 1, "context": document }, + { "type": "webapps-manage", "allow": 1, "context": document }], runTest); + }, + + // Preferences + function() { + SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true], + ["dom.enable_widgets", true], + ["dom.datastore.sysMsgOnChangeShortTimeoutSec", 1], + ["dom.datastore.sysMsgOnChangeLongTimeoutSec", 3]]}, runTest); + }, + + function() { + if (SpecialPowers.isMainProcess()) { + SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm"); + } + + SpecialPowers.setAllAppsLaunchable(true); + runTest(); + }, + + // No confirmation needed when an app is installed + function() { + SpecialPowers.autoConfirmAppInstall(() => { + SpecialPowers.autoConfirmAppUninstall(runTest); + }); + }, + + // Installing the app + ()=>installApp(gWidgetManifestURL), + + // Run tests in app + ()=>testApp(true), + + // Uninstall the app + uninstallApp, + + // Installing the app for invalid widget case + ()=>installApp(gInvalidWidgetManifestURL), + + // Run tests in app for invalid widget case + ()=>testApp(false), + + // Uninstall the app + uninstallApp + ]; + + function runTest() { + if (!tests.length) { + finish(); + return; + } + + var test = tests.shift(); + test(); + } + + function finish() { + SimpleTest.finish(); + } + SimpleTest.waitForExplicitFinish(); - gHasBrowserPermission = false; runTest(); </script> </body> </html>
deleted file mode 100644 --- a/dom/apps/tests/test_widget_browser.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <meta charset="utf-8"> - <title>Test for DataStore - basic operation on a readonly db</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript" src="file_test_widget.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<div id="container"></div> - <script type="application/javascript;version=1.7"> - SimpleTest.waitForExplicitFinish(); - gHasBrowserPermission = true; - runTest(); - </script> -</body> -</html>
--- a/dom/base/EventSource.cpp +++ b/dom/base/EventSource.cpp @@ -57,17 +57,16 @@ namespace dom { EventSource::EventSource(nsPIDOMWindow* aOwnerWindow) : DOMEventTargetHelper(aOwnerWindow), mStatus(PARSE_STATE_OFF), mFrozen(false), mErrorLoadOnRedirect(false), mGoingToDispatchAllMessages(false), mWithCredentials(false), mWaitingForOnStopRequest(false), - mInterrupted(false), mLastConvertionResult(NS_OK), mReadyState(CONNECTING), mScriptLine(0), mInnerWindowID(0) { } EventSource::~EventSource() @@ -336,39 +335,40 @@ EventSource::OnStartRequest(nsIRequest * nsISupports *ctxt) { nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest, &rv); NS_ENSURE_SUCCESS(rv, rv); - bool requestSucceeded; - rv = httpChannel->GetRequestSucceeded(&requestSucceeded); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString contentType; - rv = httpChannel->GetContentType(contentType); + nsresult status; + rv = aRequest->GetStatus(&status); NS_ENSURE_SUCCESS(rv, rv); - nsresult status; - aRequest->GetStatus(&status); - - if (NS_FAILED(status) || !requestSucceeded || - !contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { - DispatchFailConnection(); - return NS_ERROR_NOT_AVAILABLE; + if (NS_FAILED(status)) { + // EventSource::OnStopRequest will evaluate if it shall either reestablish + // or fail the connection + return NS_ERROR_ABORT; } uint32_t httpStatus; rv = httpChannel->GetResponseStatus(&httpStatus); NS_ENSURE_SUCCESS(rv, rv); if (httpStatus != 200) { - mInterrupted = true; + DispatchFailConnection(); + return NS_ERROR_ABORT; + } + + nsAutoCString contentType; + rv = httpChannel->GetContentType(contentType); + NS_ENSURE_SUCCESS(rv, rv); + + if (!contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { DispatchFailConnection(); return NS_ERROR_ABORT; } nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::AnnounceConnection); NS_ENSURE_STATE(event); @@ -449,40 +449,48 @@ EventSource::OnStopRequest(nsIRequest *a nsresult aStatusCode) { mWaitingForOnStopRequest = false; if (mReadyState == CLOSED) { return NS_ERROR_ABORT; } - if (NS_FAILED(aStatusCode)) { + // "Network errors that prevents the connection from being established in the + // first place (e.g. DNS errors), must cause the user agent to asynchronously + // reestablish the connection. + // + // (...) the cancelation of the fetch algorithm by the user agent (e.g. in + // response to window.stop() or the user canceling the network connection + // manually) must cause the user agent to fail the connection. + + if (NS_FAILED(aStatusCode) && + aStatusCode != NS_ERROR_CONNECTION_REFUSED && + aStatusCode != NS_ERROR_NET_TIMEOUT && + aStatusCode != NS_ERROR_NET_RESET && + aStatusCode != NS_ERROR_NET_INTERRUPT && + aStatusCode != NS_ERROR_PROXY_CONNECTION_REFUSED && + aStatusCode != NS_ERROR_DNS_LOOKUP_QUEUE_FULL) { DispatchFailConnection(); - return aStatusCode; + return NS_ERROR_ABORT; } - nsresult rv; - nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest); - if (NS_SUCCEEDED(healthOfRequestResult) && - mLastConvertionResult == NS_PARTIAL_MORE_INPUT) { - // we had an incomplete UTF8 char at the end of the stream - rv = ParseCharacter(REPLACEMENT_CHAR); - NS_ENSURE_SUCCESS(rv, rv); - } + nsresult rv = CheckHealthOfRequestCallback(aRequest); + NS_ENSURE_SUCCESS(rv, rv); ClearFields(); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::ReestablishConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event); NS_ENSURE_SUCCESS(rv, rv); - return healthOfRequestResult; + return NS_OK; } /** * Simple helper class that just forwards the redirect callback back * to the EventSource. */ class AsyncVerifyRedirectCallbackFwr MOZ_FINAL : public nsIAsyncVerifyRedirectCallback { @@ -864,21 +872,16 @@ EventSource::ResetConnection() void EventSource::ReestablishConnection() { if (mReadyState == CLOSED) { return; } - if (mReadyState != OPEN) { - NS_WARNING("Unexpected mReadyState!!!"); - return; - } - nsresult rv = ResetConnection(); if (NS_FAILED(rv)) { NS_WARNING("Failed to reset the connection!!!"); return; } rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { @@ -989,17 +992,17 @@ EventSource::ConsoleError() { nsAutoCString targetSpec; nsresult rv = mSrc->GetSpec(targetSpec); NS_ENSURE_SUCCESS(rv, rv); NS_ConvertUTF8toUTF16 specUTF16(targetSpec); const char16_t *formatStrings[] = { specUTF16.get() }; - if (mReadyState == CONNECTING && !mInterrupted) { + if (mReadyState == CONNECTING) { rv = PrintErrorOnConsole("chrome://global/locale/appstrings.properties", MOZ_UTF16("connectionFailure"), formatStrings, ArrayLength(formatStrings)); } else { rv = PrintErrorOnConsole("chrome://global/locale/appstrings.properties", MOZ_UTF16("netInterrupt"), formatStrings, ArrayLength(formatStrings)); }
--- a/dom/base/EventSource.h +++ b/dom/base/EventSource.h @@ -216,17 +216,16 @@ protected: }; ParserStatus mStatus; bool mFrozen; bool mErrorLoadOnRedirect; bool mGoingToDispatchAllMessages; bool mWithCredentials; bool mWaitingForOnStopRequest; - bool mInterrupted; // used while reading the input streams nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder; nsresult mLastConvertionResult; nsString mLastFieldName; nsString mLastFieldValue; nsCOMPtr<nsILoadGroup> mLoadGroup;
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -14089,18 +14089,22 @@ nsGlobalWindow::GetSidebar(OwningExterna aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); #endif } void nsGlobalWindow::ClearDocumentDependentSlots(JSContext* aCx) { MOZ_ASSERT(IsInnerWindow()); - WindowBinding::ClearCachedDocumentValue(aCx, this); - WindowBinding::ClearCachedPerformanceValue(aCx, this); + + // If JSAPI OOMs here, there is basically nothing we can do to recover safely. + if (!WindowBinding::ClearCachedDocumentValue(aCx, this) || + !WindowBinding::ClearCachedPerformanceValue(aCx, this)) { + MOZ_CRASH("Unhandlable OOM while clearing document dependent slots."); + } } /* static */ JSObject* nsGlobalWindow::CreateNamedPropertiesObject(JSContext *aCx, JS::Handle<JSObject*> aProto) { return WindowNamedPropertiesHandler::Create(aCx, aProto);
--- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -177,17 +177,17 @@ nsImageLoadingContent::Notify(imgIReques = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); nsIDocument *doc = GetOurOwnerDoc(); doc->AddBlockedTrackingNode(thisNode); } } nsresult status = reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; - return OnStopRequest(aRequest, status); + return OnLoadComplete(aRequest, status); } if (aType == imgINotificationObserver::DECODE_COMPLETE) { if (mFireEventsOnDecode) { mFireEventsOnDecode = false; uint32_t reqStatus; aRequest->GetImageStatus(&reqStatus); @@ -200,18 +200,17 @@ nsImageLoadingContent::Notify(imgIReques UpdateImageState(true); } return NS_OK; } nsresult -nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, - nsresult aStatus) +nsImageLoadingContent::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus) { uint32_t oldStatus; aRequest->GetImageStatus(&oldStatus); //XXXjdm This occurs when we have a pending request created, then another // pending request replaces it before the first one is finished. // This begs the question of what the correct behaviour is; we used // to not have to care because we ran this code in OnStopDecode which
--- a/dom/base/nsImageLoadingContent.h +++ b/dom/base/nsImageLoadingContent.h @@ -204,17 +204,17 @@ protected: */ virtual mozilla::CORSMode GetCORSMode(); // Subclasses are *required* to call BindToTree/UnbindFromTree. void BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); void UnbindFromTree(bool aDeep, bool aNullParent); - nsresult OnStopRequest(imgIRequest* aRequest, nsresult aStatus); + nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus); void OnUnlockedDraw(); nsresult OnImageIsAnimated(imgIRequest *aRequest); // The nsContentPolicyType we would use for this ImageLoadType static nsContentPolicyType PolicyTypeForLoad(ImageLoadType aImageLoadType); private: /**
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2407,24 +2407,16 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::G nsCycleCollector_dispatchDeferredDeletion(); } if (sPrevGCSliceCallback) (*sPrevGCSliceCallback)(aRt, aProgress, aDesc); } void -nsJSContext::ReportPendingException() -{ - if (mIsInitialized) { - nsJSUtils::ReportPendingException(mContext); - } -} - -void nsJSContext::SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) { mWindowProxy = aWindowProxy; } JSObject* nsJSContext::GetWindowProxy() {
--- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -141,21 +141,16 @@ protected: // Helper to convert xpcom datatypes to jsvals. nsresult ConvertSupportsTojsvals(nsISupports *aArgs, JS::Handle<JSObject*> aScope, JS::AutoValueVector &aArgsOut); nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv); - // Report the pending exception on our mContext, if any. This - // function will set aside the frame chain on mContext before - // reporting. - void ReportPendingException(); - private: void DestroyJSContext(); nsrefcnt GetCCRefcnt(); JSContext *mContext; JS::Heap<JSObject*> mWindowProxy;
--- a/dom/base/nsNodeInfoManager.cpp +++ b/dom/base/nsNodeInfoManager.cpp @@ -23,16 +23,17 @@ #include "nsReadableUtils.h" #include "nsGkAtoms.h" #include "nsComponentManagerUtils.h" #include "nsLayoutStatics.h" #include "nsBindingManager.h" #include "nsHashKeys.h" #include "nsCCUncollectableMarker.h" #include "nsNameSpaceManager.h" +#include "nsDocument.h" using namespace mozilla; using mozilla::dom::NodeInfo; #include "prlog.h" #ifdef PR_LOGGING static PRLogModuleInfo* gNodeInfoManagerLeakPRLog; @@ -148,30 +149,43 @@ nsNodeInfoManager::~nsNodeInfoManager() nsLayoutStatics::Release(); } NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager) NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfoManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager) - if (tmp->mDocument && - nsCCUncollectableMarker::InGeneration(cb, - tmp->mDocument->GetMarkedCCGeneration())) { - return NS_SUCCESS_INTERRUPTED_TRAVERSE; - } if (tmp->mNonDocumentNodeInfos) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBindingManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release) +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsNodeInfoManager) + if (tmp->mDocument) { + return NS_CYCLE_COLLECTION_PARTICIPANT(nsDocument)->CanSkip(tmp->mDocument, aRemovingAllowed); + } +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsNodeInfoManager) + if (tmp->mDocument) { + return NS_CYCLE_COLLECTION_PARTICIPANT(nsDocument)->CanSkipInCC(tmp->mDocument); + } +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsNodeInfoManager) + if (tmp->mDocument) { + return NS_CYCLE_COLLECTION_PARTICIPANT(nsDocument)->CanSkipThis(tmp->mDocument); + } +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + nsresult nsNodeInfoManager::Init(nsIDocument *aDocument) { NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY); NS_PRECONDITION(!mPrincipal, "Being inited when we already have a principal?"); nsresult rv;
--- a/dom/base/nsNodeInfoManager.h +++ b/dom/base/nsNodeInfoManager.h @@ -35,17 +35,17 @@ class NodeInfo; class nsNodeInfoManager MOZ_FINAL { private: ~nsNodeInfoManager(); public: nsNodeInfoManager(); - NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsNodeInfoManager) + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_NATIVE_CLASS(nsNodeInfoManager) NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsNodeInfoManager) /** * Initialize the nodeinfo manager with a document. */ nsresult Init(nsIDocument *aDocument);
--- a/dom/base/test/test_bug338583.html +++ b/dom/base/test/test_bug338583.html @@ -348,39 +348,39 @@ https://bugzilla.mozilla.org/show_bug.cg ok(gEventSourceObj3_g.hits['fn_onmessage'] == 0, "Test 3.g failed"); gEventSourceObj3_g.close(); setTestHasFinished(test_id); }, parseInt(1500*stress_factor)); } function fnMessageListenerTest3h(e) { fnMessageListenerTest3h.msg_ok = (fnMessageListenerTest3h.msg_ok && e.data == "ok"); - fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.msg_ok && e.lastEventId == ""); + fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.id_ok && e.lastEventId == ""); } function doTest3_h(test_id) { gEventSourceObj3_h = new EventSource("badMessageEvent2.eventsource"); - gEventSourceObj3_h.addEventListener('message event', fnMessageListenerTest3h, true); + gEventSourceObj3_h.addEventListener('message', fnMessageListenerTest3h, true); fnMessageListenerTest3h.msg_ok = true; fnMessageListenerTest3h.id_ok = true; gEventSourceObj3_h.onmessage = fn_onmessage; gEventSourceObj3_h.hits = []; gEventSourceObj3_h.hits['fn_onmessage'] = 0; setTimeout(function() { ok(gEventSourceObj3_h.hits['fn_onmessage'] > 1, "Test 3.h.1 failed"); if (gEventSourceObj3_h.hits['fn_onmessage'] > 1) { ok(fnMessageListenerTest3h.msg_ok, "Test 3.h.2 failed"); ok(fnMessageListenerTest3h.id_ok, "Test 3.h.3 failed"); } gEventSourceObj3_h.close(); setTestHasFinished(test_id); - }, parseInt(3000*stress_factor)); + }, parseInt(6000*stress_factor)); } // in order to test (4) // a) close the object when it is in use, which is being processed and that is expected // to dispatch more eventlisteners // b) remove an eventlistener in use function fn_onmessage4_a(e)
--- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -3469,17 +3469,16 @@ class CGClearCachedValueMethod(CGAbstrac slotIndex) regetMember = fill( """ JS::Rooted<JS::Value> temp(aCx); JSJitGetterCallArgs args(&temp); JSAutoCompartment ac(aCx, obj); if (!get_${name}(aCx, obj, aObject, args)) { js::SetReservedSlot(obj, ${slotIndex}, oldValue); - nsJSUtils::ReportPendingException(aCx); return false; } return true; """, name=self.member.identifier.name, slotIndex=slotIndex) else: declObj = "JSObject* obj;\n"
--- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -1,913 +1,129 @@ /* 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"; -let Cu = Components.utils; -let Ci = Components.interfaces; -let Cc = Components.classes; -let Cr = Components.results; - -/* BrowserElementParent injects script to listen for certain events in the - * child. We then listen to messages from the child script and take - * appropriate action here in the parent. - */ +const {utils: Cu, interfaces: Ci} = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); + +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; +const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled"; -XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function () { - Cu.import("resource://gre/modules/Webapps.jsm"); - return DOMApplicationRegistry; -}); +XPCOMUtils.defineLazyModuleGetter(this, "BrowserElementParentBuilder", + "resource://gre/modules/BrowserElementParent.jsm", + "BrowserElementParentBuilder"); function debug(msg) { - //dump("BrowserElementParent - " + msg + "\n"); -} - -function getIntPref(prefName, def) { - try { - return Services.prefs.getIntPref(prefName); - } - catch(err) { - return def; - } -} - -function visibilityChangeHandler(e) { - // The visibilitychange event's target is the document. - let win = e.target.defaultView; - - if (!win._browserElementParents) { - return; - } - - let beps = Cu.nondeterministicGetWeakMapKeys(win._browserElementParents); - if (beps.length == 0) { - win.removeEventListener('visibilitychange', visibilityChangeHandler); - return; - } - - for (let i = 0; i < beps.length; i++) { - beps[i]._ownerVisibilityChange(); - } + //dump("BrowserElementParent.js - " + msg + "\n"); } -function defineNoReturnMethod(fn) { - return function method() { - if (!this._domRequestReady) { - // Remote browser haven't been created, we just queue the API call. - let args = Array.slice(arguments); - args.unshift(this); - this._pendingAPICalls.push(method.bind.apply(fn, args)); - return; - } - if (this._isAlive()) { - fn.apply(this, arguments); - } - }; -} +/** + * BrowserElementParent implements one half of <iframe mozbrowser>. (The other + * half is, unsurprisingly, BrowserElementChild.) + * + * BrowserElementParentFactory detects when we create a windows or docshell + * contained inside a <iframe mozbrowser> and creates a BrowserElementParent + * object for that window. + * + * It creates a BrowserElementParent that injects script to listen for + * certain event. + */ -function defineDOMRequestMethod(msgName) { - return function() { - return this._sendDOMRequest(msgName); - }; +function BrowserElementParentFactory() { + this._initialized = false; } -function BrowserElementParent() { - debug("Creating new BrowserElementParent object"); - this._domRequestCounter = 0; - this._domRequestReady = false; - this._pendingAPICalls = []; - this._pendingDOMRequests = {}; - this._pendingSetInputMethodActive = []; - this._nextPaintListeners = []; - - Services.obs.addObserver(this, 'ask-children-to-exit-fullscreen', /* ownsWeak = */ true); - Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true); - Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true); -} - -BrowserElementParent.prototype = { - - classDescription: "BrowserElementAPI implementation", - classID: Components.ID("{9f171ac4-0939-4ef8-b360-3408aedc3060}"), - contractID: "@mozilla.org/dom/browser-element-api;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserElementAPI, - Ci.nsIObserver, +BrowserElementParentFactory.prototype = { + classID: Components.ID("{ddeafdac-cb39-47c4-9cb8-c9027ee36d26}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), - setFrameLoader: function(frameLoader) { - this._frameLoader = frameLoader; - this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement; - if (!this._frameElement) { - debug("No frame element?"); - return; - } - // Listen to visibilitychange on the iframe's owner window, and forward - // changes down to the child. We want to do this while registering as few - // visibilitychange listeners on _window as possible, because such a listener - // may live longer than this BrowserElementParent object. - // - // To accomplish this, we register just one listener on the window, and have - // it reference a WeakMap whose keys are all the BrowserElementParent objects - // on the window. Then when the listener fires, we iterate over the - // WeakMap's keys (which we can do, because we're chrome) to notify the - // BrowserElementParents. - if (!this._window._browserElementParents) { - this._window._browserElementParents = new WeakMap(); - this._window.addEventListener('visibilitychange', - visibilityChangeHandler, - /* useCapture = */ false, - /* wantsUntrusted = */ false); - } - - this._window._browserElementParents.set(this, null); - - // Insert ourself into the prompt service. - BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this); - this._setupMessageListener(); - this._registerAppManifest(); - }, - - _runPendingAPICall: function() { - if (!this._pendingAPICalls) { - return; - } - for (let i = 0; i < this._pendingAPICalls.length; i++) { - try { - this._pendingAPICalls[i](); - } catch (e) { - // throw the expections from pending functions. - debug('Exception when running pending API call: ' + e); - } - } - delete this._pendingAPICalls; - }, - - _registerAppManifest: function() { - // If this browser represents an app then let the Webapps module register for - // any messages that it needs. - let appManifestURL = - this._frameElement.QueryInterface(Ci.nsIMozBrowserFrame).appManifestURL; - if (appManifestURL) { - let inParent = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - if (inParent) { - DOMApplicationRegistry.registerBrowserElementParentForApp( - { manifestURL: appManifestURL }, this._mm); - } else { - this._mm.sendAsyncMessage("Webapps:RegisterBEP", - { manifestURL: appManifestURL }); - } - } - }, - - _setupMessageListener: function() { - this._mm = this._frameLoader.messageManager; - let self = this; - let isWidget = this._frameLoader - .QueryInterface(Ci.nsIFrameLoader) - .ownerIsWidget; - - // Messages we receive are handed to functions which take a (data) argument, - // where |data| is the message manager's data object. - // We use a single message and dispatch to various function based - // on data.msg_name - let mmCalls = { - "hello": this._recvHello, - "loadstart": this._fireProfiledEventFromMsg, - "loadend": this._fireProfiledEventFromMsg, - "close": this._fireEventFromMsg, - "error": this._fireEventFromMsg, - "firstpaint": this._fireProfiledEventFromMsg, - "documentfirstpaint": this._fireProfiledEventFromMsg, - "nextpaint": this._recvNextPaint, - "got-purge-history": this._gotDOMRequestResult, - "got-screenshot": this._gotDOMRequestResult, - "got-contentdimensions": this._gotDOMRequestResult, - "got-can-go-back": this._gotDOMRequestResult, - "got-can-go-forward": this._gotDOMRequestResult, - "fullscreen-origin-change": this._remoteFullscreenOriginChange, - "rollback-fullscreen": this._remoteFrameFullscreenReverted, - "exit-fullscreen": this._exitFullscreen, - "got-visible": this._gotDOMRequestResult, - "visibilitychange": this._childVisibilityChange, - "got-set-input-method-active": this._gotDOMRequestResult, - "selectionchange": this._handleSelectionChange, - "scrollviewchange": this._handleScrollViewChange, - "touchcarettap": this._handleTouchCaretTap - }; - - let mmSecuritySensitiveCalls = { - "showmodalprompt": this._handleShowModalPrompt, - "contextmenu": this._fireCtxMenuEvent, - "securitychange": this._fireEventFromMsg, - "locationchange": this._fireEventFromMsg, - "iconchange": this._fireEventFromMsg, - "scrollareachanged": this._fireEventFromMsg, - "titlechange": this._fireProfiledEventFromMsg, - "opensearch": this._fireEventFromMsg, - "manifestchange": this._fireEventFromMsg, - "metachange": this._fireEventFromMsg, - "resize": this._fireEventFromMsg, - "activitydone": this._fireEventFromMsg, - "scroll": this._fireEventFromMsg - }; - - this._mm.addMessageListener('browser-element-api:call', function(aMsg) { - if (!self._isAlive()) { - return; - } - - if (aMsg.data.msg_name in mmCalls) { - return mmCalls[aMsg.data.msg_name].apply(self, arguments); - } else if (!isWidget && aMsg.data.msg_name in mmSecuritySensitiveCalls) { - return mmSecuritySensitiveCalls[aMsg.data.msg_name] - .apply(self, arguments); - } - }); - }, - /** - * You shouldn't touch this._frameElement or this._window if _isAlive is - * false. (You'll likely get an exception if you do.) + * Called on app startup, and also when the browser frames enabled pref is + * changed. */ - _isAlive: function() { - return !Cu.isDeadWrapper(this._frameElement) && - !Cu.isDeadWrapper(this._frameElement.ownerDocument) && - !Cu.isDeadWrapper(this._frameElement.ownerDocument.defaultView); - }, - - get _window() { - return this._frameElement.ownerDocument.defaultView; - }, - - get _windowUtils() { - return this._window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - }, - - promptAuth: function(authDetail, callback) { - let evt; - let self = this; - let callbackCalled = false; - let cancelCallback = function() { - if (!callbackCalled) { - callbackCalled = true; - callback(false, null, null); - } - }; - - // 1. We don't handle password-only prompts. - // 2. We don't handle for widget case because of security concern. - if (authDetail.isOnlyPassword || - this._frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsWidget) { - cancelCallback(); + _init: function() { + if (this._initialized) { return; } - /* username and password */ - let detail = { - host: authDetail.host, - realm: authDetail.realm - }; - - evt = this._createEvent('usernameandpasswordrequired', detail, - /* cancelable */ true); - Cu.exportFunction(function(username, password) { - if (callbackCalled) - return; - callbackCalled = true; - callback(true, username, password); - }, evt.detail, { defineAs: 'authenticate' }); - - Cu.exportFunction(cancelCallback, evt.detail, { defineAs: 'cancel' }); - - this._frameElement.dispatchEvent(evt); - - if (!evt.defaultPrevented) { - cancelCallback(); - } - }, - - _sendAsyncMsg: function(msg, data) { - try { - if (!data) { - data = { }; - } - - data.msg_name = msg; - this._mm.sendAsyncMessage('browser-element-api:call', data); - } catch (e) { - return false; - } - return true; - }, - - _recvHello: function() { - debug("recvHello"); - - // Inform our child if our owner element's document is invisible. Note - // that we must do so here, rather than in the BrowserElementParent - // constructor, because the BrowserElementChild may not be initialized when - // we run our constructor. - if (this._window.document.hidden) { - this._ownerVisibilityChange(); - } - - if (!this._domRequestReady) { - // At least, one message listener such as for hello is registered. - // So we can use sendAsyncMessage now. - this._domRequestReady = true; - this._runPendingAPICall(); - } - - return { - name: this._frameElement.getAttribute('name'), - fullscreenAllowed: - this._frameElement.hasAttribute('allowfullscreen') || - this._frameElement.hasAttribute('mozallowfullscreen'), - isPrivate: this._frameElement.hasAttribute('mozprivatebrowsing') - }; - }, - - _fireCtxMenuEvent: function(data) { - let detail = data.json; - let evtName = detail.msg_name; - - debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail); - let evt = this._createEvent(evtName, detail, /* cancellable */ true); - - if (detail.contextmenu) { - var self = this; - Cu.exportFunction(function(id) { - self._sendAsyncMsg('fire-ctx-callback', {menuitem: id}); - }, evt.detail, { defineAs: 'contextMenuItemSelected' }); + // If the pref is disabled, do nothing except wait for the pref to change. + // (This is important for tests, if nothing else.) + if (!this._browserFramesPrefEnabled()) { + Services.prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true); + return; } - // The embedder may have default actions on context menu events, so - // we fire a context menu event even if the child didn't define a - // custom context menu - return !this._frameElement.dispatchEvent(evt); - }, - - /** - * add profiler marker for each event fired. - */ - _fireProfiledEventFromMsg: function(data) { - if (Services.profiler !== undefined) { - Services.profiler.AddMarker(data.json.msg_name); - } - this._fireEventFromMsg(data); - }, + debug("_init"); + this._initialized = true; - /** - * Fire either a vanilla or a custom event, depending on the contents of - * |data|. - */ - _fireEventFromMsg: function(data) { - let detail = data.json; - let name = detail.msg_name; + // Maps frame elements to BrowserElementParent objects. We never look up + // anything in this map; the purpose is to keep the BrowserElementParent + // alive for as long as its frame element lives. + this._bepMap = new WeakMap(); - // For events that send a "_payload_" property, we just want to transmit - // this in the event. - if ("_payload_" in detail) { - detail = detail._payload_; - } - - debug('fireEventFromMsg: ' + name + ', ' + JSON.stringify(detail)); - let evt = this._createEvent(name, detail, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); + Services.obs.addObserver(this, 'remote-browser-pending', /* ownsWeak = */ true); + Services.obs.addObserver(this, 'inprocess-browser-shown', /* ownsWeak = */ true); }, - _handleShowModalPrompt: function(data) { - // Fire a showmodalprmopt event on the iframe. When this method is called, - // the child is spinning in a nested event loop waiting for an - // unblock-modal-prompt message. - // - // If the embedder calls preventDefault() on the showmodalprompt event, - // we'll block the child until event.detail.unblock() is called. - // - // Otherwise, if preventDefault() is not called, we'll send the - // unblock-modal-prompt message to the child as soon as the event is done - // dispatching. - - let detail = data.json; - debug('handleShowPrompt ' + JSON.stringify(detail)); - - // Strip off the windowID property from the object we send along in the - // event. - let windowID = detail.windowID; - delete detail.windowID; - debug("Event will have detail: " + JSON.stringify(detail)); - let evt = this._createEvent('showmodalprompt', detail, - /* cancelable = */ true); - - let self = this; - let unblockMsgSent = false; - function sendUnblockMsg() { - if (unblockMsgSent) { - return; - } - unblockMsgSent = true; - - // We don't need to sanitize evt.detail.returnValue (e.g. converting the - // return value of confirm() to a boolean); Gecko does that for us. - - let data = { windowID: windowID, - returnValue: evt.detail.returnValue }; - self._sendAsyncMsg('unblock-modal-prompt', data); + _browserFramesPrefEnabled: function() { + try { + return Services.prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF); } - - Cu.exportFunction(sendUnblockMsg, evt.detail, { defineAs: 'unblock' }); - - this._frameElement.dispatchEvent(evt); - - if (!evt.defaultPrevented) { - // Unblock the inner frame immediately. Otherwise we'll unblock upon - // evt.detail.unblock(). - sendUnblockMsg(); + catch(e) { + return false; } }, - _handleSelectionChange: function(data) { - let evt = this._createEvent('selectionchange', data.json, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); - }, - - _handleScrollViewChange: function(data) { - let evt = this._createEvent("scrollviewchange", data.json, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); - }, - - _handleTouchCaretTap: function(data) { - let evt = this._createEvent("touchcarettap", data.json, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); - }, - - _createEvent: function(evtName, detail, cancelable) { - // This will have to change if we ever want to send a CustomEvent with null - // detail. For now, it's OK. - if (detail !== undefined && detail !== null) { - detail = Cu.cloneInto(detail, this._window); - return new this._window.CustomEvent('mozbrowser' + evtName, - { bubbles: true, - cancelable: cancelable, - detail: detail }); + _observeInProcessBrowserFrameShown: function(frameLoader) { + // Ignore notifications that aren't from a BrowserOrApp + if (!frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsBrowserOrAppFrame) { + return; } - - return new this._window.Event('mozbrowser' + evtName, - { bubbles: true, - cancelable: cancelable }); - }, - - /** - * Kick off a DOMRequest in the child process. - * - * We'll fire an event called |msgName| on the child process, passing along - * an object with two fields: - * - * - id: the ID of this request. - * - arg: arguments to pass to the child along with this request. - * - * We expect the child to pass the ID back to us upon completion of the - * request. See _gotDOMRequestResult. - */ - _sendDOMRequest: function(msgName, args) { - let id = 'req_' + this._domRequestCounter++; - let req = Services.DOMRequest.createRequest(this._window); - let self = this; - let send = function() { - if (!self._isAlive()) { - return; - } - if (self._sendAsyncMsg(msgName, {id: id, args: args})) { - self._pendingDOMRequests[id] = req; - } else { - Services.DOMRequest.fireErrorAsync(req, "fail"); - } - }; - if (this._domRequestReady) { - send(); - } else { - // Child haven't been loaded. - this._pendingAPICalls.push(send); - } - return req; - }, - - /** - * Called when the child process finishes handling a DOMRequest. data.json - * must have the fields [id, successRv], if the DOMRequest was successful, or - * [id, errorMsg], if the request was not successful. - * - * The fields have the following meanings: - * - * - id: the ID of the DOM request (see _sendDOMRequest) - * - successRv: the request's return value, if the request succeeded - * - errorMsg: the message to pass to DOMRequest.fireError(), if the request - * failed. - * - */ - _gotDOMRequestResult: function(data) { - let req = this._pendingDOMRequests[data.json.id]; - delete this._pendingDOMRequests[data.json.id]; - - if ('successRv' in data.json) { - debug("Successful gotDOMRequestResult."); - let clientObj = Cu.cloneInto(data.json.successRv, this._window); - Services.DOMRequest.fireSuccess(req, clientObj); - } - else { - debug("Got error in gotDOMRequestResult."); - Services.DOMRequest.fireErrorAsync(req, - Cu.cloneInto(data.json.errorMsg, this._window)); - } - }, - - setVisible: defineNoReturnMethod(function(visible) { - this._sendAsyncMsg('set-visible', {visible: visible}); - this._frameLoader.visible = visible; - }), - - getVisible: defineDOMRequestMethod('get-visible'), - - setActive: defineNoReturnMethod(function(active) { - this._frameLoader.visible = active; - }), - - getActive: function() { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - - return this._frameLoader.visible; + debug("In-process browser frame shown " + frameLoader); + this._createBrowserElementParent(frameLoader, + /* hasRemoteFrame = */ false, + /* pending frame */ false); }, - sendMouseEvent: defineNoReturnMethod(function(type, x, y, button, clickCount, modifiers) { - this._sendAsyncMsg("send-mouse-event", { - "type": type, - "x": x, - "y": y, - "button": button, - "clickCount": clickCount, - "modifiers": modifiers - }); - }), - - sendTouchEvent: defineNoReturnMethod(function(type, identifiers, touchesX, touchesY, - radiisX, radiisY, rotationAngles, forces, - count, modifiers) { - - let tabParent = this._frameLoader.tabParent; - if (tabParent && tabParent.useAsyncPanZoom) { - tabParent.injectTouchEvent(type, - identifiers, - touchesX, - touchesY, - radiisX, - radiisY, - rotationAngles, - forces, - count, - modifiers); - } else { - this._sendAsyncMsg("send-touch-event", { - "type": type, - "identifiers": identifiers, - "touchesX": touchesX, - "touchesY": touchesY, - "radiisX": radiisX, - "radiisY": radiisY, - "rotationAngles": rotationAngles, - "forces": forces, - "count": count, - "modifiers": modifiers - }); - } - }), - - getCanGoBack: defineDOMRequestMethod('get-can-go-back'), - getCanGoForward: defineDOMRequestMethod('get-can-go-forward'), - getContentDimensions: defineDOMRequestMethod('get-contentdimensions'), - - goBack: defineNoReturnMethod(function() { - this._sendAsyncMsg('go-back'); - }), - - goForward: defineNoReturnMethod(function() { - this._sendAsyncMsg('go-forward'); - }), - - reload: defineNoReturnMethod(function(hardReload) { - this._sendAsyncMsg('reload', {hardReload: hardReload}); - }), - - stop: defineNoReturnMethod(function() { - this._sendAsyncMsg('stop'); - }), - - /* - * The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent". - */ - zoom: defineNoReturnMethod(function(zoom) { - zoom *= 100; - zoom = Math.min(getIntPref("zoom.maxPercent", 300), zoom); - zoom = Math.max(getIntPref("zoom.minPercent", 50), zoom); - this._sendAsyncMsg('zoom', {zoom: zoom / 100.0}); - }), - - purgeHistory: defineDOMRequestMethod('purge-history'), - - - download: function(_url, _options) { - if (!this._isAlive()) { - return null; - } - let ioService = - Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService); - let uri = ioService.newURI(_url, null, null); - let url = uri.QueryInterface(Ci.nsIURL); - - // Ensure we have _options, we always use it to send the filename. - _options = _options || {}; - if (!_options.filename) { - _options.filename = url.fileName; - } - - debug('_options = ' + uneval(_options)); - - // Ensure we have a filename. - if (!_options.filename) { - throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); + _observeRemoteBrowserFramePending: function(frameLoader) { + // Ignore notifications that aren't from a BrowserOrApp + if (!frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsBrowserOrAppFrame) { + return; } - - let interfaceRequestor = - this._frameLoader.loadContext.QueryInterface(Ci.nsIInterfaceRequestor); - let req = Services.DOMRequest.createRequest(this._window); - - function DownloadListener() { - debug('DownloadListener Constructor'); - } - DownloadListener.prototype = { - extListener: null, - onStartRequest: function(aRequest, aContext) { - debug('DownloadListener - onStartRequest'); - let extHelperAppSvc = - Cc['@mozilla.org/uriloader/external-helper-app-service;1']. - getService(Ci.nsIExternalHelperAppService); - let channel = aRequest.QueryInterface(Ci.nsIChannel); - - // First, we'll ensure the filename doesn't have any leading - // periods. We have to do it here to avoid ending up with a filename - // that's only an extension with no extension (e.g. Sending in - // '.jpeg' without stripping the '.' would result in a filename of - // 'jpeg' where we want 'jpeg.jpeg'. - _options.filename = _options.filename.replace(/^\.+/, ""); - - let ext = null; - let mimeSvc = extHelperAppSvc.QueryInterface(Ci.nsIMIMEService); - try { - ext = '.' + mimeSvc.getPrimaryExtension(channel.contentType, ''); - } catch (e) { ext = null; } - - // Check if we need to add an extension to the filename. - if (ext && !_options.filename.endsWith(ext)) { - _options.filename += ext; - } - // Set the filename to use when saving to disk. - channel.contentDispositionFilename = _options.filename; - - this.extListener = - extHelperAppSvc.doContent( - channel.contentType, - aRequest, - interfaceRequestor, - true); - this.extListener.onStartRequest(aRequest, aContext); - }, - onStopRequest: function(aRequest, aContext, aStatusCode) { - debug('DownloadListener - onStopRequest (aStatusCode = ' + - aStatusCode + ')'); - if (aStatusCode == Cr.NS_OK) { - // Everything looks great. - debug('DownloadListener - Download Successful.'); - Services.DOMRequest.fireSuccess(req, aStatusCode); - } - else { - // In case of failure, we'll simply return the failure status code. - debug('DownloadListener - Download Failed!'); - Services.DOMRequest.fireError(req, aStatusCode); - } - - if (this.extListener) { - this.extListener.onStopRequest(aRequest, aContext, aStatusCode); - } - }, - onDataAvailable: function(aRequest, aContext, aInputStream, - aOffset, aCount) { - this.extListener.onDataAvailable(aRequest, aContext, aInputStream, - aOffset, aCount); - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener, - Ci.nsIRequestObserver]) - }; - - let channel = ioService.newChannelFromURI(url); - - // XXX We would set private browsing information prior to calling this. - channel.notificationCallbacks = interfaceRequestor; - - // Since we're downloading our own local copy we'll want to bypass the - // cache and local cache if the channel let's us specify this. - let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS | - Ci.nsIChannel.LOAD_BYPASS_CACHE; - if (channel instanceof Ci.nsICachingChannel) { - debug('This is a caching channel. Forcing bypass.'); - flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; - } - - channel.loadFlags |= flags; - - if (channel instanceof Ci.nsIHttpChannel) { - debug('Setting HTTP referrer = ' + this._window.document.documentURIObject); - channel.referrer = this._window.document.documentURIObject; - if (channel instanceof Ci.nsIHttpChannelInternal) { - channel.forceAllowThirdPartyCookie = true; - } - } - - // Set-up complete, let's get things started. - channel.asyncOpen(new DownloadListener(), null); - - return req; + debug("Remote browser frame shown " + frameLoader); + this._createBrowserElementParent(frameLoader, + /* hasRemoteFrame = */ true, + /* pending frame */ true); }, - getScreenshot: function(_width, _height, _mimeType) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - - let width = parseInt(_width); - let height = parseInt(_height); - let mimeType = (typeof _mimeType === 'string') ? - _mimeType.trim().toLowerCase() : 'image/jpeg'; - if (isNaN(width) || isNaN(height) || width < 0 || height < 0) { - throw Components.Exception("Invalid argument", - Cr.NS_ERROR_INVALID_ARG); - } - - return this._sendDOMRequest('get-screenshot', - {width: width, height: height, - mimeType: mimeType}); - }, - - _recvNextPaint: function(data) { - let listeners = this._nextPaintListeners; - this._nextPaintListeners = []; - for (let listener of listeners) { - try { - listener.recvNextPaint(); - } catch (e) { - // If a listener throws we'll continue. - } - } - }, - - addNextPaintListener: function(listener) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - - let self = this; - let run = function() { - if (self._nextPaintListeners.push(listener) == 1) - self._sendAsyncMsg('activate-next-paint-listener'); - }; - if (!this._domRequestReady) { - this._pendingAPICalls.push(run); - } else { - run(); - } - }, - - removeNextPaintListener: function(listener) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - - let self = this; - let run = function() { - for (let i = self._nextPaintListeners.length - 1; i >= 0; i--) { - if (self._nextPaintListeners[i] == listener) { - self._nextPaintListeners.splice(i, 1); - break; - } - } - - if (self._nextPaintListeners.length == 0) - self._sendAsyncMsg('deactivate-next-paint-listener'); - }; - if (!this._domRequestReady) { - this._pendingAPICalls.push(run); - } else { - run(); - } - }, - - setInputMethodActive: function(isActive) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - - if (typeof isActive !== 'boolean') { - throw Components.Exception("Invalid argument", - Cr.NS_ERROR_INVALID_ARG); - } - - return this._sendDOMRequest('set-input-method-active', - {isActive: isActive}); - }, - - /** - * Called when the visibility of the window which owns this iframe changes. - */ - _ownerVisibilityChange: function() { - this._sendAsyncMsg('owner-visibility-change', - {visible: !this._window.document.hidden}); - }, - - /* - * Called when the child notices that its visibility has changed. - * - * This is sometimes redundant; for example, the child's visibility may - * change in response to a setVisible request that we made here! But it's - * not always redundant; for example, the child's visibility may change in - * response to its parent docshell being hidden. - */ - _childVisibilityChange: function(data) { - debug("_childVisibilityChange(" + data.json.visible + ")"); - this._frameLoader.visible = data.json.visible; - - this._fireEventFromMsg(data); - }, - - _exitFullscreen: function() { - this._windowUtils.exitFullscreen(); - }, - - _remoteFullscreenOriginChange: function(data) { - let origin = data.json._payload_; - this._windowUtils.remoteFrameFullscreenChanged(this._frameElement, origin); - }, - - _remoteFrameFullscreenReverted: function(data) { - this._windowUtils.remoteFrameFullscreenReverted(); - }, - - _fireFatalError: function() { - let evt = this._createEvent('error', {type: 'fatal'}, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); + _createBrowserElementParent: function(frameLoader, hasRemoteFrame, isPendingFrame) { + let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement; + this._bepMap.set(frameElement, BrowserElementParentBuilder.create( + frameLoader, hasRemoteFrame, isPendingFrame)); }, observe: function(subject, topic, data) { switch(topic) { - case 'oop-frameloader-crashed': - if (this._isAlive() && subject == this._frameLoader) { - this._fireFatalError(); + case 'app-startup': + this._init(); + break; + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (data == BROWSER_FRAMES_ENABLED_PREF) { + this._init(); } break; - case 'ask-children-to-exit-fullscreen': - if (this._isAlive() && - this._frameElement.ownerDocument == subject && - this._frameLoader.QueryInterface(Ci.nsIFrameLoader).tabParent) { - this._sendAsyncMsg('exit-fullscreen'); - } + case 'remote-browser-pending': + this._observeRemoteBrowserFramePending(subject); break; - case 'copypaste-docommand': - if (this._isAlive() && this._frameElement.isEqualNode(subject.wrappedJSObject)) { - this._sendAsyncMsg('do-command', { command: data }); - } + case 'inprocess-browser-shown': + this._observeInProcessBrowserFrameShown(subject); break; - default: - debug('Unknown topic: ' + topic); - break; - }; + } }, }; -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParent]); +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParentFactory]);
copy from dom/browser-element/BrowserElementParent.js copy to dom/browser-element/BrowserElementParent.jsm --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.jsm @@ -9,27 +9,31 @@ let Ci = Components.interfaces; let Cc = Components.classes; let Cr = Components.results; /* BrowserElementParent injects script to listen for certain events in the * child. We then listen to messages from the child script and take * appropriate action here in the parent. */ +this.EXPORTED_SYMBOLS = ["BrowserElementParentBuilder"]; + Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function () { Cu.import("resource://gre/modules/Webapps.jsm"); return DOMApplicationRegistry; }); +const TOUCH_EVENTS_ENABLED_PREF = "dom.w3c_touch_events.enabled"; + function debug(msg) { - //dump("BrowserElementParent - " + msg + "\n"); + //dump("BrowserElementParent.jsm - " + msg + "\n"); } function getIntPref(prefName, def) { try { return Services.prefs.getIntPref(prefName); } catch(err) { return def; @@ -50,93 +54,148 @@ function visibilityChangeHandler(e) { return; } for (let i = 0; i < beps.length; i++) { beps[i]._ownerVisibilityChange(); } } -function defineNoReturnMethod(fn) { - return function method() { - if (!this._domRequestReady) { - // Remote browser haven't been created, we just queue the API call. - let args = Array.slice(arguments); - args.unshift(this); - this._pendingAPICalls.push(method.bind.apply(fn, args)); - return; - } - if (this._isAlive()) { - fn.apply(this, arguments); - } - }; +this.BrowserElementParentBuilder = { + create: function create(frameLoader, hasRemoteFrame, isPendingFrame) { + return new BrowserElementParent(frameLoader, hasRemoteFrame); + } } -function defineDOMRequestMethod(msgName) { - return function() { - return this._sendDOMRequest(msgName); - }; -} - -function BrowserElementParent() { - debug("Creating new BrowserElementParent object"); +function BrowserElementParent(frameLoader, hasRemoteFrame, isPendingFrame) { + debug("Creating new BrowserElementParent object for " + frameLoader); this._domRequestCounter = 0; this._domRequestReady = false; this._pendingAPICalls = []; this._pendingDOMRequests = {}; this._pendingSetInputMethodActive = []; + this._hasRemoteFrame = hasRemoteFrame; this._nextPaintListeners = []; + this._frameLoader = frameLoader; + this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement; + let self = this; + if (!this._frameElement) { + debug("No frame element?"); + return; + } + Services.obs.addObserver(this, 'ask-children-to-exit-fullscreen', /* ownsWeak = */ true); Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true); Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true); + + let defineMethod = function(name, fn) { + XPCNativeWrapper.unwrap(self._frameElement)[name] = Cu.exportFunction(function() { + if (self._isAlive()) { + return fn.apply(self, arguments); + } + }, self._frameElement); + } + + let defineNoReturnMethod = function(name, fn) { + XPCNativeWrapper.unwrap(self._frameElement)[name] = Cu.exportFunction(function method() { + if (!self._domRequestReady) { + // Remote browser haven't been created, we just queue the API call. + let args = Array.slice(arguments); + args.unshift(self); + self._pendingAPICalls.push(method.bind.apply(fn, args)); + return; + } + if (self._isAlive()) { + fn.apply(self, arguments); + } + }, self._frameElement); + }; + + let defineDOMRequestMethod = function(domName, msgName) { + XPCNativeWrapper.unwrap(self._frameElement)[domName] = Cu.exportFunction(function() { + return self._sendDOMRequest(msgName); + }, self._frameElement); + } + + // Define methods on the frame element. + defineNoReturnMethod('setVisible', this._setVisible); + defineDOMRequestMethod('getVisible', 'get-visible'); + + // Not expose security sensitive browser API for widgets + if (!this._frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsWidget) { + defineNoReturnMethod('sendMouseEvent', this._sendMouseEvent); + + // 0 = disabled, 1 = enabled, 2 - auto detect + if (getIntPref(TOUCH_EVENTS_ENABLED_PREF, 0) != 0) { + defineNoReturnMethod('sendTouchEvent', this._sendTouchEvent); + } + defineNoReturnMethod('goBack', this._goBack); + defineNoReturnMethod('goForward', this._goForward); + defineNoReturnMethod('reload', this._reload); + defineNoReturnMethod('stop', this._stop); + defineMethod('download', this._download); + defineDOMRequestMethod('purgeHistory', 'purge-history'); + defineMethod('getScreenshot', this._getScreenshot); + defineNoReturnMethod('zoom', this._zoom); + + defineDOMRequestMethod('getCanGoBack', 'get-can-go-back'); + defineDOMRequestMethod('getCanGoForward', 'get-can-go-forward'); + defineDOMRequestMethod('getContentDimensions', 'get-contentdimensions'); + } + + defineMethod('addNextPaintListener', this._addNextPaintListener); + defineMethod('removeNextPaintListener', this._removeNextPaintListener); + defineNoReturnMethod('setActive', this._setActive); + defineMethod('getActive', 'this._getActive'); + + let principal = this._frameElement.ownerDocument.nodePrincipal; + let perm = Services.perms + .testExactPermissionFromPrincipal(principal, "input-manage"); + if (perm === Ci.nsIPermissionManager.ALLOW_ACTION) { + defineMethod('setInputMethodActive', this._setInputMethodActive); + } + + // Listen to visibilitychange on the iframe's owner window, and forward + // changes down to the child. We want to do this while registering as few + // visibilitychange listeners on _window as possible, because such a listener + // may live longer than this BrowserElementParent object. + // + // To accomplish this, we register just one listener on the window, and have + // it reference a WeakMap whose keys are all the BrowserElementParent objects + // on the window. Then when the listener fires, we iterate over the + // WeakMap's keys (which we can do, because we're chrome) to notify the + // BrowserElementParents. + if (!this._window._browserElementParents) { + this._window._browserElementParents = new WeakMap(); + this._window.addEventListener('visibilitychange', + visibilityChangeHandler, + /* useCapture = */ false, + /* wantsUntrusted = */ false); + } + + this._window._browserElementParents.set(this, null); + + // Insert ourself into the prompt service. + BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this); + if (!isPendingFrame) { + this._setupMessageListener(); + this._registerAppManifest(); + } else { + // if we are a pending frame, we setup message manager after + // observing remote-browser-frame-shown + Services.obs.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true); + } } BrowserElementParent.prototype = { - classDescription: "BrowserElementAPI implementation", - classID: Components.ID("{9f171ac4-0939-4ef8-b360-3408aedc3060}"), - contractID: "@mozilla.org/dom/browser-element-api;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserElementAPI, - Ci.nsIObserver, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), - setFrameLoader: function(frameLoader) { - this._frameLoader = frameLoader; - this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement; - if (!this._frameElement) { - debug("No frame element?"); - return; - } - // Listen to visibilitychange on the iframe's owner window, and forward - // changes down to the child. We want to do this while registering as few - // visibilitychange listeners on _window as possible, because such a listener - // may live longer than this BrowserElementParent object. - // - // To accomplish this, we register just one listener on the window, and have - // it reference a WeakMap whose keys are all the BrowserElementParent objects - // on the window. Then when the listener fires, we iterate over the - // WeakMap's keys (which we can do, because we're chrome) to notify the - // BrowserElementParents. - if (!this._window._browserElementParents) { - this._window._browserElementParents = new WeakMap(); - this._window.addEventListener('visibilitychange', - visibilityChangeHandler, - /* useCapture = */ false, - /* wantsUntrusted = */ false); - } - - this._window._browserElementParents.set(this, null); - - // Insert ourself into the prompt service. - BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this); - this._setupMessageListener(); - this._registerAppManifest(); - }, - _runPendingAPICall: function() { if (!this._pendingAPICalls) { return; } for (let i = 0; i < this._pendingAPICalls.length; i++) { try { this._pendingAPICalls[i](); } catch (e) { @@ -528,50 +587,43 @@ BrowserElementParent.prototype = { } else { debug("Got error in gotDOMRequestResult."); Services.DOMRequest.fireErrorAsync(req, Cu.cloneInto(data.json.errorMsg, this._window)); } }, - setVisible: defineNoReturnMethod(function(visible) { + _setVisible: function(visible) { this._sendAsyncMsg('set-visible', {visible: visible}); this._frameLoader.visible = visible; - }), + }, - getVisible: defineDOMRequestMethod('get-visible'), - - setActive: defineNoReturnMethod(function(active) { + _setActive: function(active) { this._frameLoader.visible = active; - }), + }, - getActive: function() { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - + _getActive: function() { return this._frameLoader.visible; }, - sendMouseEvent: defineNoReturnMethod(function(type, x, y, button, clickCount, modifiers) { + _sendMouseEvent: function(type, x, y, button, clickCount, modifiers) { this._sendAsyncMsg("send-mouse-event", { "type": type, "x": x, "y": y, "button": button, "clickCount": clickCount, "modifiers": modifiers }); - }), + }, - sendTouchEvent: defineNoReturnMethod(function(type, identifiers, touchesX, touchesY, - radiisX, radiisY, rotationAngles, forces, - count, modifiers) { + _sendTouchEvent: function(type, identifiers, touchesX, touchesY, + radiisX, radiisY, rotationAngles, forces, + count, modifiers) { let tabParent = this._frameLoader.tabParent; if (tabParent && tabParent.useAsyncPanZoom) { tabParent.injectTouchEvent(type, identifiers, touchesX, touchesY, radiisX, @@ -589,55 +641,45 @@ BrowserElementParent.prototype = { "radiisX": radiisX, "radiisY": radiisY, "rotationAngles": rotationAngles, "forces": forces, "count": count, "modifiers": modifiers }); } - }), + }, - getCanGoBack: defineDOMRequestMethod('get-can-go-back'), - getCanGoForward: defineDOMRequestMethod('get-can-go-forward'), - getContentDimensions: defineDOMRequestMethod('get-contentdimensions'), - - goBack: defineNoReturnMethod(function() { + _goBack: function() { this._sendAsyncMsg('go-back'); - }), + }, - goForward: defineNoReturnMethod(function() { + _goForward: function() { this._sendAsyncMsg('go-forward'); - }), + }, - reload: defineNoReturnMethod(function(hardReload) { + _reload: function(hardReload) { this._sendAsyncMsg('reload', {hardReload: hardReload}); - }), + }, - stop: defineNoReturnMethod(function() { + _stop: function() { this._sendAsyncMsg('stop'); - }), + }, /* * The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent". */ - zoom: defineNoReturnMethod(function(zoom) { + _zoom: function(zoom) { zoom *= 100; zoom = Math.min(getIntPref("zoom.maxPercent", 300), zoom); zoom = Math.max(getIntPref("zoom.minPercent", 50), zoom); this._sendAsyncMsg('zoom', {zoom: zoom / 100.0}); - }), - - purgeHistory: defineDOMRequestMethod('purge-history'), - + }, - download: function(_url, _options) { - if (!this._isAlive()) { - return null; - } + _download: function(_url, _options) { let ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService); let uri = ioService.newURI(_url, null, null); let url = uri.QueryInterface(Ci.nsIURL); // Ensure we have _options, we always use it to send the filename. _options = _options || {}; if (!_options.filename) { @@ -713,17 +755,17 @@ BrowserElementParent.prototype = { this.extListener.onStopRequest(aRequest, aContext, aStatusCode); } }, onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) { this.extListener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount); }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener, Ci.nsIRequestObserver]) }; let channel = ioService.newChannelFromURI(url); // XXX We would set private browsing information prior to calling this. channel.notificationCallbacks = interfaceRequestor; @@ -747,22 +789,17 @@ BrowserElementParent.prototype = { } // Set-up complete, let's get things started. channel.asyncOpen(new DownloadListener(), null); return req; }, - getScreenshot: function(_width, _height, _mimeType) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - + _getScreenshot: function(_width, _height, _mimeType) { let width = parseInt(_width); let height = parseInt(_height); let mimeType = (typeof _mimeType === 'string') ? _mimeType.trim().toLowerCase() : 'image/jpeg'; if (isNaN(width) || isNaN(height) || width < 0 || height < 0) { throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); } @@ -772,46 +809,42 @@ BrowserElementParent.prototype = { mimeType: mimeType}); }, _recvNextPaint: function(data) { let listeners = this._nextPaintListeners; this._nextPaintListeners = []; for (let listener of listeners) { try { - listener.recvNextPaint(); + listener(); } catch (e) { // If a listener throws we'll continue. } } }, - addNextPaintListener: function(listener) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } + _addNextPaintListener: function(listener) { + if (typeof listener != 'function') + throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); let self = this; let run = function() { if (self._nextPaintListeners.push(listener) == 1) self._sendAsyncMsg('activate-next-paint-listener'); }; if (!this._domRequestReady) { this._pendingAPICalls.push(run); } else { run(); } }, - removeNextPaintListener: function(listener) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } + _removeNextPaintListener: function(listener) { + if (typeof listener != 'function') + throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); let self = this; let run = function() { for (let i = self._nextPaintListeners.length - 1; i >= 0; i--) { if (self._nextPaintListeners[i] == listener) { self._nextPaintListeners.splice(i, 1); break; } @@ -822,22 +855,17 @@ BrowserElementParent.prototype = { }; if (!this._domRequestReady) { this._pendingAPICalls.push(run); } else { run(); } }, - setInputMethodActive: function(isActive) { - if (!this._isAlive()) { - throw Components.Exception("Dead content process", - Cr.NS_ERROR_DOM_INVALID_STATE_ERR); - } - + _setInputMethodActive: function(isActive) { if (typeof isActive !== 'boolean') { throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); } return this._sendDOMRequest('set-input-method-active', {isActive: isActive}); }, @@ -889,25 +917,31 @@ BrowserElementParent.prototype = { case 'oop-frameloader-crashed': if (this._isAlive() && subject == this._frameLoader) { this._fireFatalError(); } break; case 'ask-children-to-exit-fullscreen': if (this._isAlive() && this._frameElement.ownerDocument == subject && - this._frameLoader.QueryInterface(Ci.nsIFrameLoader).tabParent) { + this._hasRemoteFrame) { this._sendAsyncMsg('exit-fullscreen'); } break; + case 'remote-browser-frame-shown': + if (this._frameLoader == subject) { + if (!this._mm) { + this._setupMessageListener(); + this._registerAppManifest(); + } + Services.obs.removeObserver(this, 'remote-browser-frame-shown'); + } case 'copypaste-docommand': if (this._isAlive() && this._frameElement.isEqualNode(subject.wrappedJSObject)) { this._sendAsyncMsg('do-command', { command: data }); } break; default: debug('Unknown topic: ' + topic); break; }; }, }; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParent]);
--- a/dom/browser-element/BrowserElementParent.manifest +++ b/dom/browser-element/BrowserElementParent.manifest @@ -1,2 +1,3 @@ -component {9f171ac4-0939-4ef8-b360-3408aedc3060} BrowserElementParent.js -contract @mozilla.org/dom/browser-element-api;1 {9f171ac4-0939-4ef8-b360-3408aedc3060} +component {ddeafdac-cb39-47c4-9cb8-c9027ee36d26} BrowserElementParent.js +contract @mozilla.org/browser-element-parent-factory;1 {ddeafdac-cb39-47c4-9cb8-c9027ee36d26} +category app-startup BrowserElementParentFactory service,@mozilla.org/browser-element-parent-factory;1
--- a/dom/browser-element/moz.build +++ b/dom/browser-element/moz.build @@ -7,28 +7,23 @@ EXPORTS.mozilla += [ 'BrowserElementParent.h', ] SOURCES += [ 'BrowserElementParent.cpp', ] -XPIDL_SOURCES += [ - 'nsIBrowserElementAPI.idl', -] - -XPIDL_MODULE = 'browser-element' - EXTRA_COMPONENTS += [ 'BrowserElementParent.js', 'BrowserElementParent.manifest', ] EXTRA_JS_MODULES += [ + 'BrowserElementParent.jsm', 'BrowserElementPromptService.jsm', ] FAIL_ON_WARNINGS = True LOCAL_INCLUDES += [ '../bluetooth', '/dom/html',
deleted file mode 100644 --- a/dom/browser-element/nsIBrowserElementAPI.idl +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIDOMDOMRequest; -interface nsIFrameLoader; - -[scriptable, function, uuid(c0c2dd9b-41ef-42dd-a4c1-e456619c1941)] -interface nsIBrowserElementNextPaintListener : nsISupports -{ - void recvNextPaint(); -}; - -%{C++ -#define BROWSER_ELEMENT_API_CONTRACTID "@mozilla.org/dom/browser-element-api;1" -#define BROWSER_ELEMENT_API_CID \ - { 0x651db7e3, 0x1734, 0x4536, \ - { 0xb1, 0x5a, 0x5b, 0x3a, 0xe6, 0x44, 0x13, 0x4c } } -%} - -/** - * Interface to the BrowserElementParent implementation. All methods - * but setFrameLoader throw when the remote process is dead. - */ -[scriptable, uuid(abae4fb1-7d6f-4e3f-b435-6501f1d4c659)] -interface nsIBrowserElementAPI : nsISupports -{ - void setFrameLoader(in nsIFrameLoader frameLoader); - - void setVisible(in boolean visible); - nsIDOMDOMRequest getVisible(); - void setActive(in boolean active); - boolean getActive(); - - void sendMouseEvent(in DOMString type, - in uint32_t x, - in uint32_t y, - in uint32_t button, - in uint32_t clickCount, - in uint32_t mifiers); - void sendTouchEvent(in DOMString aType, - [const, array, size_is(count)] in uint32_t aIdentifiers, - [const, array, size_is(count)] in int32_t aXs, - [const, array, size_is(count)] in int32_t aYs, - [const, array, size_is(count)] in uint32_t aRxs, - [const, array, size_is(count)] in uint32_t aRys, - [const, array, size_is(count)] in float aRotationAngles, - [const, array, size_is(count)] in float aForces, - in uint32_t count, - in long aModifiers); - void goBack(); - void goForward(); - void reload(in boolean hardReload); - void stop(); - nsIDOMDOMRequest download(in DOMString url, - [optional] in jsval options); - nsIDOMDOMRequest purgeHistory(); - nsIDOMDOMRequest getScreenshot(in uint32_t width, - in uint32_t height, - [optional] in DOMString mimeType); - void zoom(in float zoom); - nsIDOMDOMRequest getCanGoBack(); - nsIDOMDOMRequest getCanGoForward(); - nsIDOMDOMRequest getContentDimensions(); - - void addNextPaintListener(in nsIBrowserElementNextPaintListener listener); - void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener); - - nsIDOMDOMRequest setInputMethodActive(in boolean isActive); -};
--- a/dom/canvas/WebGL1Context.cpp +++ b/dom/canvas/WebGL1Context.cpp @@ -1,50 +1,51 @@ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 "WebGL1Context.h" + #include "mozilla/dom/WebGLRenderingContextBinding.h" - #include "mozilla/Telemetry.h" -using namespace mozilla; +namespace mozilla { -// ----------------------------------------------------------------------------- -// CONSTRUCTOR & DESTRUCTOR +/*static*/ WebGL1Context* +WebGL1Context::Create() +{ + return new WebGL1Context(); +} WebGL1Context::WebGL1Context() : WebGLContext() { - } WebGL1Context::~WebGL1Context() { - } - -// ----------------------------------------------------------------------------- -// IMPLEMENT nsWrapperCache +//////////////////////////////////////// +// nsWrapperCache JSObject* -WebGL1Context::WrapObject(JSContext *cx) +WebGL1Context::WrapObject(JSContext* cx) { return dom::WebGLRenderingContextBinding::Wrap(cx, this); } +} // namespace mozilla -// ----------------------------------------------------------------------------- -// INSTANCING nsIDOMWebGLRenderingContext +//////////////////////////////////////// +// nsIDOMWebGLRenderingContext nsresult -NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult) +NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result) { - Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); - nsIDOMWebGLRenderingContext* ctx = new WebGL1Context(); + mozilla::Telemetry::Accumulate(mozilla::Telemetry::CANVAS_WEBGL_USED, 1); - NS_ADDREF(*aResult = ctx); + nsIDOMWebGLRenderingContext* ctx = mozilla::WebGL1Context::Create(); + + NS_ADDREF(*out_result = ctx); return NS_OK; } -
--- a/dom/canvas/WebGL1Context.h +++ b/dom/canvas/WebGL1Context.h @@ -1,46 +1,35 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 WEBGL1CONTEXT_H_ -#define WEBGL1CONTEXT_H_ +#ifndef WEBGL_1_CONTEXT_H_ +#define WEBGL_1_CONTEXT_H_ #include "WebGLContext.h" namespace mozilla { class WebGL1Context : public WebGLContext { -// ----------------------------------------------------------------------------- -// PUBLIC public: + static WebGL1Context* Create(); - // ------------------------------------------------------------------------- - // CONSTRUCTOR & DESTRUCTOR +private: + WebGL1Context(); - WebGL1Context(); +public: virtual ~WebGL1Context(); - - // ------------------------------------------------------------------------- - // IMPLEMENT WebGLContext - - virtual bool IsWebGL2() const MOZ_OVERRIDE - { + virtual bool IsWebGL2() const MOZ_OVERRIDE { return false; } - - // ------------------------------------------------------------------------- - // IMPLEMENT nsWrapperCache - - virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; - - + // nsWrapperCache + virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; }; } // namespace mozilla -#endif +#endif // WEBGL_1_CONTEXT_H_
--- a/dom/canvas/WebGL2ContextSamplers.cpp +++ b/dom/canvas/WebGL2ContextSamplers.cpp @@ -1,78 +1,218 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 "WebGL2Context.h" +#include "WebGLSampler.h" #include "GLContext.h" using namespace mozilla; using namespace mozilla::dom; already_AddRefed<WebGLSampler> WebGL2Context::CreateSampler() { - MOZ_CRASH("Not Implemented."); - return nullptr; + if (IsContextLost()) + return nullptr; + + GLuint sampler; + MakeContextCurrent(); + gl->fGenSamplers(1, &sampler); + + nsRefPtr<WebGLSampler> globj = new WebGLSampler(this, sampler); + return globj.forget(); } void WebGL2Context::DeleteSampler(WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler)) + return; + + if (!sampler || sampler->IsDeleted()) + return; + + sampler->RequestDelete(); } bool WebGL2Context::IsSampler(WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); - return false; + if (IsContextLost()) + return false; + + if (!sampler) + return false; + + if (!ValidateObjectAllowDeleted("isSampler", sampler)) + return false; + + if (sampler->IsDeleted()) + return false; + + return !sampler->HasEverBeenBound(); } void WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!ValidateObjectAllowDeletedOrNull("bindSampler", sampler)) + return; + + if (GLint(unit) >= mGLMaxTextureUnits) + return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits); + + if (sampler && sampler->IsDeleted()) + return ErrorInvalidOperation("bindSampler: binding deleted sampler"); + + WebGLContextUnchecked::BindSampler(unit, sampler); } void WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteri: invalid sampler"); + + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri")) + return; + + WebGLContextUnchecked::SamplerParameteri(sampler, pname, param); } void WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Int32Array& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteriv: invalid sampler"); + + param.ComputeLengthAndData(); + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv")) + return; + + WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data()); } void WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLint>& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameteriv: invalid sampler"); + + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv")) + return; + + WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements()); } void WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterf: invalid sampler"); + + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf")) + return; + + WebGLContextUnchecked::SamplerParameterf(sampler, pname, param); } void WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Float32Array& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterfv: invalid sampler"); + + param.ComputeLengthAndData(); + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv")) + return; + + WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data()); } void WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLfloat>& param) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("samplerParameterfv: invalid sampler"); + + if (param.Length() < 1) + return /* TODO(djg): Error message */; + + /* TODO(djg): All of these calls in ES3 only take 1 param */ + if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv")) + return; + + WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements()); } void WebGL2Context::GetSamplerParameter(JSContext*, WebGLSampler* sampler, GLenum pname, JS::MutableHandleValue retval) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sampler || sampler->IsDeleted()) + return ErrorInvalidOperation("getSamplerParameter: invalid sampler"); + + if (!ValidateSamplerParameterName(pname, "getSamplerParameter")) + return; + + retval.set(JS::NullValue()); + + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + case LOCAL_GL_TEXTURE_MAG_FILTER: + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + case LOCAL_GL_TEXTURE_COMPARE_MODE: + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + retval.set(JS::Int32Value( + WebGLContextUnchecked::GetSamplerParameteriv(sampler, pname))); + return; + + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + retval.set(JS::Float32Value( + WebGLContextUnchecked::GetSamplerParameterfv(sampler, pname))); + return; + } }
--- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -2,25 +2,26 @@ /* 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 "WebGLContext.h" #include "WebGLContextLossHandler.h" #include "WebGL1Context.h" -#include "WebGLObjectModel.h" +#include "WebGLBuffer.h" +#include "WebGLContextUtils.h" #include "WebGLExtensions.h" -#include "WebGLContextUtils.h" -#include "WebGLBuffer.h" +#include "WebGLFramebuffer.h" +#include "WebGLMemoryTracker.h" +#include "WebGLObjectModel.h" +#include "WebGLQuery.h" +#include "WebGLSampler.h" +#include "WebGLVertexArray.h" #include "WebGLVertexAttribData.h" -#include "WebGLMemoryTracker.h" -#include "WebGLFramebuffer.h" -#include "WebGLVertexArray.h" -#include "WebGLQuery.h" #include "GLBlitHelper.h" #include "AccessCheck.h" #include "nsIConsoleService.h" #include "nsServiceManagerUtils.h" #include "nsIClassInfoImpl.h" #include "nsContentUtils.h" #include "nsIXPConnect.h" @@ -221,17 +222,17 @@ WebGLContextOptions::WebGLContextOptions preserveDrawingBuffer(false) { // Set default alpha state based on preference. if (Preferences::GetBool("webgl.default-no-alpha", false)) alpha = false; } WebGLContext::WebGLContext() - : gl(nullptr) + : WebGLContextUnchecked(nullptr) , mNeedsFakeNoAlpha(false) { mGeneration = 0; mInvalidated = false; mShouldPresent = true; mResetLayer = true; mOptionsFrozen = false; @@ -366,16 +367,18 @@ WebGLContext::DestroyResourcesAndContext while (!mFramebuffers.isEmpty()) mFramebuffers.getLast()->DeleteOnce(); while (!mShaders.isEmpty()) mShaders.getLast()->DeleteOnce(); while (!mPrograms.isEmpty()) mPrograms.getLast()->DeleteOnce(); while (!mQueries.isEmpty()) mQueries.getLast()->DeleteOnce(); + while (!mSamplers.isEmpty()) + mSamplers.getLast()->DeleteOnce(); mBlackOpaqueTexture2D = nullptr; mBlackOpaqueTextureCubeMap = nullptr; mBlackTransparentTexture2D = nullptr; mBlackTransparentTextureCubeMap = nullptr; if (mFakeVertexAttrib0BufferObject) { gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
--- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -10,16 +10,17 @@ #include "mozilla/CheckedInt.h" #include "mozilla/EnumeratedArray.h" #include "mozilla/LinkedList.h" #include "mozilla/UniquePtr.h" #include "mozilla/WeakPtr.h" #include "GLDefs.h" #include "WebGLActiveInfo.h" +#include "WebGLContextUnchecked.h" #include "WebGLObjectModel.h" #include "WebGLRenderbuffer.h" #include "WebGLTexture.h" #include "WebGLStrongTypes.h" #include <stdarg.h> #include "nsTArray.h" #include "nsCycleCollectionNoteChild.h" @@ -73,20 +74,22 @@ class WebGLExtensionBase; class WebGLBuffer; struct WebGLVertexAttribData; class WebGLShader; class WebGLProgram; class WebGLQuery; class WebGLUniformLocation; class WebGLFramebuffer; class WebGLRenderbuffer; +class WebGLSampler; class WebGLShaderPrecisionFormat; class WebGLTexture; class WebGLVertexArray; + namespace dom { class ImageData; class Element; struct WebGLContextAttributes; template<typename> struct Nullable; } @@ -122,20 +125,39 @@ struct WebGLContextOptions { bool premultipliedAlpha; bool antialias; bool preserveDrawingBuffer; }; // From WebGLContextUtils TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget); +class WebGLIntOrFloat { + enum { + Int, + Float + } mType; + union { + GLint i; + GLfloat f; + } mValue; + +public: + explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; } + explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; } + + GLint AsInt() const { return (mType == Int) ? mValue.i : NS_lroundf(mValue.f); } + GLfloat AsFloat() const { return (mType == Float) ? mValue.f : GLfloat(mValue.i); } +}; + class WebGLContext : public nsIDOMWebGLRenderingContext, public nsICanvasRenderingContextInternal, public nsSupportsWeakReference, + public WebGLContextUnchecked, public WebGLRectangleObject, public nsWrapperCache, public SupportsWeakPtr<WebGLContext> { friend class WebGLContextUserData; friend class WebGLExtensionCompressedTextureATC; friend class WebGLExtensionCompressedTextureETC1; friend class WebGLExtensionCompressedTexturePVRTC; @@ -1000,18 +1022,16 @@ protected: virtual JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname); // Returns x rounded to the next highest multiple of y. static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) { return ((x + y - 1) / y) * y; } - nsRefPtr<gl::GLContext> gl; - CheckedUint32 mGeneration; WebGLContextOptions mOptions; bool mInvalidated; bool mResetLayer; bool mOptionsFrozen; bool mMinCapability; @@ -1133,16 +1153,20 @@ protected: bool ValidateGLSLVariableName(const nsAString& name, const char *info); bool ValidateGLSLCharacter(char16_t c); bool ValidateGLSLString(const nsAString& string, const char *info); bool ValidateCopyTexImage(GLenum internalformat, WebGLTexImageFunc func, WebGLTexDimensions dims); + + bool ValidateSamplerParameterName(GLenum pname, const char* info); + bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info); + bool ValidateTexImage(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, GLint border, GLenum format, GLenum type, WebGLTexImageFunc func, WebGLTexDimensions dims); bool ValidateTexImageTarget(GLenum target, @@ -1320,16 +1344,19 @@ protected: LinkedList<WebGLBuffer> mBuffers; LinkedList<WebGLProgram> mPrograms; LinkedList<WebGLQuery> mQueries; LinkedList<WebGLShader> mShaders; LinkedList<WebGLRenderbuffer> mRenderbuffers; LinkedList<WebGLFramebuffer> mFramebuffers; LinkedList<WebGLVertexArray> mVertexArrays; + // TODO(djg): Does this need a rethink? Should it be WebGL2Context? + LinkedList<WebGLSampler> mSamplers; + WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray; // PixelStore parameters uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion; bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha; WebGLContextFakeBlackStatus mFakeBlackStatus; @@ -1435,16 +1462,17 @@ public: void GenerateWarning(const char *fmt, va_list ap); friend class WebGLTexture; friend class WebGLFramebuffer; friend class WebGLRenderbuffer; friend class WebGLProgram; friend class WebGLQuery; friend class WebGLBuffer; + friend class WebGLSampler; friend class WebGLShader; friend class WebGLUniformLocation; friend class WebGLVertexArray; friend class WebGLVertexArrayFake; friend class WebGLVertexArrayGL; }; // used by DOM bindings in conjunction with GetParentObject
new file mode 100644 --- /dev/null +++ b/dom/canvas/WebGLContextUnchecked.cpp @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "WebGLContextUnchecked.h" + +#include "GLContext.h" +#include "WebGLSampler.h" + +namespace mozilla { + +WebGLContextUnchecked::WebGLContextUnchecked(gl::GLContext* gl) + : gl(gl) +{ } + + +// ----------------------------------------------------------------------------- +// Sampler Objects + +void +WebGLContextUnchecked::BindSampler(GLuint unit, WebGLSampler* sampler) +{ + gl->MakeCurrent(); + gl->fBindSampler(unit, sampler ? sampler->GLName() : 0); + if (sampler) + sampler->BindTo(LOCAL_GL_SAMPLER_BINDING); +} + +GLint +WebGLContextUnchecked::GetSamplerParameteriv(WebGLSampler* sampler, + GLenum pname) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + + GLint param = 0; + gl->MakeCurrent(); + gl->fGetSamplerParameteriv(sampler->GLName(), pname, ¶m); + + return param; +} + +GLfloat +WebGLContextUnchecked::GetSamplerParameterfv(WebGLSampler* sampler, + GLenum pname) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + + GLfloat param = 0.0f; + gl->MakeCurrent(); + gl->fGetSamplerParameterfv(sampler->GLName(), pname, ¶m); + return param; +} + +void +WebGLContextUnchecked::SamplerParameteri(WebGLSampler* sampler, + GLenum pname, + GLint param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameteri(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameteriv(WebGLSampler* sampler, + GLenum pname, + const GLint* param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameteriv(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameterf(WebGLSampler* sampler, + GLenum pname, + GLfloat param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameterf(sampler->GLName(), pname, param); +} + +void +WebGLContextUnchecked::SamplerParameterfv(WebGLSampler* sampler, + GLenum pname, + const GLfloat* param) +{ + MOZ_ASSERT(sampler, "Did you validate?"); + gl->MakeCurrent(); + gl->fSamplerParameterfv(sampler->GLName(), pname, param); +} + +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/dom/canvas/WebGLContextUnchecked.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 WEBGLCONTEXTUNCHECKED_H +#define WEBGLCONTEXTUNCHECKED_H + +#include "GLDefs.h" +#include "WebGLTypes.h" +#include "nsAutoPtr.h" +#include "nsTArray.h" + +namespace mozilla { + +class WebGLSampler; +namespace gl { + class GLContext; +} + +class WebGLContextUnchecked +{ +public: + explicit WebGLContextUnchecked(gl::GLContext* gl); + + // ------------------------------------------------------------------------- + // Sampler Objects + void BindSampler(GLuint unit, WebGLSampler* sampler); + + GLint GetSamplerParameteriv(WebGLSampler* sampler, GLenum pname); + GLfloat GetSamplerParameterfv(WebGLSampler* sampler, GLenum pname); + + void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param); + void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const GLint* param); + void SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param); + void SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const GLfloat* param); + +protected: // data + nsRefPtr<gl::GLContext> gl; +}; + +} // namespace mozilla + +#endif // !WEBGLCONTEXTUNCHECKED_H
--- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -374,16 +374,128 @@ WebGLContext::ValidateFramebufferAttachm return true; } ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment); return false; } /** + * Return true if pname is valid for GetSamplerParameter calls. + */ +bool +WebGLContext::ValidateSamplerParameterName(GLenum pname, const char* info) +{ + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + case LOCAL_GL_TEXTURE_MAG_FILTER: + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + case LOCAL_GL_TEXTURE_COMPARE_MODE: + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + return true; + + default: + ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname)); + return false; + } +} + +/** + * Return true if pname and param are valid combination for SamplerParameter calls. + */ +bool +WebGLContext::ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info) +{ + const GLenum p = param.AsInt(); + + switch (pname) { + case LOCAL_GL_TEXTURE_MIN_FILTER: + switch (p) { + case LOCAL_GL_NEAREST: + case LOCAL_GL_LINEAR: + case LOCAL_GL_NEAREST_MIPMAP_NEAREST: + case LOCAL_GL_NEAREST_MIPMAP_LINEAR: + case LOCAL_GL_LINEAR_MIPMAP_NEAREST: + case LOCAL_GL_LINEAR_MIPMAP_LINEAR: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_MAG_FILTER: + switch (p) { + case LOCAL_GL_NEAREST: + case LOCAL_GL_LINEAR: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_WRAP_S: + case LOCAL_GL_TEXTURE_WRAP_T: + case LOCAL_GL_TEXTURE_WRAP_R: + switch (p) { + case LOCAL_GL_CLAMP_TO_EDGE: + case LOCAL_GL_REPEAT: + case LOCAL_GL_MIRRORED_REPEAT: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_MIN_LOD: + case LOCAL_GL_TEXTURE_MAX_LOD: + return true; + + case LOCAL_GL_TEXTURE_COMPARE_MODE: + switch (param.AsInt()) { + case LOCAL_GL_NONE: + case LOCAL_GL_COMPARE_REF_TO_TEXTURE: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + case LOCAL_GL_TEXTURE_COMPARE_FUNC: + switch (p) { + case LOCAL_GL_LEQUAL: + case LOCAL_GL_GEQUAL: + case LOCAL_GL_LESS: + case LOCAL_GL_GREATER: + case LOCAL_GL_EQUAL: + case LOCAL_GL_NOTEQUAL: + case LOCAL_GL_ALWAYS: + case LOCAL_GL_NEVER: + return true; + + default: + ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p)); + return false; + } + + default: + ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname)); + return false; + } +} + + +/** * Return true if format is a valid texture image format for source, * taking into account enabled WebGL extensions. */ bool WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebGLTexDimensions dims) { /* Core WebGL texture formats */ if (format == LOCAL_GL_ALPHA || @@ -1713,18 +1825,17 @@ WebGLContext::InitAndValidateGL() // Note that this used to cause crashes on old ATI drivers... hopefully not a significant // problem anymore. See bug 602183. gl->fEnable(LOCAL_GL_POINT_SPRITE); } #ifdef XP_MACOSX if (gl->WorkAroundDriverBugs() && gl->Vendor() == gl::GLVendor::ATI && - nsCocoaFeatures::OSXVersionMajor() == 10 && - nsCocoaFeatures::OSXVersionMinor() < 9) + !nsCocoaFeatures::IsAtLeastVersion(10,9)) { // The Mac ATI driver, in all known OSX version up to and including 10.8, // renders points sprites upside-down. Apple bug 11778921 gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN, LOCAL_GL_LOWER_LEFT); } #endif // Check the shader validator pref
--- a/dom/canvas/WebGLFramebuffer.cpp +++ b/dom/canvas/WebGLFramebuffer.cpp @@ -368,17 +368,17 @@ WebGLFramebuffer::Attachment::FinalizeAt LOCAL_GL_RENDERBUFFER, 0); } return; } MOZ_ASSERT(HasImage()); if (Texture()) { - MOZ_ASSERT(gl == Texture()->Context()->gl); + MOZ_ASSERT(gl == Texture()->Context()->GL()); const GLenum imageTarget = ImageTarget().get(); const GLint mipLevel = MipLevel(); const GLuint glName = Texture()->GLName(); if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, imageTarget, glName, mipLevel);
--- a/dom/canvas/WebGLSampler.cpp +++ b/dom/canvas/WebGLSampler.cpp @@ -7,42 +7,45 @@ #include "WebGLSampler.h" #include "GLContext.h" #include "mozilla/dom/WebGL2RenderingContextBinding.h" using namespace mozilla; -WebGLSampler::WebGLSampler(WebGLContext* context) - : WebGLBindableName<GLenum>(0), +WebGLSampler::WebGLSampler(WebGLContext* context, GLuint sampler) + : WebGLBindableName<GLenum>(sampler), WebGLContextBoundObject(context) { - MOZ_CRASH("Not Implemented."); + mContext->mSamplers.insertBack(this); } WebGLSampler::~WebGLSampler() -{} +{ + DeleteOnce(); +} void WebGLSampler::Delete() { - MOZ_CRASH("Not Implemented."); + mContext->MakeContextCurrent(); + mContext->gl->fDeleteSamplers(1, &mGLName); + + removeFrom(mContext->mSamplers); } WebGLContext* WebGLSampler::GetParentObject() const { - MOZ_CRASH("Not Implemented."); - return nullptr; + return Context(); } JSObject* WebGLSampler::WrapObject(JSContext* cx) { - MOZ_CRASH("Not Implemented."); return dom::WebGLSamplerBinding::Wrap(cx, this); } NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLSampler, Release)
--- a/dom/canvas/WebGLSampler.h +++ b/dom/canvas/WebGLSampler.h @@ -1,15 +1,15 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 WEBGL2SAMPLER_H_ -#define WEBGL2SAMPLER_H_ +#ifndef WEBGLSAMPLER_H_ +#define WEBGLSAMPLER_H_ #include "WebGLBindableName.h" #include "WebGLObjectModel.h" #include "nsWrapperCache.h" #include "mozilla/LinkedList.h" @@ -21,26 +21,28 @@ class WebGLSampler MOZ_FINAL , public WebGLRefCountedObject<WebGLSampler> , public LinkedListElement<WebGLSampler> , public WebGLContextBoundObject { friend class WebGLContext2; public: - explicit WebGLSampler(WebGLContext* aContext); + explicit WebGLSampler(WebGLContext* aContext, GLuint sampler); void Delete(); WebGLContext* GetParentObject() const; virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; +private: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler) private: ~WebGLSampler(); }; } // namespace mozilla -#endif // !WEBGL2SAMPLER_H_ +#endif // !WEBGLSAMPLER_H_
--- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -59,16 +59,17 @@ UNIFIED_SOURCES += [ 'WebGLContextBuffers.cpp', 'WebGLContextDraw.cpp', 'WebGLContextExtensions.cpp', 'WebGLContextFramebufferOperations.cpp', 'WebGLContextGL.cpp', 'WebGLContextLossHandler.cpp', 'WebGLContextReporter.cpp', 'WebGLContextState.cpp', + 'WebGLContextUnchecked.cpp', 'WebGLContextUtils.cpp', 'WebGLContextValidate.cpp', 'WebGLContextVertexArray.cpp', 'WebGLContextVertices.cpp', 'WebGLElementArrayCache.cpp', 'WebGLExtensionBase.cpp', 'WebGLExtensionBlendMinMax.cpp', 'WebGLExtensionColorBufferFloat.cpp',
--- a/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html +++ b/dom/canvas/test/webgl-mochitest/test_webgl_request_mismatch.html @@ -1,35 +1,90 @@ <!DOCTYPE HTML> -<title>WebGL test: Mismatched 'webgl' and 'experimental-webgl' context requests</title> +<html> +<head> <script src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" href="/tests/SimpleTest/test.css"> +</head> <body> -<canvas id="c1"></canvas> -<canvas id="c2"></canvas> -<canvas id="c3"></canvas> -<canvas id="c4"></canvas> <script> -function testContextRetrieval(canvasId, creationId, requestId) { - var canvas = document.getElementById(canvasId); - ok(canvas, 'Invalid `canvasId`: ' + canvasId); +WEBGL_TYPES = {}; +WEBGL_TYPES['experimental-webgl'] = true; +WEBGL_TYPES['webgl'] = true; - var createdGL = canvas.getContext(creationId); - if (!createdGL) - return; // No WebGL on this machine? +function AreBothIn(a, b, set) { + return (a in set) && (b in set); +} - var requestedGL = canvas.getContext(requestId); - if (creationId == requestId) { - ok(requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should succeed.'); - ok(requestedGL == createdGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should match.'); - } else { - ok(!requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should fail.'); - } +function IsAlias(typeA, typeB) { + if (typeA == typeB) + return true; + + if (AreBothIn(typeA, typeB, WEBGL_TYPES)) + return true; + + return false; } -testContextRetrieval('c1', 'experimental-webgl', 'webgl'); -testContextRetrieval('c2', 'webgl', 'experimental-webgl'); -testContextRetrieval('c3', 'experimental-webgl', 'experimental-webgl'); -testContextRetrieval('c4', 'webgl', 'webgl'); +function TestContextRetrieval(creationType, requestType, functionalTypeSet) { + var canvas = document.createElement('canvas'); + var createdGL = canvas.getContext(creationType); + + var didCreationSucceed = (createdGL != null); + if (creationType in functionalTypeSet) { + ok(createdGL, 'Context creation should succeed for type \'' + + creationType + '\''); + } else { + ok(!createdGL, 'Context creation should fail for type \'' + + creationType + '\''); + return; + } + + var requestedGL = canvas.getContext(requestType); + + if (requestType in functionalTypeSet && + IsAlias(creationType, requestType)) + { + ok(requestedGL, 'Request for \'' + requestType + '\' from \'' + + creationType + '\' should succeed.'); + ok(requestedGL == createdGL, 'Request for \'' + requestType + + '\' from \'' + creationType + + '\' should match.'); + } else { + ok(!requestedGL, 'Request for \'' + requestType + '\' from \'' + + creationType + '\' should fail.'); + } +} + +function IsWebGLFunctional() { + var canvas = document.createElement('canvas'); + return canvas.getContext('experimental-webgl') != null; +} + +function IsWebGLConformant() { + var canvas = document.createElement('canvas'); + return canvas.getContext('webgl') != null; +} + +var typeList = ['2d', 'experimental-webgl', 'webgl']; +var functionalTypeSet = {}; +functionalTypeSet['2d'] = true; + +if (IsWebGLFunctional()) + functionalTypeSet['experimental-webgl'] = true; + +if (IsWebGLConformant()) + functionalTypeSet['webgl'] = true; + +for (var i in typeList) { + var creationType = typeList[i]; + + for (var j in typeList) { + var requestType = typeList[j]; + + TestContextRetrieval(creationType, requestType, functionalTypeSet); + } +} </script> - +</body> +</html>
--- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -29,16 +29,17 @@ #include "nsIWritablePropertyBag2.h" #include "nsIXPConnect.h" #include "nsJSUtils.h" #include "nsLayoutUtils.h" #include "nsMathUtils.h" #include "nsNetUtil.h" #include "nsStreamUtils.h" #include "ActiveLayerTracker.h" +#include "WebGL1Context.h" #include "WebGL2Context.h" using namespace mozilla::layers; using namespace mozilla::gfx; NS_IMPL_NS_NEW_HTML_ELEMENT(Canvas) namespace { @@ -643,147 +644,131 @@ HTMLCanvasElement::MozGetAsFileImpl(cons nsRefPtr<File> file = File::CreateMemoryFile(win, imgData, (uint32_t)imgSize, aName, type, PR_Now()); file.forget(aResult); return NS_OK; } -nsresult -HTMLCanvasElement::GetContextHelper(const nsAString& aContextId, - nsICanvasRenderingContextInternal **aContext) +static bool +GetCanvasContextType(const nsAString& str, CanvasContextType* const out_type) { - NS_ENSURE_ARG(aContext); + if (str.EqualsLiteral("2d")) { + *out_type = CanvasContextType::Canvas2D; + return true; + } - if (aContextId.EqualsLiteral("2d")) { - Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1); - nsRefPtr<CanvasRenderingContext2D> ctx = - new CanvasRenderingContext2D(); - - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; + if (str.EqualsLiteral("experimental-webgl")) { + *out_type = CanvasContextType::WebGL1; + return true; } - if (WebGL2Context::IsSupported() && - aContextId.EqualsLiteral("experimental-webgl2")) - { - Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); - nsRefPtr<WebGL2Context> ctx = WebGL2Context::Create(); - - if (ctx == nullptr) { - return NS_ERROR_NOT_IMPLEMENTED; - } - - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; +#ifdef MOZ_WEBGL_CONFORMANT + if (str.EqualsLiteral("webgl")) { + /* WebGL 1.0, $2.1 "Context Creation": + * If the user agent supports both the webgl and experimental-webgl + * canvas context types, they shall be treated as aliases. + */ + *out_type = CanvasContextType::WebGL1; + return true; } - - NS_ConvertUTF16toUTF8 ctxId(aContextId); +#endif - // check that ctxId is clamped to A-Za-z0-9_- - for (uint32_t i = 0; i < ctxId.Length(); i++) { - if ((ctxId[i] < 'A' || ctxId[i] > 'Z') && - (ctxId[i] < 'a' || ctxId[i] > 'z') && - (ctxId[i] < '0' || ctxId[i] > '9') && - (ctxId[i] != '-') && - (ctxId[i] != '_')) - { - // XXX ERRMSG we need to report an error to developers here! (bug 329026) - return NS_OK; + if (WebGL2Context::IsSupported()) { + if (str.EqualsLiteral("experimental-webgl2")) { + *out_type = CanvasContextType::WebGL2; + return true; } } - nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id="); - ctxString.Append(ctxId); + return false; +} + +static already_AddRefed<nsICanvasRenderingContextInternal> +CreateContextForCanvas(CanvasContextType contextType, HTMLCanvasElement* canvas) +{ + nsRefPtr<nsICanvasRenderingContextInternal> ret; + + switch (contextType) { + case CanvasContextType::Canvas2D: + Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1); + ret = new CanvasRenderingContext2D(); + break; - nsresult rv; - nsCOMPtr<nsICanvasRenderingContextInternal> ctx = - do_CreateInstance(ctxString.get(), &rv); - if (rv == NS_ERROR_OUT_OF_MEMORY) { - *aContext = nullptr; - return NS_ERROR_OUT_OF_MEMORY; + case CanvasContextType::WebGL1: + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); + + ret = WebGL1Context::Create(); + if (!ret) + return nullptr; + break; + + case CanvasContextType::WebGL2: + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1); + + ret = WebGL2Context::Create(); + if (!ret) + return nullptr; + break; } - if (NS_FAILED(rv)) { - *aContext = nullptr; - // XXX ERRMSG we need to report an error to developers here! (bug 329026) - return NS_OK; - } + MOZ_ASSERT(ret); - ctx->SetCanvasElement(this); - ctx.forget(aContext); - return NS_OK; + ret->SetCanvasElement(canvas); + return ret.forget(); } nsresult HTMLCanvasElement::GetContext(const nsAString& aContextId, nsISupports** aContext) { ErrorResult rv; - *aContext = - GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take(); + *aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take(); return rv.ErrorCode(); } -static bool -IsContextIdWebGL(const nsAString& str) -{ - return str.EqualsLiteral("webgl") || - str.EqualsLiteral("experimental-webgl"); -} - already_AddRefed<nsISupports> HTMLCanvasElement::GetContext(JSContext* aCx, const nsAString& aContextId, JS::Handle<JS::Value> aContextOptions, ErrorResult& rv) { - if (mCurrentContextId.IsEmpty()) { - rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext)); - if (rv.Failed() || !mCurrentContext) { + CanvasContextType contextType; + if (!GetCanvasContextType(aContextId, &contextType)) + return nullptr; + + if (!mCurrentContext) { + // This canvas doesn't have a context yet. + + nsRefPtr<nsICanvasRenderingContextInternal> context; + context = CreateContextForCanvas(contextType, this); + if (!context) return nullptr; - } // Ensure that the context participates in CC. Note that returning a // CC participant from QI doesn't addref. - nsXPCOMCycleCollectionParticipant *cp = nullptr; - CallQueryInterface(mCurrentContext, &cp); + nsXPCOMCycleCollectionParticipant* cp = nullptr; + CallQueryInterface(context, &cp); if (!cp) { - mCurrentContext = nullptr; rv.Throw(NS_ERROR_FAILURE); return nullptr; } + mCurrentContext = context.forget(); + mCurrentContextType = contextType; + rv = UpdateContext(aCx, aContextOptions); if (rv.Failed()) { rv = NS_OK; // See bug 645792 return nullptr; } - mCurrentContextId.Assign(aContextId); - } - - if (!mCurrentContextId.Equals(aContextId)) { - if (IsContextIdWebGL(aContextId) && - IsContextIdWebGL(mCurrentContextId)) - { - // Warn when we get a request for a webgl context with an id that differs - // from the id it was created with. - nsCString creationId = NS_LossyConvertUTF16toASCII(mCurrentContextId); - nsCString requestId = NS_LossyConvertUTF16toASCII(aContextId); - JS_ReportWarning(aCx, "WebGL: Retrieving a WebGL context from a canvas " - "via a request id ('%s') different from the id used " - "to create the context ('%s') is not allowed.", - requestId.get(), - creationId.get()); - } - - //XXX eventually allow for more than one active context on a given canvas - return nullptr; + } else { + // We already have a context of some type. + if (contextType != mCurrentContextType) + return nullptr; } nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext; return context.forget(); } NS_IMETHODIMP HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId, @@ -793,32 +778,38 @@ HTMLCanvasElement::MozGetIPCContext(cons // XXX ERRMSG we need to report an error to developers here! (bug 329026) return NS_ERROR_DOM_SECURITY_ERR; } // We only support 2d shmem contexts for now. if (!aContextId.EqualsLiteral("2d")) return NS_ERROR_INVALID_ARG; - if (mCurrentContextId.IsEmpty()) { - nsresult rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext)); - NS_ENSURE_SUCCESS(rv, rv); - if (!mCurrentContext) { + CanvasContextType contextType = CanvasContextType::Canvas2D; + + if (!mCurrentContext) { + // This canvas doesn't have a context yet. + + nsRefPtr<nsICanvasRenderingContextInternal> context; + context = CreateContextForCanvas(contextType, this); + if (!context) { + *aContext = nullptr; return NS_OK; } + mCurrentContext = context; mCurrentContext->SetIsIPC(true); - - rv = UpdateContext(nullptr, JS::NullHandleValue); - NS_ENSURE_SUCCESS(rv, rv); + mCurrentContextType = contextType; - mCurrentContextId.Assign(aContextId); - } else if (!mCurrentContextId.Equals(aContextId)) { - //XXX eventually allow for more than one active context on a given canvas - return NS_ERROR_INVALID_ARG; + nsresult rv = UpdateContext(nullptr, JS::NullHandleValue); + NS_ENSURE_SUCCESS(rv, rv); + } else { + // We already have a context of some type. + if (contextType != mCurrentContextType) + return NS_ERROR_INVALID_ARG; } NS_ADDREF (*aContext = mCurrentContext); return NS_OK; } nsresult HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewContextOptions) @@ -826,31 +817,28 @@ HTMLCanvasElement::UpdateContext(JSConte if (!mCurrentContext) return NS_OK; nsIntSize sz = GetWidthHeight(); nsresult rv = mCurrentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque)); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } rv = mCurrentContext->SetContextOptions(aCx, aNewContextOptions); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } rv = mCurrentContext->SetDimensions(sz.width, sz.height); if (NS_FAILED(rv)) { mCurrentContext = nullptr; - mCurrentContextId.Truncate(); return rv; } return rv; } nsIntSize HTMLCanvasElement::GetSize()
--- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -2,16 +2,17 @@ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if !defined(mozilla_dom_HTMLCanvasElement_h) #define mozilla_dom_HTMLCanvasElement_h #include "mozilla/Attributes.h" +#include "mozilla/TypedEnum.h" #include "nsIDOMHTMLCanvasElement.h" #include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsSize.h" #include "nsError.h" #include "mozilla/gfx/Rect.h" @@ -30,16 +31,22 @@ class SourceSurface; namespace dom { class File; class FileCallback; class HTMLCanvasPrintState; class PrintCallback; +MOZ_BEGIN_ENUM_CLASS(CanvasContextType, uint8_t) + Canvas2D, + WebGL1, + WebGL2 +MOZ_END_ENUM_CLASS(CanvasContextType) + class HTMLCanvasElement MOZ_FINAL : public nsGenericHTMLElement, public nsIDOMHTMLCanvasElement { enum { DEFAULT_CANVAS_WIDTH = 300, DEFAULT_CANVAS_HEIGHT = 150 }; @@ -224,21 +231,19 @@ protected: nsIInputStream** aStream); nsresult ToDataURLImpl(JSContext* aCx, const nsAString& aMimeType, const JS::Value& aEncoderOptions, nsAString& aDataURL); nsresult MozGetAsFileImpl(const nsAString& aName, const nsAString& aType, nsIDOMFile** aResult); - nsresult GetContextHelper(const nsAString& aContextId, - nsICanvasRenderingContextInternal **aContext); void CallPrintCallback(); - nsString mCurrentContextId; + CanvasContextType mCurrentContextType; nsRefPtr<HTMLCanvasElement> mOriginalCanvas; nsRefPtr<PrintCallback> mPrintCallback; nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext; nsRefPtr<HTMLCanvasPrintState> mPrintState; public: // Record whether this canvas should be write-only or not. // We set this when script paints an image from a different origin.
--- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -454,70 +454,48 @@ ImageDocument::DOMToggleImageSize() } NS_IMETHODIMP ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData) { if (aType == imgINotificationObserver::SIZE_AVAILABLE) { nsCOMPtr<imgIContainer> image; aRequest->GetImage(getter_AddRefs(image)); - return OnStartContainer(aRequest, image); + return OnSizeAvailable(aRequest, image); } - // Do these two off a script runner because decode complete notifications often - // come during painting and these will trigger invalidation. - if (aType == imgINotificationObserver::DECODE_COMPLETE) { + // Run this using a script runner because HAS_TRANSPARENCY notifications can + // come during painting and this will trigger invalidation. + if (aType == imgINotificationObserver::HAS_TRANSPARENCY) { nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableMethod(this, &ImageDocument::AddDecodedClass); - nsContentUtils::AddScriptRunner(runnable); - } - - if (aType == imgINotificationObserver::DISCARD) { - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableMethod(this, &ImageDocument::RemoveDecodedClass); + NS_NewRunnableMethod(this, &ImageDocument::OnHasTransparency); nsContentUtils::AddScriptRunner(runnable); } if (aType == imgINotificationObserver::LOAD_COMPLETE) { uint32_t reqStatus; aRequest->GetImageStatus(&reqStatus); nsresult status = reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; - return OnStopRequest(aRequest, status); + return OnLoadComplete(aRequest, status); } return NS_OK; } void -ImageDocument::AddDecodedClass() +ImageDocument::OnHasTransparency() { if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) { return; } nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); mozilla::ErrorResult rv; - // Update the background-color of the image only after the - // image has been decoded to prevent flashes of just the - // background-color. - classList->Add(NS_LITERAL_STRING("decoded"), rv); -} - -void -ImageDocument::RemoveDecodedClass() -{ - if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) { - return; - } - - nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); - mozilla::ErrorResult rv; - // Remove any decoded-related styling when the image is unloaded. - classList->Remove(NS_LITERAL_STRING("decoded"), rv); + classList->Add(NS_LITERAL_STRING("transparent"), rv); } void ImageDocument::SetModeClass(eModeClasses mode) { nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); mozilla::ErrorResult rv; @@ -530,34 +508,33 @@ ImageDocument::SetModeClass(eModeClasses if (mode == eOverflowing) { classList->Add(NS_LITERAL_STRING("overflowing"), rv); } else { classList->Remove(NS_LITERAL_STRING("overflowing"), rv); } } nsresult -ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage) +ImageDocument::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) { // Styles have not yet been applied, so we don't know the final size. For now, // default to the image's intrinsic size. aImage->GetWidth(&mImageWidth); aImage->GetHeight(&mImageHeight); nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing); nsContentUtils::AddScriptRunner(runnable); UpdateTitleAndCharset(); return NS_OK; } nsresult -ImageDocument::OnStopRequest(imgIRequest *aRequest, - nsresult aStatus) +ImageDocument::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus) { UpdateTitleAndCharset(); // mImageContent can be null if the document is already destroyed if (NS_FAILED(aStatus) && mStringBundle && mImageContent) { nsAutoCString src; mDocumentURI->GetSpec(src); NS_ConvertUTF8toUTF16 srcString(src);
--- a/dom/html/ImageDocument.h +++ b/dom/html/ImageDocument.h @@ -46,19 +46,16 @@ public: NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE; NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ImageDocument, MediaDocument) friend class ImageListener; void DefaultCheckOverflowing() { CheckOverflowing(mResizeImageByDefault); } - void AddDecodedClass(); - void RemoveDecodedClass(); - // WebIDL API virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE; bool ImageResizingEnabled() const { return true; } @@ -102,18 +99,19 @@ protected: enum eModeClasses { eNone, eShrinkToFit, eOverflowing }; void SetModeClass(eModeClasses mode); - nsresult OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage); - nsresult OnStopRequest(imgIRequest *aRequest, nsresult aStatus); + nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage); + nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus); + void OnHasTransparency(); nsCOMPtr<nsIContent> mImageContent; float mVisibleWidth; float mVisibleHeight; int32_t mImageWidth; int32_t mImageHeight;
--- a/dom/html/moz.build +++ b/dom/html/moz.build @@ -107,17 +107,16 @@ EXPORTS.mozilla.dom += [ 'HTMLTextAreaElement.h', 'HTMLTimeElement.h', 'HTMLTitleElement.h', 'HTMLTrackElement.h', 'HTMLUnknownElement.h', 'HTMLVideoElement.h', 'ImageDocument.h', 'MediaError.h', - 'nsBrowserElement.h', 'RadioNodeList.h', 'TextTrackManager.h', 'TimeRanges.h', 'UndoManager.h', 'ValidityState.h', ] UNIFIED_SOURCES += [ @@ -186,17 +185,16 @@ UNIFIED_SOURCES += [ 'HTMLTimeElement.cpp', 'HTMLTitleElement.cpp', 'HTMLTrackElement.cpp', 'HTMLUnknownElement.cpp', 'HTMLVideoElement.cpp', 'ImageDocument.cpp', 'MediaDocument.cpp', 'MediaError.cpp', - 'nsBrowserElement.cpp', 'nsDOMStringMap.cpp', 'nsFormSubmission.cpp', 'nsGenericHTMLElement.cpp', 'nsGenericHTMLFrameElement.cpp', 'nsHTMLContentSink.cpp', 'nsHTMLDNSPrefetch.cpp', 'nsHTMLDocument.cpp', 'nsIConstraintValidation.cpp',
deleted file mode 100644 --- a/dom/html/nsBrowserElement.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsBrowserElement.h" - -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" -#include "mozilla/dom/BrowserElementBinding.h" -#include "mozilla/dom/DOMRequest.h" -#include "mozilla/dom/ScriptSettings.h" -#include "mozilla/dom/ToJSValue.h" - -#include "nsComponentManagerUtils.h" -#include "nsContentUtils.h" -#include "nsFrameLoader.h" -#include "nsIDOMDOMRequest.h" -#include "nsIDOMElement.h" -#include "nsINode.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsIPrincipal.h" -#include "nsWeakReference.h" - -using namespace mozilla::dom; - -namespace mozilla { - -static const char kRemoteBrowserPending[] = "remote-browser-pending"; -static const char kInprocessBrowserShown[] = "inprocess-browser-shown"; - -class nsBrowserElement::BrowserShownObserver : public nsIObserver - , public nsSupportsWeakReference -{ -public: - BrowserShownObserver(nsBrowserElement* aBrowserElement); - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - void AddObserver(); - void RemoveObserver(); -private: - virtual ~BrowserShownObserver(); - - // Weak reference to the browser element. nsBrowserElement has a - // reference to us. nsBrowserElement's destructor is responsible to - // null out this weak reference via RemoveObserver() - nsBrowserElement* mBrowserElement; -}; - -NS_IMPL_ISUPPORTS(nsBrowserElement::BrowserShownObserver, nsIObserver, nsISupportsWeakReference) - -nsBrowserElement::BrowserShownObserver::BrowserShownObserver(nsBrowserElement* aBrowserElement) - : mBrowserElement(aBrowserElement) -{ -} - -nsBrowserElement::BrowserShownObserver::~BrowserShownObserver() -{ - RemoveObserver(); -} - -NS_IMETHODIMP -nsBrowserElement::BrowserShownObserver::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - NS_ENSURE_TRUE(mBrowserElement, NS_OK); - - if (!strcmp(aTopic, kRemoteBrowserPending) || - !strcmp(aTopic, kInprocessBrowserShown)) { - nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(aSubject); - nsCOMPtr<nsIFrameLoader> myFrameLoader = mBrowserElement->GetFrameLoader(); - // The browser element API needs the frameloader to - // initialize. We still use the observer to get notified when the - // frameloader is created. So we check if the frameloader created - // is ours, then initialize the browser element API. - if (frameLoader && frameLoader == myFrameLoader) { - mBrowserElement->InitBrowserElementAPI(); - } - } - return NS_OK; -} - -void -nsBrowserElement::BrowserShownObserver::AddObserver() -{ - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - if (obs) { - obs->AddObserver(this, kRemoteBrowserPending, true); - obs->AddObserver(this, kInprocessBrowserShown, true); - } -} - -void -nsBrowserElement::BrowserShownObserver::RemoveObserver() -{ - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - if (obs) { - obs->RemoveObserver(this, kRemoteBrowserPending); - obs->RemoveObserver(this, kInprocessBrowserShown); - } - mBrowserElement = nullptr; -} - -bool -nsBrowserElement::IsBrowserElementOrThrow(ErrorResult& aRv) -{ - if (mBrowserElementAPI) { - return true; - } - aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR); - return false; -} - -bool -nsBrowserElement::IsNotWidgetOrThrow(ErrorResult& aRv) -{ - if (!mOwnerIsWidget) { - return true; - } - aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR); - return false; -} - -void -nsBrowserElement::InitBrowserElementAPI() -{ - bool isBrowserOrApp; - nsCOMPtr<nsIFrameLoader> frameLoader = GetFrameLoader(); - NS_ENSURE_TRUE_VOID(frameLoader); - nsresult rv = frameLoader->GetOwnerIsBrowserOrAppFrame(&isBrowserOrApp); - NS_ENSURE_SUCCESS_VOID(rv); - rv = frameLoader->GetOwnerIsWidget(&mOwnerIsWidget); - NS_ENSURE_SUCCESS_VOID(rv); - - if (!isBrowserOrApp) { - return; - } - - mBrowserElementAPI = do_CreateInstance("@mozilla.org/dom/browser-element-api;1"); - if (mBrowserElementAPI) { - mBrowserElementAPI->SetFrameLoader(frameLoader); - } -} - -nsBrowserElement::nsBrowserElement() - : mOwnerIsWidget(false) -{ - mObserver = new BrowserShownObserver(this); - mObserver->AddObserver(); -} - -nsBrowserElement::~nsBrowserElement() -{ - mObserver->RemoveObserver(); -} - -void -nsBrowserElement::SetVisible(bool aVisible, ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->SetVisible(aVisible); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -already_AddRefed<DOMRequest> -nsBrowserElement::GetVisible(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->GetVisible(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -void -nsBrowserElement::SetActive(bool aVisible, ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->SetActive(aVisible); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -bool -nsBrowserElement::GetActive(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), false); - - bool isActive; - nsresult rv = mBrowserElementAPI->GetActive(&isActive); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return false; - } - - return isActive; -} - -void -nsBrowserElement::SendMouseEvent(const nsAString& aType, - uint32_t aX, - uint32_t aY, - uint32_t aButton, - uint32_t aClickCount, - uint32_t aModifiers, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->SendMouseEvent(aType, - aX, - aY, - aButton, - aClickCount, - aModifiers); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::SendTouchEvent(const nsAString& aType, - const Sequence<uint32_t>& aIdentifiers, - const Sequence<int32_t>& aXs, - const Sequence<int32_t>& aYs, - const Sequence<uint32_t>& aRxs, - const Sequence<uint32_t>& aRys, - const Sequence<float>& aRotationAngles, - const Sequence<float>& aForces, - uint32_t aCount, - uint32_t aModifiers, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - if (aIdentifiers.Length() != aCount || - aXs.Length() != aCount || - aYs.Length() != aCount || - aRxs.Length() != aCount || - aRys.Length() != aCount || - aRotationAngles.Length() != aCount || - aForces.Length() != aCount) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return; - } - - nsresult rv = mBrowserElementAPI->SendTouchEvent(aType, - aIdentifiers.Elements(), - aXs.Elements(), - aYs.Elements(), - aRxs.Elements(), - aRys.Elements(), - aRotationAngles.Elements(), - aForces.Elements(), - aCount, - aModifiers); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::GoBack(ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->GoBack(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::GoForward(ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->GoForward(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::Reload(bool aHardReload, ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->Reload(aHardReload); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::Stop(ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->Stop(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -already_AddRefed<DOMRequest> -nsBrowserElement::Download(const nsAString& aUrl, - const BrowserElementDownloadOptions& aOptions, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI); - MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component."); - AutoJSAPI jsapi; - jsapi.Init(wrappedObj->GetJSObject()); - JSContext* cx = jsapi.cx(); - JS::Rooted<JS::Value> options(cx); - if (!ToJSValue(cx, aOptions, &options)) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - nsresult rv = mBrowserElementAPI->Download(aUrl, options, getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -already_AddRefed<DOMRequest> -nsBrowserElement::PurgeHistory(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->PurgeHistory(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -already_AddRefed<DOMRequest> -nsBrowserElement::GetScreenshot(uint32_t aWidth, - uint32_t aHeight, - const nsAString& aMimeType, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->GetScreenshot(aWidth, aHeight, aMimeType, - getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - if (rv == NS_ERROR_INVALID_ARG) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - } else { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -void -nsBrowserElement::Zoom(float aZoom, ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); - - nsresult rv = mBrowserElementAPI->Zoom(aZoom); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -already_AddRefed<DOMRequest> -nsBrowserElement::GetCanGoBack(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->GetCanGoBack(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -already_AddRefed<DOMRequest> -nsBrowserElement::GetCanGoForward(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->GetCanGoForward(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -already_AddRefed<DOMRequest> -nsBrowserElement::GetContentDimensions(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr); - - nsCOMPtr<nsIDOMDOMRequest> req; - nsresult rv = mBrowserElementAPI->GetContentDimensions(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -void -nsBrowserElement::AddNextPaintListener(BrowserElementNextPaintEventCallback& aListener, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - - CallbackObjectHolder<BrowserElementNextPaintEventCallback, - nsIBrowserElementNextPaintListener> holder(&aListener); - nsCOMPtr<nsIBrowserElementNextPaintListener> listener = holder.ToXPCOMCallback(); - - nsresult rv = mBrowserElementAPI->AddNextPaintListener(listener); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -nsBrowserElement::RemoveNextPaintListener(BrowserElementNextPaintEventCallback& aListener, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); - - CallbackObjectHolder<BrowserElementNextPaintEventCallback, - nsIBrowserElementNextPaintListener> holder(&aListener); - nsCOMPtr<nsIBrowserElementNextPaintListener> listener = holder.ToXPCOMCallback(); - - nsresult rv = mBrowserElementAPI->RemoveNextPaintListener(listener); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -already_AddRefed<DOMRequest> -nsBrowserElement::SetInputMethodActive(bool aIsActive, - ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - - nsCOMPtr<nsIFrameLoader> frameLoader = GetFrameLoader(); - if (!frameLoader) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - - nsCOMPtr<nsIDOMElement> ownerElement; - nsresult rv = frameLoader->GetOwnerElement(getter_AddRefs(ownerElement)); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return nullptr; - } - - nsCOMPtr<nsINode> node = do_QueryInterface(ownerElement); - nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal(); - if (!nsContentUtils::IsExactSitePermAllow(principal, "input-manage")) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return nullptr; - } - - nsCOMPtr<nsIDOMDOMRequest> req; - rv = mBrowserElementAPI->SetInputMethodActive(aIsActive, - getter_AddRefs(req)); - if (NS_WARN_IF(NS_FAILED(rv))) { - if (rv == NS_ERROR_INVALID_ARG) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - } else { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - } - return nullptr; - } - - return req.forget().downcast<DOMRequest>(); -} - -} // namespace mozilla
deleted file mode 100644 --- a/dom/html/nsBrowserElement.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsBrowserElement_h -#define nsBrowserElement_h - -#include "mozilla/dom/BindingDeclarations.h" - -#include "nsCOMPtr.h" -#include "nsIBrowserElementAPI.h" - -class nsFrameLoader; -class nsIObserver; - -namespace mozilla { - -namespace dom { -struct BrowserElementDownloadOptions; -class BrowserElementNextPaintEventCallback; -class DOMRequest; -} // namespace dom - -class ErrorResult; - -/** - * A helper class for browser-element frames - */ -class nsBrowserElement -{ -public: - nsBrowserElement(); - virtual ~nsBrowserElement(); - - void SetVisible(bool aVisible, ErrorResult& aRv); - already_AddRefed<dom::DOMRequest> GetVisible(ErrorResult& aRv); - void SetActive(bool aActive, ErrorResult& aRv); - bool GetActive(ErrorResult& aRv); - - void SendMouseEvent(const nsAString& aType, - uint32_t aX, - uint32_t aY, - uint32_t aButton, - uint32_t aClickCount, - uint32_t aModifiers, - ErrorResult& aRv); - void SendTouchEvent(const nsAString& aType, - const dom::Sequence<uint32_t>& aIdentifiers, - const dom::Sequence<int32_t>& aX, - const dom::Sequence<int32_t>& aY, - const dom::Sequence<uint32_t>& aRx, - const dom::Sequence<uint32_t>& aRy, - const dom::Sequence<float>& aRotationAngles, - const dom::Sequence<float>& aForces, - uint32_t aCount, - uint32_t aModifiers, - ErrorResult& aRv); - void GoBack(ErrorResult& aRv); - void GoForward(ErrorResult& aRv); - void Reload(bool aHardReload, ErrorResult& aRv); - void Stop(ErrorResult& aRv); - - already_AddRefed<dom::DOMRequest> - Download(const nsAString& aUrl, - const dom::BrowserElementDownloadOptions& options, - ErrorResult& aRv); - - already_AddRefed<dom::DOMRequest> PurgeHistory(ErrorResult& aRv); - - already_AddRefed<dom::DOMRequest> - GetScreenshot(uint32_t aWidth, - uint32_t aHeight, - const nsAString& aMimeType, - ErrorResult& aRv); - - void Zoom(float aZoom, ErrorResult& aRv); - - already_AddRefed<dom::DOMRequest> GetCanGoBack(ErrorResult& aRv); - already_AddRefed<dom::DOMRequest> GetCanGoForward(ErrorResult& aRv); - already_AddRefed<dom::DOMRequest> GetContentDimensions(ErrorResult& aRv); - - void AddNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener, - ErrorResult& aRv); - void RemoveNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener, - ErrorResult& aRv); - - already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive, - ErrorResult& aRv); - -protected: - NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0; - nsCOMPtr<nsIBrowserElementAPI> mBrowserElementAPI; - -private: - void InitBrowserElementAPI(); - bool IsBrowserElementOrThrow(ErrorResult& aRv); - bool IsNotWidgetOrThrow(ErrorResult& aRv); - bool mOwnerIsWidget; - - class BrowserShownObserver; - friend class BrowserShownObserver; - nsRefPtr<BrowserShownObserver> mObserver; -}; - -} // namespace mozilla - -#endif // nsBrowserElement_h
--- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -29,17 +29,16 @@ using namespace mozilla; using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_ADDREF_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement) NS_IMPL_RELEASE_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement) NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement) NS_INTERFACE_TABLE_INHERITED(nsGenericHTMLFrameElement, nsIDOMMozBrowserFrame, @@ -302,20 +301,16 @@ nsGenericHTMLFrameElement::GetReallyIsBr nsIPrincipal *principal = NodePrincipal(); nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager(); NS_ENSURE_TRUE(permMgr, NS_OK); uint32_t permission = nsIPermissionManager::DENY_ACTION; nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission); NS_ENSURE_SUCCESS(rv, NS_OK); - if (permission != nsIPermissionManager::ALLOW_ACTION) { - rv = permMgr->TestPermissionFromPrincipal(principal, "embed-widgets", &permission); - NS_ENSURE_SUCCESS(rv, NS_OK); - } *aOut = permission == nsIPermissionManager::ALLOW_ACTION; return NS_OK; } /* [infallible] */ NS_IMETHODIMP nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut) { nsAutoString manifestURL;
--- a/dom/html/nsGenericHTMLFrameElement.h +++ b/dom/html/nsGenericHTMLFrameElement.h @@ -4,42 +4,39 @@ /* 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 nsGenericHTMLFrameElement_h #define nsGenericHTMLFrameElement_h #include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/dom/nsBrowserElement.h" - #include "nsElementFrameLoaderOwner.h" -#include "nsFrameLoader.h" #include "nsGenericHTMLElement.h" -#include "nsIDOMEventListener.h" #include "nsIFrameLoader.h" #include "nsIMozBrowserFrame.h" +#include "nsIDOMEventListener.h" +#include "mozilla/ErrorResult.h" + +#include "nsFrameLoader.h" class nsXULElement; /** * A helper class for frame elements */ class nsGenericHTMLFrameElement : public nsGenericHTMLElement, public nsElementFrameLoaderOwner, - public mozilla::nsBrowserElement, public nsIMozBrowserFrame { public: nsGenericHTMLFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo, mozilla::dom::FromParser aFromParser) : nsGenericHTMLElement(aNodeInfo) , nsElementFrameLoaderOwner(aFromParser) - , nsBrowserElement() { } NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMMOZBROWSERFRAME NS_DECL_NSIMOZBROWSERFRAME @@ -70,29 +67,16 @@ public: virtual int32_t TabIndexDefault() MOZ_OVERRIDE; NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement, nsGenericHTMLElement) static bool BrowserFramesEnabled(); /** - * nsIFrameLoaderOwner defines two GetFrameLoader() overloads. One - * is XPCOM style interface, the other one is C++ only. "using" pulls - * them both in, now GetFrameLoader() is ambiguous because - * nsBrowserElement also has GetFrameLoader(). Explicit redefine - * GetFrameLoader() to choose nsElementFrameLoaderOwner::GetFrameLoader() - */ - using nsElementFrameLoaderOwner::GetFrameLoader; - NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() MOZ_OVERRIDE - { - return nsElementFrameLoaderOwner::GetFrameLoader(); - } - - /** * Helper method to map a HTML 'scrolling' attribute value to a nsIScrollable * enum value. scrolling="no" (and its synonyms) maps to * nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps * to nsIScrollable::Scrollbar_Auto. * @param aValue the attribute value to map or nullptr * @return nsIScrollable::Scrollbar_Never or nsIScrollable::Scrollbar_Auto */ static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
--- a/dom/identity/nsDOMIdentity.js +++ b/dom/identity/nsDOMIdentity.js @@ -96,32 +96,35 @@ nsDOMIdentity.prototype = { let message = this.DOMIdentityMessage(aOptions); // loggedInUser vs loggedInEmail // https://developer.mozilla.org/en-US/docs/DOM/navigator.id.watch // This parameter, loggedInUser, was renamed from loggedInEmail in early // September, 2012. Both names will continue to work for the time being, // but code should be changed to use loggedInUser instead. checkRenamed(aOptions, "loggedInEmail", "loggedInUser"); - message["loggedInUser"] = aOptions["loggedInUser"]; - let emailType = typeof(aOptions["loggedInUser"]); - if (aOptions["loggedInUser"] && aOptions["loggedInUser"] !== "undefined") { - if (emailType !== "string") { + // Bad IPC or IDL converts null and undefined to "null" and "undefined". + // We can't assign to aOptions, which complicates the workaround. + message["loggedInUser"] = aOptions["loggedInUser"]; + if (message.loggedInUser == "null" || message.loggedInUser == "undefined") { + message.loggedInUser = null; + } + + if (message.loggedInUser) { + if (typeof(message.loggedInUser) !== "string") { throw new Error("loggedInUser must be a String or null"); } // TODO: Bug 767610 - check email format. // See HTMLInputElement::IsValidEmailAddress if (aOptions["loggedInUser"].indexOf("@") == -1 || aOptions["loggedInUser"].length > MAX_STRING_LENGTH) { throw new Error("loggedInUser is not valid"); } - // Set loggedInUser in this block that "undefined" doesn't get through. - message.loggedInUser = aOptions.loggedInUser; } this._log("loggedInUser: " + message.loggedInUser); this._rpWatcher = aOptions; this._rpWatcher.audience = message.audience; if (message.errors.length) { this.reportErrors(message);
--- a/dom/imptests/editing/implementation.js +++ b/dom/imptests/editing/implementation.js @@ -1968,19 +1968,19 @@ function isSimpleModifiableElement(node) // // The weird extra node.style.length check is for Firefox, which as of // 8.0a2 has annoying and weird behavior here. if (["A", "FONT", "S", "SPAN", "STRIKE", "U"].indexOf(node.tagName) != -1 && node.hasAttribute("style") && (node.style.length == 1 || (node.style.length == 4 && "MozTextBlink" in node.style - && "MozTextDecorationColor" in node.style - && "MozTextDecorationLine" in node.style - && "MozTextDecorationStyle" in node.style) + && "textDecorationColor" in node.style + && "textDecorationLine" in node.style + && "textDecorationStyle" in node.style) ) && (node.style.textDecoration == "line-through" || node.style.textDecoration == "underline" || node.style.textDecoration == "overline" || node.style.textDecoration == "none")) { return true; }
--- a/dom/ipc/ScreenManagerParent.cpp +++ b/dom/ipc/ScreenManagerParent.cpp @@ -116,16 +116,21 @@ ScreenManagerParent::RecvScreenForRect(c } bool ScreenManagerParent::RecvScreenForBrowser(PBrowserParent* aBrowser, ScreenDetails* aRetVal, bool* aSuccess) { *aSuccess = false; +#ifdef MOZ_VALGRIND + // Zero this so that Valgrind doesn't complain when we send it to another + // process. + memset(aRetVal, 0, sizeof(ScreenDetails)); +#endif // Find the mWidget associated with the tabparent, and then return // the nsIScreen it's on. TabParent* tabParent = static_cast<TabParent*>(aBrowser); nsCOMPtr<nsIWidget> widget = tabParent->GetWidget(); if (!widget) { return true; }
--- a/dom/media/MediaRecorder.cpp +++ b/dom/media/MediaRecorder.cpp @@ -174,31 +174,56 @@ class MediaRecorder::Session: public nsI LOG(PR_LOG_DEBUG, ("Session.PushBlobRunnable s=(%p)", mSession.get())); MOZ_ASSERT(NS_IsMainThread()); nsRefPtr<MediaRecorder> recorder = mSession->mRecorder; if (!recorder) { return NS_OK; } - if (mSession->IsEncoderError()) { - recorder->NotifyError(NS_ERROR_UNEXPECTED); - } nsresult rv = recorder->CreateAndDispatchBlobEvent(mSession->GetEncodedData()); if (NS_FAILED(rv)) { recorder->NotifyError(rv); } return NS_OK; } private: nsRefPtr<Session> mSession; }; + // Notify encoder error, run in main thread task. (Bug 1095381) + class EncoderErrorNotifierRunnable : public nsRunnable + { + public: + explicit EncoderErrorNotifierRunnable(Session* aSession) + : mSession(aSession) + { } + + NS_IMETHODIMP Run() + { + LOG(PR_LOG_DEBUG, ("Session.ErrorNotifyRunnable s=(%p)", mSession.get())); + MOZ_ASSERT(NS_IsMainThread()); + + nsRefPtr<MediaRecorder> recorder = mSession->mRecorder; + if (!recorder) { + return NS_OK; + } + + if (mSession->IsEncoderError()) { + recorder->NotifyError(NS_ERROR_UNEXPECTED); + } + return NS_OK; + } + + private: + nsRefPtr<Session> mSession; + }; + // Fire start event and set mimeType, run in main thread task. class DispatchStartEventRunnable : public nsRunnable { public: DispatchStartEventRunnable(Session* aSession, const nsAString & aEventName) : mSession(aSession) , mEventName(aEventName) { } @@ -331,16 +356,17 @@ class MediaRecorder::Session: public nsI return NS_OK; } private: // Call mSession::Release automatically while DestroyRunnable be destroy. nsRefPtr<Session> mSession; }; + friend class EncoderErrorNotifierRunnable; friend class PushBlobRunnable; friend class ExtractRunnable; friend class DestroyRunnable; friend class TracksAvailableCallback; public: Session(MediaRecorder* aRecorder, int32_t aTimeSlice) : mRecorder(aRecorder), @@ -394,17 +420,18 @@ public: return NS_OK; } nsresult RequestData() { LOG(PR_LOG_DEBUG, ("Session.RequestData")); MOZ_ASSERT(NS_IsMainThread()); - if (NS_FAILED(NS_DispatchToMainThread(new PushBlobRunnable(this)))) { + if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this))) || + NS_FAILED(NS_DispatchToMainThread(new PushBlobRunnable(this)))) { MOZ_ASSERT(false, "RequestData NS_DispatchToMainThread failed"); return NS_ERROR_FAILURE; } return NS_OK; } already_AddRefed<nsIDOMBlob> GetEncodedData() @@ -475,16 +502,19 @@ private: // Whether push encoded data back to onDataAvailable automatically or we // need a flush. bool pushBlob = false; if ((mTimeSlice > 0) && ((TimeStamp::Now()-mLastBlobTimeStamp).ToMilliseconds() > mTimeSlice)) { pushBlob = true; } if (pushBlob || aForceFlush) { + if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this)))) { + MOZ_ASSERT(false, "NS_DispatchToMainThread EncoderErrorNotifierRunnable failed"); + } if (NS_FAILED(NS_DispatchToMainThread(new PushBlobRunnable(this)))) { MOZ_ASSERT(false, "NS_DispatchToMainThread PushBlobRunnable failed"); } else { mLastBlobTimeStamp = TimeStamp::Now(); } } } @@ -571,16 +601,19 @@ private: void DoSessionEndTask(nsresult rv) { MOZ_ASSERT(NS_IsMainThread()); if (NS_FAILED(rv)) { mRecorder->NotifyError(rv); } CleanupStreams(); + if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this)))) { + MOZ_ASSERT(false, "NS_DispatchToMainThread EncoderErrorNotifierRunnable failed"); + } if (NS_FAILED(NS_DispatchToMainThread(new PushBlobRunnable(this)))) { MOZ_ASSERT(false, "NS_DispatchToMainThread PushBlobRunnable failed"); } if (NS_FAILED(NS_DispatchToMainThread(new DestroyRunnable(this)))) { MOZ_ASSERT(false, "NS_DispatchToMainThread DestroyRunnable failed"); } } void CleanupStreams()
--- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -60,17 +60,17 @@ PRLogModuleInfo* gMediaStreamGraphLog; # endif #else # define LIFECYCLE_LOG(...) #endif /** * The singleton graph instance. */ -static MediaStreamGraphImpl* gGraph; +static nsDataHashtable<nsUint32HashKey, MediaStreamGraphImpl*> gGraphs; MediaStreamGraphImpl::~MediaStreamGraphImpl() { NS_ASSERTION(IsEmpty(), "All streams should have been destroyed by messages from the main thread"); STREAM_LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p destroyed", this)); LIFECYCLE_LOG("MediaStreamGraphImpl::~MediaStreamGraphImpl\n"); } @@ -1631,19 +1631,20 @@ MediaStreamGraphImpl::RunInStableState(b // synchronously because it spins the event loop waiting for threads // to shut down, and we don't want to do that in a stable state handler. mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN; LIFECYCLE_LOG("Sending MediaStreamGraphShutDownRunnable %p", this); nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this ); NS_DispatchToMainThread(event); LIFECYCLE_LOG("Disconnecting MediaStreamGraph %p", this); - if (this == gGraph) { + MediaStreamGraphImpl* graph; + if (gGraphs.Get(mAudioChannel, &graph) && graph == this) { // null out gGraph if that's the graph being shut down - gGraph = nullptr; + gGraphs.Remove(mAudioChannel); } } } else { if (mLifecycleState <= LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) { MessageBlock* block = mBackMessageQueue.AppendElement(); block->mMessages.SwapElements(mCurrentTaskMessageQueue); block->mGraphUpdateIndex = mNextGraphUpdateIndex; ++mNextGraphUpdateIndex; @@ -1784,19 +1785,22 @@ MediaStreamGraphImpl::AppendMessage(Cont #endif aMessage->RunDuringShutdown(); #ifdef DEBUG mCanRunMessagesSynchronously = true; #endif delete aMessage; if (IsEmpty() && mLifecycleState >= LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION) { - if (gGraph == this) { - gGraph = nullptr; + + MediaStreamGraphImpl* graph; + if (gGraphs.Get(mAudioChannel, &graph) && graph == this) { + gGraphs.Remove(mAudioChannel); } + Destroy(); } return; } mCurrentTaskMessageQueue.AppendElement(aMessage); EnsureRunInStableState(); } @@ -2736,16 +2740,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm #endif , mMemoryReportMonitor("MSGIMemory") , mSelfRef(MOZ_THIS_IN_INITIALIZER_LIST()) , mAudioStreamSizes() , mNeedsMemoryReport(false) #ifdef DEBUG , mCanRunMessagesSynchronously(false) #endif + , mAudioChannel(static_cast<uint32_t>(aChannel)) { #ifdef PR_LOGGING if (!gMediaStreamGraphLog) { gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph"); } #endif if (mRealtime) { @@ -2774,50 +2779,65 @@ MediaStreamGraphImpl::Destroy() // Clear the self reference which will destroy this instance. mSelfRef = nullptr; } NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver) static bool gShutdownObserverRegistered = false; +namespace { + +PLDHashOperator +ForceShutdownEnumerator(const uint32_t& /* aAudioChannel */, + MediaStreamGraphImpl* aGraph, + void* /* aUnused */) +{ + aGraph->ForceShutDown(); + return PL_DHASH_NEXT; +} + +} // anonymous namespace + NS_IMETHODIMP MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) { if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { - if (gGraph) { - gGraph->ForceShutDown(); - } + gGraphs.EnumerateRead(ForceShutdownEnumerator, nullptr); nsContentUtils::UnregisterShutdownObserver(this); gShutdownObserverRegistered = false; } return NS_OK; } MediaStreamGraph* MediaStreamGraph::GetInstance(DOMMediaStream::TrackTypeHints aHint, dom::AudioChannel aChannel) { NS_ASSERTION(NS_IsMainThread(), "Main thread only"); - if (!gGraph) { + uint32_t channel = static_cast<uint32_t>(aChannel); + MediaStreamGraphImpl* graph = nullptr; + + if (!gGraphs.Get(channel, &graph)) { if (!gShutdownObserverRegistered) { gShutdownObserverRegistered = true; nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver()); } CubebUtils::InitPreferredSampleRate(); - gGraph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aHint, aChannel); + graph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aHint, aChannel); + gGraphs.Put(channel, graph); - STREAM_LOG(PR_LOG_DEBUG, ("Starting up MediaStreamGraph %p", gGraph)); + STREAM_LOG(PR_LOG_DEBUG, ("Starting up MediaStreamGraph %p", graph)); } - return gGraph; + return graph; } MediaStreamGraph* MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate) { NS_ASSERTION(NS_IsMainThread(), "Main thread only"); MediaStreamGraphImpl* graph = new MediaStreamGraphImpl(false, aSampleRate); @@ -2990,17 +3010,20 @@ MediaStreamGraph::CreateAudioNodeStream( } graph->AppendMessage(new CreateMessage(stream)); return stream; } bool MediaStreamGraph::IsNonRealtime() const { - return this != gGraph; + const MediaStreamGraphImpl* impl = static_cast<const MediaStreamGraphImpl*>(this); + MediaStreamGraphImpl* graph; + + return !gGraphs.Get(impl->AudioChannel(), &graph) || graph != impl; } void MediaStreamGraph::StartNonRealtimeProcessing(TrackRate aRate, uint32_t aTicksToProcess) { NS_ASSERTION(NS_IsMainThread(), "main thread only"); MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
--- a/dom/media/MediaStreamGraphImpl.h +++ b/dom/media/MediaStreamGraphImpl.h @@ -656,16 +656,18 @@ public: * Hold a ref to the Latency logger */ nsRefPtr<AsyncLatencyLogger> mLatencyLog; AudioMixer mMixer; #ifdef MOZ_WEBRTC nsRefPtr<AudioOutputObserver> mFarendObserverRef; #endif + uint32_t AudioChannel() const { return mAudioChannel; } + private: virtual ~MediaStreamGraphImpl(); MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) /** * Used to signal that a memory report has been requested. */ @@ -689,13 +691,16 @@ private: #ifdef DEBUG /** * Used to assert when AppendMessage() runs ControlMessages synchronously. */ bool mCanRunMessagesSynchronously; #endif + // We use uint32_t instead AudioChannel because this is just used as key for + // the hashtable gGraphs. + uint32_t mAudioChannel; }; } #endif /* MEDIASTREAMGRAPHIMPL_H_ */
--- a/dom/media/fmp4/android/AndroidDecoderModule.cpp +++ b/dom/media/fmp4/android/AndroidDecoderModule.cpp @@ -53,17 +53,17 @@ public: printf_stderr("Failed to create SurfaceTexture for video decode\n"); return NS_ERROR_FAILURE; } return InitDecoder(mSurfaceTexture->JavaSurface()); } virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE { - mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b); + mp4_demuxer::AnnexB::ConvertSample(aSample); return MediaCodecDataDecoder::Input(aSample); } virtual nsresult PostOutput(BufferInfo* aInfo, MediaFormat* aFormat, Microseconds aDuration) MOZ_OVERRIDE { VideoInfo videoInfo; videoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height); bool isSync = false;
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp +++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp @@ -48,17 +48,16 @@ enum { kNotifyCodecReserved = 'core', kNotifyCodecCanceled = 'coca', }; GonkVideoDecoderManager::GonkVideoDecoderManager( mozilla::layers::ImageContainer* aImageContainer, const mp4_demuxer::VideoDecoderConfig& aConfig) : mImageContainer(aImageContainer) - , mConfig(aConfig) , mReaderCallback(nullptr) , mColorConverterBufferSize(0) , mNativeWindow(nullptr) , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock") { NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread."); MOZ_ASSERT(mImageContainer); MOZ_COUNT_CTOR(GonkVideoDecoderManager); @@ -391,17 +390,17 @@ GonkVideoDecoderManager::Input(mp4_demux { if (mDecoder == nullptr) { ALOG("Decoder is not inited"); return NS_ERROR_UNEXPECTED; } status_t rv; if (aSample != nullptr) { // We must prepare samples in AVC Annex B. - mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b); + mp4_demuxer::AnnexB::ConvertSample(aSample); // Forward sample data to the decoder. const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data); uint32_t length = aSample->size; rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0); } else { // Inputted data is null, so it is going to notify decoder EOS
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h +++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h @@ -110,17 +110,16 @@ private: // For codec resource management void codecReserved(); void codecCanceled(); void onMessageReceived(const sp<AMessage> &aMessage); void ReleaseAllPendingVideoBuffersLocked(); void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer); - const mp4_demuxer::VideoDecoderConfig& mConfig; uint32_t mVideoWidth; uint32_t mVideoHeight; uint32_t mDisplayWidth; uint32_t mDisplayHeight; nsIntRect mPicture; nsIntSize mInitialFrame; android::sp<MediaCodecProxy> mDecoder;
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp @@ -35,17 +35,16 @@ namespace mozilla { WMFVideoMFTManager::WMFVideoMFTManager( const mp4_demuxer::VideoDecoderConfig& aConfig, mozilla::layers::LayersBackend aLayersBackend, mozilla::layers::ImageContainer* aImageContainer, bool aDXVAEnabled) : mVideoStride(0) , mVideoWidth(0) , mVideoHeight(0) - , mConfig(aConfig) , mImageContainer(aImageContainer) , mDXVAEnabled(aDXVAEnabled) , mLayersBackend(aLayersBackend) , mUseHwAccel(false) { NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread."); MOZ_ASSERT(mImageContainer); MOZ_COUNT_CTOR(WMFVideoMFTManager); @@ -142,17 +141,17 @@ WMFVideoMFTManager::Init() return decoder.forget(); } HRESULT WMFVideoMFTManager::Input(mp4_demuxer::MP4Sample* aSample) { // We must prepare samples in AVC Annex B. - mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b); + mp4_demuxer::AnnexB::ConvertSample(aSample); // Forward sample data to the decoder. const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data); uint32_t length = aSample->size; return mDecoder->Input(data, length, aSample->composition_timestamp); } HRESULT WMFVideoMFTManager::ConfigureVideoFrameGeometry()
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.h +++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.h @@ -51,18 +51,16 @@ private: // Video frame geometry. VideoInfo mVideoInfo; uint32_t mVideoStride; uint32_t mVideoWidth; uint32_t mVideoHeight; nsIntRect mPictureRegion; - const mp4_demuxer::VideoDecoderConfig& mConfig; - RefPtr<MFTDecoder> mDecoder; RefPtr<layers::ImageContainer> mImageContainer; nsAutoPtr<DXVA2Manager> mDXVA2Manager; RefPtr<MediaTaskQueue> mTaskQueue; MediaDataDecoderCallback* mCallback; const bool mDXVAEnabled; const layers::LayersBackend mLayersBackend;
--- a/dom/media/omx/MediaCodecReader.cpp +++ b/dom/media/omx/MediaCodecReader.cpp @@ -277,20 +277,16 @@ MediaCodecReader::ProcessCachedDataTask: MOZ_ASSERT(mReader, "Should have a valid MediaCodecReader."); MOZ_ASSERT(mOffset >= INT64_C(0), "Should have a valid offset."); } void MediaCodecReader::ProcessCachedDataTask::Run() { mReader->ProcessCachedData(mOffset, nullptr); - nsRefPtr<ReferenceKeeperRunnable<MediaCodecReader>> runnable( - new ReferenceKeeperRunnable<MediaCodecReader>(mReader)); - mReader = nullptr; - NS_DispatchToMainThread(runnable.get()); } MediaCodecReader::MediaCodecReader(AbstractMediaDecoder* aDecoder) : MediaOmxCommonReader(aDecoder) , mExtractor(nullptr) , mIsWaitingResources(false) , mTextureClientIndexesLock("MediaCodecReader::mTextureClientIndexesLock") , mColorConverterBufferSize(0) @@ -300,17 +296,16 @@ MediaCodecReader::MediaCodecReader(Abstr , mParsedDataLength(INT64_C(0)) { mHandler = new MessageHandler(this); mVideoListener = new VideoResourceListener(this); } MediaCodecReader::~MediaCodecReader() { - MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread."); } nsresult MediaCodecReader::Init(MediaDecoderReader* aCloneDonor) { return NS_OK; }
--- a/dom/media/omx/MediaCodecReader.h +++ b/dom/media/omx/MediaCodecReader.h @@ -333,47 +333,16 @@ private: ProcessCachedDataTask(const ProcessCachedDataTask &rhs) MOZ_DELETE; const ProcessCachedDataTask &operator=(const ProcessCachedDataTask &rhs) MOZ_DELETE; nsRefPtr<MediaCodecReader> mReader; int64_t mOffset; }; friend class ProcessCachedDataTask; - // This class is used to keep one reference count of T in it. And this class - // can make sure the stored reference count will be released on the dispatched - // thread. By using this class properly (ex. passing the pointer into this - // runnable first, then releasing the original pointer held by ourselves, and - // then dispatching this runnable onto the desired thread), we can avoid - // running the destructor of the referenced object on any other threads - // unexpectedly before this runnable has been executed. - template<class T> - class ReferenceKeeperRunnable : public nsRunnable - { - public: - ReferenceKeeperRunnable(nsRefPtr<T> aPointer) - : mPointer(aPointer) - { - } - - NS_IMETHOD Run() MOZ_OVERRIDE - { - mPointer = nullptr; - return NS_OK; - } - - private: - // Forbidden - ReferenceKeeperRunnable() MOZ_DELETE; - ReferenceKeeperRunnable(const ReferenceKeeperRunnable &rhs) MOZ_DELETE; - const ReferenceKeeperRunnable &operator=(const ReferenceKeeperRunnable &rhs) MOZ_DELETE; - - nsRefPtr<T> mPointer; - }; - // Forbidden MediaCodecReader() MOZ_DELETE; const MediaCodecReader& operator=(const MediaCodecReader& rhs) MOZ_DELETE; bool ReallocateResources(); void ReleaseCriticalResources(); void ReleaseResources();
--- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -2578,16 +2578,58 @@ PeerConnectionWrapper.prototype = { ok(numRemoteCandidates, "Have remotecandidate stat(s)"); } else { is(numLocalCandidates, 0, "Have no localcandidate stats"); is(numRemoteCandidates, 0, "Have no remotecandidate stats"); } }, /** + * Compares the Ice server configured for this PeerConnectionWrapper + * with the ICE candidates received in the RTCP stats. + * + * @param {object} stats + * The stats to be verified for relayed vs. direct connection. + */ + checkStatsIceConnectionType : function PCW_checkStatsIceConnectionType(stats) + { + var lId; + var rId; + Object.keys(stats).forEach(function(name) { + if ((stats[name].type === "candidatepair") && + (stats[name].selected)) { + lId = stats[name].localCandidateId; + rId = stats[name].remoteCandidateId; + } + }); + info("checkStatsIceConnectionType verifying: local=" + + JSON.stringify(stats[lId]) + " remote=" + JSON.stringify(stats[rId])); + if ((typeof stats[lId] === 'undefined') || + (typeof stats[rId] === 'undefined')) { + info("checkStatsIceConnectionType failed to find candidatepair IDs"); + return; + } + var lType = stats[lId].candidateType; + var rType = stats[rId].candidateType; + var lIp = stats[lId].ipAddress; + var rIp = stats[rId].ipAddress; + if ((this.configuration) && (typeof this.configuration.iceServers !== 'undefined')) { + info("Ice Server configured"); + // Note: the IP comparising is a workaround for bug 1097333 + // And this will fail if a TURN server address is a DNS name! + var serverIp = this.configuration.iceServers[0].url.split(':')[1]; + ok((lType === "relayed" || rType === "relayed") || + (lIp === serverIp || rIp === serverIp), "One peer uses a relay"); + } else { + info("P2P configured"); + ok(((lType !== "relayed") && (rType !== "relayed")), "Pure peer to peer call without a relay"); + } + }, + + /** * Property-matching function for finding a certain stat in passed-in stats * * @param {object} stats * The stats to check from this PeerConnectionWrapper * @param {object} props * The properties to look for * @returns {boolean} Whether an entry containing all match-props was found. */
--- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -19,16 +19,27 @@ function deltaSeconds(date1, date2) { function dumpSdp(test) { if (typeof test._local_offer !== 'undefined') { dump("ERROR: SDP offer: " + test._local_offer.sdp.replace(/[\r]/g, '')); } if (typeof test._remote_answer !== 'undefined') { dump("ERROR: SDP answer: " + test._remote_answer.sdp.replace(/[\r]/g, '')); } + if ((test.pcLocal) && (typeof test.pcLocal._local_ice_candidates !== 'undefined')) { + dump("pcLocal._local_ice_candidates: " + JSON.stringify(test.pcLocal._local_ice_candidates) + "\n"); + dump("pcLocal._remote_ice_candidates: " + JSON.stringify(test.pcLocal._remote_ice_candidates) + "\n"); + dump("pcLocal._ice_candidates_to_add: " + JSON.stringify(test.pcLocal._ice_candidates_to_add) + "\n"); + } + if ((test.pcRemote) && (typeof test.pcRemote._local_ice_candidates !== 'undefined')) { + dump("pcRemote._local_ice_candidates: " + JSON.stringify(test.pcRemote._local_ice_candidates) + "\n"); + dump("pcRemote._remote_ice_candidates: " + JSON.stringify(test.pcRemote._remote_ice_candidates) + "\n"); + dump("pcRemote._ice_candidates_to_add: " + JSON.stringify(test.pcRemote._ice_candidates_to_add) + "\n"); + } + if ((test.pcLocal) && (typeof test.pcLocal.iceConnectionLog !== 'undefined')) { dump("pcLocal ICE connection state log: " + test.pcLocal.iceConnectionLog + "\n"); } if ((test.pcRemote) && (typeof test.pcRemote.iceConnectionLog !== 'undefined')) { dump("pcRemote ICE connection state log: " + test.pcRemote.iceConnectionLog + "\n"); } if ((test.pcLocal) && (test.pcRemote) && @@ -488,16 +499,34 @@ var commandsPeerConnection = [ function (test) { test.pcRemote.getStats(null, function(stats) { test.pcRemote.checkStats(stats, test.steeplechase); test.next(); }); } ], [ + 'PC_LOCAL_CHECK_ICE_CONNECTION_TYPE', + function (test) { + test.pcLocal.getStats(null, function(stats) { + test.pcLocal.checkStatsIceConnectionType(stats); + test.next(); + }); + } + ], + [ + 'PC_REMOTE_CHECK_ICE_CONNECTION_TYPE', + function (test) { + test.pcRemote.getStats(null, function(stats) { + test.pcRemote.checkStatsIceConnectionType(stats); + test.next(); + }); + } + ], + [ 'PC_LOCAL_CHECK_GETSTATS_AUDIOTRACK_OUTBOUND', function (test) { var pc = test.pcLocal; var stream = pc._pc.getLocalStreams()[0]; var track = stream && stream.getAudioTracks()[0]; if (track) { var msg = "pcLocal.HasStat outbound audio rtp "; pc.getStats(track, function(stats) {
--- a/dom/media/tests/mochitest/turnConfig.js +++ b/dom/media/tests/mochitest/turnConfig.js @@ -1,12 +1,16 @@ /* 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/. */ /* An example of how to specify two TURN server configs: + * + * Note: If turn URL uses FQDN rather then an IP address the TURN relay + * verification step in checkStatsIceConnectionType might fail. + * * var turnServers = { * local: { iceServers: [{"username":"mozilla","credential":"mozilla","url":"turn:10.0.0.1"}] }, * remote: { iceServers: [{"username":"firefox","credential":"firefox","url":"turn:10.0.0.2"}] } * }; */ var turnServers = { };
--- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -664,22 +664,16 @@ AudioContext::Unmute() const } AudioChannel AudioContext::MozAudioChannelType() const { return mDestination->MozAudioChannelType(); } -void -AudioContext::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv) -{ - mDestination->SetMozAudioChannelType(aValue, aRv); -} - AudioChannel AudioContext::TestAudioChannelInAudioNodeStream() { MediaStream* stream = mDestination->Stream(); MOZ_ASSERT(stream); return stream->AudioChannelType(); }
--- a/dom/media/webaudio/AudioContext.h +++ b/dom/media/webaudio/AudioContext.h @@ -219,17 +219,16 @@ public: uint32_t MaxChannelCount() const; void Mute() const; void Unmute() const; JSObject* GetGlobalJSObject() const; AudioChannel MozAudioChannelType() const; - void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv); AudioChannel TestAudioChannelInAudioNodeStream(); void UpdateNodeCount(int32_t aDelta); double DOMTimeToStreamTime(double aTime) const { return aTime - ExtraCurrentTime();
--- a/dom/media/webaudio/test/test_mozaudiochannel.html +++ b/dom/media/webaudio/test/test_mozaudiochannel.html @@ -13,37 +13,33 @@ function test_basic() { var ac = new AudioContext(); ok(ac, "AudioContext created"); // Default is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - // random wrong channel - ac.mozAudioChannelType = "foo"; + // Unpermitted channels + ac = new AudioContext("content"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - // Unpermitted channels - ac.mozAudioChannelType = "content"; - is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - - ac.mozAudioChannelType = "notification"; + ac = new AudioContext("notification"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - ac.mozAudioChannelType = "alarm"; + ac = new AudioContext("alarm"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - ac.mozAudioChannelType = "telephony"; + ac = new AudioContext("telephony"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - ac.mozAudioChannelType = "ringer"; + ac = new AudioContext("ringer"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); - ac.mozAudioChannelType = "publicnotification"; + ac = new AudioContext("publicnotification"); is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); runTest(); } function test_permission(aChannel) { var ac = new AudioContext(); ok(ac, "AudioContext created"); @@ -51,17 +47,17 @@ function test_permission(aChannel) { is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'"); var channel = SpecialPowers.wrap(ac).testAudioChannelInAudioNodeStream(); is(channel, "normal", "AudioNodeStream is using the correct default audio channel."); SpecialPowers.pushPermissions( [{ "type": "audio-channel-" + aChannel, "allow": true, "context": document }], function() { - ac.mozAudioChannelType = aChannel; + var ac = new AudioContext(aChannel); is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'"); var channel = SpecialPowers.wrap(ac).testAudioChannelInAudioNodeStream(); is(channel, aChannel, "AudioNodeStream is using the correct new audio channel."); runTest(); } ); @@ -142,13 +138,14 @@ function runTest() { } var test = tests.shift(); test(); } SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true ]]}, runTest); SimpleTest.waitForExplicitFinish(); +SimpleTest.requestLongerTimeout(5); </script> </pre> </body> </html>
--- a/dom/mobileconnection/Assertions.cpp +++ b/dom/mobileconnection/Assertions.cpp @@ -52,10 +52,22 @@ ASSERT_PREFERRED_NETWORK_TYPE_EQUALITY(L "MobileRoamingMode::" #webidlState " should equal to nsIMobileConnection::" #xpidlState) ASSERT_MOBILE_ROAMING_MODE_EQUALITY(Home, CDMA_ROAMING_PREFERENCE_HOME); ASSERT_MOBILE_ROAMING_MODE_EQUALITY(Affiliated, CDMA_ROAMING_PREFERENCE_AFFILIATED); ASSERT_MOBILE_ROAMING_MODE_EQUALITY(Any, CDMA_ROAMING_PREFERENCE_ANY); #undef ASSERT_MOBILE_ROAMING_MODE_EQUALITY +#define ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(webidlState, xpidlState) \ + static_assert(static_cast<int32_t>(MobileNetworkType::webidlState) == nsIMobileConnection::xpidlState, \ + "MobileNetworkType::" #webidlState " should equal to nsIMobileConnection::" #xpidlState) + +ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(Gsm, MOBILE_NETWORK_TYPE_GSM); +ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(Wcdma, MOBILE_NETWORK_TYPE_WCDMA); +ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(Cdma, MOBILE_NETWORK_TYPE_CDMA); +ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(Evdo, MOBILE_NETWORK_TYPE_EVDO); +ASSERT_MOBILE_NETWORK_TYPE_EQUALITY(Lte, MOBILE_NETWORK_TYPE_LTE); + +#undef ASSERT_MOBILE_NETWORK_TYPE_EQUALITY + } // namespace dom } // namespace mozilla
--- a/dom/mobileconnection/MobileConnection.cpp +++ b/dom/mobileconnection/MobileConnection.cpp @@ -373,33 +373,30 @@ MobileConnection::GetRadioState() const void MobileConnection::GetSupportedNetworkTypes(nsTArray<MobileNetworkType>& aTypes) const { if (!mMobileConnection) { return; } - char16_t** types = nullptr; + int32_t* types = nullptr; uint32_t length = 0; nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); NS_ENSURE_SUCCESS_VOID(rv); for (uint32_t i = 0; i < length; ++i) { - nsDependentString rawType(types[i]); - Nullable<MobileNetworkType> type = Nullable<MobileNetworkType>(); - CONVERT_STRING_TO_NULLABLE_ENUM(rawType, MobileNetworkType, type); + int32_t type = types[i]; - if (!type.IsNull()) { - aTypes.AppendElement(type.Value()); - } + MOZ_ASSERT(type < static_cast<int32_t>(MobileNetworkType::EndGuard_)); + aTypes.AppendElement(static_cast<MobileNetworkType>(type)); } - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); + nsMemory::Free(types); } already_AddRefed<DOMRequest> MobileConnection::GetNetworks(ErrorResult& aRv) { if (!mMobileConnection) { aRv.Throw(NS_ERROR_FAILURE); return nullptr;
--- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -393,32 +393,36 @@ MobileConnectionProvider.prototype = { if (DEBUG) this._debug("Fallback to " + key + ": " + index); let networkTypes = RIL.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO[index]; supportedNetworkTypes = networkTypes ? networkTypes.replace("-auto", "", "g").split("/") : RIL.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT.split(","); } + let enumNetworkTypes = []; for (let type of supportedNetworkTypes) { // If the value in system property is not valid, use the default one which // is defined in ril_consts.js. if (RIL.GECKO_SUPPORTED_NETWORK_TYPES.indexOf(type) < 0) { if (DEBUG) { this._debug("Unknown network type: " + type); } - supportedNetworkTypes = - RIL.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT.split(","); + RIL.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT.split(",").forEach(aType => { + enumNetworkTypes.push(RIL.GECKO_SUPPORTED_NETWORK_TYPES.indexOf(aType)); + }); break; } + enumNetworkTypes.push(RIL.GECKO_SUPPORTED_NETWORK_TYPES.indexOf(type)); } if (DEBUG) { - this._debug("Supported Network Types: " + supportedNetworkTypes); + this._debug("Supported Network Types: " + enumNetworkTypes); } - return supportedNetworkTypes; + + return enumNetworkTypes; }, /** * Helper for guarding us against invalid mode for clir. */ _isValidClirMode: function(aMode) { switch (aMode) { case Ci.nsIMobileConnection.CLIR_DEFAULT:
--- a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl +++ b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl @@ -230,17 +230,17 @@ interface nsIMobileConnectionService : n %{C++ template<typename T> struct already_AddRefed; already_AddRefed<nsIMobileConnectionService> NS_CreateMobileConnectionService(); %} -[scriptable, uuid(5250a0ba-19a2-4e5b-a5ee-1e69ba2897a9)] +[scriptable, uuid(99e43353-5fc4-497e-88a2-5fa6862ee64c)] interface nsIMobileConnection : nsISupports { /* * ICC service class. */ const long ICC_SERVICE_CLASS_NONE = 0; // not available const long ICC_SERVICE_CLASS_VOICE = (1 << 0); const long ICC_SERVICE_CLASS_DATA = (1 << 1); @@ -330,16 +330,25 @@ interface nsIMobileConnection : nsISuppo /** * CDMA roaming preference. */ const long CDMA_ROAMING_PREFERENCE_HOME = 0; const long CDMA_ROAMING_PREFERENCE_AFFILIATED = 1; const long CDMA_ROAMING_PREFERENCE_ANY = 2; + /** + * Supported network type. + */ + const long MOBILE_NETWORK_TYPE_GSM = 0; + const long MOBILE_NETWORK_TYPE_WCDMA = 1; + const long MOBILE_NETWORK_TYPE_CDMA = 2; + const long MOBILE_NETWORK_TYPE_EVDO = 3; + const long MOBILE_NETWORK_TYPE_LTE = 4; + readonly attribute unsigned long serviceId; /** * Called when any one who is interested in receiving unsolicited messages * from this nsIMobileConnection instance. */ void registerListener(in nsIMobileConnectionListener listener); void unregisterListener(in nsIMobileConnectionListener listener); @@ -381,20 +390,19 @@ interface nsIMobileConnection : nsISuppo * Current radio state. One of the nsIMobileConnection.MOBILE_RADIO_STATE_* * values. */ readonly attribute long radioState; /** * The network types supported by this radio. * - * @return an array of DOMString - * Possible values: 'gsm', 'wcdma', 'cdma', 'evdo', 'lte'. + * @return an array of nsIMobileConnection.MOBILE_NETWORK_TYPE_* values. */ - void getSupportedNetworkTypes([array, size_is(length)] out wstring types, + void getSupportedNetworkTypes([array, size_is(length)] out long types, [retval] out unsigned long length); /** * Search for available networks. * * @param requestCallback * Called when request is finished. *
--- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp @@ -108,29 +108,29 @@ MobileConnectionChild::GetIccId(nsAStrin NS_IMETHODIMP MobileConnectionChild::GetRadioState(int32_t* aRadioState) { *aRadioState = mRadioState; return NS_OK; } NS_IMETHODIMP -MobileConnectionChild::GetSupportedNetworkTypes(char16_t*** aTypes, +MobileConnectionChild::GetSupportedNetworkTypes(int32_t** aTypes, uint32_t* aLength) { NS_ENSURE_ARG(aTypes); NS_ENSURE_ARG(aLength); *aLength = mSupportedNetworkTypes.Length(); *aTypes = - static_cast<char16_t**>(nsMemory::Alloc((*aLength) * sizeof(char16_t*))); + static_cast<int32_t*>(nsMemory::Alloc((*aLength) * sizeof(int32_t))); NS_ENSURE_TRUE(*aTypes, NS_ERROR_OUT_OF_MEMORY); for (uint32_t i = 0; i < *aLength; i++) { - (*aTypes)[i] = ToNewUnicode(mSupportedNetworkTypes[i]); + (*aTypes)[i] = mSupportedNetworkTypes[i]; } return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetLastKnownNetwork(nsAString& aNetwork) {
--- a/dom/mobileconnection/ipc/MobileConnectionChild.h +++ b/dom/mobileconnection/ipc/MobileConnectionChild.h @@ -112,17 +112,17 @@ private: nsCOMArray<nsIMobileConnectionListener> mListeners; nsRefPtr<MobileConnectionInfo> mVoice; nsRefPtr<MobileConnectionInfo> mData; nsString mIccId; int32_t mRadioState; nsString mLastNetwork; nsString mLastHomeNetwork; int32_t mNetworkSelectionMode; - nsTArray<nsString> mSupportedNetworkTypes; + nsTArray<int32_t> mSupportedNetworkTypes; }; /****************************************************************************** * PMobileConnectionRequestChild ******************************************************************************/ /** * Child actor of PMobileConnectionRequest. The object is created when an
--- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp @@ -126,40 +126,39 @@ MobileConnectionParent::DeallocPMobileCo bool MobileConnectionParent::RecvInit(nsMobileConnectionInfo* aVoice, nsMobileConnectionInfo* aData, nsString* aLastKnownNetwork, nsString* aLastKnownHomeNetwork, nsString* aIccId, int32_t* aNetworkSelectionMode, int32_t* aRadioState, - nsTArray<nsString>* aSupportedNetworkTypes) + nsTArray<int32_t>* aSupportedNetworkTypes) { NS_ENSURE_TRUE(mMobileConnection, false); NS_ENSURE_SUCCESS(mMobileConnection->GetVoice(aVoice), false); NS_ENSURE_SUCCESS(mMobileConnection->GetData(aData), false); NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownNetwork(*aLastKnownNetwork), false); NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownHomeNetwork(*aLastKnownHomeNetwork), false); NS_ENSURE_SUCCESS(mMobileConnection->GetIccId(*aIccId), false); NS_ENSURE_SUCCESS(mMobileConnection->GetNetworkSelectionMode(aNetworkSelectionMode), false); NS_ENSURE_SUCCESS(mMobileConnection->GetRadioState(aRadioState), false); - char16_t** types = nullptr; + int32_t* types = nullptr; uint32_t length = 0; nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); NS_ENSURE_SUCCESS(rv, false); for (uint32_t i = 0; i < length; ++i) { - nsDependentString type(types[i]); - aSupportedNetworkTypes->AppendElement(type); + aSupportedNetworkTypes->AppendElement(types[i]); } - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); + nsMemory::Free(types); return true; } // nsIMobileConnectionListener NS_IMPL_ISUPPORTS(MobileConnectionParent, nsIMobileConnectionListener)
--- a/dom/mobileconnection/ipc/MobileConnectionParent.h +++ b/dom/mobileconnection/ipc/MobileConnectionParent.h @@ -47,17 +47,17 @@ protected: virtual bool DeallocPMobileConnectionRequestParent(PMobileConnectionRequestParent* aActor) MOZ_OVERRIDE; virtual bool RecvInit(nsMobileConnectionInfo* aVoice, nsMobileConnectionInfo* aData, nsString* aLastKnownNetwork, nsString* aLastKnownHomeNetwork, nsString* aIccId, int32_t* aNetworkSelectionMode, - int32_t* aRadioState, nsTArray<nsString>* aSupportedNetworkTypes) MOZ_OVERRIDE; + int32_t* aRadioState, nsTArray<int32_t>* aSupportedNetworkTypes) MOZ_OVERRIDE; private: nsCOMPtr<nsIMobileConnection> mMobileConnection; bool mLive; }; /****************************************************************************** * PMobileConnectionRequestParent
--- a/dom/mobileconnection/ipc/PMobileConnection.ipdl +++ b/dom/mobileconnection/ipc/PMobileConnection.ipdl @@ -46,17 +46,17 @@ parent: /** * Sync call only be called once per child actor for initialization. */ sync Init() returns (nsMobileConnectionInfo aVoice, nsMobileConnectionInfo aData, nsString aLastKnownNetwork, nsString aLastKnownHomeNetwork, nsString aIccId, int32_t aNetworkSelectionMode, - int32_t aRadioState, nsString[] aSupportedNetworkTypes); + int32_t aRadioState, int32_t[] aSupportedNetworkTypes); }; /** * MobileConnectionRequest */ struct GetNetworksRequest { };
--- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -2,16 +2,17 @@ /* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/Promise.h" #include "jsfriendapi.h" +#include "js/Debug.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DOMError.h" #include "mozilla/dom/OwningNonNull.h" #include "mozilla/dom/PromiseBinding.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/MediaStreamError.h" #include "mozilla/CycleCollectedJSRuntime.h" #include "mozilla/Preferences.h" @@ -319,31 +320,34 @@ Promise::CreateWrapper(ErrorResult& aRv) { AutoJSAPI jsapi; if (!jsapi.Init(mGlobal)) { aRv.Throw(NS_ERROR_UNEXPECTED); return; } JSContext* cx = jsapi.cx(); - JS::Rooted<JS::Value> ignored(cx); - if (!WrapNewBindingObject(cx, this, &ignored)) { + JS::Rooted<JS::Value> wrapper(cx); + if (!WrapNewBindingObject(cx, this, &wrapper)) { JS_ClearPendingException(cx); aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } dom::PreserveWrapper(this); // Now grab our allocation stack if (!CaptureStack(cx, mAllocationStack)) { JS_ClearPendingException(cx); aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } + + JS::RootedObject obj(cx, &wrapper.toObject()); + JS::dbg::onNewPromise(cx, obj); } void Promise::MaybeResolve(JSContext* aCx, JS::Handle<JS::Value> aValue) { MaybeResolveInternal(aCx, aValue); } @@ -1108,29 +1112,29 @@ Promise::RejectInternal(JSContext* aCx, JS::Handle<JS::Value> aValue) { mResolvePending = true; MaybeSettle(aValue, Rejected); } void -Promise::MaybeSettle(JS::Handle<JS::Value> aValue, - PromiseState aState) +Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState) { - // Promise.all() or Promise.race() implementations will repeatedly call - // Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState - // from asserting. - if (mState != Pending) { - return; - } - + mSettlementTimestamp = TimeStamp::Now(); SetResult(aValue); SetState(aState); - mSettlementTimestamp = TimeStamp::Now(); + + AutoJSAPI jsapi; + jsapi.Init(); + JSContext* cx = jsapi.cx(); + JS::RootedObject wrapper(cx, GetWrapper()); + MOZ_ASSERT(wrapper); // We preserved it + JSAutoCompartment ac(cx, wrapper); + JS::dbg::onPromiseSettled(cx, wrapper); // If the Promise was rejected, and there is no reject handler already setup, // watch for thread shutdown. if (aState == PromiseState::Rejected && !mHadRejectCallback && !NS_IsMainThread()) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); @@ -1145,16 +1149,30 @@ Promise::MaybeSettle(JS::Handle<JS::Valu MaybeReportRejectedOnce(); } } EnqueueCallbackTasks(); } void +Promise::MaybeSettle(JS::Handle<JS::Value> aValue, + PromiseState aState) +{ + // Promise.all() or Promise.race() implementations will repeatedly call + // Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState + // from asserting. + if (mState != Pending) { + return; + } + + Settle(aValue, aState); +} + +void Promise::EnqueueCallbackTasks() { nsTArray<nsRefPtr<PromiseCallback>> callbacks; callbacks.SwapElements(mState == Resolved ? mResolveCallbacks : mRejectCallbacks); mResolveCallbacks.Clear(); mRejectCallbacks.Clear();
--- a/dom/promise/Promise.h +++ b/dom/promise/Promise.h @@ -220,18 +220,18 @@ private: } // This method enqueues promise's resolve/reject callbacks with promise's // result. It's executed when the resolver.resolve() or resolver.reject() is // called or when the promise already has a result and new callbacks are // appended by then(), catch() or done(). void EnqueueCallbackTasks(); - void MaybeSettle(JS::Handle<JS::Value> aValue, - Promise::PromiseState aState); + void Settle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState); + void MaybeSettle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState); void AppendCallbacks(PromiseCallback* aResolveCallback, PromiseCallback* aRejectCallback); // If we have been rejected and our mResult is a JS exception, // report it to the error console. // Use MaybeReportRejectedOnce() for actual calls. void MaybeReportRejected();
--- a/dom/promise/tests/chrome.ini +++ b/dom/promise/tests/chrome.ini @@ -1,3 +1,6 @@ [DEFAULT] [test_dependentPromises.html] +[test_on_new_promise.html] +[test_on_promise_settled.html] +[test_on_promise_settled_duplicates.html]
new file mode 100644 --- /dev/null +++ b/dom/promise/tests/test_on_new_promise.html @@ -0,0 +1,45 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<!-- +Bug 1083210 - Sanity test for interaction between DOM promises and +Debugger.prototype.onNewPromise. +--> + +<html> +<head> + <title>Test for interaction with SpiderMonkey's Debugger.prototype.onNewPromise</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> + <script type="application/javascript"> + is(Object.prototype.toString.call(new Promise(function () {})), + "[object Promise]", + "We should have the native DOM promise implementation."); + + var Cu = Components.utils; + Cu.import("resource://gre/modules/jsdebugger.jsm"); + var dbgGlobal = new Cu.Sandbox(document.nodePrincipal); + addDebuggerToGlobal(dbgGlobal); + var dbg = new dbgGlobal.Debugger(this); + + var wrappedPromise; + dbg.onNewPromise = function (wp) { wrappedPromise = wp; }; + + var promise = new Promise(function () {}); + debugger; + ok(wrappedPromise); + is(wrappedPromise.unsafeDereference(), promise); + </script> +</pre> +</body> +</html> +
new file mode 100644 --- /dev/null +++ b/dom/promise/tests/test_on_promise_settled.html @@ -0,0 +1,54 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<!-- +Bug 1084065 - Sanity test for interaction between DOM promises and +Debugger.prototype.onPromiseResolved. +--> + +<html> +<head> + <title>Test for interaction with SpiderMonkey's Debugger.prototype.onNewPromise</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + is(Object.prototype.toString.call(new Promise(function () {})), + "[object Promise]", + "We should have the native DOM promise implementation."); + + var Cu = Components.utils; + Cu.import("resource://gre/modules/jsdebugger.jsm"); + var dbgGlobal = new Cu.Sandbox(document.nodePrincipal); + addDebuggerToGlobal(dbgGlobal); + var dbg = new dbgGlobal.Debugger(this); + + var wrappedPromise; + dbg.onPromiseSettled = function (wp) { wrappedPromise = wp; }; + + var promise = Promise.resolve(); + promise + .then(function () { + ok(wrappedPromise); + is(wrappedPromise.unsafeDereference(), promise); + dbg.onPromiseSettled = undefined; + }) + .then(null, function (e) { + ok(false, "Got an unexpected error: " + e); + }) + .then(SimpleTest.finish); + </script> +</pre> +</body> +</html> +
new file mode 100644 --- /dev/null +++ b/dom/promise/tests/test_on_promise_settled_duplicates.html @@ -0,0 +1,59 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<!-- +Bug 1084065 - Test that Debugger.prototype.onPromiseResolved doesn't get dupes. +--> + +<html> +<head> + <title>Test for interaction with SpiderMonkey's Debugger.prototype.onNewPromise</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + is(Object.prototype.toString.call(new Promise(function () {})), + "[object Promise]", + "We should have the native DOM promise implementation."); + + var Cu = Components.utils; + Cu.import("resource://gre/modules/jsdebugger.jsm"); + var dbgGlobal = new Cu.Sandbox(document.nodePrincipal); + addDebuggerToGlobal(dbgGlobal); + var dbg = new dbgGlobal.Debugger(this); + + var seen = new Set(); + dbg.onPromiseSettled = function (wp) { + is(seen.has(wp), false); + seen.add(wp); + }; + + var promise = new Promise(function (fulfill, reject) { + fulfill(1); + fulfill(2); + fulfill(3); + }); + + promise + .then(function () { + dbg.onPromiseSettled = undefined; + }) + .then(null, function (e) { + ok(false, "Got an unexpected error: " + e); + }) + .then(SimpleTest.finish); + </script> +</pre> +</body> +</html> +
--- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -422,16 +422,17 @@ this.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO, GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO, GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM, GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO, GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY ]; this.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT = "gsm,wcdma"; +// Index-item pair must be in sync with nsIMobileConnection.MOBILE_NETWORK_TYPE_* this.GECKO_SUPPORTED_NETWORK_TYPES = [ "gsm", "wcdma", "cdma", "evdo", "lte" ];
--- a/dom/webidl/AudioContext.webidl +++ b/dom/webidl/AudioContext.webidl @@ -73,18 +73,18 @@ interface AudioContext : EventTarget { [NewObject, Throws] PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag); }; // Mozilla extensions partial interface AudioContext { // Read AudioChannel.webidl for more information about this attribute. - [Pref="media.useAudioChannelService", SetterThrows] - attribute AudioChannel mozAudioChannelType; + [Pref="media.useAudioChannelService"] + readonly attribute AudioChannel mozAudioChannelType; // These 2 events are dispatched when the AudioContext object is muted by // the AudioChannelService. It's call 'interrupt' because when this event is // dispatched on a HTMLMediaElement, the audio stream is paused. [Pref="media.useAudioChannelService"] attribute EventHandler onmozinterruptbegin; [Pref="media.useAudioChannelService"]
deleted file mode 100644 --- a/dom/webidl/BrowserElement.webidl +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -callback BrowserElementNextPaintEventCallback = void (); - -dictionary BrowserElementDownloadOptions { - DOMString? filename; -}; - -[NoInterfaceObject] -interface BrowserElement { -}; - -BrowserElement implements BrowserElementCommon; -BrowserElement implements BrowserElementPrivileged; - -[NoInterfaceObject] -interface BrowserElementCommon { - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - void setVisible(boolean visible); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - DOMRequest getVisible(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - void setActive(boolean active); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - boolean getActive(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - void addNextPaintListener(BrowserElementNextPaintEventCallback listener); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser embed-widgets"] - void removeNextPaintListener(BrowserElementNextPaintEventCallback listener); -}; - -[NoInterfaceObject] -interface BrowserElementPrivileged { - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void sendMouseEvent(DOMString type, - unsigned long x, - unsigned long y, - unsigned long button, - unsigned long clickCount, - unsigned long modifiers); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - Func="TouchEvent::PrefEnabled", - CheckPermissions="browser"] - void sendTouchEvent(DOMString type, - sequence<unsigned long> identifiers, - sequence<long> x, - sequence<long> y, - sequence<unsigned long> rx, - sequence<unsigned long> ry, - sequence<float> rotationAngles, - sequence<float> forces, - unsigned long count, - unsigned long modifiers); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void goBack(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void goForward(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void reload(optional boolean hardReload = false); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void stop(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest download(DOMString url, - optional BrowserElementDownloadOptions options); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest purgeHistory(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest getScreenshot([EnforceRange] unsigned long width, - [EnforceRange] unsigned long height, - optional DOMString mimeType=""); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - void zoom(float zoom); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest getCanGoBack(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest getCanGoForward(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest getContentDimensions(); - - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] - DOMRequest setInputMethodActive(boolean isActive); -};
--- a/dom/webidl/HTMLIFrameElement.webidl +++ b/dom/webidl/HTMLIFrameElement.webidl @@ -58,9 +58,8 @@ partial interface HTMLIFrameElement { partial interface HTMLIFrameElement { // nsIMozBrowserFrame [ChromeOnly] readonly attribute DOMString appManifestURL; }; HTMLIFrameElement implements MozFrameLoaderOwner; -HTMLIFrameElement implements BrowserElement;
--- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -50,17 +50,16 @@ WEBIDL_FILES = [ 'AutocompleteInfo.webidl', 'BarProp.webidl', 'BatteryManager.webidl', 'BeforeAfterKeyboardEvent.webidl', 'BeforeUnloadEvent.webidl', 'BiquadFilterNode.webidl', 'Blob.webidl', 'BoxObject.webidl', - 'BrowserElement.webidl', 'BrowserElementDictionaries.webidl', 'CallsList.webidl', 'CameraCapabilities.webidl', 'CameraControl.webidl', 'CameraManager.webidl', 'CameraUtil.webidl', 'CanvasRenderingContext2D.webidl', 'CaretPosition.webidl',
--- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -93,22 +93,22 @@ skip-if(Android||B2G) needs-focus == 462 == readonly-editable.html readonly-editable-ref.html == dynamic-overflow-change.html dynamic-overflow-change-ref.html == 694880-1.html 694880-ref.html == 694880-2.html 694880-ref.html == 694880-3.html 694880-ref.html == 388980-1.html 388980-1-ref.html needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658 -needs-focus == 824080-1.html 824080-1-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-1.html 824080-1-ref.html needs-focus == 824080-2.html 824080-2-ref.html -needs-focus test-pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html needs-focus != 824080-2.html 824080-3.html -needs-focus == 824080-4.html 824080-4-ref.html -needs-focus test-pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-4.html 824080-4-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html needs-focus != 824080-4.html 824080-5.html needs-focus == 824080-6.html 824080-6-ref.html needs-focus pref(selectioncaret.enabled,false) == 824080-7.html 824080-7-ref.html needs-focus != 824080-6.html 824080-7.html # Bug 674927: copy spellcheck-textarea tests to contenteditable == spellcheck-contenteditable-attr.html spellcheck-contenteditable-nofocus-ref.html fails-if(Android||B2G) needs-focus != spellcheck-contenteditable-attr.html spellcheck-contenteditable-ref.html # B2G no spellcheck underline needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-ref.html
--- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -678,21 +678,22 @@ GLContext::InitWithPrefix(const char *pr if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) { // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer) // multisampling hardcodes blending with the default blendfunc, which breaks WebGL. MarkUnsupported(GLFeature::framebuffer_multisample); } #ifdef XP_MACOSX - // The Mac Nvidia driver, for versions up to and including 10.8, don't seem - // to properly support this. See 814839 + // The Mac Nvidia driver, for versions up to and including 10.8, + // don't seem to properly support this. See 814839 // this has been fixed in Mac OS X 10.9. See 907946 + // and it also works in 10.8.3 and higher. See 1094338. if (Vendor() == gl::GLVendor::NVIDIA && - !nsCocoaFeatures::OnMavericksOrLater()) + !nsCocoaFeatures::IsAtLeastVersion(10,8,3)) { MarkUnsupported(GLFeature::depth_texture); } #endif } NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) || (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
--- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -389,20 +389,20 @@ struct ParamTraits<nsIntPoint> static bool Read(const Message* msg, void** iter, paramType* result) { return (ReadParam(msg, iter, &result->x) && ReadParam(msg, iter, &result->y)); } }; -template<> -struct ParamTraits<mozilla::gfx::IntSize> +template<typename T> +struct ParamTraits<mozilla::gfx::IntSizeTyped<T> > { - typedef mozilla::gfx::IntSize paramType; + typedef mozilla::gfx::IntSizeTyped<T> paramType; static void Write(Message* msg, const paramType& param) { WriteParam(msg, param.width); WriteParam(msg, param.height); } static bool Read(const Message* msg, void** iter, paramType* result) @@ -751,16 +751,17 @@ struct ParamTraits<mozilla::layers::Fram WriteParam(aMsg, aParam.mIsRoot); WriteParam(aMsg, aParam.mHasScrollgrab); WriteParam(aMsg, aParam.mUpdateScrollOffset); WriteParam(aMsg, aParam.mScrollGeneration); WriteParam(aMsg, aParam.mExtraResolution); WriteParam(aMsg, aParam.mBackgroundColor); WriteParam(aMsg, aParam.mDoSmoothScroll); WriteParam(aMsg, aParam.mSmoothScrollOffset); + WriteParam(aMsg, aParam.GetLineScrollAmount()); WriteParam(aMsg, aParam.GetContentDescription()); } static bool ReadContentDescription(const Message* aMsg, void** aIter, paramType* aResult) { nsCString str; if (!ReadParam(aMsg, aIter, &str)) { return false; @@ -792,16 +793,17 @@ struct ParamTraits<mozilla::layers::Fram ReadParam(aMsg, aIter, &aResult->mIsRoot) && ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) && ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) && ReadParam(aMsg, aIter, &aResult->mScrollGeneration) && ReadParam(aMsg, aIter, &aResult->mExtraResolution) && ReadParam(aMsg, aIter, &aResult->mBackgroundColor) && ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) && ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) && + ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) && ReadContentDescription(aMsg, aIter, aResult)); } }; template<> struct ParamTraits<mozilla::layers::TextureFactoryIdentifier> { typedef mozilla::layers::TextureFactoryIdentifier paramType;
--- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -60,16 +60,17 @@ public: , mSmoothScrollOffset(0, 0) , mRootCompositionSize(0, 0) , mDisplayPortMargins(0, 0, 0, 0) , mUseDisplayPortMargins(false) , mPresShellId(-1) , mViewport(0, 0, 0, 0) , mExtraResolution(1) , mBackgroundColor(0, 0, 0, 0) + , mLineScrollAmount(0, 0) { } // Default copy ctor and operator= are fine bool operator==(const FrameMetrics& aOther) const { return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) && @@ -90,17 +91,18 @@ public: mScrollId == aOther.mScrollId && mScrollParentId == aOther.mScrollParentId && mScrollOffset == aOther.mScrollOffset && mSmoothScrollOffset == aOther.mSmoothScrollOffset && mHasScrollgrab == aOther.mHasScrollgrab && mUpdateScrollOffset == aOther.mUpdateScrollOffset && mExtraResolution == aOther.mExtraResolution && mBackgroundColor == aOther.mBackgroundColor && - mDoSmoothScroll == aOther.mDoSmoothScroll; + mDoSmoothScroll == aOther.mDoSmoothScroll && + mLineScrollAmount == aOther.mLineScrollAmount; } bool operator!=(const FrameMetrics& aOther) const { return !operator==(aOther); } bool IsDefault() const { @@ -509,16 +511,26 @@ public: return mMayHaveTouchListeners; } void SetMayHaveTouchListeners(bool aMayHaveTouchListeners) { mMayHaveTouchListeners = aMayHaveTouchListeners; } + const LayoutDeviceIntSize& GetLineScrollAmount() const + { + return mLineScrollAmount; + } + + void SetLineScrollAmount(const LayoutDeviceIntSize& size) + { + mLineScrollAmount = size; + } + private: // New fields from now on should be made private and old fields should // be refactored to be private. // Whether or not this frame may have a touch listeners. bool mMayHaveTouchListeners; // Whether or not this frame may have a touch caret. @@ -600,16 +612,19 @@ private: // The background color to use when overscrolling. gfxRGBA mBackgroundColor; // A description of the content element corresponding to this frame. // This is empty unless this is a scrollable layer and the // apz.printtree pref is turned on. nsCString mContentDescription; + + // The value of GetLineScrollAmount(), for scroll frames. + LayoutDeviceIntSize mLineScrollAmount; }; /** * This class allows us to uniquely identify a scrollable layer. The * mLayersId identifies the layer tree (corresponding to a child process * and/or tab) that the scrollable layer belongs to. The mPresShellId * is a temporal identifier (corresponding to the document loaded that * contains the scrollable layer, which may change over time). The
--- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -606,16 +606,39 @@ APZCTreeManager::ReceiveInputEvent(Input nsEventStatus result = nsEventStatus_eIgnore; Matrix4x4 transformToApzc; HitTestResult hitResult = NoApzcHit; switch (aEvent.mInputType) { case MULTITOUCH_INPUT: { MultiTouchInput& touchInput = aEvent.AsMultiTouchInput(); result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId); break; + } case SCROLLWHEEL_INPUT: { + ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput(); + nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(wheelInput.mOrigin, + &hitResult); + if (apzc) { + MOZ_ASSERT(hitResult == ApzcHitRegion || hitResult == ApzcContentRegion); + + transformToApzc = GetScreenToApzcTransform(apzc); + wheelInput.mLocalOrigin = + TransformTo<ParentLayerPixel>(transformToApzc, wheelInput.mOrigin); + + result = mInputQueue->ReceiveInputEvent( + apzc, + /* aTargetConfirmed = */ hitResult, + wheelInput, aOutInputBlockId); + + // Update the out-parameters so they are what the caller expects. + apzc->GetGuid(aOutTargetGuid); + Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc); + wheelInput.mOrigin = + TransformTo<ScreenPixel>(transformToGecko, wheelInput.mLocalOrigin); + } + break; } case PANGESTURE_INPUT: { PanGestureInput& panInput = aEvent.AsPanGestureInput(); nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint, &hitResult); if (apzc) { MOZ_ASSERT(hitResult == ApzcHitRegion || hitResult == ApzcContentRegion); transformToApzc = GetScreenToApzcTransform(apzc); panInput.mLocalPanStartPoint = TransformTo<ParentLayerPixel>(
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -528,31 +528,19 @@ public: } /** * Advances a fling by an interpolated amount based on the passed in |aDelta|. * This should be called whenever sampling the content transform for this * frame. Returns true if the fling animation should be advanced by one frame, * or false if there is no fling or the fling has ended. */ - virtual bool Sample(FrameMetrics& aFrameMetrics, - const TimeDuration& aDelta) MOZ_OVERRIDE + virtual bool DoSample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) MOZ_OVERRIDE { - // If the fling is handed off to our APZC from a child, on the first call to - // Sample() aDelta might be negative because it's computed as the sample time - // from SampleContentTransformForFrame() minus our APZC's mLastSampleTime - // which is the time the child handed off the fling from its call to - // SampleContentTransformForFrame() with the same sample time. If we allow - // the negative aDelta to be processed, it will yield a displacement in the - // direction opposite to the fling, which can cause us to overscroll and - // hand off the fling to _our_ parent, which effectively kills the fling. - if (aDelta.ToMilliseconds() <= 0) { - return true; - } - float friction = gfxPrefs::APZFlingFriction(); float threshold = gfxPrefs::APZFlingStoppedThreshold(); bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta, friction, threshold), shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta, friction, threshold); // If we shouldn't continue the fling, let's just stop and repaint. if (!shouldContinueFlingX && !shouldContinueFlingY) { APZC_LOG("%p ending fling animation. overscrolled=%d\n", &mApzc, mApzc.IsOverscrolled()); @@ -650,18 +638,18 @@ public: CSSPoint aEndOffset, CSSToParentLayerScale aEndZoom) : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) , mStartOffset(aStartOffset) , mStartZoom(aStartZoom) , mEndOffset(aEndOffset) , mEndZoom(aEndZoom) {} - virtual bool Sample(FrameMetrics& aFrameMetrics, - const TimeDuration& aDelta) MOZ_OVERRIDE + virtual bool DoSample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) MOZ_OVERRIDE { mDuration += aDelta; double animPosition = mDuration / mTotalDuration; if (animPosition >= 1.0) { aFrameMetrics.SetZoom(mEndZoom); aFrameMetrics.SetScrollOffset(mEndOffset); return false; @@ -707,18 +695,18 @@ class OverscrollAnimation: public AsyncP public: explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) : mApzc(aApzc) { mApzc.mX.SetVelocity(aVelocity.x); mApzc.mY.SetVelocity(aVelocity.y); } - virtual bool Sample(FrameMetrics& aFrameMetrics, - const TimeDuration& aDelta) MOZ_OVERRIDE + virtual bool DoSample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) MOZ_OVERRIDE { // Can't inline these variables due to short-circuit evaluation. bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta); bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta); return continueX || continueY; } private: AsyncPanZoomController& mApzc; @@ -742,22 +730,17 @@ public: } /** * Advances a smooth scroll simulation based on the time passed in |aDelta|. * This should be called whenever sampling the content transform for this * frame. Returns true if the smooth scroll should be advanced by one frame, * or false if the smooth scroll has ended. */ - bool Sample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) { - - if (aDelta.ToMilliseconds() <= 0) { - return true; - } - + bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) { if (mXAxisModel.IsFinished() && mYAxisModel.IsFinished()) { return false; } mXAxisModel.Simulate(aDelta); mYAxisModel.Simulate(aDelta); CSSPoint position = CSSPoint::FromAppUnits(nsPoint(mXAxisModel.GetPosition(), @@ -1082,16 +1065,21 @@ nsEventStatus AsyncPanZoomController::Ha case PanGestureInput::PANGESTURE_END: rv = OnPanEnd(panGestureInput); break; case PanGestureInput::PANGESTURE_MOMENTUMSTART: rv = OnPanMomentumStart(panGestureInput); break; case PanGestureInput::PANGESTURE_MOMENTUMPAN: rv = OnPan(panGestureInput, false); break; case PanGestureInput::PANGESTURE_MOMENTUMEND: rv = OnPanMomentumEnd(panGestureInput); break; default: NS_WARNING("Unhandled pan gesture"); break; } break; } + case SCROLLWHEEL_INPUT: { + const ScrollWheelInput& scrollInput = aEvent.AsScrollWheelInput(); + rv = OnScrollWheel(scrollInput); + break; + } default: return HandleGestureEvent(aEvent); } return rv; } nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent) { @@ -1465,16 +1453,82 @@ AsyncPanZoomController::ConvertToGecko(c ReentrantMonitorAutoEnter lock(mMonitor); *aOut = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel; } return true; } return false; } +nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent) +{ + double deltaX = aEvent.mDeltaX; + double deltaY = aEvent.mDeltaY; + switch (aEvent.mDeltaType) { + case ScrollWheelInput::SCROLLDELTA_LINE: { + LayoutDeviceIntSize scrollAmount = mFrameMetrics.GetLineScrollAmount(); + deltaX *= scrollAmount.width; + deltaY *= scrollAmount.height; + break; + } + default: + MOZ_ASSERT_UNREACHABLE("unexpected scroll delta type"); + return nsEventStatus_eConsumeNoDefault; + } + + switch (aEvent.mScrollMode) { + case ScrollWheelInput::SCROLLMODE_INSTANT: { + // Decompose into pan events for simplicity. + PanGestureInput start(PanGestureInput::PANGESTURE_START, aEvent.mTime, aEvent.mTimeStamp, + aEvent.mOrigin, ScreenPoint(0, 0), aEvent.modifiers); + start.mLocalPanStartPoint = aEvent.mLocalOrigin; + OnPanBegin(start); + + // Pan gestures use natural directions which are inverted from scroll + // wheel and touchpad scroll gestures, so we invert x/y here. Since the + // zoom includes any device : css pixel zoom, we convert to CSS pixels + // before applying the zoom. + LayoutDevicePoint devicePixelDelta(-deltaX, -deltaY); + ParentLayerPoint delta = (devicePixelDelta / mFrameMetrics.mDevPixelsPerCSSPixel) * + mFrameMetrics.GetZoom(); + + PanGestureInput move(PanGestureInput::PANGESTURE_PAN, aEvent.mTime, aEvent.mTimeStamp, + aEvent.mOrigin, + ToScreenCoordinates(delta, aEvent.mLocalOrigin), + aEvent.modifiers); + move.mLocalPanStartPoint = aEvent.mLocalOrigin; + move.mLocalPanDisplacement = delta; + OnPan(move, false); + + PanGestureInput end(PanGestureInput::PANGESTURE_END, aEvent.mTime, aEvent.mTimeStamp, + aEvent.mOrigin, ScreenPoint(0, 0), aEvent.modifiers); + end.mLocalPanStartPoint = aEvent.mLocalOrigin; + OnPanEnd(start); + break; + } + + case ScrollWheelInput::SCROLLMODE_SMOOTH: { + CSSPoint delta = LayoutDevicePoint(deltaX, deltaY) / mFrameMetrics.mDevPixelsPerCSSPixel; + + // If we're already in a smooth scroll animation, don't cancel it. This + // lets us preserve the existing scrolling velocity. + if (mState != SMOOTH_SCROLL) { + CancelAnimation(); + mFrameMetrics.SetSmoothScrollOffset(mFrameMetrics.GetScrollOffset() + delta); + } else { + mFrameMetrics.SetSmoothScrollOffset(mFrameMetrics.GetSmoothScrollOffset() + delta); + } + StartSmoothScroll(); + break; + } + } + + return nsEventStatus_eConsumeNoDefault; +} + nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) { APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState); mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime); mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); if (mPanGestureState) { mPanGestureState->GetOverscrollHandoffChain()->CancelAnimations(); } else {
--- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -410,16 +410,21 @@ protected: nsEventStatus OnPanCancelled(const PanGestureInput& aEvent); nsEventStatus OnPanBegin(const PanGestureInput& aEvent); nsEventStatus OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad); nsEventStatus OnPanEnd(const PanGestureInput& aEvent); nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent); nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent); /** + * Helper methods for handling scroll wheel events. + */ + nsEventStatus OnScrollWheel(const ScrollWheelInput& aEvent); + + /** * Helper methods for long press gestures. */ nsEventStatus OnLongPress(const TapGestureInput& aEvent); nsEventStatus OnLongPressUp(const TapGestureInput& aEvent); /** * Helper method for single tap gestures. */ @@ -1120,18 +1125,30 @@ class AsyncPanZoomAnimation { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation) public: explicit AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval = TimeDuration::Forever()) : mRepaintInterval(aRepaintInterval) { } - virtual bool Sample(FrameMetrics& aFrameMetrics, - const TimeDuration& aDelta) = 0; + virtual bool DoSample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) = 0; + + bool Sample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) { + // In some situations, particularly when handoff is involved, it's possible + // for |aDelta| to be negative on the first call to sample. Ignore such a + // sample here, to avoid each derived class having to deal with this case. + if (aDelta.ToMilliseconds() <= 0) { + return true; + } + + return DoSample(aFrameMetrics, aDelta); + } /** * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks| * for more information. * Clears |mDeferredTasks|. */ Vector<Task*> TakeDeferredTasks() { Vector<Task*> result;
--- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -524,18 +524,16 @@ ClientLayerManager::StopFrameTimeRecordi if (renderer) { renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals); } } void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { - gfxPlatform::GetPlatform()->FenceContentDrawing(); - mPhase = PHASE_FORWARD; mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(); TimeStamp transactionStart; if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) { transactionStart = mTransactionIdAllocator->GetTransactionStart(); } else { transactionStart = mTransactionStart;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -824,18 +824,16 @@ CompositorD3D11::BeginFrame(const nsIntR NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?"); if (::IsIconic(mHwnd)) { *aRenderBoundsOut = Rect(); return; } UpdateRenderTarget(); - gfxPlatform::GetPlatform()->WaitContentDrawing(); - // Failed to create a render target or the view. if (!mDefaultRT || !mDefaultRT->mRTView || mSize.width == 0 || mSize.height == 0) { *aRenderBoundsOut = Rect(); return; } mContext->IASetInputLayout(mAttachments->mInputLayout);
--- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -352,29 +352,29 @@ TextureClientD3D11::AllocateForSurface(g ID3D11Device* d3d11device = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice(); if (gfxPrefs::Direct2DUse1_1() && d3d11device) { CD3D11_TEXTURE2D_DESC newDesc(mFormat == SurfaceFormat::A8 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); - newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; hr = d3d11device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture)); } else #endif { ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1, D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE); - newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED; + newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture10)); } if (FAILED(hr)) { gfx::gfxCriticalError() << "[D3D11] CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr); return false; }
--- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -242,18 +242,16 @@ public: * rendering to offscreen surfaces on this platform, making it safe to * render content to data surfaces. This is generally false on platforms * which use different backends for each type of DrawTarget. */ virtual bool CanRenderContentToDataSurface() const { return false; } - virtual void FenceContentDrawing() {} - virtual void WaitContentDrawing() {} /** * Returns true if we should use Azure to render content with aTarget. For * example, it is possible that we are using Direct2D for rendering and thus * using Azure. But we want to render to a CairoDrawTarget, in which case * SupportsAzureContent will return true but SupportsAzureContentForDrawTarget * will return false. */ bool SupportsAzureContentForDrawTarget(mozilla::gfx::DrawTarget* aTarget);
--- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1429,116 +1429,16 @@ gfxWindowsPlatform::GetD3D9DeviceManager NS_WARNING("Could not initialise device manager"); mDeviceManager = nullptr; } } return mDeviceManager; } -ID3D11Texture2D* -gfxWindowsPlatform::GetD3D11Texture() -{ - if (mD3D11Texture) { - return mD3D11Texture; - } - - MOZ_ASSERT(mD3D10Texture || mD3D11ContentTexture); - - RefPtr<IDXGIResource> resource; - if (mD3D10Texture) { - mD3D10Texture->QueryInterface((IDXGIResource**)byRef(resource)); - } else { - mD3D11ContentTexture->QueryInterface((IDXGIResource**)byRef(resource)); - } - HANDLE sharedHandle; - HRESULT hr = resource->GetSharedHandle(&sharedHandle); - - hr = GetD3D11Device()->OpenSharedResource(sharedHandle, - __uuidof(ID3D11Texture2D), - (void**)(ID3D11Texture2D**)byRef(mD3D11Texture)); - - return mD3D11Texture; -} - -ID3D11Texture2D* -gfxWindowsPlatform::GetD3D11ContentTexture() -{ - if (mD3D11ContentTexture) { - return mD3D11ContentTexture; - } - ID3D11Device* device = GetD3D11ContentDevice(); - - CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM, - 1, 1, 1, 1, - D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); - - newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; - - HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mD3D11ContentTexture)); - return mD3D11ContentTexture; -} - -ID3D10Texture2D* -gfxWindowsPlatform::GetD3D10Texture() -{ - if (mD3D10Texture) { - return mD3D10Texture; - } - ID3D10Device* device = GetD3D10Device(); - - CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM, - 1, 1, 1, 1, - D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE); - - newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; - - HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mD3D10Texture)); - return mD3D10Texture; -} - -void -gfxWindowsPlatform::FenceContentDrawing() -{ -#ifdef USE_D2D1_1 - if (gfxPrefs::Direct2DUse1_1() && GetD3D11ContentDevice()) { - ID3D11Texture2D* tex = GetD3D11ContentTexture(); - RefPtr<IDXGIKeyedMutex> mutex; - tex->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); - mutex->AcquireSync(0, INFINITE); - RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForD3D11Texture(tex, SurfaceFormat::B8G8R8A8); - dt->ClearRect(Rect(0, 0, 1, 1)); - dt->Flush(); - dt = nullptr; - mutex->ReleaseSync(0); - } else -#endif - if (GetD3D10Device()) { - ID3D10Texture2D* tex = GetD3D10Texture(); - RefPtr<IDXGIKeyedMutex> mutex; - tex->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); - mutex->AcquireSync(0, INFINITE); - RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForD3D10Texture(tex, SurfaceFormat::B8G8R8A8); - dt->ClearRect(Rect(0, 0, 1, 1)); - dt->Flush(); - dt = nullptr; - mutex->ReleaseSync(0); - } -} - -void -gfxWindowsPlatform::WaitContentDrawing() -{ - ID3D11Texture2D *sentinelTexture = GetD3D11Texture(); - RefPtr<IDXGIKeyedMutex> mutex; - sentinelTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); - mutex->AcquireSync(0, INFINITE); - mutex->ReleaseSync(0); -} - ID3D11Device* gfxWindowsPlatform::GetD3D11Device() { if (mD3D11DeviceInitialized) { return mD3D11Device; } InitD3D11Devices();
--- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -50,17 +50,16 @@ class DrawTarget; namespace layers { class DeviceManagerD3D9; class ReadbackManagerD3D11; } } struct IDirect3DDevice9; struct ID3D11Device; struct IDXGIAdapter1; -struct ID3D11Texture2D; class nsIMemoryReporter; /** * Utility to get a Windows HDC from a Moz2D DrawTarget. If the DrawTarget is * not backed by a HDC this will get the HDC for the screen device context * instead. */ @@ -251,23 +250,16 @@ public: IDirect3DDevice9* GetD3D9Device(); #ifdef CAIRO_HAS_D2D_SURFACE cairo_device_t *GetD2DDevice() { return mD2DDevice; } ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; } #endif ID3D11Device *GetD3D11Device(); ID3D11Device *GetD3D11ContentDevice(); - ID3D10Texture2D* GetD3D10Texture(); - ID3D11Texture2D* GetD3D11Texture(); - ID3D11Texture2D* GetD3D11ContentTexture(); - - virtual void FenceContentDrawing(); - virtual void WaitContentDrawing(); - mozilla::layers::ReadbackManagerD3D11* GetReadbackManager(); static bool IsOptimus(); protected: RenderMode mRenderMode; int8_t mUseClearTypeForDownloadableFonts; @@ -292,21 +284,16 @@ private: #endif mozilla::RefPtr<IDXGIAdapter1> mAdapter; nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager; mozilla::RefPtr<ID3D11Device> mD3D11Device; mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice; bool mD3D11DeviceInitialized; mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager; - mozilla::RefPtr<ID3D10Texture2D> mD3D10Texture; - mozilla::RefPtr<ID3D11Texture2D> mD3D11Texture; - mozilla::RefPtr<ID3D11Texture2D> mD3D11ContentTexture; - - virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size); // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts; }; bool DoesD3D11DeviceWork(ID3D11Device *device);
--- a/image/decoders/nsBMPDecoder.cpp +++ b/image/decoders/nsBMPDecoder.cpp @@ -7,16 +7,17 @@ // This is a Cross-Platform BMP Decoder, which should work everywhere, including // Big-Endian machines like the PowerPC. #include <stdlib.h> #include "ImageLogging.h" #include "mozilla/Endian.h" +#include "mozilla/Likely.h" #include "nsBMPDecoder.h" #include "nsIInputStream.h" #include "RasterImage.h" #include <algorithm> namespace mozilla { namespace image { @@ -653,20 +654,20 @@ nsBMPDecoder::WriteInternal(const char* (mCurLine - 1); uint32_t heightDifference = GetHeight() - mCurLine + 1; uint32_t pixelCount = GetWidth() * heightDifference; memset(start, 0, pixelCount * sizeof(uint32_t)); + PostHasTransparency(); mHaveAlphaData = true; } - SetPixel(d, p[2], p[1], p[0], mHaveAlphaData ? - p[3] : 0xFF); + SetPixel(d, p[2], p[1], p[0], mHaveAlphaData ? p[3] : 0xFF); } else { SetPixel(d, p[2], p[1], p[0]); } p += 4; --lpos; } break; default: @@ -784,31 +785,37 @@ nsBMPDecoder::WriteInternal(const char* case eRLEStateNeedXDelta: // Handle the XDelta and proceed to get Y Delta byte = *aBuffer++; aCount--; mCurPos += byte; // Delta encoding makes it possible to skip pixels // making the image transparent. + if (MOZ_UNLIKELY(!mHaveAlphaData)) { + PostHasTransparency(); + } mUseAlphaData = mHaveAlphaData = true; if (mCurPos > mBIH.width) { mCurPos = mBIH.width; } mState = eRLEStateNeedYDelta; continue; case eRLEStateNeedYDelta: // Get the Y Delta and then "handle" the move byte = *aBuffer++; aCount--; mState = eRLEStateInitial; // Delta encoding makes it possible to skip pixels // making the image transparent. + if (MOZ_UNLIKELY(!mHaveAlphaData)) { + PostHasTransparency(); + } mUseAlphaData = mHaveAlphaData = true; mCurLine -= std::min<int32_t>(byte, mCurLine); break; case eRLEStateAbsoluteMode: // Absolute Mode case eRLEStateAbsoluteModePadded: if (mStateData) {