зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
4f0f16c656
|
@ -451,6 +451,18 @@ AndroidPresenter.prototype.liveRegion =
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -709,12 +709,12 @@
|
|||
</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>
|
||||
|
||||
|
|
|
@ -8,22 +8,27 @@
|
|||
|
||||
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)
|
||||
|
@ -31,61 +36,124 @@ let readLogFile = function(logLocation) {
|
|||
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
|
||||
);
|
||||
}
|
||||
|
||||
const O_READONLY = 0;
|
||||
const O_NONBLOCK = 1 << 11;
|
||||
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 BUF_SIZE = 2048;
|
||||
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
|
||||
|
||||
let BufType = this.ctypes.ArrayType(this.ctypes.char);
|
||||
let buf = new BufType(BUF_SIZE);
|
||||
let logArray = [];
|
||||
this.key_buf = this.ctypes.char.array(SYSTEM_PROPERTY_KEY_MAX)();
|
||||
this.value_buf = this.ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)();
|
||||
},
|
||||
|
||||
let logFd = this.open(logLocation, O_READONLY | O_NONBLOCK);
|
||||
if (logFd === -1) {
|
||||
return null;
|
||||
}
|
||||
cleanup: function() {
|
||||
this.libc.close();
|
||||
|
||||
let readStart = Date.now();
|
||||
let readCount = 0;
|
||||
while (true) {
|
||||
let count = this.read(logFd, buf, BUF_SIZE);
|
||||
readCount += 1;
|
||||
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;
|
||||
|
||||
if (count <= 0) {
|
||||
// log has return due to being nonblocking or running out of things
|
||||
break;
|
||||
this.libc = null;
|
||||
this.ctypes = 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 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;
|
||||
}
|
||||
for(let i = 0; i < count; i++) {
|
||||
logArray.push(buf[i]);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
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 = {};
|
||||
|
||||
while(true) {
|
||||
let prop_info = this.property_find_nth(n);
|
||||
if(prop_info.isNull()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
propertyDict[key] = value;
|
||||
n++;
|
||||
}
|
||||
|
||||
return propertyDict;
|
||||
}
|
||||
|
||||
let logTypedArray = new Uint8Array(logArray);
|
||||
|
||||
this.close(logFd);
|
||||
|
||||
return logTypedArray;
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
|
@ -215,71 +215,14 @@ function prettyPrintLogArray(array) {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -294,7 +237,6 @@ function prettyPrintArray(array) {
|
|||
|
||||
this.LogParser = {
|
||||
parseLogArray: parseLogArray,
|
||||
parsePropertiesArray: parsePropertiesArray,
|
||||
prettyPrintArray: prettyPrintArray,
|
||||
prettyPrintLogArray: prettyPrintLogArray,
|
||||
prettyPrintPropertiesArray: prettyPrintPropertiesArray
|
||||
|
|
|
@ -79,7 +79,6 @@ let LogShake = {
|
|||
* 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,
|
||||
|
@ -210,6 +209,14 @@ let LogShake = {
|
|||
*/
|
||||
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 {
|
||||
|
|
Двоичные данные
b2g/components/test/unit/data/test_properties
Двоичные данные
b2g/components/test/unit/data/test_properties
Двоичный файл не отображается.
|
@ -8,7 +8,7 @@
|
|||
* log devices
|
||||
*/
|
||||
function run_test() {
|
||||
Components.utils.import('resource:///modules/LogCapture.jsm');
|
||||
Components.utils.import("resource:///modules/LogCapture.jsm");
|
||||
|
||||
function verifyLog(log) {
|
||||
// log exists
|
||||
|
@ -17,9 +17,14 @@ function run_test() {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -2,48 +2,73 @@
|
|||
|
||||
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');
|
||||
|
||||
let propertiesFile = do_get_file('data/test_properties');
|
||||
let loggerFile = do_get_file('data/test_logger_file');
|
||||
|
||||
let propertiesStream = makeStream(propertiesFile);
|
||||
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');
|
||||
|
||||
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'
|
||||
};
|
||||
|
||||
deepEqual(expectedLogEntry, logMessages[0]);
|
||||
Cu.import("resource:///modules/LogParser.jsm");
|
||||
debug("Starting");
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function makeStream(file) {
|
||||
var fileStream = Cc['@mozilla.org/network/file-input-stream;1']
|
||||
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']
|
||||
var bis = Cc["@mozilla.org/binaryinputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
bis.setInputStream(fileStream);
|
||||
return bis;
|
||||
}
|
||||
|
||||
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 loggerArray = new Uint8Array(loggerStream.readByteArray(4037));
|
||||
|
||||
loggerStream.close();
|
||||
|
||||
let logMessages = LogParser.parseLogArray(loggerArray);
|
||||
|
||||
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"
|
||||
};
|
||||
|
||||
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");
|
||||
|
||||
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();
|
||||
});
|
||||
|
|
|
@ -8,19 +8,19 @@
|
|||
|
||||
/* 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,
|
||||
|
@ -34,7 +34,7 @@ function sendDeviceMotionEvent(x, y, z) {
|
|||
// conditions.
|
||||
function sendScreenChangeEvent(screenEnabled) {
|
||||
let event = {
|
||||
type: 'screenchange',
|
||||
type: "screenchange",
|
||||
detail: {
|
||||
screenEnabled: screenEnabled
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ function sendScreenChangeEvent(screenEnabled) {
|
|||
|
||||
function debug(msg) {
|
||||
var timestamp = Date.now();
|
||||
dump('LogShake: ' + timestamp + ': ' + msg);
|
||||
dump("LogShake: " + timestamp + ": " + msg);
|
||||
}
|
||||
|
||||
add_test(function test_do_log_capture_after_shaking() {
|
||||
|
@ -61,7 +61,7 @@ add_test(function test_do_log_capture_after_shaking() {
|
|||
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();
|
||||
|
@ -81,15 +81,15 @@ add_test(function test_do_nothing_when_resting() {
|
|||
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();
|
||||
|
||||
|
@ -103,7 +103,7 @@ add_test(function test_do_nothing_when_disabled() {
|
|||
sendDeviceMotionEvent(0, 9001, 9001);
|
||||
|
||||
ok(readLocations.length === 0,
|
||||
'LogShake should not read any logs');
|
||||
"LogShake should not read any logs");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -126,7 +126,7 @@ add_test(function test_do_nothing_when_screen_off() {
|
|||
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);
|
||||
|
@ -149,7 +149,7 @@ add_test(function test_do_log_capture_resilient_readLogFile() {
|
|||
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();
|
||||
|
@ -172,13 +172,13 @@ add_test(function test_do_log_capture_resilient_parseLog() {
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ tail =
|
|||
|
||||
support-files =
|
||||
data/test_logger_file
|
||||
data/test_properties
|
||||
|
||||
[test_bug793310.js]
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
<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 -->
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</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"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
<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 -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</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"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "587d98bf26625137015c17d5b937bf06bd055dd0",
|
||||
"revision": "67a3857cc29aaa2b2f890b4ed575065f6e5a7691",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -10,7 +10,6 @@ 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"
|
||||
|
|
|
@ -11,7 +11,6 @@ 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"
|
||||
|
|
|
@ -29,7 +29,6 @@ no_sccache=
|
|||
#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
|
||||
|
|
|
@ -27,7 +27,6 @@ no_sccache=
|
|||
|
||||
#B2G options
|
||||
ac_add_options --enable-application=b2g
|
||||
ac_add_options --disable-elf-hack
|
||||
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
|
||||
|
||||
GAIADIR=$topsrcdir/gaia
|
||||
|
|
|
@ -29,7 +29,6 @@ no_sccache=
|
|||
#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
|
||||
|
|
|
@ -27,7 +27,6 @@ no_sccache=
|
|||
|
||||
#B2G options
|
||||
ac_add_options --enable-application=b2g
|
||||
ac_add_options --disable-elf-hack
|
||||
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
|
||||
|
||||
GAIADIR=$topsrcdir/gaia
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</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"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<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"/>
|
||||
|
|
|
@ -83,9 +83,6 @@ 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
|
||||
|
|
|
@ -132,7 +132,6 @@
|
|||
@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
|
||||
|
|
|
@ -21,6 +21,7 @@ skip-if = os == "mac" # Intermittent failures, bug 898317
|
|||
[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]
|
||||
|
|
|
@ -36,4 +36,4 @@ skip-if = e10s # Bug ?????? - Test uses load event and checks event.target.
|
|||
[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
|
||||
|
|
|
@ -19,7 +19,7 @@ support-files =
|
|||
[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]
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -5,7 +5,6 @@ no_sccache=1
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -5,7 +5,6 @@ no_sccache=1
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ whitelist['nightly']['linux32'] += [
|
|||
'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'] += [
|
||||
|
@ -44,7 +43,6 @@ whitelist['nightly']['linux64'] += [
|
|||
'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'] += [
|
||||
|
|
|
@ -354,43 +354,43 @@ 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]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
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;
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
|
||||
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;
|
||||
|
@ -309,7 +308,6 @@ function performTest() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
|
||||
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;
|
||||
|
@ -33,7 +32,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,7 +115,6 @@ function verifySourceAndCaret(aUrl, aLine, aColumn, aSelection) {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -37,7 +36,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,7 +111,6 @@ function verifySourceAndCaret(aUrl, aLine, aColumn) {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -123,7 +122,6 @@ function testTokenSearch() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -31,7 +30,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -264,7 +263,6 @@ function clearSearch() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -34,7 +33,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -208,7 +207,6 @@ function testSearchTokenEmpty() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -30,7 +29,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,7 +95,6 @@ function performTest() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -30,7 +29,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -84,7 +83,6 @@ function secondSearch() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
|
||||
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;
|
||||
|
@ -33,7 +32,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -146,7 +145,6 @@ function testClickMatchToJump() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -32,7 +31,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -111,7 +110,6 @@ function testEscape() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
|
||||
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;
|
||||
|
@ -111,7 +110,6 @@ function pressKeyToHide(aKey) {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSearchBox = null;
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
|
||||
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;
|
||||
|
@ -226,7 +225,6 @@ function verifyContents(aArgs) {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
|
||||
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;
|
||||
|
@ -268,7 +267,6 @@ function verifyContents(aMatches) {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
|
||||
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;
|
||||
|
@ -92,7 +91,6 @@ function verifySourcesPane() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSources = null;
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
|
||||
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;
|
||||
|
@ -459,7 +458,6 @@ function writeInfo() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -28,7 +27,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -52,7 +51,6 @@ function hidePopup() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gSearchBox = null;
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
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;
|
||||
|
@ -34,7 +33,7 @@ function test() {
|
|||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
callInTab(gTab, "firstCall");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -77,7 +76,6 @@ function testFocusLost() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -130,9 +130,6 @@ 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
|
||||
|
|
|
@ -177,7 +177,6 @@
|
|||
@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
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
.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 {
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
|
||||
.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 {
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
}
|
||||
|
||||
.theme-light .ruleview-overridden {
|
||||
-moz-text-decoration-color: #667380; /* Content (Text) - Dark Grey */
|
||||
text-decoration-color: #667380; /* Content (Text) - Dark Grey */
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
|
|
13
configure.in
13
configure.in
|
@ -7161,6 +7161,7 @@ if test -n "$MOZ_REPLACE_MALLOC" -a -z "$MOZ_MEMORY"; then
|
|||
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
|
||||
|
@ -7383,17 +7384,7 @@ 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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -17,7 +17,6 @@ support-files =
|
|||
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/*
|
||||
|
@ -45,5 +44,3 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
|||
[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
|
||||
|
|
|
@ -4,14 +4,231 @@
|
|||
<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>
|
||||
|
|
|
@ -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>
|
|
@ -62,7 +62,6 @@ EventSource::EventSource(nsPIDOMWindow* aOwnerWindow) :
|
|||
mGoingToDispatchAllMessages(false),
|
||||
mWithCredentials(false),
|
||||
mWaitingForOnStopRequest(false),
|
||||
mInterrupted(false),
|
||||
mLastConvertionResult(NS_OK),
|
||||
mReadyState(CONNECTING),
|
||||
mScriptLine(0),
|
||||
|
@ -341,21 +340,14 @@ EventSource::OnStartRequest(nsIRequest *aRequest,
|
|||
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);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsresult status;
|
||||
aRequest->GetStatus(&status);
|
||||
rv = aRequest->GetStatus(&status);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
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;
|
||||
|
@ -363,7 +355,15 @@ EventSource::OnStartRequest(nsIRequest *aRequest,
|
|||
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;
|
||||
}
|
||||
|
@ -454,19 +454,27 @@ EventSource::OnStopRequest(nsIRequest *aRequest,
|
|||
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();
|
||||
|
||||
|
@ -477,7 +485,7 @@ EventSource::OnStopRequest(nsIRequest *aRequest,
|
|||
rv = NS_DispatchToMainThread(event);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return healthOfRequestResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -869,11 +877,6 @@ EventSource::ReestablishConnection()
|
|||
return;
|
||||
}
|
||||
|
||||
if (mReadyState != OPEN) {
|
||||
NS_WARNING("Unexpected mReadyState!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = ResetConnection();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to reset the connection!!!");
|
||||
|
@ -994,7 +997,7 @@ EventSource::ConsoleError()
|
|||
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));
|
||||
|
|
|
@ -221,7 +221,6 @@ protected:
|
|||
bool mGoingToDispatchAllMessages;
|
||||
bool mWithCredentials;
|
||||
bool mWaitingForOnStopRequest;
|
||||
bool mInterrupted;
|
||||
|
||||
// used while reading the input streams
|
||||
nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
|
||||
|
|
|
@ -14094,8 +14094,12 @@ 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 */
|
||||
|
|
|
@ -182,7 +182,7 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
|
|||
}
|
||||
nsresult status =
|
||||
reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK;
|
||||
return OnStopRequest(aRequest, status);
|
||||
return OnLoadComplete(aRequest, status);
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
||||
|
@ -205,8 +205,7 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest,
|
||||
nsresult aStatus)
|
||||
nsImageLoadingContent::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
|
||||
{
|
||||
uint32_t oldStatus;
|
||||
aRequest->GetImageStatus(&oldStatus);
|
||||
|
|
|
@ -209,7 +209,7 @@ protected:
|
|||
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);
|
||||
|
||||
|
|
|
@ -2411,14 +2411,6 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::GCProgress aProgress, const JS::GCDescrip
|
|||
(*sPrevGCSliceCallback)(aRt, aProgress, aDesc);
|
||||
}
|
||||
|
||||
void
|
||||
nsJSContext::ReportPendingException()
|
||||
{
|
||||
if (mIsInitialized) {
|
||||
nsJSUtils::ReportPendingException(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsJSContext::SetWindowProxy(JS::Handle<JSObject*> aWindowProxy)
|
||||
{
|
||||
|
|
|
@ -146,11 +146,6 @@ protected:
|
|||
|
||||
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();
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsHashKeys.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsDocument.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::dom::NodeInfo;
|
||||
|
@ -153,11 +154,6 @@ 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)
|
||||
}
|
||||
|
@ -167,6 +163,24 @@ 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)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,7 @@ private:
|
|||
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)
|
||||
|
||||
|
|
|
@ -353,13 +353,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
|||
|
||||
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;
|
||||
|
||||
|
@ -375,7 +375,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
|||
}
|
||||
gEventSourceObj3_h.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
}, parseInt(6000*stress_factor));
|
||||
}
|
||||
|
||||
// in order to test (4)
|
||||
|
|
|
@ -3474,7 +3474,6 @@ class CGClearCachedValueMethod(CGAbstractMethod):
|
|||
JSAutoCompartment ac(aCx, obj);
|
||||
if (!get_${name}(aCx, obj, aObject, args)) {
|
||||
js::SetReservedSlot(obj, ${slotIndex}, oldValue);
|
||||
nsJSUtils::ReportPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -4,910 +4,126 @@
|
|||
|
||||
"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");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function () {
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
return DOMApplicationRegistry;
|
||||
});
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserElementParentBuilder",
|
||||
"resource://gre/modules/BrowserElementParent.jsm",
|
||||
"BrowserElementParentBuilder");
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
//dump("BrowserElementParent.js - " + msg + "\n");
|
||||
}
|
||||
|
||||
function getIntPref(prefName, def) {
|
||||
try {
|
||||
return Services.prefs.getIntPref(prefName);
|
||||
}
|
||||
catch(err) {
|
||||
return def;
|
||||
}
|
||||
/**
|
||||
* 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 BrowserElementParentFactory() {
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function defineDOMRequestMethod(msgName) {
|
||||
return function() {
|
||||
return this._sendDOMRequest(msgName);
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
// 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;
|
||||
}
|
||||
|
||||
debug("_init");
|
||||
this._initialized = true;
|
||||
|
||||
// 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();
|
||||
|
||||
Services.obs.addObserver(this, 'remote-browser-pending', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'inprocess-browser-shown', /* ownsWeak = */ true);
|
||||
},
|
||||
|
||||
_sendAsyncMsg: function(msg, data) {
|
||||
_browserFramesPrefEnabled: function() {
|
||||
try {
|
||||
if (!data) {
|
||||
data = { };
|
||||
}
|
||||
|
||||
data.msg_name = msg;
|
||||
this._mm.sendAsyncMessage('browser-element-api:call', data);
|
||||
} catch (e) {
|
||||
return Services.prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
|
||||
}
|
||||
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();
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader) {
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
if (!frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsBrowserOrAppFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
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')
|
||||
};
|
||||
debug("In-process browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader,
|
||||
/* hasRemoteFrame = */ false,
|
||||
/* pending frame */ false);
|
||||
},
|
||||
|
||||
_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' });
|
||||
_observeRemoteBrowserFramePending: function(frameLoader) {
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
if (!frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerIsBrowserOrAppFrame) {
|
||||
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);
|
||||
debug("Remote browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader,
|
||||
/* hasRemoteFrame = */ true,
|
||||
/* pending frame */ true);
|
||||
},
|
||||
|
||||
/**
|
||||
* add profiler marker for each event fired.
|
||||
*/
|
||||
_fireProfiledEventFromMsg: function(data) {
|
||||
if (Services.profiler !== undefined) {
|
||||
Services.profiler.AddMarker(data.json.msg_name);
|
||||
}
|
||||
this._fireEventFromMsg(data);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// 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);
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
_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 });
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
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]);
|
||||
|
|
|
@ -0,0 +1,947 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
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.jsm - " + 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();
|
||||
}
|
||||
}
|
||||
|
||||
this.BrowserElementParentBuilder = {
|
||||
create: function create(frameLoader, hasRemoteFrame, isPendingFrame) {
|
||||
return new BrowserElementParent(frameLoader, hasRemoteFrame);
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
_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.)
|
||||
*/
|
||||
_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();
|
||||
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' });
|
||||
}
|
||||
|
||||
// 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);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// 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);
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
_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 });
|
||||
}
|
||||
|
||||
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: function(visible) {
|
||||
this._sendAsyncMsg('set-visible', {visible: visible});
|
||||
this._frameLoader.visible = visible;
|
||||
},
|
||||
|
||||
_setActive: function(active) {
|
||||
this._frameLoader.visible = active;
|
||||
},
|
||||
|
||||
_getActive: function() {
|
||||
return this._frameLoader.visible;
|
||||
},
|
||||
|
||||
_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: 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
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_goBack: function() {
|
||||
this._sendAsyncMsg('go-back');
|
||||
},
|
||||
|
||||
_goForward: function() {
|
||||
this._sendAsyncMsg('go-forward');
|
||||
},
|
||||
|
||||
_reload: function(hardReload) {
|
||||
this._sendAsyncMsg('reload', {hardReload: hardReload});
|
||||
},
|
||||
|
||||
_stop: function() {
|
||||
this._sendAsyncMsg('stop');
|
||||
},
|
||||
|
||||
/*
|
||||
* The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent".
|
||||
*/
|
||||
_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});
|
||||
},
|
||||
|
||||
_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) {
|
||||
_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);
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
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();
|
||||
} catch (e) {
|
||||
// If a listener throws we'll continue.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
if (self._nextPaintListeners.length == 0)
|
||||
self._sendAsyncMsg('deactivate-next-paint-listener');
|
||||
};
|
||||
if (!this._domRequestReady) {
|
||||
this._pendingAPICalls.push(run);
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
},
|
||||
|
||||
_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});
|
||||
},
|
||||
|
||||
/**
|
||||
* 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);
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch(topic) {
|
||||
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._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;
|
||||
};
|
||||
},
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -12,18 +12,13 @@ SOURCES += [
|
|||
'BrowserElementParent.cpp',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIBrowserElementAPI.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'browser-element'
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'BrowserElementParent.js',
|
||||
'BrowserElementParent.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'BrowserElementParent.jsm',
|
||||
'BrowserElementPromptService.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -4,47 +4,48 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGL1Context.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* 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"
|
||||
|
||||
|
@ -13,34 +13,23 @@ namespace mozilla {
|
|||
class WebGL1Context
|
||||
: public WebGLContext
|
||||
{
|
||||
// -----------------------------------------------------------------------------
|
||||
// PUBLIC
|
||||
public:
|
||||
static WebGL1Context* Create();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// CONSTRUCTOR & DESTRUCTOR
|
||||
|
||||
private:
|
||||
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_
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGL2Context.h"
|
||||
#include "WebGLSampler.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -12,67 +13,206 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
|
||||
#include "WebGLContextLossHandler.h"
|
||||
#include "WebGL1Context.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLVertexAttribData.h"
|
||||
#include "WebGLMemoryTracker.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
#include "WebGLMemoryTracker.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLQuery.h"
|
||||
#include "WebGLSampler.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
#include "WebGLVertexAttribData.h"
|
||||
|
||||
#include "GLBlitHelper.h"
|
||||
#include "AccessCheck.h"
|
||||
|
@ -226,7 +227,7 @@ WebGLContextOptions::WebGLContextOptions()
|
|||
}
|
||||
|
||||
WebGLContext::WebGLContext()
|
||||
: gl(nullptr)
|
||||
: WebGLContextUnchecked(nullptr)
|
||||
, mNeedsFakeNoAlpha(false)
|
||||
{
|
||||
mGeneration = 0;
|
||||
|
@ -371,6 +372,8 @@ WebGLContext::DestroyResourcesAndContext()
|
|||
mPrograms.getLast()->DeleteOnce();
|
||||
while (!mQueries.isEmpty())
|
||||
mQueries.getLast()->DeleteOnce();
|
||||
while (!mSamplers.isEmpty())
|
||||
mSamplers.getLast()->DeleteOnce();
|
||||
|
||||
mBlackOpaqueTexture2D = nullptr;
|
||||
mBlackOpaqueTextureCubeMap = nullptr;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "GLDefs.h"
|
||||
#include "WebGLActiveInfo.h"
|
||||
#include "WebGLContextUnchecked.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "WebGLTexture.h"
|
||||
|
@ -78,10 +79,12 @@ class WebGLQuery;
|
|||
class WebGLUniformLocation;
|
||||
class WebGLFramebuffer;
|
||||
class WebGLRenderbuffer;
|
||||
class WebGLSampler;
|
||||
class WebGLShaderPrecisionFormat;
|
||||
class WebGLTexture;
|
||||
class WebGLVertexArray;
|
||||
|
||||
|
||||
namespace dom {
|
||||
class ImageData;
|
||||
class Element;
|
||||
|
@ -127,10 +130,29 @@ struct WebGLContextOptions {
|
|||
// 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>
|
||||
|
@ -1005,8 +1027,6 @@ protected:
|
|||
return ((x + y - 1) / y) * y;
|
||||
}
|
||||
|
||||
nsRefPtr<gl::GLContext> gl;
|
||||
|
||||
CheckedUint32 mGeneration;
|
||||
|
||||
WebGLContextOptions mOptions;
|
||||
|
@ -1138,6 +1158,10 @@ protected:
|
|||
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,
|
||||
|
@ -1325,6 +1349,9 @@ protected:
|
|||
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
|
||||
|
@ -1440,6 +1467,7 @@ public:
|
|||
friend class WebGLProgram;
|
||||
friend class WebGLQuery;
|
||||
friend class WebGLBuffer;
|
||||
friend class WebGLSampler;
|
||||
friend class WebGLShader;
|
||||
friend class WebGLUniformLocation;
|
||||
friend class WebGLVertexArray;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -378,6 +378,118 @@ WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcN
|
|||
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.
|
||||
|
@ -1718,8 +1830,7 @@ WebGLContext::InitAndValidateGL()
|
|||
#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
|
||||
|
|
|
@ -373,7 +373,7 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, FBAttachment att
|
|||
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();
|
||||
|
|
|
@ -12,33 +12,36 @@
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* 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"
|
||||
|
@ -26,13 +26,15 @@ class WebGLSampler MOZ_FINAL
|
|||
|
||||
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)
|
||||
|
||||
|
@ -43,4 +45,4 @@ private:
|
|||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // !WEBGL2SAMPLER_H_
|
||||
#endif // !WEBGLSAMPLER_H_
|
||||
|
|
|
@ -64,6 +64,7 @@ UNIFIED_SOURCES += [
|
|||
'WebGLContextLossHandler.cpp',
|
||||
'WebGLContextReporter.cpp',
|
||||
'WebGLContextState.cpp',
|
||||
'WebGLContextUnchecked.cpp',
|
||||
'WebGLContextUtils.cpp',
|
||||
'WebGLContextValidate.cpp',
|
||||
'WebGLContextVertexArray.cpp',
|
||||
|
|
|
@ -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?
|
||||
|
||||
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 AreBothIn(a, b, set) {
|
||||
return (a in set) && (b in set);
|
||||
}
|
||||
|
||||
testContextRetrieval('c1', 'experimental-webgl', 'webgl');
|
||||
testContextRetrieval('c2', 'webgl', 'experimental-webgl');
|
||||
testContextRetrieval('c3', 'experimental-webgl', 'experimental-webgl');
|
||||
testContextRetrieval('c4', 'webgl', 'webgl');
|
||||
function IsAlias(typeA, typeB) {
|
||||
if (typeA == typeB)
|
||||
return true;
|
||||
|
||||
if (AreBothIn(typeA, typeB, WEBGL_TYPES))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
#include "WebGL1Context.h"
|
||||
#include "WebGL2Context.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
@ -648,71 +649,71 @@ HTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
|
|||
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")) {
|
||||
if (str.EqualsLiteral("experimental-webgl")) {
|
||||
*out_type = CanvasContextType::WebGL1;
|
||||
return true;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (WebGL2Context::IsSupported()) {
|
||||
if (str.EqualsLiteral("experimental-webgl2")) {
|
||||
*out_type = CanvasContextType::WebGL2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
nsRefPtr<CanvasRenderingContext2D> ctx =
|
||||
new CanvasRenderingContext2D();
|
||||
ret = new CanvasRenderingContext2D();
|
||||
break;
|
||||
|
||||
ctx->SetCanvasElement(this);
|
||||
ctx.forget(aContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (WebGL2Context::IsSupported() &&
|
||||
aContextId.EqualsLiteral("experimental-webgl2"))
|
||||
{
|
||||
case CanvasContextType::WebGL1:
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
|
||||
nsRefPtr<WebGL2Context> ctx = WebGL2Context::Create();
|
||||
|
||||
if (ctx == nullptr) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
ret = WebGL1Context::Create();
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
break;
|
||||
|
||||
ctx->SetCanvasElement(this);
|
||||
ctx.forget(aContext);
|
||||
return NS_OK;
|
||||
case CanvasContextType::WebGL2:
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
|
||||
|
||||
ret = WebGL2Context::Create();
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(ret);
|
||||
|
||||
NS_ConvertUTF16toUTF8 ctxId(aContextId);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id=");
|
||||
ctxString.Append(ctxId);
|
||||
|
||||
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;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
*aContext = nullptr;
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ctx->SetCanvasElement(this);
|
||||
ctx.forget(aContext);
|
||||
return NS_OK;
|
||||
ret->SetCanvasElement(canvas);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -720,65 +721,49 @@ 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;
|
||||
|
@ -798,22 +783,28 @@ HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
|
|||
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);
|
||||
mCurrentContextType = contextType;
|
||||
|
||||
rv = UpdateContext(nullptr, JS::NullHandleValue);
|
||||
nsresult rv = UpdateContext(nullptr, JS::NullHandleValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
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;
|
||||
} else {
|
||||
// We already have a context of some type.
|
||||
if (contextType != mCurrentContextType)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_ADDREF (*aContext = mCurrentContext);
|
||||
|
@ -831,21 +822,18 @@ HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewConte
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define mozilla_dom_HTMLCanvasElement_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypedEnum.h"
|
||||
#include "nsIDOMHTMLCanvasElement.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
@ -35,6 +36,12 @@ 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
|
||||
{
|
||||
|
@ -229,11 +236,9 @@ protected:
|
|||
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;
|
||||
|
|
|
@ -459,20 +459,14 @@ ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aDa
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -481,14 +475,14 @@ ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aDa
|
|||
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;
|
||||
|
@ -496,23 +490,7 @@ ImageDocument::AddDecodedClass()
|
|||
|
||||
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
|
||||
|
@ -535,7 +513,7 @@ ImageDocument::SetModeClass(eModeClasses mode)
|
|||
}
|
||||
|
||||
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.
|
||||
|
@ -551,8 +529,7 @@ ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage)
|
|||
}
|
||||
|
||||
nsresult
|
||||
ImageDocument::OnStopRequest(imgIRequest *aRequest,
|
||||
nsresult aStatus)
|
||||
ImageDocument::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
|
||||
{
|
||||
UpdateTitleAndCharset();
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче