mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
59bcf9294a
@ -13,7 +13,6 @@ include $(topsrcdir)/config/rules.mk
|
||||
TEST_FILES = \
|
||||
source/app-extension \
|
||||
source/bin \
|
||||
source/data \
|
||||
source/python-lib \
|
||||
source/test \
|
||||
source/package.json \
|
||||
|
@ -35,7 +35,7 @@ such, will only return favicon URLs for visited sites.
|
||||
console.log(url); // http://mozorg.cdn.mozilla.net/media/img/favicon.ico
|
||||
});
|
||||
|
||||
@param object {string, tab}
|
||||
@param object {string|tab}
|
||||
A value that represents the URL of the page to get the favicon URL from.
|
||||
Can be a URL `String` or a [`Tab`](modules/sdk/tabs.html#Tab).
|
||||
|
||||
|
@ -126,6 +126,10 @@ content (see the
|
||||
});
|
||||
});
|
||||
|
||||
Note that `tab.attach` is tab-centric: if the user navigates to a new
|
||||
page in the same tab, then the worker and content scripts will be
|
||||
reattached to the new page.
|
||||
|
||||
## Private Windows ##
|
||||
|
||||
If your add-on has not opted into private browsing, then you won't see any
|
||||
@ -346,7 +350,10 @@ Returns thumbnail data URI of the page currently loaded in this tab.
|
||||
|
||||
<api name="attach">
|
||||
@method
|
||||
Create a page mod and attach it to the document in the tab.
|
||||
Create a [Worker](modules/sdk/content/worker.html) and attach it to
|
||||
every document loaded in the tab. Note that this is tab-centric: if
|
||||
the user navigates to a new page in the same tab, then the worker and
|
||||
content scripts will be reattached to the new page.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -360,20 +367,22 @@ Returns thumbnail data URI of the page currently loaded in this tab.
|
||||
});
|
||||
|
||||
@param options {object}
|
||||
Options for the page mod, with the following keys:
|
||||
Options for the worker, with the following keys:
|
||||
|
||||
@prop [contentScriptFile] {string,array}
|
||||
The local file URLs of content scripts to load. Content scripts specified
|
||||
by this option are loaded *before* those specified by the `contentScript`
|
||||
option. Optional.
|
||||
@prop [contentScript] {string,array}
|
||||
The texts of content scripts to load. Content scripts specified by this
|
||||
option are loaded *after* those specified by the `contentScriptFile` option.
|
||||
A string or an array of strings of code to be evaluated in the context.
|
||||
Content scripts specified by this option are loaded *after*
|
||||
those specified by the `contentScriptFile` option.
|
||||
Optional.
|
||||
@prop [onMessage] {function}
|
||||
A function called when the page mod receives a message from content scripts.
|
||||
Listeners are passed a single argument, the message posted from the
|
||||
content script. Optional.
|
||||
A function called when the content worker receives a message from
|
||||
content scripts. Listeners are passed a single argument, the
|
||||
message posted from the content script.
|
||||
Optional.
|
||||
|
||||
@returns {Worker}
|
||||
The [Worker](modules/sdk/content/worker.html#Worker) object can be used to
|
||||
|
@ -1,214 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- contributed by Erik Vold [evold@mozilla.com] -->
|
||||
|
||||
This module exports a two constructor functions `Button` which constructs a
|
||||
new toolbar button, and `Sidebar` which constructs a sidebar (with a button).
|
||||
|
||||
Sidebars are displayed on the left side of your browser. Its content is specified as
|
||||
local HTML, so the appearance and behaviour of the sidebar
|
||||
is limited only by what you can do using HTML, CSS and JavaScript.
|
||||
|
||||
The screenshot below shows a sidebar whose content is built from tweets:
|
||||
|
||||
<!-- add screen shot here -->
|
||||
|
||||
Sidebars are useful for presenting temporary interfaces to users in a way that is
|
||||
easier for users to ignore and dismiss than a modal dialog
|
||||
and easier for users to keep around than a Panel, since sidebars are
|
||||
displayed at the side of the browser until the user decides to close it.
|
||||
|
||||
A sidebar's content is loaded anew as soon as it is opened, and unloads
|
||||
when the user closes the sidebar.
|
||||
|
||||
Your add-on can receive notifications when a sidebar is shown or hidden by
|
||||
listening to its `show` and `hide` events.
|
||||
|
||||
Opening a sidebar in a window will close an already opened sidebar in that window.
|
||||
|
||||
## Sidebar Content ##
|
||||
|
||||
The sidebar's content is specified as HTML, which is loaded from the URL
|
||||
supplied in the `url` option to the sidebar's constructor.
|
||||
|
||||
You can load remote HTML into the sidebar:
|
||||
|
||||
var sidebar = require("sdk/ui").Sidebar({
|
||||
id: 'a-new-sidebar',
|
||||
title: 'A New Sidebar',
|
||||
icon: './icon.png',
|
||||
url: './index.html'
|
||||
});
|
||||
|
||||
sidebar.show();
|
||||
|
||||
This will load HTML that's been packaged with your add-on, and this is
|
||||
most probably how you will create sidebars. To do this, save
|
||||
the `index.html` HTML file in your add-on's `data` directory.
|
||||
|
||||
## Sidebar Positioning ##
|
||||
|
||||
By default the sidebars appears on the left side of the currently active browser window.
|
||||
|
||||
|
||||
## Updating Sidebar Content ##
|
||||
|
||||
You can update the sidebar's content simply by setting the sidebar's `url`
|
||||
property. Note this will change the sidebar's url for all windows.
|
||||
|
||||
## Scripting Sidebar Content ##
|
||||
|
||||
You can't directly access your sidebar's content from your main add-on code.
|
||||
To access the sidebar's content, you need to add a `<script>` into the sidebar.
|
||||
|
||||
The sidebar's scripts will have access to a `addon` global, with you can
|
||||
communicate with your main add-on code, like so:
|
||||
|
||||
`lib/main.js`:
|
||||
|
||||
let sidebar = Sidebar({
|
||||
id: 'a-new-sidebar',
|
||||
title: 'A New Sidebar',
|
||||
icon: './icon.png',
|
||||
url: './index.html',
|
||||
onAttach: function (worker) {
|
||||
worker.port.on('message', function() { // part 2
|
||||
// do things...
|
||||
worker.port.emit('message', 'I have information for you!'); // part 3
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
`data/index.html`
|
||||
|
||||
<pre class="brush: html">
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
...
|
||||
<script>
|
||||
addon.port.on('message', function(msg) { // part 4
|
||||
// msg will == 'I have information for you!'
|
||||
});
|
||||
// starting communication here..
|
||||
addon.port.emit('message'); // part 1
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</pre>
|
||||
|
||||
<api name="Sidebar">
|
||||
@class
|
||||
The Sidebar object.
|
||||
|
||||
Once a sidebar object has been created it can be shown and hidden,
|
||||
in the active window, using its
|
||||
`show()` and `hide()` methods. Once a sidebar is no longer needed it can be
|
||||
removed/destructed using `destroy()`.
|
||||
|
||||
<api name="Sidebar">
|
||||
@constructor
|
||||
Creates a sidebar.
|
||||
@param options {object}
|
||||
Options for the sidebar, with the following keys:
|
||||
@prop id {string}
|
||||
The `id` of the sidebar.
|
||||
@prop title {string}
|
||||
A title for the sidebar.
|
||||
@prop icon {string, object}
|
||||
The icon used for the sidebar's button.
|
||||
@prop url {string, URL}
|
||||
The URL of the content to load in the sidebar.
|
||||
@prop [onAttach] {function}
|
||||
Include this to listen to the sidebar's `attach` event.
|
||||
@prop [onShow] {function}
|
||||
Include this to listen to the sidebar's `show` event.
|
||||
@prop [onHide] {function}
|
||||
Include this to listen to the sidebar's `hide` event.
|
||||
</api>
|
||||
|
||||
<api name="id">
|
||||
@property {string}
|
||||
The `id` for the sidebar.
|
||||
</api>
|
||||
|
||||
<api name="title">
|
||||
@property {string}
|
||||
The `title` of the sidebar.
|
||||
</api>
|
||||
|
||||
<api name="icon">
|
||||
@property {string, object}
|
||||
The global icon for the sidebar.
|
||||
</api>
|
||||
|
||||
<api name="url">
|
||||
@property {string}
|
||||
The URL of content loaded into the sidebar.
|
||||
</api>
|
||||
|
||||
<api name="destroy">
|
||||
@method
|
||||
Destroys the sidebar, once destroyed, the sidebar can no longer be used.
|
||||
</api>
|
||||
|
||||
<api name="show">
|
||||
@method
|
||||
Displays the sidebar in the active window.
|
||||
</api>
|
||||
|
||||
<api name="hide">
|
||||
@method
|
||||
Hides the sidebar in the active window.
|
||||
</api>
|
||||
|
||||
<api name="on">
|
||||
@method
|
||||
Registers an event listener with the sidebar.
|
||||
@param type {string}
|
||||
The type of event to listen for.
|
||||
@param listener {function}
|
||||
The listener function that handles the event.
|
||||
</api>
|
||||
|
||||
<api name="once">
|
||||
@method
|
||||
Registers an event listener with the sidebar.
|
||||
The difference between `on` and `once` is that
|
||||
`on` will continue listening until it is
|
||||
removed, whereas `once` is removed automatically
|
||||
upon the first event it catches.
|
||||
@param type {string}
|
||||
The type of event to listen for.
|
||||
@param listener {function}
|
||||
The listener function that handles the event.
|
||||
</api>
|
||||
|
||||
<api name="removeListener">
|
||||
@method
|
||||
Unregisters/removes an event listener from the sidebar.
|
||||
@param type {string}
|
||||
The type of event for which `listener` was registered.
|
||||
@param listener {function}
|
||||
The listener function that was registered.
|
||||
</api>
|
||||
|
||||
<api name="attach">
|
||||
@event
|
||||
This event is emitted when the sidebar's window
|
||||
is created and the `addon` global was added.
|
||||
</api>
|
||||
|
||||
<api name="show">
|
||||
@event
|
||||
This event is emitted when the sidebar is shown.
|
||||
</api>
|
||||
|
||||
<api name="hide">
|
||||
@event
|
||||
This event is emitted when the sidebar is hidden.
|
||||
</api>
|
||||
|
||||
</api>
|
378
addon-sdk/source/doc/module-source/sdk/ui/sidebar.md
Normal file
378
addon-sdk/source/doc/module-source/sdk/ui/sidebar.md
Normal file
@ -0,0 +1,378 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
The `sidebar` module enables you to create sidebars. A sidebar is a a strip
|
||||
of user interface real estate for your add-on that's attached to the
|
||||
left-hand side of the browser window. A sidebar is a bit like a widget,
|
||||
in that it's a persistent user interface element belonging to your add-on
|
||||
that's attached to the browser window. However, it's much bigger than a
|
||||
widget and is suitable for more presenting more complex interfaces.
|
||||
|
||||
## Creating, showing, and hiding sidebars
|
||||
|
||||
You construct a `Sidebar` object using the [`Sidebar()`](modules/sdk/ui/sidebar.html#Sidebar(options)) constructor.
|
||||
|
||||
Once you've done that, you can show the sidebar in the currently active window
|
||||
by calling the Sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method. If a new window is opened from a
|
||||
window that has a sidebar visible, the new window gets a sidebar, too.
|
||||
|
||||
You can hide the sidebar in the currently active window by calling its
|
||||
[`hide()`](modules/sdk/ui/sidebar.html#hide()) method.
|
||||
|
||||
Alternatively, the View->Sidebar submenu in Firefox will contain a new item
|
||||
which the user can use to show or hide the sidebar:
|
||||
|
||||
<img class="image-center" src="static-files/media/screenshots/sidebar-menu.png" alt="Opening sidebar from a menu">
|
||||
|
||||
The sidebar generates a [`show`](modules/sdk/ui/sidebar.html#show) event when it is shown and a [`hide`](modules/sdk/ui/sidebar.html#hide) event when
|
||||
it is hidden.
|
||||
|
||||
Once you've finished using the sidebar you can destroy it by calling its
|
||||
[`dispose()`](file:///Users/Work/mozilla/jetpack-sdk/doc/modules/sdk/ui/sidebar.html#dispose()) method.
|
||||
|
||||
To show what a sidebar looks like, here's a sidebar that displays the results
|
||||
of running the [W3C Validator](http://validator.w3.org/) on the current page:
|
||||
|
||||
<img class="image-center" src="static-files/media/screenshots/sidebar.png" alt="Simple sidebar example">
|
||||
|
||||
|
||||
## Specifying sidebar content
|
||||
|
||||
The content of a sidebar is specified using HTML, which is loaded from the URL
|
||||
supplied in the `url` option to the sidebar's constructor. Unlike modules
|
||||
such as [`panel`](modules/sdk/panel.html), the content must be local,
|
||||
typically loaded from the add-on's `data` directory via a URL constructed
|
||||
using [`self.data.url()`](modules/sdk/self.html#data):
|
||||
|
||||
var sidebar = require("sdk/ui/sidebar").Sidebar({
|
||||
id: 'my-sidebar',
|
||||
title: 'My sidebar',
|
||||
url: require("sdk/self").data.url("sidebar.html")
|
||||
});
|
||||
|
||||
You can include JavaScript and CSS from the HTML as you would with any web
|
||||
page, for example using `<script>` and `<link>` tags containing a path
|
||||
relative to the HTML file itself.
|
||||
|
||||
<pre class="brush: html">
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link href="stuff.css" type="text/css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="stuff.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</pre>
|
||||
|
||||
You can update the sidebar's content by setting the sidebar's `url`
|
||||
property. This will change the sidebar's content across all windows.
|
||||
|
||||
## Communicating with sidebar scripts ##
|
||||
|
||||
You can't directly access your sidebar's content from your main add-on code,
|
||||
but you can send messages between your main add-on code and scripts loaded
|
||||
into your sidebar.
|
||||
|
||||
On the sidebar end of the conversation, sidebar scripts get a global
|
||||
variable `addon` that contains a `port` for sending and receiving
|
||||
messages.
|
||||
|
||||
On the add-on side, you must listen for the sidebar's `attach` event,
|
||||
which is triggered whenever the DOM for a new sidebar instance is loaded
|
||||
and its scripts are attached. This message passes a `worker` object into
|
||||
the listener function, and you can use that worker to communicate with the
|
||||
script loaded into the new sidebar instance.
|
||||
|
||||
Here's a simple but complete add-on that shows how to set up communication
|
||||
between main.js and a script in a sidebar:
|
||||
|
||||
The HTML file includes just a script, "sidebar.js":
|
||||
|
||||
<pre class="brush: html">
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
Content for my sidebar
|
||||
<script type="text/javascript" src="sidebar.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</pre>
|
||||
|
||||
The "sidebar.js" file sends a `ready` message to main.js using `port.emit()`,
|
||||
and adds a listener to the `init` message that logs the message payload.
|
||||
|
||||
addon.port.emit("ready");
|
||||
addon.port.on("init", sayStuff);
|
||||
|
||||
function sayStuff(message) {
|
||||
console.log("got the message '" + message + "'" );
|
||||
}
|
||||
|
||||
The "main.js" file creates a sidebar object and adds a listener to its
|
||||
`attach` event. The listener listens for the `ready` message from the
|
||||
sidebar script, and responds with an `init` message:
|
||||
|
||||
var sidebar = require("sdk/ui/sidebar").Sidebar({
|
||||
id: 'my-sidebar',
|
||||
title: 'My sidebar',
|
||||
url: require("sdk/self").data.url("sidebar.html"),
|
||||
onAttach: function (worker) {
|
||||
worker.port.on("ready", function() {
|
||||
worker.port.emit("init", "message from main.js");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Try running the add-on, and showing the sidebar using the
|
||||
"View->Sidebar->My sidebar" menu item. You should see console output like:
|
||||
|
||||
<pre>
|
||||
example-add-on: got the message 'message from main.js'
|
||||
</pre>
|
||||
|
||||
You *can't* send the sidebar script
|
||||
messages in the `attach` event listener, because the script may not be
|
||||
initialized yet. It's safer, as in this example, to have the script
|
||||
message "main.js" as soon as it is loaded, and have "main.js" listen
|
||||
for that message before responding.
|
||||
|
||||
<api name="Sidebar">
|
||||
@class
|
||||
The Sidebar object. Once a sidebar has been created it can be shown and hidden
|
||||
in the active window using its
|
||||
[`show()`](modules/sdk/ui/sidebar.html#show()) and
|
||||
[`hide()`](modules/sdk/ui/sidebar.html#hide()) methods.
|
||||
Once a sidebar is no longer needed it can be
|
||||
destroyed using [`dispose()`](modules/sdk/ui/sidebar.html#dispose()).
|
||||
|
||||
<api name="Sidebar">
|
||||
@constructor
|
||||
Creates a sidebar.
|
||||
|
||||
var sidebar = require("sdk/ui/sidebar").Sidebar({
|
||||
id: 'my-sidebar',
|
||||
title: 'My sidebar',
|
||||
url: require("sdk/self").data.url("sidebar.html"),
|
||||
onAttach: function (worker) {
|
||||
console.log("attaching");
|
||||
},
|
||||
onShow: function () {
|
||||
console.log("showing");
|
||||
},
|
||||
onHide: function () {
|
||||
console.log("hiding");
|
||||
},
|
||||
onDetach: function () {
|
||||
console.log("detaching");
|
||||
}
|
||||
});
|
||||
|
||||
@param options {object}
|
||||
Options for the sidebar, with the following keys:
|
||||
@prop id {string}
|
||||
The `id` of the sidebar. This used to identify this sidebar in its chrome window. It must be unique.
|
||||
@prop title {string}
|
||||
A title for the sidebar. This will be used for the label for your sidebar
|
||||
in the "Sidebar" submenu in Firefox, and will be shown at the top of your
|
||||
sidebar when it is open.
|
||||
@prop url {string}
|
||||
The URL of the content to load in the sidebar. This must be a local URL (typically, loaded from the "data" folder using `self.data.url()`).
|
||||
@prop [onAttach] {function}
|
||||
Listener for the sidebar's `attach` event.
|
||||
@prop [onDetach] {function}
|
||||
Listener for the sidebar's `detach` event.
|
||||
@prop [onShow] {function}
|
||||
Listener for the sidebar's `show` event.
|
||||
@prop [onHide] {function}
|
||||
Listener for the sidebar's `hide` event.
|
||||
</api>
|
||||
|
||||
<api name="id">
|
||||
@property {string}
|
||||
The id of the sidebar. This used to identify this sidebar in its chrome window. It must be unique.
|
||||
</api>
|
||||
|
||||
<api name="title">
|
||||
@property {string}
|
||||
The title of the sidebar. This will be used for the label for your sidebar
|
||||
in the "Sidebar" submenu in Firefox, and will be shown at the top of your
|
||||
sidebar when it is open.
|
||||
</api>
|
||||
|
||||
<api name="url">
|
||||
@property {string}
|
||||
The URL of the content to load in the sidebar. This must be a local URL (typically, loaded from the "data" folder using `self.data.url()`).
|
||||
</api>
|
||||
|
||||
<api name="dispose">
|
||||
@method
|
||||
Destroys the sidebar. Once destroyed, the sidebar can no longer be used.
|
||||
</api>
|
||||
|
||||
<api name="show">
|
||||
@method
|
||||
Displays the sidebar in the active window.
|
||||
</api>
|
||||
|
||||
<api name="hide">
|
||||
@method
|
||||
Hides the sidebar in the active window.
|
||||
</api>
|
||||
|
||||
<api name="on">
|
||||
@method
|
||||
Registers an event listener with the sidebar.
|
||||
@param type {string}
|
||||
The type of event to listen for.
|
||||
@param listener {function}
|
||||
The listener function that handles the event.
|
||||
</api>
|
||||
|
||||
<api name="once">
|
||||
@method
|
||||
Registers an event listener with the sidebar.
|
||||
The difference between `on` and `once` is that
|
||||
`on` will continue listening until it is
|
||||
removed, whereas `once` is removed automatically
|
||||
upon the first event it catches.
|
||||
@param type {string}
|
||||
The type of event to listen for.
|
||||
@param listener {function}
|
||||
The listener function that handles the event.
|
||||
</api>
|
||||
|
||||
<api name="removeListener">
|
||||
@method
|
||||
Unregisters/removes an event listener from the sidebar.
|
||||
@param type {string}
|
||||
The type of event for which `listener` was registered.
|
||||
@param listener {function}
|
||||
The listener function that was registered.
|
||||
</api>
|
||||
|
||||
<api name="attach">
|
||||
@event
|
||||
This event is emitted when a worker is attached to a sidebar, as a result of any of the following:
|
||||
|
||||
* calling the sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method,
|
||||
when the sidebar is not shown in the currently active window
|
||||
* changing the sidebar's [`url`](modules/sdk/ui/sidebar.html#url) property
|
||||
* the user switching the sidebar on using the "Sidebar" submenu in Firefox,
|
||||
when the sidebar is not shown in the currently active window
|
||||
* the user opening a new window from a window that has the sidebar showing
|
||||
|
||||
This is the event you should listen to if you need to communicate with the
|
||||
scripts loaded into the sidebar. It is passed a [`worker`](modules/sdk/content/worker.html)
|
||||
as an argument, which defines `port.emit()` and `port.on()` methods that you can use
|
||||
to send messages to, and receive messages from, scripts loaded into the sidebar.
|
||||
|
||||
This code listens to `attach` and in the listener, starts listening to a message called "ready"
|
||||
from the script. When the listener receives the "ready" message it sends an "init" message to
|
||||
the script:
|
||||
|
||||
var sidebar = require("sdk/ui/sidebar").Sidebar({
|
||||
id: 'my-sidebar',
|
||||
title: 'My Sidebar',
|
||||
url: require("sdk/self").data.url("sidebar.html"),
|
||||
onAttach: function (worker) {
|
||||
// listen for a "ready" message from the script
|
||||
worker.port.on("ready", function() {
|
||||
// send an "init" message to the script
|
||||
worker.port.emit("init", "message from main.js");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Here's the corresponding script, that sends "ready" as soon as it runs, and listens for
|
||||
the "init" message from main.js:
|
||||
|
||||
addon.port.emit("ready");
|
||||
addon.port.on("init", sayStuff);
|
||||
|
||||
function sayStuff(message) {
|
||||
console.log("got the message '" + message + "'" );
|
||||
}
|
||||
|
||||
You should not try to send messages to the script in your `attach` handler, because it's not
|
||||
guaranteed that the script is listening to them yet. It's safer to start by listening for a
|
||||
message from the script, as in this example.
|
||||
|
||||
</api>
|
||||
|
||||
<api name="detach">
|
||||
@event
|
||||
This event is emitted when a worker is detached from a sidebar, as a result of either of the following:
|
||||
|
||||
* calling the sidebar's [`hide()`](modules/sdk/ui/sidebar.html#hide()) method,
|
||||
when the sidebar is being shown in the currently active window
|
||||
* the user switching the sidebar off using the "Sidebar" submenu in Firefox,
|
||||
when the sidebar is being shown in the currently active window
|
||||
|
||||
The `detach` listener receives a [`worker`](modules/sdk/content/worker.html) object as a parameter.
|
||||
This object is the same as the worker passed into the corresponding `attach` event. After
|
||||
`detach`, this worker can no longer be used to communicate with the scripts in that sidebar
|
||||
instance, because it has been unloaded.
|
||||
|
||||
If you listen to `attach`, and in the listener take a reference to the worker object that's
|
||||
passed into it, so you can send it messages later on, then you should probably listen to `detach`,
|
||||
and in its handler, remove your reference to the worker.
|
||||
|
||||
Here's an add-on that adds each worker to an array in the `attach` handler, and makes sure
|
||||
that its references are cleaned up by listening to `detach` and removing workers as they are
|
||||
detached:
|
||||
|
||||
var workerArray = [];
|
||||
|
||||
function attachWorker(worker) {
|
||||
workerArray.push(worker);
|
||||
}
|
||||
|
||||
function detachWorker(worker) {
|
||||
var index = workerArray.indexOf(worker);
|
||||
if(index != -1) {
|
||||
workerArray.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
var sidebar = require("sdk/ui/sidebar").Sidebar({
|
||||
id: 'my-sidebar',
|
||||
title: 'My Sidebar',
|
||||
url: require("sdk/self").data.url("sidebar.html"),
|
||||
onAttach: attachWorker,
|
||||
onDetach: detachWorker
|
||||
});
|
||||
|
||||
</api>
|
||||
|
||||
<api name="show">
|
||||
@event
|
||||
This event is emitted when the sidebar is shown, as a result of any of the following:
|
||||
|
||||
* calling the sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method,
|
||||
when the sidebar is not shown in the currently active window
|
||||
* changing the sidebar's [`url`](modules/sdk/ui/sidebar.html#url) property
|
||||
* the user switching the sidebar on using the "Sidebar" submenu in Firefox,
|
||||
when the sidebar is not shown in the currently active window
|
||||
* the user opening a new window from a window that has the sidebar showing
|
||||
|
||||
</api>
|
||||
|
||||
<api name="hide">
|
||||
@event
|
||||
This event is emitted when the sidebar is hidden, as a result of either of the following:
|
||||
|
||||
* calling the sidebar's [`hide()`](modules/sdk/ui/sidebar.html#hide()) method,
|
||||
when the sidebar is being shown in the currently active window
|
||||
* the user switching the sidebar off using the "Sidebar" submenu in Firefox,
|
||||
when the sidebar is being shown in the currently active window
|
||||
|
||||
</api>
|
||||
|
||||
</api>
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
addon-sdk/source/doc/static-files/media/screenshots/sidebar.png
Normal file
BIN
addon-sdk/source/doc/static-files/media/screenshots/sidebar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
@ -3,7 +3,7 @@
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"fullName": "library-detector-sdk",
|
||||
"title": "library-detector-sdk",
|
||||
"id": "jid1-R4rSVNkBANnvGQ",
|
||||
"description": "a basic add-on"
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ const unload = require('../system/unload');
|
||||
const { getDocShell } = require("../frame/utils");
|
||||
const { ignoreWindow } = require('../private-browsing/utils');
|
||||
|
||||
const assetsURI = require('../self').data.url();
|
||||
// Everything coming from add-on's xpi considered an asset.
|
||||
const assetsURI = require('../self').data.url().replace(/data\/$/, "");
|
||||
|
||||
/**
|
||||
* This trait is layered on top of `Worker` and in contrast to symbiont
|
||||
|
@ -1,37 +1,79 @@
|
||||
/* 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";
|
||||
|
||||
'use strict';
|
||||
|
||||
module.metadata = {
|
||||
"stability": "experimental"
|
||||
'stability': 'experimental'
|
||||
};
|
||||
|
||||
/*
|
||||
* Encodings supported by TextEncoder/Decoder:
|
||||
* utf-8, utf-16le, utf-16be
|
||||
* http://encoding.spec.whatwg.org/#interface-textencoder
|
||||
*
|
||||
* Node however supports the following encodings:
|
||||
* ascii, utf-8, utf-16le, usc2, base64, hex
|
||||
*/
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
|
||||
const { Cu } = require('chrome');
|
||||
const { isNumber } = require('sdk/lang/type');
|
||||
const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
|
||||
|
||||
exports.TextEncoder = TextEncoder;
|
||||
exports.TextDecoder = TextDecoder;
|
||||
|
||||
/**
|
||||
* Use WeakMaps to work around Bug 929146, which prevents us from adding
|
||||
* getters or values to typed arrays
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=929146
|
||||
*/
|
||||
const parents = new WeakMap();
|
||||
const views = new WeakMap();
|
||||
|
||||
function Buffer(subject, encoding) {
|
||||
var type = typeof(subject);
|
||||
switch (type) {
|
||||
case "number":
|
||||
// Create typed array of the given size if number.
|
||||
return Uint8Array(subject > 0 ? Math.floor(subject) : 0);
|
||||
case "string":
|
||||
// If string encode it and use buffer for the returned Uint8Array
|
||||
// to create a local patched version that acts like node buffer.
|
||||
encoding = encoding || "utf8";
|
||||
return Uint8Array(TextEncoder(encoding).encode(subject).buffer);
|
||||
case "object":
|
||||
// If array or alike just make a copy with a local patched prototype.
|
||||
function Buffer(subject, encoding /*, bufferLength */) {
|
||||
|
||||
// Allow invocation without `new` constructor
|
||||
if (!(this instanceof Buffer))
|
||||
return new Buffer(subject, encoding, arguments[2]);
|
||||
|
||||
var type = typeof(subject);
|
||||
|
||||
switch (type) {
|
||||
case 'number':
|
||||
// Create typed array of the given size if number.
|
||||
try {
|
||||
let buffer = Uint8Array(subject > 0 ? Math.floor(subject) : 0);
|
||||
return buffer;
|
||||
} catch (e) {
|
||||
if (/size and count too large/.test(e.message) ||
|
||||
/invalid arguments/.test(e.message))
|
||||
throw new RangeError('Could not instantiate buffer: size of buffer may be too large');
|
||||
else
|
||||
throw new Error('Could not instantiate buffer');
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// If string encode it and use buffer for the returned Uint8Array
|
||||
// to create a local patched version that acts like node buffer.
|
||||
encoding = encoding || 'utf8';
|
||||
return Uint8Array(TextEncoder(encoding).encode(subject).buffer);
|
||||
case 'object':
|
||||
// This form of the constructor uses the form of
|
||||
// Uint8Array(buffer, offset, length);
|
||||
// So we can instantiate a typed array within the constructor
|
||||
// to inherit the appropriate properties, where both the
|
||||
// `subject` and newly instantiated buffer share the same underlying
|
||||
// data structure.
|
||||
if (arguments.length === 3)
|
||||
return Uint8Array(subject, encoding, arguments[2]);
|
||||
// If array or alike just make a copy with a local patched prototype.
|
||||
else
|
||||
return Uint8Array(subject);
|
||||
default:
|
||||
throw new TypeError("must start with number, buffer, array or string");
|
||||
}
|
||||
default:
|
||||
throw new TypeError('must start with number, buffer, array or string');
|
||||
}
|
||||
}
|
||||
exports.Buffer = Buffer;
|
||||
|
||||
@ -39,12 +81,20 @@ exports.Buffer = Buffer;
|
||||
Buffer.isBuffer = value => value instanceof Buffer
|
||||
|
||||
// Returns true if the encoding is a valid encoding argument & false otherwise
|
||||
Buffer.isEncoding = encoding => !!ENCODINGS[String(encoding).toLowerCase()]
|
||||
Buffer.isEncoding = function (encoding) {
|
||||
if (!encoding) return false;
|
||||
try {
|
||||
TextDecoder(encoding);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Gives the actual byte length of a string. encoding defaults to 'utf8'.
|
||||
// This is not the same as String.prototype.length since that returns the
|
||||
// number of characters in a string.
|
||||
Buffer.byteLength = (value, encoding = "utf8") =>
|
||||
Buffer.byteLength = (value, encoding = 'utf8') =>
|
||||
TextEncoder(encoding).encode(value).byteLength
|
||||
|
||||
// Direct copy of the nodejs's buffer implementation:
|
||||
@ -85,78 +135,167 @@ Buffer.concat = function(list, length) {
|
||||
|
||||
// Node buffer is very much like Uint8Array although it has bunch of methods
|
||||
// that typically can be used in combination with `DataView` while preserving
|
||||
// access by index. Since in SDK echo module has it's own set of bult-ins it
|
||||
// access by index. Since in SDK each module has it's own set of bult-ins it
|
||||
// ok to patch ours to make it nodejs Buffer compatible.
|
||||
Buffer.prototype = Uint8Array.prototype;
|
||||
Object.defineProperties(Buffer.prototype, {
|
||||
parent: {
|
||||
get: function() { return parents.get(this, undefined); }
|
||||
},
|
||||
view: {
|
||||
get: function() this._view || (this._view = DataView(this.buffer))
|
||||
get: function () {
|
||||
let view = views.get(this, undefined);
|
||||
if (view) return view;
|
||||
view = DataView(this.buffer);
|
||||
views.set(this, view);
|
||||
return view;
|
||||
}
|
||||
},
|
||||
toString: {
|
||||
value: function(encoding, start, end) {
|
||||
encoding = !!encoding ? (encoding + '').toLowerCase() : "utf8";
|
||||
encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
|
||||
start = Math.max(0, ~~start);
|
||||
end = Math.min(this.length, end === void(0) ? this.length : ~~end);
|
||||
return TextDecoder(encoding).decode(this.subarray(start, end));
|
||||
}
|
||||
},
|
||||
toJSON: {
|
||||
value: function() ({ type: "Buffer", data: Array.slice(this, 0) })
|
||||
value: function() {
|
||||
return { type: 'Buffer', data: Array.slice(this, 0) };
|
||||
}
|
||||
},
|
||||
get: {
|
||||
value: function(offset) this[offset]
|
||||
value: function(offset) {
|
||||
return this[offset];
|
||||
}
|
||||
},
|
||||
set: {
|
||||
value: function(offset, value) this[offset] = value
|
||||
value: function(offset, value) { this[offset] = value; }
|
||||
},
|
||||
copy: {
|
||||
value: function(target, offset, start, end)
|
||||
Uint8Array.set(target, this.subarray(start, end), offset)
|
||||
value: function(target, offset, start, end) {
|
||||
let length = this.length;
|
||||
let targetLength = target.length;
|
||||
offset = isNumber(offset) ? offset : 0;
|
||||
start = isNumber(start) ? start : 0;
|
||||
|
||||
if (start < 0)
|
||||
throw new RangeError('sourceStart is outside of valid range');
|
||||
if (end < 0)
|
||||
throw new RangeError('sourceEnd is outside of valid range');
|
||||
|
||||
// If sourceStart > sourceEnd, or targetStart > targetLength,
|
||||
// zero bytes copied
|
||||
if (start > end ||
|
||||
offset > targetLength
|
||||
)
|
||||
return 0;
|
||||
|
||||
// If `end` is not defined, or if it is defined
|
||||
// but would overflow `target`, redefine `end`
|
||||
// so we can copy as much as we can
|
||||
if (end - start > targetLength - offset ||
|
||||
end == null) {
|
||||
let remainingTarget = targetLength - offset;
|
||||
let remainingSource = length - start;
|
||||
if (remainingSource <= remainingTarget)
|
||||
end = length;
|
||||
else
|
||||
end = start + remainingTarget;
|
||||
}
|
||||
|
||||
Uint8Array.set(target, this.subarray(start, end), offset);
|
||||
return end - start;
|
||||
}
|
||||
},
|
||||
slice: {
|
||||
value: Buffer.prototype.subarray
|
||||
value: function(start, end) {
|
||||
let length = this.length;
|
||||
start = ~~start;
|
||||
end = end != null ? end : length;
|
||||
|
||||
if (start < 0) {
|
||||
start += length;
|
||||
if (start < 0) start = 0;
|
||||
} else if (start > length)
|
||||
start = length;
|
||||
|
||||
if (end < 0) {
|
||||
end += length;
|
||||
if (end < 0) end = 0;
|
||||
} else if (end > length)
|
||||
end = length;
|
||||
|
||||
if (end < start)
|
||||
end = start;
|
||||
|
||||
// This instantiation uses the Uint8Array(buffer, offset, length) version
|
||||
// of construction to share the same underling data structure
|
||||
let buffer = new Buffer(this.buffer, start, end - start);
|
||||
|
||||
// If buffer has a value, assign its parent value to the
|
||||
// buffer it shares its underlying structure with. If a slice of
|
||||
// a slice, then use the root structure
|
||||
if (buffer.length > 0)
|
||||
parents.set(buffer, this.parent || this);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
},
|
||||
write: {
|
||||
value: function(string, offset, length, encoding = "utf8") {
|
||||
if (typeof(offset) === "string")
|
||||
value: function(string, offset, length, encoding = 'utf8') {
|
||||
// write(string, encoding);
|
||||
if (typeof(offset) === 'string' && Number.isNaN(parseInt(offset))) {
|
||||
([offset, length, encoding]) = [0, null, offset];
|
||||
else if (typeof(length) === "string")
|
||||
}
|
||||
// write(string, offset, encoding);
|
||||
else if (typeof(length) === 'string')
|
||||
([length, encoding]) = [null, length];
|
||||
|
||||
if (offset < 0 || offset > this.length)
|
||||
throw new RangeError('offset is outside of valid range');
|
||||
|
||||
offset = ~~offset;
|
||||
length = length || this.length - offset;
|
||||
|
||||
// Clamp length if it would overflow buffer, or if its
|
||||
// undefined
|
||||
if (length == null || length + offset > this.length)
|
||||
length = this.length - offset;
|
||||
|
||||
let buffer = TextEncoder(encoding).encode(string);
|
||||
let result = Math.min(buffer.length, length);
|
||||
if (buffer.length !== length)
|
||||
buffer = buffer.subarray(0, length);
|
||||
|
||||
Uint8Array.set(this, buffer, offset);
|
||||
return result;
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
value: function fill(value, start, end) {
|
||||
let length = this.length;
|
||||
value = value || 0;
|
||||
start = start || 0;
|
||||
end = end || this.length;
|
||||
end = end || length;
|
||||
|
||||
if (typeof(value) === "string")
|
||||
if (typeof(value) === 'string')
|
||||
value = value.charCodeAt(0);
|
||||
if (typeof(value) !== "number" || isNaN(value))
|
||||
throw TypeError("value is not a number");
|
||||
if (typeof(value) !== 'number' || isNaN(value))
|
||||
throw TypeError('value is not a number');
|
||||
if (end < start)
|
||||
throw new RangeError("end < start");
|
||||
throw new RangeError('end < start');
|
||||
|
||||
// Fill 0 bytes; we're done
|
||||
if (end === start)
|
||||
return 0;
|
||||
if (this.length == 0)
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
if (start < 0 || start >= this.length)
|
||||
throw RangeError("start out of bounds");
|
||||
if (start < 0 || start >= length)
|
||||
throw RangeError('start out of bounds');
|
||||
|
||||
if (end < 0 || end > this.length)
|
||||
throw RangeError("end out of bounds");
|
||||
if (end < 0 || end > length)
|
||||
throw RangeError('end out of bounds');
|
||||
|
||||
let index = start;
|
||||
while (index < end) this[index++] = value;
|
||||
@ -166,94 +305,42 @@ Object.defineProperties(Buffer.prototype, {
|
||||
|
||||
// Define nodejs Buffer's getter and setter functions that just proxy
|
||||
// to internal DataView's equivalent methods.
|
||||
[["readUInt16LE", "getUint16", true],
|
||||
["readUInt16BE", "getUint16", false],
|
||||
["readInt16LE", "getInt16", true],
|
||||
["readInt16BE", "getInt16", false],
|
||||
["readUInt32LE", "getInt32", true],
|
||||
["readUInt32BE", "getInt32", false],
|
||||
["readInt32LE", "getInt32", true],
|
||||
["readInt32BE", "getInt32", false],
|
||||
["readFloatLE", "getFloat32", true],
|
||||
["readFloatBE", "getFloat32", false],
|
||||
["readDoubleLE", "getFloat64", true],
|
||||
["readDoubleBE", "getFloat64", false],
|
||||
["readUInt8", "getUint8"],
|
||||
["readInt8", "getInt8"]].forEach(([alias, name, littleEndian]) => {
|
||||
|
||||
// TODO do we need to check architecture to see if it's default big/little endian?
|
||||
[['readUInt16LE', 'getUint16', true],
|
||||
['readUInt16BE', 'getUint16', false],
|
||||
['readInt16LE', 'getInt16', true],
|
||||
['readInt16BE', 'getInt16', false],
|
||||
['readUInt32LE', 'getUint32', true],
|
||||
['readUInt32BE', 'getUint32', false],
|
||||
['readInt32LE', 'getInt32', true],
|
||||
['readInt32BE', 'getInt32', false],
|
||||
['readFloatLE', 'getFloat32', true],
|
||||
['readFloatBE', 'getFloat32', false],
|
||||
['readDoubleLE', 'getFloat64', true],
|
||||
['readDoubleBE', 'getFloat64', false],
|
||||
['readUInt8', 'getUint8'],
|
||||
['readInt8', 'getInt8']].forEach(([alias, name, littleEndian]) => {
|
||||
Object.defineProperty(Buffer.prototype, alias, {
|
||||
value: function(offset) this.view[name](offset, littleEndian)
|
||||
});
|
||||
});
|
||||
|
||||
[["writeUInt16LE", "setUint16", true],
|
||||
["writeUInt16BE", "setUint16", false],
|
||||
["writeInt16LE", "setInt16", true],
|
||||
["writeInt16BE", "setInt16", false],
|
||||
["writeUInt32LE", "setUint32", true],
|
||||
["writeUInt32BE", "setUint32", false],
|
||||
["writeInt32LE", "setInt32", true],
|
||||
["writeInt32BE", "setInt32", false],
|
||||
["writeFloatLE", "setFloat32", true],
|
||||
["writeFloatBE", "setFloat32", false],
|
||||
["writeDoubleLE", "setFloat64", true],
|
||||
["writeDoubleBE", "setFloat64", false],
|
||||
["writeUInt8", "setUint8"],
|
||||
["writeInt8", "setInt8"]].forEach(([alias, name, littleEndian]) => {
|
||||
[['writeUInt16LE', 'setUint16', true],
|
||||
['writeUInt16BE', 'setUint16', false],
|
||||
['writeInt16LE', 'setInt16', true],
|
||||
['writeInt16BE', 'setInt16', false],
|
||||
['writeUInt32LE', 'setUint32', true],
|
||||
['writeUInt32BE', 'setUint32', false],
|
||||
['writeInt32LE', 'setInt32', true],
|
||||
['writeInt32BE', 'setInt32', false],
|
||||
['writeFloatLE', 'setFloat32', true],
|
||||
['writeFloatBE', 'setFloat32', false],
|
||||
['writeDoubleLE', 'setFloat64', true],
|
||||
['writeDoubleBE', 'setFloat64', false],
|
||||
['writeUInt8', 'setUint8'],
|
||||
['writeInt8', 'setInt8']].forEach(([alias, name, littleEndian]) => {
|
||||
Object.defineProperty(Buffer.prototype, alias, {
|
||||
value: function(value, offset) this.view[name](offset, value, littleEndian)
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// List of supported encodings taken from:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
|
||||
const ENCODINGS = { "unicode-1-1-utf-8": 1, "utf-8": 1, "utf8": 1,
|
||||
"866": 1, "cp866": 1, "csibm866": 1, "ibm866": 1, "csisolatin2": 1,
|
||||
"iso-8859-2": 1, "iso-ir-101": 1, "iso8859-2": 1, "iso88592": 1,
|
||||
"iso_8859-2": 1, "iso_8859-2:1987": 1, "l2": 1, "latin2": 1, "csisolatin3": 1,
|
||||
"iso-8859-3": 1, "iso-ir-109": 1, "iso8859-3": 1, "iso88593": 1,
|
||||
"iso_8859-3": 1, "iso_8859-3:1988": 1, "l3": 1, "latin3": 1, "csisolatin4": 1,
|
||||
"iso-8859-4": 1, "iso-ir-110": 1, "iso8859-4": 1, "iso88594": 1,
|
||||
"iso_8859-4": 1, "iso_8859-4:1988": 1, "l4": 1, "latin4": 1,
|
||||
"csisolatincyrillic": 1, "cyrillic": 1, "iso-8859-5": 1, "iso-ir-144": 1,
|
||||
"iso8859-5": 1, "iso88595": 1, "iso_8859-5": 1, "iso_8859-5:1988": 1,
|
||||
"arabic": 1, "asmo-708": 1, "csiso88596e": 1, "csiso88596i": 1,
|
||||
"csisolatinarabic": 1, "ecma-114": 1, "iso-8859-6": 1, "iso-8859-6-e": 1,
|
||||
"iso-8859-6-i": 1, "iso-ir-127": 1, "iso8859-6": 1, "iso88596": 1,
|
||||
"iso_8859-6": 1, "iso_8859-6:1987": 1, "csisolatingreek": 1, "ecma-118": 1,
|
||||
"elot_928": 1, "greek": 1, "greek8": 1, "iso-8859-7": 1, "iso-ir-126": 1,
|
||||
"iso8859-7": 1, "iso88597": 1, "iso_8859-7": 1, "iso_8859-7:1987": 1,
|
||||
"sun_eu_greek": 1, "csiso88598e": 1, "csisolatinhebrew": 1, "hebrew": 1,
|
||||
"iso-8859-8": 1, "iso-8859-8-e": 1, "iso-ir-138": 1, "iso8859-8": 1,
|
||||
"iso88598": 1, "iso_8859-8": 1, "iso_8859-8:1988": 1, "visual": 1,
|
||||
"csiso88598i": 1, "iso-8859-8-i": 1, "logical": 1, "csisolatin6": 1,
|
||||
"iso-8859-10": 1, "iso-ir-157": 1, "iso8859-10": 1, "iso885910": 1,
|
||||
"l6": 1, "latin6": 1, "iso-8859-13": 1, "iso8859-13": 1, "iso885913": 1,
|
||||
"iso-8859-14": 1, "iso8859-14": 1, "iso885914": 1, "csisolatin9": 1,
|
||||
"iso-8859-15": 1, "iso8859-15": 1, "iso885915": 1, "iso_8859-15": 1,
|
||||
"l9": 1, "iso-8859-16": 1, "cskoi8r": 1, "koi": 1, "koi8": 1, "koi8-r": 1,
|
||||
"koi8_r": 1, "koi8-u": 1, "csmacintosh": 1, "mac": 1, "macintosh": 1,
|
||||
"x-mac-roman": 1, "dos-874": 1, "iso-8859-11": 1, "iso8859-11": 1,
|
||||
"iso885911": 1, "tis-620": 1, "windows-874": 1, "cp1250": 1,
|
||||
"windows-1250": 1, "x-cp1250": 1, "cp1251": 1, "windows-1251": 1,
|
||||
"x-cp1251": 1, "ansi_x3.4-1968": 1, "ascii": 1, "cp1252": 1, "cp819": 1,
|
||||
"csisolatin1": 1, "ibm819": 1, "iso-8859-1": 1, "iso-ir-100": 1,
|
||||
"iso8859-1": 1, "iso88591": 1, "iso_8859-1": 1, "iso_8859-1:1987": 1,
|
||||
"l1": 1, "latin1": 1, "us-ascii": 1, "windows-1252": 1, "x-cp1252": 1,
|
||||
"cp1253": 1, "windows-1253": 1, "x-cp1253": 1, "cp1254": 1, "csisolatin5": 1,
|
||||
"iso-8859-9": 1, "iso-ir-148": 1, "iso8859-9": 1, "iso88599": 1,
|
||||
"iso_8859-9": 1, "iso_8859-9:1989": 1, "l5": 1, "latin5": 1,
|
||||
"windows-1254": 1, "x-cp1254": 1, "cp1255": 1, "windows-1255": 1,
|
||||
"x-cp1255": 1, "cp1256": 1, "windows-1256": 1, "x-cp1256": 1, "cp1257": 1,
|
||||
"windows-1257": 1, "x-cp1257": 1, "cp1258": 1, "windows-1258": 1,
|
||||
"x-cp1258": 1, "x-mac-cyrillic": 1, "x-mac-ukrainian": 1, "chinese": 1,
|
||||
"csgb2312": 1, "csiso58gb231280": 1, "gb2312": 1, "gb_2312": 1,
|
||||
"gb_2312-80": 1, "gbk": 1, "iso-ir-58": 1, "x-gbk": 1, "gb18030": 1,
|
||||
"hz-gb-2312": 1, "big5": 1, "big5-hkscs": 1, "cn-big5": 1, "csbig5": 1,
|
||||
"x-x-big5": 1, "cseucpkdfmtjapanese": 1, "euc-jp": 1, "x-euc-jp": 1,
|
||||
"csiso2022jp": 1, "iso-2022-jp": 1, "csshiftjis": 1, "ms_kanji": 1,
|
||||
"shift-jis": 1, "shift_jis": 1, "sjis": 1, "windows-31j": 1, "x-sjis": 1,
|
||||
"cseuckr": 1, "csksc56011987": 1, "euc-kr": 1, "iso-ir-149": 1, "korean": 1,
|
||||
"ks_c_5601-1987": 1, "ks_c_5601-1989": 1, "ksc5601": 1, "ksc_5601": 1,
|
||||
"windows-949": 1, "csiso2022kr": 1, "iso-2022-kr": 1, "utf-16": 1,
|
||||
"utf-16le": 1, "utf-16be": 1, "x-user-defined": 1 };
|
||||
|
@ -811,12 +811,7 @@ function readFile(path, encoding, callback) {
|
||||
let readStream = new ReadStream(path);
|
||||
readStream.on("data", function(data) {
|
||||
if (!buffer) buffer = data;
|
||||
else {
|
||||
let bufferred = buffer
|
||||
buffer = new Buffer(buffer.length + data.length);
|
||||
bufferred.copy(buffer, 0);
|
||||
data.copy(buffer, bufferred.length);
|
||||
}
|
||||
else buffer = Buffer.concat([buffer, data], 2);
|
||||
});
|
||||
readStream.on("error", function onError(error) {
|
||||
callback(error);
|
||||
|
@ -139,7 +139,7 @@ const StreamListener = Class({
|
||||
let stream = this.stream;
|
||||
let buffer = new ArrayBuffer(count);
|
||||
nsIBinaryInputStream(stream).readArrayBuffer(count, buffer);
|
||||
emit(stream, "data", new Buffer(buffer, stream.encoding));
|
||||
emit(stream, "data", new Buffer(buffer));
|
||||
},
|
||||
|
||||
// Next two methods implement `nsIRequestObserver` interface and are invoked
|
||||
|
@ -33,8 +33,20 @@ const Subject = Class({
|
||||
});
|
||||
|
||||
function emit(type, event) {
|
||||
let subject = 'subject' in event ? Subject(event.subject) : null;
|
||||
let data = 'data' in event ? event.data : null;
|
||||
// From bug 910599
|
||||
// We must test to see if 'subject' or 'data' is a defined property
|
||||
// of the event object, but also allow primitives to be passed in,
|
||||
// which the `in` operator breaks, yet `null` is an object, hence
|
||||
// the long conditional
|
||||
let subject = event && typeof event === 'object' && 'subject' in event ?
|
||||
Subject(event.subject) :
|
||||
null;
|
||||
let data = event && typeof event === 'object' ?
|
||||
// An object either returns its `data` property or null
|
||||
('data' in event ? event.data : null) :
|
||||
// All other types return themselves (and cast to strings/null
|
||||
// via observer service)
|
||||
event;
|
||||
notifyObservers(subject, type, data);
|
||||
}
|
||||
exports.emit = emit;
|
||||
|
@ -17,6 +17,7 @@ const { off, emit, setListeners } = require('../event/core');
|
||||
const { EventTarget } = require('../event/target');
|
||||
const { URL } = require('../url');
|
||||
const { add, remove, has, clear, iterator } = require('../lang/weak-set');
|
||||
const { id: addonID } = require('../self');
|
||||
const { WindowTracker } = require('../deprecated/window-utils');
|
||||
const { isShowing } = require('./sidebar/utils');
|
||||
const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../window/utils');
|
||||
@ -30,6 +31,8 @@ const { defer } = require('../core/promise');
|
||||
const { models, views, viewsFor, modelFor } = require('./sidebar/namespace');
|
||||
const { isLocalURL } = require('../url');
|
||||
const { ensure } = require('../system/unload');
|
||||
const { identify } = require('./id');
|
||||
const { uuid } = require('../util/uuid');
|
||||
|
||||
const Worker = WorkerTrait.resolve({
|
||||
_injectInDocument: '__injectInDocument'
|
||||
@ -47,9 +50,16 @@ const Sidebar = Class({
|
||||
implements: [ Disposable ],
|
||||
extends: EventTarget,
|
||||
setup: function(options) {
|
||||
// inital validation for the model information
|
||||
let model = sidebarContract(options);
|
||||
|
||||
// save the model information
|
||||
models.set(this, model);
|
||||
|
||||
// generate an id if one was not provided
|
||||
model.id = model.id || addonID + '-' + uuid();
|
||||
|
||||
// further validation for the title and url
|
||||
validateTitleAndURLCombo({}, this.title, this.url);
|
||||
|
||||
const self = this;
|
||||
@ -119,6 +129,7 @@ const Sidebar = Class({
|
||||
|
||||
emit(self, 'hide', {});
|
||||
emit(self, 'detach', worker);
|
||||
windowNS(window).worker = null;
|
||||
}
|
||||
windowNS(window).onWebPanelSidebarUnload = onWebPanelSidebarUnload;
|
||||
panelBrowser.contentWindow.addEventListener('unload', onWebPanelSidebarUnload, true);
|
||||
@ -126,6 +137,15 @@ const Sidebar = Class({
|
||||
// check the associated menuitem
|
||||
bar.setAttribute('checked', 'true');
|
||||
|
||||
function onWebPanelSidebarReady() {
|
||||
panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', onWebPanelSidebarReady, false);
|
||||
windowNS(window).onWebPanelSidebarReady = null;
|
||||
|
||||
emit(self, 'ready', worker);
|
||||
}
|
||||
windowNS(window).onWebPanelSidebarReady = onWebPanelSidebarReady;
|
||||
panelBrowser.contentWindow.addEventListener('DOMContentLoaded', onWebPanelSidebarReady, false);
|
||||
|
||||
function onWebPanelSidebarLoad() {
|
||||
panelBrowser.contentWindow.removeEventListener('load', onWebPanelSidebarLoad, true);
|
||||
windowNS(window).onWebPanelSidebarLoad = null;
|
||||
@ -173,6 +193,11 @@ const Sidebar = Class({
|
||||
windowNS(window).onWebPanelSidebarCreated = null;
|
||||
}
|
||||
|
||||
if (windowNS(window).onWebPanelSidebarReady) {
|
||||
panelBrowser && panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', windowNS(window).onWebPanelSidebarReady, false);
|
||||
windowNS(window).onWebPanelSidebarReady = null;
|
||||
}
|
||||
|
||||
if (windowNS(window).onWebPanelSidebarLoad) {
|
||||
panelBrowser && panelBrowser.contentWindow.removeEventListener('load', windowNS(window).onWebPanelSidebarLoad, true);
|
||||
windowNS(window).onWebPanelSidebarLoad = null;
|
||||
@ -180,7 +205,7 @@ const Sidebar = Class({
|
||||
|
||||
if (windowNS(window).onWebPanelSidebarUnload) {
|
||||
panelBrowser && panelBrowser.contentWindow.removeEventListener('unload', windowNS(window).onWebPanelSidebarUnload, true);
|
||||
windowNS(window).onWebPanelSidebarUnload = null;
|
||||
windowNS(window).onWebPanelSidebarUnload();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -208,10 +233,13 @@ const Sidebar = Class({
|
||||
// destroyed?
|
||||
if (!modelFor(this))
|
||||
return;
|
||||
|
||||
// validation
|
||||
if (!isLocalURL(v))
|
||||
throw Error('the url must be a valid local url');
|
||||
|
||||
validateTitleAndURLCombo(this, this.title, v);
|
||||
|
||||
// do update
|
||||
updateURL(this, v);
|
||||
modelFor(this).url = v;
|
||||
@ -260,6 +288,10 @@ isShowing.define(Sidebar, isSidebarShowing.bind(null, null));
|
||||
show.define(Sidebar, showSidebar.bind(null, null));
|
||||
hide.define(Sidebar, hideSidebar.bind(null, null));
|
||||
|
||||
identify.define(Sidebar, function(sidebar) {
|
||||
return sidebar.id;
|
||||
});
|
||||
|
||||
function toggleSidebar(window, sidebar) {
|
||||
// TODO: make sure this is not private
|
||||
window = window || getMostRecentBrowserWindow();
|
||||
|
@ -9,7 +9,7 @@ const { isNil, isObject, isString } = require('../../lang/type');
|
||||
|
||||
exports.contract = contract({
|
||||
id: {
|
||||
is: [ 'string' ],
|
||||
is: [ 'string', 'undefined' ],
|
||||
ok: v => /^[a-z0-9-_]+$/i.test(v),
|
||||
msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' +
|
||||
'underscores are allowed).'
|
||||
@ -22,6 +22,6 @@ exports.contract = contract({
|
||||
is: [ 'string' ],
|
||||
ok: v => isLocalURL(v),
|
||||
map: function(v) v.toString(),
|
||||
msg: 'The option "url" must be a valid URI.'
|
||||
msg: 'The option "url" must be a valid local URI.'
|
||||
}
|
||||
});
|
||||
|
@ -72,7 +72,15 @@ function updateTitle(sidebar, title) {
|
||||
exports.updateTitle = updateTitle;
|
||||
|
||||
function updateURL(sidebar, url) {
|
||||
let eleID = makeID(sidebar.id);
|
||||
|
||||
for (let window of windows(null, { includePrivate: true })) {
|
||||
// update the menuitem
|
||||
let mi = window.document.getElementById(eleID);
|
||||
if (mi) {
|
||||
mi.setAttribute('sidebarurl', url)
|
||||
}
|
||||
|
||||
// update sidebar, if showing
|
||||
if (isSidebarShowing(window, sidebar)) {
|
||||
showSidebar(window, sidebar, url);
|
||||
@ -134,7 +142,10 @@ function showSidebar(window, sidebar, newURL) {
|
||||
let { promise, resolve, reject } = defer();
|
||||
let model = modelFor(sidebar);
|
||||
|
||||
if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
|
||||
if (!newURL && isSidebarShowing(window, sidebar)) {
|
||||
resolve({});
|
||||
}
|
||||
else if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
|
||||
reject(Error('You cannot show a sidebar on private windows'));
|
||||
}
|
||||
else {
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
const { defer } = require('../core/promise');
|
||||
const events = require('../system/events');
|
||||
const { setImmediate } = require('../timers');
|
||||
const { open: openWindow, onFocus, getToplevelWindow,
|
||||
isInteractive } = require('./utils');
|
||||
isInteractive, getOuterId } = require('./utils');
|
||||
const { Ci } = require("chrome");
|
||||
|
||||
function open(uri, options) {
|
||||
return promise(openWindow.apply(null, arguments), 'load');
|
||||
@ -15,19 +15,14 @@ function open(uri, options) {
|
||||
exports.open = open;
|
||||
|
||||
function close(window) {
|
||||
// We shouldn't wait for unload, as it is dispatched
|
||||
// before the window is actually closed. 'domwindowclosed' isn't great either,
|
||||
// because it's fired midway through window teardown (see bug 874502
|
||||
// comment 15). We could go with xul-window-destroyed, but _that_ doesn't
|
||||
// provide us with a subject by which to disambiguate notifications. So we
|
||||
// end up just doing the dumb thing and round-tripping through the event loop
|
||||
// with setImmediate.
|
||||
let deferred = defer();
|
||||
let toplevelWindow = getToplevelWindow(window);
|
||||
events.on("domwindowclosed", function onclose({subject}) {
|
||||
if (subject == toplevelWindow) {
|
||||
events.off("domwindowclosed", onclose);
|
||||
setImmediate(function() deferred.resolve(window));
|
||||
let outerId = getOuterId(toplevelWindow);
|
||||
events.on("outer-window-destroyed", function onclose({subject}) {
|
||||
let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (id == outerId) {
|
||||
events.off("outer-window-destroyed", onclose);
|
||||
deferred.resolve();
|
||||
}
|
||||
}, true);
|
||||
window.close();
|
||||
|
@ -297,8 +297,7 @@ function windows(type, options) {
|
||||
let window = winEnum.getNext().QueryInterface(Ci.nsIDOMWindow);
|
||||
// Only add non-private windows when pb permission isn't set,
|
||||
// unless an option forces the addition of them.
|
||||
// XXXbz should this be checking window.closed?
|
||||
if (options.includePrivate || !isWindowPrivate(window)) {
|
||||
if (!window.closed && (options.includePrivate || !isWindowPrivate(window))) {
|
||||
list.push(window);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
const { notifyObservers } = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
|
||||
// Define some shortcuts.
|
||||
const bind = Function.call.bind(Function.bind);
|
||||
@ -157,6 +158,18 @@ var serializeStack = iced(function serializeStack(frames) {
|
||||
})
|
||||
exports.serializeStack = serializeStack
|
||||
|
||||
function readURI(uri) {
|
||||
let stream = NetUtil.newChannel(uri, 'UTF-8', null).open();
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, {
|
||||
charset: 'UTF-8'
|
||||
});
|
||||
|
||||
stream.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Function takes set of options and returns a JS sandbox. Function may be
|
||||
// passed set of options:
|
||||
// - `name`: A string value which identifies the sandbox in about:memory. Will
|
||||
@ -313,7 +326,11 @@ exports.load = load;
|
||||
// Utility function to check if id is relative.
|
||||
function isRelative(id) { return id[0] === '.'; }
|
||||
// Utility function to normalize module `uri`s so they have `.js` extension.
|
||||
function normalize(uri) { return uri.substr(-3) === '.js' ? uri : uri + '.js'; }
|
||||
function normalize(uri) {
|
||||
return isJSURI(uri) ? uri :
|
||||
isJSONURI(uri) ? uri :
|
||||
uri + '.js';
|
||||
}
|
||||
// Utility function to join paths. In common case `base` is a
|
||||
// `requirer.uri` but in some cases it may be `baseURI`. In order to
|
||||
// avoid complexity we require `baseURI` with a trailing `/`.
|
||||
@ -371,9 +388,31 @@ const Require = iced(function Require(loader, requirer) {
|
||||
if (uri in modules) {
|
||||
module = modules[uri];
|
||||
}
|
||||
// Otherwise load and cache it. We also freeze module to prevent it from
|
||||
// further changes at runtime.
|
||||
else {
|
||||
else if (isJSONURI(uri)) {
|
||||
let data;
|
||||
|
||||
// First attempt to load and parse json uri
|
||||
// ex: `test.json`
|
||||
// If that doesn't exist, check for `test.json.js`
|
||||
// for node parity
|
||||
try {
|
||||
data = JSON.parse(readURI(uri));
|
||||
module = modules[uri] = Module(requirement, uri);
|
||||
module.exports = data;
|
||||
freeze(module);
|
||||
}
|
||||
catch (err) {
|
||||
// If error thrown from JSON parsing, throw that, do not
|
||||
// attempt to find .json.js file
|
||||
if (err && /JSON\.parse/.test(err.message))
|
||||
throw err;
|
||||
uri = uri + '.js';
|
||||
}
|
||||
}
|
||||
// If not yet cached, load and cache it.
|
||||
// We also freeze module to prevent it from further changes
|
||||
// at runtime.
|
||||
if (!(uri in modules)) {
|
||||
module = modules[uri] = Module(requirement, uri);
|
||||
freeze(load(loader, module));
|
||||
}
|
||||
@ -504,5 +543,8 @@ const Loader = iced(function Loader(options) {
|
||||
});
|
||||
exports.Loader = Loader;
|
||||
|
||||
let isJSONURI = uri => uri.substr(-5) === '.json';
|
||||
let isJSURI = uri => uri.substr(-3) === '.js';
|
||||
|
||||
});
|
||||
|
||||
|
@ -172,7 +172,7 @@ parser_groups = (
|
||||
(("", "--strip-sdk",), dict(dest="bundle_sdk",
|
||||
help=("Do not ship SDK modules in the xpi"),
|
||||
action="store_false",
|
||||
default=True,
|
||||
default=False,
|
||||
cmds=['run', 'test', 'testex', 'testpkgs',
|
||||
'testall', 'xpi'])),
|
||||
(("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk",
|
||||
@ -554,7 +554,7 @@ def initializer(env_root, args, out=sys.stdout, err=sys.stderr):
|
||||
jid = create_jid()
|
||||
print >>out, '* generated jID automatically:', jid
|
||||
open(os.path.join(path,'package.json'),'w').write(PACKAGE_JSON % {'name':addon.lower(),
|
||||
'fullName':addon,
|
||||
'title':addon,
|
||||
'id':jid })
|
||||
print >>out, '* package.json written'
|
||||
open(os.path.join(path,'test','test-main.js'),'w').write(TEST_MAIN_JS)
|
||||
@ -568,7 +568,7 @@ def initializer(env_root, args, out=sys.stdout, err=sys.stderr):
|
||||
print >>out, 'Do "cfx test" to test it and "cfx run" to try it. Have fun!'
|
||||
else:
|
||||
print >>out, '\nYour sample add-on is now ready in the \'' + args[1] + '\' directory.'
|
||||
print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it. Have fun!'
|
||||
print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it. Have fun!'
|
||||
return {"result":0, "jid":jid}
|
||||
|
||||
def buildJID(target_cfg):
|
||||
@ -597,7 +597,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
(options, args) = parse_args(**parser_kwargs)
|
||||
|
||||
config_args = get_config_args(options.config, env_root);
|
||||
|
||||
|
||||
# reparse configs with arguments from local.json
|
||||
if config_args:
|
||||
parser_kwargs['arguments'] += config_args
|
||||
|
@ -606,9 +606,13 @@ class ManifestBuilder:
|
||||
filename = os.sep.join(name.split("/"))
|
||||
# normalize filename, make sure that we do not add .js if it already has
|
||||
# it.
|
||||
if not filename.endswith(".js"):
|
||||
if not filename.endswith(".js") and not filename.endswith(".json"):
|
||||
filename += ".js"
|
||||
basename = filename[:-3]
|
||||
|
||||
if filename.endswith(".js"):
|
||||
basename = filename[:-3]
|
||||
if filename.endswith(".json"):
|
||||
basename = filename[:-5]
|
||||
|
||||
pkg = self.pkg_cfg.packages[pkgname]
|
||||
if isinstance(sections, basestring):
|
||||
|
@ -122,7 +122,7 @@ def gen_manifest(template_root_dir, target_cfg, jid,
|
||||
manifest.set("em:version",
|
||||
target_cfg.get('version', '1.0'))
|
||||
manifest.set("em:name",
|
||||
target_cfg.get('fullName', target_cfg['name']))
|
||||
target_cfg.get('title', target_cfg.get('fullName', target_cfg['name'])))
|
||||
manifest.set("em:description",
|
||||
target_cfg.get("description", ""))
|
||||
manifest.set("em:creator",
|
||||
|
@ -22,7 +22,7 @@ require("sdk/test").run(exports);
|
||||
PACKAGE_JSON = '''\
|
||||
{
|
||||
"name": "%(name)s",
|
||||
"fullName": "%(fullName)s",
|
||||
"title": "%(title)s",
|
||||
"id": "%(id)s",
|
||||
"description": "a basic add-on",
|
||||
"author": "",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"fullName": "empty",
|
||||
"title": "empty",
|
||||
"id": "jid1-80fr8b6qeRlQSQ",
|
||||
"unpack": false,
|
||||
"description": "test unpack= support"
|
||||
|
@ -3,7 +3,7 @@
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"fullName": "empty",
|
||||
"title": "empty",
|
||||
"id": "jid1-80fr8b6qeRlQSQ",
|
||||
"unpack": true,
|
||||
"description": "test unpack= support"
|
||||
|
@ -3,7 +3,7 @@
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"fullName": "empty",
|
||||
"title": "empty",
|
||||
"id": "jid1-80fr8b6qeRlQSQ",
|
||||
"description": "test unpack= support"
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "empty",
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"fullName": "a long fullName",
|
||||
"id": "jid1-80123",
|
||||
"description": "test addon name fallback to 'fullName' key"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "a long none",
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
|
||||
"id": "jid1-80123",
|
||||
"description": "test addon name falls back all the way to the 'name' key"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "empty",
|
||||
"license": "MPL 2.0",
|
||||
"author": "",
|
||||
"version": "0.1",
|
||||
"title": "a long title",
|
||||
"id": "jid1-80123",
|
||||
"description": "test addon name comes from the 'title' key"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "jid1-fZHqN9JfrDBa8A",
|
||||
"fullName": "No Prefs Test",
|
||||
"title": "No Prefs Test",
|
||||
"author": "Erik Vold",
|
||||
"loader": "lib/main.js"
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "jid1-fZHqN9JfrDBa8A",
|
||||
"fullName": "Simple Prefs Test",
|
||||
"title": "Simple Prefs Test",
|
||||
"author": "Erik Vold",
|
||||
"preferences": [{
|
||||
"name": "test",
|
||||
|
@ -48,7 +48,7 @@ class TestInit(unittest.TestCase):
|
||||
self.assertEqual(open(main_js,"r").read(),"")
|
||||
self.assertEqual(open(package_json,"r").read() % {"id":"tmp_addon_id" },
|
||||
PACKAGE_JSON % {"name":"tmp_addon_sample",
|
||||
"fullName": "tmp_addon_SAMPLE",
|
||||
"title": "tmp_addon_SAMPLE",
|
||||
"id":init_run["jid"] })
|
||||
self.assertEqual(open(test_main_js,"r").read(),TEST_MAIN_JS)
|
||||
|
||||
|
@ -188,16 +188,13 @@ class Contents(unittest.TestCase):
|
||||
self.failUnlessEqual(e.args[0], 0)
|
||||
zf = zipfile.ZipFile("seven.xpi", "r")
|
||||
names = zf.namelist()
|
||||
# the first problem found in bug 664840 was that cuddlefish.js
|
||||
# (the loader) was stripped out on windows, due to a /-vs-\ bug
|
||||
self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names)
|
||||
# the second problem found in bug 664840 was that an addon
|
||||
# problem found in bug 664840 was that an addon
|
||||
# without an explicit tests/ directory would copy all files from
|
||||
# the package into a bogus JID-PKGNAME-tests/ directory, so check
|
||||
# for that
|
||||
testfiles = [fn for fn in names if "seven/tests" in fn]
|
||||
self.failUnlessEqual([], testfiles)
|
||||
# the third problem was that data files were being stripped from
|
||||
# another problem was that data files were being stripped from
|
||||
# the XPI. Note that data/ is only supposed to be included if a
|
||||
# module that actually gets used does a require("self") .
|
||||
self.assertIn("resources/seven/data/text.data",
|
||||
|
@ -41,5 +41,14 @@ class RDFTests(unittest.TestCase):
|
||||
self.failUnlessEqual(m.get("em:unpack"), "true")
|
||||
self.failUnlessIn("<em:unpack>true</em:unpack>", str(m), n)
|
||||
|
||||
def testTitle(self):
|
||||
basedir = os.path.join(test_dir, 'bug-906359-files')
|
||||
for n in ['title', 'fullName', 'none']:
|
||||
cfg = packaging.get_config_in_dir(os.path.join(basedir, n))
|
||||
m = rdf.gen_manifest(template_dir, cfg, jid='JID')
|
||||
self.failUnlessEqual(m.get('em:name'), 'a long ' + n)
|
||||
self.failUnlessIn('<em:name>a long ' + n + '</em:name>', str(m), n)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -49,7 +49,7 @@ class PrefsTests(unittest.TestCase):
|
||||
|
||||
xulNamespacePrefix = \
|
||||
"{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"
|
||||
|
||||
|
||||
settings = root.findall(xulNamespacePrefix + 'setting')
|
||||
|
||||
def assertPref(setting, name, prefType, title):
|
||||
@ -74,7 +74,7 @@ class PrefsTests(unittest.TestCase):
|
||||
def assertOption(option, value, label):
|
||||
self.failUnlessEqual(option.get('value'), value)
|
||||
self.failUnlessEqual(option.get('label'), label)
|
||||
|
||||
|
||||
assertOption(menuItems[0], "0", "label1")
|
||||
assertOption(menuItems[1], "1", "label2")
|
||||
assertOption(radios[0], "red", "rouge")
|
||||
@ -257,7 +257,6 @@ class SmallXPI(unittest.TestCase):
|
||||
"defaults/preferences/prefs.js",
|
||||
"resources/",
|
||||
"resources/addon-sdk/",
|
||||
"resources/addon-sdk/data/",
|
||||
"resources/addon-sdk/lib/",
|
||||
"resources/addon-sdk/lib/sdk/",
|
||||
"resources/addon-sdk/lib/sdk/self.js",
|
||||
|
@ -164,4 +164,4 @@ exports['test that malformed uri is not an addon-page'] = function(assert, done)
|
||||
});
|
||||
};
|
||||
|
||||
require('test').run(exports);
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
3
addon-sdk/source/test/addons/addon-page/package.json
Normal file
3
addon-sdk/source/test/addons/addon-page/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"id": "test-addon-page"
|
||||
}
|
24
addon-sdk/source/test/addons/places/main.js
Normal file
24
addon-sdk/source/test/addons/places/main.js
Normal file
@ -0,0 +1,24 @@
|
||||
/* 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';
|
||||
|
||||
module.metadata = {
|
||||
'engines': {
|
||||
'Firefox': '*'
|
||||
}
|
||||
};
|
||||
|
||||
const { safeMerge: merge } = require('sdk/util/object');
|
||||
|
||||
merge(module.exports,
|
||||
require('./tests/test-places-bookmarks'),
|
||||
require('./tests/test-places-events'),
|
||||
require('./tests/test-places-favicon'),
|
||||
require('./tests/test-places-history'),
|
||||
require('./tests/test-places-host'),
|
||||
require('./tests/test-places-utils')
|
||||
);
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
3
addon-sdk/source/test/addons/places/package.json
Normal file
3
addon-sdk/source/test/addons/places/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"id": "test-places"
|
||||
}
|
@ -28,7 +28,7 @@ const {
|
||||
invalidResolve, invalidReject, createTree,
|
||||
compareWithHost, createBookmark, createBookmarkItem,
|
||||
createBookmarkTree, addVisits, resetPlaces
|
||||
} = require('./places-helper');
|
||||
} = require('../places-helper');
|
||||
const { promisedEmitter } = require('sdk/places/utils');
|
||||
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
@ -963,5 +963,3 @@ function delayed (value, ms) {
|
||||
setTimeout(() => resolve(value), ms || 10);
|
||||
return promise;
|
||||
}
|
||||
|
||||
require('test').run(exports);
|
@ -23,7 +23,7 @@ const {
|
||||
invalidResolve, invalidReject, createTree, createBookmark,
|
||||
compareWithHost, addVisits, resetPlaces, createBookmarkItem,
|
||||
removeVisits
|
||||
} = require('./places-helper');
|
||||
} = require('../places-helper');
|
||||
const { save, MENU, UNSORTED } = require('sdk/places/bookmarks');
|
||||
const { promisedEmitter } = require('sdk/places/utils');
|
||||
|
||||
@ -289,4 +289,3 @@ function makeCompleted (done, countTo) {
|
||||
if (++count === countTo) done();
|
||||
};
|
||||
}
|
||||
require('sdk/test').run(exports);
|
@ -16,10 +16,10 @@ const tabs = require('sdk/tabs');
|
||||
const open = tabs.open;
|
||||
const port = 8099;
|
||||
const host = 'http://localhost:' + port;
|
||||
const { onFaviconChange, serve, binFavicon } = require('./favicon-helpers');
|
||||
const { onFaviconChange, serve, binFavicon } = require('../favicon-helpers');
|
||||
const { once } = require('sdk/system/events');
|
||||
const { defer } = require('sdk/core/promise');
|
||||
const { resetPlaces } = require('./places-helper');
|
||||
const { resetPlaces } = require('../places-helper');
|
||||
const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
|
||||
@ -186,5 +186,3 @@ function complete(tab, srv, done) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
require("test").run(exports);
|
@ -21,7 +21,7 @@ const {
|
||||
const {
|
||||
invalidResolve, invalidReject, createTree,
|
||||
compareWithHost, addVisits, resetPlaces
|
||||
} = require('./places-helper');
|
||||
} = require('../places-helper');
|
||||
const { promisedEmitter } = require('sdk/places/utils');
|
||||
|
||||
exports.testEmptyQuery = function (assert, done) {
|
||||
@ -247,5 +247,3 @@ function searchP () {
|
||||
|
||||
before(exports, (name, assert, done) => resetPlaces(done));
|
||||
after(exports, (name, assert, done) => resetPlaces(done));
|
||||
|
||||
require('test').run(exports);
|
@ -23,7 +23,7 @@ require('sdk/places/host/host-query');
|
||||
const {
|
||||
invalidResolve, invalidReject, createTree,
|
||||
compareWithHost, createBookmark, createBookmarkTree, resetPlaces
|
||||
} = require('./places-helper');
|
||||
} = require('../places-helper');
|
||||
|
||||
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
@ -301,5 +301,3 @@ exports.testGetAllChildren = function (assert, done) {
|
||||
|
||||
before(exports, (name, assert, done) => resetPlaces(done));
|
||||
after(exports, (name, assert, done) => resetPlaces(done));
|
||||
|
||||
require('test').run(exports);
|
@ -77,5 +77,3 @@ exports['test async walk'] = function (assert, done) {
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
require('test').run(exports);
|
1
addon-sdk/source/test/addons/self/data/data.md
Normal file
1
addon-sdk/source/test/addons/self/data/data.md
Normal file
@ -0,0 +1 @@
|
||||
# hello world
|
20
addon-sdk/source/test/addons/self/main.js
Normal file
20
addon-sdk/source/test/addons/self/main.js
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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 self = require("sdk/self");
|
||||
|
||||
exports["test self.data.load"] = assert => {
|
||||
|
||||
assert.equal(self.data.load("data.md"),
|
||||
"# hello world\n",
|
||||
"paths work");
|
||||
|
||||
assert.equal(self.data.load("./data.md"),
|
||||
"# hello world\n",
|
||||
"relative paths work");
|
||||
};
|
||||
|
||||
require("sdk/test/runner").runTestsFromModule(module);
|
3
addon-sdk/source/test/addons/self/package.json
Normal file
3
addon-sdk/source/test/addons/self/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"id": "test-self"
|
||||
}
|
39
addon-sdk/source/test/addons/symbiont/main.js
Normal file
39
addon-sdk/source/test/addons/symbiont/main.js
Normal file
@ -0,0 +1,39 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { data } = require("sdk/self");
|
||||
const { Symbiont } = require("sdk/content/symbiont");
|
||||
|
||||
exports["test:direct communication with trusted document"] = function(assert, done) {
|
||||
let worker = Symbiont({
|
||||
contentURL: data.url("test-trusted-document.html")
|
||||
});
|
||||
|
||||
worker.port.on('document-to-addon', function (arg) {
|
||||
assert.equal(arg, "ok", "Received an event from the document");
|
||||
worker.destroy();
|
||||
done();
|
||||
});
|
||||
worker.port.emit('addon-to-document', 'ok');
|
||||
};
|
||||
|
||||
exports["test:`addon` is not available when a content script is set"] = function(assert, done) {
|
||||
let worker = Symbiont({
|
||||
contentURL: data.url("test-trusted-document.html"),
|
||||
contentScript: "new " + function ContentScriptScope() {
|
||||
self.port.emit("cs-to-addon", "addon" in unsafeWindow);
|
||||
}
|
||||
});
|
||||
|
||||
worker.port.on('cs-to-addon', function (hasAddon) {
|
||||
assert.equal(hasAddon, false,
|
||||
"`addon` is not available");
|
||||
worker.destroy();
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
require("sdk/test/runner").runTestsFromModule(module);
|
3
addon-sdk/source/test/addons/symbiont/package.json
Normal file
3
addon-sdk/source/test/addons/symbiont/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"id": "test-symbiont"
|
||||
}
|
368
addon-sdk/source/test/buffers/test-read-types.js
Normal file
368
addon-sdk/source/test/buffers/test-read-types.js
Normal file
@ -0,0 +1,368 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
const { Buffer } = require('sdk/io/buffer');
|
||||
|
||||
exports.testReadDouble = helper('readDoubleLE/readDoubleBE', function (assert) {
|
||||
var buffer = new Buffer(8);
|
||||
|
||||
buffer[0] = 0x55;
|
||||
buffer[1] = 0x55;
|
||||
buffer[2] = 0x55;
|
||||
buffer[3] = 0x55;
|
||||
buffer[4] = 0x55;
|
||||
buffer[5] = 0x55;
|
||||
buffer[6] = 0xd5;
|
||||
buffer[7] = 0x3f;
|
||||
assert.equal(1.1945305291680097e+103, buffer.readDoubleBE(0));
|
||||
assert.equal(0.3333333333333333, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[0] = 1;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x3f;
|
||||
assert.equal(7.291122019655968e-304, buffer.readDoubleBE(0));
|
||||
assert.equal(1.0000000000000002, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[0] = 2;
|
||||
assert.equal(4.778309726801735e-299, buffer.readDoubleBE(0));
|
||||
assert.equal(1.0000000000000004, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[0] = 1;
|
||||
buffer[6] = 0;
|
||||
buffer[7] = 0;
|
||||
assert.equal(7.291122019556398e-304, buffer.readDoubleBE(0));
|
||||
assert.equal(5e-324, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xff;
|
||||
buffer[2] = 0xff;
|
||||
buffer[3] = 0xff;
|
||||
buffer[4] = 0xff;
|
||||
buffer[5] = 0xff;
|
||||
buffer[6] = 0x0f;
|
||||
buffer[7] = 0x00;
|
||||
assert.ok(isNaN(buffer.readDoubleBE(0)));
|
||||
assert.equal(2.225073858507201e-308, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[6] = 0xef;
|
||||
buffer[7] = 0x7f;
|
||||
assert.ok(isNaN(buffer.readDoubleBE(0)));
|
||||
assert.equal(1.7976931348623157e+308, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x3f;
|
||||
assert.equal(3.03865e-319, buffer.readDoubleBE(0));
|
||||
assert.equal(1, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[6] = 0;
|
||||
buffer[7] = 0x40;
|
||||
assert.equal(3.16e-322, buffer.readDoubleBE(0));
|
||||
assert.equal(2, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[7] = 0xc0;
|
||||
assert.equal(9.5e-322, buffer.readDoubleBE(0));
|
||||
assert.equal(-2, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[6] = 0x10;
|
||||
buffer[7] = 0;
|
||||
assert.equal(2.0237e-320, buffer.readDoubleBE(0));
|
||||
assert.equal(2.2250738585072014e-308, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[6] = 0;
|
||||
assert.equal(0, buffer.readDoubleBE(0));
|
||||
assert.equal(0, buffer.readDoubleLE(0));
|
||||
assert.equal(false, 1 / buffer.readDoubleLE(0) < 0);
|
||||
|
||||
buffer[7] = 0x80;
|
||||
assert.equal(6.3e-322, buffer.readDoubleBE(0));
|
||||
assert.equal(0, buffer.readDoubleLE(0));
|
||||
assert.equal(true, 1 / buffer.readDoubleLE(0) < 0);
|
||||
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x7f;
|
||||
assert.equal(3.0418e-319, buffer.readDoubleBE(0));
|
||||
assert.equal(Infinity, buffer.readDoubleLE(0));
|
||||
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0xff;
|
||||
assert.equal(3.04814e-319, buffer.readDoubleBE(0));
|
||||
assert.equal(-Infinity, buffer.readDoubleLE(0));
|
||||
});
|
||||
|
||||
|
||||
exports.testReadFloat = helper('readFloatLE/readFloatBE', function (assert) {
|
||||
var buffer = new Buffer(4);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0x3f;
|
||||
assert.equal(4.600602988224807e-41, buffer.readFloatBE(0));
|
||||
assert.equal(1, buffer.readFloatLE(0));
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0xc0;
|
||||
assert.equal(2.6904930515036488e-43, buffer.readFloatBE(0));
|
||||
assert.equal(-2, buffer.readFloatLE(0));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xff;
|
||||
buffer[2] = 0x7f;
|
||||
buffer[3] = 0x7f;
|
||||
assert.ok(isNaN(buffer.readFloatBE(0)));
|
||||
assert.equal(3.4028234663852886e+38, buffer.readFloatLE(0));
|
||||
|
||||
buffer[0] = 0xab;
|
||||
buffer[1] = 0xaa;
|
||||
buffer[2] = 0xaa;
|
||||
buffer[3] = 0x3e;
|
||||
assert.equal(-1.2126478207002966e-12, buffer.readFloatBE(0));
|
||||
assert.equal(0.3333333432674408, buffer.readFloatLE(0));
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
assert.equal(0, buffer.readFloatBE(0));
|
||||
assert.equal(0, buffer.readFloatLE(0));
|
||||
assert.equal(false, 1 / buffer.readFloatLE(0) < 0);
|
||||
|
||||
buffer[3] = 0x80;
|
||||
assert.equal(1.793662034335766e-43, buffer.readFloatBE(0));
|
||||
assert.equal(0, buffer.readFloatLE(0));
|
||||
assert.equal(true, 1 / buffer.readFloatLE(0) < 0);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0x7f;
|
||||
assert.equal(4.609571298396486e-41, buffer.readFloatBE(0));
|
||||
assert.equal(Infinity, buffer.readFloatLE(0));
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0xff;
|
||||
assert.equal(4.627507918739843e-41, buffer.readFloatBE(0));
|
||||
assert.equal(-Infinity, buffer.readFloatLE(0));
|
||||
});
|
||||
|
||||
|
||||
exports.testReadInt8 = helper('readInt8', function (assert) {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data[0] = 0x23;
|
||||
assert.equal(0x23, data.readInt8(0));
|
||||
|
||||
data[0] = 0xff;
|
||||
assert.equal(-1, data.readInt8(0));
|
||||
|
||||
data[0] = 0x87;
|
||||
data[1] = 0xab;
|
||||
data[2] = 0x7c;
|
||||
data[3] = 0xef;
|
||||
assert.equal(-121, data.readInt8(0));
|
||||
assert.equal(-85, data.readInt8(1));
|
||||
assert.equal(124, data.readInt8(2));
|
||||
assert.equal(-17, data.readInt8(3));
|
||||
});
|
||||
|
||||
|
||||
exports.testReadInt16 = helper('readInt16BE/readInt16LE', function (assert) {
|
||||
var buffer = new Buffer(6);
|
||||
|
||||
buffer[0] = 0x16;
|
||||
buffer[1] = 0x79;
|
||||
assert.equal(0x1679, buffer.readInt16BE(0));
|
||||
assert.equal(0x7916, buffer.readInt16LE(0));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0x80;
|
||||
assert.equal(-128, buffer.readInt16BE(0));
|
||||
assert.equal(-32513, buffer.readInt16LE(0));
|
||||
|
||||
/* test offset with weenix */
|
||||
buffer[0] = 0x77;
|
||||
buffer[1] = 0x65;
|
||||
buffer[2] = 0x65;
|
||||
buffer[3] = 0x6e;
|
||||
buffer[4] = 0x69;
|
||||
buffer[5] = 0x78;
|
||||
assert.equal(0x7765, buffer.readInt16BE(0));
|
||||
assert.equal(0x6565, buffer.readInt16BE(1));
|
||||
assert.equal(0x656e, buffer.readInt16BE(2));
|
||||
assert.equal(0x6e69, buffer.readInt16BE(3));
|
||||
assert.equal(0x6978, buffer.readInt16BE(4));
|
||||
assert.equal(0x6577, buffer.readInt16LE(0));
|
||||
assert.equal(0x6565, buffer.readInt16LE(1));
|
||||
assert.equal(0x6e65, buffer.readInt16LE(2));
|
||||
assert.equal(0x696e, buffer.readInt16LE(3));
|
||||
assert.equal(0x7869, buffer.readInt16LE(4));
|
||||
});
|
||||
|
||||
|
||||
exports.testReadInt32 = helper('readInt32BE/readInt32LE', function (assert) {
|
||||
var buffer = new Buffer(6);
|
||||
|
||||
buffer[0] = 0x43;
|
||||
buffer[1] = 0x53;
|
||||
buffer[2] = 0x16;
|
||||
buffer[3] = 0x79;
|
||||
assert.equal(0x43531679, buffer.readInt32BE(0));
|
||||
assert.equal(0x79165343, buffer.readInt32LE(0));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xfe;
|
||||
buffer[2] = 0xef;
|
||||
buffer[3] = 0xfa;
|
||||
assert.equal(-69638, buffer.readInt32BE(0));
|
||||
assert.equal(-84934913, buffer.readInt32LE(0));
|
||||
|
||||
buffer[0] = 0x42;
|
||||
buffer[1] = 0xc3;
|
||||
buffer[2] = 0x95;
|
||||
buffer[3] = 0xa9;
|
||||
buffer[4] = 0x36;
|
||||
buffer[5] = 0x17;
|
||||
assert.equal(0x42c395a9, buffer.readInt32BE(0));
|
||||
assert.equal(-1013601994, buffer.readInt32BE(1));
|
||||
assert.equal(-1784072681, buffer.readInt32BE(2));
|
||||
assert.equal(-1449802942, buffer.readInt32LE(0));
|
||||
assert.equal(917083587, buffer.readInt32LE(1));
|
||||
assert.equal(389458325, buffer.readInt32LE(2));
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* We need to check the following things:
|
||||
* - We are correctly resolving big endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly resolving little endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
exports.testReadUInt8 = helper('readUInt8', function (assert) {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data[0] = 23;
|
||||
data[1] = 23;
|
||||
data[2] = 23;
|
||||
data[3] = 23;
|
||||
assert.equal(23, data.readUInt8(0));
|
||||
assert.equal(23, data.readUInt8(1));
|
||||
assert.equal(23, data.readUInt8(2));
|
||||
assert.equal(23, data.readUInt8(3));
|
||||
|
||||
data[0] = 255; /* If it became a signed int, would be -1 */
|
||||
assert.equal(255, data.readUInt8(0));
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
|
||||
* now some of the issues actually matter:
|
||||
* - We are correctly resolving big endian
|
||||
* - Correctly resolving little endian
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
exports.testReadUInt16 = helper('readUInt16LE/readUInt16BE', function (assert) {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data[0] = 0;
|
||||
data[1] = 0x23;
|
||||
data[2] = 0x42;
|
||||
data[3] = 0x3f;
|
||||
assert.equal(0x23, data.readUInt16BE(0));
|
||||
assert.equal(0x2342, data.readUInt16BE(1));
|
||||
assert.equal(0x423f, data.readUInt16BE(2));
|
||||
assert.equal(0x2300, data.readUInt16LE(0));
|
||||
assert.equal(0x4223, data.readUInt16LE(1));
|
||||
assert.equal(0x3f42, data.readUInt16LE(2));
|
||||
|
||||
data[0] = 0xfe;
|
||||
data[1] = 0xfe;
|
||||
assert.equal(0xfefe, data.readUInt16BE(0));
|
||||
assert.equal(0xfefe, data.readUInt16LE(0));
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
|
||||
* now some of the issues actually matter:
|
||||
* - We are correctly resolving big endian
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
exports.testReadUInt32 = helper('readUInt32LE/readUInt32BE', function (assert) {
|
||||
var data = new Buffer(8);
|
||||
|
||||
data[0] = 0x32;
|
||||
data[1] = 0x65;
|
||||
data[2] = 0x42;
|
||||
data[3] = 0x56;
|
||||
data[4] = 0x23;
|
||||
data[5] = 0xff;
|
||||
assert.equal(0x32654256, data.readUInt32BE(0));
|
||||
assert.equal(0x65425623, data.readUInt32BE(1));
|
||||
assert.equal(0x425623ff, data.readUInt32BE(2));
|
||||
assert.equal(0x56426532, data.readUInt32LE(0));
|
||||
assert.equal(0x23564265, data.readUInt32LE(1));
|
||||
assert.equal(0xff235642, data.readUInt32LE(2));
|
||||
});
|
||||
|
||||
function helper (description, fn) {
|
||||
let bulkAssert = {
|
||||
equal: function (a, b) {
|
||||
if (a !== b) throw new Error('Error found in ' + description);
|
||||
},
|
||||
ok: function (value) {
|
||||
if (!value) throw new Error('Error found in ' + description);
|
||||
},
|
||||
throws: function (shouldThrow) {
|
||||
let didItThrow = false;
|
||||
try {
|
||||
shouldThrow();
|
||||
} catch (e) {
|
||||
didItThrow = e;
|
||||
}
|
||||
if (!didItThrow)
|
||||
throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
|
||||
}
|
||||
};
|
||||
return function (assert) {
|
||||
fn(bulkAssert);
|
||||
// If we get here, no errors thrown
|
||||
assert.pass('All tests passed for ' + description);
|
||||
};
|
||||
}
|
602
addon-sdk/source/test/buffers/test-write-types.js
Normal file
602
addon-sdk/source/test/buffers/test-write-types.js
Normal file
@ -0,0 +1,602 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
const { Buffer } = require('sdk/io/buffer');
|
||||
|
||||
exports.testWriteDouble = helper('writeDoubleBE/writeDoubleLE', function (assert) {
|
||||
var buffer = new Buffer(16);
|
||||
|
||||
buffer.writeDoubleBE(2.225073858507201e-308, 0);
|
||||
buffer.writeDoubleLE(2.225073858507201e-308, 8);
|
||||
assert.equal(0x00, buffer[0]);
|
||||
assert.equal(0x0f, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0xff, buffer[3]);
|
||||
assert.equal(0xff, buffer[4]);
|
||||
assert.equal(0xff, buffer[5]);
|
||||
assert.equal(0xff, buffer[6]);
|
||||
assert.equal(0xff, buffer[7]);
|
||||
assert.equal(0xff, buffer[8]);
|
||||
assert.equal(0xff, buffer[9]);
|
||||
assert.equal(0xff, buffer[10]);
|
||||
assert.equal(0xff, buffer[11]);
|
||||
assert.equal(0xff, buffer[12]);
|
||||
assert.equal(0xff, buffer[13]);
|
||||
assert.equal(0x0f, buffer[14]);
|
||||
assert.equal(0x00, buffer[15]);
|
||||
|
||||
buffer.writeDoubleBE(1.0000000000000004, 0);
|
||||
buffer.writeDoubleLE(1.0000000000000004, 8);
|
||||
assert.equal(0x3f, buffer[0]);
|
||||
assert.equal(0xf0, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x02, buffer[7]);
|
||||
assert.equal(0x02, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0xf0, buffer[14]);
|
||||
assert.equal(0x3f, buffer[15]);
|
||||
|
||||
buffer.writeDoubleBE(-2, 0);
|
||||
buffer.writeDoubleLE(-2, 8);
|
||||
assert.equal(0xc0, buffer[0]);
|
||||
assert.equal(0x00, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.equal(0x00, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0x00, buffer[14]);
|
||||
assert.equal(0xc0, buffer[15]);
|
||||
|
||||
buffer.writeDoubleBE(1.7976931348623157e+308, 0);
|
||||
buffer.writeDoubleLE(1.7976931348623157e+308, 8);
|
||||
assert.equal(0x7f, buffer[0]);
|
||||
assert.equal(0xef, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0xff, buffer[3]);
|
||||
assert.equal(0xff, buffer[4]);
|
||||
assert.equal(0xff, buffer[5]);
|
||||
assert.equal(0xff, buffer[6]);
|
||||
assert.equal(0xff, buffer[7]);
|
||||
assert.equal(0xff, buffer[8]);
|
||||
assert.equal(0xff, buffer[9]);
|
||||
assert.equal(0xff, buffer[10]);
|
||||
assert.equal(0xff, buffer[11]);
|
||||
assert.equal(0xff, buffer[12]);
|
||||
assert.equal(0xff, buffer[13]);
|
||||
assert.equal(0xef, buffer[14]);
|
||||
assert.equal(0x7f, buffer[15]);
|
||||
|
||||
buffer.writeDoubleBE(0 * -1, 0);
|
||||
buffer.writeDoubleLE(0 * -1, 8);
|
||||
assert.equal(0x80, buffer[0]);
|
||||
assert.equal(0x00, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.equal(0x00, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0x00, buffer[14]);
|
||||
assert.equal(0x80, buffer[15]);
|
||||
|
||||
buffer.writeDoubleBE(Infinity, 0);
|
||||
buffer.writeDoubleLE(Infinity, 8);
|
||||
assert.equal(0x7F, buffer[0]);
|
||||
assert.equal(0xF0, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.equal(0x00, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0xF0, buffer[14]);
|
||||
assert.equal(0x7F, buffer[15]);
|
||||
assert.equal(Infinity, buffer.readDoubleBE(0));
|
||||
assert.equal(Infinity, buffer.readDoubleLE(8));
|
||||
|
||||
buffer.writeDoubleBE(-Infinity, 0);
|
||||
buffer.writeDoubleLE(-Infinity, 8);
|
||||
assert.equal(0xFF, buffer[0]);
|
||||
assert.equal(0xF0, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.equal(0x00, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0xF0, buffer[14]);
|
||||
assert.equal(0xFF, buffer[15]);
|
||||
assert.equal(-Infinity, buffer.readDoubleBE(0));
|
||||
assert.equal(-Infinity, buffer.readDoubleLE(8));
|
||||
|
||||
buffer.writeDoubleBE(NaN, 0);
|
||||
buffer.writeDoubleLE(NaN, 8);
|
||||
// Darwin ia32 does the other kind of NaN.
|
||||
// Compiler bug. No one really cares.
|
||||
assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
|
||||
assert.equal(0xF8, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.equal(0x00, buffer[8]);
|
||||
assert.equal(0x00, buffer[9]);
|
||||
assert.equal(0x00, buffer[10]);
|
||||
assert.equal(0x00, buffer[11]);
|
||||
assert.equal(0x00, buffer[12]);
|
||||
assert.equal(0x00, buffer[13]);
|
||||
assert.equal(0xF8, buffer[14]);
|
||||
// Darwin ia32 does the other kind of NaN.
|
||||
// Compiler bug. No one really cares.
|
||||
assert.ok(0x7F === buffer[15] || 0xFF === buffer[15]);
|
||||
assert.ok(isNaN(buffer.readDoubleBE(0)));
|
||||
assert.ok(isNaN(buffer.readDoubleLE(8)));
|
||||
});
|
||||
|
||||
exports.testWriteFloat = helper('writeFloatBE/writeFloatLE', function (assert) {
|
||||
var buffer = new Buffer(8);
|
||||
|
||||
buffer.writeFloatBE(1, 0);
|
||||
buffer.writeFloatLE(1, 4);
|
||||
assert.equal(0x3f, buffer[0]);
|
||||
assert.equal(0x80, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x80, buffer[6]);
|
||||
assert.equal(0x3f, buffer[7]);
|
||||
|
||||
buffer.writeFloatBE(1 / 3, 0);
|
||||
buffer.writeFloatLE(1 / 3, 4);
|
||||
assert.equal(0x3e, buffer[0]);
|
||||
assert.equal(0xaa, buffer[1]);
|
||||
assert.equal(0xaa, buffer[2]);
|
||||
assert.equal(0xab, buffer[3]);
|
||||
assert.equal(0xab, buffer[4]);
|
||||
assert.equal(0xaa, buffer[5]);
|
||||
assert.equal(0xaa, buffer[6]);
|
||||
assert.equal(0x3e, buffer[7]);
|
||||
|
||||
buffer.writeFloatBE(3.4028234663852886e+38, 0);
|
||||
buffer.writeFloatLE(3.4028234663852886e+38, 4);
|
||||
assert.equal(0x7f, buffer[0]);
|
||||
assert.equal(0x7f, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0xff, buffer[3]);
|
||||
assert.equal(0xff, buffer[4]);
|
||||
assert.equal(0xff, buffer[5]);
|
||||
assert.equal(0x7f, buffer[6]);
|
||||
assert.equal(0x7f, buffer[7]);
|
||||
|
||||
buffer.writeFloatLE(1.1754943508222875e-38, 0);
|
||||
buffer.writeFloatBE(1.1754943508222875e-38, 4);
|
||||
assert.equal(0x00, buffer[0]);
|
||||
assert.equal(0x00, buffer[1]);
|
||||
assert.equal(0x80, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x80, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
|
||||
buffer.writeFloatBE(0 * -1, 0);
|
||||
buffer.writeFloatLE(0 * -1, 4);
|
||||
assert.equal(0x80, buffer[0]);
|
||||
assert.equal(0x00, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x80, buffer[7]);
|
||||
|
||||
buffer.writeFloatBE(Infinity, 0);
|
||||
buffer.writeFloatLE(Infinity, 4);
|
||||
assert.equal(0x7F, buffer[0]);
|
||||
assert.equal(0x80, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x80, buffer[6]);
|
||||
assert.equal(0x7F, buffer[7]);
|
||||
assert.equal(Infinity, buffer.readFloatBE(0));
|
||||
assert.equal(Infinity, buffer.readFloatLE(4));
|
||||
|
||||
buffer.writeFloatBE(-Infinity, 0);
|
||||
buffer.writeFloatLE(-Infinity, 4);
|
||||
// Darwin ia32 does the other kind of NaN.
|
||||
// Compiler bug. No one really cares.
|
||||
assert.ok(0xFF === buffer[0] || 0x7F === buffer[0]);
|
||||
assert.equal(0x80, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x80, buffer[6]);
|
||||
assert.equal(0xFF, buffer[7]);
|
||||
assert.equal(-Infinity, buffer.readFloatBE(0));
|
||||
assert.equal(-Infinity, buffer.readFloatLE(4));
|
||||
|
||||
buffer.writeFloatBE(NaN, 0);
|
||||
buffer.writeFloatLE(NaN, 4);
|
||||
// Darwin ia32 does the other kind of NaN.
|
||||
// Compiler bug. No one really cares.
|
||||
assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
|
||||
assert.equal(0xc0, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0xc0, buffer[6]);
|
||||
// Darwin ia32 does the other kind of NaN.
|
||||
// Compiler bug. No one really cares.
|
||||
assert.ok(0x7F === buffer[7] || 0xFF === buffer[7]);
|
||||
assert.ok(isNaN(buffer.readFloatBE(0)));
|
||||
assert.ok(isNaN(buffer.readFloatLE(4)));
|
||||
});
|
||||
|
||||
|
||||
exports.testWriteInt8 = helper('writeInt8', function (assert) {
|
||||
var buffer = new Buffer(2);
|
||||
|
||||
buffer.writeInt8(0x23, 0);
|
||||
buffer.writeInt8(-5, 1);
|
||||
|
||||
assert.equal(0x23, buffer[0]);
|
||||
assert.equal(0xfb, buffer[1]);
|
||||
|
||||
/* Make sure we handle truncation correctly */
|
||||
assert.throws(function() {
|
||||
buffer.writeInt8(0xabc, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt8(0xabc, 0);
|
||||
});
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt8(0x7f, 0);
|
||||
buffer.writeInt8(-0x80, 1);
|
||||
|
||||
assert.equal(0x7f, buffer[0]);
|
||||
assert.equal(0x80, buffer[1]);
|
||||
assert.throws(function() {
|
||||
buffer.writeInt8(0x7f + 1, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt8(-0x80 - 1, 0);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
exports.testWriteInt16 = helper('writeInt16LE/writeInt16BE', function (assert) {
|
||||
var buffer = new Buffer(6);
|
||||
|
||||
buffer.writeInt16BE(0x0023, 0);
|
||||
buffer.writeInt16LE(0x0023, 2);
|
||||
assert.equal(0x00, buffer[0]);
|
||||
assert.equal(0x23, buffer[1]);
|
||||
assert.equal(0x23, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
|
||||
buffer.writeInt16BE(-5, 0);
|
||||
buffer.writeInt16LE(-5, 2);
|
||||
assert.equal(0xff, buffer[0]);
|
||||
assert.equal(0xfb, buffer[1]);
|
||||
assert.equal(0xfb, buffer[2]);
|
||||
assert.equal(0xff, buffer[3]);
|
||||
|
||||
buffer.writeInt16BE(-1679, 1);
|
||||
buffer.writeInt16LE(-1679, 3);
|
||||
assert.equal(0xf9, buffer[1]);
|
||||
assert.equal(0x71, buffer[2]);
|
||||
assert.equal(0x71, buffer[3]);
|
||||
assert.equal(0xf9, buffer[4]);
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt16BE(0x7fff, 0);
|
||||
buffer.writeInt16BE(-0x8000, 2);
|
||||
assert.equal(0x7f, buffer[0]);
|
||||
assert.equal(0xff, buffer[1]);
|
||||
assert.equal(0x80, buffer[2]);
|
||||
assert.equal(0x00, buffer[3]);
|
||||
assert.throws(function() {
|
||||
buffer.writeInt16BE(0x7fff + 1, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt16BE(-0x8000 - 1, 0);
|
||||
});
|
||||
|
||||
buffer.writeInt16LE(0x7fff, 0);
|
||||
buffer.writeInt16LE(-0x8000, 2);
|
||||
assert.equal(0xff, buffer[0]);
|
||||
assert.equal(0x7f, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x80, buffer[3]);
|
||||
assert.throws(function() {
|
||||
buffer.writeInt16LE(0x7fff + 1, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt16LE(-0x8000 - 1, 0);
|
||||
});
|
||||
});
|
||||
|
||||
exports.testWriteInt32 = helper('writeInt32BE/writeInt32LE', function (assert) {
|
||||
var buffer = new Buffer(8);
|
||||
|
||||
buffer.writeInt32BE(0x23, 0);
|
||||
buffer.writeInt32LE(0x23, 4);
|
||||
assert.equal(0x00, buffer[0]);
|
||||
assert.equal(0x00, buffer[1]);
|
||||
assert.equal(0x00, buffer[2]);
|
||||
assert.equal(0x23, buffer[3]);
|
||||
assert.equal(0x23, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
|
||||
buffer.writeInt32BE(-5, 0);
|
||||
buffer.writeInt32LE(-5, 4);
|
||||
assert.equal(0xff, buffer[0]);
|
||||
assert.equal(0xff, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0xfb, buffer[3]);
|
||||
assert.equal(0xfb, buffer[4]);
|
||||
assert.equal(0xff, buffer[5]);
|
||||
assert.equal(0xff, buffer[6]);
|
||||
assert.equal(0xff, buffer[7]);
|
||||
|
||||
buffer.writeInt32BE(-805306713, 0);
|
||||
buffer.writeInt32LE(-805306713, 4);
|
||||
assert.equal(0xcf, buffer[0]);
|
||||
assert.equal(0xff, buffer[1]);
|
||||
assert.equal(0xfe, buffer[2]);
|
||||
assert.equal(0xa7, buffer[3]);
|
||||
assert.equal(0xa7, buffer[4]);
|
||||
assert.equal(0xfe, buffer[5]);
|
||||
assert.equal(0xff, buffer[6]);
|
||||
assert.equal(0xcf, buffer[7]);
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt32BE(0x7fffffff, 0);
|
||||
buffer.writeInt32BE(-0x80000000, 4);
|
||||
assert.equal(0x7f, buffer[0]);
|
||||
assert.equal(0xff, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0xff, buffer[3]);
|
||||
assert.equal(0x80, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x00, buffer[7]);
|
||||
assert.throws(function() {
|
||||
buffer.writeInt32BE(0x7fffffff + 1, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt32BE(-0x80000000 - 1, 0);
|
||||
});
|
||||
|
||||
buffer.writeInt32LE(0x7fffffff, 0);
|
||||
buffer.writeInt32LE(-0x80000000, 4);
|
||||
assert.equal(0xff, buffer[0]);
|
||||
assert.equal(0xff, buffer[1]);
|
||||
assert.equal(0xff, buffer[2]);
|
||||
assert.equal(0x7f, buffer[3]);
|
||||
assert.equal(0x00, buffer[4]);
|
||||
assert.equal(0x00, buffer[5]);
|
||||
assert.equal(0x00, buffer[6]);
|
||||
assert.equal(0x80, buffer[7]);
|
||||
assert.throws(function() {
|
||||
buffer.writeInt32LE(0x7fffffff + 1, 0);
|
||||
});
|
||||
assert.throws(function() {
|
||||
buffer.writeInt32LE(-0x80000000 - 1, 0);
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* We need to check the following things:
|
||||
* - We are correctly resolving big endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly resolving little endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
exports.testWriteUInt8 = helper('writeUInt8', function (assert) {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data.writeUInt8(23, 0);
|
||||
data.writeUInt8(23, 1);
|
||||
data.writeUInt8(23, 2);
|
||||
data.writeUInt8(23, 3);
|
||||
assert.equal(23, data[0]);
|
||||
assert.equal(23, data[1]);
|
||||
assert.equal(23, data[2]);
|
||||
assert.equal(23, data[3]);
|
||||
|
||||
data.writeUInt8(23, 0);
|
||||
data.writeUInt8(23, 1);
|
||||
data.writeUInt8(23, 2);
|
||||
data.writeUInt8(23, 3);
|
||||
assert.equal(23, data[0]);
|
||||
assert.equal(23, data[1]);
|
||||
assert.equal(23, data[2]);
|
||||
assert.equal(23, data[3]);
|
||||
|
||||
data.writeUInt8(255, 0);
|
||||
assert.equal(255, data[0]);
|
||||
|
||||
data.writeUInt8(255, 0);
|
||||
assert.equal(255, data[0]);
|
||||
});
|
||||
|
||||
|
||||
exports.testWriteUInt16 = helper('writeUInt16BE/writeUInt16LE', function (assert) {
|
||||
var value = 0x2343;
|
||||
var data = new Buffer(4);
|
||||
|
||||
data.writeUInt16BE(value, 0);
|
||||
assert.equal(0x23, data[0]);
|
||||
assert.equal(0x43, data[1]);
|
||||
|
||||
data.writeUInt16BE(value, 1);
|
||||
assert.equal(0x23, data[1]);
|
||||
assert.equal(0x43, data[2]);
|
||||
|
||||
data.writeUInt16BE(value, 2);
|
||||
assert.equal(0x23, data[2]);
|
||||
assert.equal(0x43, data[3]);
|
||||
|
||||
data.writeUInt16LE(value, 0);
|
||||
assert.equal(0x23, data[1]);
|
||||
assert.equal(0x43, data[0]);
|
||||
|
||||
data.writeUInt16LE(value, 1);
|
||||
assert.equal(0x23, data[2]);
|
||||
assert.equal(0x43, data[1]);
|
||||
|
||||
data.writeUInt16LE(value, 2);
|
||||
assert.equal(0x23, data[3]);
|
||||
assert.equal(0x43, data[2]);
|
||||
|
||||
value = 0xff80;
|
||||
data.writeUInt16LE(value, 0);
|
||||
assert.equal(0xff, data[1]);
|
||||
assert.equal(0x80, data[0]);
|
||||
|
||||
data.writeUInt16BE(value, 0);
|
||||
assert.equal(0xff, data[0]);
|
||||
assert.equal(0x80, data[1]);
|
||||
});
|
||||
|
||||
|
||||
exports.testWriteUInt32 = helper('writeUInt32BE/writeUInt32LE', function (assert) {
|
||||
var data = new Buffer(6);
|
||||
var value = 0xe7f90a6d;
|
||||
|
||||
data.writeUInt32BE(value, 0);
|
||||
assert.equal(0xe7, data[0]);
|
||||
assert.equal(0xf9, data[1]);
|
||||
assert.equal(0x0a, data[2]);
|
||||
assert.equal(0x6d, data[3]);
|
||||
|
||||
data.writeUInt32BE(value, 1);
|
||||
assert.equal(0xe7, data[1]);
|
||||
assert.equal(0xf9, data[2]);
|
||||
assert.equal(0x0a, data[3]);
|
||||
assert.equal(0x6d, data[4]);
|
||||
|
||||
data.writeUInt32BE(value, 2);
|
||||
assert.equal(0xe7, data[2]);
|
||||
assert.equal(0xf9, data[3]);
|
||||
assert.equal(0x0a, data[4]);
|
||||
assert.equal(0x6d, data[5]);
|
||||
|
||||
data.writeUInt32LE(value, 0);
|
||||
assert.equal(0xe7, data[3]);
|
||||
assert.equal(0xf9, data[2]);
|
||||
assert.equal(0x0a, data[1]);
|
||||
assert.equal(0x6d, data[0]);
|
||||
|
||||
data.writeUInt32LE(value, 1);
|
||||
assert.equal(0xe7, data[4]);
|
||||
assert.equal(0xf9, data[3]);
|
||||
assert.equal(0x0a, data[2]);
|
||||
assert.equal(0x6d, data[1]);
|
||||
|
||||
data.writeUInt32LE(value, 2);
|
||||
assert.equal(0xe7, data[5]);
|
||||
assert.equal(0xf9, data[4]);
|
||||
assert.equal(0x0a, data[3]);
|
||||
assert.equal(0x6d, data[2]);
|
||||
});
|
||||
|
||||
function helper (description, fn) {
|
||||
return function (assert) {
|
||||
let bulkAssert = {
|
||||
equal: function (a, b) {
|
||||
if (a !== b) throw new Error('Error found in ' + description);
|
||||
},
|
||||
ok: function (value) {
|
||||
if (!value) throw new Error('Error found in ' + description);
|
||||
},
|
||||
/*
|
||||
* TODO
|
||||
* There should be errors when setting outside of the value range
|
||||
* of the data type (like writeInt8 with value of 1000), but DataView
|
||||
* does not throw; seems to just grab the appropriate max bits.
|
||||
* So ignoring this test for now
|
||||
*/
|
||||
throws: function (shouldThrow) {
|
||||
assert.pass(description + ': Need to implement error handling for setting buffer values ' +
|
||||
'outside of the data types\' range.');
|
||||
/*
|
||||
let didItThrow = false;
|
||||
try {
|
||||
shouldThrow();
|
||||
} catch (e) {
|
||||
didItThrow = e;
|
||||
}
|
||||
if (!didItThrow)
|
||||
throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
|
||||
*/
|
||||
}
|
||||
};
|
||||
fn(bulkAssert);
|
||||
// If we get here, no errors thrown
|
||||
assert.pass('All tests passed for ' + description);
|
||||
};
|
||||
}
|
@ -2,13 +2,5 @@
|
||||
* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct PermissionRequest {
|
||||
nsCString type;
|
||||
nsCString access;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
exports.url = path =>
|
||||
module.uri.substr(0, module.uri.lastIndexOf("/") + 1) + "fixtures/" + path
|
13
addon-sdk/source/test/fixtures/index.html
vendored
Normal file
13
addon-sdk/source/test/fixtures/index.html
vendored
Normal file
@ -0,0 +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/. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Add-on Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>This is an add-on page test!</p>
|
||||
</body>
|
||||
</html>
|
3
addon-sdk/source/test/fixtures/loader/json/invalid.json
vendored
Normal file
3
addon-sdk/source/test/fixtures/loader/json/invalid.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
invalidjson
|
||||
}
|
14
addon-sdk/source/test/fixtures/loader/json/manifest.json
vendored
Normal file
14
addon-sdk/source/test/fixtures/loader/json/manifest.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Jetpack Loader Test",
|
||||
"version": "1.0.1",
|
||||
"dependencies": {
|
||||
"async": "*",
|
||||
"underscore": "*"
|
||||
},
|
||||
"contributors": [
|
||||
"ash nazg durbatulûk",
|
||||
"ash nazg gimbatul",
|
||||
"ash nazg thrakatulûk",
|
||||
"agh burzum-ishi krimpatul"
|
||||
]
|
||||
}
|
4
addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
vendored
Normal file
4
addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
"filename": "nodotjson.json.js",
|
||||
"data": {}
|
||||
};
|
3
addon-sdk/source/test/fixtures/loader/json/test.json
vendored
Normal file
3
addon-sdk/source/test/fixtures/loader/json/test.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"filename": "test.json"
|
||||
}
|
3
addon-sdk/source/test/fixtures/loader/json/test.json.js
vendored
Normal file
3
addon-sdk/source/test/fixtures/loader/json/test.json.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
"filename": "test.json.js"
|
||||
};
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
20
addon-sdk/source/test/fixtures/test-trusted-document.html
vendored
Normal file
20
addon-sdk/source/test/fixtures/test-trusted-document.html
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Worker test</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="paragraph">Lorem ipsum dolor sit amet.</p>
|
||||
<script>
|
||||
if ("addon" in window) {
|
||||
addon.port.on('addon-to-document', function (arg) {
|
||||
addon.port.emit('document-to-addon', arg);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -10,6 +10,7 @@ const observers = require("sdk/deprecated/observer-service");
|
||||
const { setTimeout } = require("sdk/timers");
|
||||
const tmp = require("sdk/test/tmp-file");
|
||||
const system = require("sdk/system");
|
||||
const fixtures = require("./fixtures");
|
||||
|
||||
const testFolderURL = module.uri.split('test-addon-installer.js')[0];
|
||||
const ADDON_URL = testFolderURL + "fixtures/addon-install-unit-test@mozilla.com.xpi";
|
||||
|
@ -2,31 +2,486 @@
|
||||
* 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/. */
|
||||
|
||||
|
||||
/*
|
||||
* Many of these tests taken from Joyent's Node
|
||||
* https://github.com/joyent/node/blob/master/test/simple/test-buffer.js
|
||||
*/
|
||||
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
|
||||
const { safeMerge } = require('sdk/util/object');
|
||||
|
||||
const ENCODINGS = ['utf-8', 'utf-16le', 'utf-16be'];
|
||||
|
||||
exports.testBufferMain = function (assert) {
|
||||
let b = Buffer('abcdef');
|
||||
|
||||
// try to create 0-length buffers
|
||||
new Buffer('');
|
||||
new Buffer(0);
|
||||
// test encodings supported by node;
|
||||
// this is different than what node supports, details
|
||||
// in buffer.js
|
||||
ENCODINGS.forEach(enc => {
|
||||
new Buffer('', enc);
|
||||
assert.pass('Creating a buffer with ' + enc + ' does not throw');
|
||||
});
|
||||
|
||||
ENCODINGS.forEach(function(encoding) {
|
||||
// Does not work with utf8
|
||||
if (encoding === 'utf-8') return;
|
||||
var b = new Buffer(10);
|
||||
b.write('あいうえお', encoding);
|
||||
assert.equal(b.toString(encoding), 'あいうえお',
|
||||
'encode and decodes buffer with ' + encoding);
|
||||
});
|
||||
|
||||
// invalid encoding for Buffer.toString
|
||||
assert.throws(() => {
|
||||
b.toString('invalid');
|
||||
}, TypeError, 'invalid encoding for Buffer.toString');
|
||||
|
||||
// try to toString() a 0-length slice of a buffer, both within and without the
|
||||
// valid buffer range
|
||||
assert.equal(new Buffer('abc').toString('utf8', 0, 0), '',
|
||||
'toString 0-length buffer, valid range');
|
||||
assert.equal(new Buffer('abc').toString('utf8', -100, -100), '',
|
||||
'toString 0-length buffer, invalid range');
|
||||
assert.equal(new Buffer('abc').toString('utf8', 100, 100), '',
|
||||
'toString 0-length buffer, invalid range');
|
||||
|
||||
// try toString() with a object as a encoding
|
||||
assert.equal(new Buffer('abc').toString({toString: function() {
|
||||
return 'utf8';
|
||||
}}), 'abc', 'toString with object as an encoding');
|
||||
|
||||
// test for buffer overrun
|
||||
var buf = new Buffer([0, 0, 0, 0, 0]); // length: 5
|
||||
var sub = buf.slice(0, 4); // length: 4
|
||||
var written = sub.write('12345', 'utf8');
|
||||
assert.equal(written, 4, 'correct bytes written in slice');
|
||||
assert.equal(buf[4], 0, 'correct origin buffer value');
|
||||
|
||||
// Check for fractional length args, junk length args, etc.
|
||||
// https://github.com/joyent/node/issues/1758
|
||||
Buffer(3.3).toString(); // throws bad argument error in commit 43cb4ec
|
||||
assert.equal(Buffer(-1).length, 0);
|
||||
assert.equal(Buffer(NaN).length, 0);
|
||||
assert.equal(Buffer(3.3).length, 3);
|
||||
assert.equal(Buffer({length: 3.3}).length, 3);
|
||||
assert.equal(Buffer({length: 'BAM'}).length, 0);
|
||||
|
||||
// Make sure that strings are not coerced to numbers.
|
||||
assert.equal(Buffer('99').length, 2);
|
||||
assert.equal(Buffer('13.37').length, 5);
|
||||
};
|
||||
|
||||
exports.testIsEncoding = function (assert) {
|
||||
Object.keys(ENCODINGS).forEach(encoding => {
|
||||
ENCODINGS.map(encoding => {
|
||||
assert.ok(Buffer.isEncoding(encoding),
|
||||
'Buffer.isEncoding ' + encoding + ' truthy');
|
||||
});
|
||||
['not-encoding', undefined, null, 100, {}].forEach(encoding => {
|
||||
['not-encoding', undefined, null, 100, {}].map(encoding => {
|
||||
assert.ok(!Buffer.isEncoding(encoding),
|
||||
'Buffer.isEncoding ' + encoding + ' falsy');
|
||||
});
|
||||
};
|
||||
|
||||
exports.testBufferCopy = function (assert) {
|
||||
// counter to ensure unique value is always copied
|
||||
var cntr = 0;
|
||||
var b = Buffer(1024); // safe constructor
|
||||
|
||||
assert.strictEqual(1024, b.length);
|
||||
b[0] = -1;
|
||||
assert.strictEqual(b[0], 255);
|
||||
|
||||
var shimArray = [];
|
||||
for (var i = 0; i < 1024; i++) {
|
||||
b[i] = i % 256;
|
||||
shimArray[i] = i % 256;
|
||||
}
|
||||
|
||||
compareBuffers(assert, b, shimArray, 'array notation');
|
||||
|
||||
var c = new Buffer(512);
|
||||
assert.strictEqual(512, c.length);
|
||||
// copy 512 bytes, from 0 to 512.
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = b.copy(c, 0, 0, 512);
|
||||
assert.strictEqual(512, copied,
|
||||
'copied ' + copied + ' bytes from b into c');
|
||||
|
||||
compareBuffers(assert, b, c, 'copied to other buffer');
|
||||
|
||||
// copy c into b, without specifying sourceEnd
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = c.copy(b, 0, 0);
|
||||
assert.strictEqual(c.length, copied,
|
||||
'copied ' + copied + ' bytes from c into b w/o sourceEnd');
|
||||
compareBuffers(assert, b, c,
|
||||
'copied to other buffer without specifying sourceEnd');
|
||||
|
||||
// copy c into b, without specifying sourceStart
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = c.copy(b, 0);
|
||||
assert.strictEqual(c.length, copied,
|
||||
'copied ' + copied + ' bytes from c into b w/o sourceStart');
|
||||
compareBuffers(assert, b, c,
|
||||
'copied to other buffer without specifying sourceStart');
|
||||
|
||||
// copy longer buffer b to shorter c without targetStart
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
|
||||
var copied = b.copy(c);
|
||||
assert.strictEqual(c.length, copied,
|
||||
'copied ' + copied + ' bytes from b into c w/o targetStart');
|
||||
compareBuffers(assert, b, c,
|
||||
'copy long buffer to shorter buffer without targetStart');
|
||||
|
||||
// copy starting near end of b to c
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
|
||||
assert.strictEqual(Math.floor(c.length / 2), copied,
|
||||
'copied ' + copied + ' bytes from end of b into beg. of c');
|
||||
|
||||
let successStatus = true;
|
||||
for (var i = 0; i < Math.floor(c.length / 2); i++) {
|
||||
if (b[b.length - Math.floor(c.length / 2) + i] !== c[i])
|
||||
successStatus = false;
|
||||
}
|
||||
|
||||
for (var i = Math.floor(c.length /2) + 1; i < c.length; i++) {
|
||||
if (c[c.length-1] !== c[i])
|
||||
successStatus = false;
|
||||
}
|
||||
assert.ok(successStatus,
|
||||
'Copied bytes from end of large buffer into beginning of small buffer');
|
||||
|
||||
// try to copy 513 bytes, and check we don't overrun c
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = b.copy(c, 0, 0, 513);
|
||||
assert.strictEqual(c.length, copied,
|
||||
'copied ' + copied + ' bytes from b trying to overrun c');
|
||||
compareBuffers(assert, b, c,
|
||||
'copying to buffer that would overflow');
|
||||
|
||||
// copy 768 bytes from b into b
|
||||
b.fill(++cntr);
|
||||
b.fill(++cntr, 256);
|
||||
var copied = b.copy(b, 0, 256, 1024);
|
||||
assert.strictEqual(768, copied,
|
||||
'copied ' + copied + ' bytes from b into b');
|
||||
|
||||
compareBuffers(assert, b, shimArray.map(()=>cntr),
|
||||
'copy partial buffer to itself');
|
||||
|
||||
// copy string longer than buffer length (failure will segfault)
|
||||
var bb = new Buffer(10);
|
||||
bb.fill('hello crazy world');
|
||||
|
||||
// copy throws at negative sourceStart
|
||||
assert.throws(function() {
|
||||
Buffer(5).copy(Buffer(5), 0, -1);
|
||||
}, RangeError, 'buffer copy throws at negative sourceStart');
|
||||
|
||||
// check sourceEnd resets to targetEnd if former is greater than the latter
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
var copied = b.copy(c, 0, 0, 1025);
|
||||
assert.strictEqual(copied, c.length,
|
||||
'copied ' + copied + ' bytes from b into c');
|
||||
compareBuffers(assert, b, c, 'copying should reset sourceEnd if targetEnd if sourceEnd > targetEnd');
|
||||
|
||||
// throw with negative sourceEnd
|
||||
assert.throws(function() {
|
||||
b.copy(c, 0, 0, -1);
|
||||
}, RangeError, 'buffer copy throws at negative sourceEnd');
|
||||
|
||||
// when sourceStart is greater than sourceEnd, zero copied
|
||||
assert.equal(b.copy(c, 0, 100, 10), 0);
|
||||
|
||||
// when targetStart > targetLength, zero copied
|
||||
assert.equal(b.copy(c, 512, 0, 10), 0);
|
||||
|
||||
// try to copy 0 bytes worth of data into an empty buffer
|
||||
b.copy(new Buffer(0), 0, 0, 0);
|
||||
|
||||
// try to copy 0 bytes past the end of the target buffer
|
||||
b.copy(new Buffer(0), 1, 1, 1);
|
||||
b.copy(new Buffer(1), 1, 1, 1);
|
||||
|
||||
// try to copy 0 bytes from past the end of the source buffer
|
||||
b.copy(new Buffer(1), 0, 2048, 2048);
|
||||
};
|
||||
|
||||
exports.testBufferWrite = function (assert) {
|
||||
let b = Buffer(1024);
|
||||
b.fill(0);
|
||||
|
||||
assert.throws(() => {
|
||||
b.write('test string', 0, 5, 'invalid');
|
||||
}, TypeError, 'invalid encoding with buffer write throws');
|
||||
// try to write a 0-length string beyond the end of b
|
||||
assert.throws(function() {
|
||||
b.write('', 2048);
|
||||
}, RangeError, 'writing a 0-length string beyond buffer throws');
|
||||
// throw when writing to negative offset
|
||||
assert.throws(function() {
|
||||
b.write('a', -1);
|
||||
}, RangeError, 'writing negative offset on buffer throws');
|
||||
|
||||
// throw when writing past bounds from the pool
|
||||
assert.throws(function() {
|
||||
b.write('a', 2048);
|
||||
}, RangeError, 'writing past buffer bounds from pool throws');
|
||||
|
||||
// testing for smart defaults and ability to pass string values as offset
|
||||
|
||||
// previous write API was the following:
|
||||
// write(string, encoding, offset, length)
|
||||
// this is planned on being removed in node v0.13,
|
||||
// we will not support it
|
||||
var writeTest = new Buffer('abcdes');
|
||||
writeTest.write('n', 'utf8');
|
||||
// writeTest.write('o', 'utf8', '1');
|
||||
writeTest.write('d', '2', 'utf8');
|
||||
writeTest.write('e', 3, 'utf8');
|
||||
// writeTest.write('j', 'utf8', 4);
|
||||
assert.equal(writeTest.toString(), 'nbdees',
|
||||
'buffer write API alternative syntax works');
|
||||
};
|
||||
|
||||
exports.testBufferWriteEncoding = function (assert) {
|
||||
|
||||
// Node #1210 Test UTF-8 string includes null character
|
||||
var buf = new Buffer('\0');
|
||||
assert.equal(buf.length, 1);
|
||||
buf = new Buffer('\0\0');
|
||||
assert.equal(buf.length, 2);
|
||||
|
||||
buf = new Buffer(2);
|
||||
var written = buf.write(''); // 0byte
|
||||
assert.equal(written, 0);
|
||||
written = buf.write('\0'); // 1byte (v8 adds null terminator)
|
||||
assert.equal(written, 1);
|
||||
written = buf.write('a\0'); // 1byte * 2
|
||||
assert.equal(written, 2);
|
||||
// TODO, these tests write 0, possibly due to character encoding
|
||||
/*
|
||||
written = buf.write('あ'); // 3bytes
|
||||
assert.equal(written, 0);
|
||||
written = buf.write('\0あ'); // 1byte + 3bytes
|
||||
assert.equal(written, 1);
|
||||
*/
|
||||
written = buf.write('\0\0あ'); // 1byte * 2 + 3bytes
|
||||
buf = new Buffer(10);
|
||||
written = buf.write('あいう'); // 3bytes * 3 (v8 adds null terminator)
|
||||
assert.equal(written, 9);
|
||||
written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
|
||||
assert.equal(written, 10);
|
||||
};
|
||||
|
||||
exports.testBufferWriteWithMaxLength = function (assert) {
|
||||
// Node #243 Test write() with maxLength
|
||||
var buf = new Buffer(4);
|
||||
buf.fill(0xFF);
|
||||
var written = buf.write('abcd', 1, 2, 'utf8');
|
||||
assert.equal(written, 2);
|
||||
assert.equal(buf[0], 0xFF);
|
||||
assert.equal(buf[1], 0x61);
|
||||
assert.equal(buf[2], 0x62);
|
||||
assert.equal(buf[3], 0xFF);
|
||||
|
||||
buf.fill(0xFF);
|
||||
written = buf.write('abcd', 1, 4);
|
||||
assert.equal(written, 3);
|
||||
assert.equal(buf[0], 0xFF);
|
||||
assert.equal(buf[1], 0x61);
|
||||
assert.equal(buf[2], 0x62);
|
||||
assert.equal(buf[3], 0x63);
|
||||
|
||||
buf.fill(0xFF);
|
||||
// Ignore legacy API
|
||||
/*
|
||||
written = buf.write('abcd', 'utf8', 1, 2); // legacy style
|
||||
console.log(buf);
|
||||
assert.equal(written, 2);
|
||||
assert.equal(buf[0], 0xFF);
|
||||
assert.equal(buf[1], 0x61);
|
||||
assert.equal(buf[2], 0x62);
|
||||
assert.equal(buf[3], 0xFF);
|
||||
*/
|
||||
};
|
||||
|
||||
exports.testBufferSlice = function (assert) {
|
||||
var asciiString = 'hello world';
|
||||
var offset = 100;
|
||||
var b = Buffer(1024);
|
||||
b.fill(0);
|
||||
|
||||
for (var i = 0; i < asciiString.length; i++) {
|
||||
b[i] = asciiString.charCodeAt(i);
|
||||
}
|
||||
var asciiSlice = b.toString('utf8', 0, asciiString.length);
|
||||
assert.equal(asciiString, asciiSlice);
|
||||
|
||||
var written = b.write(asciiString, offset, 'utf8');
|
||||
assert.equal(asciiString.length, written);
|
||||
asciiSlice = b.toString('utf8', offset, offset + asciiString.length);
|
||||
assert.equal(asciiString, asciiSlice);
|
||||
|
||||
var sliceA = b.slice(offset, offset + asciiString.length);
|
||||
var sliceB = b.slice(offset, offset + asciiString.length);
|
||||
compareBuffers(assert, sliceA, sliceB,
|
||||
'slicing is idempotent');
|
||||
|
||||
let sliceTest = true;
|
||||
for (var j = 0; j < 100; j++) {
|
||||
var slice = b.slice(100, 150);
|
||||
if (50 !== slice.length)
|
||||
sliceTest = false;
|
||||
for (var i = 0; i < 50; i++) {
|
||||
if (b[100 + i] !== slice[i])
|
||||
sliceTest = false;
|
||||
}
|
||||
}
|
||||
assert.ok(sliceTest, 'massive slice runs do not affect buffer');
|
||||
|
||||
// Single argument slice
|
||||
let testBuf = new Buffer('abcde');
|
||||
assert.equal('bcde', testBuf.slice(1).toString(), 'single argument slice');
|
||||
|
||||
// slice(0,0).length === 0
|
||||
assert.equal(0, Buffer('hello').slice(0, 0).length, 'slice(0,0) === 0');
|
||||
|
||||
var buf = new Buffer('0123456789');
|
||||
assert.equal(buf.slice(-10, 10), '0123456789', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(-20, 10), '0123456789', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(-20, -10), '', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(0, -1), '012345678', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(2, -2), '234567', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(0, 65536), '0123456789', 'buffer slice range correct');
|
||||
assert.equal(buf.slice(65536, 0), '', 'buffer slice range correct');
|
||||
|
||||
let sliceTest = true;
|
||||
for (var i = 0, s = buf.toString(); i < buf.length; ++i) {
|
||||
if (buf.slice(-i) != s.slice(-i)) sliceTest = false;
|
||||
if (buf.slice(0, -i) != s.slice(0, -i)) sliceTest = false;
|
||||
}
|
||||
assert.ok(sliceTest, 'buffer.slice should be consistent');
|
||||
|
||||
// Make sure modifying a sliced buffer, affects original and vice versa
|
||||
b.fill(0);
|
||||
let sliced = b.slice(0, 10);
|
||||
let babyslice = sliced.slice(0, 5);
|
||||
|
||||
for (let i = 0; i < sliced.length; i++)
|
||||
sliced[i] = 'jetpack'.charAt(i);
|
||||
|
||||
compareBuffers(assert, b, sliced,
|
||||
'modifying sliced buffer affects original');
|
||||
|
||||
compareBuffers(assert, b, babyslice,
|
||||
'modifying sliced buffer affects child-sliced buffer');
|
||||
|
||||
for (let i = 0; i < sliced.length; i++)
|
||||
b[i] = 'odinmonkey'.charAt(i);
|
||||
|
||||
compareBuffers(assert, b, sliced,
|
||||
'modifying original buffer affects sliced');
|
||||
|
||||
compareBuffers(assert, b, babyslice,
|
||||
'modifying original buffer affects grandchild sliced buffer');
|
||||
};
|
||||
|
||||
exports.testSlicingParents = function (assert) {
|
||||
let root = Buffer(5);
|
||||
let child = root.slice(0, 4);
|
||||
let grandchild = child.slice(0, 3);
|
||||
|
||||
assert.equal(root.parent, undefined, 'a new buffer should not have a parent');
|
||||
|
||||
// make sure a zero length slice doesn't set the .parent attribute
|
||||
assert.equal(root.slice(0,0).parent, undefined,
|
||||
'0-length slice should not have a parent');
|
||||
|
||||
assert.equal(child.parent, root,
|
||||
'a valid slice\'s parent should be the original buffer (child)');
|
||||
|
||||
assert.equal(grandchild.parent, root,
|
||||
'a valid slice\'s parent should be the original buffer (grandchild)');
|
||||
};
|
||||
|
||||
exports.testIsBuffer = function (assert) {
|
||||
let buffer = new Buffer('content', 'utf8');
|
||||
assert.ok(Buffer.isBuffer(buffer), 'isBuffer truthy on buffers');
|
||||
assert.ok(!Buffer.isBuffer({}), 'isBuffer falsy on objects');
|
||||
assert.ok(!Buffer.isBuffer(new Uint8Array()),
|
||||
'isBuffer falsy on Uint8Array');
|
||||
assert.ok(Buffer.isBuffer(buffer.slice(0)), 'Buffer#slice should be a new buffer');
|
||||
};
|
||||
|
||||
exports.testBufferConcat = function (assert) {
|
||||
let zero = [];
|
||||
let one = [ new Buffer('asdf') ];
|
||||
let long = [];
|
||||
for (let i = 0; i < 10; i++) long.push(new Buffer('asdf'));
|
||||
|
||||
let flatZero = Buffer.concat(zero);
|
||||
let flatOne = Buffer.concat(one);
|
||||
let flatLong = Buffer.concat(long);
|
||||
let flatLongLen = Buffer.concat(long, 40);
|
||||
|
||||
assert.equal(flatZero.length, 0);
|
||||
assert.equal(flatOne.toString(), 'asdf');
|
||||
assert.equal(flatOne, one[0]);
|
||||
assert.ok(flatLong.toString(), (new Array(10+1).join('asdf')));
|
||||
assert.equal(flatLongLen.toString(), (new Array(10+1).join('asdf')));
|
||||
};
|
||||
|
||||
exports.testBufferByteLength = function (assert) {
|
||||
let str = '\u00bd + \u00bc = \u00be';
|
||||
assert.equal(Buffer.byteLength(str), 12,
|
||||
'correct byteLength of string');
|
||||
|
||||
assert.equal(14, Buffer.byteLength('Il était tué'));
|
||||
assert.equal(14, Buffer.byteLength('Il était tué', 'utf8'));
|
||||
// We do not currently support these encodings
|
||||
/*
|
||||
['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
|
||||
assert.equal(24, Buffer.byteLength('Il était tué', encoding));
|
||||
});
|
||||
assert.equal(12, Buffer.byteLength('Il était tué', 'ascii'));
|
||||
assert.equal(12, Buffer.byteLength('Il était tué', 'binary'));
|
||||
*/
|
||||
};
|
||||
|
||||
exports.testTextEncoderDecoder = function (assert) {
|
||||
@ -34,57 +489,78 @@ exports.testTextEncoderDecoder = function (assert) {
|
||||
assert.ok(TextDecoder, 'TextDecoder exists');
|
||||
};
|
||||
|
||||
// List of supported encodings taken from:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
|
||||
const ENCODINGS = { "unicode-1-1-utf-8": 1, "utf-8": 1, "utf8": 1,
|
||||
"866": 1, "cp866": 1, "csibm866": 1, "ibm866": 1, "csisolatin2": 1,
|
||||
"iso-8859-2": 1, "iso-ir-101": 1, "iso8859-2": 1, "iso88592": 1,
|
||||
"iso_8859-2": 1, "iso_8859-2:1987": 1, "l2": 1, "latin2": 1, "csisolatin3": 1,
|
||||
"iso-8859-3": 1, "iso-ir-109": 1, "iso8859-3": 1, "iso88593": 1,
|
||||
"iso_8859-3": 1, "iso_8859-3:1988": 1, "l3": 1, "latin3": 1, "csisolatin4": 1,
|
||||
"iso-8859-4": 1, "iso-ir-110": 1, "iso8859-4": 1, "iso88594": 1,
|
||||
"iso_8859-4": 1, "iso_8859-4:1988": 1, "l4": 1, "latin4": 1,
|
||||
"csisolatincyrillic": 1, "cyrillic": 1, "iso-8859-5": 1, "iso-ir-144": 1,
|
||||
"iso8859-5": 1, "iso88595": 1, "iso_8859-5": 1, "iso_8859-5:1988": 1,
|
||||
"arabic": 1, "asmo-708": 1, "csiso88596e": 1, "csiso88596i": 1,
|
||||
"csisolatinarabic": 1, "ecma-114": 1, "iso-8859-6": 1, "iso-8859-6-e": 1,
|
||||
"iso-8859-6-i": 1, "iso-ir-127": 1, "iso8859-6": 1, "iso88596": 1,
|
||||
"iso_8859-6": 1, "iso_8859-6:1987": 1, "csisolatingreek": 1, "ecma-118": 1,
|
||||
"elot_928": 1, "greek": 1, "greek8": 1, "iso-8859-7": 1, "iso-ir-126": 1,
|
||||
"iso8859-7": 1, "iso88597": 1, "iso_8859-7": 1, "iso_8859-7:1987": 1,
|
||||
"sun_eu_greek": 1, "csiso88598e": 1, "csisolatinhebrew": 1, "hebrew": 1,
|
||||
"iso-8859-8": 1, "iso-8859-8-e": 1, "iso-ir-138": 1, "iso8859-8": 1,
|
||||
"iso88598": 1, "iso_8859-8": 1, "iso_8859-8:1988": 1, "visual": 1,
|
||||
"csiso88598i": 1, "iso-8859-8-i": 1, "logical": 1, "csisolatin6": 1,
|
||||
"iso-8859-10": 1, "iso-ir-157": 1, "iso8859-10": 1, "iso885910": 1,
|
||||
"l6": 1, "latin6": 1, "iso-8859-13": 1, "iso8859-13": 1, "iso885913": 1,
|
||||
"iso-8859-14": 1, "iso8859-14": 1, "iso885914": 1, "csisolatin9": 1,
|
||||
"iso-8859-15": 1, "iso8859-15": 1, "iso885915": 1, "iso_8859-15": 1,
|
||||
"l9": 1, "iso-8859-16": 1, "cskoi8r": 1, "koi": 1, "koi8": 1, "koi8-r": 1,
|
||||
"koi8_r": 1, "koi8-u": 1, "csmacintosh": 1, "mac": 1, "macintosh": 1,
|
||||
"x-mac-roman": 1, "dos-874": 1, "iso-8859-11": 1, "iso8859-11": 1,
|
||||
"iso885911": 1, "tis-620": 1, "windows-874": 1, "cp1250": 1,
|
||||
"windows-1250": 1, "x-cp1250": 1, "cp1251": 1, "windows-1251": 1,
|
||||
"x-cp1251": 1, "ansi_x3.4-1968": 1, "ascii": 1, "cp1252": 1, "cp819": 1,
|
||||
"csisolatin1": 1, "ibm819": 1, "iso-8859-1": 1, "iso-ir-100": 1,
|
||||
"iso8859-1": 1, "iso88591": 1, "iso_8859-1": 1, "iso_8859-1:1987": 1,
|
||||
"l1": 1, "latin1": 1, "us-ascii": 1, "windows-1252": 1, "x-cp1252": 1,
|
||||
"cp1253": 1, "windows-1253": 1, "x-cp1253": 1, "cp1254": 1, "csisolatin5": 1,
|
||||
"iso-8859-9": 1, "iso-ir-148": 1, "iso8859-9": 1, "iso88599": 1,
|
||||
"iso_8859-9": 1, "iso_8859-9:1989": 1, "l5": 1, "latin5": 1,
|
||||
"windows-1254": 1, "x-cp1254": 1, "cp1255": 1, "windows-1255": 1,
|
||||
"x-cp1255": 1, "cp1256": 1, "windows-1256": 1, "x-cp1256": 1, "cp1257": 1,
|
||||
"windows-1257": 1, "x-cp1257": 1, "cp1258": 1, "windows-1258": 1,
|
||||
"x-cp1258": 1, "x-mac-cyrillic": 1, "x-mac-ukrainian": 1, "chinese": 1,
|
||||
"csgb2312": 1, "csiso58gb231280": 1, "gb2312": 1, "gb_2312": 1,
|
||||
"gb_2312-80": 1, "gbk": 1, "iso-ir-58": 1, "x-gbk": 1, "gb18030": 1,
|
||||
"hz-gb-2312": 1, "big5": 1, "big5-hkscs": 1, "cn-big5": 1, "csbig5": 1,
|
||||
"x-x-big5": 1, "cseucpkdfmtjapanese": 1, "euc-jp": 1, "x-euc-jp": 1,
|
||||
"csiso2022jp": 1, "iso-2022-jp": 1, "csshiftjis": 1, "ms_kanji": 1,
|
||||
"shift-jis": 1, "shift_jis": 1, "sjis": 1, "windows-31j": 1, "x-sjis": 1,
|
||||
"cseuckr": 1, "csksc56011987": 1, "euc-kr": 1, "iso-ir-149": 1, "korean": 1,
|
||||
"ks_c_5601-1987": 1, "ks_c_5601-1989": 1, "ksc5601": 1, "ksc_5601": 1,
|
||||
"windows-949": 1, "csiso2022kr": 1, "iso-2022-kr": 1, "utf-16": 1,
|
||||
"utf-16le": 1, "utf-16be": 1, "x-user-defined": 1 };
|
||||
exports.testOverflowedBuffers = function (assert) {
|
||||
assert.throws(function() {
|
||||
new Buffer(0xFFFFFFFF);
|
||||
}, RangeError, 'correctly throws buffer overflow');
|
||||
|
||||
assert.throws(function() {
|
||||
new Buffer(0xFFFFFFFFF);
|
||||
}, RangeError, 'correctly throws buffer overflow');
|
||||
|
||||
assert.throws(function() {
|
||||
var buf = new Buffer(8);
|
||||
buf.readFloatLE(0xffffffff);
|
||||
}, RangeError, 'correctly throws buffer overflow with readFloatLE');
|
||||
|
||||
assert.throws(function() {
|
||||
var buf = new Buffer(8);
|
||||
buf.writeFloatLE(0.0, 0xffffffff);
|
||||
}, RangeError, 'correctly throws buffer overflow with writeFloatLE');
|
||||
|
||||
//ensure negative values can't get past offset
|
||||
assert.throws(function() {
|
||||
var buf = new Buffer(8);
|
||||
buf.readFloatLE(-1);
|
||||
}, RangeError, 'correctly throws with readFloatLE negative values');
|
||||
|
||||
assert.throws(function() {
|
||||
var buf = new Buffer(8);
|
||||
buf.writeFloatLE(0.0, -1);
|
||||
}, RangeError, 'correctly throws with writeFloatLE with negative values');
|
||||
|
||||
assert.throws(function() {
|
||||
var buf = new Buffer(8);
|
||||
buf.readFloatLE(-1);
|
||||
}, RangeError, 'correctly throws with readFloatLE with negative values');
|
||||
};
|
||||
|
||||
exports.testReadWriteDataTypeErrors = function (assert) {
|
||||
var buf = new Buffer(0);
|
||||
assert.throws(function() { buf.readUInt8(0); }, RangeError,
|
||||
'readUInt8(0) throws');
|
||||
assert.throws(function() { buf.readInt8(0); }, RangeError,
|
||||
'readInt8(0) throws');
|
||||
|
||||
[16, 32].forEach(function(bits) {
|
||||
var buf = new Buffer(bits / 8 - 1);
|
||||
assert.throws(function() { buf['readUInt' + bits + 'BE'](0); },
|
||||
RangeError,
|
||||
'readUInt' + bits + 'BE');
|
||||
|
||||
assert.throws(function() { buf['readUInt' + bits + 'LE'](0); },
|
||||
RangeError,
|
||||
'readUInt' + bits + 'LE');
|
||||
|
||||
assert.throws(function() { buf['readInt' + bits + 'BE'](0); },
|
||||
RangeError,
|
||||
'readInt' + bits + 'BE()');
|
||||
|
||||
assert.throws(function() { buf['readInt' + bits + 'LE'](0); },
|
||||
RangeError,
|
||||
'readInt' + bits + 'LE()');
|
||||
});
|
||||
};
|
||||
|
||||
safeMerge(exports, require('./buffers/test-write-types'));
|
||||
safeMerge(exports, require('./buffers/test-read-types'));
|
||||
|
||||
function compareBuffers (assert, buf1, buf2, message) {
|
||||
let status = true;
|
||||
for (let i = 0; i < Math.min(buf1.length, buf2.length); i++) {
|
||||
if (buf1[i] !== buf2[i])
|
||||
status = false;
|
||||
}
|
||||
assert.ok(status, 'buffer successfully copied: ' + message);
|
||||
}
|
||||
require('sdk/test').run(exports);
|
||||
|
@ -5,6 +5,7 @@
|
||||
"use strict";
|
||||
const { Loader } = require('sdk/content/loader');
|
||||
const self = require("sdk/self");
|
||||
const fixtures = require("./fixtures");
|
||||
|
||||
exports['test:contentURL'] = function(assert) {
|
||||
let loader = Loader(),
|
||||
@ -172,7 +173,7 @@ exports['test:contentScript'] = function(assert) {
|
||||
};
|
||||
|
||||
exports['test:contentScriptFile'] = function(assert) {
|
||||
let loader = Loader(), value, uri = self.data.url("test-content-loader.js");
|
||||
let loader = Loader(), value, uri = fixtures.url("test-content-loader.js");
|
||||
assert.equal(
|
||||
null,
|
||||
loader.contentScriptFile,
|
||||
|
@ -7,7 +7,7 @@ const { create: makeFrame } = require("sdk/frame/utils");
|
||||
const { window } = require("sdk/addon/window");
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { URL } = require("sdk/url");
|
||||
const testURI = require("sdk/self").data.url("test.html");
|
||||
const testURI = require("./fixtures").url("test.html");
|
||||
const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
|
||||
|
||||
/*
|
||||
|
@ -6,6 +6,7 @@
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { Symbiont } = require('sdk/content/symbiont');
|
||||
const self = require('sdk/self');
|
||||
const fixtures = require("./fixtures");
|
||||
const { close } = require('sdk/window/helpers');
|
||||
const app = require("sdk/system/xul-app");
|
||||
|
||||
@ -27,7 +28,7 @@ function makeWindow() {
|
||||
|
||||
exports['test:constructing symbiont && validating API'] = function(assert) {
|
||||
let contentScript = ["1;", "2;"];
|
||||
let contentScriptFile = self.data.url("test-content-symbiont.js");
|
||||
let contentScriptFile = fixtures.url("test-content-symbiont.js");
|
||||
|
||||
// We can avoid passing a `frame` argument. Symbiont will create one
|
||||
// by using HiddenFrame module
|
||||
@ -75,6 +76,8 @@ exports["test:communication with worker global scope"] = function(assert, done)
|
||||
let window = makeWindow();
|
||||
let contentSymbiont;
|
||||
|
||||
console.log(window)
|
||||
|
||||
function onMessage1(message) {
|
||||
assert.equal(message, 1, "Program gets message via onMessage.");
|
||||
contentSymbiont.removeListener('message', onMessage1);
|
||||
@ -154,33 +157,4 @@ exports["test:document element present on 'start'"] = function(assert, done) {
|
||||
});
|
||||
};
|
||||
|
||||
exports["test:direct communication with trusted document"] = function(assert, done) {
|
||||
let worker = Symbiont({
|
||||
contentURL: require("sdk/self").data.url("test-trusted-document.html")
|
||||
});
|
||||
|
||||
worker.port.on('document-to-addon', function (arg) {
|
||||
assert.equal(arg, "ok", "Received an event from the document");
|
||||
worker.destroy();
|
||||
done();
|
||||
});
|
||||
worker.port.emit('addon-to-document', 'ok');
|
||||
};
|
||||
|
||||
exports["test:`addon` is not available when a content script is set"] = function(assert, done) {
|
||||
let worker = Symbiont({
|
||||
contentURL: require("sdk/self").data.url("test-trusted-document.html"),
|
||||
contentScript: "new " + function ContentScriptScope() {
|
||||
self.port.emit("cs-to-addon", "addon" in unsafeWindow);
|
||||
}
|
||||
});
|
||||
|
||||
worker.port.on('cs-to-addon', function (hasAddon) {
|
||||
assert.equal(hasAddon, false,
|
||||
"`addon` is not available");
|
||||
worker.destroy();
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
require("test").run(exports);
|
||||
|
@ -21,6 +21,7 @@ const OVERFLOW_MENU_CLASS = "addon-content-menu-overflow-menu";
|
||||
const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup";
|
||||
|
||||
const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html");
|
||||
const data = require("./fixtures");
|
||||
|
||||
// Tests that when present the separator is placed before the separator from
|
||||
// the old context-menu module
|
||||
@ -894,7 +895,7 @@ exports.testContentScriptFile = function (assert, done) {
|
||||
// But accept files from data folder
|
||||
let item = new loader.cm.Item({
|
||||
label: "item",
|
||||
contentScriptFile: require("sdk/self").data.url("test-context-menu.js")
|
||||
contentScriptFile: data.url("test-context-menu.js")
|
||||
});
|
||||
|
||||
test.showMenu(null, function (popup) {
|
||||
@ -2669,7 +2670,7 @@ exports.testItemImage = function (assert, done) {
|
||||
let test = new TestHelper(assert, done);
|
||||
let loader = test.newLoader();
|
||||
|
||||
let imageURL = require("sdk/self").data.url("moz_favicon.ico");
|
||||
let imageURL = data.url("moz_favicon.ico");
|
||||
let item = new loader.cm.Item({ label: "item", image: imageURL });
|
||||
let menu = new loader.cm.Menu({ label: "menu", image: imageURL, items: [
|
||||
loader.cm.Item({ label: "subitem" })
|
||||
@ -2680,7 +2681,7 @@ exports.testItemImage = function (assert, done) {
|
||||
test.showMenu(null, function (popup) {
|
||||
test.checkMenu([item, menu], [], []);
|
||||
|
||||
let imageURL2 = require("sdk/self").data.url("dummy.ico");
|
||||
let imageURL2 = data.url("dummy.ico");
|
||||
item.image = imageURL2;
|
||||
menu.image = imageURL2;
|
||||
assert.equal(item.image, imageURL2, "Should have set the image correctly");
|
||||
@ -2701,7 +2702,7 @@ exports.testItemImage = function (assert, done) {
|
||||
exports.testItemImageValidURL = function (assert, done) {
|
||||
let test = new TestHelper(assert, done);
|
||||
let loader = test.newLoader();
|
||||
|
||||
|
||||
assert.throws(function(){
|
||||
new loader.cm.Item({
|
||||
label: "item 1",
|
||||
@ -2725,8 +2726,8 @@ exports.testItemImageValidURL = function (assert, done) {
|
||||
})
|
||||
}, /Image URL validation failed/
|
||||
);
|
||||
|
||||
let imageURL = require("sdk/self").data.url("moz_favicon.ico");
|
||||
|
||||
let imageURL = data.url("moz_favicon.ico");
|
||||
let item4 = new loader.cm.Item({ label: "item 4", image: imageURL });
|
||||
let item5 = new loader.cm.Item({ label: "item 5", image: null });
|
||||
let item6 = new loader.cm.Item({ label: "item 6", image: undefined });
|
||||
@ -3228,7 +3229,7 @@ TestHelper.prototype = {
|
||||
},
|
||||
|
||||
// Asserts that the context menu looks OK given the arguments. presentItems
|
||||
// are items that have been added to the menu. absentItems are items that
|
||||
// are items that have been added to the menu. absentItems are items that
|
||||
// shouldn't match the current context. removedItems are items that have been
|
||||
// removed from the menu.
|
||||
checkMenu: function (presentItems, absentItems, removedItems) {
|
||||
|
@ -36,7 +36,7 @@ exports['test syntax errors'] = function(assert) {
|
||||
assert.equal(error.name, "SyntaxError", "throws syntax error");
|
||||
assert.equal(error.fileName.split("/").pop(), "error.js",
|
||||
"Error contains filename");
|
||||
assert.equal(error.lineNumber, 11, "error is on line 11")
|
||||
assert.equal(error.lineNumber, 11, "error is on line 11");
|
||||
let stack = parseStack(error.stack);
|
||||
|
||||
assert.equal(stack.pop().fileName, uri + "error.js",
|
||||
@ -147,7 +147,41 @@ exports['test early errors in module'] = function(assert) {
|
||||
} finally {
|
||||
unload(loader);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports['test require json'] = function (assert) {
|
||||
let data = require('./fixtures/loader/json/manifest.json');
|
||||
assert.equal(data.name, 'Jetpack Loader Test', 'loads json with strings');
|
||||
assert.equal(data.version, '1.0.1', 'loads json with strings');
|
||||
assert.equal(data.dependencies.async, '*', 'loads json with objects');
|
||||
assert.equal(data.dependencies.underscore, '*', 'loads json with objects');
|
||||
assert.equal(data.contributors.length, 4, 'loads json with arrays');
|
||||
assert.ok(Array.isArray(data.contributors), 'loads json with arrays');
|
||||
data.version = '2.0.0';
|
||||
let newdata = require('./fixtures/loader/json/manifest.json');
|
||||
assert.equal(newdata.version, '2.0.0',
|
||||
'JSON objects returned should be cached and the same instance');
|
||||
|
||||
try {
|
||||
require('./fixtures/loader/json/invalid.json');
|
||||
assert.fail('Error not thrown when loading invalid json');
|
||||
} catch (err) {
|
||||
assert.ok(err, 'error thrown when loading invalid json');
|
||||
assert.ok(/JSON\.parse/.test(err.message),
|
||||
'should thrown an error from JSON.parse, not attempt to load .json.js');
|
||||
}
|
||||
|
||||
// Try again to ensure an empty module isn't loaded from cache
|
||||
try {
|
||||
require('./fixtures/loader/json/invalid.json');
|
||||
assert.fail('Error not thrown when loading invalid json a second time');
|
||||
} catch (err) {
|
||||
assert.ok(err,
|
||||
'error thrown when loading invalid json a second time');
|
||||
assert.ok(/JSON\.parse/.test(err.message),
|
||||
'should thrown an error from JSON.parse a second time, not attempt to load .json.js');
|
||||
}
|
||||
};
|
||||
|
||||
exports['test setting metadata for newly created sandboxes'] = function(assert) {
|
||||
let addonID = 'random-addon-id';
|
||||
@ -165,6 +199,23 @@ exports['test setting metadata for newly created sandboxes'] = function(assert)
|
||||
}
|
||||
|
||||
let program = main(loader, 'main');
|
||||
}
|
||||
};
|
||||
|
||||
exports['test require .json, .json.js'] = function (assert) {
|
||||
let testjson = require('./fixtures/loader/json/test.json');
|
||||
assert.equal(testjson.filename, 'test.json',
|
||||
'require("./x.json") should load x.json, not x.json.js');
|
||||
|
||||
let nodotjson = require('./fixtures/loader/json/nodotjson.json');
|
||||
assert.equal(nodotjson.filename, 'nodotjson.json.js',
|
||||
'require("./x.json") should load x.json.js when x.json does not exist');
|
||||
nodotjson.data.prop = 'hydralisk';
|
||||
|
||||
// require('nodotjson.json') and require('nodotjson.json.js')
|
||||
// should resolve to the same file
|
||||
let nodotjsonjs = require('./fixtures/loader/json/nodotjson.json.js');
|
||||
assert.equal(nodotjsonjs.data.prop, 'hydralisk',
|
||||
'js modules are cached whether access via .json.js or .json');
|
||||
};
|
||||
|
||||
require('test').run(exports);
|
||||
|
@ -5,7 +5,7 @@
|
||||
"use strict";
|
||||
|
||||
const { readURI, readURISync } = require("sdk/net/url");
|
||||
const { data } = require("sdk/self");
|
||||
const data = require("./fixtures");
|
||||
|
||||
const utf8text = "Hello, ゼロ!";
|
||||
const latin1text = "Hello, ゼãƒ!";
|
||||
|
@ -13,15 +13,18 @@ const { open, getFrames, getMostRecentBrowserWindow } = require('sdk/window/util
|
||||
const windowUtils = require('sdk/deprecated/window-utils');
|
||||
const { getTabContentWindow, getActiveTab, setTabURL, openTab, closeTab } = require('sdk/tabs/utils');
|
||||
const xulApp = require("sdk/system/xul-app");
|
||||
const { data, isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { openWebpage } = require('./private-browsing/helper');
|
||||
const { isTabPBSupported, isWindowPBSupported, isGlobalPBSupported } = require('sdk/private-browsing/utils');
|
||||
const promise = require("sdk/core/promise");
|
||||
const { pb } = require('./private-browsing/helper');
|
||||
const { URL } = require("sdk/url");
|
||||
const testPageURI = require("sdk/self").data.url("test.html");
|
||||
|
||||
const { waitUntil } = require("sdk/test/utils");
|
||||
const data = require("./fixtures");
|
||||
|
||||
const testPageURI = data.url("test.html");
|
||||
|
||||
// The following adds Debugger constructor to the global namespace.
|
||||
const { addDebuggerToGlobal } =
|
||||
@ -311,7 +314,7 @@ exports.testHistory = function(assert, done) {
|
||||
// We need a valid url in order to have a working History API.
|
||||
// (i.e do not work on data: or about: pages)
|
||||
// Test bug 679054.
|
||||
let url = require("sdk/self").data.url("test-page-mod.html");
|
||||
let url = data.url("test-page-mod.html");
|
||||
let callbackDone = null;
|
||||
testPageMod(assert, done, url, [{
|
||||
include: url,
|
||||
@ -691,8 +694,7 @@ exports.testPageModCss = function(assert, done) {
|
||||
'data:text/html;charset=utf-8,<div style="background: silver">css test</div>', [{
|
||||
include: ["*", "data:*"],
|
||||
contentStyle: "div { height: 100px; }",
|
||||
contentStyleFile:
|
||||
require("sdk/self").data.url("pagemod-css-include-file.css")
|
||||
contentStyleFile: data.url("pagemod-css-include-file.css")
|
||||
}],
|
||||
function(win, done) {
|
||||
let div = win.document.querySelector("div");
|
||||
|
@ -8,7 +8,8 @@ const { Loader } = require('sdk/test/loader');
|
||||
const Pages = require("sdk/page-worker");
|
||||
const Page = Pages.Page;
|
||||
const { URL } = require("sdk/url");
|
||||
const testURI = require("sdk/self").data.url("test.html");
|
||||
const fixtures = require("./fixtures");
|
||||
const testURI = fixtures.url("test.html");
|
||||
|
||||
const ERR_DESTROYED =
|
||||
"Couldn't find the worker to receive this message. " +
|
||||
@ -264,8 +265,8 @@ exports.testLoadContentPage = function(assert, done) {
|
||||
return done();
|
||||
assert[msg].apply(assert, message);
|
||||
},
|
||||
contentURL: require("sdk/self").data.url("test-page-worker.html"),
|
||||
contentScriptFile: require("sdk/self").data.url("test-page-worker.js"),
|
||||
contentURL: fixtures.url("test-page-worker.html"),
|
||||
contentScriptFile: fixtures.url("test-page-worker.js"),
|
||||
contentScriptWhen: "ready"
|
||||
});
|
||||
}
|
||||
|
@ -22,8 +22,9 @@ const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { getWindow } = require('sdk/panel/window');
|
||||
const { pb } = require('./private-browsing/helper');
|
||||
const { URL } = require('sdk/url');
|
||||
const fixtures = require('./fixtures')
|
||||
|
||||
const SVG_URL = self.data.url('mofo_logo.SVG');
|
||||
const SVG_URL = fixtures.url('mofo_logo.SVG');
|
||||
const Isolate = fn => '(' + fn + ')()';
|
||||
|
||||
function ignorePassingDOMNodeWarning(type, message) {
|
||||
|
@ -276,6 +276,21 @@ exports['test promised error handleing'] = function(assert, done) {
|
||||
})
|
||||
}
|
||||
|
||||
exports['test errors in promise resolution handlers are propagated'] = function(assert, done) {
|
||||
var expected = Error('Boom');
|
||||
var { promise, resolve } = defer();
|
||||
|
||||
promise.then(function() {
|
||||
throw expected;
|
||||
}).then(function() {
|
||||
return undefined;
|
||||
}).then(null, function(actual) {
|
||||
assert.equal(actual, expected, 'rejected as expected');
|
||||
}).then(done, assert.fail);
|
||||
|
||||
resolve({});
|
||||
}
|
||||
|
||||
exports['test return promise form promised'] = function(assert, done) {
|
||||
var f = promised(function() {
|
||||
return resolve(17)
|
||||
|
@ -10,9 +10,6 @@ const self = require("sdk/self");
|
||||
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
|
||||
exports.testSelf = function(assert) {
|
||||
var source = self.data.load("test-content-symbiont.js");
|
||||
assert.ok(source.match(/test-content-symbiont/), "self.data.load() works");
|
||||
|
||||
// Likewise, we can't assert anything about the full URL, because that
|
||||
// depends on self.id . We can only assert that it ends in the right
|
||||
// thing.
|
||||
|
@ -17,7 +17,7 @@ exports["test basic"] = function(assert) {
|
||||
let type = Date.now().toString(32);
|
||||
|
||||
let timesCalled = 0;
|
||||
function handler(subject, data) { timesCalled++; };
|
||||
function handler({subject, data}) { timesCalled++; };
|
||||
|
||||
events.on(type, handler);
|
||||
events.emit(type, { data: "yo yo" });
|
||||
@ -36,6 +36,32 @@ exports["test basic"] = function(assert) {
|
||||
assert.equal(timesCalled, 2, "handlers added via once are triggered once");
|
||||
}
|
||||
|
||||
exports["test simple argument passing"] = function (assert) {
|
||||
let type = Date.now().toString(32);
|
||||
|
||||
let lastArg;
|
||||
function handler({data}) { lastArg = data; }
|
||||
events.on(type, handler);
|
||||
|
||||
[true, false, 100, 0, 'a string', ''].forEach(arg => {
|
||||
events.emit(type, arg);
|
||||
assert.strictEqual(lastArg, arg + '',
|
||||
'event emitted for ' + arg + ' has correct data value');
|
||||
|
||||
events.emit(type, { data: arg });
|
||||
assert.strictEqual(lastArg, arg + '',
|
||||
'event emitted for ' + arg + ' has correct data value when a property on an object');
|
||||
});
|
||||
|
||||
[null, undefined, {}].forEach(arg => {
|
||||
events.emit(type, arg);
|
||||
assert.strictEqual(lastArg, null,
|
||||
'emitting ' + arg + ' gets null data');
|
||||
});
|
||||
|
||||
events.off(type, handler);
|
||||
};
|
||||
|
||||
exports["test error reporting"] = function(assert) {
|
||||
let { loader, messages } = LoaderWithHookedConsole2(module);
|
||||
|
||||
@ -220,7 +246,7 @@ exports["test emit to nsIObserverService observers"] = function(assert) {
|
||||
assert.equal(lastData, "data again", "event.data is notification data");
|
||||
|
||||
nsIObserverService.removeObserver(nsIObserver, "*");
|
||||
|
||||
|
||||
events.emit(topic, { data: "last data" });
|
||||
assert.equal(timesCalled, 3, "removed observers no longer invoked");
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ module.metadata = {
|
||||
|
||||
const { Cu } = require('chrome');
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { data } = require('sdk/self');
|
||||
const data = require('./fixtures');
|
||||
const { open, focus, close } = require('sdk/window/helpers');
|
||||
const { setTimeout } = require('sdk/timers');
|
||||
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
|
@ -15,9 +15,9 @@ const { show, hide } = require('sdk/ui/sidebar/actions');
|
||||
const { isShowing } = require('sdk/ui/sidebar/utils');
|
||||
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
|
||||
const { setTimeout } = require('sdk/timers');
|
||||
const { setTimeout, setImmediate } = require('sdk/timers');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { data } = require('sdk/self');
|
||||
const data = require('./fixtures');
|
||||
const { URL } = require('sdk/url');
|
||||
const { once, off, emit } = require('sdk/event/core');
|
||||
const { defer, all } = require('sdk/core/promise');
|
||||
@ -251,6 +251,32 @@ exports.testAddonGlobalComplex = function(assert, done) {
|
||||
show(sidebar);
|
||||
}
|
||||
|
||||
exports.testAddonReady = function(assert, done) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testAddonReady';
|
||||
let sidebar = Sidebar({
|
||||
id: testName,
|
||||
title: testName,
|
||||
url: data.url('test-sidebar-addon-global.html'),
|
||||
onReady: function(worker) {
|
||||
assert.pass('sidebar was attached');
|
||||
assert.ok(!!worker, 'attach event has worker');
|
||||
|
||||
worker.port.on('X', function(msg) {
|
||||
assert.equal(msg, '123', 'the final message is correct');
|
||||
|
||||
sidebar.destroy();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
worker.port.emit('X', '12');
|
||||
}
|
||||
});
|
||||
|
||||
show(sidebar);
|
||||
}
|
||||
|
||||
exports.testShowingOneSidebarAfterAnother = function(assert, done) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testShowingOneSidebarAfterAnother';
|
||||
@ -356,7 +382,7 @@ exports.testRemoteContent = function(assert) {
|
||||
sidebar.destroy();
|
||||
}
|
||||
catch(e) {
|
||||
assert.ok(/The option "url" must be a valid URI./.test(e), 'remote content is not acceptable');
|
||||
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'remote content is not acceptable');
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,7 +399,7 @@ exports.testInvalidURL = function(assert) {
|
||||
sidebar.destroy();
|
||||
}
|
||||
catch(e) {
|
||||
assert.ok(/The option "url" must be a valid URI./.test(e), 'invalid URIs are not acceptable');
|
||||
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,7 +415,7 @@ exports.testInvalidURLType = function(assert) {
|
||||
sidebar.destroy();
|
||||
}
|
||||
catch(e) {
|
||||
assert.ok(/The option "url" must be a valid URI./.test(e), 'invalid URIs are not acceptable');
|
||||
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,19 +487,24 @@ exports.testInvalidNullID = function(assert) {
|
||||
}
|
||||
}
|
||||
|
||||
exports.testInvalidUndefinedID = function(assert) {
|
||||
exports.testUndefinedID = function(assert) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testInvalidBlankID';
|
||||
let testName = 'testInvalidUndefinedID';
|
||||
|
||||
try {
|
||||
let sidebar = Sidebar({
|
||||
title: testName,
|
||||
url: 'data:text/html;charset=utf-8,'+testName
|
||||
url: 'data:text/html;charset=utf-8,' + testName
|
||||
});
|
||||
assert.fail('a bad sidebar was created..');
|
||||
|
||||
assert.ok(sidebar.id, 'an undefined id was accepted, id was creawted: ' + sidebar.id);
|
||||
assert.ok(getMostRecentBrowserWindow().document.getElementById(makeID(sidebar.id)), 'the sidebar element was found');
|
||||
|
||||
sidebar.destroy();
|
||||
}
|
||||
catch(e) {
|
||||
assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
|
||||
assert.fail('undefined ids are acceptable');
|
||||
assert.fail(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,6 +923,64 @@ exports.testGCdShowingSidebarsOnUnload = function(assert, done) {
|
||||
sidebar.show();
|
||||
}
|
||||
|
||||
exports.testDetachEventOnWindowClose = function(assert, done) {
|
||||
const loader = Loader(module);
|
||||
const { Sidebar } = loader.require('sdk/ui/sidebar');
|
||||
const window = getMostRecentBrowserWindow();
|
||||
|
||||
let testName = 'testDetachEventOnWindowClose';
|
||||
let url = 'data:text/html;charset=utf-8,' + testName;
|
||||
|
||||
|
||||
windowPromise(window.OpenBrowserWindow(), 'load').then(focus).then(function(window) {
|
||||
let sidebar = Sidebar({
|
||||
id: testName,
|
||||
title: testName,
|
||||
url: url,
|
||||
onAttach: function() {
|
||||
assert.pass('the attach event is fired');
|
||||
window.close();
|
||||
},
|
||||
onDetach: function() {
|
||||
assert.pass('the detach event is fired when the window showing it closes');
|
||||
loader.unload();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.show();
|
||||
}).then(null, assert.fail);
|
||||
}
|
||||
|
||||
exports.testHideEventOnWindowClose = function(assert, done) {
|
||||
const loader = Loader(module);
|
||||
const { Sidebar } = loader.require('sdk/ui/sidebar');
|
||||
const window = getMostRecentBrowserWindow();
|
||||
|
||||
let testName = 'testDetachEventOnWindowClose';
|
||||
let url = 'data:text/html;charset=utf-8,' + testName;
|
||||
|
||||
|
||||
windowPromise(window.OpenBrowserWindow(), 'load').then(focus).then(function(window) {
|
||||
let sidebar = Sidebar({
|
||||
id: testName,
|
||||
title: testName,
|
||||
url: url,
|
||||
onAttach: function() {
|
||||
assert.pass('the attach event is fired');
|
||||
window.close();
|
||||
},
|
||||
onHide: function() {
|
||||
assert.pass('the hide event is fired when the window showing it closes');
|
||||
loader.unload();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.show();
|
||||
}).then(null, assert.fail);
|
||||
}
|
||||
|
||||
exports.testGCdHiddenSidebarsOnUnload = function(assert, done) {
|
||||
const loader = Loader(module);
|
||||
const { Sidebar } = loader.require('sdk/ui/sidebar');
|
||||
@ -1078,6 +1167,35 @@ exports.testTwoSidebarsWithSameTitleAndURL = function(assert) {
|
||||
sidebar2.destroy();
|
||||
}
|
||||
|
||||
exports.testChangingURLBackToOriginalValue = function(assert) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testChangingURLBackToOriginalValue';
|
||||
|
||||
let title = testName;
|
||||
let url = 'data:text/html;charset=utf-8,' + testName;
|
||||
let count = 0;
|
||||
|
||||
let sidebar = Sidebar({
|
||||
id: testName,
|
||||
title: title,
|
||||
url: url
|
||||
});
|
||||
|
||||
sidebar.url = url + 2;
|
||||
assert.equal(sidebar.url, url + 2, 'the sidebar.url is correct');
|
||||
sidebar.url = url;
|
||||
assert.equal(sidebar.url, url, 'the sidebar.url is correct');
|
||||
|
||||
sidebar.title = 'foo';
|
||||
assert.equal(sidebar.title, 'foo', 'the sidebar.title is correct');
|
||||
sidebar.title = title;
|
||||
assert.equal(sidebar.title, title, 'the sidebar.title is correct');
|
||||
|
||||
sidebar.destroy();
|
||||
|
||||
assert.pass('Changing values back to originals works');
|
||||
}
|
||||
|
||||
exports.testShowToOpenXToClose = function(assert, done) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testShowToOpenXToClose';
|
||||
@ -1181,14 +1299,17 @@ exports.testEventListeners = function(assert, done) {
|
||||
let constructorOnShow = defer();
|
||||
let constructorOnHide = defer();
|
||||
let constructorOnAttach = defer();
|
||||
let constructorOnReady = defer();
|
||||
|
||||
let onShow = defer();
|
||||
let onHide = defer();
|
||||
let onAttach = defer();
|
||||
let onReady = defer();
|
||||
|
||||
let onceShow = defer();
|
||||
let onceHide = defer();
|
||||
let onceAttach = defer();
|
||||
let onceReady = defer();
|
||||
|
||||
function testThis() {
|
||||
assert(this, sidebar, '`this` is correct');
|
||||
@ -1208,6 +1329,11 @@ exports.testEventListeners = function(assert, done) {
|
||||
eventListenerOrder.push('onAttach');
|
||||
constructorOnAttach.resolve();
|
||||
},
|
||||
onReady: function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in onReady');
|
||||
eventListenerOrder.push('onReady');
|
||||
constructorOnReady.resolve();
|
||||
},
|
||||
onHide: function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in onHide');
|
||||
eventListenerOrder.push('onHide');
|
||||
@ -1225,6 +1351,11 @@ exports.testEventListeners = function(assert, done) {
|
||||
eventListenerOrder.push('once attach');
|
||||
onceAttach.resolve();
|
||||
});
|
||||
sidebar.once('ready', function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in once ready');
|
||||
eventListenerOrder.push('once ready');
|
||||
onceReady.resolve();
|
||||
});
|
||||
sidebar.once('hide', function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in once hide');
|
||||
eventListenerOrder.push('once hide');
|
||||
@ -1243,6 +1374,11 @@ exports.testEventListeners = function(assert, done) {
|
||||
eventListenerOrder.push('on attach');
|
||||
onAttach.resolve();
|
||||
});
|
||||
sidebar.on('ready', function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in on ready');
|
||||
eventListenerOrder.push('on ready');
|
||||
onReady.resolve();
|
||||
});
|
||||
sidebar.on('hide', function() {
|
||||
assert.equal(this, sidebar, '`this` is correct in on hide');
|
||||
eventListenerOrder.push('on hide');
|
||||
@ -1251,17 +1387,23 @@ exports.testEventListeners = function(assert, done) {
|
||||
|
||||
all(constructorOnShow.promise,
|
||||
constructorOnAttach.promise,
|
||||
constructorOnReady.promise,
|
||||
constructorOnHide.promise,
|
||||
onceShow.promise,
|
||||
onceAttach.promise,
|
||||
onceReady.promise,
|
||||
onceHide.promise,
|
||||
onShow.promise,
|
||||
onAttach.promise,
|
||||
onReady.promise,
|
||||
onHide.promise).then(function() {
|
||||
assert.equal(eventListenerOrder.join(), [
|
||||
'onAttach',
|
||||
'once attach',
|
||||
'on attach',
|
||||
'onReady',
|
||||
'once ready',
|
||||
'on ready',
|
||||
'onShow',
|
||||
'once show',
|
||||
'on show',
|
||||
@ -1275,6 +1417,58 @@ exports.testEventListeners = function(assert, done) {
|
||||
sidebar.show();
|
||||
}
|
||||
|
||||
// For more information see Bug 920780
|
||||
exports.testAttachDoesNotEmitWhenShown = function(assert, done) {
|
||||
const { Sidebar } = require('sdk/ui/sidebar');
|
||||
let testName = 'testSidebarLeakCheckUnloadAfterAttach';
|
||||
let count = 0;
|
||||
|
||||
let sidebar = Sidebar({
|
||||
id: testName,
|
||||
title: testName,
|
||||
url: 'data:text/html;charset=utf-8,'+testName,
|
||||
onAttach: function() {
|
||||
if (count > 2) {
|
||||
assert.fail('sidebar was attached again..');
|
||||
}
|
||||
else {
|
||||
assert.pass('sidebar was attached ' + count + ' time(s)');
|
||||
}
|
||||
|
||||
if (++count == 1) {
|
||||
setTimeout(function() {
|
||||
let shown = false;
|
||||
let endShownTest = false;
|
||||
sidebar.once('show', function() {
|
||||
assert.pass('shown was emitted');
|
||||
shown = !endShownTest && true;
|
||||
});
|
||||
|
||||
sidebar.show().then(function() {
|
||||
assert.pass('calling hide');
|
||||
sidebar.hide();
|
||||
}).then(function() {
|
||||
endShownTest = true;
|
||||
|
||||
setTimeout(function() {
|
||||
sidebar.show().then(function() {
|
||||
assert.ok(!shown, 'show did not emit');
|
||||
|
||||
sidebar.hide().then(function() {
|
||||
sidebar.destroy();
|
||||
done();
|
||||
}).then(null, assert.fail);
|
||||
})
|
||||
})
|
||||
}).then(null, assert.fail);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.show();
|
||||
}
|
||||
|
||||
// If the module doesn't support the app we're being run in, require() will
|
||||
// throw. In that case, remove all tests above from exports, and add one dummy
|
||||
// test that passes.
|
||||
|
@ -18,6 +18,7 @@ const self = require("sdk/self");
|
||||
const windowUtils = require("sdk/deprecated/window-utils");
|
||||
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { close } = require("sdk/window/helpers");
|
||||
const fixtures = require("./fixtures");
|
||||
|
||||
let jetpackID = "testID";
|
||||
try {
|
||||
@ -243,7 +244,7 @@ exports.testConstructor = function(assert, done) {
|
||||
tests.push(function testImageURLWidget() testSingleWidget({
|
||||
id: "image",
|
||||
label: "image url widget",
|
||||
contentURL: require("sdk/self").data.url("test.html"),
|
||||
contentURL: fixtures.url("test.html"),
|
||||
contentScript: "self.postMessage({title: document.title, " +
|
||||
"tag: document.body.firstElementChild.tagName, " +
|
||||
"content: document.body.firstElementChild.innerHTML});",
|
||||
@ -261,7 +262,7 @@ exports.testConstructor = function(assert, done) {
|
||||
tests.push(function testWebURIWidget() testSingleWidget({
|
||||
id: "web",
|
||||
label: "web uri widget",
|
||||
contentURL: require("sdk/self").data.url("test.html"),
|
||||
contentURL: fixtures.url("test.html"),
|
||||
contentScript: "self.postMessage({title: document.title, " +
|
||||
"tag: document.body.firstElementChild.tagName, " +
|
||||
"content: document.body.firstElementChild.innerHTML});",
|
||||
@ -324,7 +325,7 @@ exports.testConstructor = function(assert, done) {
|
||||
tests.push(function testOnclickEventImage() testSingleWidget({
|
||||
id: "click",
|
||||
label: "click test widget - image",
|
||||
contentURL: require("sdk/self").data.url("moz_favicon.ico"),
|
||||
contentURL: fixtures.url("moz_favicon.ico"),
|
||||
contentScript: "var evt = new MouseEvent('click'); " +
|
||||
"document.body.firstElementChild.dispatchEvent(evt);",
|
||||
contentScriptWhen: "end",
|
||||
@ -339,7 +340,7 @@ exports.testConstructor = function(assert, done) {
|
||||
tests.push(function testOnmouseoverEventImage() testSingleWidget({
|
||||
id: "mouseover",
|
||||
label: "mouseover test widget - image",
|
||||
contentURL: require("sdk/self").data.url("moz_favicon.ico"),
|
||||
contentURL: fixtures.url("moz_favicon.ico"),
|
||||
contentScript: "var evt = new MouseEvent('mouseover');" +
|
||||
"document.body.firstElementChild.dispatchEvent(evt);",
|
||||
contentScriptWhen: "end",
|
||||
@ -354,7 +355,7 @@ exports.testConstructor = function(assert, done) {
|
||||
tests.push(function testOnmouseoutEventImage() testSingleWidget({
|
||||
id: "mouseout",
|
||||
label: "mouseout test widget - image",
|
||||
contentURL: require("sdk/self").data.url("moz_favicon.ico"),
|
||||
contentURL: fixtures.url("moz_favicon.ico"),
|
||||
contentScript: "var evt = new MouseEvent('mouseout'); " +
|
||||
"document.body.firstElementChild.dispatchEvent(evt);",
|
||||
contentScriptWhen: "end",
|
||||
@ -1034,7 +1035,7 @@ exports.testPostMessageOnLocationChange = function(assert, done) {
|
||||
|
||||
exports.testSVGWidget = function(assert, done) {
|
||||
// use of capital SVG here is intended, that was failing..
|
||||
let SVG_URL = self.data.url("mofo_logo.SVG");
|
||||
let SVG_URL = fixtures.url("mofo_logo.SVG");
|
||||
|
||||
let widget = require("sdk/widget").Widget({
|
||||
id: "mozilla-svg-logo",
|
||||
|
@ -13,7 +13,7 @@ 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 { open, getFrames, getWindowTitle, onFocus, windows } = require('sdk/window/utils');
|
||||
const { close } = require('sdk/window/helpers');
|
||||
const { fromIterator: toArray } = require('sdk/util/array');
|
||||
|
||||
@ -297,4 +297,29 @@ exports.testWindowIterator = function(assert, done) {
|
||||
}, false);
|
||||
};
|
||||
|
||||
exports.testIgnoreClosingWindow = function(assert, done) {
|
||||
assert.equal(windows().length, 1, "Only one window open");
|
||||
|
||||
// make a new window
|
||||
let window = makeEmptyWindow();
|
||||
|
||||
assert.equal(windows().length, 2, "Two windows open");
|
||||
|
||||
window.addEventListener("load", function onload() {
|
||||
window.addEventListener("load", onload, false);
|
||||
|
||||
assert.equal(windows().length, 2, "Two windows open");
|
||||
|
||||
// Wait for the window unload before ending test
|
||||
let checked = false;
|
||||
|
||||
close(window).then(function() {
|
||||
assert.ok(checked, 'the test is finished');
|
||||
}).then(done, assert.fail)
|
||||
|
||||
assert.equal(windows().length, 1, "Only one window open");
|
||||
checked = true;
|
||||
}, false);
|
||||
};
|
||||
|
||||
require("test").run(exports);
|
||||
|
@ -5,8 +5,9 @@
|
||||
|
||||
const { XMLHttpRequest } = require('sdk/net/xhr');
|
||||
const { LoaderWithHookedConsole } = require('sdk/test/loader');
|
||||
const { data } = require('sdk/self');
|
||||
const { set: setPref } = require("sdk/preferences/service");
|
||||
const data = require("./fixtures");
|
||||
|
||||
const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
|
||||
|
||||
exports.testAPIExtension = function(assert) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
"use strict"
|
||||
|
||||
function debug(str) {
|
||||
//dump("-*- ContentPermissionPrompt: " + str + "\n");
|
||||
//dump("-*- ContentPermissionPrompt: " + s + "\n");
|
||||
}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
@ -13,14 +13,11 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const PROMPT_FOR_UNKNOWN = ["audio-capture",
|
||||
"desktop-notification",
|
||||
"geolocation",
|
||||
"video-capture"];
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
|
||||
"audio-capture"];
|
||||
// Due to privary issue, permission requests like GetUserMedia should prompt
|
||||
// every time instead of providing session persistence.
|
||||
const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
|
||||
const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
|
||||
const PERMISSION_NO_SESSION = ["audio-capture"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -44,21 +41,7 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"@mozilla.org/telephony/audiomanager;1",
|
||||
"nsIAudioManager");
|
||||
|
||||
/**
|
||||
* aTypesInfo is an array of {permission, access, action, deny} which keeps
|
||||
* the information of each permission. This arrary is initialized in
|
||||
* ContentPermissionPrompt.prompt and used among functions.
|
||||
*
|
||||
* aTypesInfo[].permission : permission name
|
||||
* aTypesInfo[].access : permission name + request.access
|
||||
* aTypesInfo[].action : the default action of this permission
|
||||
* aTypesInfo[].deny : true if security manager denied this app's origin
|
||||
* principal.
|
||||
* Note:
|
||||
* aTypesInfo[].permission will be sent to prompt only when
|
||||
* aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
|
||||
*/
|
||||
function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
{
|
||||
function convertPermToAllow(aPerm, aPrincipal)
|
||||
{
|
||||
@ -66,13 +49,12 @@ function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
||||
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
||||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
|
||||
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
|
||||
if (!aSession) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
@ -81,18 +63,14 @@ function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
}
|
||||
}
|
||||
|
||||
for (let i in aTypesInfo) {
|
||||
// Expand the permission to see if we have multiple access properties
|
||||
// to convert
|
||||
let perm = aTypesInfo[i].permission;
|
||||
let access = PermissionsTable[perm].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(perm + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(perm, aPrincipal);
|
||||
// Expand the permission to see if we have multiple access properties to convert
|
||||
let access = PermissionsTable[aPermission].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(aPermission, aPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,63 +78,23 @@ function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request,
|
||||
typesInfo) {
|
||||
typesInfo.forEach(function(type) {
|
||||
type.action =
|
||||
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
type.access);
|
||||
});
|
||||
|
||||
// If all permissions are allowed already, call allow() without prompting.
|
||||
let checkAllowPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkAllowPermission)) {
|
||||
debug("all permission requests are allowed");
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
}
|
||||
|
||||
// If all permissions are DENY_ACTION or UNKNOWN_ACTION, call cancel()
|
||||
// without prompting.
|
||||
let checkDenyPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(type.access) < 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkDenyPermission)) {
|
||||
debug("all permission requests are denied");
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// multiple requests should be audio and video
|
||||
checkMultipleRequest: function checkMultipleRequest(typesInfo) {
|
||||
if (typesInfo.length == 1) {
|
||||
return true;
|
||||
} else if (typesInfo.length > 1) {
|
||||
let checkIfAllowMultiRequest = function(type) {
|
||||
return (ALLOW_MULTIPLE_REQUESTS.indexOf(type.access) !== -1);
|
||||
}
|
||||
if (typesInfo.every(checkIfAllowMultiRequest)) {
|
||||
debug("legal multiple requests");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByApp: function handledByApp(request, typesInfo) {
|
||||
handledByApp: function handledByApp(request) {
|
||||
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
||||
// This should not really happen
|
||||
@ -168,94 +106,49 @@ ContentPermissionPrompt.prototype = {
|
||||
.getService(Ci.nsIAppsService);
|
||||
let app = appsService.getAppByLocalId(request.principal.appId);
|
||||
|
||||
// Check each permission if it's denied by permission manager with app's
|
||||
// URL.
|
||||
let checkIfDenyAppPrincipal = function(type) {
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url,
|
||||
request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
type.access);
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal, access);
|
||||
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
type.deny = false;
|
||||
}
|
||||
return type.deny;
|
||||
}
|
||||
if (typesInfo.every(checkIfDenyAppPrincipal)) {
|
||||
request.cancel();
|
||||
return true;
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
request.cancel();
|
||||
return true;
|
||||
},
|
||||
|
||||
handledByPermissionType: function handledByPermissionType(request, typesInfo) {
|
||||
for (let i in typesInfo) {
|
||||
if (permissionSpecificChecker.hasOwnProperty(typesInfo[i].permission) &&
|
||||
permissionSpecificChecker[typesInfo[i].permission](request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
handledByPermissionType: function handledByPermissionType(request) {
|
||||
return permissionSpecificChecker.hasOwnProperty(request.type)
|
||||
? permissionSpecificChecker[request.type](request)
|
||||
: false;
|
||||
},
|
||||
|
||||
_id: 0,
|
||||
prompt: function(request) {
|
||||
if (secMan.isSystemPrincipal(request.principal)) {
|
||||
request.allow();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize the typesInfo and set the default value.
|
||||
let typesInfo = [];
|
||||
let perms = request.types.QueryInterface(Ci.nsIArray);
|
||||
for (let idx = 0; idx < perms.length; idx++) {
|
||||
let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
|
||||
let tmp = {
|
||||
permission: perm.type,
|
||||
access: (perm.access && perm.access !== "unused") ?
|
||||
perm.type + "-" + perm.access : perm.type,
|
||||
deny: true,
|
||||
action: Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
};
|
||||
typesInfo.push(tmp);
|
||||
}
|
||||
if (typesInfo.length == 0) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.checkMultipleRequest(typesInfo)) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.handledByApp(request, typesInfo) ||
|
||||
this.handledByPermissionType(request, typesInfo)) {
|
||||
if (this.handledByApp(request) ||
|
||||
this.handledByPermissionType(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request, typesInfo)) {
|
||||
if (this.handleExistingPermission(request))
|
||||
return;
|
||||
}
|
||||
|
||||
// prompt PROMPT_ACTION request only.
|
||||
typesInfo.forEach(function(aType, aIndex) {
|
||||
if (aType.action != Ci.nsIPermissionManager.PROMPT_ACTION || aType.deny) {
|
||||
typesInfo.splice(aIndex);
|
||||
}
|
||||
});
|
||||
|
||||
let frame = request.element;
|
||||
let requestId = this._id++;
|
||||
|
||||
if (!frame) {
|
||||
this.delegatePrompt(request, requestId, typesInfo);
|
||||
this.delegatePrompt(request, requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -270,7 +163,7 @@ ContentPermissionPrompt.prototype = {
|
||||
if (evt.detail.visible === true)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, requestId, typesInfo);
|
||||
self.cancelPrompt(request, requestId);
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
@ -287,7 +180,7 @@ ContentPermissionPrompt.prototype = {
|
||||
// away but the request is still here.
|
||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
|
||||
self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
|
||||
self.delegatePrompt(request, requestId, function onCallback() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
});
|
||||
};
|
||||
@ -298,17 +191,22 @@ ContentPermissionPrompt.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
cancelPrompt: function(request, requestId, typesInfo) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
|
||||
typesInfo);
|
||||
cancelPrompt: function(request, requestId) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
|
||||
},
|
||||
|
||||
delegatePrompt: function(request, requestId, typesInfo, callback) {
|
||||
delegatePrompt: function(request, requestId, callback) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let principal = request.principal;
|
||||
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
|
||||
function(type, remember) {
|
||||
this._permission = access;
|
||||
this._uri = principal.URI.spec;
|
||||
this._origin = principal.origin;
|
||||
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
|
||||
if (type == "permission-allow") {
|
||||
rememberPermission(typesInfo, request.principal, !remember);
|
||||
rememberPermission(request.type, principal, !remember);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
@ -316,20 +214,14 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let addDenyPermission = function(type) {
|
||||
debug("add " + type.permission +
|
||||
" to permission manager with DENY_ACTION");
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||
0);
|
||||
}
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
typesInfo.forEach(addDenyPermission);
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
@ -338,7 +230,7 @@ ContentPermissionPrompt.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
|
||||
sendToBrowserWindow: function(type, request, requestId, callback) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
if (!content)
|
||||
@ -361,15 +253,10 @@ ContentPermissionPrompt.prototype = {
|
||||
principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
|
||||
? true
|
||||
: request.remember;
|
||||
let permissions = [];
|
||||
for (let i in typesInfo) {
|
||||
debug("prompt " + typesInfo[i].permission);
|
||||
permissions.push(typesInfo[i].permission);
|
||||
}
|
||||
|
||||
let details = {
|
||||
type: type,
|
||||
permissions: permissions,
|
||||
permission: request.type,
|
||||
id: requestId,
|
||||
origin: principal.origin,
|
||||
isApp: isApp,
|
||||
@ -402,5 +289,6 @@ ContentPermissionPrompt.prototype = {
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
//module initialization
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user