Merge latest green birch changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-07-25 16:32:43 +01:00
Родитель a9df95ea6f cde517b135
Коммит e1444d4588
298 изменённых файлов: 3492 добавлений и 5524 удалений

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

@ -932,13 +932,19 @@ HyperTextAccessible::GetTextBeforeOffset(int32_t aOffset,
*aEndOffset = FindLineBoundary(offset, eThisLineBegin);
return GetText(*aStartOffset, *aEndOffset, aText);
case BOUNDARY_LINE_END:
case BOUNDARY_LINE_END: {
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
offset = AdjustCaretOffset(offset);
*aEndOffset = FindLineBoundary(offset, ePrevLineEnd);
*aStartOffset = FindLineBoundary(*aEndOffset, ePrevLineEnd);
int32_t tmpOffset = *aEndOffset;
// Adjust offset if line is wrapped.
if (*aEndOffset != 0 && !IsLineEndCharAt(*aEndOffset))
tmpOffset--;
*aStartOffset = FindLineBoundary(tmpOffset, ePrevLineEnd);
return GetText(*aStartOffset, *aEndOffset, aText);
}
default:
return NS_ERROR_INVALID_ARG;
@ -2151,13 +2157,9 @@ HyperTextAccessible::GetCharAt(int32_t aOffset, EGetTextType aShift,
aChar.Truncate();
int32_t offset = ConvertMagicOffset(aOffset) + static_cast<int32_t>(aShift);
int32_t childIdx = GetChildIndexAtOffset(offset);
if (childIdx == -1)
if (!CharAt(offset, aChar))
return false;
Accessible* child = GetChildAt(childIdx);
child->AppendTextTo(aChar, offset - GetChildOffset(childIdx), 1);
if (aStartOffset)
*aStartOffset = offset;
if (aEndOffset)

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

@ -164,6 +164,36 @@ public:
return GetChildOffset(ChildCount());
}
/**
* Get a character at the given offset (don't support magic offsets).
*/
bool CharAt(int32_t aOffset, nsAString& aChar)
{
int32_t childIdx = GetChildIndexAtOffset(aOffset);
if (childIdx == -1)
return false;
Accessible* child = GetChildAt(childIdx);
child->AppendTextTo(aChar, aOffset - GetChildOffset(childIdx), 1);
return true;
}
/**
* Return true if char at the given offset equals to given char.
*/
bool IsCharAt(int32_t aOffset, char aChar)
{
nsAutoString charAtOffset;
CharAt(aOffset, charAtOffset);
return charAtOffset.CharAt(0) == aChar;
}
/**
* Return true if terminal char is at the given offset.
*/
bool IsLineEndCharAt(int32_t aOffset)
{ return IsCharAt(aOffset, '\n'); }
/**
* Get a character before/at/after the given offset.
*
@ -288,12 +318,8 @@ protected:
*/
bool IsEmptyLastLineOffset(int32_t aOffset)
{
if (aOffset != static_cast<int32_t>(CharacterCount()))
return false;
nsAutoString lastChar;
GetText(aOffset -1, -1, lastChar);
return lastChar.EqualsLiteral("\n");
return aOffset == static_cast<int32_t>(CharacterCount()) &&
IsLineEndCharAt(aOffset - 1);
}
/**

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

@ -56,7 +56,7 @@
[ "textarea" ]);
testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10,
"textarea", kTodo, kTodo, kOk);
[ "textarea" ]);
}
this.getID = function moveToLastLineEnd_getID()
@ -87,7 +87,7 @@
[ "textarea" ]);
testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10,
"textarea", kTodo, kTodo, kOk);
[ "textarea" ]);
}
this.getID = function moveToLastLineStart_getID()
@ -181,7 +181,7 @@
[ "textarea" ]);
testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "", 0, 0,
"textarea", kOk, kOk, kOk);
[ "textarea" ]);
}
this.getID = function moveToFirstLineStart_getID()

2
addon-sdk/source/app-extension/bootstrap.js поставляемый
Просмотреть файл

@ -220,6 +220,8 @@ function startup(data, reasonCode) {
// options used by system module.
// File to write 'OK' or 'FAIL' (exit code emulation).
resultFile: options.resultFile,
// File to write stdout.
logFile: options.logFile,
// Arguments passed as --static-args
staticArgs: options.staticArgs,

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

@ -17,8 +17,8 @@
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>21.0</em:minVersion>
<em:maxVersion>25.0a1</em:maxVersion>
<em:minVersion>19.0</em:minVersion>
<em:maxVersion>22.0a1</em:maxVersion>
</Description>
</em:targetApplication>

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

@ -640,14 +640,15 @@ and this usually involves using HTTPS for the links.
So if we run the following command:
<pre>
cfx xpi --update-link https://example.com/addon/latest/pluginName.xpi --update-url https://example.com/addon/update_rdf/pluginName.update.rdf
cfx xpi --update-link https://example.com/addon/latest
--update-url https://example.com/addon/update_rdf
</pre>
`cfx` will create two files:
* an XPI file which embeds
`https://example.com/addon/update_rdf/pluginName.update.rdf` as the value of `updateURL`
* an RDF file which embeds `https://example.com/addon/latest/pluginName.xpi` as the value of
`https://example.com/addon/update_rdf` as the value of `updateURL`
* an RDF file which embeds `https://example.com/addon/latest` as the value of
`updateLink`.
### Supported Options ###

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

@ -13,13 +13,6 @@ Note that the `self` module is completely different from the global `self`
object accessible to content scripts, which is used by a content script to
[communicate with the add-on code](dev-guide/guides/content-scripts/using-port.html).
<api name="uri">
@property {string}
This property represents an add-on associated unique URI string.
This URI can be used for APIs which require a valid URI string, such as the
[passwords](modules/sdk/passwords.html) module.
</api>
<api name="id">
@property {string}
This property is a printable string that is unique for each add-on. It comes

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

@ -1,90 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
The `test/utils` module provides additional helper methods to be used in
the CommonJS Unit Testing test suite.
## Before and After
Helper functions `before()` and `after()` are available for running a function
before or after each test in a suite. They're useful when you need to
guarantee a particular state before running a test, and to clean up
after your test.
let { before, after } = require('sdk/test/utils');
let { search } = require('sdk/places/bookmarks');
exports.testCountBookmarks = function (assert, done) {
search().on('end', function (results) {
assert.equal(results, 0, 'should be no bookmarks');
done();
});
};
before(exports, function (name, assert) {
removeAllBookmarks();
});
require('sdk/test').run(exports);
Both `before` and `after` may be asynchronous. To make them asynchronous,
pass a third argument `done`, which is a function to call when you have
finished:
let { before, after } = require('sdk/test/utils');
let { search } = require('sdk/places/bookmarks');
exports.testCountBookmarks = function (assert, done) {
search().on('end', function (results) {
assert.equal(results, 0, 'should be no bookmarks');
done();
});
};
before(exports, function (name, assert, done) {
removeAllBookmarksAsync(function () {
done();
});
});
require('sdk/test').run(exports);
<api name="before">
@function
Runs `beforeFn` before each test in the file. May be asynchronous
if `beforeFn` accepts a third argument, which is a callback.
@param exports {Object}
A test file's `exports` object
@param beforeFn {Function}
The function to be called before each test. It has two arguments,
or three if it is asynchronous:
* the first argument is the test's name as a `String`.
* the second argument is the `assert` object for the test.
* the third, optional, argument is a callback. If the callback is
defined, then the `beforeFn` is considered asynchronous, and the
callback must be invoked before the test runs.
</api>
<api name="after">
@function
Runs `afterFn` after each test in the file. May be asynchronous
if `afterFn` accepts a third argument, which is a callback.
@param exports {Object}
A test file's `exports` object
@param afterFn {Function}
The function to be called after each test. It has two arguments,
or three if it is asynchronous:
* the first argument is the test's name as a `String`.
* the second argument is the `assert` object for the test.
* the third, optional, argument is a callback. If the callback is
defined, then the `afterFn` is considered asynchronous, and the
callback must be invoked before the next test runs.
</api>

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

@ -2,7 +2,7 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
The `util/array` module provides simple helper functions for working with
The `util/array` module provides simple helper functions for working with
arrays.
<api name="has">
@ -29,7 +29,7 @@ A simplified version of `array.indexOf(element) >= 0`.
<api name="hasAny">
@function
Returns `true` if the given [`Array`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array) contains any of the elements in the
Returns `true` if the given [`Array`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array) contains any of the elements in the
`elements` array, or `false` otherwise.
let { hasAny } = require('sdk/util/array');
@ -84,7 +84,7 @@ does not alter the array and returns `false`.
let a = ['alice', 'bob', 'carol'];
remove(a, 'dave'); // false
remove(a, 'bob'); // true
remove(a, 'bob'); // true
remove(a, 'bob'); // false
console.log(a); // ['alice', 'carol']
@ -154,24 +154,3 @@ Iterates over an [iterator](https://developer.mozilla.org/en-US/docs/JavaScript/
The iterator's results in an array.
</api>
<api name="find">
@function
Iterates over given `array` and applies given `predicate` function until
`predicate(element)` is `true`. If such element is found it's retured back
otherwise third optional `fallback` argument is returned back. If fallback
is not provided returns `undefined`.
let { find } = require('sdk/util/array');
let isOdd = (x) => x % 2;
find([2, 4, 5, 7, 8, 9], isOdd); // => 5
find([2, 4, 6, 8], isOdd); // => undefiend
find([2, 4, 6, 8], isOdd, null); // => null
fromIterator(i) // ['otoro', 'unagi', 'keon']
@param iterator {iterator}
The [`Iterator`](https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Iterators_and_Generators#Iterators) object over which to iterate and place results into an array.
@returns {array}
The iterator's results in an array.
</api>

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

@ -8,32 +8,34 @@ module.metadata = {
"stability": "unstable"
};
const { Cc, Ci, Cu, Cr } = require("chrome");
const { Cc, Ci } = require("chrome");
const self = require("../self");
const traceback = require("./traceback")
const prefs = require("../preferences/service");
const { merge } = require("../util/object");
const { ConsoleAPI } = Cu.import("resource://gre/modules/devtools/Console.jsm");
const { partial } = require("../lang/functional");
const LEVELS = {
"all": Number.MIN_VALUE,
"debug": 20000,
"info": 30000,
"warn": 40000,
"error": 50000,
"off": Number.MAX_VALUE,
};
const DEFAULT_LOG_LEVEL = "error";
const ADDON_LOG_LEVEL_PREF = "extensions." + self.id + ".sdk.console.logLevel";
const SDK_LOG_LEVEL_PREF = "extensions.sdk.console.logLevel";
let logLevel = DEFAULT_LOG_LEVEL;
let logLevel;
function setLogLevel() {
logLevel = prefs.get(ADDON_LOG_LEVEL_PREF,
prefs.get(SDK_LOG_LEVEL_PREF,
DEFAULT_LOG_LEVEL));
logLevel = prefs.get(ADDON_LOG_LEVEL_PREF, prefs.get(SDK_LOG_LEVEL_PREF,
DEFAULT_LOG_LEVEL));
}
setLogLevel();
let logLevelObserver = {
QueryInterface: function(iid) {
if (!iid.equals(Ci.nsIObserver) &&
!iid.equals(Ci.nsISupportsWeakReference) &&
!iid.equals(Ci.nsISupports))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
observe: function(subject, topic, data) {
setLogLevel();
}
@ -41,23 +43,79 @@ let logLevelObserver = {
let branch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService).
getBranch(null);
branch.addObserver(ADDON_LOG_LEVEL_PREF, logLevelObserver, true);
branch.addObserver(SDK_LOG_LEVEL_PREF, logLevelObserver, true);
branch.addObserver(ADDON_LOG_LEVEL_PREF, logLevelObserver, false);
branch.addObserver(SDK_LOG_LEVEL_PREF, logLevelObserver, false);
function stringify(arg) {
try {
return String(arg);
}
catch(ex) {
return "<toString() error>";
}
}
function stringifyArgs(args) {
return Array.map(args, stringify).join(" ");
}
function message(print, level) {
if (LEVELS[level] < LEVELS[logLevel])
return;
let args = Array.slice(arguments, 2);
print(level + ": " + self.name + ": " + stringifyArgs(args) + "\n", level);
}
function errorMessage(print, e) {
// Some platform exception doesn't have name nor message but
// can be stringified to a meaningfull message
var fullString = ("An exception occurred.\n" +
(e.name ? e.name + ": " : "") +
(e.message ? e.message : e.toString()) + "\n" +
(e.fileName ? traceback.sourceURI(e.fileName) + " " +
e.lineNumber + "\n"
: "") +
traceback.format(e));
message(print, "error", fullString);
}
function traceMessage(print) {
var stack = traceback.get();
stack.splice(-1, 1);
message(print, "info", traceback.format(stack));
}
function PlainTextConsole(print) {
if (!print)
print = dump;
let consoleOptions = {
prefix: self.name + ": ",
maxLogLevel: logLevel,
dump: print
};
let console = new ConsoleAPI(consoleOptions);
if (print === dump) {
// If we're just using dump(), auto-enable preferences so
// that the developer actually sees the console output.
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
prefs.setBoolPref("browser.dom.window.dump.enabled", true);
}
// As we freeze the console object, we can't modify this property afterward
Object.defineProperty(console, "maxLogLevel", {
get: function() {
return logLevel;
}
merge(this, {
log: partial(message, print, "info"),
info: partial(message, print, "info"),
warn: partial(message, print, "warn"),
error: partial(message, print, "error"),
debug: partial(message, print, "debug"),
exception: partial(errorMessage, print),
trace: partial(traceMessage, print),
dir: function dir() {},
group: function group() {},
groupCollapsed: function groupCollapsed() {},
groupEnd: function groupEnd() {},
time: function time() {},
timeEnd: function timeEnd() {}
});
// We defined the `__exposedProps__` in our console chrome object.
@ -68,12 +126,11 @@ function PlainTextConsole(print) {
// Meanwhile we're investigating with the platform team if `__exposedProps__`
// are needed, or are just a left-over.
console.__exposedProps__ = Object.keys(ConsoleAPI.prototype).reduce(function(exposed, prop) {
this.__exposedProps__ = Object.keys(this).reduce(function(exposed, prop) {
exposed[prop] = "r";
return exposed;
}, {});
Object.freeze(console);
return console;
Object.freeze(this);
};
exports.PlainTextConsole = PlainTextConsole;

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

@ -9,8 +9,7 @@ module.metadata = {
"stability": "deprecated"
};
const { Cu } = require("chrome");
const memory = require("./memory");
const memory = require('./memory');
var timer = require("../timers");
var cfxArgs = require("@test/options");
@ -444,7 +443,7 @@ TestRunner.prototype = {
},
startMany: function startMany(options) {
let runNextTest = (self) => Cu.schedulePreciseGC(_ => {
function runNextTest(self) {
var test = options.tests.shift();
if (options.stopOnError && self.test && self.test.failed) {
self.console.error("aborted: test failed and --stop-on-error was specified");
@ -454,8 +453,7 @@ TestRunner.prototype = {
} else {
options.onDone(self);
}
});
}
runNextTest(this);
},

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

@ -9,252 +9,74 @@ module.metadata = {
};
const { Cu } = require("chrome");
const { TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
const { Cc, Ci, CC } = require("chrome");
const { Class } = require("../core/heritage");
exports.TextEncoder = TextEncoder;
exports.TextDecoder = TextDecoder;
const Transcoder = CC("@mozilla.org/intl/scriptableunicodeconverter",
"nsIScriptableUnicodeConverter");
var Buffer = Class({
initialize: function initialize(subject, encoding) {
subject = subject ? subject.valueOf() : 0;
let length = typeof subject === "number" ? subject : 0;
this.encoding = encoding || "utf-8";
this.valueOf(Array.isArray(subject) ? subject : new Array(length));
function Buffer(subject, encoding) {
var type = typeof(subject);
switch (type) {
case "number":
// Create typed array of the given size if number.
return Uint8Array(subject > 0 ? Math.floor(subject) : 0);
case "string":
// If string encode it and use buffer for the returned Uint8Array
// to create a local patched version that acts like node buffer.
encoding = encoding || "utf8";
return Uint8Array(TextEncoder(encoding).encode(subject).buffer);
case "object":
// If array or alike just make a copy with a local patched prototype.
return Uint8Array(subject);
default:
throw new TypeError("must start with number, buffer, array or string");
}
}
exports.Buffer = Buffer;
// Tests if `value` is a Buffer.
Buffer.isBuffer = value => value instanceof Buffer
// Returns true if the encoding is a valid encoding argument & false otherwise
Buffer.isEncoding = encoding => !!ENCODINGS[String(encoding).toLowerCase()]
// Gives the actual byte length of a string. encoding defaults to 'utf8'.
// This is not the same as String.prototype.length since that returns the
// number of characters in a string.
Buffer.byteLength = (value, encoding = "utf8") =>
TextEncoder(encoding).encode(value).byteLength
// Direct copy of the nodejs's buffer implementation:
// https://github.com/joyent/node/blob/b255f4c10a80343f9ce1cee56d0288361429e214/lib/buffer.js#L146-L177
Buffer.concat = function(list, length) {
if (!Array.isArray(list))
throw new TypeError('Usage: Buffer.concat(list[, length])');
if (typeof length === 'undefined') {
length = 0;
for (var i = 0; i < list.length; i++)
length += list[i].length;
} else {
length = ~~length;
if (typeof subject === "string") this.write(subject);
},
get length() {
return this.valueOf().length;
},
get: function get(index) {
return this.valueOf()[index];
},
set: function set(index, value) {
return this.valueOf()[index] = value;
},
valueOf: function valueOf(value) {
Object.defineProperty(this, "valueOf", {
value: Array.prototype.valueOf.bind(value),
configurable: false,
writable: false,
enumerable: false
});
},
toString: function toString(encoding, start, end) {
let bytes = this.valueOf().slice(start || 0, end || this.length);
let transcoder = Transcoder();
transcoder.charset = String(encoding || this.encoding).toUpperCase();
return transcoder.convertFromByteArray(bytes, this.length);
},
toJSON: function toJSON() {
return this.toString()
},
write: function write(string, offset, encoding) {
offset = Math.max(offset || 0, 0);
let value = this.valueOf();
let transcoder = Transcoder();
transcoder.charset = String(encoding || this.encoding).toUpperCase();
let bytes = transcoder.convertToByteArray(string, {});
value.splice.apply(value, [
offset,
Math.min(value.length - offset, bytes.length, bytes)
].concat(bytes));
return bytes;
},
slice: function slice(start, end) {
return new Buffer(this.valueOf().slice(start, end));
},
copy: function copy(target, offset, start, end) {
offset = Math.max(offset || 0, 0);
target = target.valueOf();
let bytes = this.valueOf();
bytes.slice(Math.max(start || 0, 0), end);
target.splice.apply(target, [
offset,
Math.min(target.length - offset, bytes.length),
].concat(bytes));
}
if (length < 0)
length = 0;
if (list.length === 0)
return new Buffer(0);
else if (list.length === 1)
return list[0];
if (length < 0)
throw new RangeError('length is not a positive number');
var buffer = new Buffer(length);
var pos = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
buf.copy(buffer, pos);
pos += buf.length;
}
return buffer;
});
Buffer.isBuffer = function isBuffer(buffer) {
return buffer instanceof Buffer
};
// Node buffer is very much like Uint8Array although it has bunch of methods
// that typically can be used in combination with `DataView` while preserving
// access by index. Since in SDK echo module has it's own set of bult-ins it
// ok to patch ours to make it nodejs Buffer compatible.
Buffer.prototype = Uint8Array.prototype;
Object.defineProperties(Buffer.prototype, {
view: {
get: function() this._view || (this._view = DataView(this.buffer))
},
toString: {
value: function(encoding, start, end) {
encoding = !!encoding ? (encoding + '').toLowerCase() : "utf8";
start = Math.max(0, ~~start);
end = Math.min(this.length, end === void(0) ? this.length : ~~end);
return TextDecoder(encoding).decode(this.subarray(start, end));
}
},
toJSON: {
value: function() ({ type: "Buffer", data: Array.slice(this, 0) })
},
get: {
value: function(offset) this[offset]
},
set: {
value: function(offset, value) this[offset] = value
},
copy: {
value: function(target, offset, start, end)
Uint8Array.set(target, this.subarray(start, end), offset)
},
slice: {
value: Buffer.prototype.subarray
},
write: {
value: function(string, offset, length, encoding = "utf8") {
if (typeof(offset) === "string")
([offset, length, encoding]) = [0, null, offset];
else if (typeof(length) === "string")
([length, encoding]) = [null, length];
offset = ~~offset;
length = length || this.length - offset;
let buffer = TextEncoder(encoding).encode(string);
let result = Math.min(buffer.length, length);
if (buffer.length !== length)
buffer = buffer.subarray(0, length);
Uint8Array.set(this, buffer, offset);
return result;
}
},
fill: {
value: function fill(value, start, end) {
value = value || 0;
start = start || 0;
end = end || this.length;
if (typeof(value) === "string")
value = value.charCodeAt(0);
if (typeof(value) !== "number" || isNaN(value))
throw TypeError("value is not a number");
if (end < start)
throw new RangeError("end < start");
// Fill 0 bytes; we're done
if (end === start)
return 0;
if (this.length == 0)
return 0;
if (start < 0 || start >= this.length)
throw RangeError("start out of bounds");
if (end < 0 || end > this.length)
throw RangeError("end out of bounds");
let index = start;
while (index < end) this[index++] = value;
}
}
});
// Define nodejs Buffer's getter and setter functions that just proxy
// to internal DataView's equivalent methods.
[["readUInt16LE", "getUint16", true],
["readUInt16BE", "getUint16", false],
["readInt16LE", "getInt16", true],
["readInt16BE", "getInt16", false],
["readUInt32LE", "getInt32", true],
["readUInt32BE", "getInt32", false],
["readInt32LE", "getInt32", true],
["readInt32BE", "getInt32", false],
["readFloatLE", "getFloat32", true],
["readFloatBE", "getFloat32", false],
["readDoubleLE", "getFloat64", true],
["readDoubleBE", "getFloat64", false],
["readUInt8", "getUint8"],
["readInt8", "getInt8"]].forEach(([alias, name, littleEndian]) => {
Object.defineProperty(Buffer.prototype, alias, {
value: function(offset) this.view[name](offset, littleEndian)
});
});
[["writeUInt16LE", "setUint16", true],
["writeUInt16BE", "setUint16", false],
["writeInt16LE", "setInt16", true],
["writeInt16BE", "setInt16", false],
["writeUInt32LE", "setUint32", true],
["writeUInt32BE", "setUint32", false],
["writeInt32LE", "setInt32", true],
["writeInt32BE", "setInt32", false],
["writeFloatLE", "setFloat32", true],
["writeFloatBE", "setFloat32", false],
["writeDoubleLE", "setFloat64", true],
["writeDoubleBE", "setFloat64", false],
["writeUInt8", "setUint8"],
["writeInt8", "setInt8"]].forEach(([alias, name, littleEndian]) => {
Object.defineProperty(Buffer.prototype, alias, {
value: function(value, offset) this.view[name](offset, value, littleEndian)
});
});
// List of supported encodings taken from:
// http://mxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
const ENCODINGS = { "unicode-1-1-utf-8": 1, "utf-8": 1, "utf8": 1,
"866": 1, "cp866": 1, "csibm866": 1, "ibm866": 1, "csisolatin2": 1,
"iso-8859-2": 1, "iso-ir-101": 1, "iso8859-2": 1, "iso88592": 1,
"iso_8859-2": 1, "iso_8859-2:1987": 1, "l2": 1, "latin2": 1, "csisolatin3": 1,
"iso-8859-3": 1, "iso-ir-109": 1, "iso8859-3": 1, "iso88593": 1,
"iso_8859-3": 1, "iso_8859-3:1988": 1, "l3": 1, "latin3": 1, "csisolatin4": 1,
"iso-8859-4": 1, "iso-ir-110": 1, "iso8859-4": 1, "iso88594": 1,
"iso_8859-4": 1, "iso_8859-4:1988": 1, "l4": 1, "latin4": 1,
"csisolatincyrillic": 1, "cyrillic": 1, "iso-8859-5": 1, "iso-ir-144": 1,
"iso8859-5": 1, "iso88595": 1, "iso_8859-5": 1, "iso_8859-5:1988": 1,
"arabic": 1, "asmo-708": 1, "csiso88596e": 1, "csiso88596i": 1,
"csisolatinarabic": 1, "ecma-114": 1, "iso-8859-6": 1, "iso-8859-6-e": 1,
"iso-8859-6-i": 1, "iso-ir-127": 1, "iso8859-6": 1, "iso88596": 1,
"iso_8859-6": 1, "iso_8859-6:1987": 1, "csisolatingreek": 1, "ecma-118": 1,
"elot_928": 1, "greek": 1, "greek8": 1, "iso-8859-7": 1, "iso-ir-126": 1,
"iso8859-7": 1, "iso88597": 1, "iso_8859-7": 1, "iso_8859-7:1987": 1,
"sun_eu_greek": 1, "csiso88598e": 1, "csisolatinhebrew": 1, "hebrew": 1,
"iso-8859-8": 1, "iso-8859-8-e": 1, "iso-ir-138": 1, "iso8859-8": 1,
"iso88598": 1, "iso_8859-8": 1, "iso_8859-8:1988": 1, "visual": 1,
"csiso88598i": 1, "iso-8859-8-i": 1, "logical": 1, "csisolatin6": 1,
"iso-8859-10": 1, "iso-ir-157": 1, "iso8859-10": 1, "iso885910": 1,
"l6": 1, "latin6": 1, "iso-8859-13": 1, "iso8859-13": 1, "iso885913": 1,
"iso-8859-14": 1, "iso8859-14": 1, "iso885914": 1, "csisolatin9": 1,
"iso-8859-15": 1, "iso8859-15": 1, "iso885915": 1, "iso_8859-15": 1,
"l9": 1, "iso-8859-16": 1, "cskoi8r": 1, "koi": 1, "koi8": 1, "koi8-r": 1,
"koi8_r": 1, "koi8-u": 1, "csmacintosh": 1, "mac": 1, "macintosh": 1,
"x-mac-roman": 1, "dos-874": 1, "iso-8859-11": 1, "iso8859-11": 1,
"iso885911": 1, "tis-620": 1, "windows-874": 1, "cp1250": 1,
"windows-1250": 1, "x-cp1250": 1, "cp1251": 1, "windows-1251": 1,
"x-cp1251": 1, "ansi_x3.4-1968": 1, "ascii": 1, "cp1252": 1, "cp819": 1,
"csisolatin1": 1, "ibm819": 1, "iso-8859-1": 1, "iso-ir-100": 1,
"iso8859-1": 1, "iso88591": 1, "iso_8859-1": 1, "iso_8859-1:1987": 1,
"l1": 1, "latin1": 1, "us-ascii": 1, "windows-1252": 1, "x-cp1252": 1,
"cp1253": 1, "windows-1253": 1, "x-cp1253": 1, "cp1254": 1, "csisolatin5": 1,
"iso-8859-9": 1, "iso-ir-148": 1, "iso8859-9": 1, "iso88599": 1,
"iso_8859-9": 1, "iso_8859-9:1989": 1, "l5": 1, "latin5": 1,
"windows-1254": 1, "x-cp1254": 1, "cp1255": 1, "windows-1255": 1,
"x-cp1255": 1, "cp1256": 1, "windows-1256": 1, "x-cp1256": 1, "cp1257": 1,
"windows-1257": 1, "x-cp1257": 1, "cp1258": 1, "windows-1258": 1,
"x-cp1258": 1, "x-mac-cyrillic": 1, "x-mac-ukrainian": 1, "chinese": 1,
"csgb2312": 1, "csiso58gb231280": 1, "gb2312": 1, "gb_2312": 1,
"gb_2312-80": 1, "gbk": 1, "iso-ir-58": 1, "x-gbk": 1, "gb18030": 1,
"hz-gb-2312": 1, "big5": 1, "big5-hkscs": 1, "cn-big5": 1, "csbig5": 1,
"x-x-big5": 1, "cseucpkdfmtjapanese": 1, "euc-jp": 1, "x-euc-jp": 1,
"csiso2022jp": 1, "iso-2022-jp": 1, "csshiftjis": 1, "ms_kanji": 1,
"shift-jis": 1, "shift_jis": 1, "sjis": 1, "windows-31j": 1, "x-sjis": 1,
"cseuckr": 1, "csksc56011987": 1, "euc-kr": 1, "iso-ir-149": 1, "korean": 1,
"ks_c_5601-1987": 1, "ks_c_5601-1989": 1, "ksc5601": 1, "ksc_5601": 1,
"windows-949": 1, "csiso2022kr": 1, "iso-2022-kr": 1, "utf-16": 1,
"utf-16le": 1, "utf-16be": 1, "x-user-defined": 1 };
exports.Buffer = Buffer;

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

@ -12,12 +12,10 @@ const { Cc, Ci, CC } = require("chrome");
const { setTimeout } = require("../timers");
const { Stream, InputStream, OutputStream } = require("./stream");
const { emit, on } = require("../event/core");
const { Buffer } = require("./buffer");
const { ns } = require("../core/namespace");
const { Class } = require("../core/heritage");
const nsILocalFile = CC("@mozilla.org/file/local;1", "nsILocalFile",
"initWithPath");
const FileOutputStream = CC("@mozilla.org/network/file-output-stream;1",
@ -35,8 +33,6 @@ const { createOutputTransport, createInputTransport } =
Cc["@mozilla.org/network/stream-transport-service;1"].
getService(Ci.nsIStreamTransportService);
const { OPEN_UNBUFFERED } = Ci.nsITransport;
const { REOPEN_ON_REWIND, DEFER_OPEN } = Ci.nsIFileInputStream;
const { DIRECTORY_TYPE, NORMAL_FILE_TYPE } = Ci.nsIFile;
@ -161,16 +157,14 @@ const ReadStream = Class({
// Open an input stream on a transport. We don"t pass flags to guarantee
// non-blocking stream semantics. Also we use defaults for segment size &
// count.
let asyncInputStream = transport.openInputStream(null, 0, 0);
let binaryInputStream = BinaryInputStream(asyncInputStream);
nsIBinaryInputStream(fd, binaryInputStream);
let pump = StreamPump(asyncInputStream, position, length, 0, 0, false);
InputStream.prototype.initialize.call(this, {
asyncInputStream: transport.openInputStream(null, 0, 0)
input: binaryInputStream, pump: pump
});
// Close file descriptor on end and destroy the stream.
on(this, "end", _ => {
this.destroy();
emit(this, "close");
});
this.read();
},
destroy: function() {
@ -217,20 +211,21 @@ const WriteStream = Class({
// Open an output stream on a transport. We don"t pass flags to guarantee
// non-blocking stream semantics. Also we use defaults for segment size &
// count.
OutputStream.prototype.initialize.call(this, {
asyncOutputStream: transport.openOutputStream(OPEN_UNBUFFERED, 0, 0),
output: output
});
let asyncOutputStream = transport.openOutputStream(null, 0, 0);
// Finally we create a non-blocking binary output stream. This will allows
// us to write buffers as byte arrays without any further transcoding.
let binaryOutputStream = BinaryOutputStream(asyncOutputStream);
nsIBinaryOutputStream(fd, binaryOutputStream);
// For write streams "finish" basically means close.
on(this, "finish", _ => {
this.destroy();
emit(this, "close");
// Storing output stream so that it can beaccessed later.
OutputStream.prototype.initialize.call(this, {
output: binaryOutputStream,
asyncOutputStream: asyncOutputStream
});
},
destroy: function() {
OutputStream.prototype.destroy.call(this);
closeSync(this.fd);
OutputStream.prototype.destroy.call(this);
}
});
exports.WriteStream = WriteStream;
@ -370,7 +365,7 @@ function ftruncate(fd, length, callback) {
}
exports.ftruncate = ftruncate;
function ftruncateSync(fd, length = 0) {
function ftruncateSync(fd, length) {
writeSync(fd, new Buffer(length), 0, length, 0);
}
exports.ftruncateSync = ftruncateSync;
@ -639,8 +634,6 @@ function openSync(path, flags, mode) {
let [ fd, flags, mode, file ] =
[ { path: path }, Flags(flags), Mode(mode), nsILocalFile(path) ];
nsIFile(fd, file);
// If trying to open file for just read that does not exists
// need to throw exception as node does.
if (!file.exists() && !isWritable(flags))
@ -682,9 +675,7 @@ function writeSync(fd, buffer, offset, length, position) {
}
let writeStream = new WriteStream(fd, { position: position,
length: length });
let output = BinaryOutputStream(nsIFileOutputStream(fd));
nsIBinaryOutputStream(fd, output);
let output = nsIBinaryOutputStream(fd);
// We write content as a byte array as this will avoid any transcoding
// if content was a buffer.
output.writeByteArray(buffer.valueOf(), buffer.length);
@ -745,14 +736,10 @@ function readSync(fd, buffer, offset, length, position) {
// without blocking the main thread.
let binaryInputStream = BinaryInputStream(input);
let count = length === ALL ? binaryInputStream.available() : length;
if (offset === 0) binaryInputStream.readArrayBuffer(count, buffer.buffer);
else {
let chunk = new Buffer(count);
binaryInputStream.readArrayBuffer(count, chunk.buffer);
chunk.copy(buffer, offset);
}
var bytes = binaryInputStream.readByteArray(count);
buffer.copy.call(bytes, buffer, offset);
return buffer.slice(offset, offset + count);
return bytes;
};
exports.readSync = readSync;
@ -772,9 +759,9 @@ exports.readSync = readSync;
function read(fd, buffer, offset, length, position, callback) {
let bytesRead = 0;
let readStream = new ReadStream(fd, { position: position, length: length });
readStream.on("data", function onData(data) {
data.copy(buffer, offset + bytesRead);
bytesRead += data.length;
readStream.on("data", function onData(chunck) {
chunck.copy(buffer, offset + bytesRead);
bytesRead += chunck.length;
});
readStream.on("end", function onEnd() {
callback(null, bytesRead, buffer);
@ -794,26 +781,19 @@ function readFile(path, encoding, callback) {
encoding = null
}
let buffer = null;
let buffer = new Buffer();
try {
let readStream = new ReadStream(path);
readStream.on("data", function(data) {
if (!buffer) buffer = data;
else {
let bufferred = buffer
buffer = new Buffer(buffer.length + data.length);
bufferred.copy(buffer, 0);
data.copy(buffer, bufferred.length);
}
readStream.on("data", function(chunck) {
chunck.copy(buffer, buffer.length);
});
readStream.on("error", function onError(error) {
callback(error);
readStream.destroy();
});
readStream.on("end", function onEnd() {
// Note: Need to destroy before invoking a callback
// so that file descriptor is released.
readStream.destroy();
callback(null, buffer);
readStream.destroy();
});
} catch (error) {
setTimeout(callback, 0, error);
@ -827,9 +807,8 @@ exports.readFile = readFile;
* Otherwise it returns a buffer.
*/
function readFileSync(path, encoding) {
let buffer = new Buffer();
let fd = openSync(path, "r");
let size = fstatSync(fd).size;
let buffer = new Buffer(size);
try {
readSync(fd, buffer, 0, ALL, 0);
}
@ -854,17 +833,14 @@ function writeFile(path, content, encoding, callback) {
content = new Buffer(content, encoding);
let writeStream = new WriteStream(path);
let error = null;
writeStream.end(content, function() {
writeStream.destroy();
writeStream.on("error", function onError(error) {
callback(error);
});
writeStream.on("error", function onError(reason) {
error = reason;
writeStream.destroy();
});
writeStream.write(content, function onDrain() {
writeStream.destroy();
callback(null);
});
} catch (error) {
callback(error);
}

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

@ -8,45 +8,99 @@ module.metadata = {
"stability": "experimental"
};
const { CC, Cc, Ci, Cu, Cr, components } = require("chrome");
const { EventTarget } = require("../event/target");
const { emit } = require("../event/core");
const { Buffer } = require("./buffer");
const { Class } = require("../core/heritage");
const { setTimeout } = require("../timers");
const { ns } = require("../core/namespace");
const MultiplexInputStream = CC("@mozilla.org/io/multiplex-input-stream;1",
"nsIMultiplexInputStream");
const AsyncStreamCopier = CC("@mozilla.org/network/async-stream-copier;1",
"nsIAsyncStreamCopier", "init");
const StringInputStream = CC("@mozilla.org/io/string-input-stream;1",
"nsIStringInputStream");
const ArrayBufferInputStream = CC("@mozilla.org/io/arraybuffer-input-stream;1",
"nsIArrayBufferInputStream");
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream", "setInputStream");
const InputStreamPump = CC("@mozilla.org/network/input-stream-pump;1",
"nsIInputStreamPump", "init");
const threadManager = Cc["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
const eventTarget = Cc["@mozilla.org/network/socket-transport-service;1"].
getService(Ci.nsIEventTarget);
let isFunction = value => typeof(value) === "function"
function isFunction(value) typeof value === "function"
function accessor() {
let map = new WeakMap();
return function(target, value) {
if (value)
map.set(target, value);
return map.get(target);
return function(fd, value) {
if (value === null) map.delete(fd);
if (value !== undefined) map.set(fd, value);
return map.get(fd);
}
}
let nsIInputStreamPump = accessor();
let nsIAsyncOutputStream = accessor();
let nsIInputStream = accessor();
let nsIOutputStream = accessor();
/**
* Utility function / hack that we use to figure if output stream is closed.
*/
function isClosed(stream) {
// We assume that stream is not closed.
let isClosed = false;
stream.asyncWait({
// If `onClose` callback is called before outer function returns
// (synchronously) `isClosed` will be set to `true` identifying
// that stream is closed.
onOutputStreamReady: function onClose() isClosed = true
// `WAIT_CLOSURE_ONLY` flag overrides the default behavior, causing the
// `onOutputStreamReady` notification to be suppressed until the stream
// becomes closed.
}, stream.WAIT_CLOSURE_ONLY, 0, null);
return isClosed;
}
/**
* Utility function takes output `stream`, `onDrain`, `onClose` callbacks and
* calls one of this callbacks depending on stream state. It is guaranteed
* that only one called will be called and it will be called asynchronously.
* @param {nsIAsyncOutputStream} stream
* @param {Function} onDrain
* callback that is called when stream becomes writable.
* @param {Function} onClose
* callback that is called when stream becomes closed.
*/
function onStateChange(stream, target) {
let isAsync = false;
stream.asyncWait({
onOutputStreamReady: function onOutputStreamReady() {
// If `isAsync` was not yet set to `true` by the last line we know that
// `onOutputStreamReady` was called synchronously. In such case we just
// defer execution until next turn of event loop.
if (!isAsync)
return setTimeout(onOutputStreamReady, 0);
// As it"s not clear what is a state of the stream (TODO: Is there really
// no better way ?) we employ hack (see details in `isClosed`) to verify
// if stream is closed.
emit(target, isClosed(stream) ? "close" : "drain");
}
}, 0, 0, null);
isAsync = true;
}
function pump(stream) {
let input = nsIInputStream(stream);
nsIInputStreamPump(stream).asyncRead({
onStartRequest: function onStartRequest() {
emit(stream, "start");
},
onDataAvailable: function onDataAvailable(req, c, is, offset, count) {
try {
let bytes = input.readByteArray(count);
emit(stream, "data", new Buffer(bytes, stream.encoding));
} catch (error) {
emit(stream, "error", error);
stream.readable = false;
}
},
onStopRequest: function onStopRequest() {
stream.readable = false;
emit(stream, "end");
}
}, null);
}
const Stream = Class({
extends: EventTarget,
initialize: function() {
@ -66,8 +120,7 @@ const Stream = Class({
}
}
function onDrain() {
if (source.readable)
source.resume();
if (source.readable) source.resume();
}
function onEnd() {
target.end();
@ -123,69 +176,18 @@ const Stream = Class({
});
exports.Stream = Stream;
let nsIStreamListener = accessor();
let nsIInputStreamPump = accessor();
let nsIAsyncInputStream = accessor();
let nsIBinaryInputStream = accessor();
const StreamListener = Class({
initialize: function(stream) {
this.stream = stream;
},
// Next three methods are part of `nsIStreamListener` interface and are
// invoked by `nsIInputStreamPump.asyncRead`.
onDataAvailable: function(request, context, input, offset, count) {
let stream = this.stream;
let buffer = new ArrayBuffer(count);
nsIBinaryInputStream(stream).readArrayBuffer(count, buffer);
emit(stream, "data", new Buffer(buffer, stream.encoding));
},
// Next two methods implement `nsIRequestObserver` interface and are invoked
// by `nsIInputStreamPump.asyncRead`.
onStartRequest: function() {},
// Called to signify the end of an asynchronous request. We only care to
// discover errors.
onStopRequest: function(request, context, status) {
let stream = this.stream;
stream.readable = false;
if (!components.isSuccessCode(status))
emit(stream, "error", status);
else
emit(stream, "end");
}
});
const InputStream = Class({
extends: Stream,
readable: false,
paused: false,
initialize: function initialize(options) {
let { asyncInputStream } = options;
let { input, pump } = options;
this.readable = true;
let binaryInputStream = new BinaryInputStream(asyncInputStream);
let inputStreamPump = new InputStreamPump(asyncInputStream,
-1, -1, 0, 0, false);
let streamListener = new StreamListener(this);
nsIAsyncInputStream(this, asyncInputStream);
nsIInputStreamPump(this, inputStreamPump);
nsIBinaryInputStream(this, binaryInputStream);
nsIStreamListener(this, streamListener);
this.asyncInputStream = asyncInputStream;
this.inputStreamPump = inputStreamPump;
this.binaryInputStream = binaryInputStream;
this.paused = false;
nsIInputStream(this, input);
nsIInputStreamPump(this, pump);
},
get status() nsIInputStreamPump(this).status,
read: function() {
nsIInputStreamPump(this).asyncRead(nsIStreamListener(this), null);
},
read: function() pump(this),
pause: function pause() {
this.paused = true;
nsIInputStreamPump(this).suspend();
@ -196,176 +198,67 @@ const InputStream = Class({
nsIInputStreamPump(this).resume();
emit(this, "resume");
},
close: function close() {
this.readable = false;
nsIInputStreamPump(this).cancel(Cr.NS_OK);
nsIBinaryInputStream(this).close();
nsIAsyncInputStream(this).close();
},
destroy: function destroy() {
this.close();
this.readable = false;
try {
emit(this, "close", null);
nsIInputStreamPump(this).cancel(null);
nsIInputStreamPump(this, null);
nsIInputStreamPump(this);
nsIAsyncInputStream(this);
nsIBinaryInputStream(this);
nsIStreamListener(this);
nsIInputStream(this).close();
nsIInputStream(this, null);
} catch (error) {
emit(this, "error", error);
}
}
});
exports.InputStream = InputStream;
let nsIRequestObserver = accessor();
let nsIAsyncOutputStream = accessor();
let nsIAsyncStreamCopier = accessor();
let nsIMultiplexInputStream = accessor();
const RequestObserver = Class({
initialize: function(stream) {
this.stream = stream;
},
// Method is part of `nsIRequestObserver` interface that is
// invoked by `nsIAsyncStreamCopier.asyncCopy`.
onStartRequest: function() {},
// Method is part of `nsIRequestObserver` interface that is
// invoked by `nsIAsyncStreamCopier.asyncCopy`.
onStopRequest: function(request, context, status) {
let stream = this.stream;
stream.drained = true;
// Remove copied chunk.
let multiplexInputStream = nsIMultiplexInputStream(stream);
multiplexInputStream.removeStream(0);
// If there was an error report.
if (!components.isSuccessCode(status))
emit(stream, "error", status);
// If there more chunks in queue then flush them.
else if (multiplexInputStream.count)
stream.flush();
// If stream is still writable notify that queue has drained.
else if (stream.writable)
emit(stream, "drain");
// If stream is no longer writable close it.
else {
nsIAsyncStreamCopier(stream).cancel(Cr.NS_OK);
nsIMultiplexInputStream(stream).close();
nsIAsyncOutputStream(stream).close();
nsIAsyncOutputStream(stream).flush();
}
}
});
const OutputStreamCallback = Class({
initialize: function(stream) {
this.stream = stream;
},
// Method is part of `nsIOutputStreamCallback` interface that
// is invoked by `nsIAsyncOutputStream.asyncWait`. It is registered
// with `WAIT_CLOSURE_ONLY` flag that overrides the default behavior,
// causing the `onOutputStreamReady` notification to be suppressed until
// the stream becomes closed.
onOutputStreamReady: function(nsIAsyncOutputStream) {
emit(this.stream, "finish");
}
});
const OutputStream = Class({
extends: Stream,
writable: false,
drained: true,
get bufferSize() {
let multiplexInputStream = nsIMultiplexInputStream(this);
return multiplexInputStream && multiplexInputStream.available();
},
initialize: function initialize(options) {
let { asyncOutputStream, output } = options;
let { output, asyncOutputStream } = options;
this.writable = true;
// Ensure that `nsIAsyncOutputStream` was provided.
asyncOutputStream.QueryInterface(Ci.nsIAsyncOutputStream);
// Create a `nsIMultiplexInputStream` and `nsIAsyncStreamCopier`. Former
// is used to queue written data chunks that `asyncStreamCopier` will
// asynchronously drain into `asyncOutputStream`.
let multiplexInputStream = MultiplexInputStream();
let asyncStreamCopier = AsyncStreamCopier(multiplexInputStream,
output || asyncOutputStream,
eventTarget,
// nsIMultiplexInputStream
// implemnts .readSegments()
true,
// nsIOutputStream may or
// may not implemnet
// .writeSegments().
false,
// Use default buffer size.
null,
// Should not close an input.
false,
// Should not close an output.
false);
// Create `requestObserver` implementing `nsIRequestObserver` interface
// in the constructor that's gonna be reused across several flushes.
let requestObserver = RequestObserver(this);
// Create observer that implements `nsIOutputStreamCallback` and register
// using `WAIT_CLOSURE_ONLY` flag. That way it will be notfied once
// `nsIAsyncOutputStream` is closed.
asyncOutputStream.asyncWait(OutputStreamCallback(this),
asyncOutputStream.WAIT_CLOSURE_ONLY,
0,
threadManager.currentThread);
nsIRequestObserver(this, requestObserver);
nsIOutputStream(this, output);
nsIAsyncOutputStream(this, asyncOutputStream);
nsIMultiplexInputStream(this, multiplexInputStream);
nsIAsyncStreamCopier(this, asyncStreamCopier);
this.asyncOutputStream = asyncOutputStream;
this.multiplexInputStream = multiplexInputStream;
this.asyncStreamCopier = asyncStreamCopier;
},
write: function write(content, encoding, callback) {
let output = nsIOutputStream(this);
let asyncOutputStream = nsIAsyncOutputStream(this);
if (isFunction(encoding)) {
callback = encoding;
encoding = callback;
}
// Flag indicating whether or not content has been flushed to the kernel
// buffer.
let isWritten = false;
// If stream is not writable we throw an error.
if (!this.writable) throw Error("stream is not writable");
if (!this.writable)
throw Error("stream not writable");
let chunk = null;
try {
// If content is not a buffer then we create one out of it.
if (!Buffer.isBuffer(content))
content = new Buffer(content, encoding);
// If content is not a buffer then we create one out of it.
if (Buffer.isBuffer(content)) {
chunk = new ArrayBufferInputStream();
chunk.setData(content.buffer, 0, content.length);
// We write content as a byte array as this will avoid any transcoding
// if content was a buffer.
output.writeByteArray(content.valueOf(), content.length);
output.flush();
if (callback) this.once("drain", callback);
onStateChange(asyncOutputStream, this);
return true;
} catch (error) {
// If errors occur we emit appropriate event.
emit(this, "error", error);
}
else {
chunk = new StringInputStream();
chunk.setData(content, content.length);
}
if (callback)
this.once("drain", callback);
// Queue up chunk to be copied to output sync.
nsIMultiplexInputStream(this).appendStream(chunk);
this.flush();
return this.drained;
},
flush: function() {
if (this.drained) {
this.drained = false;
nsIAsyncStreamCopier(this).asyncCopy(nsIRequestObserver(this), null);
}
flush: function flush() {
nsIOutputStream(this).flush();
},
end: function end(content, encoding, callback) {
if (isFunction(content)) {
@ -377,59 +270,53 @@ const OutputStream = Class({
encoding = callback
}
// Setting a listener to "finish" event if passed.
// Setting a listener to "close" event if passed.
if (isFunction(callback))
this.once("finish", callback);
this.once("close", callback);
// If content is passed then we defer closing until we finish with writing.
if (content)
this.write(content, encoding);
this.writable = false;
// Close `asyncOutputStream` only if output has drained. If it's
// not drained than `asyncStreamCopier` is busy writing, so let
// it finish. Note that since `this.writable` is false copier will
// close `asyncOutputStream` once output drains.
if (this.drained)
nsIAsyncOutputStream(this).close();
this.write(content, encoding, end.bind(this));
// If we don"t write anything, then we close an outputStream.
else
nsIOutputStream(this).close();
},
destroy: function destroy() {
nsIAsyncOutputStream(this).close();
nsIAsyncOutputStream(this);
nsIMultiplexInputStream(this);
nsIAsyncStreamCopier(this);
nsIRequestObserver(this);
destroy: function destroy(callback) {
try {
this.end(callback);
nsIOutputStream(this, null);
nsIAsyncOutputStream(this, null);
} catch (error) {
emit(this, "error", error);
}
}
});
exports.OutputStream = OutputStream;
const DuplexStream = Class({
extends: Stream,
implements: [InputStream, OutputStream],
allowHalfOpen: true,
initialize: function initialize(options) {
options = options || {};
let { readable, writable, allowHalfOpen } = options;
let { input, output, pump } = options;
InputStream.prototype.initialize.call(this, options);
OutputStream.prototype.initialize.call(this, options);
this.writable = true;
this.readable = true;
this.encoding = null;
if (readable === false)
this.readable = false;
if (writable === false)
this.writable = false;
if (allowHalfOpen === false)
this.allowHalfOpen = false;
// If in a half open state and it's disabled enforce end.
this.once("end", () => {
if (!this.allowHalfOpen && (!this.readable || !this.writable))
this.end();
});
nsIInputStream(this, input);
nsIOutputStream(this, output);
nsIInputStreamPump(this, pump);
},
read: InputStream.prototype.read,
pause: InputStream.prototype.pause,
resume: InputStream.prototype.resume,
write: OutputStream.prototype.write,
flush: OutputStream.prototype.flush,
end: OutputStream.prototype.end,
destroy: function destroy(error) {
if (error)
emit(this, "error", error);
InputStream.prototype.destroy.call(this);
OutputStream.prototype.destroy.call(this);
}

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

@ -12,7 +12,7 @@ module.metadata = {
"stability": "unstable"
};
const { setImmediate, setTimeout } = require("../timers");
const { setTimeout } = require("../timers");
const { deprecateFunction } = require("../util/deprecate");
/**
@ -30,12 +30,13 @@ exports.method = method;
/**
* Takes a function and returns a wrapped one instead, calling which will call
* original function in the next turn of event loop. This is basically utility
* to do `setImmediate(function() { ... })`, with a difference that returned
* to do `setTimeout(function() { ... }, 0)`, with a difference that returned
* function is reused, instead of creating a new one each time. This also allows
* to use this functions as event listeners.
*/
function defer(f) {
return function deferred() setImmediate(invoke, f, arguments, this);
return function deferred()
setTimeout(invoke, 0, f, arguments, this);
}
exports.defer = defer;
// Exporting `remit` alias as `defer` may conflict with promises.

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

@ -68,11 +68,19 @@ exports.exit = function exit(code) {
appStartup.quit(code ? E_ATTEMPT : E_FORCE);
};
// Adapter for nodejs's stdout & stderr:
// http://nodejs.org/api/process.html#process_process_stdout
let stdout = Object.freeze({ write: dump, end: dump });
exports.stdout = stdout;
exports.stderr = stdout;
exports.stdout = new function() {
let write = dump
if ('logFile' in options && options.logFile) {
let mode = PR_WRONLY | PR_CREATE_FILE | PR_APPEND;
let stream = openFile(options.logFile, mode);
write = function write(data) {
let text = String(data);
stream.write(text, text.length);
stream.flush();
}
}
return Object.freeze({ write: write });
};
/**
* Returns a path of the system's or application's special directory / file
@ -126,7 +134,7 @@ exports.build = appInfo.appBuildID;
exports.id = appInfo.ID;
/**
* The name of the application.
* The name of the application.
*/
exports.name = appInfo.name;

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

@ -22,7 +22,20 @@ let consoleService = Cc['@mozilla.org/consoleservice;1'].getService().
// For more details see: bug-673383
exports.dump = stdout.write;
exports.console = new PlainTextConsole();
// Bug 718230: We need to send console messages to stdout and JS Console
function forsakenConsoleDump(msg, level) {
stdout.write(msg);
if (level === 'error') {
let error = ScriptError();
msg = msg.replace(/^error: /, '');
error.init(msg, null, null, 0, 0, 0, 'Add-on SDK');
consoleService.logMessage(error);
}
else
consoleService.logStringMessage(msg);
};
exports.console = new PlainTextConsole(forsakenConsoleDump);
// Provide CommonJS `define` to allow authoring modules in a format that can be
// loaded both into jetpack and into browser via AMD loaders.

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

@ -26,9 +26,10 @@ Object.defineProperties(tabs, {
newTabWindow(options);
return undefined;
}
// Open in active window if new window was not required.
let activeWindow = windows.activeWindow;
let privateState = (supportPrivateTabs && (options.isPrivate || isPrivate(activeWindow))) || false;
let privateState = !!options.isPrivate;
// if the active window is in the state that we need then use it
if (activeWindow && (!supportPrivateTabs || privateState === isPrivate(activeWindow))) {

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

@ -8,7 +8,7 @@ module.metadata = {
"stability": "experimental"
};
const { Cc, Ci, Cu } = require("chrome");
const { Cc,Ci } = require("chrome");
const { Loader } = require('./loader');
const { serializeStack, parseStack } = require("toolkit/loader");
const { setTimeout } = require('../timers');
@ -147,11 +147,9 @@ function reportMemoryUsage() {
var mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
.getService(Ci.nsIMemoryReporterManager);
var reporters = mgr.enumerateReporters();
if (reporters.hasMoreElements())
print("\n");
while (reporters.hasMoreElements()) {
var reporter = reporters.getNext();
reporter.QueryInterface(Ci.nsIMemoryReporter);
@ -169,24 +167,26 @@ var gWeakrefInfo;
function checkMemory() {
memory.gc();
Cu.schedulePreciseGC(function () {
let leaks = getPotentialLeaks();
setTimeout(function () {
memory.gc();
setTimeout(function () {
let leaks = getPotentialLeaks();
let compartmentURLs = Object.keys(leaks.compartments).filter(function(url) {
return !(url in startLeaks.compartments);
});
let compartmentURLs = Object.keys(leaks.compartments).filter(function(url) {
return !(url in startLeaks.compartments);
let windowURLs = Object.keys(leaks.windows).filter(function(url) {
return !(url in startLeaks.windows);
});
for (let url of compartmentURLs)
console.warn("LEAKED", leaks.compartments[url]);
for (let url of windowURLs)
console.warn("LEAKED", leaks.windows[url]);
showResults();
});
let windowURLs = Object.keys(leaks.windows).filter(function(url) {
return !(url in startLeaks.windows);
});
for (let url of compartmentURLs)
console.warn("LEAKED", leaks.compartments[url]);
for (let url of windowURLs)
console.warn("LEAKED", leaks.windows[url]);
showResults();
});
}
@ -298,7 +298,6 @@ function getPotentialLeaks() {
let pos = spec.indexOf("!/");
WHITELIST_BASE_URLS.push(spec.substring(0, pos + 2));
let zoneRegExp = new RegExp("^explicit/js-non-window/zones/zone[^/]+/compartment\\((.+)\\)");
let compartmentRegexp = new RegExp("^explicit/js-non-window/compartments/non-window-global/compartment\\((.+)\\)/");
let compartmentDetails = new RegExp("^([^,]+)(?:, (.+?))?(?: \\(from: (.*)\\))?$");
let windowRegexp = new RegExp("^explicit/window-objects/top\\((.*)\\)/active");
@ -319,9 +318,8 @@ function getPotentialLeaks() {
let compartments = {};
let windows = {};
function logReporter(process, path, kind, units, amount, description) {
let matches;
if ((matches = compartmentRegexp.exec(path)) || (matches = zoneRegExp.exec(path))) {
let matches = compartmentRegexp.exec(path);
if (matches) {
if (matches[1] in compartments)
return;
@ -578,7 +576,7 @@ var runTests = exports.runTests = function runTests(options) {
if (options.parseable)
testConsole = new TestRunnerTinderboxConsole(options);
else
testConsole = new TestRunnerConsole(new PlainTextConsole(), options);
testConsole = new TestRunnerConsole(new PlainTextConsole(print), options);
loader = Loader(module, {
console: testConsole,

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

@ -7,31 +7,22 @@ module.metadata = {
"stability": "stable"
};
const { CC, Cc, Ci } = require("chrome");
const { when: unload } = require("./system/unload");
const { CC, Ci } = require('chrome');
const { when: unload } = require('./system/unload');
const { TYPE_ONE_SHOT, TYPE_REPEATING_SLACK } = Ci.nsITimer;
const Timer = CC("@mozilla.org/timer;1", "nsITimer");
const Timer = CC('@mozilla.org/timer;1', 'nsITimer');
const timers = Object.create(null);
const threadManager = Cc["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
const prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService).
QueryInterface(Ci.nsIPrefBranch);
let MIN_DELAY = 4;
// Try to get min timeout delay used by browser.
try { MIN_DELAY = prefBranch.getIntPref("dom.min_timeout_value"); } finally {}
// Last timer id.
let lastID = 0;
// Sets typer either by timeout or by interval
// depending on a given type.
function setTimer(type, callback, delay, ...args) {
function setTimer(type, callback, delay) {
let id = ++ lastID;
let timer = timers[id] = Timer();
let args = Array.slice(arguments, 3);
timer.initWithCallback({
notify: function notify() {
try {
@ -43,63 +34,20 @@ function setTimer(type, callback, delay, ...args) {
console.exception(error);
}
}
}, Math.max(delay || MIN_DELAY), type);
}, delay || 0, type);
return id;
}
function unsetTimer(id) {
let timer = timers[id];
delete timers[id];
if (timer) timer.cancel();
if (timer)
timer.cancel();
}
let immediates = new Map();
let dispatcher = _ => {
// Allow scheduling of a new dispatch loop.
dispatcher.scheduled = false;
// Take a snapshot of timer `id`'s that have being present before
// starting a dispatch loop, in order to ignore timers registered
// in side effect to dispatch while also skipping immediates that
// were removed in side effect.
let ids = [id for ([id] of immediates)];
for (let id of ids) {
let immediate = immediates.get(id);
if (immediate) {
immediates.delete(id);
try { immediate(); }
catch (error) { console.exception(error); }
}
}
}
function setImmediate(callback, ...params) {
let id = ++ lastID;
// register new immediate timer with curried params.
immediates.set(id, _ => callback.apply(callback, params));
// if dispatch loop is not scheduled schedule one. Own scheduler
if (!dispatcher.scheduled) {
dispatcher.scheduled = true;
threadManager.currentThread.dispatch(dispatcher,
Ci.nsIThread.DISPATCH_NORMAL);
}
return id;
}
function clearImmediate(id) {
immediates.delete(id);
}
// Bind timers so that toString-ing them looks same as on native timers.
exports.setImmediate = setImmediate.bind(null);
exports.clearImmediate = clearImmediate.bind(null);
exports.setTimeout = setTimer.bind(null, TYPE_ONE_SHOT);
exports.setInterval = setTimer.bind(null, TYPE_REPEATING_SLACK);
exports.clearTimeout = unsetTimer.bind(null);
exports.clearInterval = unsetTimer.bind(null);
// all timers are cleared out on unload.
unload(function() {
immediates.clear();
Object.keys(timers).forEach(unsetTimer)
});
unload(function() { Object.keys(timers).forEach(unsetTimer) });

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

@ -101,7 +101,7 @@ function fromIterator(iterator) {
}
exports.fromIterator = fromIterator;
function find(array, predicate, fallback) {
function find(array, predicate) {
var index = 0;
var count = array.length;
while (index < count) {
@ -109,6 +109,5 @@ function find(array, predicate, fallback) {
if (predicate(value)) return value;
else index = index + 1;
}
return fallback;
}
exports.find = find;

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

@ -18,8 +18,6 @@ const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
getService(Ci.nsIAppShellService);
const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
getService(Ci.nsIWindowMediator);
const io = Cc['@mozilla.org/network/io-service;1'].
getService(Ci.nsIIOService);
const BROWSER = 'navigator:browser',
URI_BROWSER = 'chrome://browser/content/browser.xul',
@ -186,21 +184,18 @@ function serializeFeatures(options) {
* Map of key, values like: `{ width: 10, height: 15, chrome: true, private: true }`.
*/
function open(uri, options) {
uri = uri || URI_BROWSER;
options = options || {}
if (['chrome', 'resource', 'data'].indexOf(io.newURI(uri, null, null).scheme) < 0)
throw new Error('only chrome, resource and data uris are allowed');
options = options || {};
let newWindow = windowWatcher.
openWindow(options.parent || null,
uri,
uri || URI_BROWSER,
options.name || null,
serializeFeatures(options.features || {}),
options.args || null);
return newWindow;
}
exports.open = open;
function onFocus(window) {

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

@ -52,9 +52,6 @@ def parse_options(options, jetpack_id):
doc.appendChild(root)
for pref in options:
if ("hidden" in pref and pref["hidden"] == True):
continue;
setting = doc.createElement("setting")
setting.setAttribute("pref-name", pref["name"])
setting.setAttribute("data-jetpack-id", jetpack_id)

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

@ -30,7 +30,7 @@ PARSEABLE_TEST_NAME = re.compile(r'TEST-START \| ([^\n]+)\n')
# The purpose of this timeout is to recover from infinite loops. It should be
# longer than the amount of time any test run takes, including those on slow
# machines running slow (debug) versions of Firefox.
RUN_TIMEOUT = 1.5 * 60 * 60 # 1.5 Hour
RUN_TIMEOUT = 45 * 60 # 45 minutes
# Maximum time we'll wait for tests to emit output, in seconds.
# The purpose of this timeout is to recover from hangs. It should be longer
@ -496,6 +496,9 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
logfile = os.path.abspath(os.path.expanduser(logfile))
maybe_remove_logfile()
if app_type != "fennec-on-device":
harness_options['logFile'] = logfile
env = {}
env.update(os.environ)
env['MOZ_NO_REMOTE'] = '1'

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

@ -330,9 +330,13 @@ GetExitCodeProcess = GetExitCodeProcessProto(
GetExitCodeProcess.errcheck = ErrCheckBool
def CanCreateJobObject():
# Running firefox in a job (from cfx) hangs on sites using flash plugin
# so job creation is turned off for now. (see Bug 768651).
return False
currentProc = GetCurrentProcess()
if IsProcessInJob(currentProc):
jobinfo = QueryInformationJobObject(HANDLE(0), 'JobObjectExtendedLimitInformation')
limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
return bool(limitflags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) or bool(limitflags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
else:
return True
### testing functions

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

@ -3,14 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const xulApp = require("sdk/system/xul-app");
const { PageMod } = require("sdk/page-mod");
const tabs = require("sdk/tabs");
const { startServerAsync } = require("sdk/test/httpd");
const serverPort = 8099;
exports.testCrossDomainIframe = function(assert, done) {
let server = startServerAsync(serverPort);
let serverPort = 8099;
let server = require("sdk/test/httpd").startServerAsync(serverPort);
server.registerPathHandler("/iframe", function handle(request, response) {
response.write("<html><body>foo</body></html>");
});
@ -32,23 +31,19 @@ exports.testCrossDomainIframe = function(assert, done) {
w.on("message", function (body) {
assert.equal(body, "foo", "received iframe html content");
pageMod.destroy();
w.tab.close(function() {
server.stop(done);
});
w.tab.close();
server.stop(done);
});
w.postMessage("http://localhost:8099/iframe");
}
});
tabs.open({
url: "about:home",
inBackground: true
});
tabs.open("about:credits");
};
exports.testCrossDomainXHR = function(assert, done) {
let server = startServerAsync(serverPort);
let serverPort = 8099;
let server = require("sdk/test/httpd").startServerAsync(serverPort);
server.registerPathHandler("/xhr", function handle(request, response) {
response.write("foo");
});
@ -70,19 +65,22 @@ exports.testCrossDomainXHR = function(assert, done) {
w.on("message", function (body) {
assert.equal(body, "foo", "received XHR content");
pageMod.destroy();
w.tab.close(function() {
server.stop(done);
});
w.tab.close();
server.stop(done);
});
w.postMessage("http://localhost:8099/xhr");
}
});
tabs.open({
url: "about:home",
inBackground: true
});
tabs.open("about:credits");
};
if (!xulApp.versionInRange(xulApp.platformVersion, "17.0a2", "*")) {
module.exports = {
"test Unsupported Application": function Unsupported (assert) {
assert.pass("This firefox version doesn't support cross-domain-content permission.");
}
};
}
require("sdk/test/runner").runTestsFromModule(module);

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

@ -1,35 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
const { setTimeout } = require('sdk/timers');
let mainStarted = false;
exports.main = function main(options, callbacks) {
mainStarted = true;
let tests = {};
tests.testMainArguments = function(assert) {
assert.ok(!!options, 'options argument provided to main');
assert.ok('loadReason' in options, 'loadReason is in options provided by main');
assert.equal(typeof callbacks.print, 'function', 'callbacks.print is a function');
assert.equal(typeof callbacks.quit, 'function', 'callbacks.quit is a function');
assert.equal(options.loadReason, 'install', 'options.loadReason is install');
}
require('sdk/test/runner').runTestsFromModule({exports: tests});
}
// this causes a fail if main does not start
setTimeout(function() {
if (mainStarted)
return;
// main didn't start, fail..
require("sdk/test/runner").runTestsFromModule({exports: {
testFail: function(assert) assert.fail('Main did not start..')
}});
}, 500);

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

@ -1,3 +0,0 @@
{
"id": "test-main"
}

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

@ -4,7 +4,7 @@
'use strict';
const { merge } = require('sdk/util/object');
const app = require('sdk/system/xul-app');
const app = require("sdk/system/xul-app");
const { isGlobalPBSupported } = require('sdk/private-browsing/utils');
merge(module.exports,
@ -18,7 +18,7 @@ merge(module.exports,
// Doesn't make sense to test window-utils and windows on fennec,
// as there is only one window which is never private
if (!app.is('Fennec'))
if (!app.is("Fennec"))
merge(module.exports, require('./test-windows'));
require('sdk/test/runner').runTestsFromModule(module);

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

@ -5,8 +5,6 @@ const { is } = require('sdk/system/xul-app');
const { isPrivate } = require('sdk/private-browsing');
const pbUtils = require('sdk/private-browsing/utils');
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
const { promise: windowPromise, close, focus } = require('sdk/window/helpers');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
exports.testPrivateTabsAreListed = function (assert, done) {
let originalTabCount = tabs.length;
@ -28,86 +26,7 @@ exports.testPrivateTabsAreListed = function (assert, done) {
assert.equal(tabs.length, originalTabCount + 1,
'New non-private window\'s tab is visible in tabs list');
}
tab.close(done);
}
});
}
exports.testOpenTabWithPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
windowPromise(window, 'load').then(focus).then(function (window) {
assert.ok(isPrivate(window), 'new window is private');
tabs.open({
url: 'about:blank',
onOpen: function(tab) {
assert.ok(isPrivate(tab), 'new tab is private');
assert.ok(isPrivate(getOwnerWindow(tab)), 'new tab window is private');
assert.strictEqual(getOwnerWindow(tab), window, 'the tab window and the private window are the same');
close(window).then(done, assert.fail);
}
})
}, assert.fail).then(null, assert.fail);
}
exports.testOpenTabWithNonPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
windowPromise(window, 'load').then(focus).then(function (window) {
assert.equal(isPrivate(window), false, 'new window is not private');
tabs.open({
url: 'about:blank',
onOpen: function(tab) {
assert.equal(isPrivate(tab), false, 'new tab is not private');
assert.equal(isPrivate(getOwnerWindow(tab)), false, 'new tab window is not private');
assert.strictEqual(getOwnerWindow(tab), window, 'the tab window and the new window are the same');
close(window).then(done, assert.fail);
}
})
}, assert.fail).then(null, assert.fail);
}
exports.testOpenTabWithPrivateActiveWindowWithIsPrivateOptionTrue = function(assert, done) {
let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
windowPromise(window, 'load').then(focus).then(function (window) {
assert.ok(isPrivate(window), 'new window is private');
tabs.open({
url: 'about:blank',
isPrivate: true,
onOpen: function(tab) {
assert.ok(isPrivate(tab), 'new tab is private');
assert.ok(isPrivate(getOwnerWindow(tab)), 'new tab window is private');
assert.strictEqual(getOwnerWindow(tab), window, 'the tab window and the private window are the same');
close(window).then(done, assert.fail);
}
})
}, assert.fail).then(null, assert.fail);
}
exports.testOpenTabWithNonPrivateActiveWindowWithIsPrivateOptionFalse = function(assert, done) {
let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
windowPromise(window, 'load').then(focus).then(function (window) {
assert.equal(isPrivate(window), false, 'new window is not private');
tabs.open({
url: 'about:blank',
isPrivate: false,
onOpen: function(tab) {
assert.equal(isPrivate(tab), false, 'new tab is not private');
assert.equal(isPrivate(getOwnerWindow(tab)), false, 'new tab window is not private');
assert.strictEqual(getOwnerWindow(tab), window, 'the tab window and the new window are the same');
close(window).then(done, assert.fail);
}
})
}, assert.fail).then(null, assert.fail);
}

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

@ -1,82 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
const { Cu } = require('chrome');
const sp = require('sdk/simple-prefs');
const app = require('sdk/system/xul-app');
const self = require('sdk/self');
const tabs = require('sdk/tabs');
const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
exports.testDefaultValues = function (assert) {
assert.equal(sp.prefs.myHiddenInt, 5, 'myHiddenInt default is 5');
assert.equal(sp.prefs.myInteger, 8, 'myInteger default is 8');
assert.equal(sp.prefs.somePreference, 'TEST', 'somePreference default is correct');
}
exports.testOptionsType = function(assert, done) {
AddonManager.getAddonByID(self.id, function(aAddon) {
assert.equal(aAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, 'options type is inline');
done();
});
}
if (app.is('Firefox')) {
exports.testAOM = function(assert, done) {
tabs.open({
url: 'about:addons',
onReady: function(tab) {
tab.attach({
contentScript: 'AddonManager.getAddonByID("' + self.id + '", function(aAddon) {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.addEventListener("ViewChanged", function whenViewChanges() {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.removeEventListener("ViewChanged", whenViewChanges, false);\n' +
'setTimeout(function() {\n' + // TODO: figure out why this is necessary..
'self.postMessage({\n' +
'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[title=\'some-title\']")),\n' +
'myInteger: getAttributes(unsafeWindow.document.querySelector("setting[title=\'my-int\']")),\n' +
'myHiddenInt: getAttributes(unsafeWindow.document.querySelector("setting[title=\'hidden-int\']"))\n' +
'});\n' +
'}, 250);\n' +
'}, false);\n' +
'unsafeWindow.gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);\n' +
'});\n' +
'function getAttributes(ele) {\n' +
'if (!ele) return {};\n' +
'return {\n' +
'pref: ele.getAttribute("pref"),\n' +
'type: ele.getAttribute("type"),\n' +
'title: ele.getAttribute("title"),\n' +
'desc: ele.getAttribute("desc")\n' +
'}\n' +
'}\n',
onMessage: function(msg) {
// test somePreference
assert.equal(msg.somePreference.type, 'string', 'some pref is a string');
assert.equal(msg.somePreference.pref, 'extensions.'+self.id+'.somePreference', 'somePreference path is correct');
assert.equal(msg.somePreference.title, 'some-title', 'somePreference title is correct');
assert.equal(msg.somePreference.desc, 'Some short description for the preference', 'somePreference description is correct');
// test myInteger
assert.equal(msg.myInteger.type, 'integer', 'myInteger is a int');
assert.equal(msg.myInteger.pref, 'extensions.'+self.id+'.myInteger', 'extensions.test-simple-prefs.myInteger');
assert.equal(msg.myInteger.title, 'my-int', 'myInteger title is correct');
assert.equal(msg.myInteger.desc, 'How many of them we have.', 'myInteger desc is correct');
// test myHiddenInt
assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.pref, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
tab.close(done);
}
});
}
});
}
}
require('sdk/test/runner').runTestsFromModule(module);

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

@ -1,23 +0,0 @@
{
"id": "test-simple-prefs",
"preferences": [{
"name": "somePreference",
"title": "some-title",
"description": "Some short description for the preference",
"type": "string",
"value": "TEST"
},
{
"description": "How many of them we have.",
"name": "myInteger",
"type": "integer",
"value": 8,
"title": "my-int"
}, {
"name": "myHiddenInt",
"type": "integer",
"hidden": true,
"value": 5,
"title": "hidden-int"
}]
}

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

@ -19,7 +19,6 @@ const { setTimeout } = require('sdk/timers');
const { newURI } = require('sdk/url/utils');
const { defer, all } = require('sdk/core/promise');
const { once } = require('sdk/system/events');
const { set } = require('sdk/preferences/service');
const {
Bookmark, Group, Separator,
save, search,
@ -46,25 +45,12 @@ function clearBookmarks (group) {
? bmsrv.removeFolderChildren(group.id)
: clearAllBookmarks();
}
exports.clearBookmarks = clearBookmarks;
function clearAllBookmarks () {
[MENU, TOOLBAR, UNSORTED].forEach(clearBookmarks);
}
function clearHistory (done) {
hsrv.removeAllPages();
once('places-expiration-finished', done);
}
// Cleans bookmarks and history and disables maintanance
function resetPlaces (done) {
// Set last maintenance to current time to prevent
// Places DB maintenance occuring and locking DB
set('places.database.lastMaintenance', Math.floor(Date.now() / 1000));
clearAllBookmarks();
clearHistory(done);
}
exports.resetPlaces = resetPlaces;
exports.clearAllBookmarks = clearAllBookmarks;
function compareWithHost (assert, item) {
let id = item.id;
@ -119,6 +105,12 @@ function createVisit (url) {
return place;
}
function clearHistory (done) {
hsrv.removeAllPages();
once('places-expiration-finished', done);
}
exports.clearHistory = clearHistory;
function createBookmark (data) {
data = data || {};
let item = {

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

@ -111,11 +111,12 @@ exports.testTabProperties = function(test) {
test.assertEqual(tab.url, url, "URL of the new tab matches");
test.assert(tab.favicon, "favicon of the new tab is not empty");
// TODO: remove need for this test by implementing the favicon feature
test.assertEqual(messages[0].msg,
"tab.favicon is deprecated, and " +
"currently favicon helpers are not yet supported " +
"by Fennec",
"favicon logs an error for now");
// Poors man deepEqual with JSON.stringify...
test.assertEqual(JSON.stringify(messages),
JSON.stringify(['tab.favicon is deprecated, and ' +
'currently favicon helpers are not yet supported ' +
'by Fennec']),
"favicon logs an error for now");
test.assertEqual(tab.style, null, "style of the new tab matches");
test.assertEqual(tab.index, tabsLen, "index of the new tab matches");
test.assertNotEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");

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

@ -85,11 +85,3 @@ exports.testUnique = function(test) {
}
}
};
exports.testFind = function(test) {
let isOdd = (x) => x % 2;
test.assertEqual(array.find([2, 4, 5, 7, 8, 9], isOdd), 5);
test.assertEqual(array.find([2, 4, 6, 8], isOdd), undefined);
test.assertEqual(array.find([2, 4, 6, 8], isOdd, null), null);
};

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

@ -92,4 +92,14 @@ exports["test browser events ignore other wins"] = function(assert, done) {
let window = open("data:text/html,not a browser");
};
if (require("sdk/system/xul-app").is("Fennec")) {
module.exports = {
"test Unsupported Test": function UnsupportedTest (assert) {
assert.pass(
"Skipping this test until Fennec support is implemented." +
"See bug 793071");
}
}
}
require("test").run(exports);

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

@ -3,12 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const hiddenFrames = require("sdk/frame/hidden-frame");
const { create: makeFrame } = require("sdk/frame/utils");
const { window } = require("sdk/addon/window");
const { Loader } = require('sdk/test/loader');
const { URL } = require("sdk/url");
const testURI = require("sdk/self").data.url("test.html");
const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
/*
* Utility function that allow to easily run a proxy test with a clean
@ -16,51 +12,41 @@ const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
*/
function createProxyTest(html, callback) {
return function (assert, done) {
let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
let principalLoaded = false;
let url = 'data:text/html;charset=utf-8,' + encodeURI(html);
let element = makeFrame(window.document, {
nodeName: "iframe",
type: "content",
allowJavascript: true,
allowPlugins: true,
allowAuth: true,
uri: testURI
});
let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({
onReady: function () {
element.addEventListener("DOMContentLoaded", onDOMReady, false);
function onDOMReady() {
// Reload frame after getting principal from `testURI`
if (!principalLoaded) {
element.setAttribute("src", url);
principalLoaded = true;
return;
}
assert.equal(element.getAttribute("src"), url, "correct URL loaded");
element.removeEventListener("DOMContentLoaded", onDOMReady,
function onDOMReady() {
hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady,
false);
let xrayWindow = element.contentWindow;
let rawWindow = xrayWindow.wrappedJSObject;
let isDone = false;
let helper = {
xrayWindow: xrayWindow,
rawWindow: rawWindow,
createWorker: function (contentScript) {
return createWorker(assert, xrayWindow, contentScript, helper.done);
},
done: function () {
if (isDone)
return;
isDone = true;
element.parentNode.removeChild(element);
done();
let xrayWindow = hiddenFrame.element.contentWindow;
let rawWindow = xrayWindow.wrappedJSObject;
let isDone = false;
let helper = {
xrayWindow: xrayWindow,
rawWindow: rawWindow,
createWorker: function (contentScript) {
return createWorker(assert, xrayWindow, contentScript, helper.done);
},
done: function () {
if (isDone)
return;
isDone = true;
hiddenFrames.remove(hiddenFrame);
done();
}
}
callback(helper, assert);
}
};
callback(helper, assert);
}
hiddenFrame.element.addEventListener("DOMContentLoaded", onDOMReady, false);
hiddenFrame.element.setAttribute("src", url);
}
}));
};
}
@ -179,9 +165,9 @@ exports["test postMessage"] = createProxyTest(html, function (helper, assert) {
// xrays use current compartments when calling postMessage method.
// Whereas js proxies was using postMessage method compartment,
// not the caller one.
assert.strictEqual(event.source, helper.xrayWindow,
"event.source is the top window");
assert.equal(event.origin, testHost, "origin matches testHost");
assert.equal(event.source, helper.xrayWindow,
"event.source is the top window");
assert.equal(event.origin, "null", "origin is null");
assert.equal(event.data, "{\"foo\":\"bar\\n \\\"escaped\\\".\"}",
"message data is correct");
@ -230,9 +216,7 @@ exports["test Object Listener"] = createProxyTest(html, function (helper) {
exports["test Object Listener 2"] = createProxyTest("", function (helper) {
helper.createWorker(
('new ' + function ContentScriptScope() {
// variable replaced with `testHost`
let testHost = "TOKEN";
'new ' + function ContentScriptScope() {
// Verify object as DOM event listener
let myMessageListener = {
called: false,
@ -244,7 +228,7 @@ exports["test Object Listener 2"] = createProxyTest("", function (helper) {
this.called = true;
assert(event.target == document.defaultView, "event.target is the wrapped window");
assert(event.source == document.defaultView, "event.source is the wrapped window");
assert(event.origin == testHost, "origin matches testHost");
assert(event.origin == "null", "origin is null");
assert(event.data == "ok", "message data is correct");
done();
}
@ -253,7 +237,7 @@ exports["test Object Listener 2"] = createProxyTest("", function (helper) {
window.addEventListener("message", myMessageListener, true);
document.defaultView.postMessage("ok", '*');
}
).replace("TOKEN", testHost));
);
});

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

@ -9,7 +9,6 @@ const fs = require("sdk/io/fs");
const url = require("sdk/url");
const path = require("sdk/fs/path");
const { Buffer } = require("sdk/io/buffer");
const { is } = require("sdk/system/xul-app");
// Use profile directory to list / read / write files.
const profilePath = pathFor("ProfD");
@ -27,18 +26,19 @@ const renameToPath = path.join(profilePath, "sdk-fixture-rename-to");
const profileEntries = [
"compatibility.ini",
"extensions",
"extensions.ini",
"prefs.js"
// There are likely to be a lot more files but we can't really
// on consistent list so we limit to this.
];
exports["test readdir"] = function(assert, end) {
exports["test readir"] = function(assert, end) {
var async = false;
fs.readdir(profilePath, function(error, entries) {
assert.ok(async, "readdir is async");
assert.ok(!error, "there is no error when reading directory");
assert.ok(profileEntries.length <= entries.length,
"got at least number of entries we expect");
"got et least number of entries we expect");
assert.ok(profileEntries.every(function(entry) {
return entries.indexOf(entry) >= 0;
}), "all profiles are present");
@ -67,13 +67,13 @@ exports["test readdirSync"] = function(assert) {
var async = false;
var entries = fs.readdirSync(profilePath);
assert.ok(profileEntries.length <= entries.length,
"got at least number of entries we expect");
"got et least number of entries we expect");
assert.ok(profileEntries.every(function(entry) {
return entries.indexOf(entry) >= 0;
}), "all profiles are present");
};
exports["test readdirSync error"] = function(assert) {
exports["test readirSync error"] = function(assert) {
var async = false;
var path = profilePath + "-does-not-exists";
try {
@ -92,7 +92,6 @@ exports["test readFile"] = function(assert, end) {
fs.readFile(filePathInProfile, function(error, content) {
assert.ok(async, "readFile is async");
assert.ok(!error, "error is falsy");
assert.ok(Buffer.isBuffer(content), "readFile returns buffer");
assert.ok(typeof(content.length) === "number", "buffer has length");
assert.ok(content.toString().indexOf("[Compatibility]") >= 0,
@ -339,6 +338,7 @@ exports["test fs.truncate"] = function(assert, end) {
let async = false;
fs.truncate(path, 0, function(error) {
assert.ok(async, "truncate is async");
console.log(error);
assert.ok(!error, "no error");
assert.equal(fs.existsSync(path), true, "file was created");
fs.unlinkSync(path);
@ -459,28 +459,4 @@ exports["test fs.writeFile"] = function(assert, end) {
async = true;
};
exports["test fs.writeFile (with large files)"] = function(assert, end) {
let path = writePath;
let content = "";
for (var i = 0; i < 100000; i++) {
content += "buffer\n";
}
var async = false;
fs.writeFile(path, content, function(error) {
assert.ok(async, "fs write is async");
assert.ok(!error, "error is falsy");
assert.ok(fs.existsSync(path), "file was created");
assert.equal(fs.readFileSync(path).toString(),
content,
"contet was written");
fs.unlinkSync(path);
assert.ok(!fs.exists(path), "file was removed");
end();
});
async = true;
};
require("test").run(exports);

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

@ -22,13 +22,13 @@ exports.testUnloadAndErrorLogging = function(test) {
test.assertEqual(timesCalled, 1);
sbobsvc.add("narg", badCb);
observers.notify("narg", "yo yo");
test.assertEqual(messages[0], "console.error: " + require("sdk/self").name + ": \n");
var lines = messages[1].split("\n");
test.assertEqual(lines[0], " Message: Error: foo");
test.assertEqual(lines[1], " Stack:");
var lines = messages[0].split("\n");
test.assertEqual(lines[0], "error: " + require("sdk/self").name + ": An exception occurred.");
test.assertEqual(lines[0], "error: " + require("sdk/self").name + ": An exception occurred.");
test.assertEqual(lines[1], "Error: foo");
// Keep in mind to update "18" to the line of "throw new Error("foo")"
test.assert(lines[2].indexOf(module.uri + ":18") != -1);
test.assertEqual(lines[2], module.uri + " 18");
test.assertEqual(lines[3], "Traceback (most recent call last):");
loader.unload();
observers.notify("blarg", "yo yo");

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

@ -19,8 +19,6 @@ const { openWebpage } = require('./private-browsing/helper');
const { isTabPBSupported, isWindowPBSupported, isGlobalPBSupported } = require('sdk/private-browsing/utils');
const promise = require("sdk/core/promise");
const { pb } = require('./private-browsing/helper');
const { URL } = require("sdk/url");
const testPageURI = require("sdk/self").data.url("test.html");
/* XXX This can be used to delay closing the test Firefox instance for interactive
* testing or visual inspection. This test is registered first so that it runs
@ -121,16 +119,16 @@ exports.testPageModIncludes = function(test) {
};
}
testPageMod(test, testPageURI, [
testPageMod(test, "about:buildconfig", [
createPageModTest("*", false),
createPageModTest("*.google.com", false),
createPageModTest("resource:*", true),
createPageModTest("resource:", false),
createPageModTest(testPageURI, true)
createPageModTest("about:*", true),
createPageModTest("about:", false),
createPageModTest("about:buildconfig", true)
],
function (win, done) {
test.waitUntil(function () win.localStorage[testPageURI],
testPageURI + " page-mod to be executed")
test.waitUntil(function () win.localStorage["about:buildconfig"],
"about:buildconfig page-mod to be executed")
.then(function () {
asserts.forEach(function(fn) {
fn(test, win);

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

@ -7,8 +7,6 @@
const { Loader } = require('sdk/test/loader');
const Pages = require("sdk/page-worker");
const Page = Pages.Page;
const { URL } = require("sdk/url");
const testURI = require("sdk/self").data.url("test.html");
const ERR_DESTROYED =
"Couldn't find the worker to receive this message. " +
@ -158,23 +156,14 @@ exports.testValidateOptions = function(assert) {
exports.testContentAndAllowGettersAndSetters = function(assert, done) {
let content = "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=3;</script>";
// Load up the page with testURI initially for the resource:// principal,
// then load the actual data:* content, as data:* URIs no longer
// have localStorage
let page = Page({
contentURL: testURI,
contentScript: "if (window.location.href==='"+testURI+"')" +
" self.postMessage('reload');" +
"else " +
" self.postMessage(window.localStorage.allowScript)",
contentURL: content,
contentScript: "self.postMessage(window.localStorage.allowScript)",
contentScriptWhen: "end",
onMessage: step0
});
function step0(message) {
if (message === 'reload')
return page.contentURL = content;
assert.equal(message, "3",
"Correct value expected for allowScript - 3");
assert.equal(page.contentURL, content,

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

@ -25,9 +25,9 @@ const {
MENU, TOOLBAR, UNSORTED
} = require('sdk/places/bookmarks');
const {
invalidResolve, invalidReject, createTree,
compareWithHost, createBookmark, createBookmarkItem,
createBookmarkTree, addVisits, resetPlaces
invalidResolve, invalidReject, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, createBookmark, createBookmarkItem,
createBookmarkTree, addVisits
} = require('./places-helper');
const { promisedEmitter } = require('sdk/places/utils');
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
@ -941,8 +941,13 @@ exports.testCheckSaveOrder = function (assert, done) {
});
};
before(exports, (name, assert, done) => resetPlaces(done));
after(exports, (name, assert, done) => resetPlaces(done));
before(exports, name => {
clearAllBookmarks();
});
after(exports, name => {
clearAllBookmarks();
});
function saveP () {
return promisedEmitter(save.apply(null, Array.slice(arguments)));

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

@ -19,7 +19,7 @@ const host = 'http://localhost:' + port;
const { onFaviconChange, serve, binFavicon } = require('./favicon-helpers');
const { once } = require('sdk/system/events');
const { defer } = require('sdk/core/promise');
const { resetPlaces } = require('./places-helper');
const { clearHistory } = require('./places-helper');
const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService);
@ -181,7 +181,7 @@ function waitAndExpire (url) {
function complete(tab, srv, done) {
tab.close(function () {
resetPlaces(() => {
clearHistory(() => {
srv.stop(done);
});
});

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

@ -14,15 +14,16 @@ const { defer, all } = require('sdk/core/promise');
const { has } = require('sdk/util/array');
const { setTimeout } = require('sdk/timers');
const { before, after } = require('sdk/test/utils');
const { set } = require('sdk/preferences/service');
const {
search
} = require('sdk/places/history');
const {
invalidResolve, invalidReject, createTree,
compareWithHost, addVisits, resetPlaces
invalidResolve, invalidReject, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, addVisits, clearHistory
} = require('./places-helper');
const { promisedEmitter } = require('sdk/places/utils');
const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
getService(Ci.nsINavHistoryService);
exports.testEmptyQuery = function (assert, done) {
let within = toBeWithin();
@ -238,11 +239,16 @@ function toBeWithin (range) {
};
}
function clear (done) {
clearAllBookmarks();
clearHistory(done);
}
function searchP () {
return promisedEmitter(search.apply(null, Array.slice(arguments)));
}
before(exports, (name, assert, done) => resetPlaces(done));
after(exports, (name, assert, done) => resetPlaces(done));
before(exports, (name, assert, done) => clear(done));
after(exports, (name, assert, done) => clear(done));
require('test').run(exports);

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

@ -14,15 +14,13 @@ const { defer, all } = require('sdk/core/promise');
const { setTimeout } = require('sdk/timers');
const { newURI } = require('sdk/url/utils');
const { send } = require('sdk/addon/events');
const { set } = require('sdk/preferences/service');
const { before, after } = require('sdk/test/utils');
require('sdk/places/host/host-bookmarks');
require('sdk/places/host/host-tags');
require('sdk/places/host/host-query');
const {
invalidResolve, invalidReject, createTree,
compareWithHost, createBookmark, createBookmarkTree, resetPlaces
invalidResolve, invalidReject, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, createBookmark, createBookmarkTree
} = require('./places-helper');
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
@ -31,6 +29,7 @@ const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
getService(Ci.nsINavHistoryService);
const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
getService(Ci.nsITaggingService);
clearAllBookmarks();
exports.testBookmarksCreate = function (assert, done) {
let items = [{
@ -52,6 +51,7 @@ exports.testBookmarksCreate = function (assert, done) {
compareWithHost(assert, data);
}, invalidReject(assert));
})).then(function () {
clearAllBookmarks();
done();
}, invalidReject(assert));
};
@ -72,6 +72,7 @@ exports.testBookmarksCreateFail = function (assert, done) {
assert.ok(reason, 'bookmark create should fail');
});
})).then(function () {
clearAllBookmarks();
done();
});
};
@ -93,6 +94,7 @@ exports.testBookmarkLastUpdated = function (assert, done) {
});
}).then(function (data) {
assert.ok(data.updated > timestamp, 'time has elapsed and updated the updated property');
clearAllBookmarks();
done();
});
};
@ -108,6 +110,7 @@ exports.testBookmarkRemove = function (assert, done) {
assert.throws(function () {
bmsrv.getItemTitle(id);
}, 'item should no longer exist');
clearAllBookmarks();
done();
}, console.error);
};
@ -130,6 +133,7 @@ exports.testBookmarkGet = function (assert, done) {
else
assert.equal(bookmark[prop], data[prop], 'correctly fetched ' + prop);
});
clearAllBookmarks();
done();
});
};
@ -147,6 +151,7 @@ exports.testTagsTag = function (assert, done) {
assert.ok(~tags.indexOf('foxfire'), 'second tag found');
assert.ok(~tags.indexOf('firefox'), 'default tag found');
assert.equal(tags.length, 3, 'no extra tags');
clearAllBookmarks();
done();
});
};
@ -166,6 +171,7 @@ exports.testTagsUntag = function (assert, done) {
assert.ok(!~tags.indexOf('firefox'), 'first tag removed');
assert.ok(!~tags.indexOf('tag2'), 'second tag removed');
assert.equal(tags.length, 2, 'no extra tags');
clearAllBookmarks();
done();
});
};
@ -180,6 +186,7 @@ exports.testTagsGetURLsByTag = function (assert, done) {
}).then(function(urls) {
assert.equal(item.url, urls[0], 'returned correct url');
assert.equal(urls.length, 1, 'returned only one url');
clearAllBookmarks();
done();
});
};
@ -196,6 +203,7 @@ exports.testTagsGetTagsByURL = function (assert, done) {
assert.ok(~tags.indexOf('mozilla'), 'returned second tag');
assert.ok(~tags.indexOf('metal'), 'returned third tag');
assert.equal(tags.length, 3, 'returned all tags');
clearAllBookmarks();
done();
});
};
@ -220,6 +228,7 @@ exports.testHostQuery = function (assert, done) {
}).then(results => {
assert.equal(results.length, 2, 'should only return two');
assert.equal(results[0].url, 'http://firefox.com/', 'is sorted by URI desc');
clearAllBookmarks();
done();
});
};
@ -244,6 +253,7 @@ exports.testHostMultiQuery = function (assert, done) {
});
}).then(results => {
assert.equal(results.length, 0, 'query props should be AND\'d');
clearAllBookmarks();
done();
});
};
@ -253,6 +263,7 @@ exports.testGetAllBookmarks = function (assert, done) {
return send('sdk-places-bookmarks-get-all', {});
}).then(res => {
assert.equal(res.length, 8, 'all bookmarks returned');
clearAllBookmarks();
done();
}, console.error);
};
@ -265,12 +276,9 @@ exports.testGetAllChildren = function (assert, done) {
}).then(results => {
assert.equal(results.length, 5,
'should return all children and folders at a single depth');
clearAllBookmarks();
done();
});
};
before(exports, (name, assert, done) => resetPlaces(done));
after(exports, (name, assert, done) => resetPlaces(done));
require('test').run(exports);

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

@ -36,61 +36,50 @@ exports.testPlainTextConsole = function(test) {
test.pass("PlainTextConsole instantiates");
con.log('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, 1, Array [2,3,4]\n",
test.assertEqual(lastPrint(), "info: " + name + ": testing 1 2,3,4\n",
"PlainTextConsole.log() must work.");
con.info('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "console.info: " + name + ": testing, 1, Array [2,3,4]\n",
test.assertEqual(lastPrint(), "info: " + name + ": testing 1 2,3,4\n",
"PlainTextConsole.info() must work.");
con.warn('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "console.warn: " + name + ": testing, 1, Array [2,3,4]\n",
test.assertEqual(lastPrint(), "warn: " + name + ": testing 1 2,3,4\n",
"PlainTextConsole.warn() must work.");
con.error('testing', 1, [2, 3, 4]);
test.assertEqual(prints[0], "console.error: " + name + ": \n",
test.assertEqual(lastPrint(), "error: " + name + ": testing 1 2,3,4\n",
"PlainTextConsole.error() must work.");
test.assertEqual(prints[1], " testing\n")
test.assertEqual(prints[2], " 1\n")
test.assertEqual(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n");
prints = [];
con.debug('testing', 1, [2, 3, 4]);
test.assertEqual(prints[0], "console.debug: " + name + ": \n",
test.assertEqual(lastPrint(), "debug: " + name + ": testing 1 2,3,4\n",
"PlainTextConsole.debug() must work.");
test.assertEqual(prints[1], " testing\n")
test.assertEqual(prints[2], " 1\n")
test.assertEqual(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n");
prints = [];
con.log('testing', undefined);
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, undefined\n",
test.assertEqual(lastPrint(), "info: " + name + ": testing undefined\n",
"PlainTextConsole.log() must stringify undefined.");
con.log('testing', null);
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, null\n",
test.assertEqual(lastPrint(), "info: " + name + ": testing null\n",
"PlainTextConsole.log() must stringify null.");
// TODO: Fix console.jsm to detect custom toString.
con.log("testing", { toString: function() "obj.toString()" });
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, {}\n",
"PlainTextConsole.log() doesn't printify custom toString.");
test.assertEqual(lastPrint(), "info: " + name + ": testing obj.toString()\n",
"PlainTextConsole.log() must stringify custom toString.");
con.log("testing", { toString: function() { throw "fail!"; } });
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, {}\n",
test.assertEqual(lastPrint(), "info: " + name + ": testing <toString() error>\n",
"PlainTextConsole.log() must stringify custom bad toString.");
con.exception(new Error("blah"));
test.assertEqual(prints[0], "console.error: " + name + ": \n");
let tbLines = prints[1].split("\n");
test.assertEqual(tbLines[0], " Message: Error: blah");
test.assertEqual(tbLines[1], " Stack:");
test.assert(prints[1].indexOf(module.uri + ":84") !== -1);
prints = []
var tbLines = prints[0].split("\n");
test.assertEqual(tbLines[0], "error: " + name + ": An exception occurred.");
test.assertEqual(tbLines[1], "Error: blah");
test.assertEqual(tbLines[2], module.uri + " 74");
test.assertEqual(tbLines[3], "Traceback (most recent call last):");
prints = [];
try {
loadSubScript("invalid-url", {});
test.fail("successed in calling loadSubScript with invalid-url");
@ -98,15 +87,16 @@ exports.testPlainTextConsole = function(test) {
catch(e) {
con.exception(e);
}
test.assertEqual(prints[0], "console.error: " + name + ": \n");
test.assertEqual(prints[1], " Error creating URI (invalid URL scheme?)\n");
prints = [];
var tbLines = prints[0].split("\n");
test.assertEqual(tbLines[0], "error: " + name + ": An exception occurred.");
test.assertEqual(tbLines[1], "Error creating URI (invalid URL scheme?)");
test.assertEqual(tbLines[2], "Traceback (most recent call last):");
con.trace();
let tbLines = prints[0].split("\n");
test.assertEqual(tbLines[0], "console.trace: " + name + ": ");
test.assert(tbLines[1].indexOf("_ain-text-console.js 105") == 0);
prints = [];
con.trace();
tbLines = prints[0].split("\n");
test.assertEqual(tbLines[0], "info: " + name + ": Traceback (most recent call last):");
test.assertEqual(tbLines[tbLines.length - 4].trim(), "con.trace();");
// Whether or not console methods should print at the various log levels,
// structured as a hash of levels, each of which contains a hash of methods,
@ -123,11 +113,11 @@ exports.testPlainTextConsole = function(test) {
// The messages we use to test the various methods, as a hash of methods.
let messages = {
debug: "console.debug: " + name + ": \n \n",
log: "console.log: " + name + ": \n",
info: "console.info: " + name + ": \n",
warn: "console.warn: " + name + ": \n",
error: "console.error: " + name + ": \n \n",
debug: "debug: " + name + ": \n",
log: "info: " + name + ": \n",
info: "info: " + name + ": \n",
warn: "warn: " + name + ": \n",
error: "error: " + name + ": \n",
};
for (let level in levels) {
@ -140,20 +130,17 @@ exports.testPlainTextConsole = function(test) {
prefs.set(SDK_LOG_LEVEL_PREF, level);
con[method]("");
prefs.set(SDK_LOG_LEVEL_PREF, "all");
test.assertEqual(prints.join(""),
(methods[method] ? messages[method] : ""),
test.assertEqual(lastPrint(), (methods[method] ? messages[method] : null),
"at log level '" + level + "', " + method + "() " +
(methods[method] ? "prints" : "doesn't print"));
prints = [];
}
}
prefs.set(SDK_LOG_LEVEL_PREF, "off");
prefs.set(ADDON_LOG_LEVEL_PREF, "all");
con.debug("");
test.assertEqual(prints.join(""), messages["debug"],
test.assertEqual(lastPrint(), messages["debug"],
"addon log level 'all' overrides SDK log level 'off'");
prints = [];
prefs.set(SDK_LOG_LEVEL_PREF, "all");
prefs.set(ADDON_LOG_LEVEL_PREF, "off");

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

@ -10,8 +10,6 @@ const { Loader, LoaderWithHookedConsole2 } = require("sdk/test/loader");
const nsIObserverService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let isConsoleEvent = (topic) =>
!!~["console-api-log-event", "console-storage-cache-event"].indexOf(topic)
exports["test basic"] = function(assert) {
let type = Date.now().toString(32);
@ -50,10 +48,10 @@ exports["test error reporting"] = function(assert) {
events.on(errorType, brokenHandler);
events.emit(errorType, { data: "yo yo" });
assert.equal(messages.length, 2, "Got an exception");
assert.equal(messages[0], "console.error: " + self.name + ": \n",
"error is logged");
let text = messages[1];
assert.equal(messages.length, 1, "Got an exception");
let text = messages[0];
assert.ok(text.indexOf(self.name + ": An exception occurred.") >= 0,
"error is logged");
assert.ok(text.indexOf("Error: foo") >= 0, "error message is logged");
assert.ok(text.indexOf(module.uri) >= 0, "module uri is logged");
assert.ok(text.indexOf(lineNumber) >= 0, "error line is logged");
@ -106,9 +104,6 @@ exports["test handle nsIObserverService notifications"] = function(assert) {
let lastType = null;
function handler({ subject, data, type }) {
// Ignores internal console events
if (isConsoleEvent(type))
return;
timesCalled++;
lastSubject = subject;
lastData = data;
@ -173,9 +168,6 @@ exports["test emit to nsIObserverService observers"] = function(assert) {
return nsIObserver;
},
observe: function(subject, topic, data) {
// Ignores internal console events
if (isConsoleEvent(topic))
return;
timesCalled = timesCalled + 1;
lastSubject = subject;
lastData = data;
@ -192,6 +184,7 @@ exports["test emit to nsIObserverService observers"] = function(assert) {
assert.equal(lastSubject.wrappedJSObject.object, uri,
"event.subject is notification subject");
assert.equal(lastData, "some data", "event.data is notification data");
function customSubject() {}
function customData() {}
events.emit(topic, { subject: customSubject, data: customData });
@ -213,14 +206,13 @@ exports["test emit to nsIObserverService observers"] = function(assert) {
events.emit(topic, { data: "data again" });
assert.equal(timesCalled, 3, "emit notifies * observers");
assert.equal(lastTopic, topic, "event.type is notification");
assert.equal(lastSubject, null,
"event.subject is notification subject");
assert.equal(lastData, "data again", "event.data is notification data");
nsIObserverService.removeObserver(nsIObserver, "*");
events.emit(topic, { data: "last data" });
assert.equal(timesCalled, 3, "removed observers no longer invoked");
}

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

@ -6,17 +6,33 @@ const { browserWindows } = require('sdk/windows');
const tabs = require('sdk/tabs');
const { pb } = require('./private-browsing/helper');
const { isPrivate } = require('sdk/private-browsing');
const { openTab, closeTab, getTabContentWindow, getOwnerWindow } = require('sdk/tabs/utils');
const { openTab, closeTab, getTabContentWindow } = require('sdk/tabs/utils');
const { open, close } = require('sdk/window/helpers');
const { windows } = require('sdk/window/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const { fromIterator } = require('sdk/util/array');
if (isWindowPBSupported) {
if (isGlobalPBSupported) {
exports.testGetTabs = function(assert, done) {
pb.once('start', function() {
tabs.open({
url: 'about:blank',
inNewWindow: true,
onOpen: function(tab) {
assert.equal(getTabs().length, 2, 'there are two tabs');
assert.equal(browserWindows.length, 2, 'there are two windows');
pb.once('stop', function() {
done();
});
pb.deactivate();
}
});
});
pb.activate();
};
}
else if (isWindowPBSupported) {
exports.testGetTabs = function(assert, done) {
let tabCount = getTabs().length;
let windowCount = browserWindows.length;
open(null, {
features: {
private: true,
@ -25,21 +41,12 @@ if (isWindowPBSupported) {
}
}).then(function(window) {
assert.ok(isPrivate(window), 'new tab is private');
assert.equal(getTabs().length, tabCount, 'there are no new tabs found');
getTabs().forEach(function(tab) {
assert.equal(isPrivate(tab), false, 'all found tabs are not private');
assert.equal(isPrivate(getOwnerWindow(tab)), false, 'all found tabs are not private');
assert.equal(isPrivate(getTabContentWindow(tab)), false, 'all found tabs are not private');
});
assert.equal(browserWindows.length, windowCount, 'there are no new windows found');
assert.equal(getTabs().length, 1, 'there is one tab found');
assert.equal(browserWindows.length, 1, 'there is one window found');
fromIterator(browserWindows).forEach(function(window) {
assert.equal(isPrivate(window), false, 'all found windows are not private');
assert.ok(!isPrivate(window), 'all found windows are not private');
});
assert.equal(windows(null, {includePrivate: true}).length, 2, 'there are really two windows');
close(window).then(done);
});
};
@ -64,4 +71,7 @@ else if (isTabPBSupported) {
};
}
// Test disabled because of bug 855771
module.exports = {};
require('test').run(exports);

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

@ -5,162 +5,116 @@
var timer = require("sdk/timers");
const { Loader } = require("sdk/test/loader");
exports.testSetTimeout = function(assert, end) {
exports.testSetTimeout = function(test) {
timer.setTimeout(function() {
assert.pass("testSetTimeout passed");
end();
test.pass("testSetTimeout passed");
test.done();
}, 1);
test.waitUntilDone();
};
exports.testParamedSetTimeout = function(assert, end) {
exports.testParamedSetTimeout = function(test) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
timer.setTimeout.apply(null, [function() {
assert.equal(arguments.length, params.length);
test.assertEqual(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
assert.equal(params[i], arguments[i]);
end();
test.assertEqual(params[i], arguments[i]);
test.done();
}, 1].concat(params));
test.waitUntilDone();
};
exports.testClearTimeout = function(assert, end) {
exports.testClearTimeout = function(test) {
var myFunc = function myFunc() {
assert.fail("myFunc() should not be called in testClearTimeout");
test.fail("myFunc() should not be called in testClearTimeout");
};
var id = timer.setTimeout(myFunc, 1);
timer.setTimeout(function() {
assert.pass("testClearTimeout passed");
end();
test.pass("testClearTimeout passed");
test.done();
}, 2);
timer.clearTimeout(id);
test.waitUntilDone();
};
exports.testParamedClearTimeout = function(assert, end) {
exports.testParamedClearTimeout = function(test) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
var myFunc = function myFunc() {
assert.fail("myFunc() should not be called in testClearTimeout");
test.fail("myFunc() should not be called in testClearTimeout");
};
var id = timer.setTimeout(myFunc, 1);
timer.setTimeout.apply(null, [function() {
assert.equal(arguments.length, params.length);
test.assertEqual(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
assert.equal(params[i], arguments[i]);
end();
test.assertEqual(params[i], arguments[i]);
test.done();
}, 1].concat(params));
timer.clearTimeout(id);
test.waitUntilDone();
};
exports.testSetInterval = function (assert, end) {
exports.testSetInterval = function (test) {
var count = 0;
var id = timer.setInterval(function () {
count++;
if (count >= 5) {
timer.clearInterval(id);
assert.pass("testSetInterval passed");
end();
test.pass("testSetInterval passed");
test.done();
}
}, 1);
test.waitUntilDone();
};
exports.testParamedSetInerval = function(assert, end) {
exports.testParamedSetInerval = function(test) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
let count = 0;
let id = timer.setInterval.apply(null, [function() {
count ++;
if (count < 5) {
assert.equal(arguments.length, params.length);
test.assertEqual(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
assert.equal(params[i], arguments[i]);
test.assertEqual(params[i], arguments[i]);
} else {
timer.clearInterval(id);
end();
test.done();
}
}, 1].concat(params));
test.waitUntilDone();
};
exports.testClearInterval = function (assert, end) {
exports.testClearInterval = function (test) {
timer.clearInterval(timer.setInterval(function () {
assert.fail("setInterval callback should not be called");
test.fail("setInterval callback should not be called");
}, 1));
var id = timer.setInterval(function () {
timer.clearInterval(id);
assert.pass("testClearInterval passed");
end();
test.pass("testClearInterval passed");
test.done();
}, 2);
test.waitUntilDone();
};
exports.testParamedClearInterval = function(assert, end) {
exports.testParamedClearInterval = function(test) {
timer.clearInterval(timer.setInterval(function () {
assert.fail("setInterval callback should not be called");
test.fail("setInterval callback should not be called");
}, 1, timer, {}, null));
let id = timer.setInterval(function() {
timer.clearInterval(id);
assert.equal(3, arguments.length);
end();
test.assertEqual(3, arguments.length);
test.done();
}, 2, undefined, 'test', {});
test.waitUntilDone();
};
exports.testImmediate = function(assert, end) {
let actual = [];
let ticks = 0;
timer.setImmediate(function(...params) {
actual.push(params);
assert.equal(ticks, 1, "is a next tick");
assert.deepEqual(actual, [["start", "immediates"]]);
}, "start", "immediates");
timer.setImmediate(function(...params) {
actual.push(params);
assert.deepEqual(actual, [["start", "immediates"],
["added"]]);
assert.equal(ticks, 1, "is a next tick");
timer.setImmediate(function(...params) {
actual.push(params);
assert.equal(ticks, 2, "is second tick");
assert.deepEqual(actual, [["start", "immediates"],
["added"],
[],
["last", "immediate", "handler"],
["side-effect"]]);
end();
}, "side-effect");
}, "added");
timer.setImmediate(function(...params) {
actual.push(params);
assert.equal(ticks, 1, "is a next tick");
assert.deepEqual(actual, [["start", "immediates"],
["added"],
[]]);
timer.clearImmediate(removeID);
});
function removed() {
assert.fail("should be removed");
}
let removeID = timer.setImmediate(removed);
timer.setImmediate(function(...params) {
actual.push(params);
assert.equal(ticks, 1, "is a next tick");
assert.deepEqual(actual, [["start", "immediates"],
["added"],
[],
["last", "immediate", "handler"]]);
ticks = ticks + 1;
}, "last", "immediate", "handler");
ticks = ticks + 1;
};
exports.testUnload = function(assert, end) {
exports.testUnload = function(test) {
var loader = Loader(module);
var sbtimer = loader.require("sdk/timers");
var myFunc = function myFunc() {
assert.fail("myFunc() should not be called in testUnload");
test.fail("myFunc() should not be called in testUnload");
};
sbtimer.setTimeout(myFunc, 1);
@ -169,9 +123,9 @@ exports.testUnload = function(assert, end) {
sbtimer.setInterval(myFunc, 1, {}, null, 'bar', undefined, 87);
loader.unload();
timer.setTimeout(function() {
assert.pass("timer testUnload passed");
end();
test.pass("timer testUnload passed");
test.done();
}, 2);
test.waitUntilDone();
};
require("test").run(exports);

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

@ -1,6 +1,7 @@
/* 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";
const { Loader } = require("sdk/test/loader");
@ -52,4 +53,4 @@ if (require("sdk/system/xul-app").is("Fennec")) {
}
}
require("sdk/test").run(exports);
require("test").run(exports);

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

@ -61,34 +61,6 @@ exports['test new top window with options'] = function(assert, done) {
close(window).then(done);
};
exports['test new top window with various URIs'] = function(assert, done) {
let msg = 'only chrome, resource and data uris are allowed';
assert.throws(function () {
open('foo');
}, msg);
assert.throws(function () {
open('http://foo');
}, msg);
assert.throws(function () {
open('https://foo');
}, msg);
assert.throws(function () {
open('ftp://foo');
}, msg);
assert.throws(function () {
open('//foo');
}, msg);
let chromeWindow = open('chrome://foo/content/');
assert.ok(~windows().indexOf(chromeWindow), 'chrome URI works');
let resourceWindow = open('resource://foo');
assert.ok(~windows().indexOf(resourceWindow), 'resource URI works');
// Wait for the window unload before ending test
close(chromeWindow).then(close.bind(null, resourceWindow)).then(done);
};
exports.testBackgroundify = function(assert, done) {
let window = open('data:text/html;charset=utf-8,backgroundy');
assert.ok(~windows().indexOf(window),

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

@ -177,6 +177,8 @@ pref("content.sink.perf_parse_time", 50000000);
// Maximum scripts runtime before showing an alert
pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
// Disable the watchdog thread for B2G. See bug 870043 comment 31.
pref("dom.use_watchdog", false);
// plugins
pref("plugin.disable", true);

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

@ -538,8 +538,10 @@ function setupBracketCompletion(sourceEditor)
let utils = editorElement.ownerDocument.defaultView.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
let handled = utils.sendKeyEvent("keydown", keyCode, 0, modifiers);
utils.sendKeyEvent("keypress", 0, charCode, modifiers, !handled);
if (utils.sendKeyEvent("keydown", keyCode, 0, modifiers)) {
utils.sendKeyEvent("keypress", 0, charCode, modifiers);
}
utils.sendKeyEvent("keyup", keyCode, 0, modifiers);
// and rewind caret
sourceEditor.setCaretOffset(sourceEditor.getCaretOffset() - 1);

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

@ -1227,7 +1227,6 @@ TiltVisualizer.Controller.prototype = {
canvas.addEventListener("MozMousePixelScroll", this._onMozScroll, false);
canvas.addEventListener("keydown", this._onKeyDown, false);
canvas.addEventListener("keyup", this._onKeyUp, false);
canvas.addEventListener("keypress", this._onKeyPress, true);
canvas.addEventListener("blur", this._onBlur, false);
// handle resize events to change the arcball dimensions
@ -1250,7 +1249,6 @@ TiltVisualizer.Controller.prototype = {
canvas.removeEventListener("MozMousePixelScroll", this._onMozScroll, false);
canvas.removeEventListener("keydown", this._onKeyDown, false);
canvas.removeEventListener("keyup", this._onKeyUp, false);
canvas.removeEventListener("keypress", this._onKeyPress, true);
canvas.removeEventListener("blur", this._onBlur, false);
// Closing the tab would result in contentWindow being a dead object,
@ -1392,6 +1390,15 @@ TiltVisualizer.Controller.prototype = {
} else {
this.arcball.cancelKeyEvents();
}
if (e.keyCode === e.DOM_VK_ESCAPE) {
let {TiltManager} = require("devtools/tilt/tilt");
let tilt =
TiltManager.getTiltForBrowser(this.presenter.chromeWindow);
e.preventDefault();
e.stopPropagation();
tilt.destroy(tilt.currentWindowId, true);
}
},
/**
@ -1419,21 +1426,6 @@ TiltVisualizer.Controller.prototype = {
}
},
/**
* Called when a key is pressed.
*/
_onKeyPress: function TVC__onKeyPress(e)
{
if (e.keyCode === e.DOM_VK_ESCAPE) {
let {TiltManager} = require("devtools/tilt/tilt");
let tilt =
TiltManager.getTiltForBrowser(this.presenter.chromeWindow);
e.preventDefault();
e.stopPropagation();
tilt.destroy(tilt.currentWindowId, true);
}
},
/**
* Called when the canvas looses focus.
*/

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

@ -267,8 +267,6 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
// fire a MozContextActionsChange event to update the context appbar
let event = document.createEvent("Events");
event.actions = [...nextContextActions];
event.noun = tileGroup.contextNoun;
event.qty = selectedTiles.length;
event.initEvent("MozContextActionsChange", true, false);
tileGroup.dispatchEvent(event);
},0);

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

@ -45,10 +45,9 @@ var Appbar = {
case 'MozContextActionsChange':
let actions = aEvent.actions;
let noun = aEvent.noun;
let qty = aEvent.qty;
let setName = aEvent.target.contextSetName;
// could transition in old, new buttons?
this.showContextualActions(actions, noun, qty);
this.showContextualActions(actions, setName);
break;
case "selectionchange":
@ -161,14 +160,15 @@ var Appbar = {
}
},
showContextualActions: function(aVerbs, aNoun, aQty) {
showContextualActions: function(aVerbs, aSetName) {
// When the appbar is not visible, we want the icons to refresh right away
let immediate = !Elements.contextappbar.isShowing;
if (aVerbs.length)
if (aVerbs.length) {
Elements.contextappbar.show();
else
} else {
Elements.contextappbar.hide();
}
// Look up all of the buttons for the verbs that should be visible.
let idsToVisibleVerbs = new Map();
@ -187,7 +187,7 @@ var Appbar = {
let verb = idsToVisibleVerbs.get(button.id);
if (verb != undefined) {
// Button should be visible, and may or may not be showing.
this._updateContextualActionLabel(button, verb, aNoun, aQty);
this._updateContextualActionLabel(button, verb, aSetName);
if (button.hidden) {
toShow.push(button);
}
@ -223,18 +223,12 @@ var Appbar = {
this.showContextualActions([]);
},
_updateContextualActionLabel: function(aBtnNode, aVerb, aNoun, aQty) {
// True if action modifies the noun for the grid (bookmark, top site, etc.),
// causing the label to be pluralized by the number of selected items.
let modifiesNoun = aBtnNode.getAttribute("modifies-noun") == "true";
if (modifiesNoun && (!aNoun || isNaN(aQty))) {
throw new Error("Appbar._updateContextualActionLabel: " +
"missing noun/quantity for " + aVerb);
}
let labelName = "contextAppbar." + aVerb + (modifiesNoun ? "." + aNoun : "");
let label = Strings.browser.GetStringFromName(labelName);
aBtnNode.label = modifiesNoun ? PluralForm.get(aQty, label) : label;
_updateContextualActionLabel: function(aButton, aVerb, aSetName) {
// True if the action's label string contains the set name and
// thus has to be selected based on the list passed in.
let usesSetName = aButton.hasAttribute("label-uses-set-name");
let name = "contextAppbar2." + aVerb + (usesSetName ? "." + aSetName : "");
aButton.label = Strings.browser.GetStringFromName(name);
},
_onTileSelectionChanged: function _onTileSelectionChanged(aEvent){
@ -255,10 +249,8 @@ var Appbar = {
// fire event with these verbs as payload
let event = document.createEvent("Events");
event.actions = verbs;
event.noun = activeTileset.contextNoun;
event.qty = activeTileset.selectedItems.length;
event.initEvent("MozContextActionsChange", true, false);
Elements.contextappbar.dispatchEvent(event);
activeTileset.dispatchEvent(event);
if (verbs.length) {
Elements.contextappbar.show(); // should be no-op if we're already showing

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

@ -121,8 +121,8 @@
</body>
</method>
<property name="contextNoun" readonly="true"
onget="return this.getAttribute('noun');"/>
<property name="contextSetName" readonly="true"
onget="return this.getAttribute('set-name');"/>
<property name="contextActions">
<getter>

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

@ -294,8 +294,6 @@ BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
let event = document.createEvent("Events");
// we need the restore button to show (the tile node will go away though)
event.actions = ["restore"];
event.noun = tileGroup.contextNoun;
event.qty = selectedTiles.length;
event.initEvent("MozContextActionsChange", true, false);
tileGroup.dispatchEvent(event);
}, 0);

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

@ -196,31 +196,31 @@
<scrollbox id="start-scrollbox" observes="bcast_preciseInput" flex="1">
<vbox id="start-topsites" class="meta-section">
<label class="meta-section-title wide-title" value="&startTopSitesHeader.label;"/>
<label class="meta-section-title wide-title" value="&topSitesHeader.label;"/>
<label class="meta-section-title narrow-title" value="&snappedTopSitesHeader.label;"
onclick="StartUI.onNarrowTitleClick('start-topsites-grid')"/>
<richgrid id="start-topsites-grid" noun="topsite" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1" expanded="true"/>
<richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1" expanded="true"/>
</vbox>
<vbox id="start-bookmarks" class="meta-section">
<label class="meta-section-title wide-title" value="&startBookmarksHeader.label;"/>
<label class="meta-section-title wide-title" value="&bookmarksHeader.label;"/>
<label class="meta-section-title narrow-title" value="&snappedBookmarksHeader.label;"
onclick="StartUI.onNarrowTitleClick('start-bookmarks-grid')"/>
<richgrid id="start-bookmarks-grid" noun="bookmark" seltype="multiple" flex="1"/>
<richgrid id="start-bookmarks-grid" set-name="bookmarks" seltype="multiple" flex="1"/>
</vbox>
<vbox id="start-history" class="meta-section">
<label class="meta-section-title wide-title" value="&startHistoryHeader.label;"/>
<label class="meta-section-title narrow-title" value="&snappedHistoryHeader.label;"
<label class="meta-section-title wide-title" value="&recentHistoryHeader.label;"/>
<label class="meta-section-title narrow-title" value="&snappedRecentHistoryHeader.label;"
onclick="StartUI.onNarrowTitleClick('start-history-grid')"/>
<richgrid id="start-history-grid" noun="history" seltype="multiple" flex="1"/>
<richgrid id="start-history-grid" set-name="recentHistory" seltype="multiple" flex="1"/>
</vbox>
<vbox id="start-remotetabs" class="meta-section">
<label class="meta-section-title wide-title" value="&startRemoteTabsHeader.label;"/>
<label class="meta-section-title wide-title" value="&remoteTabsHeader.label;"/>
<label id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" value="&snappedRemoteTabsHeader.label;"
onclick="StartUI.onNarrowTitleClick('start-remotetabs-grid')"/>
<richgrid id="start-remotetabs-grid" noun="tab" seltype="multiple" flex="1"/>
<richgrid id="start-remotetabs-grid" set-name="remoteTabs" seltype="multiple" flex="1"/>
</vbox>
<!-- Spacer to take extra space in snapped mode. -->
@ -311,16 +311,16 @@
<deck id="panel-items" selectedIndex="0" flex="1" >
<scrollbox id="bookmarks-container" flex="1">
<richgrid id="bookmarks-list" noun="bookmark" class="canSnapTiles"
seltype="multiple" flex="1"/>
<richgrid id="bookmarks-list" class="canSnapTiles"
set-name="bookmarks" seltype="multiple" flex="1"/>
</scrollbox>
<scrollbox id="history-container" flex="1">
<richgrid id="history-list" noun="history" class="canSnapTiles"
seltype="multiple" flex="1"/>
<richgrid id="history-list" class="canSnapTiles"
set-name="recentHistory" seltype="multiple" flex="1"/>
</scrollbox>
<scrollbox id="remotetabs-container" flex="1">
<richgrid id="remotetabs-list" noun="tab" class="canSnapTiles"
seltype="single" flex="1"/>
<richgrid id="remotetabs-list" class="canSnapTiles"
set-name="remoteTabs" seltype="single" flex="1"/>
</scrollbox>
<vbox id="console-container" flex="1">
<vbox id="console-header" class="panel-list">
@ -374,18 +374,18 @@
<!-- Context button bar -->
<appbar id="contextappbar">
<toolbar id="contextualactions-tray" labelled="true" flex="1">
<toolbarbutton id="delete-selected-button" class="appbar-secondary"
modifies-noun="true" hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('delete')"/>
<toolbarbutton id="restore-selected-button" class="appbar-secondary"
modifies-noun="true" hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('restore')"/>
<toolbarbutton id="pin-selected-button" class="appbar-secondary"
modifies-noun="true" hidden="true" fade="true"
label-uses-set-name="true" hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('pin')"/>
<toolbarbutton id="unpin-selected-button" class="appbar-secondary"
modifies-noun="true" hidden="true" fade="true"
label-uses-set-name="true" hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('unpin')"/>
<toolbarbutton id="delete-selected-button" class="appbar-secondary"
hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('delete')"/>
<toolbarbutton id="restore-selected-button" class="appbar-secondary"
hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('restore')"/>
<toolbarbutton id="clear-selected-button" class="appbar-secondary"
hidden="true" fade="true"
oncommand="Appbar.dispatchContextualAction('clear')"/>

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

@ -148,8 +148,6 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
let event = document.createEvent("Events");
// we need the restore button to show (the tile node will go away though)
event.actions = ["restore"];
event.noun = tileGroup.contextNoun;
event.qty = selectedTiles.length;
event.initEvent("MozContextActionsChange", true, false);
tileGroup.dispatchEvent(event);
}, 0);

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

@ -2,6 +2,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/. -->
<!-- NAVBAR AND AUTOCOMPLETE -->
<!ENTITY urlbar.emptytext "Enter Search or Address">
<!ENTITY urlbar.accesskey "d">
@ -10,15 +12,18 @@
<!ENTITY newtab.label "New Tab">
<!ENTITY closetab.label "Close Tab">
<!ENTITY autocompleteResultsHeader.label "Your Results">
<!ENTITY autocompleteSearchesHeader.label "Internet Searches">
<!ENTITY appbarErrorConsole.label "Open error console">
<!ENTITY appbarJSShell.label "Open JavaScript shell">
<!ENTITY appbarFindInPage2.label "Find in page">
<!ENTITY appbarViewOnDesktop2.label "View on desktop">
<!ENTITY startTopSitesHeader.label "Top Sites">
<!ENTITY startBookmarksHeader.label "Bookmarks">
<!ENTITY startHistoryHeader.label "Recent History">
<!ENTITY startRemoteTabsHeader.label "Tabs from Other Devices">
<!ENTITY topSitesHeader.label "Top Sites">
<!ENTITY bookmarksHeader.label "Bookmarks">
<!ENTITY recentHistoryHeader.label "Recent History">
<!ENTITY remoteTabsHeader.label "Tabs from Other Devices">
<!-- LOCALIZATION NOTE (snappedRemoteTabsHeader.label): shortened version of startRemoteTabsHeader.label.
Needs to be two words or shorter to fit in narrow vertical space.-->
@ -29,12 +34,9 @@
The '>' character is not part of the name, but is an indicator of more content. Please do not localize the '>' -->
<!ENTITY snappedRemoteTabsHeader.label "Remote Tabs >">
<!ENTITY snappedBookmarksHeader.label "Bookmarks >">
<!ENTITY snappedHistoryHeader.label "Recent History >">
<!ENTITY snappedRecentHistoryHeader.label "Recent History >">
<!ENTITY snappedTopSitesHeader.label "Top Sites >">
<!ENTITY autocompleteResultsHeader.label "Your Results">
<!ENTITY autocompleteSearchesHeader.label "Internet Searches">
<!ENTITY downloadsHeader.label "Downloads">
<!ENTITY downloadShowPage.label "Go to Page">
<!ENTITY downloadShow2.label "Find">
@ -47,7 +49,6 @@
<!ENTITY downloadDelete.label "Delete">
<!ENTITY downloadFailed.label "Failed">
<!ENTITY bookmarksHeader.label "Bookmarks">
<!ENTITY allBookmarks.label "See all bookmarks">
<!ENTITY consoleHeader.label "Error Console">

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

@ -2,6 +2,13 @@
# 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/.
# LOCALIZATION NOTE : FILE Capitalized phrases like "Top Sites", "Bookmarks",
# and "Recent History" are typically used as proper noun phrases to refer to
# the specific visual set (usually displayed as a grid) of top sites,
# bookmarks, etc. displayed on screen, rather than those concepts in general.
# Buttons (like with contextAppbar2.pin.topSites) refer to actions against
# the specific on-screen sets with similarly-named headings.
# Default search engine
browser.search.defaultenginename=Bing
@ -14,32 +21,27 @@ browser.search.order.3=Yahoo
# menu item text will be: |Search (browser.search.defaultenginename) for "string"|
browser.search.contextTextSearchLabel2=Search %S for "%S"
# Contextual Appbar - button labels
# LOCALIZATION NOTE: All of the following represent actions that can be done
# to items (top sites, bookmarks, history items) that are selected by the user
# on the start screen. Each string is a semicolon list of plural forms.
contextAppbar.delete.topsite=Delete top site;Delete top sites
contextAppbar.restore.topsite=Restore top site;Restore top sites
contextAppbar.pin.topsite=Pin top site;Pin top sites
contextAppbar.unpin.topsite=Unpin top site;Unpin top sites
contextAppbar.delete.bookmark=Delete bookmark;Delete bookmarks
contextAppbar.restore.bookmark=Restore bookmark;Restore bookmarks
contextAppbar.pin.bookmark=Pin bookmark;Pin bookmarks
contextAppbar.unpin.bookmark=Unpin bookmark;Unpin bookmarks
contextAppbar.delete.history=Delete page;Delete pages
contextAppbar.restore.history=Restore page;Restore pages
contextAppbar.pin.history=Pin page;Pin pages
contextAppbar.unpin.history=Unpin page;Unpin pages
contextAppbar.delete.tab=Delete tab;Delete tabs
contextAppbar.restore.tab=Restore tab;Restore tabs
contextAppbar.pin.tab=Pin tab;Pin tabs
contextAppbar.unpin.tab=Unpin page;Unpin tabs
contextAppbar.delete.download=Delete download;Delete downloads
contextAppbar.restore.download=Restore download;Restore downloads
contextAppbar.pin.download=Pin download;Pin downloads
contextAppbar.unpin.download=Unpin page;Unpin downloads
# LOCALIZATION NOTE (contextAppbar.clear): Unselects items without modification.
contextAppbar.clear=Clear selection
# Contextual Appbar - Button Labels
contextAppbar2.pin.topSites=Pin to Top Sites
contextAppbar2.pin.bookmarks=Pin to Bookmarks
contextAppbar2.pin.recentHistory=Pin to Recent History
contextAppbar2.pin.downloads=Pin to Downloads
contextAppbar2.unpin.topSites=Unpin from Top Sites
contextAppbar2.unpin.bookmarks=Unpin from Bookmarks
contextAppbar2.unpin.recentHistory=Unpin from Recent History
contextAppbar2.unpin.downloads=Unpin from Downloads
# LOCALIZATION NOTE (contextAppbar2.delete): Deletes selected pages.
contextAppbar2.delete=Delete
# LOCALIZATION NOTE (contextAppbar2.restore): Undoes a previous deletion.
# Button with this label only appears immediately after a deletion.
contextAppbar2.restore=Undo delete
# LOCALIZATION NOTE (contextAppbar2.clear): Unselects pages without modification.
contextAppbar2.clear=Clear selection
# Settings Charms
aboutCharm1=About

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

@ -8150,7 +8150,11 @@ if test "${OS_TARGET}" = "WINNT"; then
fi
fi
if test "${OS_TARGET}" = "WINNT" -o "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android" -o "${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then
if test "${OS_TARGET}" = "WINNT" -o \
"${OS_ARCH}" = "Darwin" -o \
"${MOZ_WIDGET_TOOLKIT}" = "android" -o \
"${MOZ_WIDGET_TOOLKIT}" = "gonk" -o \
"${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then
case "${target_cpu}" in
i*86*|x86_64|arm)
MOZ_ENABLE_SKIA=1

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

@ -273,7 +273,10 @@ function testSynthesizedKeyLocation()
is(aEvent.location, currentTest.event.location,
description + "location of " + aEvent.type + " was invalid");
events[aEvent.type] = true;
aEvent.preventDefault();
if (aEvent.type != "keydown" ||
(currentTest.event.isModifier && aEvent.type == "keydown")) {
aEvent.preventDefault();
}
}
window.addEventListener("keydown", handler, true);

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

@ -4,7 +4,7 @@
* 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 "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
#include "MediaDecoderReader.h"
#include "AbstractMediaDecoder.h"
#include "MediaDecoderStateMachine.h"
@ -348,16 +348,16 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
aTimecode,
aInfo.mDisplay));
ImageFormat format = GONK_IO_SURFACE;
ImageFormat format = GRALLOC_PLANAR_YCBCR;
v->mImage = aContainer->CreateImage(&format, 1);
if (!v->mImage) {
return nullptr;
}
NS_ASSERTION(v->mImage->GetFormat() == GONK_IO_SURFACE,
NS_ASSERTION(v->mImage->GetFormat() == GRALLOC_PLANAR_YCBCR,
"Wrong format?");
typedef mozilla::layers::GonkIOSurfaceImage GonkIOSurfaceImage;
GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(v->mImage.get());
GonkIOSurfaceImage::Data data;
typedef mozilla::layers::GrallocImage GrallocImage;
GrallocImage* videoImage = static_cast<GrallocImage*>(v->mImage.get());
GrallocImage::GrallocData data;
data.mPicSize = gfxIntSize(aPicture.width, aPicture.height);
data.mGraphicBuffer = aBuffer;

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

@ -7,7 +7,7 @@
#define MPAPI_h_
#include <stdint.h>
#include "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
namespace MPAPI {

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

@ -8,7 +8,7 @@
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
#include "MPAPI.h"
#include "MediaResource.h"
#include "AbstractMediaDecoder.h"

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

@ -282,8 +282,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginElement)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPluginElement,
mMimeTypes)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPluginElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
// Invalidate before we unlink mMimeTypes
tmp->Invalidate();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMimeTypes)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPluginElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsPluginElement)
nsPluginElement::nsPluginElement(nsWeakPtr aWindow,
nsPluginTag* aPluginTag)
@ -295,9 +303,7 @@ nsPluginElement::nsPluginElement(nsWeakPtr aWindow,
nsPluginElement::~nsPluginElement()
{
for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
mMimeTypes[i]->Invalidate();
}
Invalidate();
}
nsPIDOMWindow*
@ -419,3 +425,11 @@ nsPluginElement::EnsureMimeTypes()
mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type));
}
}
void
nsPluginElement::Invalidate()
{
for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
mMimeTypes[i]->Invalidate();
}
}

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

@ -102,6 +102,7 @@ public:
protected:
void EnsureMimeTypes();
void Invalidate();
nsWeakPtr mWindow;
nsRefPtr<nsPluginTag> mPluginTag;

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

@ -216,6 +216,9 @@ const ContentPanning = {
}
this._finishPanning();
// Now that we're done, avoid entraining the thing we just panned.
this.pointerDownTarget = null;
},
// True when there's an async pan-zoom controll watching the

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

@ -1486,8 +1486,8 @@ GonkFrameBuilder(Image* aImage, void* aBuffer, uint32_t aWidth, uint32_t aHeight
* Cast the generic Image back to our platform-specific type and
* populate it.
*/
GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(aImage);
GonkIOSurfaceImage::Data data;
GrallocImage* videoImage = static_cast<GrallocImage*>(aImage);
GrallocImage::GrallocData data;
data.mGraphicBuffer = static_cast<layers::GraphicBufferLocked*>(aBuffer);
data.mPicSize = gfxIntSize(aWidth, aHeight);
videoImage->SetData(data);
@ -1496,7 +1496,7 @@ GonkFrameBuilder(Image* aImage, void* aBuffer, uint32_t aWidth, uint32_t aHeight
void
ReceiveFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer)
{
if (!gc->ReceiveFrame(aBuffer, ImageFormat::GONK_IO_SURFACE, GonkFrameBuilder)) {
if (!gc->ReceiveFrame(aBuffer, ImageFormat::GRALLOC_PLANAR_YCBCR, GonkFrameBuilder)) {
aBuffer->Unlock();
}
}

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

@ -32,7 +32,7 @@
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
#include "CameraCommon.h"
namespace android {

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

@ -1,164 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GonkIOSurfaceImage.h"
#include <OMX_IVCommon.h>
#include <ColorConverter.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
#define ALIGN(x, align) ((x + align - 1) & ~(align - 1))
typedef android::GraphicBuffer GraphicBuffer;
namespace mozilla {
namespace layers {
uint32_t GonkIOSurfaceImage::sColorIdMap[] = {
HAL_PIXEL_FORMAT_YCbCr_420_P, OMX_COLOR_FormatYUV420Planar,
HAL_PIXEL_FORMAT_YCbCr_422_P, OMX_COLOR_FormatYUV422Planar,
HAL_PIXEL_FORMAT_YCbCr_420_SP, OMX_COLOR_FormatYUV420SemiPlanar,
HAL_PIXEL_FORMAT_YCrCb_420_SP, -1,
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO, -1,
HAL_PIXEL_FORMAT_YV12, OMX_COLOR_FormatYUV420Planar,
0, 0
};
struct GraphicBufferAutoUnlock {
android::sp<GraphicBuffer> mGraphicBuffer;
GraphicBufferAutoUnlock(android::sp<GraphicBuffer>& aGraphicBuffer)
: mGraphicBuffer(aGraphicBuffer) { }
~GraphicBufferAutoUnlock() { mGraphicBuffer->unlock(); }
};
/**
* Converts YVU420 semi planar frames to RGB565, possibly taking different
* stride values.
* Needed because the Android ColorConverter class assumes that the Y and UV
* channels have equal stride.
*/
static void
ConvertYVU420SPToRGB565(void *aYData, uint32_t aYStride,
void *aUVData, uint32_t aUVStride,
void *aOut,
uint32_t aWidth, uint32_t aHeight)
{
uint8_t *y = (uint8_t*)aYData;
int8_t *uv = (int8_t*)aUVData;
uint16_t *rgb = (uint16_t*)aOut;
for (size_t i = 0; i < aHeight; i++) {
for (size_t j = 0; j < aWidth; j++) {
int8_t d = uv[j | 1] - 128;
int8_t e = uv[j & ~1] - 128;
// Constants taken from https://en.wikipedia.org/wiki/YUV
int32_t r = (298 * y[j] + 409 * e + 128) >> 11;
int32_t g = (298 * y[j] - 100 * d - 208 * e + 128) >> 10;
int32_t b = (298 * y[j] + 516 * d + 128) >> 11;
r = r > 0x1f ? 0x1f : r < 0 ? 0 : r;
g = g > 0x3f ? 0x3f : g < 0 ? 0 : g;
b = b > 0x1f ? 0x1f : b < 0 ? 0 : b;
*rgb++ = (uint16_t)(r << 11 | g << 5 | b);
}
y += aYStride;
if (i % 2) {
uv += aUVStride;
}
}
}
already_AddRefed<gfxASurface>
GonkIOSurfaceImage::GetAsSurface()
{
android::sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(GetSurfaceDescriptor());
void *buffer;
int32_t rv =
graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN, &buffer);
if (rv) {
NS_WARNING("Couldn't lock graphic buffer");
return nullptr;
}
GraphicBufferAutoUnlock unlock(graphicBuffer);
uint32_t format = graphicBuffer->getPixelFormat();
uint32_t omxFormat = 0;
for (int i = 0; sColorIdMap[i]; i += 2) {
if (sColorIdMap[i] == format) {
omxFormat = sColorIdMap[i + 1];
break;
}
}
if (!omxFormat) {
NS_WARNING("Unknown color format");
return nullptr;
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(GetSize(), gfxASurface::ImageFormatRGB16_565);
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;
if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO) {
// The Adreno hardware decoder aligns image dimensions to a multiple of 32,
// so we have to account for that here
uint32_t alignedWidth = ALIGN(width, 32);
uint32_t alignedHeight = ALIGN(height, 32);
uint32_t uvOffset = ALIGN(alignedHeight * alignedWidth, 4096);
uint32_t uvStride = 2 * ALIGN(width / 2, 32);
uint8_t* buffer_as_bytes = static_cast<uint8_t*>(buffer);
ConvertYVU420SPToRGB565(buffer, alignedWidth,
buffer_as_bytes + uvOffset, uvStride,
imageSurface->Data(),
width, height);
return imageSurface.forget();
}
else if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
uint32_t uvOffset = height * width;
ConvertYVU420SPToRGB565(buffer, width,
buffer + uvOffset, width,
imageSurface->Data(),
width, height);
return imageSurface.forget();
}
android::ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)omxFormat,
OMX_COLOR_Format16bitRGB565);
if (!colorConverter.isValid()) {
NS_WARNING("Invalid color conversion");
return nullptr;
}
rv = colorConverter.convert(buffer, width, height,
0, 0, width - 1, height - 1 /* source crop */,
imageSurface->Data(), width, height,
0, 0, width - 1, height - 1 /* dest crop */);
if (rv) {
NS_WARNING("OMX color conversion failed");
return nullptr;
}
return imageSurface.forget();
}
} // namespace layers
} // namespace mozilla

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

@ -1,112 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GONKIOSURFACEIMAGE_H
#define GONKIOSURFACEIMAGE_H
#ifdef MOZ_WIDGET_GONK
#include "mozilla/layers/LayersSurfaces.h"
#include "ImageContainer.h"
#include <ui/GraphicBuffer.h>
namespace mozilla {
namespace layers {
/**
* The gralloc buffer maintained by android GraphicBuffer can be
* shared between the compositor thread and the producer thread. The
* mGraphicBuffer is owned by the producer thread, but when it is
* wrapped by GraphicBufferLocked and passed to the compositor, the
* buffer content is guaranteed to not change until Unlock() is
* called. Each producer must maintain their own buffer queue and
* implement the GraphicBufferLocked::Unlock() interface.
*/
class GraphicBufferLocked {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphicBufferLocked)
public:
GraphicBufferLocked(SurfaceDescriptor aGraphicBuffer)
: mSurfaceDescriptor(aGraphicBuffer)
{}
virtual ~GraphicBufferLocked() {}
virtual void Unlock() {}
SurfaceDescriptor GetSurfaceDescriptor()
{
return mSurfaceDescriptor;
}
protected:
SurfaceDescriptor mSurfaceDescriptor;
};
class GonkIOSurfaceImage : public Image {
typedef android::GraphicBuffer GraphicBuffer;
static uint32_t sColorIdMap[];
public:
struct Data {
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
gfxIntSize mPicSize;
};
GonkIOSurfaceImage()
: Image(nullptr, GONK_IO_SURFACE)
, mSize(0, 0)
{}
virtual ~GonkIOSurfaceImage()
{
mGraphicBuffer->Unlock();
}
virtual void SetData(const Data& aData)
{
mGraphicBuffer = aData.mGraphicBuffer;
mSize = aData.mPicSize;
}
virtual gfxIntSize GetSize()
{
return mSize;
}
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
enum {
/* OEM specific HAL formats */
HAL_PIXEL_FORMAT_YCbCr_422_P = 0x102,
HAL_PIXEL_FORMAT_YCbCr_420_P = 0x103,
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A,
};
enum {
OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
};
virtual already_AddRefed<gfxASurface> GetAsSurface();
void* GetNativeBuffer()
{
return GrallocBufferActor::GetFrom(GetSurfaceDescriptor())->getNativeBuffer();
}
SurfaceDescriptor GetSurfaceDescriptor()
{
return mGraphicBuffer->GetSurfaceDescriptor();
}
private:
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
gfxIntSize mSize;
};
} // namespace layers
} // namespace mozilla
#endif
#endif /* GONKIOSURFACEIMAGE_H */

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

@ -10,26 +10,58 @@
#include "ImageContainer.h"
#include "GrallocImages.h"
#include <OMX_IVCommon.h>
#include <ColorConverter.h>
using namespace mozilla::ipc;
using namespace android;
#define ALIGN(x, align) ((x + align - 1) & ~(align - 1))
namespace mozilla {
namespace layers {
GrallocPlanarYCbCrImage::GrallocPlanarYCbCrImage()
: PlanarYCbCrImage(nullptr)
uint32_t GrallocImage::sColorIdMap[] = {
HAL_PIXEL_FORMAT_YCbCr_420_P, OMX_COLOR_FormatYUV420Planar,
HAL_PIXEL_FORMAT_YCbCr_422_P, OMX_COLOR_FormatYUV422Planar,
HAL_PIXEL_FORMAT_YCbCr_420_SP, OMX_COLOR_FormatYUV420SemiPlanar,
HAL_PIXEL_FORMAT_YCrCb_420_SP, -1,
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO, -1,
HAL_PIXEL_FORMAT_YV12, OMX_COLOR_FormatYUV420Planar,
0, 0
};
struct GraphicBufferAutoUnlock {
android::sp<GraphicBuffer> mGraphicBuffer;
GraphicBufferAutoUnlock(android::sp<GraphicBuffer>& aGraphicBuffer)
: mGraphicBuffer(aGraphicBuffer) { }
~GraphicBufferAutoUnlock() { mGraphicBuffer->unlock(); }
};
GrallocImage::GrallocImage()
: PlanarYCbCrImage(nullptr),
mBufferAllocated(false),
mGraphicBuffer(nullptr)
{
mFormat = GRALLOC_PLANAR_YCBCR;
}
GrallocPlanarYCbCrImage::~GrallocPlanarYCbCrImage()
GrallocImage::~GrallocImage()
{
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
if (mGraphicBuffer.get()) {
mGraphicBuffer->Unlock();
if (mBufferAllocated) {
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
ibc->DeallocSurfaceDescriptorGralloc(mGraphicBuffer->GetSurfaceDescriptor());
mBufferAllocated = false;
}
}
}
void
GrallocPlanarYCbCrImage::SetData(const Data& aData)
GrallocImage::SetData(const Data& aData)
{
NS_PRECONDITION(aData.mYSize.width % 2 == 0, "Image should have even width");
NS_PRECONDITION(aData.mYSize.height % 2 == 0, "Image should have even height");
@ -38,17 +70,23 @@ GrallocPlanarYCbCrImage::SetData(const Data& aData)
mData = aData;
mSize = aData.mPicSize;
if (mSurfaceDescriptor.type() == SurfaceDescriptor::T__None) {
if (!mGraphicBuffer.get()) {
SurfaceDescriptor desc;
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
ibc->AllocSurfaceDescriptorGralloc(aData.mYSize,
HAL_PIXEL_FORMAT_YV12,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE,
&mSurfaceDescriptor);
&desc);
mBufferAllocated = true;
mGraphicBuffer = new GraphicBufferLocked(desc);
}
sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(mSurfaceDescriptor.get_SurfaceDescriptorGralloc());
GrallocBufferActor::GetFrom(
mGraphicBuffer->GetSurfaceDescriptor().get_SurfaceDescriptorGralloc());
if (!graphicBuffer.get()) {
return;
}
@ -104,5 +142,136 @@ GrallocPlanarYCbCrImage::SetData(const Data& aData)
graphicBuffer->unlock();
}
void GrallocImage::SetData(const GrallocData& aData)
{
mGraphicBuffer = aData.mGraphicBuffer;
mSize = aData.mPicSize;
}
/**
* Converts YVU420 semi planar frames to RGB565, possibly taking different
* stride values.
* Needed because the Android ColorConverter class assumes that the Y and UV
* channels have equal stride.
*/
static void
ConvertYVU420SPToRGB565(void *aYData, uint32_t aYStride,
void *aUVData, uint32_t aUVStride,
void *aOut,
uint32_t aWidth, uint32_t aHeight)
{
uint8_t *y = (uint8_t*)aYData;
int8_t *uv = (int8_t*)aUVData;
uint16_t *rgb = (uint16_t*)aOut;
for (size_t i = 0; i < aHeight; i++) {
for (size_t j = 0; j < aWidth; j++) {
int8_t d = uv[j | 1] - 128;
int8_t e = uv[j & ~1] - 128;
// Constants taken from https://en.wikipedia.org/wiki/YUV
int32_t r = (298 * y[j] + 409 * e + 128) >> 11;
int32_t g = (298 * y[j] - 100 * d - 208 * e + 128) >> 10;
int32_t b = (298 * y[j] + 516 * d + 128) >> 11;
r = r > 0x1f ? 0x1f : r < 0 ? 0 : r;
g = g > 0x3f ? 0x3f : g < 0 ? 0 : g;
b = b > 0x1f ? 0x1f : b < 0 ? 0 : b;
*rgb++ = (uint16_t)(r << 11 | g << 5 | b);
}
y += aYStride;
if (i % 2) {
uv += aUVStride;
}
}
}
already_AddRefed<gfxASurface>
GrallocImage::GetAsSurface()
{
android::sp<GraphicBuffer> graphicBuffer =
GrallocBufferActor::GetFrom(GetSurfaceDescriptor());
void *buffer;
int32_t rv =
graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN, &buffer);
if (rv) {
NS_WARNING("Couldn't lock graphic buffer");
return nullptr;
}
GraphicBufferAutoUnlock unlock(graphicBuffer);
uint32_t format = graphicBuffer->getPixelFormat();
uint32_t omxFormat = 0;
for (int i = 0; sColorIdMap[i]; i += 2) {
if (sColorIdMap[i] == format) {
omxFormat = sColorIdMap[i + 1];
break;
}
}
if (!omxFormat) {
NS_WARNING("Unknown color format");
return nullptr;
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(GetSize(), gfxASurface::ImageFormatRGB16_565);
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;
if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO) {
// The Adreno hardware decoder aligns image dimensions to a multiple of 32,
// so we have to account for that here
uint32_t alignedWidth = ALIGN(width, 32);
uint32_t alignedHeight = ALIGN(height, 32);
uint32_t uvOffset = ALIGN(alignedHeight * alignedWidth, 4096);
uint32_t uvStride = 2 * ALIGN(width / 2, 32);
uint8_t* buffer_as_bytes = static_cast<uint8_t*>(buffer);
ConvertYVU420SPToRGB565(buffer, alignedWidth,
buffer_as_bytes + uvOffset, uvStride,
imageSurface->Data(),
width, height);
return imageSurface.forget();
}
else if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
uint32_t uvOffset = height * width;
ConvertYVU420SPToRGB565(buffer, width,
buffer + uvOffset, width,
imageSurface->Data(),
width, height);
return imageSurface.forget();
}
android::ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)omxFormat,
OMX_COLOR_Format16bitRGB565);
if (!colorConverter.isValid()) {
NS_WARNING("Invalid color conversion");
return nullptr;
}
rv = colorConverter.convert(buffer, width, height,
0, 0, width - 1, height - 1 /* source crop */,
imageSurface->Data(), width, height,
0, 0, width - 1, height - 1 /* dest crop */);
if (rv) {
NS_WARNING("OMX color conversion failed");
return nullptr;
}
return imageSurface.forget();
}
} // namespace layers
} // namespace mozilla

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

@ -10,12 +10,43 @@
#include "mozilla/layers/LayersSurfaces.h"
#include "ImageLayers.h"
#include "ImageContainer.h"
#include <ui/GraphicBuffer.h>
namespace mozilla {
namespace layers {
/**
* The gralloc buffer maintained by android GraphicBuffer can be
* shared between the compositor thread and the producer thread. The
* mGraphicBuffer is owned by the producer thread, but when it is
* wrapped by GraphicBufferLocked and passed to the compositor, the
* buffer content is guaranteed to not change until Unlock() is
* called. Each producer must maintain their own buffer queue and
* implement the GraphicBufferLocked::Unlock() interface.
*/
class GraphicBufferLocked {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphicBufferLocked)
public:
GraphicBufferLocked(SurfaceDescriptor aGraphicBuffer)
: mSurfaceDescriptor(aGraphicBuffer)
{}
virtual ~GraphicBufferLocked() {}
virtual void Unlock() {}
SurfaceDescriptor GetSurfaceDescriptor()
{
return mSurfaceDescriptor;
}
protected:
SurfaceDescriptor mSurfaceDescriptor;
};
/**
* The YUV format supported by Android HAL
*
@ -37,13 +68,19 @@ namespace layers {
* mPicX, mPicY and mPicSize. The size of the rendered image is
* mPicSize, not mYSize or mCbCrSize.
*/
class GrallocPlanarYCbCrImage : public PlanarYCbCrImage {
class GrallocImage : public PlanarYCbCrImage {
typedef PlanarYCbCrImage::Data Data;
static uint32_t sColorIdMap[];
public:
GrallocPlanarYCbCrImage();
struct GrallocData {
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
gfxIntSize mPicSize;
};
virtual ~GrallocPlanarYCbCrImage();
GrallocImage();
virtual ~GrallocImage();
/**
* This makes a copy of the data buffers, in order to support functioning
@ -51,16 +88,44 @@ public:
*/
virtual void SetData(const Data& aData);
virtual uint32_t GetDataSize() { return 0; }
/**
* Share the SurfaceDescriptor without making the copy, in order
* to support functioning in all different layer managers.
*/
virtual void SetData(const GrallocData& aData);
virtual bool IsValid() { return mSurfaceDescriptor.type() != SurfaceDescriptor::T__None; }
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
enum {
/* OEM specific HAL formats */
HAL_PIXEL_FORMAT_YCbCr_422_P = 0x102,
HAL_PIXEL_FORMAT_YCbCr_420_P = 0x103,
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A,
};
virtual already_AddRefed<gfxASurface> GetAsSurface();
void* GetNativeBuffer()
{
if (IsValid()) {
return GrallocBufferActor::GetFrom(GetSurfaceDescriptor())->getNativeBuffer();
} else {
return nullptr;
}
}
virtual bool IsValid() { return GetSurfaceDescriptor().type() != SurfaceDescriptor::T__None; }
SurfaceDescriptor GetSurfaceDescriptor() {
return mSurfaceDescriptor;
if (mGraphicBuffer.get()) {
return mGraphicBuffer->GetSurfaceDescriptor();
}
return SurfaceDescriptor();
}
private:
SurfaceDescriptor mSurfaceDescriptor;
bool mBufferAllocated;
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
};
} // namespace layers

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

@ -7,7 +7,6 @@
#include "mozilla/layers/ImageBridgeChild.h"
#include "ImageContainer.h"
#include "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ipc/CrossProcessMutex.h"
@ -54,7 +53,7 @@ ImageFactory::CreateImage(const ImageFormat *aFormats,
nsRefPtr<Image> img;
#ifdef MOZ_WIDGET_GONK
if (FormatInList(aFormats, aNumFormats, GRALLOC_PLANAR_YCBCR)) {
img = new GrallocPlanarYCbCrImage();
img = new GrallocImage();
return img.forget();
}
#endif
@ -70,12 +69,6 @@ ImageFactory::CreateImage(const ImageFormat *aFormats,
img = new SharedTextureImage();
return img.forget();
}
#ifdef MOZ_WIDGET_GONK
if (FormatInList(aFormats, aNumFormats, GONK_IO_SURFACE)) {
img = new GonkIOSurfaceImage();
return img.forget();
}
#endif
#ifdef XP_WIN
if (FormatInList(aFormats, aNumFormats, D3D9_RGB32_TEXTURE)) {
img = new D3D9SurfaceImage();

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

@ -17,9 +17,9 @@ enum ImageFormat {
PLANAR_YCBCR,
/**
* The GRALLOC_PLANAR_YCBCR format creates a GrallocPlanarYCbCrImage, a
* subtype of PlanarYCbCrImage. It takes a PlanarYCbCrImage data and can be
* used as a texture by Gonk backend directly.
* The GRALLOC_PLANAR_YCBCR format creates a GrallocImage, a subtype of
* PlanarYCbCrImage. It takes a PlanarYCbCrImage data or the raw gralloc
* data and can be used as a texture by Gonk backend directly.
*/
GRALLOC_PLANAR_YCBCR,
@ -45,13 +45,6 @@ enum ImageFormat {
*/
CAIRO_SURFACE,
/**
* The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
*
* It wraps an GraphicBuffer object and binds it directly to a GL texture.
*/
GONK_IO_SURFACE,
/**
* An bitmap image that can be shared with a remote process.
*/

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

@ -13,7 +13,6 @@
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
#ifdef MOZ_WIDGET_GONK
#include "GonkIOSurfaceImage.h"
#include "GrallocImages.h"
#endif
@ -152,20 +151,6 @@ DeprecatedImageClientSingle::UpdateImage(ImageContainer* aContainer,
}
mDeprecatedTextureClient->SetDescriptor(desc);
#ifdef MOZ_WIDGET_GONK
} else if (image->GetFormat() == GONK_IO_SURFACE &&
EnsureDeprecatedTextureClient(TEXTURE_SHARED_GL_EXTERNAL)) {
nsIntRect rect(0, 0,
image->GetSize().width,
image->GetSize().height);
UpdatePictureRect(rect);
AutoLockDeprecatedTextureClient lock(mDeprecatedTextureClient);
SurfaceDescriptor desc = static_cast<GonkIOSurfaceImage*>(image)->GetSurfaceDescriptor();
if (!IsSurfaceDescriptorValid(desc)) {
return false;
}
mDeprecatedTextureClient->SetDescriptor(desc);
} else if (image->GetFormat() == GRALLOC_PLANAR_YCBCR) {
EnsureDeprecatedTextureClient(TEXTURE_SHARED_GL_EXTERNAL);
@ -176,7 +161,7 @@ DeprecatedImageClientSingle::UpdateImage(ImageContainer* aContainer,
AutoLockDeprecatedTextureClient lock(mDeprecatedTextureClient);
SurfaceDescriptor desc = static_cast<GrallocPlanarYCbCrImage*>(image)->GetSurfaceDescriptor();
SurfaceDescriptor desc = static_cast<GrallocImage*>(image)->GetSurfaceDescriptor();
if (!IsSurfaceDescriptorValid(desc)) {
return false;
}
@ -253,11 +238,8 @@ ImageClient::CreateImage(const uint32_t *aFormats,
img = new DeprecatedSharedRGBImage(GetForwarder());
return img.forget();
#ifdef MOZ_WIDGET_GONK
case GONK_IO_SURFACE:
img = new GonkIOSurfaceImage();
return img.forget();
case GRALLOC_PLANAR_YCBCR:
img = new GrallocPlanarYCbCrImage();
img = new GrallocImage();
return img.forget();
#endif
}

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

@ -10,7 +10,7 @@ EXPORTS += [
'CopyableCanvasLayer.h',
'D3D9SurfaceImage.h',
'FrameMetrics.h',
'GonkIOSurfaceImage.h',
'GrallocImages.h',
'ImageContainer.h',
'ImageLayers.h',
'ImageTypes.h',
@ -166,7 +166,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
CPP_SOURCES += [
'ShadowLayerUtilsGralloc.cpp',
'GrallocImages.cpp',
'GonkIOSurfaceImage.cpp',
]
CPP_SOURCES += [

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

@ -59,7 +59,7 @@ VPATH += \
$(srcdir)/src/sfnt \
$(NULL)
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gonk))
OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(CAIRO_FT_CFLAGS)
DEFINES += -DSK_FONTHOST_CAIRO_STANDALONE=0
endif

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

@ -207,14 +207,9 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
'SkThreadUtils_pthread_linux.cpp',
'SkTime_Unix.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
CPP_SOURCES += [
'SkThread_pthread.cpp',
]
# Separate 'if' from above, since the else below applies to all != 'android'
# toolkits.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
EXPORTS.skia += [
'include/ports/SkTypeface_cairo.h',
]

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

@ -58,6 +58,20 @@ class Latin1CharsZ : public mozilla::RangedPtr<unsigned char>
char *c_str() { return reinterpret_cast<char *>(get()); }
};
class UTF8Chars : public mozilla::Range<unsigned char>
{
typedef mozilla::Range<unsigned char> Base;
public:
UTF8Chars() : Base() {}
UTF8Chars(char *aBytes, size_t aLength)
: Base(reinterpret_cast<unsigned char *>(aBytes), aLength)
{}
UTF8Chars(const char *aBytes, size_t aLength)
: Base(reinterpret_cast<unsigned char *>(const_cast<char *>(aBytes)), aLength)
{}
};
/*
* SpiderMonkey also deals directly with UTF-8 encoded text in some places.
*/
@ -124,10 +138,12 @@ class TwoByteCharsZ : public mozilla::RangedPtr<jschar>
typedef mozilla::RangedPtr<jschar> Base;
public:
TwoByteCharsZ() : Base(NULL, 0) {}
TwoByteCharsZ(jschar *chars, size_t length)
: Base(chars, length)
{
JS_ASSERT(chars[length] = '\0');
JS_ASSERT(chars[length] == '\0');
}
};
@ -147,6 +163,26 @@ LossyTwoByteCharsToNewLatin1CharsZ(js::ThreadSafeContext *cx, TwoByteChars tbcha
extern UTF8CharsZ
TwoByteCharsToNewUTF8CharsZ(js::ThreadSafeContext *cx, TwoByteChars tbchars);
uint32_t
Utf8ToOneUcs4Char(const uint8_t *utf8Buffer, int utf8Length);
/*
* Inflate bytes in UTF-8 encoding to jschars.
* - On error, returns an empty TwoByteCharsZ.
* - On success, returns a malloc'd TwoByteCharsZ, and updates |outlen| to hold
* its length; the length value excludes the trailing null.
*/
extern TwoByteCharsZ
UTF8CharsToNewTwoByteCharsZ(JSContext *cx, const UTF8Chars utf8, size_t *outlen);
/*
* The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 characters
* will be replaced by \uFFFD. No exception will be thrown for malformed UTF-8
* input.
*/
extern TwoByteCharsZ
LossyUTF8CharsToNewTwoByteCharsZ(JSContext *cx, const UTF8Chars utf8, size_t *outlen);
} // namespace JS
inline void JS_free(JS::Latin1CharsZ &ptr) { js_free((void*)ptr.get()); }

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

@ -6538,12 +6538,10 @@ CData::GetRuntime(JSContext* cx, unsigned argc, jsval* vp)
return JS_TRUE;
}
typedef bool (*InflateUTF8Method)(JSContext *, const char *, size_t,
jschar *, size_t *);
typedef JS::TwoByteCharsZ (*InflateUTF8Method)(JSContext *, const JS::UTF8Chars, size_t *);
template <InflateUTF8Method InflateUTF8>
static JSBool
ReadStringCommon(JSContext* cx, unsigned argc, jsval* vp)
ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 0) {
@ -6596,19 +6594,11 @@ ReadStringCommon(JSContext* cx, unsigned argc, jsval* vp)
size_t length = strnlen(bytes, maxLength);
// Determine the length.
size_t dstlen;
if (!InflateUTF8(cx, bytes, length, NULL, &dstlen))
return JS_FALSE;
jschar* dst =
static_cast<jschar*>(JS_malloc(cx, (dstlen + 1) * sizeof(jschar)));
jschar *dst = inflateUTF8(cx, JS::UTF8Chars(bytes, length), &length).get();
if (!dst)
return JS_FALSE;
ASSERT_OK(InflateUTF8(cx, bytes, length, dst, &dstlen));
dst[dstlen] = 0;
result = JS_NewUCString(cx, dst, dstlen);
result = JS_NewUCString(cx, dst, length);
break;
}
case TYPE_int16_t:
@ -6637,13 +6627,13 @@ ReadStringCommon(JSContext* cx, unsigned argc, jsval* vp)
JSBool
CData::ReadString(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadStringCommon<InflateUTF8StringToBuffer>(cx, argc, vp);
return ReadStringCommon(cx, JS::UTF8CharsToNewTwoByteCharsZ, argc, vp);
}
JSBool
CData::ReadStringReplaceMalformed(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadStringCommon<InflateUTF8StringToBufferReplaceInvalid>(cx, argc, vp);
return ReadStringCommon(cx, JS::LossyUTF8CharsToNewTwoByteCharsZ, argc, vp);
}
JSString *

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

@ -379,6 +379,7 @@ class StoreBuffer
GenericBuffer bufferGeneric;
JSRuntime *runtime;
const Nursery &nursery_;
void *buffer;
@ -400,10 +401,10 @@ class StoreBuffer
GenericBufferSize;
public:
explicit StoreBuffer(JSRuntime *rt)
explicit StoreBuffer(JSRuntime *rt, const Nursery &nursery)
: bufferVal(this), bufferCell(this), bufferSlot(this), bufferWholeCell(this),
bufferRelocVal(this), bufferRelocCell(this), bufferGeneric(this),
runtime(rt), buffer(NULL), aboutToOverflow(false), overflowed(false),
runtime(rt), nursery_(nursery), buffer(NULL), aboutToOverflow(false), overflowed(false),
enabled(false)
{}
@ -453,7 +454,7 @@ class StoreBuffer
/* Insert or update a callback entry. */
void putCallback(CallbackRef::MarkCallback callback, Cell *key, void *data) {
if (!key->isTenured())
if (nursery_.isInside(key))
bufferGeneric.put(CallbackRef(callback, key, data));
}

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

@ -4,14 +4,15 @@
* 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 "ion/AliasAnalysis.h"
#include <stdio.h>
#include "ion/MIR.h"
#include "ion/AliasAnalysis.h"
#include "ion/MIRGraph.h"
#include "ion/Ion.h"
#include "ion/IonBuilder.h"
#include "ion/IonSpewer.h"
#include "ion/MIR.h"
#include "ion/MIRGraph.h"
using namespace js;
using namespace js::ion;

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

@ -8,31 +8,27 @@
#include "mozilla/Move.h"
#ifdef MOZ_VTUNE
# include "jitprofiling.h"
#endif
#include "jsmath.h"
#include "jsworkers.h"
#include "jswrapper.h"
#include "prmjtime.h"
#ifdef MOZ_VTUNE
# include "jitprofiling.h"
#endif
#include "frontend/Parser.h"
#include "ion/AsmJSModule.h"
#include "ion/PerfSpewer.h"
#include "ion/CodeGenerator.h"
#include "ion/MIR.h"
#include "ion/MIRGraph.h"
#include "ion/PerfSpewer.h"
#include "jsfuninlines.h"
#include "frontend/ParseMaps-inl.h"
#include "frontend/ParseNode-inl.h"
#ifdef MOZ_VTUNE
# include "jitprofiling.h"
#endif
using namespace js;
using namespace js::frontend;
using namespace js::ion;

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

@ -8,8 +8,8 @@
#define ion_AsmJS_h
#ifdef XP_MACOSX
# include <pthread.h>
# include <mach/mach.h>
# include <pthread.h>
#endif
#include "jstypes.h"

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

@ -4,23 +4,21 @@
* 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 "jsmath.h"
#include "jscntxt.h"
#include "ion/AsmJS.h"
#include "ion/AsmJSModule.h"
#include "frontend/BytecodeCompiler.h"
#ifdef MOZ_VTUNE
# include "jitprofiling.h"
#endif
#include "jscntxt.h"
#include "jsmath.h"
#include "frontend/BytecodeCompiler.h"
#include "ion/AsmJS.h"
#include "ion/AsmJSModule.h"
#include "ion/Ion.h"
#ifdef JS_ION_PERF
# include "ion/PerfSpewer.h"
#endif
#include "ion/Ion.h"
#include "jsfuninlines.h"
using namespace js;

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

@ -7,20 +7,18 @@
#ifndef ion_AsmJSModule_h
#define ion_AsmJSModule_h
#include "mozilla/MathAlgorithms.h"
#ifdef JS_ION
#include "gc/Marking.h"
#include "ion/RegisterSets.h"
#include "mozilla/MathAlgorithms.h"
#include "jsscript.h"
#include "gc/Marking.h"
#include "ion/IonMacroAssembler.h"
#if defined(JS_ION_PERF)
# include "ion/PerfSpewer.h"
#endif
#include "ion/IonMacroAssembler.h"
#include "ion/RegisterSets.h"
namespace js {

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

@ -6,9 +6,9 @@
#include "jscntxt.h"
#include "assembler/assembler/MacroAssembler.h"
#include "ion/AsmJS.h"
#include "ion/AsmJSModule.h"
#include "assembler/assembler/MacroAssembler.h"
#include "vm/ObjectImpl-inl.h"

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

@ -9,10 +9,9 @@
#include "mozilla/Array.h"
#include "ion/LiveRangeAllocator.h"
#include "ds/PriorityQueue.h"
#include "ds/SplayTree.h"
#include "ion/LiveRangeAllocator.h"
// Backtracking priority queue based register allocator based on that described
// in the following blog post:

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

@ -4,18 +4,19 @@
* 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 "ion/Bailouts.h"
#include "jsanalyze.h"
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsinfer.h"
#include "ion/Bailouts.h"
#include "ion/SnapshotReader.h"
#include "ion/BaselineJIT.h"
#include "ion/Ion.h"
#include "ion/IonCompartment.h"
#include "ion/IonSpewer.h"
#include "ion/SnapshotReader.h"
#include "vm/Interpreter.h"
#include "ion/BaselineJIT.h"
#include "vm/Stack-inl.h"

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

@ -8,9 +8,10 @@
#define ion_Bailouts_h
#include "jstypes.h"
#include "vm/Stack.h"
#include "ion/IonFrameIterator.h"
#include "ion/IonFrames.h"
#include "vm/Stack.h"
namespace js {
namespace ion {

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

@ -9,10 +9,11 @@
#include "ion/BaselineJIT.h"
#include "ion/CompileInfo.h"
#include "ion/IonSpewer.h"
#include "ion/IonFrames-inl.h"
#include "jsfuninlines.h"
#include "ion/IonFrames-inl.h"
using namespace js;
using namespace js::ion;
@ -382,7 +383,7 @@ GetStubReturnAddress(JSContext *cx, jsbytecode *pc)
if (IsSetterPC(pc))
return cx->compartment()->ionCompartment()->baselineSetPropReturnAddr();
// This should be a call op of some kind, now.
JS_ASSERT(js_CodeSpec[JSOp(*pc)].format & JOF_INVOKE);
JS_ASSERT(IsCallPC(pc));
return cx->compartment()->ionCompartment()->baselineCallReturnAddr();
}
@ -769,7 +770,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
}
uint32_t pcOff = pc - script->code;
bool isCall = js_CodeSpec[op].format & JOF_INVOKE;
bool isCall = IsCallPC(pc);
BaselineScript *baselineScript = script->baselineScript();
#ifdef DEBUG
@ -1007,7 +1008,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
// Write out actual arguments (and thisv), copied from unpacked stack of BaselineJS frame.
// Arguments are reversed on the BaselineJS frame's stack values.
JS_ASSERT(isCall || IsGetterPC(pc) || IsSetterPC(pc));
JS_ASSERT(IsIonInlinablePC(pc));
unsigned actualArgc;
if (needToSaveArgs) {
// For FUNAPPLY or an accessor, the arguments are not on the stack anymore,

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

@ -4,10 +4,11 @@
* 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 "ion/BaselineJIT.h"
#include "ion/BaselineIC.h"
#include "ion/BaselineHelpers.h"
#include "ion/BaselineCompiler.h"
#include "ion/BaselineHelpers.h"
#include "ion/BaselineIC.h"
#include "ion/BaselineJIT.h"
#include "ion/FixedList.h"
#include "ion/IonLinker.h"
#include "ion/IonSpewer.h"
@ -2188,7 +2189,7 @@ BaselineCompiler::emit_JSOP_SETARG()
bool
BaselineCompiler::emitCall()
{
JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE);
JS_ASSERT(IsCallPC(pc));
uint32_t argc = GET_ARGC(pc);

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

@ -11,17 +11,14 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "ion/IonCode.h"
#include "jsinfer.h"
#include "vm/Interpreter.h"
#include "ion/IonAllocPolicy.h"
#include "ion/BaselineJIT.h"
#include "ion/BaselineIC.h"
#include "ion/FixedList.h"
#include "ion/BytecodeAnalysis.h"
#include "ion/FixedList.h"
#include "ion/IonAllocPolicy.h"
#include "ion/IonCode.h"
#if defined(JS_CPU_X86)
# include "ion/x86/BaselineCompiler-x86.h"
#elif defined(JS_CPU_X64)
@ -29,6 +26,7 @@
#else
# include "ion/arm/BaselineCompiler-arm.h"
#endif
#include "vm/Interpreter.h"
namespace js {
namespace ion {

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

@ -15,6 +15,7 @@
#include "jscompartment.h"
#include "ion/IonFrames.h"
#include "vm/ScopeObject-inl.h"
namespace js {

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

@ -4,15 +4,14 @@
* 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 "ion/BaselineFrame.h"
#include "ion/BaselineFrame-inl.h"
#include "ion/BaselineIC.h"
#include "ion/BaselineJIT.h"
#include "ion/Ion.h"
#include "vm/Debugger.h"
#include "vm/ScopeObject.h"
#include "ion/BaselineFrame-inl.h"
#include "ion/IonFrames-inl.h"
#include "vm/Stack-inl.h"

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

@ -5,11 +5,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ion/BaselineFrameInfo.h"
#include "ion/IonSpewer.h"
#include "ion/shared/BaselineCompiler-shared.h"
#include "jsanalyze.h"
#include "ion/IonSpewer.h"
#include "ion/shared/BaselineCompiler-shared.h"
using namespace js;
using namespace js::ion;

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