Bug 849009 - Uplift Add-on SDK changeset 645b0ca71ccd41bb1fc69d97d22c456b03452e89
5
addon-sdk/source/app-extension/bootstrap.js
vendored
@ -151,6 +151,11 @@ function startup(data, reasonCode) {
|
||||
if (path) path += '/';
|
||||
let fileURI = branch.getCharPref(name);
|
||||
|
||||
// On mobile, file URI has to end with a `/` otherwise, setSubstitution
|
||||
// takes the parent folder instead.
|
||||
if (fileURI[fileURI.length-1] !== '/')
|
||||
fileURI += '/';
|
||||
|
||||
// Maps the given file:// URI to a resource:// in order to avoid various
|
||||
// failure that happens with file:// URI and be close to production env
|
||||
let resourcesURI = ioService.newURI(fileURI, null, null);
|
||||
|
0
addon-sdk/source/bin/cfx
Normal file → Executable file
0
addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper
Normal file → Executable file
@ -1,9 +1,11 @@
|
||||
|
||||
var count = 0
|
||||
var count = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
window.addEventListener("message", function(msg) {
|
||||
if (++count > 1) self.postMessage(msg.data);
|
||||
if (++count > 1) {
|
||||
self.postMessage(msg.data);
|
||||
}
|
||||
else msg.source.postMessage(msg.data, '*');
|
||||
});
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
### A ###
|
||||
|
||||
* Adamantium
|
||||
* Ehsan Akhgari
|
||||
* arky
|
||||
@ -14,6 +16,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### B ###
|
||||
|
||||
* [Romain B](https://github.com/Niamor)
|
||||
* [Louis-Rémi Babé](https://github.com/louisremi)
|
||||
* Will Bamberg
|
||||
@ -25,6 +29,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### C ###
|
||||
|
||||
* [Shane Caraveo](https://github.com/mixedpuppy)
|
||||
* [Matěj Cepl](https://github.com/mcepl)
|
||||
* Marc Chevrier
|
||||
@ -33,6 +39,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### D ###
|
||||
|
||||
* dexter
|
||||
* Christopher Dorn
|
||||
* Connor Dunn
|
||||
@ -40,11 +48,15 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### F ###
|
||||
|
||||
* [Matteo Ferretti (ZER0)](https://github.com/ZER0)
|
||||
* fuzzykiller
|
||||
|
||||
<!--end-->
|
||||
|
||||
### G ###
|
||||
|
||||
* [Marcio Galli](https://github.com/taboca)
|
||||
* [Ben Gillbanks](http://www.iconfinder.com/browse/iconset/circular_icons/)
|
||||
* Felipe Gomes
|
||||
@ -55,6 +67,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### H ###
|
||||
|
||||
* Mark Hammond
|
||||
* Mark A. Hershberger
|
||||
* Lloyd Hilaiel
|
||||
@ -62,25 +76,36 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### I ###
|
||||
|
||||
* Shun Ikejima
|
||||
|
||||
<!--end-->
|
||||
|
||||
### J ###
|
||||
|
||||
* Eric H. Jung
|
||||
|
||||
<!--end-->
|
||||
|
||||
### K ###
|
||||
|
||||
* Hrishikesh Kale
|
||||
* Wes Kocher
|
||||
* Lajos Koszti
|
||||
* [Vladimir Kukushkin](https://github.com/kukushechkin)
|
||||
|
||||
<!--end-->
|
||||
|
||||
### L ###
|
||||
|
||||
* Edward Lee
|
||||
* Gregg Lind
|
||||
|
||||
<!--end-->
|
||||
|
||||
### M ###
|
||||
|
||||
* [Nils Maier](https://github.com/nmaier)
|
||||
* Gervase Markham
|
||||
* Dave Mason
|
||||
@ -90,6 +115,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### N ###
|
||||
|
||||
* Siavash Askari Nasr
|
||||
* Joe R. Nassimian ([placidrage](https://github.com/placidrage))
|
||||
* Dương H. Nguyễn
|
||||
@ -97,22 +124,31 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### O ###
|
||||
|
||||
* [ongaeshi](https://github.com/ongaeshi)
|
||||
* Paul O’Shannessy
|
||||
* Les Orchard
|
||||
|
||||
<!--end-->
|
||||
|
||||
### P ###
|
||||
|
||||
* Robert Pankowecki
|
||||
* Alexandre Poirot
|
||||
* [Jamie Phelps](https://github.com/ongaeshi)
|
||||
* [Alexandre Poirot](https://github.com/ochameau)
|
||||
* Nickolay Ponomarev
|
||||
|
||||
<!--end-->
|
||||
|
||||
### R ###
|
||||
|
||||
* Aza Raskin
|
||||
|
||||
<!--end-->
|
||||
|
||||
### S ###
|
||||
|
||||
* Till Schneidereit
|
||||
* Justin Scott
|
||||
* Ayan Shah
|
||||
@ -125,6 +161,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### T ###
|
||||
|
||||
* taku0
|
||||
* Clint Talbert
|
||||
* Tim Taubert
|
||||
@ -134,6 +172,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### V ###
|
||||
|
||||
* Peter Van der Beken
|
||||
* Sander van Veen
|
||||
* Atul Varma
|
||||
@ -142,6 +182,8 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### W ###
|
||||
|
||||
* Brian Warner
|
||||
* [Henri Wiechers](https://github.com/hwiechers)
|
||||
* Drew Willcoxon
|
||||
@ -150,5 +192,7 @@ We'd like to thank our many Jetpack project contributors! They include:
|
||||
|
||||
<!--end-->
|
||||
|
||||
### Z ###
|
||||
|
||||
* Piotr Zalewa
|
||||
* Brett Zamir
|
||||
|
@ -242,6 +242,7 @@ Finally, the "text-entry.html" file defines the `<textarea>` element:
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style type="text/css" media="all">
|
||||
textarea {
|
||||
margin: 10px;
|
||||
|
@ -10,6 +10,9 @@
|
||||
The `preferences/service` module provides access to the
|
||||
application-wide preferences service singleton.
|
||||
|
||||
To define preferences for your own add-on and expose them to the user in
|
||||
the [Add-on Manager](https://developer.mozilla.org/en-US/docs/Addons/Add-on_Manager),
|
||||
you can use the [simple-prefs](modules/sdk/simple-prefs.html) module.
|
||||
|
||||
<api name="set">
|
||||
@function
|
||||
|
@ -181,7 +181,7 @@ if the document cannot be processed by `JSON.parse`.
|
||||
</api>
|
||||
|
||||
<api name="status">
|
||||
@property {string}
|
||||
@property {integer}
|
||||
The HTTP response status code (e.g. *200*).
|
||||
</api>
|
||||
|
||||
|
@ -355,3 +355,17 @@ for more details.
|
||||
The listener function that processes the event.
|
||||
</api>
|
||||
|
||||
## Using the Preferences Service to Access Simple Prefs ##
|
||||
|
||||
If you ever need to access your simple-prefs with the `preferences/service` module,
|
||||
you can do so using the extended preference name. To get this
|
||||
just prepend `"extensions." + require("sdk/self").id + "."` to the preference name `"somePreference"`.
|
||||
|
||||
For example, if you had a simple-pref named `"somePreference"` then you could
|
||||
get its value like so:
|
||||
|
||||
require('sdk/preferences/service').get(['extensions', require('sdk/self').id, 'somePreference'].join('.'))
|
||||
|
||||
This would give you the same value as:
|
||||
|
||||
require('sdk/simple-prefs').prefs['somePreference']
|
||||
|
@ -182,6 +182,13 @@ tabs in this window, not all tabs in all windows. This property is read-only.
|
||||
<api name="isPrivateBrowsing">
|
||||
@property {boolean}
|
||||
Returns `true` if the window is in private browsing mode, and `false` otherwise.
|
||||
|
||||
<div class="warning">
|
||||
This property is deprecated.
|
||||
From version 1.14, please consider using following code instead:<br/>
|
||||
<code>require("private-browsing").isPrivate(browserWindow)</code>
|
||||
</div>
|
||||
|
||||
</api>
|
||||
|
||||
<api name="activate">
|
||||
|
0
addon-sdk/source/examples/library-detector/README.md
Normal file → Executable file
0
addon-sdk/source/examples/library-detector/data/icons/closure.ico
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
addon-sdk/source/examples/library-detector/data/icons/jquery.ico
Normal file → Executable file
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
0
addon-sdk/source/examples/library-detector/data/icons/jquery_ui.ico
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
addon-sdk/source/examples/library-detector/data/icons/modernizr.ico
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
addon-sdk/source/examples/library-detector/data/icons/mootools.png
Normal file → Executable file
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
0
addon-sdk/source/examples/library-detector/data/icons/yui.ico
Normal file → Executable file
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
0
addon-sdk/source/examples/library-detector/data/library-detector.js
Normal file → Executable file
0
addon-sdk/source/examples/library-detector/data/widget.html
Normal file → Executable file
0
addon-sdk/source/examples/library-detector/lib/main.js
Normal file → Executable file
0
addon-sdk/source/examples/library-detector/package.json
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 expandtab */
|
||||
/*jshint asi: true undef: true es5: true node: true browser: true devel: true
|
||||
/*jshint undef: true es5: true node: true browser: true devel: true
|
||||
forin: true latedef: false */
|
||||
/*global define: true, Cu: true, __URI__: true */
|
||||
;(function(id, factory) { // Module boilerplate :(
|
||||
@ -7,8 +7,15 @@
|
||||
define(factory);
|
||||
} else if (typeof(require) === 'function') { // CommonJS
|
||||
factory.call(this, require, exports, module);
|
||||
} else if (~String(this).indexOf('BackstagePass')) { // JSM
|
||||
} else if (String(this).indexOf('BackstagePass') >= 0) { // JSM
|
||||
this[factory.name] = {};
|
||||
try {
|
||||
this.console = this['Components'].utils
|
||||
.import('resource://gre/modules/devtools/Console.jsm', {}).console;
|
||||
}
|
||||
catch (ex) {
|
||||
// Avoid failures on different toolkit configurations.
|
||||
}
|
||||
factory(function require(uri) {
|
||||
var imports = {};
|
||||
this['Components'].utils.import(uri, imports);
|
||||
@ -16,12 +23,12 @@
|
||||
}, this[factory.name], { uri: __URI__, id: id });
|
||||
this.EXPORTED_SYMBOLS = [factory.name];
|
||||
} else { // Browser or alike
|
||||
var globals = this
|
||||
var globals = this;
|
||||
factory(function require(id) {
|
||||
return globals[id];
|
||||
}, (globals[id] = {}), { uri: document.location.href + '#' + id, id: id });
|
||||
}
|
||||
}).call(this, 'loader', function Promise(require, exports, module) {
|
||||
}).call(this, 'promise/core', function Promise(require, exports, module) {
|
||||
|
||||
'use strict';
|
||||
|
||||
@ -29,157 +36,211 @@ module.metadata = {
|
||||
"stability": "unstable"
|
||||
};
|
||||
|
||||
function resolution(value) {
|
||||
/**
|
||||
Returns non-standard compliant (`then` does not returns a promise) promise
|
||||
that resolves to a given `value`. Used just internally only.
|
||||
**/
|
||||
return { then: function then(resolve) { resolve(value) } }
|
||||
/**
|
||||
* Internal utility: Wraps given `value` into simplified promise, successfully
|
||||
* fulfilled to a given `value`. Note the result is not a complete promise
|
||||
* implementation, as its method `then` does not returns anything.
|
||||
*/
|
||||
function fulfilled(value) {
|
||||
return { then: function then(fulfill) { fulfill(value); } };
|
||||
}
|
||||
|
||||
function rejection(reason) {
|
||||
/**
|
||||
Returns non-standard compliant promise (`then` does not returns a promise)
|
||||
that rejects with a given `reason`. This is used internally only.
|
||||
**/
|
||||
return { then: function then(resolve, reject) { reject(reason) } }
|
||||
/**
|
||||
* Internal utility: Wraps given input into simplified promise, pre-rejected
|
||||
* with a given `reason`. Note the result is not a complete promise
|
||||
* implementation, as its method `then` does not returns anything.
|
||||
*/
|
||||
function rejected(reason) {
|
||||
return { then: function then(fulfill, reject) { reject(reason); } };
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal utility: Decorates given `f` function, so that on exception promise
|
||||
* rejected with thrown error is returned.
|
||||
*/
|
||||
function attempt(f) {
|
||||
/**
|
||||
Returns wrapper function that delegates to `f`. If `f` throws then captures
|
||||
error and returns promise that rejects with a thrown error. Otherwise returns
|
||||
return value. (Internal utility)
|
||||
**/
|
||||
return function effort(options) {
|
||||
try { return f(options) }
|
||||
catch(error) { return rejection(error) }
|
||||
}
|
||||
}
|
||||
|
||||
function isPromise(value) {
|
||||
/**
|
||||
Returns true if given `value` is promise. Value is assumed to be promise if
|
||||
it implements `then` method.
|
||||
**/
|
||||
return value && typeof(value.then) === 'function'
|
||||
}
|
||||
|
||||
function defer(prototype) {
|
||||
/**
|
||||
Returns object containing following properties:
|
||||
- `promise` Eventual value representation implementing CommonJS [Promises/A]
|
||||
(http://wiki.commonjs.org/wiki/Promises/A) API.
|
||||
- `resolve` Single shot function that resolves returned `promise` with a given
|
||||
`value` argument.
|
||||
- `reject` Single shot function that rejects returned `promise` with a given
|
||||
`reason` argument.
|
||||
|
||||
Given `prototype` argument is used as a prototype of the returned `promise`
|
||||
allowing one to implement additional API. If prototype is not passed then
|
||||
it falls back to `Object.prototype`.
|
||||
|
||||
## Examples
|
||||
|
||||
// Simple usage.
|
||||
var deferred = defer()
|
||||
deferred.promise.then(console.log, console.error)
|
||||
deferred.resolve(value)
|
||||
|
||||
// Advanced usage
|
||||
var prototype = {
|
||||
get: function get(name) {
|
||||
return this.then(function(value) {
|
||||
return value[name];
|
||||
})
|
||||
return function effort(input) {
|
||||
try {
|
||||
return f(input);
|
||||
}
|
||||
}
|
||||
catch(error) {
|
||||
if (exports._reportErrors && typeof(console) === 'object') {
|
||||
console.error(error)
|
||||
}
|
||||
return rejected(error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal utility: Returns `true` if given `value` is a promise. Value is
|
||||
* assumed to be a promise if it implements method `then`.
|
||||
*/
|
||||
function isPromise(value) {
|
||||
return value && typeof(value.then) === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates deferred object containing fresh promise & methods to either resolve
|
||||
* or reject it. The result is an object with the following properties:
|
||||
* - `promise` Eventual value representation implementing CommonJS [Promises/A]
|
||||
* (http://wiki.commonjs.org/wiki/Promises/A) API.
|
||||
* - `resolve` Single shot function that resolves enclosed `promise` with a
|
||||
* given `value`.
|
||||
* - `reject` Single shot function that rejects enclosed `promise` with a given
|
||||
* `reason`.
|
||||
*
|
||||
* An optional `prototype` argument is used as a prototype of the returned
|
||||
* `promise` allowing one to implement additional API. If prototype is not
|
||||
* passed then it falls back to `Object.prototype`.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* function fetchURI(uri, type) {
|
||||
* var deferred = defer();
|
||||
* var request = new XMLHttpRequest();
|
||||
* request.open("GET", uri, true);
|
||||
* request.responseType = type;
|
||||
* request.onload = function onload() {
|
||||
* deferred.resolve(request.response);
|
||||
* }
|
||||
* request.onerror = function(event) {
|
||||
* deferred.reject(event);
|
||||
* }
|
||||
* request.send();
|
||||
*
|
||||
* return deferred.promise;
|
||||
* }
|
||||
*/
|
||||
function defer(prototype) {
|
||||
// Define FIFO queue of observer pairs. Once promise is resolved & all queued
|
||||
// observers are forwarded to `result` and variable is set to `null`.
|
||||
var observers = [];
|
||||
|
||||
// Promise `result`, which will be assigned a resolution value once promise
|
||||
// is resolved. Note that result will always be assigned promise (or alike)
|
||||
// object to take care of propagation through promise chains. If result is
|
||||
// `null` promise is not resolved yet.
|
||||
var result = null;
|
||||
|
||||
var foo = defer(prototype)
|
||||
deferred.promise.get('name').then(console.log)
|
||||
deferred.resolve({ name: 'Foo' })
|
||||
//=> 'Foo'
|
||||
*/
|
||||
var pending = [], result
|
||||
prototype = (prototype || prototype === null) ? prototype : Object.prototype
|
||||
|
||||
// Create an object implementing promise API.
|
||||
var promise = Object.create(prototype, {
|
||||
then: { value: function then(resolve, reject) {
|
||||
// create a new deferred using a same `prototype`.
|
||||
var deferred = defer(prototype)
|
||||
// If `resolve / reject` callbacks are not provided.
|
||||
resolve = resolve ? attempt(resolve) : resolution
|
||||
reject = reject ? attempt(reject) : rejection
|
||||
then: { value: function then(onFulfill, onError) {
|
||||
var deferred = defer(prototype);
|
||||
|
||||
// Create a listeners for a enclosed promise resolution / rejection that
|
||||
// delegate to an actual callbacks and resolve / reject returned promise.
|
||||
function resolved(value) { deferred.resolve(resolve(value)) }
|
||||
function rejected(reason) { deferred.resolve(reject(reason)) }
|
||||
// Decorate `onFulfill` / `onError` handlers with `attempt`, that
|
||||
// way if wrapped handler throws exception decorator will catch and
|
||||
// return promise rejected with it, which will cause rejection of
|
||||
// `deferred.promise`. If handler is missing, substitute it with an
|
||||
// utility function that takes one argument and returns promise
|
||||
// fulfilled / rejected with it. This takes care of propagation
|
||||
// through the rest of the promise chain.
|
||||
onFulfill = onFulfill ? attempt(onFulfill) : fulfilled;
|
||||
onError = onError ? attempt(onError) : rejected;
|
||||
|
||||
// If promise is pending register listeners. Otherwise forward them to
|
||||
// resulting resolution.
|
||||
if (pending) pending.push([ resolved, rejected ])
|
||||
else result.then(resolved, rejected)
|
||||
// Create a pair of observers that invoke given handlers & propagate
|
||||
// results to `deferred.promise`.
|
||||
function resolveDeferred(value) { deferred.resolve(onFulfill(value)); }
|
||||
function rejectDeferred(reason) { deferred.resolve(onError(reason)); }
|
||||
|
||||
return deferred.promise
|
||||
// If enclosed promise (`this.promise`) observers queue is still alive
|
||||
// enqueue a new observer pair into it. Note that this does not
|
||||
// necessary means that promise is pending, it may already be resolved,
|
||||
// but we still have to queue observers to guarantee an order of
|
||||
// propagation.
|
||||
if (observers) {
|
||||
observers.push({ resolve: resolveDeferred, reject: rejectDeferred });
|
||||
}
|
||||
// Otherwise just forward observer pair right to a `result` promise.
|
||||
else {
|
||||
result.then(resolveDeferred, rejectDeferred);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}}
|
||||
})
|
||||
|
||||
var deferred = {
|
||||
promise: promise,
|
||||
/**
|
||||
* Resolves associated `promise` to a given `value`, unless it's already
|
||||
* resolved or rejected. Note that resolved promise is not necessary a
|
||||
* successfully fulfilled. Promise may be resolved with a promise `value`
|
||||
* in which case `value` promise's fulfillment / rejection will propagate
|
||||
* up to a promise resolved with `value`.
|
||||
*/
|
||||
resolve: function resolve(value) {
|
||||
/**
|
||||
Resolves associated `promise` to a given `value`, unless it's already
|
||||
resolved or rejected.
|
||||
**/
|
||||
if (pending) {
|
||||
// store resolution `value` as a promise (`value` itself may be a
|
||||
// promise), so that all subsequent listeners can be forwarded to it,
|
||||
// which either resolves immediately or forwards if `value` is
|
||||
// a promise.
|
||||
result = isPromise(value) ? value : resolution(value)
|
||||
// forward all pending observers.
|
||||
while (pending.length) result.then.apply(result, pending.shift())
|
||||
// mark promise as resolved.
|
||||
pending = null
|
||||
if (!result) {
|
||||
// Store resolution `value` in a `result` as a promise, so that all
|
||||
// the subsequent handlers can be simply forwarded to it. Since
|
||||
// `result` will be a promise all the value / error propagation will
|
||||
// be uniformly taken care of.
|
||||
result = isPromise(value) ? value : fulfilled(value);
|
||||
|
||||
// Forward already registered observers to a `result` promise in the
|
||||
// order they were registered. Note that we intentionally dequeue
|
||||
// observer at a time until queue is exhausted. This makes sure that
|
||||
// handlers registered as side effect of observer forwarding are
|
||||
// queued instead of being invoked immediately, guaranteeing FIFO
|
||||
// order.
|
||||
while (observers.length) {
|
||||
var observer = observers.shift();
|
||||
result.then(observer.resolve, observer.reject);
|
||||
}
|
||||
|
||||
// Once `observers` queue is exhausted we `null`-ify it, so that
|
||||
// new handlers are forwarded straight to the `result`.
|
||||
observers = null;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Rejects associated `promise` with a given `reason`, unless it's already
|
||||
* resolved / rejected. This is just a (better performing) convenience
|
||||
* shortcut for `deferred.resolve(reject(reason))`.
|
||||
*/
|
||||
reject: function reject(reason) {
|
||||
/**
|
||||
Rejects associated `promise` with a given `reason`, unless it's already
|
||||
resolved / rejected.
|
||||
**/
|
||||
deferred.resolve(rejection(reason))
|
||||
// Note that if promise is resolved that does not necessary means that it
|
||||
// is successfully fulfilled. Resolution value may be a promise in which
|
||||
// case its result propagates. In other words if promise `a` is resolved
|
||||
// with promise `b`, `a` is either fulfilled or rejected depending
|
||||
// on weather `b` is fulfilled or rejected. Here `deferred.promise` is
|
||||
// resolved with a promise pre-rejected with a given `reason`, there for
|
||||
// `deferred.promise` is rejected with a given `reason`. This may feel
|
||||
// little awkward first, but doing it this way greatly simplifies
|
||||
// propagation through promise chains.
|
||||
deferred.resolve(rejected(reason));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return deferred
|
||||
return deferred;
|
||||
}
|
||||
exports.defer = defer
|
||||
exports.defer = defer;
|
||||
|
||||
/**
|
||||
* Returns a promise resolved to a given `value`. Optionally a second
|
||||
* `prototype` argument may be provided to be used as a prototype for the
|
||||
* returned promise.
|
||||
*/
|
||||
function resolve(value, prototype) {
|
||||
/**
|
||||
Returns a promise resolved to a given `value`. Optionally second `prototype`
|
||||
arguments my be provided to be used as a prototype for a returned promise.
|
||||
**/
|
||||
var deferred = defer(prototype)
|
||||
deferred.resolve(value)
|
||||
return deferred.promise
|
||||
var deferred = defer(prototype);
|
||||
deferred.resolve(value);
|
||||
return deferred.promise;
|
||||
}
|
||||
exports.resolve = resolve
|
||||
exports.resolve = resolve;
|
||||
|
||||
/**
|
||||
* Returns a promise rejected with a given `reason`. Optionally a second
|
||||
* `prototype` argument may be provided to be used as a prototype for the
|
||||
* returned promise.
|
||||
*/
|
||||
function reject(reason, prototype) {
|
||||
/**
|
||||
Returns a promise that is rejected with a given `reason`. Optionally second
|
||||
`prototype` arguments my be provided to be used as a prototype for a returned
|
||||
promise.
|
||||
**/
|
||||
var deferred = defer(prototype)
|
||||
deferred.reject(reason)
|
||||
return deferred.promise
|
||||
var deferred = defer(prototype);
|
||||
deferred.reject(reason);
|
||||
return deferred.promise;
|
||||
}
|
||||
exports.reject = reject
|
||||
exports.reject = reject;
|
||||
|
||||
var promised = (function() {
|
||||
// Note: Define shortcuts and utility functions here in order to avoid
|
||||
@ -226,6 +287,6 @@ var promised = (function() {
|
||||
}
|
||||
}
|
||||
})()
|
||||
exports.promised = promised
|
||||
exports.promised = promised;
|
||||
|
||||
})
|
||||
});
|
||||
|
@ -12,15 +12,20 @@ const { EventEmitter } = require('../deprecated/events');
|
||||
const { Trait } = require('../deprecated/traits');
|
||||
const { when } = require('../system/unload');
|
||||
const { getInnerId, getOuterId, windows, isDocumentLoaded, isBrowser,
|
||||
getMostRecentBrowserWindow } = require('../window/utils');
|
||||
getMostRecentBrowserWindow, getMostRecentWindow } = require('../window/utils');
|
||||
const errors = require('../deprecated/errors');
|
||||
const { deprecateFunction } = require('../util/deprecate');
|
||||
const { ignoreWindow } = require('sdk/private-browsing/utils');
|
||||
const { isPrivateBrowsingSupported } = require('../self');
|
||||
|
||||
const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
|
||||
getService(Ci.nsIAppShellService);
|
||||
|
||||
// Bug 834961: ignore private windows when they are not supported
|
||||
function getWindows() windows(null, { includePrivate: isPrivateBrowsingSupported });
|
||||
|
||||
/**
|
||||
* An iterator for XUL windows currently in the application.
|
||||
*
|
||||
@ -31,7 +36,7 @@ function windowIterator() {
|
||||
// Bug 752631: We only pass already loaded window in order to avoid
|
||||
// breaking XUL windows DOM. DOM is broken when some JS code try
|
||||
// to access DOM during "uninitialized" state of the related document.
|
||||
let list = windows().filter(isDocumentLoaded);
|
||||
let list = getWindows().filter(isDocumentLoaded);
|
||||
for (let i = 0, l = list.length; i < l; i++) {
|
||||
yield list[i];
|
||||
}
|
||||
@ -60,7 +65,7 @@ function WindowTracker(delegate) {
|
||||
this._delegate = delegate;
|
||||
this._loadingWindows = [];
|
||||
|
||||
for each (let window in windows())
|
||||
for each (let window in getWindows())
|
||||
this._regWindow(window);
|
||||
windowWatcher.registerNotification(this);
|
||||
|
||||
@ -71,6 +76,10 @@ function WindowTracker(delegate) {
|
||||
|
||||
WindowTracker.prototype = {
|
||||
_regLoadingWindow: function _regLoadingWindow(window) {
|
||||
// Bug 834961: ignore private windows when they are not supported
|
||||
if (ignoreWindow(window))
|
||||
return;
|
||||
|
||||
this._loadingWindows.push(window);
|
||||
window.addEventListener('load', this, true);
|
||||
},
|
||||
@ -85,6 +94,10 @@ WindowTracker.prototype = {
|
||||
},
|
||||
|
||||
_regWindow: function _regWindow(window) {
|
||||
// Bug 834961: ignore private windows when they are not supported
|
||||
if (ignoreWindow(window))
|
||||
return;
|
||||
|
||||
if (window.document.readyState == 'complete') {
|
||||
this._unregLoadingWindow(window);
|
||||
this._delegate.onTrack(window);
|
||||
@ -103,7 +116,7 @@ WindowTracker.prototype = {
|
||||
|
||||
unload: function unload() {
|
||||
windowWatcher.unregisterNotification(this);
|
||||
for each (let window in windows())
|
||||
for each (let window in getWindows())
|
||||
this._unregWindow(window);
|
||||
},
|
||||
|
||||
@ -117,6 +130,9 @@ WindowTracker.prototype = {
|
||||
|
||||
observe: errors.catchAndLog(function observe(subject, topic, data) {
|
||||
var window = subject.QueryInterface(Ci.nsIDOMWindow);
|
||||
// ignore private windows if they are not supported
|
||||
if (ignoreWindow(window))
|
||||
return;
|
||||
if (topic == 'domwindowopened')
|
||||
this._regWindow(window);
|
||||
else
|
||||
@ -159,12 +175,12 @@ Object.defineProperties(exports, {
|
||||
activeWindow: {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return Cc['@mozilla.org/appshell/window-mediator;1']
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
.getMostRecentWindow(null);
|
||||
return getMostRecentWindow(null);
|
||||
},
|
||||
set: function(window) {
|
||||
try { window.focus(); } catch (e) { }
|
||||
try {
|
||||
window.focus();
|
||||
} catch (e) {}
|
||||
}
|
||||
},
|
||||
activeBrowserWindow: {
|
||||
|
@ -7,7 +7,8 @@ module.metadata = {
|
||||
"stability": "stable"
|
||||
};
|
||||
|
||||
const { setMode, getMode, on: onStateChange, isWindowPrivate } = require('./private-browsing/utils');
|
||||
const { setMode, getMode, on: onStateChange } = require('./private-browsing/utils');
|
||||
const { isWindowPrivate } = require('./window/utils');
|
||||
const { emit, on, once, off } = require('./event/core');
|
||||
const { when: unload } = require('./system/unload');
|
||||
const { deprecateUsage, deprecateFunction, deprecateEvent } = require('./util/deprecate');
|
||||
@ -38,15 +39,24 @@ exports.removeListener = deprecateEvents(function removeListener(type, listener)
|
||||
});
|
||||
|
||||
exports.isPrivate = function(thing) {
|
||||
// if thing is defined, and we can find a window for it
|
||||
// then check if the window is private
|
||||
if (!!thing) {
|
||||
// if the thing is a window, and the window is private
|
||||
// then return true
|
||||
if (isWindowPrivate(thing)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// can we find an associated window?
|
||||
let window = getOwnerWindow(thing);
|
||||
if (window)
|
||||
return isWindowPrivate(window);
|
||||
}
|
||||
|
||||
// if we get here, and global private browsing
|
||||
// is available, and it is true, then return
|
||||
// true otherwise false is returned here
|
||||
return getMode();
|
||||
};
|
||||
|
||||
|
@ -11,11 +11,11 @@ const { Cc, Ci, Cu } = require('chrome');
|
||||
const { defer } = require('../lang/functional');
|
||||
const { emit, on, once, off } = require('../event/core');
|
||||
const { when: unload } = require('../system/unload');
|
||||
const { getWindowLoadingContext, windows } = require('../window/utils');
|
||||
const { WindowTracker } = require("../deprecated/window-utils");
|
||||
const events = require('../system/events');
|
||||
const { deprecateFunction } = require('../util/deprecate');
|
||||
const { isOneOf, is, satisfiesVersion, version } = require('../system/xul-app');
|
||||
const { isWindowPrivate } = require('../window/utils');
|
||||
const { isPrivateBrowsingSupported } = require('../self');
|
||||
|
||||
let deferredEmit = defer(emit);
|
||||
let pbService;
|
||||
@ -33,7 +33,8 @@ if (isOneOf(['Firefox', 'Fennec'])) {
|
||||
// feature is not really active. See Bug 818800 and Bug 826037
|
||||
if (!('privateBrowsingEnabled' in pbService))
|
||||
pbService = undefined;
|
||||
} catch(e) { /* Private Browsing Service has been removed (Bug 818800) */ }
|
||||
}
|
||||
catch(e) { /* Private Browsing Service has been removed (Bug 818800) */ }
|
||||
|
||||
try {
|
||||
PrivateBrowsingUtils = Cu.import('resource://gre/modules/PrivateBrowsingUtils.jsm', {}).PrivateBrowsingUtils;
|
||||
@ -41,27 +42,6 @@ if (isOneOf(['Firefox', 'Fennec'])) {
|
||||
catch(e) { /* if this file DNE then an error will be thrown */ }
|
||||
}
|
||||
|
||||
function isWindowPrivate(win) {
|
||||
if (!PrivateBrowsingUtils || !win)
|
||||
return false;
|
||||
|
||||
// if the pbService is undefined, the PrivateBrowsingUtils.jsm is available,
|
||||
// and the app is Firefox, then assume per-window private browsing is
|
||||
// enabled.
|
||||
if (win instanceof Ci.nsIDOMWindow) {
|
||||
return PrivateBrowsingUtils.isWindowPrivate(win);
|
||||
}
|
||||
|
||||
// Sometimes the input is not a nsIDOMWindow.. but it is still a winodw.
|
||||
try {
|
||||
return !!win.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
exports.isWindowPrivate = isWindowPrivate;
|
||||
|
||||
// checks that global private browsing is implemented
|
||||
let isGlobalPBSupported = exports.isGlobalPBSupported = !!pbService && is('Firefox');
|
||||
|
||||
@ -72,6 +52,11 @@ let isWindowPBSupported = exports.isWindowPBSupported =
|
||||
// checks that per-tab private browsing is implemented
|
||||
let isTabPBSupported = exports.isTabPBSupported =
|
||||
!pbService && !!PrivateBrowsingUtils && is('Fennec') && satisfiesVersion(version, '>=20.0*');
|
||||
|
||||
function ignoreWindow(window) {
|
||||
return !isPrivateBrowsingSupported && isWindowPrivate(window);
|
||||
}
|
||||
exports.ignoreWindow = ignoreWindow;
|
||||
|
||||
function onChange() {
|
||||
// Emit event with in next turn of event loop.
|
||||
|
@ -13,6 +13,7 @@ function getOwnerWindow(thing) {
|
||||
try {
|
||||
// check for and return associated window
|
||||
let fn = (privateNS(thing.prototype) || privateNS(thing) || {}).getOwnerWindow;
|
||||
|
||||
if (fn)
|
||||
return fn.apply(fn, [thing].concat(arguments));
|
||||
}
|
||||
|
@ -39,18 +39,20 @@ var ids = exports.ids = {
|
||||
Thunderbird: "{3550f703-e582-4d05-9a08-453d09bdfdc6}"
|
||||
};
|
||||
|
||||
var is = exports.is = function is(name) {
|
||||
function is(name) {
|
||||
if (!(name in ids))
|
||||
throw new Error("Unkown Mozilla Application: " + name);
|
||||
return ID == ids[name];
|
||||
};
|
||||
exports.is = is;
|
||||
|
||||
var isOneOf = exports.isOneOf = function isOneOf(names) {
|
||||
function isOneOf(names) {
|
||||
for (var i = 0; i < names.length; i++)
|
||||
if (is(names[i]))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
exports.isOneOf = isOneOf;
|
||||
|
||||
/**
|
||||
* Use this to check whether the given version (e.g. xulApp.platformVersion)
|
||||
|
@ -11,7 +11,10 @@ function Options(options) {
|
||||
|
||||
return validateOptions(options, {
|
||||
url: { is: ["string"] },
|
||||
inBackground: { is: ["undefined", "boolean"] },
|
||||
inBackground: {
|
||||
map: function(v) !!v,
|
||||
is: ["undefined", "boolean"]
|
||||
},
|
||||
isPinned: { is: ["undefined", "boolean"] },
|
||||
isPrivate: { is: ["undefined", "boolean"] },
|
||||
onOpen: { is: ["undefined", "function"] },
|
||||
|
@ -3,8 +3,17 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict';
|
||||
|
||||
const { getTabForContentWindow } = require('./utils');
|
||||
module.metadata = {
|
||||
'stability': 'unstable'
|
||||
};
|
||||
|
||||
|
||||
// NOTE: This file should only export Tab instances
|
||||
|
||||
|
||||
const { getTabForContentWindow, getTabForBrowser: getRawTabForBrowser } = require('./utils');
|
||||
const { Tab } = require('./tab');
|
||||
const { rawTabNS } = require('./namespace');
|
||||
|
||||
function getTabForWindow(win) {
|
||||
let tab = getTabForContentWindow(win);
|
||||
@ -12,6 +21,21 @@ function getTabForWindow(win) {
|
||||
if (!tab)
|
||||
return null;
|
||||
|
||||
return Tab({ tab: tab });
|
||||
return getTabForRawTab(tab) || Tab({ tab: tab });
|
||||
}
|
||||
exports.getTabForWindow = getTabForWindow;
|
||||
|
||||
// only works on fennec atm
|
||||
function getTabForRawTab(rawTab) {
|
||||
let tab = rawTabNS(rawTab).tab;
|
||||
if (tab) {
|
||||
return tab;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.getTabForRawTab = getTabForRawTab;
|
||||
|
||||
function getTabForBrowser(browser) {
|
||||
return getTabForRawTab(getRawTabForBrowser(browser));
|
||||
}
|
||||
exports.getTabForBrowser = getTabForBrowser;
|
||||
|
@ -7,3 +7,4 @@ let { ns } = require('../core/namespace');
|
||||
|
||||
exports.tabsNS = ns();
|
||||
exports.tabNS = ns();
|
||||
exports.rawTabNS = ns();
|
||||
|
@ -5,27 +5,40 @@
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { Class } = require('../core/heritage');
|
||||
const { tabNS } = require('./namespace');
|
||||
const { tabNS, rawTabNS } = require('./namespace');
|
||||
const { EventTarget } = require('../event/target');
|
||||
const { activateTab, getTabTitle, setTabTitle, closeTab, getTabURL, getContentWindowForTab,
|
||||
getTabForBrowser,
|
||||
setTabURL, getOwnerWindow, getTabContentType, getTabId } = require('./utils');
|
||||
const { emit } = require('../event/core');
|
||||
const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
|
||||
const { when: unload } = require('../system/unload');
|
||||
|
||||
const { EVENTS } = require('./events');
|
||||
|
||||
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec';
|
||||
|
||||
const Tab = Class({
|
||||
extends: EventTarget,
|
||||
initialize: function initialize(options) {
|
||||
options = options.tab ? options : { tab: options };
|
||||
let tab = options.tab;
|
||||
|
||||
EventTarget.prototype.initialize.call(this, options);
|
||||
let tabInternals = tabNS(this);
|
||||
rawTabNS(tab).tab = this;
|
||||
|
||||
tabInternals.window = options.window || getOwnerWindow(options.tab);
|
||||
tabInternals.tab = options.tab;
|
||||
let window = tabInternals.window = options.window || getOwnerWindow(tab);
|
||||
tabInternals.tab = tab;
|
||||
|
||||
// TabReady
|
||||
let onReady = tabInternals.onReady = onTabReady.bind(this);
|
||||
tab.browser.addEventListener(EVENTS.ready.dom, onReady, false);
|
||||
|
||||
// TabClose
|
||||
let onClose = tabInternals.onClose = onTabClose.bind(this);
|
||||
window.BrowserApp.deck.addEventListener(EVENTS.close.dom, onClose, false);
|
||||
|
||||
unload(cleanupTab.bind(null, this));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -145,6 +158,41 @@ const Tab = Class({
|
||||
});
|
||||
exports.Tab = Tab;
|
||||
|
||||
function cleanupTab(tab) {
|
||||
let tabInternals = tabNS(tab);
|
||||
if (!tabInternals.tab)
|
||||
return;
|
||||
|
||||
if (tabInternals.tab.browser) {
|
||||
tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady, false);
|
||||
}
|
||||
tabInternals.onReady = null;
|
||||
tabInternals.window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, tabInternals.onClose, false);
|
||||
tabInternals.onClose = null;
|
||||
rawTabNS(tabInternals.tab).tab = null;
|
||||
tabInternals.tab = null;
|
||||
tabInternals.window = null;
|
||||
}
|
||||
|
||||
function onTabReady(event) {
|
||||
let win = event.target.defaultView;
|
||||
|
||||
// ignore frames
|
||||
if (win === win.top) {
|
||||
emit(this, 'ready', this);
|
||||
}
|
||||
}
|
||||
|
||||
// TabClose
|
||||
function onTabClose(event) {
|
||||
let rawTab = getTabForBrowser(event.target);
|
||||
if (tabNS(this).tab !== rawTab)
|
||||
return;
|
||||
|
||||
emit(this, EVENTS.close.name, this);
|
||||
cleanupTab(this);
|
||||
};
|
||||
|
||||
getPBOwnerWindow.define(Tab, function(tab) {
|
||||
return getContentWindowForTab(tabNS(tab).tab);
|
||||
});
|
||||
|
@ -11,9 +11,9 @@ module.metadata = {
|
||||
}
|
||||
};
|
||||
|
||||
if (require('../system/xul-app').is('Firefox')) {
|
||||
module.exports = require('./tab-firefox');
|
||||
}
|
||||
else if (require('../system/xul-app').is('Fennec')) {
|
||||
if (require('../system/xul-app').name == 'Fennec') {
|
||||
module.exports = require('./tab-fennec');
|
||||
}
|
||||
else {
|
||||
module.exports = require('./tab-firefox');
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ Object.defineProperties(tabs, {
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
// Open in active window if new window was not required..
|
||||
|
||||
// Open in active window if new window was not required.
|
||||
|
||||
let activeWindow = windows.activeWindow;
|
||||
let privateState = !!options.isPrivate;
|
||||
@ -35,7 +34,7 @@ Object.defineProperties(tabs, {
|
||||
// find a window in the state that we need
|
||||
let window = getWindow(privateState);
|
||||
if (window) {
|
||||
window.tabs.open(options);
|
||||
window.tabs.open(options);
|
||||
}
|
||||
// open a window in the state that we need
|
||||
else {
|
||||
@ -52,9 +51,9 @@ Object.defineProperties(tabs, {
|
||||
|
||||
function getWindow(privateState) {
|
||||
for each (let window in windows) {
|
||||
if (privateState === isPrivate(window)) {
|
||||
return window;
|
||||
}
|
||||
if (privateState === isPrivate(window)) {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ module.metadata = {
|
||||
}
|
||||
};
|
||||
|
||||
if (require('../system/xul-app').is('Firefox')) {
|
||||
module.exports = require('./tabs-firefox');
|
||||
}
|
||||
else if (require('../system/xul-app').is('Fennec')) {
|
||||
if (require('../system/xul-app').name == 'Fennec') {
|
||||
module.exports = require('../windows/tabs-fennec').tabs;
|
||||
}
|
||||
else {
|
||||
module.exports = require('./tabs-firefox');
|
||||
}
|
||||
|
@ -8,9 +8,17 @@ module.metadata = {
|
||||
'stability': 'unstable'
|
||||
};
|
||||
|
||||
|
||||
// NOTE: This file should only deal with xul/native tabs
|
||||
|
||||
|
||||
const { Ci } = require('chrome');
|
||||
const { defer } = require("../lang/functional");
|
||||
const { windows, isBrowser } = require('../window/utils');
|
||||
const { Ci } = require('chrome');
|
||||
const { isPrivateBrowsingSupported } = require('../self');
|
||||
|
||||
// Bug 834961: ignore private windows when they are not supported
|
||||
function getWindows() windows(null, { includePrivate: isPrivateBrowsingSupported });
|
||||
|
||||
function activateTab(tab, window) {
|
||||
let gBrowser = getTabBrowserForTab(tab);
|
||||
@ -48,7 +56,7 @@ exports.getTabContainer = getTabContainer;
|
||||
*/
|
||||
function getTabs(window) {
|
||||
if (arguments.length === 0) {
|
||||
return windows().filter(isBrowser).reduce(function(tabs, window) {
|
||||
return getWindows().filter(isBrowser).reduce(function(tabs, window) {
|
||||
return tabs.concat(getTabs(window))
|
||||
}, []);
|
||||
}
|
||||
@ -63,7 +71,7 @@ function getTabs(window) {
|
||||
exports.getTabs = getTabs;
|
||||
|
||||
function getActiveTab(window) {
|
||||
return window.gBrowser.selectedTab;
|
||||
return getSelectedTab(window);
|
||||
}
|
||||
exports.getActiveTab = getActiveTab;
|
||||
|
||||
@ -79,7 +87,7 @@ exports.getOwnerWindow = getOwnerWindow;
|
||||
|
||||
// fennec
|
||||
function getWindowHoldingTab(rawTab) {
|
||||
for each (let window in windows()) {
|
||||
for each (let window in getWindows()) {
|
||||
// this function may be called when not using fennec,
|
||||
// but BrowserApp is only defined on Fennec
|
||||
if (!window.BrowserApp)
|
||||
@ -105,10 +113,13 @@ function openTab(window, url, options) {
|
||||
isPrivate: options.isPrivate || false
|
||||
});
|
||||
}
|
||||
let tab = window.gBrowser.addTab(url);
|
||||
if (!options.inBackground)
|
||||
activateTab(tab);
|
||||
return tab;
|
||||
|
||||
// firefox
|
||||
let newTab = window.gBrowser.addTab(url);
|
||||
if (!options.inBackground) {
|
||||
activateTab(newTab);
|
||||
}
|
||||
return newTab;
|
||||
};
|
||||
exports.openTab = openTab;
|
||||
|
||||
@ -195,6 +206,7 @@ function getAllTabContentWindows() {
|
||||
}
|
||||
exports.getAllTabContentWindows = getAllTabContentWindows;
|
||||
|
||||
// gets the tab containing the provided window
|
||||
function getTabForContentWindow(window) {
|
||||
// Retrieve the topmost frame container. It can be either <xul:browser>,
|
||||
// <xul:iframe/> or <html:iframe/>. But in our case, it should be xul:browser.
|
||||
@ -202,9 +214,12 @@ function getTabForContentWindow(window) {
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
|
||||
// Is null for toplevel documents
|
||||
if (!browser)
|
||||
if (!browser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the owner window, should be browser.xul one
|
||||
let chromeWindow = browser.ownerDocument.defaultView;
|
||||
|
||||
@ -221,15 +236,29 @@ function getTabForContentWindow(window) {
|
||||
return chromeWindow.gBrowser.tabs[i];
|
||||
return null;
|
||||
}
|
||||
// Fennec
|
||||
else if ('BrowserApp' in chromeWindow) {
|
||||
// Looks like we are on Firefox Mobile
|
||||
return chromeWindow.BrowserApp.getTabForWindow(window)
|
||||
return getTabForWindow(window);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
exports.getTabForContentWindow = getTabForContentWindow;
|
||||
|
||||
// used on fennec
|
||||
function getTabForWindow(window) {
|
||||
for each (let { BrowserApp } in getWindows()) {
|
||||
if (!BrowserApp)
|
||||
continue;
|
||||
|
||||
for each (let tab in BrowserApp.tabs) {
|
||||
if (tab.browser.contentWindow == window.top)
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getTabURL(tab) {
|
||||
if (tab.browser) // fennec
|
||||
return String(tab.browser.currentURI.spec);
|
||||
@ -262,3 +291,20 @@ function getSelectedTab(window) {
|
||||
return null;
|
||||
}
|
||||
exports.getSelectedTab = getSelectedTab;
|
||||
|
||||
|
||||
function getTabForBrowser(browser) {
|
||||
for each (let window in getWindows()) {
|
||||
// this function may be called when not using fennec
|
||||
if (!window.BrowserApp)
|
||||
continue;
|
||||
|
||||
for each (let tab in window.BrowserApp.tabs) {
|
||||
if (tab.browser === browser)
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.getTabForBrowser = getTabForBrowser;
|
||||
|
||||
|
@ -69,14 +69,17 @@ Assert.prototype = {
|
||||
return;
|
||||
}
|
||||
let message = e.message;
|
||||
if ('operator' in e) {
|
||||
message += [
|
||||
" -",
|
||||
source(e.expected),
|
||||
e.operator,
|
||||
source(e.actual)
|
||||
].join(" ");
|
||||
try {
|
||||
if ('operator' in e) {
|
||||
message += [
|
||||
" -",
|
||||
source(e.expected),
|
||||
e.operator,
|
||||
source(e.actual)
|
||||
].join(" ");
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
this._log.fail(message);
|
||||
},
|
||||
pass: function pass(message) {
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
const { Loader, resolveURI, Require,
|
||||
unload, override, descriptor } = require('../loader/cuddlefish');
|
||||
const { PlainTextConsole } = require("sdk/console/plain-text");
|
||||
|
||||
exports.Loader = function(module, globals, packaging) {
|
||||
function CustomLoader(module, globals, packaging) {
|
||||
let options = packaging || require("@loader/options");
|
||||
options = override(options, {
|
||||
globals: override(require('../system/globals'), globals || {})
|
||||
@ -26,3 +27,45 @@ exports.Loader = function(module, globals, packaging) {
|
||||
}
|
||||
}));
|
||||
};
|
||||
exports.Loader = CustomLoader;
|
||||
|
||||
// Creates a custom loader instance whose console module is hooked in order
|
||||
// to avoid printing messages to the console, and instead, expose them in the
|
||||
// returned `messages` array attribute
|
||||
exports.LoaderWithHookedConsole = function (module, callback) {
|
||||
let messages = [];
|
||||
function hook(msg) {
|
||||
messages.push({type: this, msg: msg});
|
||||
if (callback)
|
||||
callback(this, msg);
|
||||
}
|
||||
return {
|
||||
loader: CustomLoader(module, {
|
||||
console: {
|
||||
log: hook.bind("log"),
|
||||
info: hook.bind("info"),
|
||||
warn: hook.bind("warn"),
|
||||
error: hook.bind("error"),
|
||||
debug: hook.bind("debug"),
|
||||
exception: hook.bind("exception")
|
||||
}
|
||||
}),
|
||||
messages: messages
|
||||
};
|
||||
}
|
||||
|
||||
// Same than LoaderWithHookedConsole with lower level, instead we get what is
|
||||
// actually printed to the command line console
|
||||
exports.LoaderWithHookedConsole2 = function (module, callback) {
|
||||
let messages = [];
|
||||
return {
|
||||
loader: CustomLoader(module, {
|
||||
console: new PlainTextConsole(function (msg) {
|
||||
messages.push(msg);
|
||||
if (callback)
|
||||
callback(msg);
|
||||
})
|
||||
}),
|
||||
messages: messages
|
||||
};
|
||||
}
|
||||
|
@ -87,3 +87,11 @@ exports.flatten = function flatten(array){
|
||||
}
|
||||
return flat;
|
||||
};
|
||||
|
||||
function fromIterator(iterator) {
|
||||
let array = [];
|
||||
for each (let item in iterator)
|
||||
array.push(item);
|
||||
return array;
|
||||
}
|
||||
exports.fromIterator = fromIterator;
|
||||
|
@ -9,9 +9,10 @@ const { on, off, once } = require('../event/core');
|
||||
const { method } = require('../lang/functional');
|
||||
const { getWindowTitle } = require('./utils');
|
||||
const unload = require('../system/unload');
|
||||
const { getMode } = require('../private-browsing/utils');
|
||||
const { isWindowPrivate } = require('../private-browsing/utils');
|
||||
const { EventTarget } = require('../event/target');
|
||||
const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
|
||||
const { deprecateUsage } = require('../util/deprecate');
|
||||
|
||||
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("tabs") instead';
|
||||
|
||||
@ -37,7 +38,13 @@ const BrowserWindow = Class({
|
||||
on: method(on),
|
||||
removeListener: method(off),
|
||||
once: method(once),
|
||||
get isPrivateBrowsing() getMode(windowNS(this).window),
|
||||
get isPrivateBrowsing() {
|
||||
deprecateUsage('`browserWindow.isPrivateBrowsing` is deprecated, please ' +
|
||||
'consider using ' +
|
||||
'`require("private-browsing").isPrivate(browserWindow)` ' +
|
||||
'instead.');
|
||||
return isWindowPrivate(windowNS(this).window);
|
||||
}
|
||||
});
|
||||
exports.BrowserWindow = BrowserWindow;
|
||||
|
||||
|
@ -9,12 +9,13 @@ module.metadata = {
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const array = require('../util/array');
|
||||
const observers = require('../deprecated/observer-service');
|
||||
const { defer } = require('sdk/core/promise');
|
||||
|
||||
const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
|
||||
getService(Ci.nsIAppShellService);
|
||||
const observers = require('../deprecated/observer-service');
|
||||
const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
|
||||
@ -23,11 +24,41 @@ const BROWSER = 'navigator:browser',
|
||||
NAME = '_blank',
|
||||
FEATURES = 'chrome,all,dialog=no';
|
||||
|
||||
function isWindowPrivate(win) {
|
||||
if (!win)
|
||||
return false;
|
||||
|
||||
// if the pbService is undefined, the PrivateBrowsingUtils.jsm is available,
|
||||
// and the app is Firefox, then assume per-window private browsing is
|
||||
// enabled.
|
||||
try {
|
||||
return win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext)
|
||||
.usePrivateBrowsing;
|
||||
}
|
||||
catch(e) {}
|
||||
|
||||
// Sometimes the input is not a nsIDOMWindow.. but it is still a winodw.
|
||||
try {
|
||||
return !!win.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
exports.isWindowPrivate = isWindowPrivate;
|
||||
|
||||
function getMostRecentBrowserWindow() {
|
||||
return WM.getMostRecentWindow(BROWSER);
|
||||
return getMostRecentWindow(BROWSER);
|
||||
}
|
||||
exports.getMostRecentBrowserWindow = getMostRecentBrowserWindow;
|
||||
|
||||
function getMostRecentWindow(type) {
|
||||
return WM.getMostRecentWindow(type);
|
||||
}
|
||||
exports.getMostRecentWindow = getMostRecentWindow;
|
||||
|
||||
/**
|
||||
* Returns the ID of the window's current inner window.
|
||||
*/
|
||||
@ -107,6 +138,11 @@ exports.backgroundify = backgroundify;
|
||||
function serializeFeatures(options) {
|
||||
return Object.keys(options).reduce(function(result, name) {
|
||||
let value = options[name];
|
||||
|
||||
// the chrome and private features are special
|
||||
if ((name == 'private' || name == 'chrome'))
|
||||
return result + ((value === true) ? ',' + name : '');
|
||||
|
||||
return result + ',' + name + '=' +
|
||||
(value === true ? 'yes' : value === false ? 'no' : value);
|
||||
}, '').substr(1);
|
||||
@ -121,19 +157,55 @@ function serializeFeatures(options) {
|
||||
* @params {String} options.name
|
||||
* Optional name that is assigned to the window.
|
||||
* @params {Object} options.features
|
||||
* Map of key, values like: `{ width: 10, height: 15, chrome: true }`.
|
||||
* Map of key, values like: `{ width: 10, height: 15, chrome: true, private: true }`.
|
||||
*/
|
||||
function open(uri, options) {
|
||||
options = options || {};
|
||||
return windowWatcher.
|
||||
let newWindow = windowWatcher.
|
||||
openWindow(options.parent || null,
|
||||
uri,
|
||||
options.name || null,
|
||||
serializeFeatures(options.features || {}),
|
||||
options.args || null);
|
||||
|
||||
return newWindow;
|
||||
}
|
||||
exports.open = open;
|
||||
|
||||
function onFocus(window) {
|
||||
let deferred = defer();
|
||||
|
||||
if (isFocused(window)) {
|
||||
deferred.resolve(window);
|
||||
}
|
||||
else {
|
||||
window.addEventListener("focus", function focusListener() {
|
||||
window.removeEventListener("focus", focusListener, true);
|
||||
deferred.resolve(window);
|
||||
}, true);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
exports.onFocus = onFocus;
|
||||
|
||||
function isFocused(window) {
|
||||
const FM = Cc["@mozilla.org/focus-manager;1"].
|
||||
getService(Ci.nsIFocusManager);
|
||||
|
||||
let childTargetWindow = {};
|
||||
FM.getFocusedElementForWindow(window, true, childTargetWindow);
|
||||
childTargetWindow = childTargetWindow.value;
|
||||
|
||||
let focusedChildWindow = {};
|
||||
if (FM.activeWindow) {
|
||||
FM.getFocusedElementForWindow(FM.activeWindow, true, focusedChildWindow);
|
||||
focusedChildWindow = focusedChildWindow.value;
|
||||
}
|
||||
|
||||
return (focusedChildWindow === childTargetWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a top level window and returns it's `nsIDOMWindow` representation.
|
||||
* Same as `open` but with more features
|
||||
@ -149,8 +221,13 @@ function openDialog(options) {
|
||||
features = features.split(',').concat('private').join(',');
|
||||
}
|
||||
|
||||
let browser = WM.getMostRecentWindow(BROWSER);
|
||||
return browser.openDialog.apply(
|
||||
let browser = getMostRecentBrowserWindow();
|
||||
|
||||
// if there is no browser then do nothing
|
||||
if (!browser)
|
||||
return undefined;
|
||||
|
||||
let newWindow = browser.openDialog.apply(
|
||||
browser,
|
||||
array.flatten([
|
||||
options.url || URI_BROWSER,
|
||||
@ -159,6 +236,8 @@ function openDialog(options) {
|
||||
options.args || null
|
||||
])
|
||||
);
|
||||
|
||||
return newWindow;
|
||||
}
|
||||
exports.openDialog = openDialog;
|
||||
|
||||
@ -166,12 +245,17 @@ exports.openDialog = openDialog;
|
||||
* Returns an array of all currently opened windows.
|
||||
* Note that these windows may still be loading.
|
||||
*/
|
||||
function windows() {
|
||||
function windows(type, options) {
|
||||
options = options || {};
|
||||
let list = [];
|
||||
let winEnum = windowWatcher.getWindowEnumerator();
|
||||
let winEnum = WM.getEnumerator(type);
|
||||
while (winEnum.hasMoreElements()) {
|
||||
let window = winEnum.getNext().QueryInterface(Ci.nsIDOMWindow);
|
||||
list.push(window);
|
||||
// Only add non-private windows when pb permission isn't set,
|
||||
// unless an option forces the addition of them.
|
||||
if (options.includePrivate || !isWindowPrivate(window)) {
|
||||
list.push(window);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@ -189,7 +273,11 @@ function isDocumentLoaded(window) {
|
||||
exports.isDocumentLoaded = isDocumentLoaded;
|
||||
|
||||
function isBrowser(window) {
|
||||
return window.document.documentElement.getAttribute("windowtype") === BROWSER;
|
||||
try {
|
||||
return window.document.documentElement.getAttribute("windowtype") === BROWSER;
|
||||
}
|
||||
catch (e) {}
|
||||
return false;
|
||||
};
|
||||
exports.isBrowser = isBrowser;
|
||||
|
||||
|
@ -11,9 +11,9 @@ module.metadata = {
|
||||
}
|
||||
};
|
||||
|
||||
if (require('./system/xul-app').is('Firefox')) {
|
||||
module.exports = require('./windows/firefox');
|
||||
}
|
||||
else if (require('./system/xul-app').is('Fennec')) {
|
||||
if (require('./system/xul-app').is('Fennec')) {
|
||||
module.exports = require('./windows/fennec');
|
||||
}
|
||||
else {
|
||||
module.exports = require('./windows/firefox');
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
'use strict';
|
||||
|
||||
const { Trait } = require('../deprecated/traits');
|
||||
const { getWindowTitle } = require('../window/utils');
|
||||
const { getMode } = require('../private-browsing/utils');
|
||||
const { isWindowPrivate, getWindowTitle } = require('../window/utils');
|
||||
const { deprecateUsage } = require('../util/deprecate');
|
||||
|
||||
module.metadata = {
|
||||
"stability": "unstable"
|
||||
@ -27,7 +27,11 @@ const WindowDom = Trait.compose({
|
||||
return this._public;
|
||||
},
|
||||
get isPrivateBrowsing() {
|
||||
return getMode(this._window);
|
||||
deprecateUsage('`browserWindow.isPrivateBrowsing` is deprecated, please ' +
|
||||
'consider using ' +
|
||||
'`require("private-browsing").isPrivate(browserWindow)` ' +
|
||||
'instead.');
|
||||
return isWindowPrivate(this._window);
|
||||
}
|
||||
});
|
||||
exports.WindowDom = WindowDom;
|
||||
|
@ -10,7 +10,7 @@ const { Cc, Ci, Cr } = require('chrome'),
|
||||
{ WindowTabs, WindowTabTracker } = require('./tabs-firefox'),
|
||||
{ WindowDom } = require('./dom'),
|
||||
{ WindowLoader } = require('./loader'),
|
||||
{ isBrowser, getWindowDocShell } = require('../window/utils'),
|
||||
{ isBrowser, getWindowDocShell, windows: windowIterator } = require('../window/utils'),
|
||||
{ Options } = require('../tabs/common'),
|
||||
apiUtils = require('../deprecated/api-utils'),
|
||||
unload = require('../system/unload'),
|
||||
@ -21,6 +21,7 @@ const { Cc, Ci, Cr } = require('chrome'),
|
||||
{ getOwnerWindow } = require('../private-browsing/window/utils'),
|
||||
viewNS = require('../core/namespace').ns(),
|
||||
{ isPrivateBrowsingSupported } = require('../self');
|
||||
const { ignoreWindow } = require('sdk/private-browsing/utils');
|
||||
|
||||
/**
|
||||
* Window trait composes safe wrappers for browser window that are E10S
|
||||
@ -207,6 +208,9 @@ const browserWindows = Trait.resolve({ toString: null }).compose(
|
||||
*/
|
||||
get activeWindow() {
|
||||
let window = windowUtils.activeBrowserWindow;
|
||||
// Bug 834961: ignore private windows when they are not supported
|
||||
if (ignoreWindow(window))
|
||||
window = windowIterator()[0];
|
||||
return window ? BrowserWindow({window: window}) : null;
|
||||
},
|
||||
open: function open(options) {
|
||||
@ -231,6 +235,7 @@ const browserWindows = Trait.resolve({ toString: null }).compose(
|
||||
this._add(window);
|
||||
this._emit('open', window);
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal listener which is called whenever window gets closed.
|
||||
* Cleans up references and removes wrapper from this list.
|
||||
|
@ -8,8 +8,9 @@ const { Tab } = require('../tabs/tab');
|
||||
const { browserWindows } = require('./fennec');
|
||||
const { windowNS } = require('../window/namespace');
|
||||
const { tabsNS, tabNS } = require('../tabs/namespace');
|
||||
const { openTab, getTabs, getSelectedTab } = require('../tabs/utils');
|
||||
const { openTab, getTabs, getSelectedTab, getTabForBrowser: getRawTabForBrowser } = require('../tabs/utils');
|
||||
const { Options } = require('../tabs/common');
|
||||
const { getTabForBrowser, getTabForRawTab } = require('../tabs/helpers');
|
||||
const { on, once, off, emit } = require('../event/core');
|
||||
const { method } = require('../lang/functional');
|
||||
const { EVENTS } = require('../tabs/events');
|
||||
@ -41,9 +42,6 @@ const Tabs = Class({
|
||||
|
||||
// TabSelect
|
||||
window.BrowserApp.deck.addEventListener(EVENTS.activate.dom, onTabSelect, false);
|
||||
|
||||
// TabClose
|
||||
window.BrowserApp.deck.addEventListener(EVENTS.close.dom, onTabClose, false);
|
||||
},
|
||||
get activeTab() {
|
||||
return getTabForRawTab(getSelectedTab(tabsNS(this).window));
|
||||
@ -92,7 +90,6 @@ function tabsUnloader(event, window) {
|
||||
return;
|
||||
window.BrowserApp.deck.removeEventListener(EVENTS.open.dom, onTabOpen, false);
|
||||
window.BrowserApp.deck.removeEventListener(EVENTS.activate.dom, onTabSelect, false);
|
||||
window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, onTabClose, false);
|
||||
}
|
||||
|
||||
// unload handler
|
||||
@ -112,20 +109,6 @@ function removeTab(tab) {
|
||||
return tab;
|
||||
}
|
||||
|
||||
function getTabForBrowser(browser) {
|
||||
return getTabForRawTab(getRawTabForBrowser(browser));
|
||||
}
|
||||
|
||||
function getRawTabForBrowser(browser) {
|
||||
let tabs = mainWindow.BrowserApp.tabs;
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
let tab = tabs[i];
|
||||
if (tab.browser === browser)
|
||||
return tab
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// TabOpen
|
||||
function onTabOpen(event) {
|
||||
let browser = event.target;
|
||||
@ -140,19 +123,13 @@ function onTabOpen(event) {
|
||||
|
||||
tabNS(tab).opened = true;
|
||||
|
||||
// TabReady
|
||||
let onReady = tabNS(tab).onReady = onTabReady.bind(tab);
|
||||
browser.addEventListener(EVENTS.ready.dom, onReady, false);
|
||||
tab.on('ready', function() emit(gTabs, 'ready', tab));
|
||||
tab.once('close', onTabClose);
|
||||
|
||||
emit(tab, 'open', tab);
|
||||
emit(gTabs, 'open', tab);
|
||||
};
|
||||
|
||||
function onTabReady() {
|
||||
emit(this, 'ready', this);
|
||||
emit(gTabs, 'ready', this);
|
||||
}
|
||||
|
||||
// TabSelect
|
||||
function onTabSelect(event) {
|
||||
// Set value whenever new tab becomes active.
|
||||
@ -168,28 +145,7 @@ function onTabSelect(event) {
|
||||
};
|
||||
|
||||
// TabClose
|
||||
function onTabClose(event) {
|
||||
let tab = getTabForBrowser(event.target);
|
||||
function onTabClose(tab) {
|
||||
removeTab(tab);
|
||||
|
||||
emit(gTabs, 'close', tab);
|
||||
emit(tab, 'close', tab);
|
||||
emit(gTabs, EVENTS.close.name, tab);
|
||||
};
|
||||
|
||||
function getTabForRawTab(rawTab) {
|
||||
for each (let tab in gTabs) {
|
||||
if (tabNS(tab).tab === rawTab)
|
||||
return tab;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
unload(function() {
|
||||
for each (let tab in gTabs) {
|
||||
let tabInternals = tabNS(tab);
|
||||
tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady, false);
|
||||
tabInternals.onReady = null;
|
||||
tabInternals.tab = null;
|
||||
tabInternals.window = null;
|
||||
}
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ const { getOwnerWindow, getActiveTab, getTabs,
|
||||
openTab } = require("../tabs/utils");
|
||||
const { Options } = require("../tabs/common");
|
||||
const { observer: tabsObserver } = require("../tabs/observer");
|
||||
const { isWindowPrivate } = require("../private-browsing/utils");
|
||||
const { ignoreWindow, isWindowPrivate } = require("../private-browsing/utils");
|
||||
|
||||
const TAB_BROWSER = "tabbrowser";
|
||||
|
||||
@ -91,7 +91,9 @@ const WindowTabTracker = Trait.compose({
|
||||
tabsObserver.removeListener("deactivate", this._onTabDeactivate);
|
||||
},
|
||||
_onTabEvent: function _onTabEvent(type, tab) {
|
||||
if (this._window === getOwnerWindow(tab)) {
|
||||
// Accept only tabs for the watched window, and ignore private tabs
|
||||
// if addon doesn't have private permission
|
||||
if (this._window === getOwnerWindow(tab) && !ignoreWindow(this._window)) {
|
||||
let options = this._tabOptions.shift() || {};
|
||||
options.tab = tab;
|
||||
options.window = this._public;
|
||||
|
@ -825,8 +825,8 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
if target_cfg.get('preferences'):
|
||||
harness_options['preferences'] = target_cfg.get('preferences')
|
||||
|
||||
harness_options['manifest'] = \
|
||||
manifest.get_harness_options_manifest(options.bundle_sdk)
|
||||
# Do not add entries for SDK modules
|
||||
harness_options['manifest'] = manifest.get_harness_options_manifest(False)
|
||||
|
||||
# Gives an hint to tell if sdk modules are bundled or not
|
||||
harness_options['is-sdk-bundled'] = options.bundle_sdk
|
||||
@ -912,6 +912,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
binary=options.binary,
|
||||
profiledir=options.profiledir,
|
||||
verbose=options.verbose,
|
||||
parseable=options.parseable,
|
||||
enforce_timeouts=enforce_timeouts,
|
||||
logfile=options.logfile,
|
||||
addons=options.addons,
|
||||
|
0
addon-sdk/source/python-lib/cuddlefish/docs/documentationitem.py
Normal file → Executable file
0
addon-sdk/source/python-lib/cuddlefish/docs/generate.py
Normal file → Executable file
0
addon-sdk/source/python-lib/cuddlefish/docs/webdocs.py
Normal file → Executable file
@ -269,8 +269,7 @@ class ManifestBuilder:
|
||||
yield absname
|
||||
|
||||
for me in self.get_module_entries():
|
||||
# Do not add manifest entries for system modules,
|
||||
# so that we won't ship SDK files.
|
||||
# Only ship SDK files if we are told to do so
|
||||
if me.packageName != "addon-sdk" or bundle_sdk_modules:
|
||||
yield me.js_filename
|
||||
|
||||
@ -281,8 +280,9 @@ class ManifestBuilder:
|
||||
manifest = {}
|
||||
for me in self.get_module_entries():
|
||||
path = me.get_path()
|
||||
# Do not add manifest entries for system modules,
|
||||
# so that we won't ship SDK files.
|
||||
# Do not add manifest entries for system modules.
|
||||
# Doesn't prevent from shipping modules.
|
||||
# Shipping modules is decided in `get_used_files`.
|
||||
if me.packageName != "addon-sdk" or bundle_sdk_modules:
|
||||
manifest[path] = me.get_entry_for_manifest()
|
||||
return manifest
|
||||
@ -474,18 +474,6 @@ class ManifestBuilder:
|
||||
# non-relative import. Might be a short name (requiring a search
|
||||
# through "library" packages), or a fully-qualified one.
|
||||
|
||||
# Search for a module in new layout.
|
||||
# First normalize require argument in order to easily find a mapping
|
||||
normalized = reqname
|
||||
if normalized.endswith(".js"):
|
||||
normalized = normalized[:-len(".js")]
|
||||
if normalized.startswith("addon-kit/"):
|
||||
normalized = normalized[len("addon-kit/"):]
|
||||
if normalized.startswith("api-utils/"):
|
||||
normalized = normalized[len("api-utils/"):]
|
||||
if normalized in NEW_LAYOUT_MAPPING:
|
||||
reqname = NEW_LAYOUT_MAPPING[normalized]
|
||||
|
||||
if "/" in reqname:
|
||||
# 2: PKG/MOD: find PKG, look inside for MOD
|
||||
bits = reqname.split("/")
|
||||
@ -507,9 +495,32 @@ class ManifestBuilder:
|
||||
# their own package first, then the list of packages defined by their
|
||||
# .dependencies list
|
||||
from_pkg = from_module.package.name
|
||||
return self._search_packages_for_module(from_pkg,
|
||||
lookfor_sections, reqname,
|
||||
looked_in)
|
||||
mi = self._search_packages_for_module(from_pkg,
|
||||
lookfor_sections, reqname,
|
||||
looked_in)
|
||||
if mi:
|
||||
return mi
|
||||
|
||||
# Only after we look for module in the addon itself, search for a module
|
||||
# in new layout.
|
||||
# First normalize require argument in order to easily find a mapping
|
||||
normalized = reqname
|
||||
if normalized.endswith(".js"):
|
||||
normalized = normalized[:-len(".js")]
|
||||
if normalized.startswith("addon-kit/"):
|
||||
normalized = normalized[len("addon-kit/"):]
|
||||
if normalized.startswith("api-utils/"):
|
||||
normalized = normalized[len("api-utils/"):]
|
||||
if normalized in NEW_LAYOUT_MAPPING:
|
||||
# get the new absolute path for this module
|
||||
reqname = NEW_LAYOUT_MAPPING[normalized]
|
||||
from_pkg = from_module.package.name
|
||||
return self._search_packages_for_module(from_pkg,
|
||||
lookfor_sections, reqname,
|
||||
looked_in)
|
||||
else:
|
||||
# We weren't able to find this module, really.
|
||||
return None
|
||||
|
||||
def _handle_module(self, mi):
|
||||
if not mi:
|
||||
@ -659,12 +670,13 @@ def scan_requirements_with_grep(fn, lines):
|
||||
iscomment = True
|
||||
if iscomment:
|
||||
continue
|
||||
mo = re.search(REQUIRE_RE, clause)
|
||||
mo = re.finditer(REQUIRE_RE, clause)
|
||||
if mo:
|
||||
modname = mo.group(1)
|
||||
requires[modname] = {}
|
||||
if modname not in first_location:
|
||||
first_location[modname] = lineno0+1
|
||||
for mod in mo:
|
||||
modname = mod.group(1)
|
||||
requires[modname] = {}
|
||||
if modname not in first_location:
|
||||
first_location[modname] = lineno0 + 1
|
||||
|
||||
# define() can happen across multiple lines, so join everyone up.
|
||||
wholeshebang = "\n".join(lines)
|
||||
|
0
addon-sdk/source/python-lib/cuddlefish/preflight.py
Normal file → Executable file
@ -10,6 +10,7 @@ import atexit
|
||||
import shlex
|
||||
import subprocess
|
||||
import re
|
||||
import shutil
|
||||
|
||||
import mozrunner
|
||||
from cuddlefish.prefs import DEFAULT_COMMON_PREFS
|
||||
@ -22,6 +23,9 @@ CLEANUP_ADB = re.compile(r'^(I|E)/(stdout|stderr|GeckoConsole)\s*\(\s*\d+\):\s*(
|
||||
# Used to filter only messages send by `console` module
|
||||
FILTER_ONLY_CONSOLE_FROM_ADB = re.compile(r'^I/(stdout|stderr)\s*\(\s*\d+\):\s*((info|warning|error|debug): .*)$')
|
||||
|
||||
# Used to detect the currently running test
|
||||
PARSEABLE_TEST_NAME = re.compile(r'TEST-START \| ([^\n]+)\n')
|
||||
|
||||
# Maximum time we'll wait for tests to finish, in seconds.
|
||||
# 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
|
||||
@ -123,13 +127,13 @@ class FennecRunner(mozrunner.Runner):
|
||||
self.__real_binary = mozrunner.Runner.find_binary(self)
|
||||
return self.__real_binary
|
||||
|
||||
FENNEC_REMOTE_PATH = '/mnt/sdcard/jetpack-profile'
|
||||
|
||||
class RemoteFennecRunner(mozrunner.Runner):
|
||||
profile_class = FennecProfile
|
||||
|
||||
names = ['fennec']
|
||||
|
||||
_REMOTE_PATH = '/mnt/sdcard/jetpack-profile'
|
||||
_INTENT_PREFIX = 'org.mozilla.'
|
||||
|
||||
_adb_path = None
|
||||
@ -198,13 +202,13 @@ class RemoteFennecRunner(mozrunner.Runner):
|
||||
print "Pushing the addon to your device"
|
||||
|
||||
# Create a clean empty profile on the sd card
|
||||
subprocess.call([self._adb_path, "shell", "rm -r " + self._REMOTE_PATH])
|
||||
subprocess.call([self._adb_path, "shell", "mkdir " + self._REMOTE_PATH])
|
||||
subprocess.call([self._adb_path, "shell", "rm -r " + FENNEC_REMOTE_PATH])
|
||||
subprocess.call([self._adb_path, "shell", "mkdir " + FENNEC_REMOTE_PATH])
|
||||
|
||||
# Push the profile folder created by mozrunner to the device
|
||||
# (we can't simply use `adb push` as it doesn't copy empty folders)
|
||||
localDir = self.profile.profile
|
||||
remoteDir = self._REMOTE_PATH
|
||||
remoteDir = FENNEC_REMOTE_PATH
|
||||
for root, dirs, files in os.walk(localDir, followlinks='true'):
|
||||
relRoot = os.path.relpath(root, localDir)
|
||||
# Note about os.path usage below:
|
||||
@ -236,7 +240,7 @@ class RemoteFennecRunner(mozrunner.Runner):
|
||||
"am start " +
|
||||
"-a android.activity.MAIN " +
|
||||
"-n " + self._intent_name + "/" + self._intent_name + ".App " +
|
||||
"--es args \"-profile " + self._REMOTE_PATH + "\""
|
||||
"--es args \"-profile " + FENNEC_REMOTE_PATH + "\""
|
||||
]
|
||||
|
||||
def start(self):
|
||||
@ -374,9 +378,33 @@ class XulrunnerAppRunner(mozrunner.Runner):
|
||||
self.names = runner.names
|
||||
return self.__real_binary
|
||||
|
||||
def set_overloaded_modules(env_root, app_type, addon_id, preferences, overloads):
|
||||
# win32 file scheme needs 3 slashes
|
||||
desktop_file_scheme = "file://"
|
||||
if not env_root.startswith("/"):
|
||||
desktop_file_scheme = desktop_file_scheme + "/"
|
||||
|
||||
pref_prefix = "extensions.modules." + addon_id + ".path"
|
||||
|
||||
# Set preferences that will map require prefix to a given path
|
||||
for name, path in overloads.items():
|
||||
if len(name) == 0:
|
||||
prefName = pref_prefix
|
||||
else:
|
||||
prefName = pref_prefix + "." + name
|
||||
if app_type == "fennec-on-device":
|
||||
# For testing on device, we have to copy overloaded files from fs
|
||||
# to the device and use device path instead of local fs path.
|
||||
# Actual copy of files if done after the call to Profile constructor
|
||||
preferences[prefName] = "file://" + \
|
||||
FENNEC_REMOTE_PATH + "/overloads/" + name
|
||||
else:
|
||||
preferences[prefName] = desktop_file_scheme + \
|
||||
path.replace("\\", "/") + "/"
|
||||
|
||||
def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
app_type, binary=None, profiledir=None, verbose=False,
|
||||
enforce_timeouts=False,
|
||||
parseable=False, enforce_timeouts=False,
|
||||
logfile=None, addons=None, args=None, extra_environment={},
|
||||
norun=None,
|
||||
used_files=None, enable_mobile=False,
|
||||
@ -396,22 +424,6 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
cmdargs = []
|
||||
preferences = dict(DEFAULT_COMMON_PREFS)
|
||||
|
||||
# Overload global commonjs path with lib/ folders
|
||||
file_scheme = "file://"
|
||||
# win32 file scheme needs 3 slashes
|
||||
if not env_root.startswith("/"):
|
||||
file_scheme = file_scheme + "/"
|
||||
addon_id = harness_options["jetpackID"]
|
||||
pref_prefix = "extensions.modules." + addon_id + ".path"
|
||||
if overload_modules:
|
||||
preferences[pref_prefix] = file_scheme + \
|
||||
os.path.join(env_root, "lib").replace("\\", "/") + "/"
|
||||
|
||||
# Overload tests/ mapping with test/ folder, only when running test
|
||||
if is_running_tests:
|
||||
preferences[pref_prefix + ".tests"] = file_scheme + \
|
||||
os.path.join(env_root, "test").replace("\\", "/") + "/"
|
||||
|
||||
# For now, only allow running on Mobile with --force-mobile argument
|
||||
if app_type in ["fennec", "fennec-on-device"] and not enable_mobile:
|
||||
print """
|
||||
@ -533,6 +545,18 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
addon_dir = os.path.join(mydir, "mobile-utils")
|
||||
addons.append(addon_dir)
|
||||
|
||||
# Overload addon-specific commonjs modules path with lib/ folder
|
||||
overloads = dict()
|
||||
if overload_modules:
|
||||
overloads[""] = os.path.join(env_root, "lib")
|
||||
|
||||
# Overload tests/ mapping with test/ folder, only when running test
|
||||
if is_running_tests:
|
||||
overloads["tests"] = os.path.join(env_root, "test")
|
||||
|
||||
set_overloaded_modules(env_root, app_type, harness_options["jetpackID"], \
|
||||
preferences, overloads)
|
||||
|
||||
# the XPI file is copied into the profile here
|
||||
profile = profile_class(addons=addons,
|
||||
profile=profiledir,
|
||||
@ -541,6 +565,17 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
# Delete the temporary xpi file
|
||||
os.remove(xpi_path)
|
||||
|
||||
# Copy overloaded files registered in set_overloaded_modules
|
||||
# For testing on device, we have to copy overloaded files from fs
|
||||
# to the device and use device path instead of local fs path.
|
||||
# (has to be done after the call to profile_class() which eventualy creates
|
||||
# profile folder)
|
||||
if app_type == "fennec-on-device":
|
||||
profile_path = profile.profile
|
||||
for name, path in overloads.items():
|
||||
shutil.copytree(path, \
|
||||
os.path.join(profile_path, "overloads", name))
|
||||
|
||||
runner = runner_class(profile=profile,
|
||||
binary=binary,
|
||||
env=env,
|
||||
@ -672,6 +707,14 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
|
||||
done = False
|
||||
result = None
|
||||
test_name = "unknown"
|
||||
|
||||
def Timeout(message, test_name, parseable):
|
||||
if parseable:
|
||||
sys.stderr.write("TEST-UNEXPECTED-FAIL | %s | %s\n" % (test_name, message))
|
||||
sys.stderr.flush()
|
||||
return Exception(message)
|
||||
|
||||
try:
|
||||
while not done:
|
||||
time.sleep(0.05)
|
||||
@ -682,6 +725,10 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
last_output_time = time.time()
|
||||
sys.stderr.write(new_chars)
|
||||
sys.stderr.flush()
|
||||
if is_running_tests and parseable:
|
||||
match = PARSEABLE_TEST_NAME.search(new_chars)
|
||||
if match:
|
||||
test_name = match.group(1)
|
||||
if os.path.exists(resultfile):
|
||||
result = open(resultfile).read()
|
||||
if result:
|
||||
@ -692,11 +739,11 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
sys.stderr.write("'"+result+"'\n")
|
||||
if enforce_timeouts:
|
||||
if time.time() - last_output_time > OUTPUT_TIMEOUT:
|
||||
raise Exception("Test output exceeded timeout (%ds)." %
|
||||
OUTPUT_TIMEOUT)
|
||||
raise Timeout("Test output exceeded timeout (%ds)." %
|
||||
OUTPUT_TIMEOUT, test_name, parseable)
|
||||
if time.time() - starttime > RUN_TIMEOUT:
|
||||
raise Exception("Test run exceeded timeout (%ds)." %
|
||||
RUN_TIMEOUT)
|
||||
raise Timeout("Test run exceeded timeout (%ds)." %
|
||||
RUN_TIMEOUT, test_name, parseable)
|
||||
except:
|
||||
runner.stop()
|
||||
raise
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#Template used by test-main.js
|
||||
TEST_MAIN_JS = '''\
|
||||
var main = require("main");
|
||||
var main = require("./main");
|
||||
|
||||
exports["test main"] = function(assert) {
|
||||
assert.pass("Unit test running!");
|
||||
@ -15,7 +15,7 @@ exports["test main async"] = function(assert, done) {
|
||||
done();
|
||||
};
|
||||
|
||||
require("test").run(exports);
|
||||
require("sdk/test").run(exports);
|
||||
'''
|
||||
|
||||
#Template used by package.json
|
||||
|
0
addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
Normal file → Executable file
@ -11,6 +11,7 @@ const { isPrivate } = require('sdk/private-browsing');
|
||||
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
|
||||
const { is } = require('sdk/system/xul-app');
|
||||
const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
const { merge } = require('sdk/util/object');
|
||||
|
||||
const TAB_URL = 'data:text/html;charset=utf-8,TEST-TAB';
|
||||
|
||||
@ -39,13 +40,13 @@ exports.testGetOwnerWindow = function(assert, done) {
|
||||
else {
|
||||
if (isWindowPBSupported) {
|
||||
assert.notStrictEqual(chromeWindow,
|
||||
getOwnerWindow(tab),
|
||||
'associated window is not the same for window and window\'s tab');
|
||||
getOwnerWindow(tab),
|
||||
'associated window is not the same for window and window\'s tab');
|
||||
}
|
||||
else {
|
||||
assert.strictEqual(chromeWindow,
|
||||
getOwnerWindow(tab),
|
||||
'associated window is the same for window and window\'s tab');
|
||||
getOwnerWindow(tab),
|
||||
'associated window is the same for window and window\'s tab');
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,4 +164,7 @@ if (!is('Fennec')) {
|
||||
}
|
||||
}
|
||||
|
||||
merge(module.exports, require('./windows'));
|
||||
merge(module.exports, require('./tabs'));
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
|
@ -8,6 +8,7 @@ const {Cc,Ci} = require("chrome");
|
||||
const timer = require("sdk/timers");
|
||||
const xulApp = require("sdk/system/xul-app");
|
||||
const { Loader } = require("sdk/test/loader");
|
||||
const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
|
||||
|
||||
/**
|
||||
* A helper function that creates a PageMod, then opens the specified URL
|
||||
@ -40,10 +41,10 @@ exports.testPageMod = function testPageMod(test, testURL, pageModOptions,
|
||||
|
||||
var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)];
|
||||
|
||||
var tabBrowser = browserWindow.gBrowser;
|
||||
var newTab = tabBrowser.addTab(testURL);
|
||||
tabBrowser.selectedTab = newTab;
|
||||
var b = tabBrowser.getBrowserForTab(newTab);
|
||||
let newTab = openTab(browserWindow, testURL, {
|
||||
inBackground: false
|
||||
});
|
||||
var b = getBrowserForTab(newTab);
|
||||
|
||||
function onPageLoad() {
|
||||
b.removeEventListener("load", onPageLoad, true);
|
||||
@ -56,7 +57,7 @@ exports.testPageMod = function testPageMod(test, testURL, pageModOptions,
|
||||
function done() {
|
||||
pageMods.forEach(function(mod) mod.destroy());
|
||||
// XXX leaks reported if we don't close the tab?
|
||||
tabBrowser.removeTab(newTab);
|
||||
closeTab(newTab);
|
||||
loader.unload();
|
||||
test.done();
|
||||
}
|
||||
|
@ -3,9 +3,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict';
|
||||
|
||||
let { Cc, Ci } = require("chrome");
|
||||
const timer = require("sdk/timers");
|
||||
const { LoaderWithHookedConsole, pb, pbUtils, activate, deactivate } = require("./helper");
|
||||
const { LoaderWithHookedConsole, deactivate, pb, pbUtils } = require("./helper");
|
||||
const tabs = require("sdk/tabs");
|
||||
|
||||
exports["test activate private mode via handler"] = function(test) {
|
||||
@ -176,7 +175,7 @@ exports.testAutomaticUnload = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
// Create another private browsing instance and unload it
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, errors } = LoaderWithHookedConsole(module);
|
||||
let pb2 = loader.require("sdk/private-browsing");
|
||||
let called = false;
|
||||
pb2.on("start", function onStart() {
|
||||
@ -192,7 +191,10 @@ exports.testAutomaticUnload = function(test) {
|
||||
test.assert(!called,
|
||||
"First private browsing instance is destroyed and inactive");
|
||||
// Must reset to normal mode, so that next test starts with it.
|
||||
deactivate(function() test.done());
|
||||
deactivate(function() {
|
||||
test.assert(errors.length, 0, "should have been 1 deprecation error");
|
||||
test.done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
|
||||
@ -203,7 +205,7 @@ exports.testUnloadWhileActive = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let called = false;
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, errors } = LoaderWithHookedConsole(module);
|
||||
let pb2 = loader.require("sdk/private-browsing");
|
||||
let ul = loader.require("sdk/system/unload");
|
||||
|
||||
@ -223,7 +225,8 @@ exports.testUnloadWhileActive = function(test) {
|
||||
test.fail("stop should not have been fired");
|
||||
});
|
||||
pb.once("stop", function() {
|
||||
test.assert(!called, "stop was not called on unload")
|
||||
test.assert(!called, "stop was not called on unload");
|
||||
test.assert(errors.length, 2, "should have been 2 deprecation errors");
|
||||
test.done();
|
||||
});
|
||||
|
||||
|
@ -3,32 +3,30 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict';
|
||||
|
||||
let { Cc,Ci } = require('chrome');
|
||||
const unload = require("sdk/system/unload");
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { windows: windowsIterator } = require("sdk/window/utils");
|
||||
const windows = require("sdk/windows").browserWindows;
|
||||
|
||||
let { loader } = LoaderWithHookedConsole();
|
||||
const { loader } = LoaderWithHookedConsole(module);
|
||||
|
||||
const pb = loader.require('sdk/private-browsing');
|
||||
const pbUtils = loader.require('sdk/private-browsing/utils');
|
||||
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
|
||||
|
||||
require('sdk/tabs/utils');
|
||||
require('sdk/windows');
|
||||
|
||||
function LoaderWithHookedConsole() {
|
||||
function LoaderWithHookedConsole(module) {
|
||||
let globals = {};
|
||||
let errors = [];
|
||||
let loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
error: { value: function(e) {
|
||||
|
||||
globals.console = Object.create(console, {
|
||||
error: {
|
||||
value: function(e) {
|
||||
errors.push(e);
|
||||
if (!/DEPRECATED:/.test(e)) {
|
||||
console.error(e);
|
||||
}
|
||||
}}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let loader = Loader(module, globals);
|
||||
|
||||
return {
|
||||
loader: loader,
|
||||
errors: errors
|
||||
@ -44,8 +42,6 @@ function deactivate(callback) {
|
||||
}
|
||||
exports.deactivate = deactivate;
|
||||
|
||||
exports.loader = loader;
|
||||
exports.pb = pb;
|
||||
exports.pbUtils = pbUtils;
|
||||
exports.getOwnerWindow = getOwnerWindow;
|
||||
exports.LoaderWithHookedConsole = LoaderWithHookedConsole;
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const { Ci } = require('chrome');
|
||||
const { pb, pbUtils, loader: pbLoader, getOwnerWindow } = require('./helper');
|
||||
const { openTab, closeTab } = require('sdk/tabs/utils');
|
||||
const browserWindows = require('sdk/windows');
|
||||
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
|
||||
|
||||
exports.testIsPrivateOnTab = function(test) {
|
||||
const { openTab, closeTab } = pbLoader.require('sdk/tabs/utils');
|
||||
|
||||
let window = pbLoader.require('sdk/windows').browserWindows.activeWindow;
|
||||
let chromeWindow = pbLoader.require('sdk/private-browsing/window/utils').getOwnerWindow(window);
|
||||
let window = browserWindows.activeWindow;
|
||||
let chromeWindow = getOwnerWindow(window);
|
||||
test.assert(chromeWindow instanceof Ci.nsIDOMWindow, 'associated window is found');
|
||||
test.assert(!pb.isPrivate(chromeWindow), 'the top level window is not private');
|
||||
|
||||
|
@ -4,30 +4,53 @@
|
||||
'use strict';
|
||||
|
||||
const { pb, pbUtils } = require('./helper');
|
||||
const { openDialog } = require('sdk/window/utils');
|
||||
const { openDialog, open } = require('sdk/window/utils');
|
||||
const { promise, close } = require('sdk/window/helpers');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { browserWindows: windows } = require('sdk/windows');
|
||||
|
||||
// test openDialog() from window/utils with private option
|
||||
// test isActive state in pwpb case
|
||||
// test isPrivate on ChromeWindow
|
||||
exports.testPerWindowPrivateBrowsingGetter = function(assert, done) {
|
||||
let win = openDialog({
|
||||
private: true
|
||||
});
|
||||
|
||||
win.addEventListener('DOMContentLoaded', function onload() {
|
||||
win.removeEventListener('DOMContentLoaded', onload, false);
|
||||
|
||||
promise(win, 'DOMContentLoaded').then(function onload() {
|
||||
assert.equal(pbUtils.getMode(win),
|
||||
true, 'Newly opened window is in PB mode');
|
||||
assert.ok(isPrivate(win), 'isPrivate(window) is true');
|
||||
assert.equal(pb.isActive, false, 'PB mode is not active');
|
||||
|
||||
win.addEventListener("unload", function onunload() {
|
||||
win.removeEventListener('unload', onload, false);
|
||||
close(win).then(function() {
|
||||
assert.equal(pb.isActive, false, 'PB mode is not active');
|
||||
done();
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
win.close();
|
||||
}, false);
|
||||
// test open() from window/utils with private feature
|
||||
// test isActive state in pwpb case
|
||||
// test isPrivate on ChromeWindow
|
||||
exports.testPerWindowPrivateBrowsingGetter = function(assert, done) {
|
||||
let win = open('chrome://browser/content/browser.xul', {
|
||||
features: {
|
||||
private: true
|
||||
}
|
||||
});
|
||||
|
||||
promise(win, 'DOMContentLoaded').then(function onload() {
|
||||
assert.equal(pbUtils.getMode(win),
|
||||
true, 'Newly opened window is in PB mode');
|
||||
assert.ok(isPrivate(win), 'isPrivate(window) is true');
|
||||
assert.equal(pb.isActive, false, 'PB mode is not active');
|
||||
|
||||
close(win).then(function() {
|
||||
assert.equal(pb.isActive, false, 'PB mode is not active');
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.testIsPrivateOnWindowOn = function(assert, done) {
|
||||
|
@ -4,30 +4,20 @@
|
||||
'use strict';
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { Loader, LoaderWithHookedConsole } = require('sdk/test/loader');
|
||||
const timer = require('sdk/timers');
|
||||
const tabs = require('sdk/tabs');
|
||||
const windows = require('sdk/windows');
|
||||
|
||||
const tabsLen = tabs.length;
|
||||
const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
|
||||
const ERR_MSG = 'Error: This method is not yet supported by Fennec';
|
||||
|
||||
function LoaderWithHookedConsole() {
|
||||
let errors = [];
|
||||
let loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
error: { value: function(error) {
|
||||
errors.push(error);
|
||||
}}
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
loader: loader,
|
||||
errors: errors
|
||||
}
|
||||
}
|
||||
// Fennec error message dispatched on all currently unimplement tab features,
|
||||
// that match LoaderWithHookedConsole messages object pattern
|
||||
const ERR_FENNEC_MSG = {
|
||||
type: "error",
|
||||
msg: "This method is not yet supported by Fennec"
|
||||
};
|
||||
|
||||
// TEST: tab unloader
|
||||
exports.testAutomaticDestroy = function(test) {
|
||||
@ -109,7 +99,7 @@ exports.testAutomaticDestroy = function(test) {
|
||||
// TEST: tab properties
|
||||
exports.testTabProperties = function(test) {
|
||||
test.waitUntilDone();
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole();
|
||||
let tabs = loader.require('sdk/tabs');
|
||||
|
||||
let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
|
||||
@ -121,7 +111,10 @@ exports.testTabProperties = function(test) {
|
||||
test.assertEqual(tab.url, url, "URL of the new tab matches");
|
||||
test.assert(tab.favicon, "favicon of the new tab is not empty");
|
||||
// TODO: remove need for this test by implementing the favicon feature
|
||||
test.assertEqual(errors.length, 1, "favicon logs an error for now");
|
||||
// Poors man deepEqual with JSON.stringify...
|
||||
test.assertEqual(JSON.stringify(messages),
|
||||
JSON.stringify([ERR_FENNEC_MSG]),
|
||||
"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");
|
||||
@ -230,7 +223,7 @@ exports.testTabReload = function(test) {
|
||||
exports.testTabMove = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole();
|
||||
let tabs = loader.require('sdk/tabs');
|
||||
|
||||
let url = "data:text/html;charset=utf-8,testTabMove";
|
||||
@ -247,8 +240,9 @@ exports.testTabMove = function(test) {
|
||||
test.assert(tab.index > tab1.index, "2nd tab has valid index");
|
||||
tab.index = 0;
|
||||
test.assertEqual(tab.index, i, "tab index after move matches");
|
||||
test.assertEqual(errors.length, 1, "setting tab.index logs error");
|
||||
|
||||
test.assertEqual(JSON.stringify(messages),
|
||||
JSON.stringify([ERR_FENNEC_MSG]),
|
||||
"setting tab.index logs error");
|
||||
// end test
|
||||
tab1.close(function() tab.close(function() {
|
||||
loader.unload();
|
||||
@ -264,7 +258,7 @@ exports.testTabMove = function(test) {
|
||||
exports.testTabsOpen_alt = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole();
|
||||
let tabs = loader.require('sdk/tabs');
|
||||
let url = "data:text/html;charset=utf-8,default";
|
||||
|
||||
@ -274,7 +268,7 @@ exports.testTabsOpen_alt = function(test) {
|
||||
test.assertEqual(tab.url, url, "URL of the new tab matches");
|
||||
test.assertEqual(tabs.activeTab, tab, "URL of active tab in the current window matches");
|
||||
test.assertEqual(tab.isPinned, false, "The new tab is not pinned");
|
||||
test.assertEqual(errors.length, 1, "isPinned logs error");
|
||||
test.assertEqual(messages.length, 1, "isPinned logs error");
|
||||
|
||||
// end test
|
||||
tab.close(function() {
|
||||
@ -289,7 +283,7 @@ exports.testTabsOpen_alt = function(test) {
|
||||
exports.testOpenPinned_alt = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole();
|
||||
let tabs = loader.require('sdk/tabs');
|
||||
let url = "about:blank";
|
||||
|
||||
@ -298,7 +292,11 @@ exports.testOpenPinned_alt = function(test) {
|
||||
isPinned: true,
|
||||
onOpen: function(tab) {
|
||||
test.assertEqual(tab.isPinned, false, "The new tab is pinned");
|
||||
test.assertEqual(errors.length, 2, "isPinned logs error");
|
||||
// We get two error message: one for tabs.open's isPinned argument
|
||||
// and another one for tab.isPinned
|
||||
test.assertEqual(JSON.stringify(messages),
|
||||
JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
|
||||
"isPinned logs error");
|
||||
|
||||
// end test
|
||||
tab.close(function() {
|
||||
@ -313,7 +311,7 @@ exports.testOpenPinned_alt = function(test) {
|
||||
exports.testPinUnpin_alt = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { loader, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole();
|
||||
let tabs = loader.require('sdk/tabs');
|
||||
let url = "data:text/html;charset=utf-8,default";
|
||||
|
||||
@ -322,11 +320,18 @@ exports.testPinUnpin_alt = function(test) {
|
||||
onOpen: function(tab) {
|
||||
tab.pin();
|
||||
test.assertEqual(tab.isPinned, false, "The tab was pinned correctly");
|
||||
test.assertEqual(errors.length, 2, "tab.pin() logs error");
|
||||
test.assertEqual(JSON.stringify(messages),
|
||||
JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
|
||||
"tab.pin() logs error");
|
||||
|
||||
// Clear console messages for the following test
|
||||
messages.length = 0;
|
||||
|
||||
tab.unpin();
|
||||
test.assertEqual(tab.isPinned, false, "The tab was unpinned correctly");
|
||||
test.assertEqual(errors.length, 4, "tab.unpin() logs error");
|
||||
test.assertEqual(JSON.stringify(messages),
|
||||
JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
|
||||
"tab.unpin() logs error");
|
||||
|
||||
// end test
|
||||
tab.close(function() {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { setTimeout } = require("sdk/timers");
|
||||
const { Loader, Require, override } = require("sdk/test/loader");
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
const { Worker } = require("sdk/content/worker");
|
||||
|
||||
const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo";
|
||||
@ -348,24 +348,12 @@ exports["test:nothing is leaked to content script"] = WorkerTest(
|
||||
exports["test:ensure console.xxx works in cs"] = WorkerTest(
|
||||
DEFAULT_CONTENT_URL,
|
||||
function(assert, browser, done) {
|
||||
|
||||
// Create a new module loader in order to be able to create a `console`
|
||||
// module mockup:
|
||||
let loader = Loader(module, {
|
||||
console: {
|
||||
log: hook.bind("log"),
|
||||
info: hook.bind("info"),
|
||||
warn: hook.bind("warn"),
|
||||
error: hook.bind("error"),
|
||||
debug: hook.bind("debug"),
|
||||
exception: hook.bind("exception")
|
||||
}
|
||||
});
|
||||
let { loader } = LoaderWithHookedConsole(module, onMessage);
|
||||
|
||||
// Intercept all console method calls
|
||||
let calls = [];
|
||||
function hook(msg) {
|
||||
assert.equal(this, msg,
|
||||
function onMessage(type, msg) {
|
||||
assert.equal(type, msg,
|
||||
"console.xxx(\"xxx\"), i.e. message is equal to the " +
|
||||
"console method name we are calling");
|
||||
calls.push(msg);
|
||||
@ -657,22 +645,11 @@ exports["test:check worker API with page history"] = WorkerTest(
|
||||
exports["test:global postMessage"] = WorkerTest(
|
||||
DEFAULT_CONTENT_URL,
|
||||
function(assert, browser, done) {
|
||||
// Create a new module loader in order to be able to create a `console`
|
||||
// module mockup:
|
||||
let loader = Loader(module, {
|
||||
console: {
|
||||
log: hook.bind(null, "log"),
|
||||
info: hook.bind(null, "info"),
|
||||
warn: hook.bind(null, "warn"),
|
||||
error: hook.bind(null, "error"),
|
||||
debug: hook.bind(null, "debug"),
|
||||
exception: hook.bind(null, "exception")
|
||||
}
|
||||
});
|
||||
let { loader } = LoaderWithHookedConsole(module, onMessage);
|
||||
|
||||
// Intercept all console method calls
|
||||
let seenMessages = 0;
|
||||
function hook(type, message) {
|
||||
function onMessage(type, message) {
|
||||
seenMessages++;
|
||||
assert.equal(type, "error", "Should be an error");
|
||||
assert.equal(message, "DEPRECATED: The global `postMessage()` function in " +
|
||||
|
@ -3,27 +3,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const deprecate = require("sdk/util/deprecate");
|
||||
var { Loader } = require("sdk/test/loader");
|
||||
|
||||
function LoaderWithHookedConsole() {
|
||||
let errors = [];
|
||||
let loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
error: { value: function(error) {
|
||||
errors.push(error);
|
||||
}}
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
loader: loader,
|
||||
deprecate: loader.require("sdk/util/deprecate"),
|
||||
errors: errors
|
||||
}
|
||||
}
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
|
||||
exports["test Deprecate Usage"] = function testDeprecateUsage(assert) {
|
||||
let { loader, deprecate, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
let deprecate = loader.require("sdk/util/deprecate");
|
||||
|
||||
function functionIsDeprecated() {
|
||||
deprecate.deprecateUsage("foo");
|
||||
@ -31,9 +15,10 @@ exports["test Deprecate Usage"] = function testDeprecateUsage(assert) {
|
||||
|
||||
functionIsDeprecated();
|
||||
|
||||
assert.equal(errors.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages[0].type, "error", "the console message is an error");
|
||||
|
||||
let msg = errors[0];
|
||||
let msg = messages[0].msg;
|
||||
|
||||
assert.ok(msg.indexOf("foo") !== -1,
|
||||
"message contains the given message");
|
||||
@ -46,7 +31,8 @@ exports["test Deprecate Usage"] = function testDeprecateUsage(assert) {
|
||||
}
|
||||
|
||||
exports["test Deprecate Function"] = function testDeprecateFunction(assert) {
|
||||
let { loader, deprecate, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
let deprecate = loader.require("sdk/util/deprecate");
|
||||
|
||||
let self = {};
|
||||
let arg1 = "foo";
|
||||
@ -63,10 +49,10 @@ exports["test Deprecate Function"] = function testDeprecateFunction(assert) {
|
||||
|
||||
deprecateFunction.call(self, arg1, arg2);
|
||||
|
||||
assert.equal(errors.length, 1,
|
||||
"only one error is dispatched");
|
||||
assert.equal(messages.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages[0].type, "error", "the console message is an error");
|
||||
|
||||
let msg = errors[0];
|
||||
let msg = messages[0].msg;
|
||||
assert.ok(msg.indexOf("bar") !== -1, "message contains the given message");
|
||||
assert.ok(msg.indexOf("testDeprecateFunction") !== -1,
|
||||
"message contains name of the caller function");
|
||||
@ -77,7 +63,8 @@ exports["test Deprecate Function"] = function testDeprecateFunction(assert) {
|
||||
}
|
||||
|
||||
exports.testDeprecateEvent = function(assert, done) {
|
||||
let { loader, deprecate, errors } = LoaderWithHookedConsole();
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
let deprecate = loader.require("sdk/util/deprecate");
|
||||
|
||||
let { on, emit } = loader.require('sdk/event/core');
|
||||
let testObj = {};
|
||||
@ -85,15 +72,16 @@ exports.testDeprecateEvent = function(assert, done) {
|
||||
|
||||
testObj.on('fire', function() {
|
||||
testObj.on('water', function() {
|
||||
assert.equal(errors.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages.length, 1, "only one error is dispatched");
|
||||
loader.unload();
|
||||
done();
|
||||
})
|
||||
assert.equal(errors.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages.length, 1, "only one error is dispatched");
|
||||
emit(testObj, 'water');
|
||||
});
|
||||
assert.equal(errors.length, 1, "only one error is dispatched");
|
||||
let msg = errors[0];
|
||||
assert.equal(messages.length, 1, "only one error is dispatched");
|
||||
assert.equal(messages[0].type, "error", "the console message is an error");
|
||||
let msg = messages[0].msg;
|
||||
assert.ok(msg.indexOf("BAD") !== -1, "message contains the given message");
|
||||
assert.ok(msg.indexOf("deprecateEvent") !== -1,
|
||||
"message contains name of the caller function");
|
||||
|
@ -5,7 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
const { on, once, off, emit, count, amass } = require('sdk/event/core');
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
|
||||
exports['test add a listener'] = function(assert) {
|
||||
let events = [ { name: 'event#1' }, 'event#2' ];
|
||||
@ -159,13 +159,8 @@ exports['test error handling'] = function(assert) {
|
||||
|
||||
exports['test unhandled errors'] = function(assert) {
|
||||
let exceptions = [];
|
||||
let loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
exception: { value: function(e) {
|
||||
exceptions.push(e);
|
||||
}}
|
||||
})
|
||||
});
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
|
||||
let { emit, on } = loader.require('sdk/event/core');
|
||||
let target = {};
|
||||
let boom = Error('Boom!');
|
||||
@ -174,12 +169,16 @@ exports['test unhandled errors'] = function(assert) {
|
||||
on(target, 'message', function() { throw boom; });
|
||||
|
||||
emit(target, 'message');
|
||||
assert.ok(~String(exceptions[0]).indexOf('Boom!'),
|
||||
assert.equal(messages.length, 1, 'Got the first exception');
|
||||
assert.equal(messages[0].type, 'exception', 'The console message is exception');
|
||||
assert.ok(~String(messages[0].msg).indexOf('Boom!'),
|
||||
'unhandled exception is logged');
|
||||
|
||||
on(target, 'error', function() { throw drax; });
|
||||
emit(target, 'message');
|
||||
assert.ok(~String(exceptions[1]).indexOf('Draax!'),
|
||||
assert.equal(messages.length, 2, 'Got the second exception');
|
||||
assert.equal(messages[1].type, 'exception', 'The console message is exception');
|
||||
assert.ok(~String(messages[1].msg).indexOf('Draax!'),
|
||||
'error in error handler is logged');
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
|
||||
// Exposing private methods as public in order to test
|
||||
const EventEmitter = require('sdk/deprecated/events').EventEmitter.compose({
|
||||
@ -256,11 +256,7 @@ exports["test:removing once"] = function(test) {
|
||||
exports['test:emitLoop'] = function(test) {
|
||||
// Override the console for this test so it doesn't log the exception to the
|
||||
// test output
|
||||
let loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
exception: { value: function(e) { }}
|
||||
})
|
||||
});
|
||||
let { loader } = LoaderWithHookedConsole(module);
|
||||
|
||||
let EventEmitter = loader.require('sdk/deprecated/events').EventEmitter.compose({
|
||||
listeners: function(type) this._listeners(type),
|
||||
|
@ -4,16 +4,10 @@
|
||||
|
||||
const observers = require("sdk/deprecated/observer-service");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { Loader } = require("sdk/test/loader");
|
||||
const { PlainTextConsole } = require("sdk/console/plain-text");
|
||||
const { LoaderWithHookedConsole2 } = require("sdk/test/loader");
|
||||
|
||||
exports.testUnloadAndErrorLogging = function(test) {
|
||||
var prints = [];
|
||||
var loader = Loader(module, {
|
||||
console: new PlainTextConsole(function(_) {
|
||||
prints.push(_);
|
||||
})
|
||||
});
|
||||
let { loader, messages } = LoaderWithHookedConsole2(module);
|
||||
var sbobsvc = loader.require("sdk/deprecated/observer-service");
|
||||
|
||||
var timesCalled = 0;
|
||||
@ -28,10 +22,12 @@ exports.testUnloadAndErrorLogging = function(test) {
|
||||
test.assertEqual(timesCalled, 1);
|
||||
sbobsvc.add("narg", badCb);
|
||||
observers.notify("narg", "yo yo");
|
||||
var lines = prints[0].split("\n");
|
||||
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(lines[2], module.uri + " 24");
|
||||
// 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):");
|
||||
|
||||
loader.unload();
|
||||
|
@ -3,8 +3,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var pageMod = require("sdk/page-mod");
|
||||
var testPageMod = require("./pagemod-test-helpers").testPageMod;
|
||||
const pageMod = require("sdk/page-mod");
|
||||
const testPageMod = require("./pagemod-test-helpers").testPageMod;
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const tabs = require("sdk/tabs");
|
||||
const timer = require("sdk/timers");
|
||||
@ -12,6 +12,7 @@ const { Cc, Ci } = require("chrome");
|
||||
const { open, getFrames, getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const windowUtils = require('sdk/deprecated/window-utils');
|
||||
const { getTabContentWindow, getActiveTab, openTab, closeTab } = require('sdk/tabs/utils');
|
||||
const { is } = require('sdk/system/xul-app');
|
||||
const { data } = require('sdk/self');
|
||||
|
||||
/* XXX This can be used to delay closing the test Firefox instance for interactive
|
||||
@ -21,8 +22,10 @@ exports.delay = function(test) {
|
||||
if (false) {
|
||||
test.waitUntilDone(60000);
|
||||
timer.setTimeout(function() {test.done();}, 4000);
|
||||
} else
|
||||
}
|
||||
else {
|
||||
test.pass();
|
||||
}
|
||||
}
|
||||
|
||||
function Isolate(worker) {
|
||||
@ -384,11 +387,12 @@ exports.testRelatedTabNoOtherReqs = function(test) {
|
||||
let loader = Loader(module);
|
||||
let { PageMod } = loader.require("sdk/page-mod");
|
||||
let pageMod = new PageMod({
|
||||
include: "about:*",
|
||||
include: "about:blank?testRelatedTabNoOtherReqs",
|
||||
onAttach: function(worker) {
|
||||
test.assert(!!worker.tab, "Worker.tab exists");
|
||||
pageMod.destroy();
|
||||
worker.tab.close(function() {
|
||||
worker.destroy();
|
||||
loader.unload();
|
||||
test.done();
|
||||
});
|
||||
@ -396,7 +400,7 @@ exports.testRelatedTabNoOtherReqs = function(test) {
|
||||
});
|
||||
|
||||
tabs.open({
|
||||
url: "about:"
|
||||
url: "about:blank?testRelatedTabNoOtherReqs"
|
||||
});
|
||||
};
|
||||
|
||||
@ -434,7 +438,7 @@ exports.testWorksWithExistingTabs = function(test) {
|
||||
});
|
||||
};
|
||||
|
||||
exports['test tab worker on message'] = function(test) {
|
||||
exports.testTabWorkerOnMessage = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { browserWindows } = require("sdk/windows");
|
||||
@ -506,7 +510,7 @@ exports.testAutomaticDestroy = function(test) {
|
||||
|
||||
}
|
||||
|
||||
exports['test attachment to tabs only'] = function(test) {
|
||||
exports.testAttachToTabsOnly = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let { PageMod } = require('sdk/page-mod');
|
||||
@ -543,7 +547,13 @@ exports['test attachment to tabs only'] = function(test) {
|
||||
element.addEventListener('DOMContentLoaded', function onload() {
|
||||
element.removeEventListener('DOMContentLoaded', onload, false);
|
||||
hiddenFrames.remove(hiddenFrame);
|
||||
openToplevelWindow();
|
||||
|
||||
if (!is("Fennec")) {
|
||||
openToplevelWindow();
|
||||
}
|
||||
else {
|
||||
openBrowserIframe();
|
||||
}
|
||||
}, false);
|
||||
element.setAttribute('src', 'data:text/html;charset=utf-8,foo');
|
||||
}
|
||||
@ -579,7 +589,7 @@ exports['test attachment to tabs only'] = function(test) {
|
||||
function openTabWithIframes() {
|
||||
console.info('Open iframes in a tab');
|
||||
let subContent = '<iframe src="data:text/html;charset=utf-8,sub frame" />'
|
||||
let content = '<iframe src="data:text/html,' +
|
||||
let content = '<iframe src="data:text/html;charset=utf-8,' +
|
||||
encodeURIComponent(subContent) + '" />';
|
||||
require('sdk/tabs').open({
|
||||
url: 'data:text/html;charset=utf-8,' + encodeURIComponent(content),
|
||||
@ -825,8 +835,8 @@ exports.testPageModCssAutomaticDestroy = function(test) {
|
||||
let browserWindow = windowUtils.activeBrowserWindow;
|
||||
let win = getTabContentWindow(getActiveTab(browserWindow));
|
||||
|
||||
let div = win.document.querySelector("div"),
|
||||
style = win.getComputedStyle(div);
|
||||
let div = win.document.querySelector("div");
|
||||
let style = win.getComputedStyle(div);
|
||||
|
||||
test.assertEqual(
|
||||
style.width,
|
||||
@ -995,14 +1005,16 @@ exports.testExistingOnFrames = function(test) {
|
||||
|
||||
exports.testIFramePostMessage = function(test) {
|
||||
test.waitUntilDone();
|
||||
let count = 0;
|
||||
|
||||
tabs.open({
|
||||
url: data.url("test-iframe.html"),
|
||||
onReady: function(tab) {
|
||||
var worker = tab.attach({
|
||||
contentScriptFile: data.url('test-iframe.js'),
|
||||
contentScript: ' var iframePath = \'' + data.url('test-iframe-postmessage.html') + '\'',
|
||||
contentScript: 'var iframePath = \'' + data.url('test-iframe-postmessage.html') + '\'',
|
||||
onMessage: function(msg) {
|
||||
test.assertEqual(++count, 1);
|
||||
test.assertEqual(msg.first, 'a string');
|
||||
test.assert(msg.second[1], "array");
|
||||
test.assertEqual(typeof msg.third, 'object');
|
||||
@ -1039,14 +1051,3 @@ exports.testEvents = function(test) {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (require("sdk/system/xul-app").is("Fennec")) {
|
||||
|
||||
module.exports = {
|
||||
"test Unsupported Test": function UnsupportedTest (test) {
|
||||
test.pass(
|
||||
"Skipping this test until Fennec support is implemented." +
|
||||
"See bug 784224");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
let { Cc, Ci } = require("chrome");
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
const timer = require("sdk/timers");
|
||||
const self = require('sdk/self');
|
||||
|
||||
@ -492,26 +493,21 @@ exports["test console.log in Panel"] = function(assert, done) {
|
||||
console.log("' + text + '");\
|
||||
}</script>';
|
||||
|
||||
let panel;
|
||||
|
||||
let loader = Loader(module, {
|
||||
console: {
|
||||
log: function (message) {
|
||||
assert.equal(message, text, 'console.log() works');
|
||||
|
||||
panel.destroy();
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let { loader } = LoaderWithHookedConsole(module, onMessage);
|
||||
let { Panel } = loader.require('sdk/panel');
|
||||
|
||||
panel = Panel({
|
||||
let panel = Panel({
|
||||
contentURL: 'data:text/html;charset=utf-8,' + encodeURIComponent(html)
|
||||
});
|
||||
|
||||
panel.show();
|
||||
|
||||
function onMessage(type, message) {
|
||||
assert.equal(type, 'log', 'console.log() works');
|
||||
assert.equal(message, text, 'console.log() works');
|
||||
panel.destroy();
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -4,24 +4,29 @@
|
||||
'use strict';
|
||||
|
||||
const { Ci } = require('chrome');
|
||||
const { pb, pbUtils, getOwnerWindow } = require('./private-browsing/helper');
|
||||
const { merge } = require('sdk/util/object');
|
||||
const windows = require('sdk/windows').browserWindows;
|
||||
const tabs = require('sdk/tabs');
|
||||
const winUtils = require('sdk/window/utils');
|
||||
const { isWindowPrivate } = winUtils;
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const { is } = require('sdk/system/xul-app');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
|
||||
const { LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
const { getMode, isGlobalPBSupported,
|
||||
isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
const { pb } = require('./private-browsing/helper');
|
||||
|
||||
// is global pb is enabled?
|
||||
if (pbUtils.isGlobalPBSupported) {
|
||||
if (isGlobalPBSupported) {
|
||||
merge(module.exports, require('./private-browsing/global'));
|
||||
|
||||
exports.testGlobalOnlyOnFirefox = function(test) {
|
||||
test.assert(is("Firefox"), "isGlobalPBSupported is only true on Firefox");
|
||||
}
|
||||
}
|
||||
else if (pbUtils.isWindowPBSupported) {
|
||||
else if (isWindowPBSupported) {
|
||||
merge(module.exports, require('./private-browsing/windows'));
|
||||
|
||||
exports.testPWOnlyOnFirefox = function(test) {
|
||||
@ -29,7 +34,7 @@ else if (pbUtils.isWindowPBSupported) {
|
||||
}
|
||||
}
|
||||
// only on Fennec
|
||||
else if (pbUtils.isTabPBSupported) {
|
||||
else if (isTabPBSupported) {
|
||||
merge(module.exports, require('./private-browsing/tabs'));
|
||||
|
||||
exports.testPTOnlyOnFennec = function(test) {
|
||||
@ -38,19 +43,26 @@ else if (pbUtils.isTabPBSupported) {
|
||||
}
|
||||
|
||||
exports.testIsPrivateDefaults = function(test) {
|
||||
test.assertEqual(pb.isPrivate(), false, 'undefined is not private');
|
||||
test.assertEqual(pb.isPrivate('test'), false, 'strings are not private');
|
||||
test.assertEqual(pb.isPrivate({}), false, 'random objects are not private');
|
||||
test.assertEqual(pb.isPrivate(4), false, 'numbers are not private');
|
||||
test.assertEqual(pb.isPrivate(/abc/), false, 'regex are not private');
|
||||
test.assertEqual(pb.isPrivate(function() {}), false, 'functions are not private');
|
||||
test.assertEqual(isPrivate(), false, 'undefined is not private');
|
||||
test.assertEqual(isPrivate('test'), false, 'strings are not private');
|
||||
test.assertEqual(isPrivate({}), false, 'random objects are not private');
|
||||
test.assertEqual(isPrivate(4), false, 'numbers are not private');
|
||||
test.assertEqual(isPrivate(/abc/), false, 'regex are not private');
|
||||
test.assertEqual(isPrivate(function() {}), false, 'functions are not private');
|
||||
};
|
||||
|
||||
exports.testWindowDefaults = function(test) {
|
||||
test.assertEqual(windows.activeWindow.isPrivateBrowsing, false, 'window is not private browsing by default');
|
||||
// Ensure that browserWindow still works while being deprecated
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
let windows = loader.require("sdk/windows").browserWindows;
|
||||
test.assertEqual(windows.activeWindow.isPrivateBrowsing, false,
|
||||
'window is not private browsing by default');
|
||||
test.assertMatches(messages[0].msg, /DEPRECATED.+isPrivateBrowsing/,
|
||||
'isPrivateBrowsing is deprecated');
|
||||
|
||||
let chromeWin = winUtils.getMostRecentBrowserWindow();
|
||||
test.assertEqual(pbUtils.getMode(chromeWin), false);
|
||||
test.assertEqual(pbUtils.isWindowPrivate(chromeWin), false);
|
||||
test.assertEqual(getMode(chromeWin), false);
|
||||
test.assertEqual(isWindowPrivate(chromeWin), false);
|
||||
}
|
||||
|
||||
// tests for the case where private browsing doesn't exist
|
||||
@ -61,7 +73,7 @@ exports.testIsActiveDefault = function(test) {
|
||||
|
||||
exports.testIsPrivateBrowsingFalseDefault = function(test) {
|
||||
test.assertEqual(isPrivateBrowsingSupported, false,
|
||||
'usePrivateBrowsing property is false by default');
|
||||
'isPrivateBrowsingSupported property is false by default');
|
||||
};
|
||||
|
||||
exports.testGetOwnerWindow = function(test) {
|
||||
|
@ -6,8 +6,7 @@ const events = require("sdk/system/events");
|
||||
const self = require("sdk/self");
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { setTimeout } = require("sdk/timers");
|
||||
const { Loader } = require("sdk/test/loader");
|
||||
const { PlainTextConsole } = require("sdk/console/plain-text");
|
||||
const { LoaderWithHookedConsole2 } = require("sdk/test/loader");
|
||||
const nsIObserverService = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
@ -36,12 +35,7 @@ exports["test basic"] = function(assert) {
|
||||
}
|
||||
|
||||
exports["test error reporting"] = function(assert) {
|
||||
let prints = [];
|
||||
let loader = Loader(module, {
|
||||
console: new PlainTextConsole(function(_) {
|
||||
prints.push(_);
|
||||
})
|
||||
});
|
||||
let { loader, messages } = LoaderWithHookedConsole2(module);
|
||||
|
||||
let events = loader.require("sdk/system/events");
|
||||
function brokenHandler(subject, data) { throw new Error("foo"); };
|
||||
@ -49,18 +43,18 @@ exports["test error reporting"] = function(assert) {
|
||||
let lineNumber;
|
||||
try { brokenHandler() } catch (error) { lineNumber = error.lineNumber }
|
||||
|
||||
|
||||
|
||||
let errorType = Date.now().toString(32);
|
||||
|
||||
events.on(errorType, brokenHandler);
|
||||
events.emit(errorType, { data: "yo yo" });
|
||||
|
||||
assert.ok(prints[0].indexOf(self.name + ": An exception occurred.") >= 0,
|
||||
assert.equal(messages.length, 1, "Got an exception");
|
||||
let text = messages[0];
|
||||
assert.ok(text.indexOf(self.name + ": An exception occurred.") >= 0,
|
||||
"error is logged");
|
||||
assert.ok(prints[0].indexOf("Error: foo") >= 0, "error message is logged");
|
||||
assert.ok(prints[0].indexOf(module.uri) >= 0, "module uri is logged");
|
||||
assert.ok(prints[0].indexOf(lineNumber) >= 0, "error line is logged");
|
||||
assert.ok(text.indexOf("Error: foo") >= 0, "error message is logged");
|
||||
assert.ok(text.indexOf(module.uri) >= 0, "module uri is logged");
|
||||
assert.ok(text.indexOf(lineNumber) >= 0, "error line is logged");
|
||||
|
||||
events.off(errorType, brokenHandler);
|
||||
|
||||
|
@ -7,7 +7,9 @@ const { Loader } = require('sdk/test/loader');
|
||||
const { browserWindows } = require('sdk/windows');
|
||||
const tabs = require('sdk/tabs');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
const { openDialog } = require('sdk/window/utils');
|
||||
const pbUtils = require('sdk/private-browsing/utils');
|
||||
const { isWindowPrivate } = require('sdk/window/utils');
|
||||
|
||||
const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
|
||||
|
||||
@ -299,7 +301,7 @@ exports.testTabContentTypeAndReload = function(test) {
|
||||
});
|
||||
};
|
||||
|
||||
// test that it is possible to open a private tab
|
||||
// test that it isn't possible to open a private tab without the private permission
|
||||
exports.testTabOpenPrivate = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
@ -309,7 +311,7 @@ exports.testTabOpenPrivate = function(test) {
|
||||
isPrivate: true,
|
||||
onReady: function(tab) {
|
||||
test.assertEqual(tab.url, url, 'opened correct tab');
|
||||
test.assertEqual(isPrivate(tab), false, 'private tabs arenot supported by default');
|
||||
test.assertEqual(isPrivate(tab), false, 'private tabs are not supported by default');
|
||||
|
||||
tab.close(function() {
|
||||
test.done();
|
||||
@ -317,3 +319,36 @@ exports.testTabOpenPrivate = function(test) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We need permission flag in order to see private window's tabs
|
||||
exports.testPrivateAreNotListed = function (test) {
|
||||
test.waitUntilDone();
|
||||
let originalTabCount = tabs.length;
|
||||
|
||||
let win = openDialog({
|
||||
private: true
|
||||
});
|
||||
|
||||
win.addEventListener("load", function onload() {
|
||||
win.removeEventListener("load", onload);
|
||||
|
||||
// PWPB case
|
||||
if (pbUtils.isWindowPBSupported) {
|
||||
test.assert(isWindowPrivate(win), "window is private");
|
||||
test.assertEqual(tabs.length, originalTabCount,
|
||||
'New private window\'s tab isn\'t visible in tabs list');
|
||||
}
|
||||
else {
|
||||
// Global case, openDialog didn't opened a private window/tab
|
||||
test.assert(!isWindowPrivate(win), "window is private");
|
||||
test.assertEqual(tabs.length, originalTabCount + 1,
|
||||
'New non-private window\'s tab is visible in tabs list');
|
||||
}
|
||||
|
||||
win.addEventListener("unload", function onunload() {
|
||||
win.removeEventListener('unload', onunload);
|
||||
test.done();
|
||||
});
|
||||
win.close();
|
||||
});
|
||||
}
|
||||
|
@ -5,17 +5,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var unload = require("sdk/system/unload");
|
||||
var { Loader } = require("sdk/test/loader");
|
||||
var { Loader, LoaderWithHookedConsole } = require("sdk/test/loader");
|
||||
|
||||
exports.testUnloading = function(test) {
|
||||
var loader = Loader(module, {
|
||||
console: Object.create(console, {
|
||||
exception: { value: function(error) {
|
||||
exceptions.push(error);
|
||||
}}
|
||||
})
|
||||
});
|
||||
var exceptions = [];
|
||||
let { loader, messages } = LoaderWithHookedConsole(module);
|
||||
var ul = loader.require("sdk/system/unload");
|
||||
var unloadCalled = 0;
|
||||
function unload() {
|
||||
@ -32,8 +25,10 @@ exports.testUnloading = function(test) {
|
||||
loader.unload();
|
||||
test.assertEqual(unloadCalled, 2,
|
||||
"Unloader functions are called on unload.");
|
||||
test.assertEqual(exceptions.length, 1,
|
||||
"One unload handler threw exception");
|
||||
test.assertEqual(messages.length, 1,
|
||||
"One unload handler threw exception 1/2");
|
||||
test.assertEqual(messages[0].type, "exception",
|
||||
"One unload handler threw exception 2/2");
|
||||
};
|
||||
|
||||
exports.testEnsure = function(test) {
|
||||
|
@ -1,34 +1,34 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var windowUtils = require("sdk/deprecated/window-utils");
|
||||
var timer = require("sdk/timers");
|
||||
var { Cc, Ci } = require("chrome");
|
||||
var { Loader, unload } = require("sdk/test/loader");
|
||||
const windowUtils = require("sdk/deprecated/window-utils");
|
||||
const timer = require("sdk/timers");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { Loader } = require("sdk/test/loader");
|
||||
const { open, getFrames, getWindowTitle, onFocus } = require('sdk/window/utils');
|
||||
const { close } = require('sdk/window/helpers');
|
||||
const { fromIterator: toArray } = require('sdk/util/array');
|
||||
|
||||
function toArray(iterator) {
|
||||
let array = [];
|
||||
for each (let item in iterator)
|
||||
array.push(item);
|
||||
return array;
|
||||
}
|
||||
const WM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||
|
||||
function makeEmptyWindow() {
|
||||
function makeEmptyWindow(options) {
|
||||
options = options || {};
|
||||
var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var blankXul = ('<?xml version="1.0"?>' +
|
||||
'<?xml-stylesheet href="chrome://global/skin/" ' +
|
||||
' type="text/css"?>' +
|
||||
'<window xmlns="' + xulNs + '" windowtype="test:window">' +
|
||||
'</window>');
|
||||
var url = "data:application/vnd.mozilla.xul+xml;charset=utf-8," + escape(blankXul);
|
||||
var features = ["chrome", "width=10", "height=10"];
|
||||
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Ci.nsIWindowWatcher);
|
||||
return ww.openWindow(null, url, null, features.join(","), null);
|
||||
return open("data:application/vnd.mozilla.xul+xml;charset=utf-8," + escape(blankXul), {
|
||||
features: {
|
||||
chrome: true,
|
||||
width: 10,
|
||||
height: 10
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports['test close on unload'] = function(assert) {
|
||||
@ -83,7 +83,7 @@ exports['test close on unload'] = function(assert) {
|
||||
"window not closed again on module unload.");
|
||||
};
|
||||
|
||||
exports['test window watcher'] = function(assert, done) {
|
||||
exports.testWindowTracker = function(assert, done) {
|
||||
var myWindow;
|
||||
var finished = false;
|
||||
|
||||
@ -91,21 +91,23 @@ exports['test window watcher'] = function(assert, done) {
|
||||
onTrack: function(window) {
|
||||
if (window == myWindow) {
|
||||
assert.pass("onTrack() called with our test window");
|
||||
timer.setTimeout(function() { myWindow.close(); }, 1);
|
||||
timer.setTimeout(function() myWindow.close());
|
||||
}
|
||||
},
|
||||
onUntrack: function(window) {
|
||||
if (window == myWindow) {
|
||||
assert.pass("onUntrack() called with our test window");
|
||||
timer.setTimeout(function() {
|
||||
if (!finished) {
|
||||
finished = true;
|
||||
myWindow = null;
|
||||
wt.unload();
|
||||
done();
|
||||
} else
|
||||
assert.fail("finishTest() called multiple times.");
|
||||
}, 1);
|
||||
if (!finished) {
|
||||
finished = true;
|
||||
myWindow = null;
|
||||
wt.unload();
|
||||
done();
|
||||
}
|
||||
else {
|
||||
assert.fail("finishTest() called multiple times.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -159,9 +161,7 @@ exports['test window watcher untracker'] = function(assert, done) {
|
||||
exports['test window watcher unregs 4 loading wins'] = function(assert, done) {
|
||||
var myWindow;
|
||||
var finished = false;
|
||||
let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
.getMostRecentWindow("navigator:browser");
|
||||
let browserWindow = WM.getMostRecentWindow("navigator:browser");
|
||||
var counter = 0;
|
||||
|
||||
var delegate = {
|
||||
@ -236,9 +236,8 @@ exports['test window watcher without untracker'] = function(assert, done) {
|
||||
};
|
||||
|
||||
exports['test active window'] = function(assert, done) {
|
||||
let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
.getMostRecentWindow("navigator:browser");
|
||||
let browserWindow = WM.getMostRecentWindow("navigator:browser");
|
||||
let continueAfterFocus = function(window) onFocus(window).then(nextTest);
|
||||
|
||||
assert.equal(windowUtils.activeBrowserWindow, browserWindow,
|
||||
"Browser window is the active browser window.");
|
||||
@ -246,8 +245,7 @@ exports['test active window'] = function(assert, done) {
|
||||
|
||||
let testSteps = [
|
||||
function() {
|
||||
windowUtils.activeWindow = browserWindow;
|
||||
continueAfterFocus(browserWindow);
|
||||
continueAfterFocus(windowUtils.activeWindow = browserWindow);
|
||||
},
|
||||
function() {
|
||||
assert.equal(windowUtils.activeWindow, browserWindow,
|
||||
@ -267,49 +265,18 @@ exports['test active window'] = function(assert, done) {
|
||||
function() {
|
||||
assert.equal(windowUtils.activeBrowserWindow, browserWindow,
|
||||
"Correct active browser window [4]");
|
||||
browserWindow = null;
|
||||
done();
|
||||
}
|
||||
];
|
||||
|
||||
let nextTest = function() {
|
||||
let func = testSteps.shift();
|
||||
if (func) {
|
||||
func();
|
||||
}
|
||||
function nextTest() {
|
||||
if (testSteps.length)
|
||||
testSteps.shift()();
|
||||
}
|
||||
|
||||
function continueAfterFocus(targetWindow) {
|
||||
// Based on SimpleTest.waitForFocus
|
||||
var fm = Cc["@mozilla.org/focus-manager;1"].
|
||||
getService(Ci.nsIFocusManager);
|
||||
|
||||
var childTargetWindow = {};
|
||||
fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
|
||||
childTargetWindow = childTargetWindow.value;
|
||||
|
||||
var focusedChildWindow = {};
|
||||
if (fm.activeWindow) {
|
||||
fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
|
||||
focusedChildWindow = focusedChildWindow.value;
|
||||
}
|
||||
|
||||
var focused = (focusedChildWindow == childTargetWindow);
|
||||
if (focused) {
|
||||
nextTest();
|
||||
} else {
|
||||
childTargetWindow.addEventListener("focus", function focusListener() {
|
||||
childTargetWindow.removeEventListener("focus", focusListener, true);
|
||||
nextTest();
|
||||
}, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nextTest();
|
||||
};
|
||||
|
||||
exports['test windowIterator'] = function(assert, done) {
|
||||
exports.testWindowIterator = function(assert, done) {
|
||||
// make a new window
|
||||
let window = makeEmptyWindow();
|
||||
|
||||
@ -327,17 +294,12 @@ exports['test windowIterator'] = function(assert, done) {
|
||||
window.addEventListener("load", function onload() {
|
||||
window.addEventListener("load", onload, false);
|
||||
assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) !== -1,
|
||||
"window is now in windowIterator(false)");
|
||||
"window is now in windowIterator()");
|
||||
|
||||
// Wait for the window unload before ending test
|
||||
window.addEventListener("unload", function onunload() {
|
||||
window.addEventListener("unload", onunload, false);
|
||||
done();
|
||||
}, false);
|
||||
window.close();
|
||||
close(window).then(done);
|
||||
}, false);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (require("sdk/system/xul-app").is("Fennec")) {
|
||||
module.exports = {
|
||||
|
@ -1,12 +1,13 @@
|
||||
/* 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 { Ci } = require('chrome');
|
||||
const { open, backgroundify, windows,
|
||||
getXULWindow, getBaseWindow } = require('sdk/window/utils');
|
||||
const { open, backgroundify, windows, isBrowser,
|
||||
getXULWindow, getBaseWindow, getMostRecentWindow,
|
||||
getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { close } = require('sdk/window/helpers');
|
||||
const windowUtils = require('sdk/deprecated/window-utils');
|
||||
|
||||
exports['test get nsIBaseWindow from nsIDomWindow'] = function(assert) {
|
||||
@ -27,13 +28,15 @@ exports['test get nsIXULWindow from nsIDomWindow'] = function(assert) {
|
||||
'base returns nsIXULWindow');
|
||||
};
|
||||
|
||||
exports['test top window creation'] = function(assert) {
|
||||
exports['test top window creation'] = function(assert, done) {
|
||||
let window = open('data:text/html;charset=utf-8,Hello top window');
|
||||
assert.ok(~windows().indexOf(window), 'window was opened');
|
||||
window.close();
|
||||
|
||||
// Wait for the window unload before ending test
|
||||
close(window).then(done);
|
||||
};
|
||||
|
||||
exports['test new top window with options'] = function(assert) {
|
||||
exports['test new top window with options'] = function(assert, done) {
|
||||
let window = open('data:text/html;charset=utf-8,Hi custom top window', {
|
||||
name: 'test',
|
||||
features: { height: 100, width: 200, toolbar: true }
|
||||
@ -43,10 +46,12 @@ exports['test new top window with options'] = function(assert) {
|
||||
assert.equal(window.innerHeight, 100, 'height is set');
|
||||
assert.equal(window.innerWidth, 200, 'height is set');
|
||||
assert.equal(window.toolbar.visible, true, 'toolbar was set');
|
||||
window.close();
|
||||
|
||||
// Wait for the window unload before ending test
|
||||
close(window).then(done);
|
||||
};
|
||||
|
||||
exports['test backgroundify'] = function(assert) {
|
||||
exports.testBackgroundify = function(assert, done) {
|
||||
let window = open('data:text/html;charset=utf-8,backgroundy');
|
||||
assert.ok(~windows().indexOf(window),
|
||||
'window is in the list of windows');
|
||||
@ -54,7 +59,22 @@ exports['test backgroundify'] = function(assert) {
|
||||
assert.equal(backgroundy, window, 'backgroundify returs give window back');
|
||||
assert.ok(!~windows().indexOf(window),
|
||||
'backgroundifyied window is in the list of windows');
|
||||
window.close();
|
||||
|
||||
// Wait for the window unload before ending test
|
||||
close(window).then(done);
|
||||
};
|
||||
|
||||
exports.testIsBrowser = function(assert) {
|
||||
// dummy window, bad type
|
||||
assert.equal(isBrowser({ document: { documentElement: { getAttribute: function() {
|
||||
return 'navigator:browserx';
|
||||
}}}}), false, 'dummy object with correct stucture and bad type does not pass');
|
||||
|
||||
assert.ok(isBrowser(getMostRecentBrowserWindow()), 'active browser window is a browser window');
|
||||
assert.ok(!isBrowser({}), 'non window is not a browser window');
|
||||
assert.ok(!isBrowser({ document: {} }), 'non window is not a browser window');
|
||||
assert.ok(!isBrowser({ document: { documentElement: {} } }), 'non window is not a browser window');
|
||||
assert.ok(!isBrowser(), 'no argument is not a browser window');
|
||||
};
|
||||
|
||||
require('test').run(exports);
|
||||
|
@ -6,12 +6,12 @@
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { setTimeout } = require('sdk/timers');
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const wm = Cc['@mozilla.org/appshell/window-mediator;1'].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
|
||||
const { onFocus, getMostRecentWindow, windows } = require('sdk/window/utils');
|
||||
const { open, close, focus } = require('sdk/window/helpers');
|
||||
const { browserWindows } = require("sdk/windows");
|
||||
const tabs = require("sdk/tabs");
|
||||
const { WindowTracker } = require("sdk/deprecated/window-utils");
|
||||
const winUtils = require("sdk/deprecated/window-utils");
|
||||
const { WindowTracker } = winUtils;
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { isWindowPBSupported } = require('sdk/private-browsing/utils');
|
||||
|
||||
@ -269,36 +269,11 @@ exports.testActiveWindow = function(test) {
|
||||
});
|
||||
|
||||
function nextStep() {
|
||||
if (testSteps.length > 0)
|
||||
if (testSteps.length)
|
||||
testSteps.shift()();
|
||||
}
|
||||
|
||||
function continueAfterFocus(targetWindow) {
|
||||
// Based on SimpleTest.waitForFocus
|
||||
var fm = Cc["@mozilla.org/focus-manager;1"].
|
||||
getService(Ci.nsIFocusManager);
|
||||
|
||||
var childTargetWindow = {};
|
||||
fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
|
||||
childTargetWindow = childTargetWindow.value;
|
||||
|
||||
var focusedChildWindow = {};
|
||||
if (fm.activeWindow) {
|
||||
fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
|
||||
focusedChildWindow = focusedChildWindow.value;
|
||||
}
|
||||
|
||||
var focused = (focusedChildWindow == childTargetWindow);
|
||||
if (focused) {
|
||||
setTimeout(nextStep, 0);
|
||||
} else {
|
||||
childTargetWindow.addEventListener("focus", function focusListener() {
|
||||
childTargetWindow.removeEventListener("focus", focusListener, true);
|
||||
setTimeout(nextStep, 0);
|
||||
}, true);
|
||||
}
|
||||
|
||||
}
|
||||
let continueAfterFocus = function(w) onFocus(w).then(nextStep);
|
||||
|
||||
function finishTest() {
|
||||
window3.close(function() {
|
||||
@ -381,6 +356,8 @@ exports.testWindowOpenPrivateDefault = function(test) {
|
||||
url: 'about:mozilla',
|
||||
isPrivate: true,
|
||||
onOpen: function(window) {
|
||||
test.assertEqual();
|
||||
|
||||
let tab = window.tabs[0];
|
||||
tab.once('ready', function() {
|
||||
test.assertEqual(tab.url, 'about:mozilla', 'opened correct tab');
|
||||
@ -393,3 +370,42 @@ exports.testWindowOpenPrivateDefault = function(test) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test that it is not possible to find a private window in
|
||||
// windows module's iterator
|
||||
exports.testWindowIteratorPrivateDefault = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
test.assertEqual(browserWindows.length, 1, 'only one window open');
|
||||
|
||||
open('chrome://browser/content/browser.xul', {
|
||||
features: {
|
||||
private: true,
|
||||
chrome: true
|
||||
}
|
||||
}).then(function(window) focus(window).then(function() {
|
||||
// test that there is a private window opened
|
||||
test.assertEqual(isPrivate(window), isWindowPBSupported, 'there is a private window open');
|
||||
test.assertStrictEqual(window, winUtils.activeWindow);
|
||||
test.assertStrictEqual(window, getMostRecentWindow());
|
||||
|
||||
test.assert(!isPrivate(browserWindows.activeWindow));
|
||||
|
||||
if (isWindowPBSupported) {
|
||||
test.assertEqual(browserWindows.length, 1, 'only one window in browserWindows');
|
||||
test.assertEqual(windows().length, 1, 'only one window in windows()');
|
||||
}
|
||||
else {
|
||||
test.assertEqual(browserWindows.length, 2, 'two windows open');
|
||||
test.assertEqual(windows().length, 2, 'two windows in windows()');
|
||||
}
|
||||
test.assertEqual(windows(null, { includePrivate: true }).length, 2);
|
||||
|
||||
for each(let window in browserWindows) {
|
||||
// test that all windows in iterator are not private
|
||||
test.assert(!isPrivate(window), 'no window in browserWindows is private');
|
||||
}
|
||||
|
||||
close(window).then(test.done.bind(test));
|
||||
}));
|
||||
}
|
||||
|