This commit is contained in:
Wes Kocher 2013-07-24 20:09:12 -07:00
Родитель b50528f44b e1ec7bf56f
Коммит 528ae6bcd0
212 изменённых файлов: 5169 добавлений и 3876 удалений

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

@ -18,11 +18,10 @@ MOCHITEST_A11Y_FILES = \
test_doc.html \
test_gettext.html \
test_hypertext.html \
test_lineboundary.html \
test_label.xul \
test_multiline.html \
test_passwords.html \
test_selection.html \
test_singleline.html \
test_wordboundary.html \
test_words.html \
$(NULL)

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

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<title>Line boundary getText* functions tests</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var IDs = [ "input", "div", "editable", "textarea" ];
testTextBeforeOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 15, "", 0, 0 ] ]);
testTextBeforeOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 15, "", 0, 0 ] ]);
testTextAtOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 15, "hello my friend", 0, 15 ] ]);
testTextAtOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 15, "hello my friend", 0, 15 ] ]);
testTextAfterOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 15, "", 15, 15 ] ]);
testTextAfterOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 15, "", 15, 15 ] ]);
//////////////////////////////////////////////////////////////////////////
// __o__n__e__w__o__r__d__\n
// 0 1 2 3 4 5 6 7
// __\n
// 8
// __t__w__o__ __w__o__r__d__s__\n
// 9 10 11 12 13 14 15 16 17 18
IDs = [ "ml_div", "ml_divbr", "ml_editable", "ml_editablebr", "ml_textarea"];
testTextBeforeOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 7, "", 0, 0 ],
[ 8, 8, "oneword\n", 0, 8 ],
[ 9, 18, "\n", 8, 9 ],
[ 19, 19, "two words\n", 9, 19 ]]);
testTextBeforeOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 7, "", 0, 0 ],
[ 8, 8, "oneword", 0, 7 ],
[ 9, 18, "\n", 7, 8 ],
[ 19, 19, "\ntwo words", 8, 18 ]]);
testTextAtOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 7, "oneword\n", 0, 8 ],
[ 8, 8, "\n", 8, 9 ],
[ 9, 18, "two words\n", 9, 19 ],
[ 19, 19, "", 19, 19 ]]);
testTextAtOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 7, "oneword", 0, 7 ],
[ 8, 8, "\n", 7, 8 ],
[ 9, 18, "\ntwo words", 8, 18 ],
[ 19, 19, "\n", 18, 19 ]]);
testTextAfterOffset(IDs, BOUNDARY_LINE_START,
[ [ 0, 7, "\n", 8, 9 ],
[ 8, 8, "two words\n", 9, 19 ],
[ 9, 19, "", 19, 19 ]]);
testTextAfterOffset(IDs, BOUNDARY_LINE_END,
[ [ 0, 7, "\n", 7, 8 ],
[ 8, 8, "\ntwo words", 8, 18 ],
[ 9, 18, "\n", 18, 19 ],
[ 19, 19, "", 19, 19 ]]);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="getTextAtOffset for word boundaries: beginning of a new life"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=853340">
Bug 853340
</a>
<a target="_blank"
title="getTextBeforeOffset for word boundaries: evolving"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=855732">
Bug 855732
</a>
<a target="_blank"
title=" getTextAfterOffset for line boundary on new rails"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=882292">
Bug 882292
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input" value="hello my friend"/>
<div id="div">hello my friend</div>
<div id="editable" contenteditable="true">hello my friend</div>
<textarea id="textarea">hello my friend</textarea>
<pre>
<div id="ml_div">oneword
two words
</div>
<div id="ml_divbr">oneword<br/><br/>two words<br/></div>
<div id="ml_editable" contenteditable="true">oneword
two words
</div>
<div id="ml_editablebr" contenteditable="true">oneword<br/><br/>two words<br/></div>
<textarea id="ml_textarea" cols="300">oneword
two words
</textarea>
</pre>
</body>
</html>

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

@ -1,137 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>nsIAccessibleText getText related function in multiline text</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
function doTest()
{
// __o__n__e__w__o__r__d__\n
// 0 1 2 3 4 5 6 7
// __\n
// 8
// __t__w__o__ __w__o__r__d__s__\n
// 9 10 11 12 13 14 15 16 17 18
////////////////////////////////////////////////////////////////////////
// getText
var IDs = ["div", "divbr", "editable", "editablebr", "textarea"];
////////////////////////////////////////////////////////////////////////
// getTextAfterOffset
// BOUNDARY_LINE_START
testTextAfterOffset(0, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
testTextAfterOffset(7, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
testTextAfterOffset(8, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
testTextAfterOffset(9, BOUNDARY_LINE_START, "", 19, 19, IDs);
testTextAfterOffset(19, BOUNDARY_LINE_START, "", 19, 19, IDs);
// BOUNDARY_LINE_END
testTextAfterOffset(0, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
testTextAfterOffset(7, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
testTextAfterOffset(8, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
testTextAfterOffset(9, BOUNDARY_LINE_END, "\n", 18, 19, IDs);
testTextAfterOffset(18, BOUNDARY_LINE_END, "\n", 18, 19, IDs);
testTextAfterOffset(19, BOUNDARY_LINE_END, "", 19, 19, IDs);
////////////////////////////////////////////////////////////////////////
// getTextBeforeOffset
// BOUNDARY_LINE_START
testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0, IDs);
testTextBeforeOffset(8, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
testTextBeforeOffset(9, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
testTextBeforeOffset(18, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
testTextBeforeOffset(19, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
// BOUNDARY_LINE_END
testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0, IDs);
testTextBeforeOffset(7, BOUNDARY_LINE_END, "", 0, 0, IDs);
testTextBeforeOffset(8, BOUNDARY_LINE_END, "oneword", 0, 7, IDs);
testTextBeforeOffset(9, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
testTextBeforeOffset(18, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
testTextBeforeOffset(19, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
////////////////////////////////////////////////////////////////////////
// getTextAtOffset
// BOUNDARY_LINE_START
testTextAtOffset(0, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
testTextAtOffset(7, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
testTextAtOffset(8, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
testTextAtOffset(9, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
testTextAtOffset(13, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
testTextAtOffset(18, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
testTextAtOffset(19, BOUNDARY_LINE_START, "", 19, 19, IDs);
// BOUNDARY_LINE_END
testTextAtOffset(0, BOUNDARY_LINE_END, "oneword", 0, 7, IDs);
testTextAtOffset(7, BOUNDARY_LINE_END, "oneword", 0, 7, IDs);
testTextAtOffset(8, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
testTextAtOffset(9, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
testTextAtOffset(17, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
testTextAtOffset(18, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
testTextAtOffset(19, BOUNDARY_LINE_END, "\n", 18, 19, IDs);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="nsIAccessibleText getText related functions test in multiline text"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=612331">
Bug 612331
</a>
<a target="_blank"
title="getTextAtOffset for word boundaries: beginning of a new life"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=853340">
Bug 853340
</a>
<a target="_blank"
title="getTextBeforeOffset for word boundaries: evolving"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=855732">
Bug 855732
</a>
<a target="_blank"
title=" getTextAfterOffset for line boundary on new rails"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=882292">
Bug 882292
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<div id="div">oneword
two words
</div>
<div id="divbr">oneword<br/><br/>two words<br/></div>
<div id="editable" contenteditable="true">oneword
two words
</div>
<div id="editablebr" contenteditable="true">oneword<br/><br/>two words<br/></div>
<textarea id="textarea" cols="300">oneword
two words
</textarea>
</pre>
</body>
</html>

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

@ -1,112 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>nsIAccessibleText getText related function tests for html:input,html:div and html:textarea</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
function doTest()
{
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
////////////////////////////////////////////////////////////////////////
// getTextAfterOffset
var IDs = [ "input", "div", "editable", "textarea" ];
var regularIDs = [ "input", "div", "editable" ];
// BOUNDARY_LINE_START
testTextAfterOffset(0, BOUNDARY_LINE_START, "", 15, 15, IDs);
testTextAfterOffset(1, BOUNDARY_LINE_START, "", 15, 15, IDs);
testTextAfterOffset(14, BOUNDARY_LINE_START, "", 15, 15, IDs);
testTextAfterOffset(15, BOUNDARY_LINE_START, "", 15, 15, IDs);
// BOUNDARY_LINE_END
testTextAfterOffset(0, BOUNDARY_LINE_END, "", 15, 15, IDs);
testTextAfterOffset(1, BOUNDARY_LINE_END, "", 15, 15, IDs);
testTextAfterOffset(14, BOUNDARY_LINE_END, "", 15, 15, IDs);
testTextAfterOffset(15, BOUNDARY_LINE_END, "", 15, 15, IDs);
////////////////////////////////////////////////////////////////////////
// getTextBeforeOffset
var IDs = [ "input", "div", "editable", "textarea" ];
// BOUNDARY_LINE_START
testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0, IDs);
testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0, IDs);
testTextBeforeOffset(14, BOUNDARY_LINE_START, "", 0, 0, IDs);
testTextBeforeOffset(15, BOUNDARY_LINE_START, "", 0, 0, IDs);
// BOUNDARY_LINE_END
testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0, IDs);
testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0, IDs);
testTextBeforeOffset(14, BOUNDARY_LINE_END, "", 0, 0, IDs);
testTextBeforeOffset(15, BOUNDARY_LINE_END, "", 0, 0, IDs);
////////////////////////////////////////////////////////////////////////
// getTextAtOffset
IDs = [ "input", "div", "editable", "textarea" ];
regularIDs = [ "input", "div", "editable" ];
// BOUNDARY_LINE_START
testTextAtOffset(0, BOUNDARY_LINE_START, "hello my friend", 0, 15, IDs);
testTextAtOffset(1, BOUNDARY_LINE_START, "hello my friend", 0, 15, IDs);
testTextAtOffset(14, BOUNDARY_LINE_START, "hello my friend", 0, 15, IDs);
testTextAtOffset(15, BOUNDARY_LINE_START, "hello my friend", 0, 15, IDs);
// BOUNDARY_LINE_END
testTextAtOffset(0, BOUNDARY_LINE_END, "hello my friend", 0, 15, IDs);
testTextAtOffset(1, BOUNDARY_LINE_END, "hello my friend", 0, 15, IDs);
testTextAtOffset(14, BOUNDARY_LINE_END, "hello my friend", 0, 15, IDs);
testTextAtOffset(15, BOUNDARY_LINE_END, "hello my friend", 0, 15, IDs);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="nsIAccessibleText getText related function tests for html:input,html:div and html:textarea"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=452769">
Bug 452769
</a>
<a target="_blank"
title="getTextAtOffset for word boundaries: beginning of a new life"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=853340">
Bug 853340
</a>
<a target="_blank"
title="getTextBeforeOffset for word boundaries: evolving"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=855732">
Bug 855732
</a>
<a target="_blank"
title=" getTextAfterOffset for line boundary on new rails"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=882292">
Bug 882292
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input" value="hello my friend"/>
<div id="div">hello my friend</div>
<div id="editable" contenteditable="true">hello my friend</div>
<textarea id="textarea">hello my friend</textarea>
</body>
</html>

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

@ -220,8 +220,6 @@ 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>19.0</em:minVersion>
<em:maxVersion>22.0a1</em:maxVersion>
<em:minVersion>21.0</em:minVersion>
<em:maxVersion>25.0a1</em:maxVersion>
</Description>
</em:targetApplication>

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

@ -640,15 +640,14 @@ 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
--update-url https://example.com/addon/update_rdf
cfx xpi --update-link https://example.com/addon/latest/pluginName.xpi --update-url https://example.com/addon/update_rdf/pluginName.update.rdf
</pre>
`cfx` will create two files:
* an XPI file which embeds
`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
`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
`updateLink`.
### Supported Options ###

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

@ -13,6 +13,13 @@ 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

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

@ -0,0 +1,90 @@
<!-- 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,3 +154,24 @@ 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,34 +8,32 @@ module.metadata = {
"stability": "unstable"
};
const { Cc, Ci } = require("chrome");
const { Cc, Ci, Cu, Cr } = require("chrome");
const self = require("../self");
const traceback = require("./traceback")
const prefs = require("../preferences/service");
const { merge } = require("../util/object");
const { partial } = require("../lang/functional");
const { ConsoleAPI } = Cu.import("resource://gre/modules/devtools/Console.jsm");
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;
let logLevel = DEFAULT_LOG_LEVEL;
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();
}
@ -43,79 +41,23 @@ let logLevelObserver = {
let branch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService).
getBranch(null);
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));
}
branch.addObserver(ADDON_LOG_LEVEL_PREF, logLevelObserver, true);
branch.addObserver(SDK_LOG_LEVEL_PREF, logLevelObserver, true);
function PlainTextConsole(print) {
if (!print)
print = dump;
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);
}
let consoleOptions = {
prefix: self.name + ": ",
maxLogLevel: logLevel,
dump: print
};
let console = new ConsoleAPI(consoleOptions);
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() {}
// As we freeze the console object, we can't modify this property afterward
Object.defineProperty(console, "maxLogLevel", {
get: function() {
return logLevel;
}
});
// We defined the `__exposedProps__` in our console chrome object.
@ -126,11 +68,12 @@ function PlainTextConsole(print) {
// Meanwhile we're investigating with the platform team if `__exposedProps__`
// are needed, or are just a left-over.
this.__exposedProps__ = Object.keys(this).reduce(function(exposed, prop) {
console.__exposedProps__ = Object.keys(ConsoleAPI.prototype).reduce(function(exposed, prop) {
exposed[prop] = "r";
return exposed;
}, {});
Object.freeze(this);
Object.freeze(console);
return console;
};
exports.PlainTextConsole = PlainTextConsole;

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

@ -9,7 +9,8 @@ module.metadata = {
"stability": "deprecated"
};
const memory = require('./memory');
const { Cu } = require("chrome");
const memory = require("./memory");
var timer = require("../timers");
var cfxArgs = require("@test/options");
@ -443,7 +444,7 @@ TestRunner.prototype = {
},
startMany: function startMany(options) {
function runNextTest(self) {
let runNextTest = (self) => Cu.schedulePreciseGC(_ => {
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");
@ -453,7 +454,8 @@ TestRunner.prototype = {
} else {
options.onDone(self);
}
}
});
runNextTest(this);
},

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

@ -9,74 +9,252 @@ module.metadata = {
};
const { Cc, Ci, CC } = require("chrome");
const { Class } = require("../core/heritage");
const { Cu } = require("chrome");
const { TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
const Transcoder = CC("@mozilla.org/intl/scriptableunicodeconverter",
"nsIScriptableUnicodeConverter");
exports.TextEncoder = TextEncoder;
exports.TextDecoder = TextDecoder;
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));
if (typeof subject === "string") this.write(subject);
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 (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;
};
// 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))
},
get length() {
return this.valueOf().length;
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));
}
},
get: function get(index) {
return this.valueOf()[index];
toJSON: {
value: function() ({ type: "Buffer", data: Array.slice(this, 0) })
},
set: function set(index, value) {
return this.valueOf()[index] = value;
get: {
value: function(offset) this[offset]
},
valueOf: function valueOf(value) {
Object.defineProperty(this, "valueOf", {
value: Array.prototype.valueOf.bind(value),
configurable: false,
writable: false,
enumerable: false
});
set: {
value: function(offset, value) this[offset] = value
},
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);
copy: {
value: function(target, offset, start, end)
Uint8Array.set(target, this.subarray(start, end), offset)
},
toJSON: function toJSON() {
return this.toString()
slice: {
value: Buffer.prototype.subarray
},
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;
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;
}
},
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));
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;
}
}
});
Buffer.isBuffer = function isBuffer(buffer) {
return buffer instanceof Buffer
};
exports.Buffer = Buffer;
// 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 };

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

@ -12,10 +12,12 @@ 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",
@ -33,6 +35,8 @@ 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;
@ -157,14 +161,16 @@ 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, {
input: binaryInputStream, pump: pump
asyncInputStream: transport.openInputStream(null, 0, 0)
});
// Close file descriptor on end and destroy the stream.
on(this, "end", _ => {
this.destroy();
emit(this, "close");
});
this.read();
},
destroy: function() {
@ -211,21 +217,20 @@ 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.
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);
// Storing output stream so that it can beaccessed later.
OutputStream.prototype.initialize.call(this, {
output: binaryOutputStream,
asyncOutputStream: asyncOutputStream
asyncOutputStream: transport.openOutputStream(OPEN_UNBUFFERED, 0, 0),
output: output
});
// For write streams "finish" basically means close.
on(this, "finish", _ => {
this.destroy();
emit(this, "close");
});
},
destroy: function() {
closeSync(this.fd);
OutputStream.prototype.destroy.call(this);
closeSync(this.fd);
}
});
exports.WriteStream = WriteStream;
@ -365,7 +370,7 @@ function ftruncate(fd, length, callback) {
}
exports.ftruncate = ftruncate;
function ftruncateSync(fd, length) {
function ftruncateSync(fd, length = 0) {
writeSync(fd, new Buffer(length), 0, length, 0);
}
exports.ftruncateSync = ftruncateSync;
@ -634,6 +639,8 @@ 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))
@ -675,7 +682,9 @@ function writeSync(fd, buffer, offset, length, position) {
}
let writeStream = new WriteStream(fd, { position: position,
length: length });
let output = nsIBinaryOutputStream(fd);
let output = BinaryOutputStream(nsIFileOutputStream(fd));
nsIBinaryOutputStream(fd, output);
// We write content as a byte array as this will avoid any transcoding
// if content was a buffer.
output.writeByteArray(buffer.valueOf(), buffer.length);
@ -736,10 +745,14 @@ function readSync(fd, buffer, offset, length, position) {
// without blocking the main thread.
let binaryInputStream = BinaryInputStream(input);
let count = length === ALL ? binaryInputStream.available() : length;
var bytes = binaryInputStream.readByteArray(count);
buffer.copy.call(bytes, buffer, offset);
if (offset === 0) binaryInputStream.readArrayBuffer(count, buffer.buffer);
else {
let chunk = new Buffer(count);
binaryInputStream.readArrayBuffer(count, chunk.buffer);
chunk.copy(buffer, offset);
}
return bytes;
return buffer.slice(offset, offset + count);
};
exports.readSync = readSync;
@ -759,9 +772,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(chunck) {
chunck.copy(buffer, offset + bytesRead);
bytesRead += chunck.length;
readStream.on("data", function onData(data) {
data.copy(buffer, offset + bytesRead);
bytesRead += data.length;
});
readStream.on("end", function onEnd() {
callback(null, bytesRead, buffer);
@ -781,19 +794,26 @@ function readFile(path, encoding, callback) {
encoding = null
}
let buffer = new Buffer();
let buffer = null;
try {
let readStream = new ReadStream(path);
readStream.on("data", function(chunck) {
chunck.copy(buffer, buffer.length);
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("error", function onError(error) {
callback(error);
readStream.destroy();
});
readStream.on("end", function onEnd() {
callback(null, buffer);
// Note: Need to destroy before invoking a callback
// so that file descriptor is released.
readStream.destroy();
callback(null, buffer);
});
} catch (error) {
setTimeout(callback, 0, error);
@ -807,8 +827,9 @@ 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);
}
@ -833,13 +854,16 @@ function writeFile(path, content, encoding, callback) {
content = new Buffer(content, encoding);
let writeStream = new WriteStream(path);
writeStream.on("error", function onError(error) {
let error = null;
writeStream.end(content, function() {
writeStream.destroy();
callback(error);
writeStream.destroy();
});
writeStream.write(content, function onDrain() {
writeStream.on("error", function onError(reason) {
error = reason;
writeStream.destroy();
callback(null);
});
} catch (error) {
callback(error);

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

@ -8,99 +8,45 @@ 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");
function isFunction(value) typeof value === "function"
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 accessor() {
let map = new WeakMap();
return function(fd, value) {
if (value === null) map.delete(fd);
if (value !== undefined) map.set(fd, value);
return map.get(fd);
return function(target, value) {
if (value)
map.set(target, value);
return map.get(target);
}
}
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() {
@ -120,7 +66,8 @@ const Stream = Class({
}
}
function onDrain() {
if (source.readable) source.resume();
if (source.readable)
source.resume();
}
function onEnd() {
target.end();
@ -176,18 +123,69 @@ 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 { input, pump } = options;
let { asyncInputStream } = options;
this.readable = true;
this.paused = false;
nsIInputStream(this, input);
nsIInputStreamPump(this, pump);
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;
},
get status() nsIInputStreamPump(this).status,
read: function() pump(this),
read: function() {
nsIInputStreamPump(this).asyncRead(nsIStreamListener(this), null);
},
pause: function pause() {
this.paused = true;
nsIInputStreamPump(this).suspend();
@ -198,67 +196,176 @@ const InputStream = Class({
nsIInputStreamPump(this).resume();
emit(this, "resume");
},
destroy: function destroy() {
close: function close() {
this.readable = false;
try {
emit(this, "close", null);
nsIInputStreamPump(this).cancel(null);
nsIInputStreamPump(this, null);
nsIInputStreamPump(this).cancel(Cr.NS_OK);
nsIBinaryInputStream(this).close();
nsIAsyncInputStream(this).close();
},
destroy: function destroy() {
this.close();
nsIInputStream(this).close();
nsIInputStream(this, null);
} catch (error) {
emit(this, "error", error);
}
nsIInputStreamPump(this);
nsIAsyncInputStream(this);
nsIBinaryInputStream(this);
nsIStreamListener(this);
}
});
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 { output, asyncOutputStream } = options;
let { asyncOutputStream, output } = options;
this.writable = true;
nsIOutputStream(this, output);
// 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);
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 not writable");
if (!this.writable) throw Error("stream is not writable");
try {
// If content is not a buffer then we create one out of it.
if (!Buffer.isBuffer(content))
content = new Buffer(content, encoding);
let chunk = null;
// 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);
// 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);
}
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 flush() {
nsIOutputStream(this).flush();
flush: function() {
if (this.drained) {
this.drained = false;
nsIAsyncStreamCopier(this).asyncCopy(nsIRequestObserver(this), null);
}
},
end: function end(content, encoding, callback) {
if (isFunction(content)) {
@ -270,53 +377,59 @@ const OutputStream = Class({
encoding = callback
}
// Setting a listener to "close" event if passed.
// Setting a listener to "finish" event if passed.
if (isFunction(callback))
this.once("close", callback);
this.once("finish", callback);
// If content is passed then we defer closing until we finish with writing.
if (content)
this.write(content, encoding, end.bind(this));
// If we don"t write anything, then we close an outputStream.
else
nsIOutputStream(this).close();
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();
},
destroy: function destroy(callback) {
try {
this.end(callback);
nsIOutputStream(this, null);
nsIAsyncOutputStream(this, null);
} catch (error) {
emit(this, "error", error);
}
destroy: function destroy() {
nsIAsyncOutputStream(this).close();
nsIAsyncOutputStream(this);
nsIMultiplexInputStream(this);
nsIAsyncStreamCopier(this);
nsIRequestObserver(this);
}
});
exports.OutputStream = OutputStream;
const DuplexStream = Class({
extends: Stream,
implements: [InputStream, OutputStream],
allowHalfOpen: true,
initialize: function initialize(options) {
let { input, output, pump } = options;
options = options || {};
let { readable, writable, allowHalfOpen } = options;
this.writable = true;
this.readable = true;
this.encoding = null;
InputStream.prototype.initialize.call(this, options);
OutputStream.prototype.initialize.call(this, options);
nsIInputStream(this, input);
nsIOutputStream(this, output);
nsIInputStreamPump(this, pump);
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();
});
},
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 { setTimeout } = require("../timers");
const { setImmediate, setTimeout } = require("../timers");
const { deprecateFunction } = require("../util/deprecate");
/**
@ -30,13 +30,12 @@ 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 `setTimeout(function() { ... }, 0)`, with a difference that returned
* to do `setImmediate(function() { ... })`, 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()
setTimeout(invoke, 0, f, arguments, this);
return function deferred() setImmediate(invoke, f, arguments, this);
}
exports.defer = defer;
// Exporting `remit` alias as `defer` may conflict with promises.

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

@ -68,19 +68,11 @@ exports.exit = function exit(code) {
appStartup.quit(code ? E_ATTEMPT : E_FORCE);
};
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 });
};
// 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;
/**
* Returns a path of the system's or application's special directory / file
@ -134,7 +126,7 @@ exports.build = appInfo.appBuildID;
exports.id = appInfo.ID;
/**
* The name of the application.
* The name of the application.
*/
exports.name = appInfo.name;

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

@ -22,20 +22,7 @@ let consoleService = Cc['@mozilla.org/consoleservice;1'].getService().
// For more details see: bug-673383
exports.dump = stdout.write;
// 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);
exports.console = new PlainTextConsole();
// Provide CommonJS `define` to allow authoring modules in a format that can be
// loaded both into jetpack and into browser via AMD loaders.

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

@ -26,10 +26,9 @@ Object.defineProperties(tabs, {
newTabWindow(options);
return undefined;
}
// Open in active window if new window was not required.
let activeWindow = windows.activeWindow;
let privateState = !!options.isPrivate;
let privateState = (supportPrivateTabs && (options.isPrivate || isPrivate(activeWindow))) || false;
// 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 } = require("chrome");
const { Cc, Ci, Cu } = require("chrome");
const { Loader } = require('./loader');
const { serializeStack, parseStack } = require("toolkit/loader");
const { setTimeout } = require('../timers');
@ -147,9 +147,11 @@ 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);
@ -167,26 +169,24 @@ var gWeakrefInfo;
function checkMemory() {
memory.gc();
setTimeout(function () {
memory.gc();
setTimeout(function () {
let leaks = getPotentialLeaks();
let compartmentURLs = Object.keys(leaks.compartments).filter(function(url) {
return !(url in startLeaks.compartments);
});
Cu.schedulePreciseGC(function () {
let leaks = getPotentialLeaks();
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 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();
});
}
@ -298,6 +298,7 @@ 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");
@ -318,8 +319,9 @@ function getPotentialLeaks() {
let compartments = {};
let windows = {};
function logReporter(process, path, kind, units, amount, description) {
let matches = compartmentRegexp.exec(path);
if (matches) {
let matches;
if ((matches = compartmentRegexp.exec(path)) || (matches = zoneRegExp.exec(path))) {
if (matches[1] in compartments)
return;
@ -576,7 +578,7 @@ var runTests = exports.runTests = function runTests(options) {
if (options.parseable)
testConsole = new TestRunnerTinderboxConsole(options);
else
testConsole = new TestRunnerConsole(new PlainTextConsole(print), options);
testConsole = new TestRunnerConsole(new PlainTextConsole(), options);
loader = Loader(module, {
console: testConsole,

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

@ -7,22 +7,31 @@ module.metadata = {
"stability": "stable"
};
const { CC, Ci } = require('chrome');
const { when: unload } = require('./system/unload');
const { CC, 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) {
function setTimer(type, callback, delay, ...args) {
let id = ++ lastID;
let timer = timers[id] = Timer();
let args = Array.slice(arguments, 3);
timer.initWithCallback({
notify: function notify() {
try {
@ -34,20 +43,63 @@ function setTimer(type, callback, delay) {
console.exception(error);
}
}
}, delay || 0, type);
}, Math.max(delay || MIN_DELAY), 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);
unload(function() { Object.keys(timers).forEach(unsetTimer) });
// all timers are cleared out on unload.
unload(function() {
immediates.clear();
Object.keys(timers).forEach(unsetTimer)
});

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

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

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

@ -18,6 +18,8 @@ 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',
@ -184,18 +186,21 @@ function serializeFeatures(options) {
* Map of key, values like: `{ width: 10, height: 15, chrome: true, private: true }`.
*/
function open(uri, options) {
options = 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');
let newWindow = windowWatcher.
openWindow(options.parent || null,
uri || URI_BROWSER,
uri,
options.name || null,
serializeFeatures(options.features || {}),
options.args || null);
return newWindow;
}
exports.open = open;
function onFocus(window) {

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

@ -52,6 +52,9 @@ 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 = 45 * 60 # 45 minutes
RUN_TIMEOUT = 1.5 * 60 * 60 # 1.5 Hour
# 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,9 +496,6 @@ 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,13 +330,9 @@ GetExitCodeProcess = GetExitCodeProcessProto(
GetExitCodeProcess.errcheck = ErrCheckBool
def CanCreateJobObject():
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
# 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
### testing functions

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

@ -3,13 +3,14 @@
* 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 serverPort = 8099;
let server = require("sdk/test/httpd").startServerAsync(serverPort);
let server = startServerAsync(serverPort);
server.registerPathHandler("/iframe", function handle(request, response) {
response.write("<html><body>foo</body></html>");
});
@ -31,19 +32,23 @@ exports.testCrossDomainIframe = function(assert, done) {
w.on("message", function (body) {
assert.equal(body, "foo", "received iframe html content");
pageMod.destroy();
w.tab.close();
server.stop(done);
w.tab.close(function() {
server.stop(done);
});
});
w.postMessage("http://localhost:8099/iframe");
}
});
tabs.open("about:credits");
tabs.open({
url: "about:home",
inBackground: true
});
};
exports.testCrossDomainXHR = function(assert, done) {
let serverPort = 8099;
let server = require("sdk/test/httpd").startServerAsync(serverPort);
let server = startServerAsync(serverPort);
server.registerPathHandler("/xhr", function handle(request, response) {
response.write("foo");
});
@ -65,22 +70,19 @@ exports.testCrossDomainXHR = function(assert, done) {
w.on("message", function (body) {
assert.equal(body, "foo", "received XHR content");
pageMod.destroy();
w.tab.close();
server.stop(done);
w.tab.close(function() {
server.stop(done);
});
});
w.postMessage("http://localhost:8099/xhr");
}
});
tabs.open("about:credits");
tabs.open({
url: "about:home",
inBackground: true
});
};
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);

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

@ -0,0 +1,35 @@
/* 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);

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

@ -0,0 +1,3 @@
{
"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,6 +5,8 @@ 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;
@ -26,7 +28,86 @@ 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);
}

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

@ -0,0 +1,82 @@
/* 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);

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

@ -0,0 +1,23 @@
{
"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,6 +19,7 @@ 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,
@ -45,12 +46,25 @@ function clearBookmarks (group) {
? bmsrv.removeFolderChildren(group.id)
: clearAllBookmarks();
}
exports.clearBookmarks = clearBookmarks;
function clearAllBookmarks () {
[MENU, TOOLBAR, UNSORTED].forEach(clearBookmarks);
}
exports.clearAllBookmarks = clearAllBookmarks;
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;
function compareWithHost (assert, item) {
let id = item.id;
@ -105,12 +119,6 @@ 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,12 +111,11 @@ 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
// 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(messages[0].msg,
"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,3 +85,11 @@ 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,14 +92,4 @@ 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,8 +3,12 @@
* 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
@ -12,41 +16,51 @@ const { Loader } = require('sdk/test/loader');
*/
function createProxyTest(html, callback) {
return function (assert, done) {
let url = 'data:text/html;charset=utf-8,' + encodeURI(html);
let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
let principalLoaded = false;
let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({
onReady: function () {
let element = makeFrame(window.document, {
nodeName: "iframe",
type: "content",
allowJavascript: true,
allowPlugins: true,
allowAuth: true,
uri: testURI
});
function onDOMReady() {
hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady,
false);
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);
}
hiddenFrame.element.addEventListener("DOMContentLoaded", onDOMReady, false);
hiddenFrame.element.setAttribute("src", url);
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,
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();
}
};
callback(helper, assert);
}
};
}
@ -165,9 +179,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.equal(event.source, helper.xrayWindow,
"event.source is the top window");
assert.equal(event.origin, "null", "origin is null");
assert.strictEqual(event.source, helper.xrayWindow,
"event.source is the top window");
assert.equal(event.origin, testHost, "origin matches testHost");
assert.equal(event.data, "{\"foo\":\"bar\\n \\\"escaped\\\".\"}",
"message data is correct");
@ -216,7 +230,9 @@ exports["test Object Listener"] = createProxyTest(html, function (helper) {
exports["test Object Listener 2"] = createProxyTest("", function (helper) {
helper.createWorker(
'new ' + function ContentScriptScope() {
('new ' + function ContentScriptScope() {
// variable replaced with `testHost`
let testHost = "TOKEN";
// Verify object as DOM event listener
let myMessageListener = {
called: false,
@ -228,7 +244,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 == "null", "origin is null");
assert(event.origin == testHost, "origin matches testHost");
assert(event.data == "ok", "message data is correct");
done();
}
@ -237,7 +253,7 @@ exports["test Object Listener 2"] = createProxyTest("", function (helper) {
window.addEventListener("message", myMessageListener, true);
document.defaultView.postMessage("ok", '*');
}
);
).replace("TOKEN", testHost));
});

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

@ -9,6 +9,7 @@ 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");
@ -26,19 +27,18 @@ 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 readir"] = function(assert, end) {
exports["test readdir"] = 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 et least number of entries we expect");
"got at 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 et least number of entries we expect");
"got at least number of entries we expect");
assert.ok(profileEntries.every(function(entry) {
return entries.indexOf(entry) >= 0;
}), "all profiles are present");
};
exports["test readirSync error"] = function(assert) {
exports["test readdirSync error"] = function(assert) {
var async = false;
var path = profilePath + "-does-not-exists";
try {
@ -92,6 +92,7 @@ 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,
@ -338,7 +339,6 @@ 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,4 +459,28 @@ 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");
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");
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:");
// Keep in mind to update "18" to the line of "throw new Error("foo")"
test.assertEqual(lines[2], module.uri + " 18");
test.assertEqual(lines[3], "Traceback (most recent call last):");
test.assert(lines[2].indexOf(module.uri + ":18") != -1);
loader.unload();
observers.notify("blarg", "yo yo");

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

@ -19,6 +19,8 @@ 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
@ -119,16 +121,16 @@ exports.testPageModIncludes = function(test) {
};
}
testPageMod(test, "about:buildconfig", [
testPageMod(test, testPageURI, [
createPageModTest("*", false),
createPageModTest("*.google.com", false),
createPageModTest("about:*", true),
createPageModTest("about:", false),
createPageModTest("about:buildconfig", true)
createPageModTest("resource:*", true),
createPageModTest("resource:", false),
createPageModTest(testPageURI, true)
],
function (win, done) {
test.waitUntil(function () win.localStorage["about:buildconfig"],
"about:buildconfig page-mod to be executed")
test.waitUntil(function () win.localStorage[testPageURI],
testPageURI + " page-mod to be executed")
.then(function () {
asserts.forEach(function(fn) {
fn(test, win);

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

@ -7,6 +7,8 @@
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. " +
@ -156,14 +158,23 @@ 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: content,
contentScript: "self.postMessage(window.localStorage.allowScript)",
contentURL: testURI,
contentScript: "if (window.location.href==='"+testURI+"')" +
" self.postMessage('reload');" +
"else " +
" 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, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, createBookmark, createBookmarkItem,
createBookmarkTree, addVisits
invalidResolve, invalidReject, createTree,
compareWithHost, createBookmark, createBookmarkItem,
createBookmarkTree, addVisits, resetPlaces
} = require('./places-helper');
const { promisedEmitter } = require('sdk/places/utils');
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
@ -941,13 +941,8 @@ exports.testCheckSaveOrder = function (assert, done) {
});
};
before(exports, name => {
clearAllBookmarks();
});
after(exports, name => {
clearAllBookmarks();
});
before(exports, (name, assert, done) => resetPlaces(done));
after(exports, (name, assert, done) => resetPlaces(done));
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 { clearHistory } = require('./places-helper');
const { resetPlaces } = 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 () {
clearHistory(() => {
resetPlaces(() => {
srv.stop(done);
});
});

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

@ -14,16 +14,15 @@ 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, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, addVisits, clearHistory
invalidResolve, invalidReject, createTree,
compareWithHost, addVisits, resetPlaces
} = 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();
@ -239,16 +238,11 @@ function toBeWithin (range) {
};
}
function clear (done) {
clearAllBookmarks();
clearHistory(done);
}
function searchP () {
return promisedEmitter(search.apply(null, Array.slice(arguments)));
}
before(exports, (name, assert, done) => clear(done));
after(exports, (name, assert, done) => clear(done));
before(exports, (name, assert, done) => resetPlaces(done));
after(exports, (name, assert, done) => resetPlaces(done));
require('test').run(exports);

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

@ -14,13 +14,15 @@ 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, clearBookmarks, createTree,
compareWithHost, clearAllBookmarks, createBookmark, createBookmarkTree
invalidResolve, invalidReject, createTree,
compareWithHost, createBookmark, createBookmarkTree, resetPlaces
} = require('./places-helper');
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
@ -29,7 +31,6 @@ 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 = [{
@ -51,7 +52,6 @@ exports.testBookmarksCreate = function (assert, done) {
compareWithHost(assert, data);
}, invalidReject(assert));
})).then(function () {
clearAllBookmarks();
done();
}, invalidReject(assert));
};
@ -72,7 +72,6 @@ exports.testBookmarksCreateFail = function (assert, done) {
assert.ok(reason, 'bookmark create should fail');
});
})).then(function () {
clearAllBookmarks();
done();
});
};
@ -94,7 +93,6 @@ exports.testBookmarkLastUpdated = function (assert, done) {
});
}).then(function (data) {
assert.ok(data.updated > timestamp, 'time has elapsed and updated the updated property');
clearAllBookmarks();
done();
});
};
@ -110,7 +108,6 @@ exports.testBookmarkRemove = function (assert, done) {
assert.throws(function () {
bmsrv.getItemTitle(id);
}, 'item should no longer exist');
clearAllBookmarks();
done();
}, console.error);
};
@ -133,7 +130,6 @@ exports.testBookmarkGet = function (assert, done) {
else
assert.equal(bookmark[prop], data[prop], 'correctly fetched ' + prop);
});
clearAllBookmarks();
done();
});
};
@ -151,7 +147,6 @@ 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();
});
};
@ -171,7 +166,6 @@ 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();
});
};
@ -186,7 +180,6 @@ 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();
});
};
@ -203,7 +196,6 @@ 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();
});
};
@ -228,7 +220,6 @@ 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();
});
};
@ -253,7 +244,6 @@ exports.testHostMultiQuery = function (assert, done) {
});
}).then(results => {
assert.equal(results.length, 0, 'query props should be AND\'d');
clearAllBookmarks();
done();
});
};
@ -263,7 +253,6 @@ 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);
};
@ -276,9 +265,12 @@ 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,50 +36,61 @@ exports.testPlainTextConsole = function(test) {
test.pass("PlainTextConsole instantiates");
con.log('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "info: " + name + ": testing 1 2,3,4\n",
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, 1, Array [2,3,4]\n",
"PlainTextConsole.log() must work.");
con.info('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "info: " + name + ": testing 1 2,3,4\n",
test.assertEqual(lastPrint(), "console.info: " + name + ": testing, 1, Array [2,3,4]\n",
"PlainTextConsole.info() must work.");
con.warn('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "warn: " + name + ": testing 1 2,3,4\n",
test.assertEqual(lastPrint(), "console.warn: " + name + ": testing, 1, Array [2,3,4]\n",
"PlainTextConsole.warn() must work.");
con.error('testing', 1, [2, 3, 4]);
test.assertEqual(lastPrint(), "error: " + name + ": testing 1 2,3,4\n",
test.assertEqual(prints[0], "console.error: " + name + ": \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(lastPrint(), "debug: " + name + ": testing 1 2,3,4\n",
test.assertEqual(prints[0], "console.debug: " + name + ": \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(), "info: " + name + ": testing undefined\n",
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, undefined\n",
"PlainTextConsole.log() must stringify undefined.");
con.log('testing', null);
test.assertEqual(lastPrint(), "info: " + name + ": testing null\n",
test.assertEqual(lastPrint(), "console.log: " + 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(), "info: " + name + ": testing obj.toString()\n",
"PlainTextConsole.log() must stringify custom toString.");
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, {}\n",
"PlainTextConsole.log() doesn't printify custom toString.");
con.log("testing", { toString: function() { throw "fail!"; } });
test.assertEqual(lastPrint(), "info: " + name + ": testing <toString() error>\n",
test.assertEqual(lastPrint(), "console.log: " + name + ": testing, {}\n",
"PlainTextConsole.log() must stringify custom bad toString.");
con.exception(new Error("blah"));
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):");
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 = []
prints = [];
try {
loadSubScript("invalid-url", {});
test.fail("successed in calling loadSubScript with invalid-url");
@ -87,16 +98,15 @@ exports.testPlainTextConsole = function(test) {
catch(e) {
con.exception(e);
}
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):");
test.assertEqual(prints[0], "console.error: " + name + ": \n");
test.assertEqual(prints[1], " Error creating URI (invalid URL scheme?)\n");
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();");
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 = [];
// 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,
@ -113,11 +123,11 @@ exports.testPlainTextConsole = function(test) {
// The messages we use to test the various methods, as a hash of methods.
let messages = {
debug: "debug: " + name + ": \n",
log: "info: " + name + ": \n",
info: "info: " + name + ": \n",
warn: "warn: " + name + ": \n",
error: "error: " + name + ": \n",
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",
};
for (let level in levels) {
@ -130,17 +140,20 @@ exports.testPlainTextConsole = function(test) {
prefs.set(SDK_LOG_LEVEL_PREF, level);
con[method]("");
prefs.set(SDK_LOG_LEVEL_PREF, "all");
test.assertEqual(lastPrint(), (methods[method] ? messages[method] : null),
test.assertEqual(prints.join(""),
(methods[method] ? messages[method] : ""),
"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(lastPrint(), messages["debug"],
test.assertEqual(prints.join(""), 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,6 +10,8 @@ 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);
@ -48,10 +50,10 @@ exports["test error reporting"] = function(assert) {
events.on(errorType, brokenHandler);
events.emit(errorType, { data: "yo yo" });
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.equal(messages.length, 2, "Got an exception");
assert.equal(messages[0], "console.error: " + self.name + ": \n",
"error is logged");
let text = messages[1];
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");
@ -104,6 +106,9 @@ 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;
@ -168,6 +173,9 @@ 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;
@ -184,7 +192,6 @@ 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 });
@ -206,13 +213,14 @@ 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,33 +6,17 @@ 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 } = require('sdk/tabs/utils');
const { openTab, closeTab, getTabContentWindow, getOwnerWindow } = 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 (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) {
if (isWindowPBSupported) {
exports.testGetTabs = function(assert, done) {
let tabCount = getTabs().length;
let windowCount = browserWindows.length;
open(null, {
features: {
private: true,
@ -41,12 +25,21 @@ else if (isWindowPBSupported) {
}
}).then(function(window) {
assert.ok(isPrivate(window), 'new tab is private');
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.ok(!isPrivate(window), 'all found windows are not 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');
fromIterator(browserWindows).forEach(function(window) {
assert.equal(isPrivate(window), false, 'all found windows are not private');
});
assert.equal(windows(null, {includePrivate: true}).length, 2, 'there are really two windows');
close(window).then(done);
});
};
@ -71,7 +64,4 @@ else if (isTabPBSupported) {
};
}
// Test disabled because of bug 855771
module.exports = {};
require('test').run(exports);

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

@ -5,116 +5,162 @@
var timer = require("sdk/timers");
const { Loader } = require("sdk/test/loader");
exports.testSetTimeout = function(test) {
exports.testSetTimeout = function(assert, end) {
timer.setTimeout(function() {
test.pass("testSetTimeout passed");
test.done();
assert.pass("testSetTimeout passed");
end();
}, 1);
test.waitUntilDone();
};
exports.testParamedSetTimeout = function(test) {
exports.testParamedSetTimeout = function(assert, end) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
timer.setTimeout.apply(null, [function() {
test.assertEqual(arguments.length, params.length);
assert.equal(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
test.assertEqual(params[i], arguments[i]);
test.done();
assert.equal(params[i], arguments[i]);
end();
}, 1].concat(params));
test.waitUntilDone();
};
exports.testClearTimeout = function(test) {
exports.testClearTimeout = function(assert, end) {
var myFunc = function myFunc() {
test.fail("myFunc() should not be called in testClearTimeout");
assert.fail("myFunc() should not be called in testClearTimeout");
};
var id = timer.setTimeout(myFunc, 1);
timer.setTimeout(function() {
test.pass("testClearTimeout passed");
test.done();
assert.pass("testClearTimeout passed");
end();
}, 2);
timer.clearTimeout(id);
test.waitUntilDone();
};
exports.testParamedClearTimeout = function(test) {
exports.testParamedClearTimeout = function(assert, end) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
var myFunc = function myFunc() {
test.fail("myFunc() should not be called in testClearTimeout");
assert.fail("myFunc() should not be called in testClearTimeout");
};
var id = timer.setTimeout(myFunc, 1);
timer.setTimeout.apply(null, [function() {
test.assertEqual(arguments.length, params.length);
assert.equal(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
test.assertEqual(params[i], arguments[i]);
test.done();
assert.equal(params[i], arguments[i]);
end();
}, 1].concat(params));
timer.clearTimeout(id);
test.waitUntilDone();
};
exports.testSetInterval = function (test) {
exports.testSetInterval = function (assert, end) {
var count = 0;
var id = timer.setInterval(function () {
count++;
if (count >= 5) {
timer.clearInterval(id);
test.pass("testSetInterval passed");
test.done();
assert.pass("testSetInterval passed");
end();
}
}, 1);
test.waitUntilDone();
};
exports.testParamedSetInerval = function(test) {
exports.testParamedSetInerval = function(assert, end) {
let params = [1, 'foo', { bar: 'test' }, null, undefined];
let count = 0;
let id = timer.setInterval.apply(null, [function() {
count ++;
if (count < 5) {
test.assertEqual(arguments.length, params.length);
assert.equal(arguments.length, params.length);
for (let i = 0, ii = params.length; i < ii; i++)
test.assertEqual(params[i], arguments[i]);
assert.equal(params[i], arguments[i]);
} else {
timer.clearInterval(id);
test.done();
end();
}
}, 1].concat(params));
test.waitUntilDone();
};
exports.testClearInterval = function (test) {
exports.testClearInterval = function (assert, end) {
timer.clearInterval(timer.setInterval(function () {
test.fail("setInterval callback should not be called");
assert.fail("setInterval callback should not be called");
}, 1));
var id = timer.setInterval(function () {
timer.clearInterval(id);
test.pass("testClearInterval passed");
test.done();
assert.pass("testClearInterval passed");
end();
}, 2);
test.waitUntilDone();
};
exports.testParamedClearInterval = function(test) {
exports.testParamedClearInterval = function(assert, end) {
timer.clearInterval(timer.setInterval(function () {
test.fail("setInterval callback should not be called");
assert.fail("setInterval callback should not be called");
}, 1, timer, {}, null));
let id = timer.setInterval(function() {
timer.clearInterval(id);
test.assertEqual(3, arguments.length);
test.done();
assert.equal(3, arguments.length);
end();
}, 2, undefined, 'test', {});
test.waitUntilDone();
};
exports.testUnload = function(test) {
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) {
var loader = Loader(module);
var sbtimer = loader.require("sdk/timers");
var myFunc = function myFunc() {
test.fail("myFunc() should not be called in testUnload");
assert.fail("myFunc() should not be called in testUnload");
};
sbtimer.setTimeout(myFunc, 1);
@ -123,9 +169,9 @@ exports.testUnload = function(test) {
sbtimer.setInterval(myFunc, 1, {}, null, 'bar', undefined, 87);
loader.unload();
timer.setTimeout(function() {
test.pass("timer testUnload passed");
test.done();
assert.pass("timer testUnload passed");
end();
}, 2);
test.waitUntilDone();
};
require("test").run(exports);

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

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

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

@ -61,6 +61,34 @@ 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),

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

@ -214,24 +214,6 @@
</menupopup>
</menu>
<menuseparator/>
<menuitem id="menu_stop"
class="show-only-for-keyboard"
label="&stopCmd.label;"
accesskey="&stopCmd.accesskey;"
command="Browser:Stop"
#ifdef XP_MACOSX
key="key_stop_mac"/>
#else
key="key_stop"/>
#endif
<menuitem id="menu_reload"
class="show-only-for-keyboard"
label="&reloadCmd.label;"
accesskey="&reloadCmd.accesskey;"
key="key_reload"
command="Browser:ReloadOrDuplicate"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator class="show-only-for-keyboard"/>
<menu id="viewFullZoomMenu" label="&fullZoom.label;"
accesskey="&fullZoom.accesskey;"
onpopupshowing="FullZoom.updateMenu();">
@ -332,34 +314,6 @@
new HistoryMenu(event);"
tooltip="bhTooltip"
popupsinherittooltip="true">
<menuitem id="historyMenuBack"
class="show-only-for-keyboard"
label="&backCmd.label;"
#ifdef XP_MACOSX
key="goBackKb2"
#else
key="goBackKb"
#endif
command="Browser:BackOrBackDuplicate"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="historyMenuForward"
class="show-only-for-keyboard"
label="&forwardCmd.label;"
#ifdef XP_MACOSX
key="goForwardKb2"
#else
key="goForwardKb"
#endif
command="Browser:ForwardOrForwardDuplicate"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="historyMenuHome"
class="show-only-for-keyboard"
label="&historyHomeCmd.label;"
oncommand="BrowserGoHome(event);"
onclick="checkForMiddleClick(this, event);"
key="goHome"/>
<menuseparator id="historyMenuHomeSeparator"
class="show-only-for-keyboard"/>
<menuitem id="menu_showAllHistory"
label="&showAllHistoryCmd2.label;"
#ifndef XP_MACOSX

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

@ -123,6 +123,7 @@ MOCHITEST_BROWSER_FILES = \
browser_bug556061.js \
browser_bug559991.js \
browser_bug561623.js \
browser_bug561636.js \
browser_bug562649.js \
browser_bug563588.js \
browser_bug565575.js \
@ -352,13 +353,6 @@ MOCHITEST_BROWSER_FILES += \
$(NULL)
endif
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
# Bug 766546.
MOCHITEST_BROWSER_FILES += \
browser_bug561636.js \
$(NULL)
endif
ifdef MOZ_DATA_REPORTING
MOCHITEST_BROWSER_FILES += \
browser_datareporting_notification.js \

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

@ -374,12 +374,15 @@ function()
Services.obs.addObserver(gObserver, "invalidformsubmit", false);
tab.linkedBrowser.addEventListener("load", function(e) {
let browser = e.currentTarget;
browser.removeEventListener("load", arguments.callee, true);
// Ignore load events from the iframe.
if (tab.linkedBrowser.contentDocument == e.target) {
let browser = e.currentTarget;
browser.removeEventListener("load", arguments.callee, true);
isnot(gBrowser.selectedTab.linkedBrowser, browser,
"This tab should have been loaded in background");
browser.contentDocument.getElementById('s').click();
isnot(gBrowser.selectedTab.linkedBrowser, browser,
"This tab should have been loaded in background");
browser.contentDocument.getElementById('s').click();
}
}, true);
tab.linkedBrowser.loadURI(uri);

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

@ -119,13 +119,6 @@ var PlacesOrganizer = {
for (var i=0; i < elements.length; i++) {
document.getElementById(elements[i]).setAttribute("disabled", "true");
}
// 3. Disable the keyboard shortcut for the History menu back/forward
// in order to support those in the Library
var historyMenuBack = document.getElementById("historyMenuBack");
historyMenuBack.removeAttribute("key");
var historyMenuForward = document.getElementById("historyMenuForward");
historyMenuForward.removeAttribute("key");
#endif
// remove the "Properties" context-menu item, we've our own details pane

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

@ -1,4 +1,4 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 0.8.291
Current extension version is: 0.8.377

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

@ -206,6 +206,10 @@ ChromeActions.prototype = {
// The data may not be downloaded so we need just retry getting the pdf with
// the original url.
var originalUri = NetUtil.newURI(data.originalUrl);
var filename = data.filename;
if (typeof filename !== 'string' || !/\.pdf$/i.test(filename)) {
filename = 'document.pdf';
}
var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri;
var extHelperAppSvc =
Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
@ -234,7 +238,9 @@ ChromeActions.prototype = {
// contentDisposition/contentDispositionFilename is readonly before FF18
channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
if (self.contentDispositionFilename) {
channel.contentDispositionFilename = self.contentDispositionFilename;
channel.contentDispositionFilename = self.contentDispositionFilename;
} else {
channel.contentDispositionFilename = filename;
}
} catch (e) {}
channel.setURI(originalUri);
@ -353,7 +359,7 @@ ChromeActions.prototype = {
}
}];
notificationBox.appendNotification(message, 'pdfjs-fallback', null,
notificationBox.PRIORITY_WARNING_LOW,
notificationBox.PRIORITY_INFO_LOW,
buttons,
function eventsCallback(eventType) {
// Currently there is only one event "removed" but if there are any other

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -42,17 +42,6 @@ select {
display: none !important;
}
#viewerContainer:-webkit-full-screen {
top: 0px;
border-top: 2px solid transparent;
background-color: #404040;
background-image: url(images/texture.png);
width: 100%;
height: 100%;
overflow: hidden;
cursor: none;
}
#viewerContainer:-moz-full-screen {
top: 0px;
border-top: 2px solid transparent;
@ -76,10 +65,6 @@ select {
}
:-webkit-full-screen .page {
margin-bottom: 100%;
}
:-moz-full-screen .page {
margin-bottom: 100%;
}
@ -88,10 +73,6 @@ select {
margin-bottom: 100%;
}
:-webkit-full-screen a:not(.internalLink) {
display: none;
}
:-moz-full-screen a:not(.internalLink) {
display: none;
}
@ -137,30 +118,15 @@ html[dir='rtl'] .innerCenter {
bottom: 0;
width: 200px;
visibility: hidden;
-webkit-transition-duration: 200ms;
-webkit-transition-timing-function: ease;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-ms-transition-duration: 200ms;
-ms-transition-timing-function: ease;
-o-transition-duration: 200ms;
-o-transition-timing-function: ease;
transition-duration: 200ms;
transition-timing-function: ease;
}
html[dir='ltr'] #sidebarContainer {
-webkit-transition-property: left;
-moz-transition-property: left;
-ms-transition-property: left;
-o-transition-property: left;
transition-property: left;
left: -200px;
}
html[dir='rtl'] #sidebarContainer {
-webkit-transition-property: right;
-ms-transition-property: right;
-o-transition-property: right;
transition-property: right;
right: -200px;
}
@ -183,30 +149,14 @@ html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer {
bottom: 0;
left: 0;
min-width: 320px;
-webkit-transition-duration: 200ms;
-webkit-transition-timing-function: ease;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-ms-transition-duration: 200ms;
-ms-transition-timing-function: ease;
-o-transition-duration: 200ms;
-o-transition-timing-function: ease;
transition-duration: 200ms;
transition-timing-function: ease;
}
html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
-webkit-transition-property: left;
-moz-transition-property: left;
-ms-transition-property: left;
-o-transition-property: left;
transition-property: left;
left: 200px;
}
html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
-webkit-transition-property: right;
-moz-transition-property: right;
-ms-transition-property: right;
-o-transition-property: right;
transition-property: right;
right: 200px;
}
@ -236,9 +186,7 @@ html[dir='rtl'] #sidebarContent {
right: 0;
bottom: 0;
left: 0;
}
.loadingInProgress #viewerContainer {
top: 39px;
outline: none;
}
.toolbar {
@ -299,30 +247,9 @@ html[dir='rtl'] #sidebarContent {
height: 100%;
background-color: #ddd;
overflow: hidden;
-moz-transition: width 200ms;
-ms-transition: width 200ms;
-webkit-transition: width 200ms;
transition: width 200ms;
}
@-moz-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@-ms-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@-webkit-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
@ -331,9 +258,6 @@ html[dir='rtl'] #sidebarContent {
#loadingBar .progress.indeterminate {
background-color: #999;
-moz-transition: none;
-ms-transition: none;
-webkit-transition: none;
transition: none;
}
@ -345,11 +269,9 @@ html[dir='rtl'] #sidebarContent {
width: 50px;
background-image: linear-gradient(to right, #999 0%, #fff 50%, #999 100%);
background-size: 100% 100% no-repeat;
background-size: 100% 100%;
background-repeat: no-repeat;
-moz-animation: progressIndeterminate 2s linear infinite;
-ms-animation: progressIndeterminate 2s linear infinite;
-webkit-animation: progressIndeterminate 2s linear infinite;
animation: progressIndeterminate 2s linear infinite;
}
@ -378,7 +300,6 @@ html[dir='rtl'] .findbar {
}
.findbar label {
-webkit-user-select: none;
-moz-user-select: none;
}
@ -530,18 +451,6 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton {
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.15) inset,
0 1px 0 hsla(0,0%,100%,.05);
-webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 150ms;
-webkit-transition-timing-function: ease;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 150ms;
-ms-transition-timing-function: ease;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 150ms;
-o-transition-timing-function: ease;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
@ -596,18 +505,6 @@ html[dir='rtl'] .splitToolbarButtonSeparator {
padding: 12px 0;
margin: 1px 0;
box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
-webkit-transition-property: padding;
-webkit-transition-duration: 10ms;
-webkit-transition-timing-function: ease;
-moz-transition-property: padding;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: ease;
-ms-transition-property: padding;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: ease;
-o-transition-property: padding;
-o-transition-duration: 10ms;
-o-transition-timing-function: ease;
transition-property: padding;
transition-duration: 10ms;
transition-timing-function: ease;
@ -622,23 +519,9 @@ html[dir='rtl'] .splitToolbarButtonSeparator {
color: hsl(0,0%,95%);
font-size: 12px;
line-height: 14px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
/* Opera does not support user-select, use <... unselectable="on"> instead */
cursor: default;
-webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 150ms;
-webkit-transition-timing-function: ease;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 150ms;
-ms-transition-timing-function: ease;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 150ms;
-o-transition-timing-function: ease;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
@ -674,18 +557,6 @@ html[dir='rtl'] .dropdownToolbarButton {
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset,
0 1px 0 hsla(0,0%,100%,.05);
-webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 10ms;
-webkit-transition-timing-function: linear;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: linear;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 10ms;
-o-transition-timing-function: linear;
transition-property: background-color, border-color, box-shadow;
transition-duration: 10ms;
transition-timing-function: linear;
@ -699,18 +570,6 @@ html[dir='rtl'] .dropdownToolbarButton {
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset,
0 1px 0 hsla(0,0%,100%,.05);
-webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 10ms;
-webkit-transition-timing-function: linear;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: linear;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 10ms;
-o-transition-timing-function: linear;
transition-property: background-color, border-color, box-shadow;
transition-duration: 10ms;
transition-timing-function: linear;
@ -740,7 +599,6 @@ html[dir='rtl'] .dropdownToolbarButton {
}
.dropdownToolbarButton > select {
-webkit-appearance: none;
-moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */
min-width: 140px;
font-size: 12px;
@ -783,7 +641,6 @@ html[dir='rtl'] .toolbarButton:first-child {
}
.toolbarButtonFlexibleSpacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
min-width: 30px;
}
@ -887,7 +744,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
}
.toolbarButton.bookmark {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-top: 3px;
@ -935,9 +791,9 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
font-size: 12px;
line-height: 14px;
outline-style: none;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
}
.toolbarField[type=checkbox] {
@ -951,12 +807,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
width: 40px;
}
.toolbarField.pageNumber::-webkit-inner-spin-button,
.toolbarField.pageNumber::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.toolbarField:hover {
background-color: hsla(0,0%,100%,.11);
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.43) hsla(0,0%,0%,.45);
@ -977,7 +827,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
font-size: 12px;
line-height: 14px;
text-align: left;
-webkit-user-select: none;
-moz-user-select: none;
cursor: default;
}
@ -1001,7 +850,7 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
}
.thumbnailImage {
-moz-transition-duration: 150ms;
transition-duration: 150ms;
border: 1px solid transparent;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
opacity: 0.8;
@ -1011,7 +860,7 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
.thumbnailSelectionRing {
border-radius: 2px;
padding: 7px;
-moz-transition-duration: 150ms;
transition-duration: 150ms;
}
a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage,
@ -1052,7 +901,6 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
bottom: 0;
padding: 4px 4px 0;
overflow: auto;
-webkit-user-select: none;
-moz-user-select: none;
}
@ -1361,6 +1209,9 @@ canvas {
#sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer {
display: none;
}
#viewerContainer {
overflow: visible;
}
#mainContainer, #viewerContainer, .page, .page canvas {
position: static;
@ -1371,6 +1222,7 @@ canvas {
.page {
float: left;
display: none;
border: none;
box-shadow: none;
}

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

@ -174,22 +174,22 @@ limitations under the License.
data-l10n-id="page_rotate_cw" ></menuitem>
</menu>
<div id="viewerContainer">
<div id="viewerContainer">
<div id="viewer" contextmenu="viewerContextMenu"></div>
</div>
<div id="errorWrapper" hidden='true'>
<div id="errorMessageLeft">
<span id="errorMessage"></span>
<button id="errorShowMore" onclick="" oncontextmenu="return false;" data-l10n-id="error_more_info">
<button id="errorShowMore" data-l10n-id="error_more_info">
More Information
</button>
<button id="errorShowLess" onclick="" oncontextmenu="return false;" data-l10n-id="error_less_info" hidden='true'>
<button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>
Less Information
</button>
</div>
<div id="errorMessageRight">
<button id="errorClose" oncontextmenu="return false;" data-l10n-id="error_close">
<button id="errorClose" data-l10n-id="error_close">
Close
</button>
</div>

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

@ -14,9 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar */
/* globals PDFFindController, ProgressBar, getFileName, CustomStyle */
/* globals getOutputScale, TextLayerBuilder */
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
PDFHistory */
'use strict';
@ -46,6 +47,7 @@ var FindStates = {
FIND_PENDING: 3
};
PDFJS.imageResourcesPath = './images/';
PDFJS.workerSrc = '../build/pdf.js';
var mozL10n = document.mozL10n || document.webL10n;
@ -126,6 +128,61 @@ function getOutputScale() {
};
}
/**
* Scrolls specified element into view of its parent.
* element {Object} The element to be visible.
* spot {Object} The object with the top property -- offset from the top edge.
*/
function scrollIntoView(element, spot) {
// Assuming offsetParent is available (it's not available when viewer is in
// hidden iframe or object). We have to scroll: if the offsetParent is not set
// producing the error. See also animationStartedClosure.
var parent = element.offsetParent;
var offsetY = element.offsetTop + element.clientTop;
if (!parent) {
console.error('offsetParent is not set -- cannot scroll');
return;
}
while (parent.clientHeight == parent.scrollHeight) {
offsetY += parent.offsetTop;
parent = parent.offsetParent;
if (!parent)
return; // no need to scroll
}
if (spot)
offsetY += spot.top;
parent.scrollTop = offsetY;
}
/**
* Returns the filename or guessed filename from the url (see issue 3455).
* url {String} The original PDF location.
* @return {String} Guessed PDF file name.
*/
function getPDFFileNameFromURL(url) {
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
// SCHEME HOST 1.PATH 2.QUERY 3.REF
// Pattern to get last matching NAME.pdf
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) ||
reFilename.exec(splitURI[2]) ||
reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') != -1) {
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
try {
suggestedFilename =
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch(e) { // Possible (extremely rare) errors:
// URIError "Malformed URI", e.g. for "%AA.pdf"
// TypeError "null has no properties", e.g. for "%2F.pdf"
}
}
}
return suggestedFilename || 'document.pdf';
}
var ProgressBar = (function ProgressBarClosure() {
@ -135,15 +192,18 @@ var ProgressBar = (function ProgressBarClosure() {
function ProgressBar(id, opts) {
// Fetch the sub-elements for later
// Fetch the sub-elements for later.
this.div = document.querySelector(id + ' .progress');
// Get options, with sensible defaults
// Get the loading bar element, so it can be resized to fit the viewer.
this.bar = this.div.parentNode;
// Get options, with sensible defaults.
this.height = opts.height || 100;
this.width = opts.width || 100;
this.units = opts.units || '%';
// Initialize heights
// Initialize heights.
this.div.style.height = this.height + this.units;
this.percent = 0;
}
@ -170,6 +230,22 @@ var ProgressBar = (function ProgressBarClosure() {
this._indeterminate = isNaN(val);
this._percent = clamp(val, 0, 100);
this.updateBar();
},
setWidth: function ProgressBar_setWidth(viewer) {
if (viewer) {
var container = viewer.parentNode;
var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
if (scrollbarWidth > 0) {
this.bar.setAttribute('style', 'width: calc(100% - ' +
scrollbarWidth + 'px);');
}
}
},
hide: function ProgressBar_hide() {
this.bar.classList.add('hidden');
this.bar.removeAttribute('style');
}
};
@ -190,46 +266,8 @@ var Cache = function cacheCache(size) {
function scrollIntoView(element, spot) {
// Assuming offsetParent is available (it's not available when viewer is in
// hidden iframe or object). We have to scroll: if the offsetParent is not set
// producing the error. See also animationStartedClosure.
var parent = element.offsetParent;
var offsetY = element.offsetTop + element.clientTop;
if (!parent) {
console.error('offsetParent is not set -- cannot scroll');
return;
}
while (parent.clientHeight == parent.scrollHeight) {
offsetY += parent.offsetTop;
parent = parent.offsetParent;
if (!parent)
return; // no need to scroll
}
if (spot)
offsetY += spot.top;
parent.scrollTop = offsetY;
}
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var FirefoxCom = (function FirefoxComClosure() {
'use strict';
return {
/**
* Creates an event that the extension is listening for and will
@ -284,6 +322,38 @@ var FirefoxCom = (function FirefoxComClosure() {
};
})();
var DownloadManager = (function DownloadManagerClosure() {
function DownloadManager() {}
DownloadManager.prototype = {
downloadUrl: function DownloadManager_downloadUrl(url, filename) {
FirefoxCom.request('download', {
originalUrl: url,
filename: filename
});
},
download: function DownloadManager_download(blob, url, filename) {
var blobUrl = window.URL.createObjectURL(blob);
FirefoxCom.request('download', {
blobUrl: blobUrl,
originalUrl: url,
filename: filename
},
function response(err) {
if (err && this.onerror) {
this.onerror(err);
}
window.URL.revokeObjectURL(blobUrl);
}.bind(this)
);
}
};
return DownloadManager;
})();
// Settings Manager - This is a utility for saving settings
// First we see if localStorage is available
@ -874,7 +944,7 @@ var PDFHistory = {
var state = window.history.state;
if (this._isStateObjectDefined(state)) {
// This case corresponds to navigating back to the document
// This corresponds to navigating back to the document
// from another page in the browser history.
if (state.target.dest) {
this.initialDestination = state.target.dest;
@ -885,7 +955,7 @@ var PDFHistory = {
this.uid = state.uid + 1;
this.current = state.target;
} else {
// This case corresponds to the loading of a new document.
// This corresponds to the loading of a new document.
if (state && state.fingerprint &&
this.fingerprint !== state.fingerprint) {
// Reinitialize the browsing history when a new document
@ -909,10 +979,14 @@ var PDFHistory = {
} else {
// Handle the user modifying the hash of a loaded document.
self.previousHash = window.location.hash.substring(1);
// If the history is empty when the hash changes,
// update the previous entry in the browser history.
if (self.uid === 0) {
var previousParams = (self.previousHash && self.currentBookmark &&
self.previousHash !== self.currentBookmark) ?
{ hash: self.currentBookmark } : { page: 1 };
{ hash: self.currentBookmark, page: self.currentPage } :
{ page: 1 };
self.historyUnlocked = false;
self.allowHashChange = false;
window.history.back();
@ -921,23 +995,29 @@ var PDFHistory = {
self.historyUnlocked = true;
}
self._pushToHistory({ hash: self.previousHash }, false, true);
if (self.currentBookmark) {
self.previousBookmark = self.currentBookmark;
}
self._updatePreviousBookmark();
}
}, false);
window.addEventListener('beforeunload',
function pdfHistoryBeforeunload(evt) {
function pdfHistoryBeforeUnload() {
var previousParams = self._getPreviousParams(null, true);
if (previousParams) {
self._pushToHistory(previousParams, false);
}
if (PDFView.isPresentationMode) {
// Prevent the user from accidentally navigating away from
// the document when presentation mode is active.
evt.preventDefault();
var replacePrevious = (!self.current.dest &&
self.current.hash !== self.previousHash);
self._pushToHistory(previousParams, false, replacePrevious);
self._updatePreviousBookmark();
}
// Remove the event listener when navigating away from the document,
// since 'beforeunload' prevents Firefox from caching the document.
window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false);
}
window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
window.addEventListener('pageshow', function pdfHistoryPageShow(evt) {
// If the entire viewer (including the PDF file) is cached in the browser,
// we need to reattach the 'beforeunload' event listener since
// the 'DOMContentLoaded' event is not fired on 'pageshow'.
window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
}, false);
},
@ -966,16 +1046,21 @@ var PDFHistory = {
return temp;
},
_updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() {
if (this.updatePreviousBookmark &&
this.currentBookmark && this.currentPage) {
this.previousBookmark = this.currentBookmark;
this.previousPage = this.currentPage;
this.updatePreviousBookmark = false;
}
},
updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark,
pageNum) {
if (this.initialized) {
this.currentBookmark = bookmark.substring(1);
this.currentPage = pageNum | 0;
if (this.updatePreviousBookmark) {
this.previousBookmark = this.currentBookmark;
this.previousPage = this.currentPage;
this.updatePreviousBookmark = false;
}
this._updatePreviousBookmark();
}
},
@ -998,10 +1083,20 @@ var PDFHistory = {
if (params.page) {
params.page |= 0;
}
if (isInitialBookmark && this.uid === 0) {
this._pushToHistory(params, false);
this.previousHash = window.location.hash.substring(1);
if (isInitialBookmark) {
var target = window.history.state.target;
if (!target) {
// Invoked when the user specifies an initial bookmark,
// thus setting PDFView.initialBookmark, when the document is loaded.
this._pushToHistory(params, false);
this.previousHash = window.location.hash.substring(1);
}
this.updatePreviousBookmark = this.nextHashParam ? false : true;
if (target) {
// If the current document is reloaded,
// avoid creating duplicate entries in the history.
this._updatePreviousBookmark();
}
return;
}
if (this.nextHashParam && this.nextHashParam === params.hash) {
@ -1014,8 +1109,11 @@ var PDFHistory = {
if (this.current.hash) {
if (this.current.hash !== params.hash) {
this._pushToHistory(params, true);
} else if (!this.current.page && params.page) {
this._pushToHistory(params, false, true);
} else {
if (!this.current.page && params.page) {
this._pushToHistory(params, false, true);
}
this.updatePreviousBookmark = true;
}
} else {
this._pushToHistory(params, true);
@ -1064,7 +1162,8 @@ var PDFHistory = {
if (addPrevious && !overwrite) {
var previousParams = this._getPreviousParams();
if (previousParams) {
this._pushToHistory(previousParams, false);
var replacePrevious = (this.current.hash !== this.previousHash);
this._pushToHistory(previousParams, false, replacePrevious);
}
}
if (overwrite || this.uid === 0) {
@ -1135,6 +1234,7 @@ var PDFHistory = {
}
};
var PDFView = {
pages: [],
thumbnails: [],
@ -1387,16 +1487,21 @@ var PDFView = {
return support;
},
get loadingBar() {
var bar = new ProgressBar('#loadingBar', {});
Object.defineProperty(this, 'loadingBar', { value: bar,
enumerable: true,
configurable: true,
writable: false });
return bar;
},
get isHorizontalScrollbarEnabled() {
var div = document.getElementById('viewerContainer');
return div.scrollWidth > div.clientWidth;
},
initPassiveLoading: function pdfViewInitPassiveLoading() {
if (!PDFView.loadingBar) {
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
}
var pdfDataRangeTransport = {
rangeListeners: [],
progressListeners: [],
@ -1495,10 +1600,6 @@ var PDFView = {
}
}
if (!PDFView.loadingBar) {
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
}
this.pdfDocument = null;
var self = this;
self.loading = true;
@ -1555,32 +1656,30 @@ var PDFView = {
download: function pdfViewDownload() {
function noData() {
FirefoxCom.request('download', { originalUrl: url });
downloadManager.downloadUrl(url, filename);
}
var url = this.url.split('#')[0];
// Document isn't ready just try to download with the url.
if (!this.pdfDocument) {
var filename = getPDFFileNameFromURL(url);
var downloadManager = new DownloadManager();
downloadManager.onerror = function (err) {
// This error won't really be helpful because it's likely the
// fallback won't work either (or is already open).
PDFView.error('PDF failed to download.');
};
if (!this.pdfDocument) { // the PDF is not ready yet
noData();
return;
}
this.pdfDocument.getData().then(
function getDataSuccess(data) {
var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
var blobUrl = window.URL.createObjectURL(blob);
FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
function response(err) {
if (err) {
// This error won't really be helpful because it's likely the
// fallback won't work either (or is already open).
PDFView.error('PDF failed to download.');
}
window.URL.revokeObjectURL(blobUrl);
}
);
downloadManager.download(blob, url, filename);
},
noData // Error occurred try downloading with just the url.
);
).then(null, noData);
},
fallback: function pdfViewFallback() {
@ -1598,19 +1697,12 @@ var PDFView = {
},
navigateTo: function pdfViewNavigateTo(dest) {
var destString = '';
var self = this;
PDFJS.Promise.all([this.pagesPromise,
this.destinationsPromise]).then(function() {
var destString = '';
if (typeof dest === 'string') {
destString = dest;
dest = self.destinations[dest];
}
if (!(dest instanceof Array)) {
return; // invalid destination
}
var goToDestination = function(destRef) {
self.pendingRefStr = null;
// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
var destRef = dest[0];
var pageNumber = destRef instanceof Object ?
self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
(destRef + 1);
@ -1623,7 +1715,24 @@ var PDFView = {
// Update the browsing history.
PDFHistory.push({ dest: dest, hash: destString, page: pageNumber });
} else {
self.pendingRefStrLoaded = new PDFJS.Promise();
self.pendingRefStr = destRef.num + ' ' + destRef.gen + ' R';
self.pendingRefStrLoaded.then(function() {
goToDestination(destRef);
});
}
};
this.destinationsPromise.then(function() {
if (typeof dest === 'string') {
destString = dest;
dest = self.destinations[dest];
}
if (!(dest instanceof Array)) {
return; // invalid destination
}
goToDestination(dest[0]);
});
},
@ -1728,8 +1837,7 @@ var PDFView = {
errorWrapper.setAttribute('hidden', 'true');
pdfDocument.dataLoaded().then(function() {
var loadingBar = document.getElementById('loadingBar');
loadingBar.classList.add('hidden');
PDFView.loadingBar.hide();
var outerContainer = document.getElementById('outerContainer');
outerContainer.classList.remove('loadingInProgress');
});
@ -1791,6 +1899,8 @@ var PDFView = {
event.initCustomEvent('documentload', true, true, {});
window.dispatchEvent(event);
PDFView.loadingBar.setWidth(container);
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
var pagePromise = pdfDocument.getPage(pageNum);
pagePromise.then(function(pdfPage) {
@ -1809,6 +1919,10 @@ var PDFView = {
var pageRef = pdfPage.ref;
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
pagesRefMap[refStr] = pdfPage.pageNumber;
if (self.pendingRefStr && self.pendingRefStr === refStr) {
self.pendingRefStrLoaded.resolve();
}
});
pagePromises.push(pagePromise);
}
@ -3097,11 +3211,9 @@ var TextLayerBuilder = function textLayerBuilder(options) {
if (width > 0) {
var textScale = textDiv.dataset.canvasWidth / width;
var rotation = textDiv.dataset.angle;
var transform = 'scale(' + textScale + ', 1)';
if (bidiTexts[i].dir === 'ttb') {
transform = 'rotate(90deg) ' + transform;
}
transform = 'rotate(' + rotation + 'deg) ' + transform;
CustomStyle.setProp('transform' , textDiv, transform);
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
@ -3141,13 +3253,14 @@ var TextLayerBuilder = function textLayerBuilder(options) {
// vScale and hScale already contain the scaling to pixel units
var fontHeight = geom.fontSize * Math.abs(geom.vScale);
textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
textDiv.dataset.fontName = geom.fontName;
textDiv.dataset.angle = geom.angle * (180 / Math.PI);
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = geom.fontFamily;
textDiv.style.left = geom.x + 'px';
textDiv.style.top = (geom.y - fontHeight) + 'px';
textDiv.style.left = (geom.x + (fontHeight * Math.sin(geom.angle))) + 'px';
textDiv.style.top = (geom.y - (fontHeight * Math.cos(geom.angle))) + 'px';
// The content of the div is set in the `setTextContent` function.
@ -3175,7 +3288,7 @@ var TextLayerBuilder = function textLayerBuilder(options) {
textDiv.textContent = bidiText.str;
// bidiText.dir may be 'ttb' for vertical texts.
textDiv.dir = bidiText.dir === 'rtl' ? 'rtl' : 'ltr';
textDiv.dir = bidiText.dir;
}
this.setupRenderLayoutTimer();
@ -3877,12 +3990,18 @@ window.addEventListener('keydown', function keydown(evt) {
if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
// either CTRL or META key with optional SHIFT.
switch (evt.keyCode) {
case 70:
case 70: // f
if (!PDFView.supportsIntegratedFind) {
PDFFindBar.toggle();
handled = true;
}
break;
case 71: // g
if (!PDFView.supportsIntegratedFind) {
PDFFindBar.dispatchEvent('again', cmd === 5 || cmd === 12);
handled = true;
}
break;
case 61: // FF/Mac '='
case 107: // FF '+' and '='
case 187: // Chrome '+'
@ -3904,14 +4023,12 @@ window.addEventListener('keydown', function keydown(evt) {
}
}
// CTRL or META with or without SHIFT.
if (cmd == 1 || cmd == 8 || cmd == 5 || cmd == 12) {
// CTRL+ALT or Option+Command
if (cmd === 3 || cmd === 10) {
switch (evt.keyCode) {
case 71: // g
if (!PDFView.supportsIntegratedFind) {
PDFFindBar.dispatchEvent('again', cmd == 5 || cmd == 12);
handled = true;
}
case 80: // p
PDFView.presentationMode();
handled = true;
break;
}
}

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

@ -20,11 +20,11 @@ browser.contentHandlers.types.0.uri=http://add.my.yahoo.com/rss?url=%s
# profile database. Note that "new" is defined as "has a different URL"; this
# means that it's not possible to update the name of existing handler, so
# don't make any spelling errors here.
gecko.handlerService.defaultHandlersVersion=3
gecko.handlerService.defaultHandlersVersion=4
# The default set of protocol handlers for webcal:
gecko.handlerService.schemes.webcal.0.name=30 Boxes
gecko.handlerService.schemes.webcal.0.uriTemplate=http://30boxes.com/external/widget?refer=ff&url=%s
gecko.handlerService.schemes.webcal.0.uriTemplate=https://30boxes.com/external/widget?refer=ff&url=%s
# The default set of protocol handlers for mailto:
gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail

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

@ -317,7 +317,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY historyUndoWindowMenu.label "Recently Closed Windows">
<!ENTITY historyRestoreLastSession.label "Restore Previous Session">
<!ENTITY historyHomeCmd.label "Home">
<!ENTITY showAllHistoryCmd2.label "Show All History">
<!ENTITY showAllHistoryCmd.commandkey "H">

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

@ -37,9 +37,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
XPCOMUtils.defineLazyModuleGetter(this, "CrossSlide",
"resource:///modules/CrossSlide.jsm");
XPCOMUtils.defineLazyGetter(this, "OS",
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "View",
"resource:///modules/View.jsm");

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

@ -567,7 +567,8 @@
</vbox>
<cssthrobber id="sync-connected-throbber"
class="syncThrobber"
collapsed="true" />
collapsed="true"
disabled="true" />
</hbox>
<label id="sync-disconnect-label"
class="text-link"

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

@ -371,24 +371,20 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
list-style-image: url("moz-icon://stock/gtk-preferences?size=menu");
}
#menu_stop,
#context-stop {
list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
}
#menu_stop[disabled],
#context-stop[disabled] {
list-style-image: url("moz-icon://stock/gtk-stop?size=menu&state=disabled");
}
#menu_reload,
#placesContext_reload,
#context-reload,
#context-reloadframe {
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
}
#menu_reload[disabled],
#context-reload[disabled] {
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
}
@ -405,50 +401,38 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
list-style-image: url("moz-icon://stock/gtk-zoom-100?size=menu");
}
#historyMenuBack,
#context-back {
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu");
}
#historyMenuBack[disabled],
#context-back[disabled] {
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled");
}
#historyMenuBack:-moz-locale-dir(rtl),
#context-back:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu");
}
#historyMenuBack[disabled]:-moz-locale-dir(rtl),
#context-back[disabled]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled");
}
#historyMenuForward,
#context-forward {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu");
}
#historyMenuForward[disabled],
#context-forward[disabled] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
}
#historyMenuForward:-moz-locale-dir(rtl),
#context-forward:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu");
}
#historyMenuForward[disabled]:-moz-locale-dir(rtl),
#context-forward[disabled]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
}
#historyMenuHome {
list-style-image: url("moz-icon://stock/gtk-home?size=menu");
}
#appmenu_history,
#appmenu_showAllHistory,
#menu_showAllHistory {

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

@ -538,17 +538,23 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, docRequest, csp) {
// specifying either default-src or script-src, and to blocking inline
// styles by specifying either default-src or style-src.
if ("default-src" in dirs) {
aCSPR._allowInlineScripts = false;
aCSPR._allowInlineStyles = false;
aCSPR._allowEval = false;
} else {
if ("script-src" in dirs) {
// Parse the source list (look ahead) so we can set the defaults properly,
// honoring the 'unsafe-inline' and 'unsafe-eval' keywords
var defaultSrcValue = CSPSourceList.fromString(dirs["default-src"], null, self);
if (!defaultSrcValue._allowUnsafeInline) {
aCSPR._allowInlineScripts = false;
aCSPR._allowEval = false;
}
if ("style-src" in dirs) {
aCSPR._allowInlineStyles = false;
}
if (!defaultSrcValue._allowUnsafeEval) {
aCSPR._allowEval = false;
}
}
if ("script-src" in dirs) {
aCSPR._allowInlineScripts = false;
aCSPR._allowEval = false;
}
if ("style-src" in dirs) {
aCSPR._allowInlineStyles = false;
}
directive:

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

@ -633,6 +633,9 @@ MOCHITEST_FILES_C= \
test_declare_stylesheet_obsolete.html \
variable_style_sheet.sjs \
test_processing_instruction_update_stylesheet.xhtml \
test_CSP_bug888172.html \
file_CSP_bug888172.html \
file_CSP_bug888172.sjs \
$(NULL)
# OOP tests don't work on Windows (bug 763081) or native-fennec

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

@ -0,0 +1,28 @@
<!doctype html>
<html>
<body>
<ol>
<li id="unsafe-inline-script">Inline script (green if allowed, black if blocked)</li>
<li id="unsafe-eval-script">Eval script (green if allowed, black if blocked)</li>
<li id="unsafe-inline-style">Inline style (green if allowed, black if blocked)</li>
</ol>
<script>
// Use inline script to set a style attribute
document.getElementById("unsafe-inline-script").style.color = "green";
// Use eval to set a style attribute
// try/catch is used because CSP causes eval to throw an exception when it
// is blocked, which would derail the rest of the tests in this file.
try {
eval('document.getElementById("unsafe-eval-script").style.color = "green";');
} catch (e) {}
</script>
<style>
li#unsafe-inline-style {
color: green;
}
</style>
</body>
</html>

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

@ -0,0 +1,43 @@
// SJS file for CSP mochitests
Components.utils.import("resource://gre/modules/NetUtil.jsm");
function loadHTMLFromFile(path) {
// Load the HTML to return in the response from file.
// Since it's relative to the cwd of the test runner, we start there and
// append to get to the actual path of the file.
var testHTMLFile =
Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurWorkD", Components.interfaces.nsILocalFile);
var dirs = path.split("/");
for (var i = 0; i < dirs.length; i++) {
testHTMLFile.append(dirs[i]);
}
var testHTMLFileStream =
Components.classes["@mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
testHTMLFileStream.init(testHTMLFile, -1, 0, 0);
var testHTML = NetUtil.readInputStreamToString(testHTMLFileStream, testHTMLFileStream.available());
return testHTML;
}
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
// Deliver the CSP policy encoded in the URI
if (query['csp'])
response.setHeader("Content-Security-Policy", unescape(query['csp']), false);
// Send HTML to test allowed/blocked behaviors
response.setHeader("Content-Type", "text/html", false);
response.write(loadHTMLFromFile("tests/content/base/test/file_CSP_bug888172.html"));
}

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

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 888172 - CSP 1.0 does not process 'unsafe-inline' or 'unsafe-eval' for default-src</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe style="width:100%;" id='testframe1'></iframe>
<iframe style="width:100%;" id='testframe2'></iframe>
<iframe style="width:100%;" id='testframe3'></iframe>
<script class="testbody" type="text/javascript">
//////////////////////////////////////////////////////////////////////
// set up and go
SimpleTest.waitForExplicitFinish();
// utilities for check functions
// black means the style wasn't applied, applied styles are green
var green = 'rgb(0, 128, 0)';
var black = 'rgb(0, 0, 0)';
function getElementColorById(doc, id) {
return window.getComputedStyle(doc.contentDocument.getElementById(id)).color;
}
// We test both script and style execution by observing changes in computed styles
function checkDefaultSrcOnly() {
var testframe = document.getElementById('testframe1');
ok(getElementColorById(testframe, 'unsafe-inline-script') === green, "Inline script should be allowed");
ok(getElementColorById(testframe, 'unsafe-eval-script') === green, "Eval should be allowed");
ok(getElementColorById(testframe, 'unsafe-inline-style') === green, "Inline style should be allowed");
}
function checkDefaultSrcWithScriptSrc() {
var testframe = document.getElementById('testframe2');
ok(getElementColorById(testframe, 'unsafe-inline-script') === black, "Inline script should be blocked");
ok(getElementColorById(testframe, 'unsafe-eval-script') === black, "Eval should be blocked");
ok(getElementColorById(testframe, 'unsafe-inline-style') === green, "Inline style should be allowed");
}
function checkDefaultSrcWithStyleSrc() {
var testframe = document.getElementById('testframe3');
ok(getElementColorById(testframe, 'unsafe-inline-script') === green, "Inline script should be allowed");
ok(getElementColorById(testframe, 'unsafe-eval-script') === green, "Eval should be allowed");
ok(getElementColorById(testframe, 'unsafe-inline-style') === black, "Inline style should be blocked");
// last test calls finish
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('testframe1').src = 'file_CSP_bug888172.sjs?csp=' +
escape("Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'");
document.getElementById('testframe1').addEventListener('load', checkDefaultSrcOnly, false);
document.getElementById('testframe2').src = 'file_CSP_bug888172.sjs?csp=' +
escape("Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self'");
document.getElementById('testframe2').addEventListener('load', checkDefaultSrcWithScriptSrc, false);
document.getElementById('testframe3').src = 'file_CSP_bug888172.sjs?csp=' +
escape("Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self'");
document.getElementById('testframe3').addEventListener('load', checkDefaultSrcWithStyleSrc, false);
}
);
</script>
</pre>
</body>
</html>

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

@ -360,10 +360,10 @@ MediaPluginReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeight
return nullptr;
}
nsRefPtr<mozilla::layers::SharedRGBImage> rgbImage;
nsRefPtr<mozilla::layers::DeprecatedSharedRGBImage> rgbImage;
switch(aColorFormat) {
case MPAPI::RGB565:
rgbImage = mozilla::layers::SharedRGBImage::Create(mImageContainer,
rgbImage = mozilla::layers::DeprecatedSharedRGBImage::Create(mImageContainer,
nsIntSize(aWidth, aHeight),
gfxASurface::ImageFormatRGB16_565);
mImage = rgbImage;

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

@ -93,7 +93,7 @@ nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
nativeThis->OnFinalize(obj);
// The addref was part of JSObject construction
NS_RELEASE(nativeThis);
nsContentUtils::DeferredFinalize(nativeThis);
}

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

@ -53,6 +53,10 @@ AlarmsManager.prototype = {
throw Components.results.NS_ERROR_FAILURE;
}
if (!aDate) {
throw Components.results.NS_ERROR_INVALID_ARG;
}
let isIgnoreTimezone = true;
switch (aRespectTimezone) {
case "honorTimezone":
@ -64,13 +68,13 @@ AlarmsManager.prototype = {
break;
default:
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
throw Components.results.NS_ERROR_INVALID_ARG;
break;
}
let request = this.createRequest();
this._cpmm.sendAsyncMessage(
"AlarmsManager:Add",
"AlarmsManager:Add",
{ requestId: this.getRequestId(request),
date: aDate,
ignoreTimezone: isIgnoreTimezone,

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

@ -25,23 +25,26 @@
} catch (e) {
ok(false,
"Unexpected exception trying to add alarm for tomorrow.");
// Proceed to next test.
return testPastDate();
}
domRequest.onsuccess = function(e) {
navigator.mozAlarms.remove(e.target.result);
ok(true, "Add alarm for future date.");
// Awesome, no error so proceed to next test
// Awesome, no error so proceed to next test.
testPastDate();
};
domRequest.onerror = function(e) {
ok(false, "Unable to add alarm for tomorrow`.");
// Proceed to next test.
testPastDate();
};
}
// Verify passing a Date that's already past fails
// Verify passing a Date that's already past doesn't fail (it should fire immediately).
function testPastDate() {
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
@ -52,61 +55,61 @@
} catch (e) {
ok(false,
"Unexpected exception trying to add alarm for yesterday.");
return testNull();
// Move on to the next test.
testNullDate();
}
domRequest.onsuccess = function(e) {
navigator.mozAlarms.remove(e.target.result);
ok(true, "Should be able to add alarm for already past date, which should fire immediately.");
testNull();
// Move on to the next test.
testNullDate();
};
domRequest.onerror = function(e) {
ok(false, "Unable to add alarm for yesterday.");
// Errors as it should, on to the next test
testNull();
// Move on to the next test.
testNullDate();
}
}
// Verify passing null does indeed fail
function testNull() {
var domRequest;
function testNullDate() {
try {
domRequest = navigator.mozAlarms.add(null, "honorTimezone", {});
navigator.mozAlarms.add(null, "honorTimezone", {});
ok(false, "Expected an exception to be thrown for alarm with null date.");
} catch(e) {
ok(false, "Unexpected exception thrown while testing null case.");
// Exception thrown
return SimpleTest.finish();
ok(true, "Exception thrown for alarm with null date.");
}
domRequest.onsuccess = function(e) {
// Null should not be valid
ok(false, "Null should not be accepted as input for `date` param.");
SimpleTest.finish();
};
domRequest.onerror = function(e) {
// Null should not be valid
ok(true, "Passing null for date value causes failure.");
SimpleTest.finish();
};
// Move on to the next test.
testInvalidTimeZone()
}
function testInvalidTimeZone() {
try {
navigator.mozAlarms.add(new Date(), "badTimeZoneArg", {});
ok(false, "Expected an exception to be thrown while testing bad time zone arg.");
} catch(e) {
ok(true, "Exception thrown while testing bad time zone arg.");
}
SimpleTest.finish();
}
function startTests() {
SpecialPowers.pushPrefEnv({"set": [["dom.mozAlarms.enabled", true]]}, function() {
// Currently applicable only on FxOS
if (navigator.userAgent.indexOf("Mobile") != -1 &&
navigator.appVersion.indexOf("Android") == -1) {
navigator.appVersion.indexOf("Android") == -1)
{
testFutureDate();
} else {
ok(true, "mozAlarms on Firefox OS only.");
SimpleTest.finish();
}
});
}

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

@ -59,11 +59,6 @@ AppsService.prototype = {
return DOMApplicationRegistry.getManifestURLByLocalId(aLocalId);
},
getAppFromObserverMessage: function getAppFromObserverMessage(aMessage) {
debug("getAppFromObserverMessage( " + aMessage + " )");
return DOMApplicationRegistry.getAppFromObserverMessage(aMessage);
},
getCoreAppsBasePath: function getCoreAppsBasePath() {
debug("getCoreAppsBasePath()");
return DOMApplicationRegistry.getCoreAppsBasePath();

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

@ -104,11 +104,6 @@ this.DOMApplicationRegistry = {
return AppsUtils.getManifestURLByLocalId(this.webapps, aLocalId);
},
getAppFromObserverMessage: function getAppFromObserverMessage(aMessage) {
debug("getAppFromObserverMessage " + aMessage);
return AppsUtils.getAppFromObserverMessage(this.webapps. aMessage);
},
getCoreAppsBasePath: function getCoreAppsBasePath() {
debug("getCoreAppsBasePath() not yet supported on child!");
return null;

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

@ -176,21 +176,6 @@ this.AppsUtils = {
return "";
},
getAppFromObserverMessage: function(aApps, aMessage) {
let data = JSON.parse(aMessage);
for (let id in aApps) {
let app = aApps[id];
if (app.origin != data.origin) {
continue;
}
return this.cloneAsMozIApplication(app);
}
return null;
},
getCoreAppsBasePath: function getCoreAppsBasePath() {
debug("getCoreAppsBasePath()");
try {

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

@ -2982,10 +2982,6 @@ this.DOMApplicationRegistry = {
return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
},
getAppFromObserverMessage: function(aMessage) {
return AppsUtils.getAppFromObserverMessage(this.webapps, aMessage);
},
getCoreAppsBasePath: function() {
return AppsUtils.getCoreAppsBasePath();
},

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

@ -17,7 +17,7 @@ interface nsIURI;
* This service allows accessing some DOMApplicationRegistry methods from
* non-javascript code.
*/
[scriptable, uuid(27b995cf-bec8-47de-aa48-6117c950fce3)]
[scriptable, uuid(9b23d8f0-b2f3-46af-bff4-3df6c3cb69db)]
interface nsIAppsService : nsISupports
{
mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
@ -40,13 +40,6 @@ interface nsIAppsService : nsISupports
*/
DOMString getManifestURLByLocalId(in unsigned long localId);
/**
* Returns the app that is related to the message.
* This is a helper to not have to worry about what is the actual structure
* of the message when listening to one.
*/
mozIApplication getAppFromObserverMessage(in DOMString message);
/**
* Returns the CSP associated to this localId.
*/

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

@ -137,3 +137,8 @@ PESupportsConditionExpectedCloseParen=Expected ')' while parsing supports condit
PESupportsConditionExpectedStart2=Expected 'not', '(', or function while parsing supports condition but found '%1$S'.
PESupportsConditionExpectedNot=Expected 'not' while parsing supports condition but found '%1$S'.
PESupportsGroupRuleStart=Expected '{' to begin @supports rule but found '%1$S'.
PEFilterEOF=filter
PEExpectedNoneOrURL=Expected 'none' or URL but found '%1$S'.
PEExpectedNoneOrURLOrFilterFunction=Expected 'none', URL, or filter function but found '%1$S'.
PEExpectedNonnegativeNP=Expected non-negative number or percentage.
PEFilterFunctionArgumentsParsingError=Error in parsing arguments for filter function.

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

@ -345,19 +345,29 @@ this.PushService = {
break;
case "webapps-uninstall":
debug("webapps-uninstall");
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
var app = appsService.getAppFromObserverMessage(aData);
if (!app) {
debug("webapps-uninstall: No app found " + aData.origin);
let data;
try {
data = JSON.parse(aData);
} catch (ex) {
debug("webapps-uninstall: JSON parsing error: " + aData);
return;
}
this._db.getAllByManifestURL(app.manifestURL, function(records) {
let manifestURL = data.manifestURL;
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
if (appsService.getAppLocalIdByManifestURL(manifestURL) ==
Ci.nsIScriptSecurityManager.NO_APP_ID) {
debug("webapps-uninstall: No app found " + manifestURL);
return;
}
this._db.getAllByManifestURL(manifestURL, function(records) {
debug("Got " + records.length);
for (var i = 0; i < records.length; i++) {
this._db.delete(records[i].channelID, null, function() {
debug("app uninstall: " + app.manifestURL +
debug("app uninstall: " + manifestURL +
" Could not delete entry " + records[i].channelID);
});
// courtesy, but don't establish a connection
@ -368,7 +378,7 @@ this.PushService = {
}
}
}.bind(this), function() {
debug("Error in getAllByManifestURL: url " + app.manifestURL);
debug("Error in getAllByManifestURL: url " + manifestURL);
});
break;

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

@ -582,6 +582,18 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
return nullptr;
}
TemporaryRef<DataSourceSurface>
Factory::CreateDataSourceSurface(const IntSize &aSize,
SurfaceFormat aFormat)
{
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
if (newSurf->Init(aSize, aFormat)) {
return newSurf;
}
return nullptr;
}
TemporaryRef<DrawEventRecorder>
Factory::CreateEventRecorderForFile(const char *aFilename)
{

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

@ -26,5 +26,17 @@ SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
return true;
}
bool
SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
SurfaceFormat aFormat)
{
mStride = GetAlignedStride<16>(aSize.width * BytesPerPixel(aFormat));
mArray.Realloc(mStride * aSize.height);
mSize = aSize;
mFormat = aFormat;
return mArray != nullptr;
}
}
}

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

@ -38,6 +38,28 @@ private:
bool mOwnData;
};
class SourceSurfaceAlignedRawData : public DataSourceSurface
{
public:
SourceSurfaceAlignedRawData() {}
virtual uint8_t *GetData() { return mArray; }
virtual int32_t Stride() { return mStride; }
virtual SurfaceType GetType() const { return SURFACE_DATA; }
virtual IntSize GetSize() const { return mSize; }
virtual SurfaceFormat GetFormat() const { return mFormat; }
bool Init(const IntSize &aSize,
SurfaceFormat aFormat);
private:
AlignedArray<uint8_t> mArray;
int32_t mStride;
SurfaceFormat mFormat;
IntSize mSize;
};
}
}

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

@ -113,7 +113,7 @@ struct AlignedArray
mStorage = new (std::nothrow) T[aSize + (alignment - 1)];
if (uintptr_t(mStorage) % alignment) {
// Our storage does not start at a <alignment>-byte boundary. Make sure mData does!
mPtr = (uint32_t*)(uintptr_t(mStorage) +
mPtr = (T*)(uintptr_t(mStorage) +
(alignment - (uintptr_t(mStorage) % alignment)));
} else {
mPtr = mStorage;

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

@ -34,6 +34,11 @@ In this order:
angle-cross-compilation.patch
Fixes cross compilation on case sensitive OSes.
angle-line-loop-overflow.patch
Fixes a forgotten overflow check on drawing line loop
ANGLE bug : http://code.google.com/p/angleproject/issues/detail?id=444
ANGLE revision : 07dda9519cf4
In addition to these patches, the Makefile.in files are ours, they're not present in
upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
in the local .patch files.

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

@ -0,0 +1,26 @@
# HG changeset patch
# Parent 308e3cf5ba75fdf8ed3bdd3dc766410b708b98ef
diff --git a/gfx/angle/src/libGLESv2/IndexDataManager.cpp b/gfx/angle/src/libGLESv2/IndexDataManager.cpp
--- a/gfx/angle/src/libGLESv2/IndexDataManager.cpp
+++ b/gfx/angle/src/libGLESv2/IndexDataManager.cpp
@@ -375,17 +375,18 @@ void StreamingIndexBuffer::reserveSpace(
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
mWritePosition = 0;
}
- else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
+ else if (mWritePosition + requiredSpace > mBufferSize ||
+ mWritePosition + requiredSpace < mWritePosition) // Recycle
{
void *dummy;
mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
mIndexBuffer->Unlock();
mWritePosition = 0;
}
}

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

@ -380,7 +380,8 @@ void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
mWritePosition = 0;
}
else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
else if (mWritePosition + requiredSpace > mBufferSize ||
mWritePosition + requiredSpace < mWritePosition) // Recycle
{
void *dummy;
mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);

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

@ -224,36 +224,40 @@ struct EffectChain
RefPtr<Effect> mSecondaryEffects[EFFECT_MAX_SECONDARY];
};
/**
* Create a Textured effect corresponding to aFormat and using
* aSource as the (first) texture source.
*
* Note that aFormat can be different form aSource->GetFormat if, we are
* creating an effect that takes several texture sources (like with YCBCR
* where aFormat would be FOMRAT_YCBCR and each texture source would be
* a one-channel A8 texture)
*/
inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(DeprecatedTextureHost *aDeprecatedTextureHost,
DeprecatedTextureHost *aDeprecatedTextureHostOnWhite,
CreateTexturedEffect(gfx::SurfaceFormat aFormat,
TextureSource* aSource,
const gfx::Filter& aFilter)
{
if (aDeprecatedTextureHostOnWhite) {
MOZ_ASSERT(aDeprecatedTextureHost->GetFormat() == gfx::FORMAT_R8G8B8X8 ||
aDeprecatedTextureHost->GetFormat() == gfx::FORMAT_B8G8R8X8);
return new EffectComponentAlpha(aDeprecatedTextureHost, aDeprecatedTextureHostOnWhite, aFilter);
}
MOZ_ASSERT(aSource);
RefPtr<TexturedEffect> result;
switch (aDeprecatedTextureHost->GetFormat()) {
switch (aFormat) {
case gfx::FORMAT_B8G8R8A8:
result = new EffectBGRA(aDeprecatedTextureHost, true, aFilter);
result = new EffectBGRA(aSource, true, aFilter);
break;
case gfx::FORMAT_B8G8R8X8:
result = new EffectBGRX(aDeprecatedTextureHost, true, aFilter);
result = new EffectBGRX(aSource, true, aFilter);
break;
case gfx::FORMAT_R8G8B8X8:
result = new EffectRGBX(aDeprecatedTextureHost, true, aFilter);
result = new EffectRGBX(aSource, true, aFilter);
break;
case gfx::FORMAT_R5G6B5:
result = new EffectRGBX(aDeprecatedTextureHost, true, aFilter);
result = new EffectRGBX(aSource, true, aFilter);
break;
case gfx::FORMAT_R8G8B8A8:
result = new EffectRGBA(aDeprecatedTextureHost, true, aFilter);
result = new EffectRGBA(aSource, true, aFilter);
break;
case gfx::FORMAT_YUV:
result = new EffectYCbCr(aDeprecatedTextureHost, aFilter);
result = new EffectYCbCr(aSource, aFilter);
break;
default:
MOZ_CRASH("unhandled program type");
@ -262,13 +266,40 @@ CreateTexturedEffect(DeprecatedTextureHost *aDeprecatedTextureHost,
return result;
}
/**
* Create a textured effect based on aSource format and the presence of
* aSourceOnWhite.
*
* aSourceOnWhite can be null.
*/
inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(DeprecatedTextureHost *aDeprecatedTextureHost,
CreateTexturedEffect(TextureSource* aSource,
TextureSource* aSourceOnWhite,
const gfx::Filter& aFilter)
{
return CreateTexturedEffect(aDeprecatedTextureHost, nullptr, aFilter);
MOZ_ASSERT(aSource);
if (aSourceOnWhite) {
MOZ_ASSERT(aSource->GetFormat() == gfx::FORMAT_R8G8B8X8 ||
aSourceOnWhite->GetFormat() == gfx::FORMAT_B8G8R8X8);
return new EffectComponentAlpha(aSource, aSourceOnWhite, aFilter);
}
return CreateTexturedEffect(aSource->GetFormat(), aSource, aFilter);
}
/**
* Create a textured effect based on aSource format.
*
* This version excudes the possibility of component alpha.
*/
inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(TextureSource *aTexture,
const gfx::Filter& aFilter)
{
return CreateTexturedEffect(aTexture, nullptr, aFilter);
}
} // namespace layers
} // namespace mozilla

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

@ -34,6 +34,7 @@ namespace layers {
class ImageClient;
class SharedPlanarYCbCrImage;
class DeprecatedSharedPlanarYCbCrImage;
struct ImageBackendData
{
@ -720,6 +721,7 @@ public:
PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
virtual SharedPlanarYCbCrImage *AsSharedPlanarYCbCrImage() { return nullptr; }
virtual DeprecatedSharedPlanarYCbCrImage *AsDeprecatedSharedPlanarYCbCrImage() { return nullptr; }
protected:
/**

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

@ -24,7 +24,7 @@ enum ImageFormat {
GRALLOC_PLANAR_YCBCR,
/**
* The SHARED_RGB format creates a SharedRGBImage, which stores RGB data in
* The SHARED_RGB format creates a DeprecatedSharedRGBImage, which stores RGB data in
* shared memory. Some Android hardware video decoders require this format.
* Currently only used on Android.
*/

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

@ -111,7 +111,16 @@ public:
bool RemoveTile(int x, int y, Tile& aRemovedTile);
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
uint32_t GetScaledTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE / mResolution; }
uint32_t GetScaledTileLength() const {
// volatile variables to help investigate bug 881018
volatile float resolution = mResolution;
volatile float fScaledLength = TILEDLAYERBUFFER_TILE_SIZE / mResolution;
volatile uint32_t uiScaledLength = TILEDLAYERBUFFER_TILE_SIZE / mResolution;
if (!uiScaledLength) {
MOZ_CRASH();
}
return uiScaledLength;
}
unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
@ -225,7 +234,6 @@ TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
// TODO Cache firstTileOriginX/firstTileOriginY
// Find the tile x/y of the first tile and the target tile relative to the (0, 0)
// origin, the difference is the tile x/y relative to the start of the tile buffer.
volatile float resolution = mResolution; // bug 881018 investigation
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
return GetTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,

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

@ -28,10 +28,10 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
RefPtr<ImageClient> result = nullptr;
switch (aCompositableHostType) {
case BUFFER_IMAGE_SINGLE:
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
break;
case BUFFER_IMAGE_BUFFERED:
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
break;
case BUFFER_BRIDGE:
result = new ImageClientBridge(aForwarder, aFlags);
@ -66,9 +66,9 @@ ImageClient::UpdatePictureRect(nsIntRect aRect)
GetForwarder()->UpdatePictureRect(this, aRect);
}
ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType)
DeprecatedImageClientSingle::DeprecatedImageClientSingle(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType)
: ImageClient(aFwd, aType)
, mTextureInfo(aType)
{
@ -76,7 +76,7 @@ ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
}
bool
ImageClientSingle::EnsureDeprecatedTextureClient(DeprecatedTextureClientType aType)
DeprecatedImageClientSingle::EnsureDeprecatedTextureClient(DeprecatedTextureClientType aType)
{
// We should not call this method if using ImageBridge or tiled texture
// clients since SupportsType always fails
@ -88,7 +88,7 @@ ImageClientSingle::EnsureDeprecatedTextureClient(DeprecatedTextureClientType aTy
}
bool
ImageClientSingle::UpdateImage(ImageContainer* aContainer,
DeprecatedImageClientSingle::UpdateImage(ImageContainer* aContainer,
uint32_t aContentFlags)
{
AutoLockImage autoLock(aContainer);
@ -106,11 +106,11 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer,
EnsureDeprecatedTextureClient(TEXTURE_YCBCR)) {
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
if (ycbcr->AsSharedPlanarYCbCrImage()) {
if (ycbcr->AsDeprecatedSharedPlanarYCbCrImage()) {
AutoLockDeprecatedTextureClient lock(mDeprecatedTextureClient);
SurfaceDescriptor sd;
if (!ycbcr->AsSharedPlanarYCbCrImage()->ToSurfaceDescriptor(sd)) {
if (!ycbcr->AsDeprecatedSharedPlanarYCbCrImage()->ToSurfaceDescriptor(sd)) {
return false;
}
@ -147,7 +147,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer,
AutoLockDeprecatedTextureClient lock(mDeprecatedTextureClient);
SurfaceDescriptor desc;
if (!static_cast<SharedRGBImage*>(image)->ToSurfaceDescriptor(desc)) {
if (!static_cast<DeprecatedSharedRGBImage*>(image)->ToSurfaceDescriptor(desc)) {
return false;
}
mDeprecatedTextureClient->SetDescriptor(desc);
@ -209,7 +209,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer,
}
void
ImageClientSingle::Updated()
DeprecatedImageClientSingle::Updated()
{
mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->GetDescriptor());
}
@ -247,10 +247,10 @@ ImageClient::CreateImage(const uint32_t *aFormats,
for (uint32_t i = 0; i < aNumFormats; i++) {
switch (aFormats[i]) {
case PLANAR_YCBCR:
img = new SharedPlanarYCbCrImage(GetForwarder());
img = new DeprecatedSharedPlanarYCbCrImage(GetForwarder());
return img.forget();
case SHARED_RGB:
img = new SharedRGBImage(GetForwarder());
img = new DeprecatedSharedRGBImage(GetForwarder());
return img.forget();
#ifdef MOZ_WIDGET_GONK
case GONK_IO_SURFACE:

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

@ -72,12 +72,12 @@ protected:
* ContentClientDoubleBuffered, or using multiple clients for YCbCr or tiled
* images).
*/
class ImageClientSingle : public ImageClient
class DeprecatedImageClientSingle : public ImageClient
{
public:
ImageClientSingle(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType);
DeprecatedImageClientSingle(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType);
virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);

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

@ -161,7 +161,7 @@ void
DeprecatedTextureClientShmemYCbCr::SetDescriptorFromReply(const SurfaceDescriptor& aDescriptor)
{
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TYCbCrImage);
SharedPlanarYCbCrImage* shYCbCr = SharedPlanarYCbCrImage::FromSurfaceDescriptor(aDescriptor);
DeprecatedSharedPlanarYCbCrImage* shYCbCr = DeprecatedSharedPlanarYCbCrImage::FromSurfaceDescriptor(aDescriptor);
if (shYCbCr) {
shYCbCr->Release();
mDescriptor = SurfaceDescriptor();

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

@ -54,10 +54,10 @@ CompositableHost::Create(const TextureInfo& aTextureInfo)
RefPtr<CompositableHost> result;
switch (aTextureInfo.mCompositableType) {
case BUFFER_IMAGE_BUFFERED:
result = new ImageHostBuffered(aTextureInfo);
result = new DeprecatedImageHostBuffered(aTextureInfo);
return result;
case BUFFER_IMAGE_SINGLE:
result = new ImageHostSingle(aTextureInfo);
result = new DeprecatedImageHostSingle(aTextureInfo);
return result;
case BUFFER_TILED:
result = new TiledContentHost(aTextureInfo);

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

@ -17,7 +17,7 @@ using namespace gfx;
namespace layers {
void
ImageHostSingle::SetCompositor(Compositor* aCompositor) {
DeprecatedImageHostSingle::SetCompositor(Compositor* aCompositor) {
CompositableHost::SetCompositor(aCompositor);
if (mDeprecatedTextureHost) {
mDeprecatedTextureHost->SetCompositor(aCompositor);
@ -25,10 +25,10 @@ ImageHostSingle::SetCompositor(Compositor* aCompositor) {
}
void
ImageHostSingle::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
DeprecatedImageHostSingle::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
{
if (mDeprecatedTextureHost &&
mDeprecatedTextureHost->GetBuffer() &&
@ -43,10 +43,10 @@ ImageHostSingle::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
}
void
ImageHostSingle::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
DeprecatedImageHostSingle::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
{
mDeprecatedTextureHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
mTextureInfo.mDeprecatedTextureHostFlags,
@ -61,14 +61,14 @@ ImageHostSingle::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
}
void
ImageHostSingle::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Point& aOffset,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion,
TiledLayerProperties* aLayerProperties)
DeprecatedImageHostSingle::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Point& aOffset,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion,
TiledLayerProperties* aLayerProperties)
{
if (!mDeprecatedTextureHost) {
NS_WARNING("Can't composite an invalid or null DeprecatedTextureHost");
@ -138,10 +138,10 @@ ImageHostSingle::Composite(EffectChain& aEffectChain,
#ifdef MOZ_LAYERS_HAVE_LOG
void
ImageHostSingle::PrintInfo(nsACString& aTo, const char* aPrefix)
DeprecatedImageHostSingle::PrintInfo(nsACString& aTo, const char* aPrefix)
{
aTo += aPrefix;
aTo += nsPrintfCString("ImageHostSingle (0x%p)", this);
aTo += nsPrintfCString("DeprecatedImageHostSingle (0x%p)", this);
AppendToString(aTo, mPictureRect, " [picture-rect=", "]");
@ -155,8 +155,8 @@ ImageHostSingle::PrintInfo(nsACString& aTo, const char* aPrefix)
#endif
bool
ImageHostBuffered::Update(const SurfaceDescriptor& aImage,
SurfaceDescriptor* aResult) {
DeprecatedImageHostBuffered::Update(const SurfaceDescriptor& aImage,
SurfaceDescriptor* aResult) {
if (!GetDeprecatedTextureHost()) {
*aResult = aImage;
return false;
@ -166,24 +166,24 @@ ImageHostBuffered::Update(const SurfaceDescriptor& aImage,
}
void
ImageHostBuffered::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
DeprecatedImageHostBuffered::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
{
ImageHostSingle::MakeDeprecatedTextureHost(aTextureId,
aSurface,
aAllocator,
aTextureInfo);
DeprecatedImageHostSingle::MakeDeprecatedTextureHost(aTextureId,
aSurface,
aAllocator,
aTextureInfo);
if (mDeprecatedTextureHost) {
mDeprecatedTextureHost->SetBuffer(new SurfaceDescriptor(null_t()), aAllocator);
}
}
void
ImageHostSingle::Dump(FILE* aFile,
const char* aPrefix,
bool aDumpHtml)
DeprecatedImageHostSingle::Dump(FILE* aFile,
const char* aPrefix,
bool aDumpHtml)
{
if (!aFile) {
aFile = stderr;

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

@ -37,10 +37,10 @@ protected:
};
// ImageHost with a single DeprecatedTextureHost
class ImageHostSingle : public ImageHost
class DeprecatedImageHostSingle : public ImageHost
{
public:
ImageHostSingle(const TextureInfo& aTextureInfo)
DeprecatedImageHostSingle(const TextureInfo& aTextureInfo)
: ImageHost(aTextureInfo)
, mDeprecatedTextureHost(nullptr)
, mHasPictureRect(false)
@ -115,11 +115,11 @@ protected:
// Double buffered ImageHost. We have a single TextureHost and double buffering
// is done at the TextureHost/Client level. This is in contrast with buffered
// ContentHosts which do their own double buffering
class ImageHostBuffered : public ImageHostSingle
class DeprecatedImageHostBuffered : public DeprecatedImageHostSingle
{
public:
ImageHostBuffered(const TextureInfo& aTextureInfo)
: ImageHostSingle(aTextureInfo)
DeprecatedImageHostBuffered(const TextureInfo& aTextureInfo)
: DeprecatedImageHostSingle(aTextureInfo)
{}
virtual bool Update(const SurfaceDescriptor& aImage,

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