diff options
Diffstat (limited to 'tools/addon-sdk-1.4/packages')
283 files changed, 0 insertions, 49601 deletions
diff --git a/tools/addon-sdk-1.4/packages/addon-kit/README.md b/tools/addon-sdk-1.4/packages/addon-kit/README.md deleted file mode 100644 index 9a68554..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/README.md +++ /dev/null @@ -1,8 +0,0 @@ -The addon-kit package provides high-level APIs for add-on developers. -Most of the needs of most add-on developers should be served by the modules -found here. Modules in this packages don't require any special privileges to -run. - -The modules in the addon-kit package are relatively stable. We intend to add -new APIs here and extend existing ones, but will avoid making incompatible -changes to them unless absolutely necessary. diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/moz_favicon.ico b/tools/addon-sdk-1.4/packages/addon-kit/data/moz_favicon.ico Binary files differdeleted file mode 100644 index d444389..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/moz_favicon.ico +++ /dev/null diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-mod.html b/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-mod.html deleted file mode 100644 index 9211698..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-mod.html +++ /dev/null @@ -1,8 +0,0 @@ -<html> -<head> - <title>Page Mod test</title> -</head> -<body> - <p id="paragraph">Lorem ipsum dolor sit amet.</p> -</body> -</html> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.html b/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.html deleted file mode 100644 index e89a283..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.html +++ /dev/null @@ -1,8 +0,0 @@ -<html> -<head> - <title>Page Worker test</title> -</head> -<body> - <p id="paragraph">Lorem ipsum dolor sit amet.</p> -</body> -</html> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.js b/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.js deleted file mode 100644 index d8effb9..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-page-worker.js +++ /dev/null @@ -1,25 +0,0 @@ - -// get title directly -self.postMessage(["assertEqual", document.title, "Page Worker test", - "Correct page title accessed directly"]); - -// get <p> directly -let p = document.getElementById("paragraph"); -self.postMessage(["assert", !!p, "<p> can be accessed directly"]); -self.postMessage(["assertEqual", p.firstChild.nodeValue, - "Lorem ipsum dolor sit amet.", - "Correct text node expected"]); - -// Modify page -let div = document.createElement("div"); -div.setAttribute("id", "block"); -div.appendChild(document.createTextNode("Test text created")); -document.body.appendChild(div); - -// Check back the modification -div = document.getElementById("block"); -self.postMessage(["assert", !!div, "<div> can be accessed directly"]); -self.postMessage(["assertEqual", div.firstChild.nodeValue, - "Test text created", "Correct text node expected"]); -self.postMessage(["done"]); - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request-invalid.json b/tools/addon-sdk-1.4/packages/addon-kit/data/test-request-invalid.json deleted file mode 100644 index 35f9ff6..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request-invalid.json +++ /dev/null @@ -1 +0,0 @@ -"this": "isn't JSON" diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.json b/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.json deleted file mode 100644 index 8c850a5..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.json +++ /dev/null @@ -1 +0,0 @@ -{ "foo": "bar" } diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.txt b/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.txt deleted file mode 100644 index 390125d..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test-request.txt +++ /dev/null @@ -1 +0,0 @@ -Look ma, no hands! diff --git a/tools/addon-sdk-1.4/packages/addon-kit/data/test.html b/tools/addon-sdk-1.4/packages/addon-kit/data/test.html deleted file mode 100644 index 39de477..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/data/test.html +++ /dev/null @@ -1,8 +0,0 @@ -<html> - <head> - <title>foo</title> - </head> - <body> - <p>bar</p> - </body> -</html> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/clipboard.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/clipboard.md deleted file mode 100644 index 7292017..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/clipboard.md +++ /dev/null @@ -1,58 +0,0 @@ -<!-- contributed by Dietrich Ayala [dietrich@mozilla.com] --> - -The `clipboard` module allows callers to interact with the system clipboard, -setting and retrieving its contents. - -You can optionally specify the type of the data to set and retrieve. -The following types are supported: - -* `text` (plain text) -* `html` (a string of HTML) - -If no data type is provided, then the module will detect it for you. - -Examples --------- - -Set and get the contents of the clipboard. - - let clipboard = require("clipboard"); - clipboard.set("Lorem ipsum dolor sit amet"); - let contents = clipboard.get(); - -Set the clipboard contents to some HTML. - - let clipboard = require("clipboard"); - clipboard.set("<blink>Lorem ipsum dolor sit amet</blink>", "html"); - -If the clipboard contains HTML content, open it in a new tab. - - let clipboard = require("clipboard"); - if (clipboard.currentFlavors.indexOf("html") != -1) - require("tabs").open("data:text/html," + clipboard.get("html")); - -<api name="set"> -@function - Replace the contents of the user's clipboard with the provided data. -@param data {string} - The data to put on the clipboard. -@param [datatype] {string} - The type of the data (optional). -</api> - -<api name="get"> -@function - Get the contents of the user's clipboard. -@param [datatype] {string} - Retrieve the clipboard contents only if matching this type (optional). - The function will return null if the contents of the clipboard do not match - the supplied type. -</api> - -<api name="currentFlavors"> -@property {array} - Data on the clipboard is sometimes available in multiple types. For example, - HTML data might be available as both a string of HTML (the `html` type) - and a string of plain text (the `text` type). This function returns an array - of all types in which the data currently on the clipboard is available. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/context-menu.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/context-menu.md deleted file mode 100644 index f2bb5b3..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/context-menu.md +++ /dev/null @@ -1,702 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `context-menu` module lets you add items to Firefox's page context menu. - - -Introduction ------------- - -The `context-menu` API provides a simple, declarative way to add items to the -page's context menu. You can add items that perform an action when clicked, -submenus, and menu separators. - -Instead of manually adding items when particular contexts occur and then -removing them when those contexts go away, you *bind* items to contexts, and the -adding and removing is automatically handled for you. Items are bound to -contexts in much the same way that event listeners are bound to events. When -the user invokes the context menu, all of the items bound to the current context -are automatically added to the menu. If no items are bound, none are added. -Likewise, any items that were previously in the menu but are not bound to the -current context are automatically removed from the menu. You never need to -manually remove your items from the menu unless you want them to never appear -again. - -For example, if your add-on needs to add a context menu item whenever the -user visits a certain page, don't create the item when that page loads, and -don't remove it when the page unloads. Rather, create your item only once and -supply a context that matches the target URL. - - -Specifying Contexts -------------------- - -As its name implies, the context menu should be reserved for the occurrence of -specific contexts. Contexts can be related to page content or the page itself, -but they should never be external to the page. - -For example, a good use of the menu would be to show an "Edit Image" item when -the user right-clicks an image in the page. A bad use would be to show a -submenu that listed all the user's tabs, since tabs aren't related to the page -or the node the user clicked to open the menu. - -### The Page Context - -First of all, you may not need to specify a context at all. When an item does -not specify a context, the page context applies. - -The *page context* occurs when the user invokes the context menu on a -non-interactive portion of the page. Try right-clicking a blank spot in this -page, or on text. Make sure that no text is selected. The menu that appears -should contain the items "Back", "Forward", "Reload", "Stop", and so on. This -is the page context. - -The page context is appropriate when your item acts on the page as a whole. It -does not occur when the user invokes the context menu on a link, image, or other -non-text node, or while a selection exists. - -### Declarative Contexts - -You can specify some simple, declarative contexts when you create a menu item by -setting the `context` property of the options object passed to its constructor, -like this: - - var cm = require("context-menu"); - cm.Item({ - label: "My Menu Item", - context: cm.URLContext("*.mozilla.org") - }); - -These contexts may be specified by calling the following constructors. Each is -exported by the `context-menu` module. - -<table> - <tr> - <th>Constructor</th> - <th>Description</th> - </tr> - <tr> - <td><code> - PageContext() - </code></td> - <td> - The page context. - </td> - </tr> - <tr> - <td><code> - SelectionContext() - </code></td> - <td> - This context occurs when the menu is invoked on a page in which the user - has made a selection. - </td> - </tr> - <tr> - <td><code> - SelectorContext(selector) - </code></td> - <td> - This context occurs when the menu is invoked on a node that either matches - <code>selector</code>, a CSS selector, or has an ancestor that matches. - <code>selector</code> may include multiple selectors separated by commas, - e.g., <code>"a[href], img"</code>. - </td> - </tr> - <tr> - <td><code> - URLContext(matchPattern) - </code></td> - <td> - This context occurs when the menu is invoked on pages with particular - URLs. <code>matchPattern</code> is a match pattern string or an array of - match pattern strings. When <code>matchPattern</code> is an array, the - context occurs when the menu is invoked on a page whose URL matches any of - the patterns. These are the same match pattern strings that you use with - the <a href="packages/addon-kit/docs/page-mod.html"><code>page-mod</code></a> - <code>include</code> property. - <a href="packages/api-utils/docs/match-pattern.html">Read more about patterns</a>. - </td> - </tr> - <tr> - <td> - array - </td> - <td> - An array of any of the other types. This context occurs when all contexts - in the array occur. - </td> - </tr> -</table> - -Menu items also have a `context` property that can be used to add and remove -declarative contexts after construction. For example: - - var context = require("context-menu").SelectorContext("img"); - myMenuItem.context.add(context); - myMenuItem.context.remove(context); - -When a menu item is bound to more than one context, it appears in the menu when -all of those contexts occur. - -### In Content Scripts - -The declarative contexts are handy but not very powerful. For instance, you -might want your menu item to appear for any page that has at least one image, -but declarative contexts won't help you there. - -When you need more control control over the context in which your menu items are -shown, you can use content scripts. Like other APIs in the SDK, the -`context-menu` API uses -[content scripts](dev-guide/addon-development/web-content.html) to let your -add-on interact with pages in the browser. Each menu item you create in the -top-level context menu can have a content script. - -A special event named `"context"` is emitted in your content scripts whenever -the context menu is about to be shown. If you register a listener function for -this event and it returns true, the menu item associated with the listener's -content script is shown in the menu. - -For example, this item appears whenever the context menu is invoked on a page -that contains at least one image: - - require("context-menu").Item({ - label: "This Page Has Images", - contentScript: 'self.on("context", function (node) {' + - ' return !!document.querySelector("img");' + - '});' - }); - -Note that the listener function has a parameter called `node`. This is the node -in the page that the user context-clicked to invoke the menu. You can use it to -determine whether your item should be shown. - -You can both specify declarative contexts and listen for contexts in a content -script. In that case, the declarative contexts are evaluated first. If they -are not current, then your context listener is never called. - -This example takes advantage of that fact. The listener can be assured that -`node` will always be an image: - - require("context-menu").Item({ - label: "A Mozilla Image", - context: contextMenu.SelectorContext("img"), - contentScript: 'self.on("context", function (node) {' + - ' return /mozilla/.test(node.src);' + - '});' - }); - -Your item is shown only when all declarative contexts are current and your -context listener returns true. - - -Handling Menu Item Clicks -------------------------- - -In addition to using content scripts to listen for the `"context"` event as -described above, you can use content scripts to handle item clicks. When the -user clicks your menu item, an event named `"click"` is emitted in the item's -content script. - -Therefore, to handle an item click, listen for the `"click"` event in that -item's content script like so: - - require("context-menu").Item({ - label: "My Item", - contentScript: 'self.on("click", function (node, data) {' + - ' console.log("Item clicked!");' + - '});' - }); - -Note that the listener function has parameters called `node` and `data`. `node` -is the node that the user context-clicked to invoke the menu. You can use it -when performing some action. `data` is the `data` property of the menu item -that was clicked. Since only top-level menu items have content scripts, this -comes in handy for determining which item in a `Menu` was clicked: - - var cm = require("context-menu"); - cm.Menu({ - label: "My Menu", - contentScript: 'self.on("click", function (node, data) {' + - ' console.log("You clicked " + data);' + - '});', - items: [ - cm.Item({ label: "Item 1", data: "item1" }), - cm.Item({ label: "Item 2", data: "item2" }), - cm.Item({ label: "Item 3", data: "item3" }) - ] - }); - -Often you will need to collect some kind of information in the click listener -and perform an action unrelated to content. To communicate to the menu item -associated with the content script, the content script can call the -`postMessage` function attached to the global `self` object, passing it some -JSON-able data. The menu item's `"message"` event listener will be called with -that data. - - require("context-menu").Item({ - label: "Edit Image", - context: contextMenu.SelectorContext("img"), - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage(node.src);' + - '});', - onMessage: function (imgSrc) { - openImageEditor(imgSrc); - } - }); - - -Updating a Menu Item's Label ----------------------------- - -Each menu item must be created with a label, but you can change its label later -using a couple of methods. - -The simplest method is to set the menu item's `label` property. This example -updates the item's label based on the number of times it's been clicked: - - var numClicks = 0; - var myItem = require("context-menu").Item({ - label: "Click Me: " + numClicks, - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - numClicks++; - this.label = "Click Me: " + numClicks; - // Setting myItem.label is equivalent. - } - }); - -Sometimes you might want to update the label based on the context. For -instance, if your item performs a search with the user's selected text, it would -be nice to display the text in the item to provide feedback to the user. In -these cases you can use the second method. Recall that your content scripts can -listen for the `"context"` event and if your listeners return true, the items -associated with the content scripts are shown in the menu. In addition to -returning true, your `"context"` listeners can also return strings. When a -`"context"` listener returns a string, it becomes the item's new label. - -This item implements the aforementioned search example: - - var cm = require("context-menu"); - cm.Item({ - label: "Search Google", - context: cm.SelectionContext(), - contentScript: 'self.on("context", function () {' + - ' var text = window.getSelection().toString();' + - ' if (text.length > 20)' + - ' text = text.substr(0, 20) + "...";' + - ' return "Search Google for " + text;' + - '});' - }); - -The `"context"` listener gets the window's current selection, truncating it if -it's too long, and includes it in the returned string. When the item is shown, -its label will be "Search Google for `text`", where `text` is the truncated -selection. - - -More Examples -------------- - -For conciseness, these examples create their content scripts as strings and use -the `contentScript` property. In your own add-on, you will probably want to -create your content scripts in separate files and pass their URLs using the -`contentScriptFile` property. See -[Working with Content Scripts](dev-guide/addon-development/web-content.html) -for more information. - -Show an "Edit Page Source" item when the user right-clicks a non-interactive -part of the page: - - require("context-menu").Item({ - label: "Edit Page Source", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage(document.URL);' + - '});', - onMessage: function (pageURL) { - editSource(pageURL); - } - }); - -Show an "Edit Image" item when the menu is invoked on an image: - - require("context-menu").Item({ - label: "Edit Image", - context: contextMenu.SelectorContext("img"), - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage(node.src);' + - '});', - onMessage: function (imgSrc) { - openImageEditor(imgSrc); - } - }); - -Show an "Edit Mozilla Image" item when the menu is invoked on an image in a -mozilla.org or mozilla.com page: - - var cm = require("context-menu"); - cm.Item({ - label: "Edit Mozilla Image", - context: [ - cm.URLContext(["*.mozilla.org", "*.mozilla.com"]), - cm.SelectorContext("img") - ], - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage(node.src);' + - '});', - onMessage: function (imgSrc) { - openImageEditor(imgSrc); - } - }); - -Show an "Edit Page Images" item when the page contains at least one image: - - require("context-menu").Item({ - label: "Edit Page Images", - // This ensures the item only appears during the page context. - context: contextMenu.PageContext(), - contentScript: 'self.on("context", function (node) {' + - ' var pageHasImgs = !!document.querySelector("img");' + - ' return pageHasImgs;' + - '});' + - 'self.on("click", function (node, data) {' + - ' var imgs = document.querySelectorAll("img");' + - ' var imgSrcs = [];' + - ' for (var i = 0 ; i < imgs.length; i++)' + - ' imgSrcs.push(imgs[i].src);' + - ' self.postMessage(imgSrcs);' + - '});', - onMessage: function (imgSrcs) { - openImageEditor(imgSrcs); - } - }); - -Show a "Search With" menu when the user right-clicks an anchor that searches -Google or Wikipedia with the text contained in the anchor: - - var cm = require("context-menu"); - var googleItem = cm.Item({ - label: "Google", - data: "http://www.google.com/search?q=" - }); - var wikipediaItem = cm.Item({ - label: "Wikipedia", - data: "http://en.wikipedia.org/wiki/Special:Search?search=" - }); - var searchMenu = cm.Menu({ - label: "Search With", - context: contextMenu.SelectorContext("a[href]"), - contentScript: 'self.on("click", function (node, data) {' + - ' var searchURL = data + node.textContent;' + - ' window.location.href = searchURL;' + - '});', - items: [googleItem, wikipediaItem] - }); - - -<api name="Item"> -@class -A labeled menu item that can perform an action when clicked. -<api name="Item"> -@constructor - Creates a labeled menu item that can perform an action when clicked. -@param options {object} - An object with the following keys: - @prop label {string} - The item's label. It must either be a string or an object that implements - `toString()`. - @prop [image] {string} - The item's icon, a string URL. The URL can be remote, a reference to an - image in the add-on's `data` directory, or a data URI. - @prop [data] {string} - An optional arbitrary value to associate with the item. It must be either a - string or an object that implements `toString()`. It will be passed to - click listeners. - @prop [context] {value} - If the item is contained in the top-level context menu, this declaratively - specifies the context under which the item will appear; see Specifying - Contexts above. Ignored if the item is contained in a submenu. - @prop [contentScript] {string,array} - If the item is contained in the top-level context menu, this is the content - script or an array of content scripts that the item can use to interact with - the page. Ignored if the item is contained in a submenu. - @prop [contentScriptFile] {string,array} - If the item is contained in the top-level context menu, this is the local - file URL of the content script or an array of such URLs that the item can - use to interact with the page. Ignored if the item is contained in a - submenu. - @prop [onMessage] {function} - If the item is contained in the top-level context menu, this function will - be called when the content script calls `self.postMessage`. It will be - passed the data that was passed to `postMessage`. Ignored if the item is - contained in a submenu. -</api> - -<api name="label"> -@property {string} - The menu item's label. You can set this after creating the item to update its - label later. -</api> - -<api name="image"> -@property {string} - The item's icon, a string URL. The URL can be remote, a reference to an image - in the add-on's `data` directory, or a data URI. You can set this after - creating the item to update its image later. To remove the item's image, set - it to `null`. -</api> - -<api name="data"> -@property {string} - An optional arbitrary value to associate with the item. It must be either a - string or an object that implements `toString()`. It will be passed to - click listeners. You can set this after creating the item to update its data - later. -</api> - -<api name="context"> -@property {list} - A list of declarative contexts for which the menu item will appear in the - context menu. Contexts can be added by calling `context.add()` and removed by - called `context.remove()`. This property is meaningful only for items - contained in the top-level context menu. -</api> - -<api name="parentMenu"> -@property {Menu} - The item's parent `Menu`, or `null` if the item is contained in the top-level - context menu. This property is read-only. To add the item to a new menu, - call that menu's `addItem()` method. -</api> - -<api name="contentScript"> -@property {string,array} - The content script or the array of content scripts associated with the menu - item during creation. This property is meaningful only for items contained in - the top-level context menu. -</api> - -<api name="contentScriptFile"> -@property {string,array} - The URL of a content script or the array of such URLs associated with the menu - item during creation. This property is meaningful only for items contained in - the top-level context menu. -</api> - -<api name="destroy"> -@method - Permanently removes the item from its parent menu and frees its resources. - The item must not be used afterward. If you need to remove the item from its - parent menu but use it afterward, call `removeItem()` on the parent menu - instead. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this menu item. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the menu item's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -</api> - -<api name="Menu"> -@class -A labeled menu item that expands into a submenu. - -<api name="Menu"> -@constructor - Creates a labeled menu item that expands into a submenu. -@param options {object} - An object with the following keys: - @prop label {string} - The item's label. It must either be a string or an object that implements - `toString()`. - @prop items {array} - An array of menu items that the menu will contain. Each must be an `Item`, - `Menu`, or `Separator`. - @prop [image] {string} - The menu's icon, a string URL. The URL can be remote, a reference to an - image in the add-on's `data` directory, or a data URI. - @prop [context] {value} - If the menu is contained in the top-level context menu, this declaratively - specifies the context under which the menu will appear; see Specifying - Contexts above. Ignored if the menu is contained in a submenu. - @prop [contentScript] {string,array} - If the menu is contained in the top-level context menu, this is the content - script or an array of content scripts that the menu can use to interact with - the page. Ignored if the menu is contained in a submenu. - @prop [contentScriptFile] {string,array} - If the menu is contained in the top-level context menu, this is the local - file URL of the content script or an array of such URLs that the menu can - use to interact with the page. Ignored if the menu is contained in a - submenu. - @prop [onMessage] {function} - If the menu is contained in the top-level context menu, this function will - be called when the content script calls `self.postMessage`. It will be - passed the data that was passed to `postMessage`. Ignored if the item is - contained in a submenu. -</api> - -<api name="label"> -@property {string} - The menu's label. You can set this after creating the menu to update its - label later. -</api> - -<api name="items"> -@property {array} - An array containing the items in the menu. The array is read-only, meaning - that modifications to it will not affect the menu. However, setting this - property to a new array will replace all the items currently in the menu with - the items in the new array. -</api> - -<api name="image"> -@property {string} - The menu's icon, a string URL. The URL can be remote, a reference to an image - in the add-on's `data` directory, or a data URI. You can set this after - creating the menu to update its image later. To remove the menu's image, set - it to `null`. -</api> - -<api name="context"> -@property {list} - A list of declarative contexts for which the menu will appear in the context - menu. Contexts can be added by calling `context.add()` and removed by called - `context.remove()`. This property is meaningful only for menus contained in - the top-level context menu. -</api> - -<api name="parentMenu"> -@property {Menu} - The menu's parent `Menu`, or `null` if the menu is contained in the top-level - context menu. This property is read-only. To add the menu to a new menu, - call that menu's `addItem()` method. -</api> - -<api name="contentScript"> -@property {string,array} - The content script or the array of content scripts associated with the menu - during creation. This property is meaningful only for menus contained in the - top-level context menu. -</api> - -<api name="contentScriptFile"> -@property {string,array} - The URL of a content script or the array of such URLs associated with the menu - during creation. This property is meaningful only for menus contained in the - top-level context menu. -</api> - -<api name="addItem"> -@method - Appends a menu item to the end of the menu. If the item is already contained - in another menu or in the top-level context menu, it's automatically removed - first. -@param item {Item,Menu,Separator} - The `Item`, `Menu`, or `Separator` to add to the menu. -</api> - -<api name="removeItem"> -@method - Removes the given menu item from the menu. If the menu does not contain the - item, this method does nothing. -@param item {Item,Menu,Separator} - The menu item to remove from the menu. -</api> - -<api name="destroy"> -@method - Permanently removes the menu from its parent menu and frees its resources. - The menu must not be used afterward. If you need to remove the menu from its - parent menu but use it afterward, call `removeItem()` on the parent menu - instead. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this menu item. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the menu item's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -</api> - -<api name="Separator"> -@class -A menu separator. Separators can be contained only in `Menu`s, not in the -top-level context menu. - -<api name="Separator"> -@constructor - Creates a menu separator. -</api> - -<api name="parentMenu"> -@property {Menu} - The separator's parent `Menu`. This property is read-only. To add the - separator to a new menu, call that menu's `addItem()` method. -</api> - -<api name="destroy"> -@method - Permanently removes the separator from its parent menu and frees its - resources. The separator must not be used afterward. If you need to remove - the separator from its parent menu but use it afterward, call `removeItem()` - on the parent menu instead. -</api> - -</api> - -<api name="PageContext"> -@class -<api name="PageContext"> -@constructor - Creates a page context. See Specifying Contexts above. -</api> -</api> - -<api name="SelectionContext"> -@class -<api name="SelectionContext"> -@constructor - Creates a context that occurs when a page contains a selection. See - Specifying Contexts above. -</api> -</api> - -<api name="SelectorContext"> -@class -<api name="SelectorContext"> -@constructor - Creates a context that matches a given CSS selector. See Specifying Contexts - above. -@param selector {string} - A CSS selector. -</api> -</api> - -<api name="URLContext"> -@class -<api name="URLContext"> -@constructor - Creates a context that matches pages with particular URLs. See Specifying - Contexts above. -@param matchPattern {string,array} - A [match pattern](packages/api-utils/docs/match-pattern.html) string or an array of - match pattern strings. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/hotkeys.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/hotkeys.md deleted file mode 100644 index dfbe572..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/hotkeys.md +++ /dev/null @@ -1,74 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -Some add-ons may wish to define keyboard shortcuts for certain operations. This -module exposes an API to create those. - -<api name="Hotkey"> -@class - -Module exports `Hotkey` constructor allowing users to create a `hotkey` for the -host application. - -<api name="Hotkey"> -@constructor -Creates a hotkey who's `onPress` listener method is invoked when key combination -defined by `hotkey` is pressed. - -Please note: If more than one `hotkey` is created for the same key -combination, the listener is executed only on the last one created - -@param options {Object} - Options for the hotkey, with the following keys: - -@prop combo {String} -Any function key: `"f1, f2, ..., f24"` or key combination in the format -of `'modifier-key'`: - - "accel-s" - "meta-shift-i" - "control-alt-d" - -Modifier keynames: - -- **shift**: The Shift key. -- **alt**: The Alt key. On the Macintosh, this is the Option key. On - Macintosh this can only be used in conjunction with another modifier, - since `Alt-Letter` combinations are reserved for entering special - characters in text. -- **meta**: The Meta key. On the Macintosh, this is the Command key. -- **control**: The Control key. -- **accel**: The key used for keyboard shortcuts on the user's platform, - which is Control on Windows and Linux, and Command on Mac. Usually, this - would be the value you would use. - -@prop onPress {Function} -Function that is invoked when the key combination `hotkey` is pressed. - -</api> -<api name="destroy"> -@method -Stops this instance of `Hotkey` from reacting on the key combinations. Once -destroyed it can no longer be used. -</api> -</api> - -## Example ## - - // Define keyboard shortcuts for showing and hiding a custom panel. - var { Hotkey } = require("hotkeys"); - - var showHotKey = Hotkey({ - combo: "accel-shift-o", - onPress: function() { - showMyPanel(); - } - }); - var hideHotKey = Hotkey({ - combo: "accel-alt-shift-o", - onPress: function() { - hideMyPanel(); - } - }); - -[Mozilla keyboard planning FAQ]:http://www.mozilla.org/access/keyboard/ -[keyboard shortcuts]:https://developer.mozilla.org/en/XUL_Tutorial/Keyboard_Shortcuts diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/notifications.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/notifications.md deleted file mode 100644 index 5e76c1b..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/notifications.md +++ /dev/null @@ -1,60 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> - -The `notifications` module allows you to display transient, -[toaster](http://en.wikipedia.org/wiki/Toast_%28computing%29)-style -desktop messages to the user. - -This API supports desktop notifications on Windows, OS X using -[Growl](http://growl.info/), and Linux using libnotify. If the user's system -does not support desktop notifications or if its notifications service is not -running, then notifications made with this API are logged to Firefox's error -console and, if the user launched Firefox from the command line, the terminal. - -Examples --------- - -Here's a typical example. When the message is clicked, a string is logged to -the console. - - var notifications = require("notifications"); - notifications.notify({ - title: "Jabberwocky", - text: "'Twas brillig, and the slithy toves", - data: "did gyre and gimble in the wabe", - onClick: function (data) { - console.log(data); - // console.log(this.data) would produce the same result. - } - }); - -This one displays an icon that's stored in the add-on's `data` directory. (See -the [`self`](packages/addon-kit/docs/self.html) module documentation for more information.) - - var notifications = require("notifications"); - var self = require("self"); - var myIconURL = self.data.url("myIcon.png"); - notifications.notify({ - text: "I have an icon!", - iconURL: myIconURL - }); - - -<api name="notify"> -@function - Displays a transient notification to the user. -@param options {object} - An object with the following keys. Each is optional. - @prop [title] {string} - A string to display as the message's title. - @prop [text] {string} - A string to display as the body of the message. - @prop [iconURL] {string} - The URL of an icon to display inside the message. It may be a remote URL, - a data URI, or a URL returned by the [`self`](packages/addon-kit/docs/self.html) - module. - @prop [onClick] {function} - A function to be called when the user clicks the message. It will be passed - the value of `data`. - @prop [data] {string} - A string that will be passed to `onClick`. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/page-mod.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/page-mod.md deleted file mode 100644 index e523d48..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/page-mod.md +++ /dev/null @@ -1,367 +0,0 @@ -<!-- contributed by Nickolay Ponomarev [asqueella@gmail.com] --> -<!-- contributed by Myk Melez [myk@mozilla.org] --> -<!-- contributed by Irakli Gozalishvil [gozala@mozilla.com] --> - -Overview --------- -The page-mod module enables add-on developers to execute scripts in the context -of specific web pages. Most obviously you could use page-mod to dynamically -modify the content of certain pages. - -The module exports a constructor function `PageMod` which creates a new page -modification (or "mod" for short). - -A page mod does not modify its pages until those pages are loaded or reloaded. -In other words, if your add-on is loaded while the user's browser is open, the -user will have to reload any open pages that match the mod for the mod to affect -them. - -To stop a page mod from making any more modifications, call its `destroy` -method. - -Like all modules that interact with web content, page-mod uses content -scripts that execute in the content process and defines a messaging API to -communicate between the content scripts and the main add-on script. For more -details on content scripting see the tutorial on [interacting with web -content](dev-guide/addon-development/web-content.html). - -To create a PageMod the add-on developer supplies: - -* a set of rules to select the desired subset of web pages based on their URL. -Each rule is specified using the -[match-pattern](packages/api-utils/docs/match-pattern.html) syntax. - -* a set of content scripts to execute in the context of the desired pages. - -* a value for the onAttach option: this value is a function which will be -called when a page is loaded that matches the ruleset. This is used to set up a -communication channel between the add-on code and the content script. - -All these parameters are optional except for the ruleset, which must include -at least one rule. - -The following add-on displays an alert whenever a page matching the ruleset is -loaded: - - var pageMod = require("page-mod"); - pageMod.PageMod({ - include: "*.org", - contentScript: 'window.alert("Page matches ruleset");' - }); - -If you specify a value of "ready" or "end" for `contentScriptWhen`, -as opposed to "start", -then the content script can interact with the DOM itself: - - var pageMod = require("page-mod"); - pageMod.PageMod({ - include: "*.org", - contentScriptWhen: 'end', - contentScript: 'document.body.innerHTML = ' + - ' "<h1>Page matches ruleset</h1>";' - }); - -### Using `contentScriptFile` ### - -Most of the examples in this page define content scripts as strings, -and use the `contentScript` option to assign them to page mods. - -In your code you will more often create content scripts in separate files -under your add-on's `data` directory. Then you can use the -[`self`](packages/addon-kit/docs/self.html) module to retrieve a URL pointing -to the file, and assign this to the page-mod's `contentScriptFile` -property. - -For example, if you save the content script -file in your `data` directory as "myScript.js", you would assign it using -code like: - - var data = require("self").data; - - var pageMod = require("page-mod"); - pageMod.PageMod({ - include: "*.org", - contentScriptWhen: 'end', - contentScriptFile: data.url("myScript.js") - }); - -## Communicating With Content Scripts ## - -When a matching page is loaded the `PageMod` will call the function that the -add-on code supplied to `onAttach`. The `PageMod` supplies one argument to -this function: a `worker` object. - -The worker can be thought of as the add-on's end of -a communication channel between the add-on code and the content scripts that -have been attached to this page. - -Thus the add-on can pass messages to the content scripts by calling the -worker's `postMessage` function and can receive messages from the content -scripts by registering a function as a listener to the worker's `on` function. - -Note that if multiple matching pages are loaded simultaneously then each page -is loaded into its own execution context with its own copy of the content -scripts. In this case `onAttach` is called once for each loaded page, and the -add-on code will have a separate worker for each page: - -![Multiple workers](static-files/media/multiple-workers.jpg) - -This is demonstrated in the following example: - - var pageMod = require("page-mod"); - var tabs = require("tabs"); - - var workers = []; - - pageMod.PageMod({ - include: ["http://www.mozilla*"], - contentScriptWhen: 'end', - contentScript: "onMessage = function onMessage(message) {" + - " window.alert(message);};", - onAttach: function onAttach(worker) { - if (workers.push(worker) == 3) { - workers[0].postMessage("The first worker!"); - workers[1].postMessage("The second worker!"); - workers[2].postMessage("The third worker!"); - } - } - }); - - tabs.open("http://www.mozilla.com"); - tabs.open("http://www.mozilla.org"); - tabs.open("http://www.mozilla-europe.org"); - -Here we specify a ruleset to match any URLs starting with -"http://www.mozilla". When a page matches we add the supplied worker to -an array, and when we have three workers in the array we send a message to -each worker in turn, telling it the order in which it was attached. The -worker just displays the message in an alert box. - -This shows that separate pages execute in separate contexts and that each -context has its own communication channel with the add-on script. - -Note though that while there is a separate worker for each execution context, -the worker is shared across all the content scripts associated with a single -execution context. In the following example we pass two content scripts into -the `PageMod`: these content scripts will share a worker instance. - -In the example each content script identifies itself to the add-on script -by sending it a message using the global `postMessage` function. In the -`onAttach` function the add-on code logs the fact that a new page is -attached and registers a listener function that simply logs the message: - - - var pageMod = require("page-mod"); - var data = require("self").data; - var tabs = require("tabs"); - - pageMod.PageMod({ - include: ["http://www.mozilla*"], - contentScriptWhen: 'end', - contentScript: ["postMessage('Content script 1 is attached to '+ " + - "document.URL);", - "postMessage('Content script 2 is attached to '+ " + - "document.URL);"], - onAttach: function onAttach(worker) { - console.log("Attaching content scripts") - worker.on('message', function(data) { - console.log(data); - }); - } - }); - - tabs.open("http://www.mozilla.com"); - -The console output of this add-on is: - -<pre> - info: Attaching content scripts - info: Content script 1 is attached to http://www.mozilla.com/en-US/ - info: Content script 2 is attached to http://www.mozilla.com/en-US/ -</pre> - -### Mapping workers to tabs ### - -The [`worker`](packages/api-utils/docs/content/worker.html) has a `tab` -property which returns the tab associated with this worker. You can use this -to access the [`tabs API`](packages/addon-kit/docs/tabs.html) for the tab -associated with a specific page: - - var pageMod = require("page-mod"); - var tabs = require("tabs"); - - pageMod.PageMod({ - include: ["*"], - onAttach: function onAttach(worker) { - console.log(worker.tab.title); - } - }); - -### Attaching content scripts to tabs ### - -We've seen that the page mod API attaches content scripts to pages based on -their URL. Sometimes, though, we don't care about the URL: we just want -to execute a script on demand in the context of a particular tab. - -For example, we might want to run a script in the context of the currently -active tab when the user clicks a widget: to block certain content, to -change the font style, or to display the page's DOM structure. - -Using the `attach` method of the [`tab`](packages/addon-kit/docs/tabs.html) -object, you can attach a set of content scripts to a particular tab. The -scripts are executed immediately. - -The following add-on creates a widget which, when clicked, highlights all the -`div` elements in the page loaded into the active tab: - - var widgets = require("widget"); - var tabs = require("tabs"); - - var widget = widgets.Widget({ - id: "div-show", - label: "Show divs", - contentURL: "http://www.mozilla.org/favicon.ico", - onClick: function() { - tabs.activeTab.attach({ - contentScript: - 'var divs = document.getElementsByTagName("div");' + - 'for (var i = 0; i < divs.length; ++i) {' + - 'divs[i].setAttribute("style", "border: solid red 1px;");' + - '}' - }); - } - }); - -## Destroying Workers ## - -Workers generate a `detach` event when their associated page is closed: that -is, when the tab is closed or the tab's location changes. If -you are maintaining a list of workers belonging to a page mod, you can use -this event to remove workers that are no longer valid. - -For example, if you maintain a list of workers attached to a page mod: - - var workers = []; - - var pageMod = require("page-mod").PageMod({ - include: ['*'], - contentScriptWhen: 'ready', - contentScriptFile: data.url('pagemod.js'), - onAttach: function(worker) { - workers.push(worker); - } - }); - -You can remove workers when they are no longer valid by listening to `detach`: - - var workers = []; - - function detachWorker(worker, workerArray) { - var index = workerArray.indexOf(worker); - if(index != -1) { - workerArray.splice(index, 1); - } - } - - var pageMod = require("page-mod").PageMod({ - include: ['*'], - contentScriptWhen: 'ready', - contentScriptFile: data.url('pagemod.js'), - onAttach: function(worker) { - workers.push(worker); - worker.on('detach', function () { - detachWorker(this, workers); - }); - } - }); - -<api name="PageMod"> -@class -A PageMod object. Once activated a page mod will execute the supplied content -scripts in the context of any pages matching the pattern specified by the -'include' property. -<api name="PageMod"> -@constructor -Creates a PageMod. -@param options {object} - Options for the PageMod, with the following keys: - @prop include {string,array} - A match pattern string or an array of match pattern strings. These define - the pages to which the PageMod applies. See the - [match-pattern](packages/api-utils/docs/match-pattern.html) module for - a description of match pattern syntax. - At least one match pattern must be supplied. - - @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. - Optional. - @prop [contentScriptWhen="end"] {string} - When to load the content scripts. This may take one of the following - values: - - * "start": load content scripts immediately after the document - element for the page is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the page has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - - This property is optional and defaults to "end". - - @prop [onAttach] {function} -A function to call when the PageMod attaches content scripts to -a matching page. The function will be called with one argument, a `worker` -object which the add-on script can use to communicate with the content scripts -attached to the page in question. - -</api> - -<api name="include"> -@property {List} -A [list](packages/api-utils/docs/list.html) of match pattern strings. These -define the pages to which the page mod applies. See the -[match-pattern](packages/api-utils/docs/match-pattern.html) module for a -description of match patterns. Rules can be added to the list by calling its -`add` method and removed by calling its `remove` method. - -</api> - -<api name="destroy"> -@method -Stops the page mod from making any more modifications. Once destroyed the page -mod can no longer be used. Note that modifications already made to open pages -will not be undone. -</api> - -<api name="attach"> -@event -This event is emitted this event when the page-mod's content scripts are -attached to a page whose URL matches the page-mod's `include` filter. - -@argument {Worker} -The listener function is passed a [`Worker`](packages/api-utils/docs/content/worker.html) object that can be used to communicate -with any content scripts attached to this page. -</api> - -<api name="error"> -@event -This event is emitted when an uncaught runtime error occurs in one of the page -mod's content scripts. - -@argument {Error} -Listeners are passed a single argument, the -[Error](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error) -object. -</api> - -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/page-worker.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/page-worker.md deleted file mode 100644 index 06097ae..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/page-worker.md +++ /dev/null @@ -1,218 +0,0 @@ -<!-- contributed by Felipe Gomes [felipc@gmail.com] --> - -The `page-worker` module provides a way to create a permanent, invisible page -and access its DOM. - -Introduction ------------- - -The module exports a constructor function `Page`, which constructs a new page -worker. A page worker may be destroyed, after which its memory is freed, and -you must create a new instance to load another page. - -Page workers have associated content scripts, which are JavaScript scripts that -have access to the content loaded into the pages. You can specify scripts to -load for a page worker, and you communicate with those scripts over an -asynchronous JSON pipe. For more information on content scripts, see -[Working with Content Scripts](dev-guide/addon-development/web-content.html). - -Examples --------- - -For conciseness, these examples create their content scripts as strings and use -the `contentScript` property. In your own add-ons, you will probably want to -create your content scripts in separate files and pass their URLs using the -`contentScriptFile` property. See -[Working with Content Scripts](dev-guide/addon-development/web-content.html) -for more information. - -### Print all header titles from a Wikipedia article ### - - var pageWorkers = require("page-worker"); - - // This content script sends header titles from the page to the add-on: - var script = "var elements = document.querySelectorAll('h2 > span'); " + - "for (var i = 0; i < elements.length; i++) { " + - " postMessage(elements[i].textContent) " + - "}"; - - // Create a page worker that loads Wikipedia: - pageWorkers.Page({ - contentURL: "http://en.wikipedia.org/wiki/Internet", - contentScript: script, - contentScriptWhen: "ready", - onMessage: function(message) { - console.log(message); - } - }); - -The page worker's "message" event listener, specified by `onMessage`, will print -all the titles it receives from the content script. - -<api name="Page"> -@class -A `Page` object loads the page specified by its `contentURL` option and -executes any content scripts that have been supplied to it in the -`contentScript` and `contentScriptFile` options. - -The page is not displayed to the user. - -The page worker is loaded as soon as the `Page` object is created and stays -loaded until its `destroy` method is called or the add-on is unloaded. - -<api name="Page"> -@constructor - Creates an uninitialized page worker instance. -@param [options] {object} - The *`options`* parameter is optional, and if given it should be an object - with any of the following keys: - @prop [contentURL] {string} - The URL of the content to load in the panel. - @prop [allow] {object} - An object with keys to configure the permissions on the page worker. The - boolean key `script` controls if scripts from the page are allowed to run. - `script` defaults to true. - @prop [contentScriptFile] {string,array} - A local file URL or an array of local file URLs of content scripts to load. - Content scripts specified by this option are loaded *before* those specified - by the `contentScript` option. See - [Working with Content Scripts](dev-guide/addon-development/web-content.html) - for help on setting this property. - @prop [contentScript] {string,array} - A string or an array of strings containing the texts of content scripts to - load. Content scripts specified by this option are loaded *after* those - specified by the `contentScriptFile` option. - @prop [contentScriptWhen="end"] {string} - When to load the content scripts. This may take one of the following - values: - - * "start": load content scripts immediately after the document - element for the page is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the page has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - - This property is optional and defaults to "end". - - @prop [onMessage] {function} - Use this to add a listener to the page worker's `message` event. -</api> - -<api name="port"> -@property {EventEmitter} -[EventEmitter](packages/api-utils/docs/events.html) object that allows you to: - -* send events to the content script using the `port.emit` function -* receive events from the content script using the `port.on` function - -See the guide to -<a href="dev-guide/addon-development/content-scripts/using-port.html"> -communicating using <code>port</code></a> for details. -</api> - -<api name="contentURL"> -@property {string} -The URL of the content loaded. -</api> - -<api name="allow"> -@property {object} - A object describing permissions for the content. It contains a single key - named `script` whose value is a boolean that indicates whether or not to - execute script in the content. `script` defaults to true. -</api> - -<api name="contentScriptFile"> -@property {string,array} -A local file URL or an array of local file URLs of content scripts to load. -</api> - -<api name="contentScript"> -@property {string,array} -A string or an array of strings containing the texts of content scripts to -load. -</api> - -<api name="contentScriptWhen"> -@property {string} - When to load the content scripts. This may have one of the following - values: - - * "start": load content scripts immediately after the document - element for the page is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the page has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - -</api> - -<api name="destroy"> -@method -Unloads the page worker. After you destroy a page worker, its memory is freed -and you must create a new instance if you need to load another page. -</api> - -<api name="postMessage"> -@method -Sends a message to the content scripts. -@param message {value} -The message to send. Must be JSON-able. -</api> - -<api name="on"> -@method -Registers an event listener with the page worker. See -[Working with Events](dev-guide/addon-development/events.html) for help with -events. -@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 an event listener from the page worker. -@param type {string} -The type of event for which `listener` was registered. -@param listener {function} -The listener function that was registered. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this page worker. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the page worker's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a> -</api> - -<api name="error"> -@event -This event is emitted when an uncaught runtime error occurs in one of the -page worker's content scripts. - -@argument {Error} -Listeners are passed a single argument, the -[Error](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error) -object. -</api> - -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/panel.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/panel.md deleted file mode 100644 index 45eea2f..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/panel.md +++ /dev/null @@ -1,301 +0,0 @@ -<!-- contributed by Myk Melez [myk@mozilla.org] --> -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `panel` module creates floating modal "popup dialogs" that appear on top of -web content and browser chrome and persist until dismissed by users or programs. -Panels are useful for presenting temporary interfaces to users in a way that is -easier for users to ignore and dismiss than a modal dialog, since panels are -hidden the moment users interact with parts of the application interface outside -them. - -The module exports a single constructor function `Panel` which constructs a -new panel. - -A panel's content is loaded as soon as it is created, before the panel is shown, -and the content remains loaded when a panel is hidden, so it is possible -to keep a panel around in the background, updating its content as appropriate -in preparation for the next time it is shown. - -Your add-on can receive notifications when a panel is shown or hidden by -listening to its `show` and `hide` events. - -Panels have associated content scripts, which are JavaScript scripts that have -access to the content loaded into the panels. An add-on can specify one or -more content scripts to load for a panel, and the add-on can communicate with -those scripts either using the `message` event or by using user-defined -events. See -[Working with Content Scripts](dev-guide/addon-development/web-content.html) -for more information. - -The panel's default style is different for each operating system. -For example, suppose a panel's content is specified with the following HTML: - -<script type="syntaxhighlighter" class="brush: html"><![CDATA[ -<h1>Default Style</h1> - -This is what a panel with no custom styling looks like. -]]> -</script> - -On OS X it will look like this: - -<img class="image-center" src="static-files/media/screenshots/default-panel-osx.png" -alt="OS X panel default style"> -<br> - -On Windows 7 it will look like this: - -<img class="image-center" src="static-files/media/screenshots/default-panel-windows.png" -alt="Windows 7 panel default style"> -<br> - -On Ubuntu it will look like this: - -<img class="image-center" src="static-files/media/screenshots/default-panel-ubuntu.png" -alt="Ubuntu panel default style"> -<br> - -This helps to ensure that the panel's style is consistent with the dialogs -displayed by Firefox and other applications, but means you need to take care -when applying your own styles. For example, if you set the panel's -`background-color` property to `white` and do not set the `color` property, -then the panel's text will be invisible on OS X although it looks fine on Ubuntu. - -Examples --------- - -Create and show a simple panel with content from the `data/` directory: - - var data = require("self").data; - var panel = require("panel").Panel({ - contentURL: data.url("foo.html") - }); - - panel.show(); - -The tutorial section on -[web content](dev-guide/addon-development/web-content.html) has -a more complex example using panels. - -<api name="Panel"> -@class -The Panel object represents a floating modal dialog that can by an add-on to -present user interface content. - -Once a panel object has been created it can be shown and hidden using its -`show()` and `hide()` methods. Once a panel is no longer needed it can be -deactivated using `destroy()`. - -The content of a panel is specified using the `contentURL` option. An add-on -can interact with the content of a panel using content scripts which it -supplies in the `contentScript` and/or `contentScriptFile` options. For example, -a content script could create a menu and send the user's selection to the -add-on. - -<api name="Panel"> -@constructor -Creates a panel. -@param options {object} - Options for the panel, with the following keys: - @prop [width] {number} - The width of the panel in pixels. Optional. - @prop [height] {number} - The height of the panel in pixels. Optional. - @prop [contentURL] {string} - The URL of the content to load in the panel. - @prop [allow] {object} - An optional object describing permissions for the content. It should - contain a single key named `script` whose value is a boolean that indicates - whether or not to execute script in the content. `script` defaults to true. - @prop [contentScriptFile] {string,array} - A local file URL or an array of local file URLs of content scripts to load. - Content scripts specified by this property are loaded *before* those - specified by the `contentScript` property. - @prop [contentScript] {string,array} - A string or an array of strings containing the texts of content scripts to - load. Content scripts specified by this property are loaded *after* those - specified by the `contentScriptFile` property. - @prop [contentScriptWhen="end"] {string} - When to load the content scripts. This may take one of the following - values: - - * "start": load content scripts immediately after the document - element for the panel is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the panel has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - - This property is optional and defaults to "end". - - @prop [onMessage] {function} - Include this to listen to the panel's `message` event. - @prop [onShow] {function} - Include this to listen to the panel's `show` event. - @prop [onHide] {function} - Include this to listen to the panel's `hide` event. -</api> - -<api name="port"> -@property {EventEmitter} -[EventEmitter](packages/api-utils/docs/events.html) object that allows you to: - -* send events to the content script using the `port.emit` function -* receive events from the content script using the `port.on` function - -See the guide to -<a href="dev-guide/addon-development/content-scripts/using-port.html"> -communicating using <code>port</code></a> for details. -</api> - -<api name="isShowing"> -@property {boolean} -Tells if the panel is currently shown or not. This property is read-only. -</api> - -<api name="height"> -@property {number} -The height of the panel in pixels. -</api> - -<api name="width"> -@property {number} -The width of the panel in pixels. -</api> - -<api name="contentURL"> -@property {string} -The URL of the content loaded in the panel. -</api> - -<api name="allow"> -@property {object} -An object describing permissions for the content. It contains a single key -named `script` whose value is a boolean that indicates whether or not to execute -script in the content. -</api> - -<api name="contentScriptFile"> -@property {string,array} -A local file URL or an array of local file URLs of content scripts to load. -Content scripts specified by this property are loaded *before* those -specified by the `contentScript` property. -</api> - -<api name="contentScript"> -@property {string,array} -A string or an array of strings containing the texts of content scripts to -load. Content scripts specified by this property are loaded *after* those -specified by the `contentScriptFile` property. -</api> - -<api name="contentScriptWhen"> -@property {string} -When to load the content scripts. This may have one of the following -values: - -* "start": load content scripts immediately after the document -element for the panel is inserted into the DOM, but before the DOM content -itself has been loaded -* "ready": load content scripts once DOM content has been loaded, -corresponding to the -[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) -event -* "end": load content scripts once all the content (DOM, JS, CSS, -images) for the panel has been loaded, at the time the -[window.onload event](https://developer.mozilla.org/en/DOM/window.onload) -fires - -</api> - -<api name="destroy"> -@method -Destroys the panel, unloading any content that was loaded in it. Once -destroyed, the panel can no longer be used. If you just want to hide -the panel and might show it later, use `hide` instead. -</api> - -<api name="postMessage"> -@method -Sends a message to the content scripts. -@param message {value} -The message to send. Must be stringifiable to JSON. -</api> - -<api name="show"> -@method -Displays the panel. -</api> - -<api name="hide"> -@method -Stops displaying the panel. -</api> - -<api name="resize"> -@method -Resizes the panel. -@param width {number} -The new width of the panel in pixels. -@param height {number} -The new height of the panel in pixels. -</api> - -<api name="on"> -@method - Registers an event listener with the panel. -@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 an event listener from the panel. -@param type {string} - The type of event for which `listener` was registered. -@param listener {function} - The listener function that was registered. -</api> - -<api name="show"> -@event -This event is emitted when the panel is shown. -</api> - -<api name="hide"> -@event -This event is emitted when the panel is hidden. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this panel. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the panel's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="error"> -@event -This event is emitted when an uncaught runtime error occurs in one of the -panel's content scripts. - -@argument {Error} -Listeners are passed a single argument, the -[Error](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error) -object. -</api> - -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/passwords.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/passwords.md deleted file mode 100644 index 6a4b246..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/passwords.md +++ /dev/null @@ -1,564 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `passwords` module allows add-ons to interact with Firefox's -[Password Manager](http://support.mozilla.com/en-US/kb/Remembering%20passwords) -to add, retrieve and remove stored credentials. - -A _credential_ is the set of information a user supplies to authenticate -herself with a service. Typically a credential consists of a username and a -password. - -Using this module you can: - -1. **Search** for credentials which have been stored in the Password Manager. - You can then use the credentials to access their related service (for - example, by logging into a web site). - -2. **Store** credentials in the Password Manager. You can store different sorts - of credentials, as outlined in the "Credentials" section below. - -3. **Remove** stored credentials from the Password Manager. - -## Credentials ## - -In this API, credentials are represented by objects. - -You create credential objects to pass into the API, and the API also returns -credential objects to you. The sections below explain both the properties you -should define on credential objects and the properties you can expect on -credential objects returned by the API. - -All credential objects include `username` and `password` properties. Different -sorts of stored credentials include various additional properties, as -outlined in this section. - -You can use the Passwords API with three sorts of credentials: - -* Add-on credentials -* HTML form credentials -* HTTP Authentication credentials - -### Add-on Credential ### - -These are associated with your add-on rather than a particular web site. -They contain the following properties: - -<table> -<colgroup> -<col width="25%"> -</colgroup> -<tr> - <td> - <code>username</code> - </td> - <td> - The username. - </td> -</tr> - -<tr> - <td> - <code>password</code> - </td> - <td> - The password. - </td> -</tr> - -<tr> - <td> - <code>url</code> - </td> - <td> - <p>For an add-on credential, this property is of the form:<br><code> - addon:<addon-id></code>, where <code><addon-id></code> - is the add-on's - <a href="dev-guide/addon-development/program-id.html"> - Program ID</a>.</p> - <p>You don't supply this value when storing an add-on credential: it is - automatically generated for you. However, you can use it to work out - which stored credentials belong to your add-on by comparing it with the - <code>uri</code> property of the - <a href="packages/addon-kit/docs/self.html"><code>self</code></a> - module.</p> - </td> -</tr> - -<tr> - <td> - <code>realm</code> - </td> - <td> - <p>You can use this as a name for the credential, to distinguish - it from any other credentials you've stored.</p> - <p>The realm is displayed - in Firefox's Password Manager, under "Site", in brackets after the URL. - For example, if the realm for a credential is "User Registration", then - its "Site" field will look something like:</p> - <code>addon:jid0-01mBBFyu0ZAXCFuB1JYKooSTKIc (User Registration)</code> - </td> -</tr> - -</table> - -### HTML Form Credential ### - -If a web service uses HTML forms to authenticate its users, then the -corresponding credential is an HTML Form credential. - -It contains the following properties: - -<table> -<colgroup> -<col width="25%"> -</colgroup> -<tr> - <td> - <code>username</code> - </td> - <td> - The username. - </td> -</tr> - -<tr> - <td> - <code>password</code> - </td> - <td> - The password. - </td> -</tr> - -<tr> - <td> - <code>url</code> - </td> - <td> - The URL for the web service which requires the credential. - You should omit anything after the hostname and (optional) port. - </td> -</tr> - -<tr> - <td> - <code>formSubmitURL</code> - </td> - <td> - The value of the form's "action" attribute. - You should omit anything after the hostname and (optional) port. - If the form doesn't contain an "action" attribute, this property should - match the <code>url</code> property. - </td> -</tr> - -<tr> - <td> - <code>usernameField</code> - </td> - <td> - The value of the "name" attribute for the form's username field. - </td> -</tr> - -<tr> - <td> - <code>passwordField</code> - </td> - <td> - The value of the "name" attribute for the form's password field. - </td> -</tr> - -</table> - -So: given a form at `http://www.example.com/login` -with the following HTML: - -<script type="syntaxhighlighter" class="brush: html"><![CDATA[ -<form action="http://login.example.com/foo/authenticate.cgi"> - <div>Please log in.</div> - <label>Username:</label> <input type="text" name="uname"> - <label>Password:</label> <input type="password" name="pword"> -</form> -]]> -</script> - -The corresponding values for the credential (excluding username and password) -should be: - -<pre> - url: "http://www.example.com" - formSubmitURL: "http://login.example.com" - usernameField: "uname" - passwordField: "pword" -</pre> - -Note that for both `url` and `formSubmitURL`, the portion of the URL after the -hostname is omitted. - -### HTTP Authentication Credential ### - -These are used to authenticate the user to a web site -which uses HTTP Authentication, as detailed in -[RFC 2617](http://tools.ietf.org/html/rfc2617). -They contain the following properties: - -<table> -<colgroup> -<col width="25%"> -</colgroup> -<tr> - <td> - <code>username</code> - </td> - <td> - The username. - </td> -</tr> - -<tr> - <td> - <code>password</code> - </td> - <td> - The password. - </td> -</tr> - -<tr> - <td> - <code>url</code> - </td> - <td> - The URL for the web service which requires the credential. - You should omit anything after the hostname and (optional) port. - </td> -</tr> - -<tr> - <td> - <code>realm</code> - </td> - <td> - <p>The WWW-Authenticate response header sent by the server may include a - "realm" field as detailed in - <a href="http://tools.ietf.org/html/rfc2617">RFC 2617</a>. If it does, - this property contains the value for the "realm" field. Otherwise, it is - omitted.</p> - <p>The realm is displayed in Firefox's Password Manager, under "Site", - in brackets after the URL.</p> - </td> -</tr> - -</table> - -So: if a web server at `http://www.example.com` requested authentication with -a response code like this: - -<pre> - HTTP/1.0 401 Authorization Required - Server: Apache/1.3.27 - WWW-Authenticate: Basic realm="ExampleCo Login" -</pre> - -The corresponding values for the credential (excluding username and password) -should be: - -<pre> - url: "http://www.example.com" - realm: "ExampleCo Login" -</pre> - -## onComplete and onError ## - -This API is explicitly asynchronous, so all its functions take two callback -functions as additional options: `onComplete` and `onError`. - -`onComplete` is called when the operation has completed successfully and -`onError` is called when the function encounters an error. - -Because the `search` function is expected to return a list of matching -credentials, its `onComplete` option is mandatory. Because the other functions -don't return a value in case of success their `onComplete` options are -optional. - -For all functions, `onError` is optional. - -<api name="search"> -@function - -This function is used to retrieve a credential, or a list of credentials, -stored in the Password Manager. - -You pass it any subset of the possible properties a credential can contain. -Credentials which match all the properties you supplied are returned as an -argument to the `onComplete` callback. - -So if you pass in an empty set of properties, all stored credentials are -returned: - - function show_all_passwords() { - require("passwords").search({ - onComplete: function onComplete(credentials) { - credentials.forEach(function(credential) { - console.log(credential.username); - console.log(credential.password); - }); - } - }); - } - -If you pass it a single property, only credentials matching that property are -returned: - - function show_passwords_for_joe() { - require("passwords").search({ - username: "joe", - onComplete: function onComplete(credentials) { - credentials.forEach(function(credential) { - console.log(credential.username); - console.log(credential.password); - }); - } - }); - } - -If you pass more than one property, returned credentials must match all of -them: - - function show_google_password_for_joe() { - require("passwords").search({ - username: "joe", - url: "https://www.google.com", - onComplete: function onComplete(credentials) { - credentials.forEach(function(credential) { - console.log(credential.username); - console.log(credential.password); - }); - } - }); - } - -To retrieve only credentials associated with your add-on, use the `url` -property, initialized from `self.uri`: - - function show_my_addon_passwords() { - require("passwords").search({ - url: require("self").uri, - onComplete: function onComplete(credentials) { - credentials.forEach(function(credential) { - console.log(credential.username); - console.log(credential.password); - }); - } - }); - } - -@param options {object} -The `options` object may contain any credential properties. It is used to -restrict the set of credentials returned by the `search` function. - -See "Credentials" above for details on what these properties should be. - -Additionally, `options` must contain a function assigned to its `onComplete` -property: this is called when the function completes and is passed the set of -credentials retrieved. - -`options` may contain a function assigned to its `onError` property, which is -called if the function encounters an error. `onError` is passed the error as an -[nsIException](https://developer.mozilla.org/en/nsIException) object. - -@prop [username] {string} -The username for the credential. - -@prop [password] {string} -The password for the credential. - -@prop [url] {string} -The URL associated with the credential. - -@prop [formSubmitURL] {string} -The URL an HTML form credential is submitted to. - -@prop [realm] {string} -For HTTP Authentication credentials, the realm for which the credential was -requested. For add-on credentials, a name for the credential. - -@prop [usernameField] {string} -The value of the `name` attribute for the user name input field in a form. - -@prop [passwordField] {string} -The value of the `name` attribute for the password input field in a form. - -@prop onComplete {function} -The callback function that is called once the function completes successfully. -It is passed all the matching credentials as a list. This is the only -mandatory option. - -@prop [onError] {function} -The callback function that is called if the function failed. The -callback is passed an `error` containing a reason of a failure: this is an -[nsIException](https://developer.mozilla.org/en/nsIException) object. - -</api> - -<api name="store"> -@function - -This function is used to store a credential in the Password Manager. - -It takes an `options` object as an argument: this contains all the properties -for the new credential. - -As different sorts of credentials contain different properties, the -appropriate options differ depending on the sort of credential being stored. - -To store an add-on credential: - - require("passwords").store({ - realm: "User Registration", - username: "joe", - password: "SeCrEt123", - }); - -To store an HTML form credential: - - require("passwords").store({ - url: "http://www.example.com", - formSubmitURL: "http://login.example.com", - username: "joe", - usernameField: "uname", - password: "SeCrEt123", - passwordField: "pword" - }); - -To store an HTTP Authentication credential: - - require("passwords").store({ - url: "http://www.example.com", - realm: "ExampleCo Login", - username: "joe", - password: "SeCrEt123", - }); - -See "Credentials" above for more details on how to set these properties. - -The options parameter may also include `onComplete` and `onError` -callback functions, which are called when the function has completed -successfully and when it encounters an error, respectively. These options -are both optional. - -@param options {object} -An object containing the properties of the credential to be stored, and -optional `onComplete` and `onError` callback functions. - -@prop username {string} -The username for the credential. - -@prop password {string} -The password for the credential. - -@prop [url] {string} -The URL to which the credential applies. Omitted for add-on -credentials. - -@prop [formSubmitURL] {string} -The URL a form-based credential was submitted to. Omitted for add-on -credentials and HTTP Authentication credentials. - -@prop [realm] {string} -For HTTP Authentication credentials, the realm for which the credential was -requested. For add-on credentials, a name for the credential. - -@prop [usernameField] {string} -The value of the `name` attribute for the username input in a form. -Omitted for add-on credentials and HTTP Authentication credentials. - -@prop [passwordField] {string} -The value of the `name` attribute for the password input in a form. -Omitted for add-on credentials and HTTP Authentication credentials. - -@prop [onComplete] {function} -The callback function that is called once the function completes successfully. - -@prop [onError] {function} -The callback function that is called if the function failed. The -callback is passed an `error` argument: this is an -[nsIException](https://developer.mozilla.org/en/nsIException) object. - -</api> - -<api name="remove"> -@function - -Removes a stored credential. You supply it all the properties of the credential -to remove, along with optional `onComplete` and `onError` callbacks. - -Because you must supply all the credential's properties, it may be convenient -to call `search` first, and use its output as the input to `remove`. For -example, to remove all of joe's stored credentials: - - require("passwords").search({ - username: "joe", - onComplete: function onComplete(credentials) { - credentials.forEach(require("passwords").remove); - }) - }); - -To change an existing credential just call `store` after `remove` succeeds: - - require("passwords").remove({ - realm: "User Registration", - username: "joe", - password: "SeCrEt123" - onComplete: function onComplete() { - require("passwords").store({ - realm: "User Registration", - username: "joe", - password: "{{new password}}" - }) - } - }); - -@param options {object} - -An object containing all the properties of the credential to be removed, -and optional `onComplete` and `onError` callback functions. - -@prop username {string} -The username for the credential. - -@prop password {string} -The password for the credential. - -@prop [url] {string} -The URL to which the credential applies. Omitted for add-on -credentials. - -@prop [formSubmitURL] {string} -The URL a form-based credential was submitted to. Omitted for add-on -credentials and HTTP Authentication credentials. - -@prop [realm] {string} -For HTTP Authentication credentials, the realm for which the credential was -requested. For add-on credentials, a name for the credential. - -@prop [usernameField] {string} -The value of the `name` attribute for the username input in a form. -Omitted for add-on credentials and HTTP Authentication credentials. - -@prop [passwordField] {string} -The value of the `name` attribute for the password input in a form. -Omitted for add-on credentials and HTTP Authentication credentials. - -@prop [onComplete] {function} -The callback function that is called once the function has completed -successfully. - -@prop [onError] {function} -The callback function that is called if the function failed. The -callback is passed an `error` argument: this is an -[nsIException](https://developer.mozilla.org/en/nsIException) object. - -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/private-browsing.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/private-browsing.md deleted file mode 100644 index cad6166..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/private-browsing.md +++ /dev/null @@ -1,46 +0,0 @@ -<!-- contributed by Paul O'Shannessy [paul@oshannessy.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `private-browsing` module allows you to access Firefox's private browsing -mode, detecting if it is active and when its state changes. - -This module is available in all applications. However, only Firefox will ever -transition into or out of private browsing mode. For all other applications, -`pb.isActive` will always be `false`, and none of the events will be emitted. - -<api name="isActive"> -@property {boolean} - This read-only boolean is true if private browsing mode is turned on. -</api> - -<api name="activate"> -@function - Turns on private browsing mode. -</api> - -<api name="deactivate"> -@function - Turns off private browsing mode. -</api> - -<api name="start"> -@event -Emitted immediately after the browser enters private browsing mode. - - var pb = require("private-browsing"); - pb.on("start", function() { - // Do something when the browser starts private browsing mode. - }); - -</api> - -<api name="stop"> -@event -Emitted immediately after the browser exits private browsing mode. - - var pb = require("private-browsing"); - pb.on("stop", function() { - // Do something when the browser stops private browsing mode. - }); -</api>
\ No newline at end of file diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/request.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/request.md deleted file mode 100644 index 77bea43..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/request.md +++ /dev/null @@ -1,192 +0,0 @@ -The `request` module lets you make simple yet powerful network requests. - -<api name="Request"> -@class -The `Request` object is used to make `GET` or `POST` network requests. It is -constructed with a URL to which the request is sent. Optionally the user may -specify a collection of headers and content to send alongside the request and -a callback which will be executed once the request completes. - -Once a `Request` object has been created a `GET` request can be executed by -calling its `get()` method, or a `POST` request by calling its `post()` method. - -When the server completes the request, the `Request` object emits a "complete" -event. Registered event listeners are passed a `Response` object. - -Each `Request` object is designed to be used once. Once `GET` or `POST` are -called, attempting to call either will throw an error. - -Since the request is not being made by any particular website, requests made -here are not subject to the same-domain restriction that requests made in web -pages are subject to. - -With the exception of `response`, all of a `Request` object's properties -correspond with the options in the constructor. Each can be set by simply -performing an assignment. However, keep in mind that the same validation rules -that apply to `options` in the constructor will apply during assignment. Thus, -each can throw if given an invalid value. - -The example below shows how to use Request to get the most recent public tweet. - - var Request = require("request").Request; - var latestTweetRequest = Request({ - url: "http://api.twitter.com/1/statuses/public_timeline.json", - onComplete: function (response) { - var tweet = response.json[0]; - console.log("User: " + tweet.user.screen_name); - console.log("Tweet: " + tweet.text); - } - }); - - // Be a good consumer and check for rate limiting before doing more. - Request({ - url: "http://api.twitter.com/1/account/rate_limit_status.json", - onComplete: function (response) { - if (response.json.remaining_hits) { - latestTweetRequest.get(); - } else { - console.log("You have been rate limited!"); - } - } - }).get(); - -<api name="Request"> -@constructor -This constructor creates a request object that can be used to make network -requests. The constructor takes a single parameter `options` which is used to -set several properties on the resulting `Request`. -@param options {object} - @prop url {string} - This is the url to which the request will be made. - - @prop [onComplete] {function} - This function will be called when the request has received a response (or in - terms of XHR, when `readyState == 4`). The function is passed a `Response` - object. - - @prop [headers] {object} - An unordered collection of name/value pairs representing headers to send - with the request. - - @prop [content] {string,object} - The content to send to the server. If `content` is a string, it should be - URL-encoded (use `encodeURIComponent`). If `content` is an object, it - should be a collection of name/value pairs. Nested objects & arrays should - encode safely. - - For `GET` requests, the query string (`content`) will be appended to the - URL. For `POST` requests, the query string will be sent as the body of the - request. - - @prop [contentType] {string} - The type of content to send to the server. This explicitly sets the - `Content-Type` header. The default value is `application/x-www-form-urlencoded`. - - @prop [overrideMimeType] {string} - Use this string to override the MIME type returned by the server in the - response's Content-Type header. You can use this to treat the content as a - different MIME type, or to force text to be interpreted using a specific - character. - - For example, if you're retrieving text content which was encoded as - ISO-8859-1 (Latin 1), it will be given a content type of "utf-8" and - certain characters will not display correctly. To force the response to - be interpreted as Latin-1, use `overrideMimeType`: - - var Request = require("request").Request; - var quijote = Request({ - url: "http://www.latin1files.org/quijote.txt", - overrideMimeType: "text/plain; charset=latin1", - onComplete: function (response) { - console.log(response.text); - } - }); - - quijote.get(); - -</api> - -<api name="url"> -@property {string} -</api> - -<api name="headers"> -@property {object} -</api> - -<api name="content"> -@property {string,object} -</api> - -<api name="contentType"> -@property {string} -</api> - -<api name="response"> -@property {Response} -</api> - -<api name="get"> -@method -Make a `GET` request. -@returns {Request} -</api> - -<api name="post"> -@method -Make a `POST` request. -@returns {Request} -</api> - -<api name="complete"> -@event -The `Request` object emits this event when the request has completed and a -response has been received. - -@argument {Response} -Listener functions are passed the response to the request as a `Response` object. -</api> - -</api> - - -<api name="Response"> -@class -The Response object contains the response to a network request issued using a -`Request` object. It is returned by the `get()` or `post()` method of a -`Request` object. - -All members of a `Response` object are read-only. -<api name="text"> -@property {string} -The content of the response as plain text. -</api> - -<api name="json"> -@property {object} -The content of the response as a JavaScript object. The value will be `null` -if the document cannot be processed by `JSON.parse`. -</api> - -<api name="status"> -@property {string} -The HTTP response status code (e.g. *200*). -</api> - -<api name="statusText"> -@property {string} -The HTTP response status line (e.g. *OK*). -</api> - -<api name="headers"> -@property {object} -The HTTP response headers represented as key/value pairs. - -To print all the headers you can do something like this: - - for (var headerName in response.headers) { - console.log(headerName + " : " + response.headers[headerName]); - } - -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/selection.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/selection.md deleted file mode 100644 index 62a3d64..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/selection.md +++ /dev/null @@ -1,86 +0,0 @@ -<!-- contributed by Eric H. Jung [eric.jung@yahoo.com] --> -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `selection` module provides a means to get and set text and HTML selections -in the current Firefox page. It can also observe new selections. - -Registering for Selection Notifications ---------------------------------------- - -To be notified when the user makes a selection, register a listener for the -"select" event. Each listener will be called after a selection is made. - - function myListener() { - console.log("A selection has been made."); - } - var selection = require("selection"); - selection.on('select', myListener); - - // You can remove listeners too. - selection.removeListener('select', myListener); - -Iterating Over Discontiguous Selections ---------------------------------------- - -Discontiguous selections can be accessed by iterating over the `selection` -module itself. Each iteration yields a `Selection` object from which `text`, -`html`, and `isContiguous` properties can be accessed. - - -Examples --------- - -Log the current contiguous selection as text: - - var selection = require("selection"); - if (selection.text) - console.log(selection.text); - -Log the current discontiguous selections as HTML: - - var selection = require("selection"); - if (!selection.isContiguous) { - for (var subselection in selection) { - console.log(subselection.html); - } - } - -Surround HTML selections with delimiters: - - var selection = require("selection"); - selection.on('select', function () { - selection.html = "\\\" + selection.html + "///"; - }); - -<api name="text"> -@property {string} - Gets or sets the current selection as plain text. Setting the selection - removes all current selections, inserts the specified text at the location of - the first selection, and selects the new text. Getting the selection when - there is no current selection returns `null`. Setting the selection when there - is no current selection throws an exception. Getting the selection when - `isContiguous` is `true` returns the text of the first selection. -</api> - -<api name="html"> -@property {string} - Gets or sets the current selection as HTML. Setting the selection removes all - current selections, inserts the specified text at the location of the first - selection, and selects the new text. Getting the selection when there is no - current selection returns `null`. Setting the selection when there is no - current selection throws an exception. Getting the selection when - `isContiguous` is `true` returns the text of the first selection. -</api> - -<api name="isContiguous"> -@property {boolean} - `true` if the current selection is a single, contiguous selection, and `false` - if there are two or more discrete selections, each of which may or may not be - spatially adjacent. (Discontiguous selections can be created by the user with - Ctrl+click-and-drag.) -</api> - -<api name="select"> -@event - This event is emitted whenever the user makes a new selection in a page. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/self.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/self.md deleted file mode 100644 index e76ad50..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/self.md +++ /dev/null @@ -1,73 +0,0 @@ -The `self` module provides access to data that is bundled with the add-on -as a whole. It also provides access to the -[Program ID](dev-guide/addon-development/program-id.html), a value which is -unique for each add-on. - -Note that the `self` module is completely different from the global `self` -object accessible to content scripts, which is used by a content script to -[communicate with the add-on code](dev-guide/addon-development/content-scripts/using-port.html). - -<api name="id"> -@property {string} -This property is a printable string that is unique for each add-on. It comes -from the `id` property set in the `package.json` file in the main package -(i.e. the package in which you run `cfx xpi`). While not generally of use to -add-on code directly, it can be used by internal API code to index local -storage and other resources that are associated with a particular add-on. -Eventually, this ID will be unspoofable (see -[JEP 118](https://wiki.mozilla.org/Labs/Jetpack/Reboot/JEP/118) for details). -</api> - -<api name="name"> -@property {string} -This property contains the add-on's short name. It comes from the `name` -property in the main package's `package.json` file. -</api> - -<api name="version"> -@property {string} -This property contains the add-on's version string. It comes from the -`version` property set in the `package.json` file in the main package. -</api> - -<api name="data"> -@property {object} -The `data` object is used to access data that was bundled with the add-on. -This data lives in the main package's `data/` directory, immediately below -the `package.json` file. All files in this directory will be copied into the -XPI and made available through the `data` object. - -The [Package Specification](dev-guide/addon-development/package-spec.html) -section explains the `package.json` file. - -<api name="data.load"> -@method -The `data.load(NAME)` method returns the contents of an embedded data file, -as a string. It is most useful for data that will be modified or parsed in -some way, such as JSON, XML, plain text, or perhaps an HTML template. For -data that can be displayed directly in a content frame, use `data.url(NAME)`. -@param name {string} The filename to be read, relative to the - package's `data` directory. Each package that uses the `self` module - will see its own `data` directory. -@returns {string} -</api> - -<api name="data.url"> -@method -The `data.url(NAME)` method returns a URL instance that points at an embedded -data file. It is most useful for data that can be displayed directly in a -content frame. The URL instance can be passed to a content frame constructor, -such as the Panel: - - var self = require("self"); - var myPanel = require("panel").Panel({ - contentURL: self.data.url("my-panel-content.html") - }); - myPanel.show(); - -@param name {string} The filename to be read, relative to the - package's `data` directory. Each package that uses the `self` module - will see its own `data` directory. -@returns {URL} -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-prefs.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-prefs.md deleted file mode 100644 index 824a151..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-prefs.md +++ /dev/null @@ -1,70 +0,0 @@ -<!-- contributed by Erik Vold [erikvvold@gmail.com] --> - -#### *Experimental* - -The `simple-prefs` module lets you easily and persistently store preferences -across application restarts, which can be configured by users in the -Add-ons Manager. - -Introduction ------------- - -With the simple preferences module you can store booleans, integers, and string -values. - - -Inline Options & Default Values -------------------------------- - -In order to have a `options.xul` (for inline options) generated, or a -`defaults/preferences/prefs.js` for default preferences, you will need to -define the preferences in your `package.json`, like so: - - { - "fullName": "Example Add-on", - ... - "preferences": [{ - "name": "somePreference", - "title": "Some preference title", - "type": "string", - "value": "this is the default string value" - }] - } - - -<api name="prefs"> -@property {object} - *experimental* A persistent object private to your add-on. Properties with boolean, - number, and string values will be persisted in the Mozilla preferences system. -</api> - - -<api name="on"> -@function - *experimental* Registers an event `listener` that will be called when a preference is changed. - -**Example:** - - function onPrefChange(prefName) { - console.log("The " + prefName + " preference changed."); - } - require("simple-prefs").on("somePreference", onPrefChange); - require("simple-prefs").on("someOtherPreference", onPrefChange); - - -@param prefName {String} - The name of the preference to watch for changes. -@param listener {Function} - The listener function that processes the event. -</api> - -<api name="removeListener"> -@function - *experimental* Unregisters an event `listener` for the specified preference. - -@param prefName {String} - The name of the preference to watch for changes. -@param listener {Function} - The listener function that processes the event. -</api> - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-storage.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-storage.md deleted file mode 100644 index e34e333..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/simple-storage.md +++ /dev/null @@ -1,125 +0,0 @@ -The `simple-storage` module lets you easily and persistently store data across -application restarts. If you're familiar with [DOM storage][] on the Web, it's -kind of like that, but for add-ons. - -[DOM storage]: https://developer.mozilla.org/en/DOM/Storage - - -Introduction ------------- - -The simple storage module exports an object called `storage` that is persistent -and private to your add-on. It's a normal JavaScript object, and you can treat -it as you would any other. - -To store a value, just assign it to a property on `storage`: - - var ss = require("simple-storage"); - ss.storage.myArray = [1, 1, 2, 3, 5, 8, 13]; - ss.storage.myBoolean = true; - ss.storage.myNull = null; - ss.storage.myNumber = 3.1337; - ss.storage.myObject = { a: "foo", b: { c: true }, d: null }; - ss.storage.myString = "O frabjous day!"; - -You can store array, boolean, number, object, null, and string values. If you'd -like to store other types of values, you'll first have to convert them to -strings or another one of these types. - -Be careful to set properties on the `storage` object and not the module itself: - - // This is no good! - var ss = require("simple-storage"); - ss.foo = "I will not be saved! :("; - - -Quotas ------- - -The simple storage available to your add-on is limited. Currently this limit is -about five megabytes (5,242,880 bytes). You can choose to be notified when you -go over quota, and you should respond by reducing the amount of data in storage. -If the user quits the application while you are over quota, all data stored -since the last time you were under quota will not be persisted. You should not -let that happen. - -To listen for quota notifications, register a listener for the `"OverQuota"` -event. It will be called when your storage goes over quota. - - function myOnOverQuotaListener() { - console.log("Uh oh."); - } - ss.on("OverQuota", myOnOverQuotaListener); - -Listeners can also be removed: - - ss.removeListener("OverQuota", myOnOverQuotaListener); - -To find out how much of your quota you're using, check the module's `quotaUsage` -property. It indicates the percentage of quota your storage occupies. If -you're within your quota, it's a number from 0 to 1, inclusive, and if you're -over, it's a number greater than 1. - -Therefore, when you're notified that you're over quota, respond by removing -storage until your `quotaUsage` is less than or equal to 1. Which particular -data you remove is up to you. For example: - - ss.storage.myList = [ /* some long array */ ]; - ss.on("OverQuota", function () { - while (ss.quotaUsage > 1) - ss.storage.myList.pop(); - }); - - -Private Browsing ----------------- - -*This section applies only to add-ons running on Firefox.* - -If your storage is related to your users' Web history, personal information, or -other sensitive data, your add-on should respect [private browsing mode][SUMO]. -While private browsing mode is active, you should not store any sensitive data. - -Because any kind of data can be placed into simple storage, support for private -browsing is not built into the module. Instead, use the -[`private-browsing`](packages/addon-kit/docs/private-browsing.html) module to -check private browsing status and respond accordingly. - -For example, the URLs your users visit should not be stored during private -browsing. If your add-on records the URL of the selected tab, here's how you -might handle that: - - ss.storage.history = []; - var privateBrowsing = require("private-browsing"); - if (!privateBrowsing.active) { - var url = getSelectedTabURL(); - ss.storage.history.push(url); - } - -For more information on supporting private browsing, see its [Mozilla Developer -Network documentation][MDN]. While that page does not apply specifically to -SDK-based add-ons (and its code samples don't apply at all), you should follow -its guidance on best practices and policies. - -[SUMO]: http://support.mozilla.com/en-US/kb/Private+Browsing -[MDN]: https://developer.mozilla.org/En/Supporting_private_browsing_mode - - -<api name="storage"> -@property {object} - A persistent object private to your add-on. Properties with array, boolean, - number, object, null, and string values will be persisted. -</api> - -<api name="quotaUsage"> -@property {number} - A number in the range [0, Infinity) that indicates the percentage of quota - occupied by storage. A value in the range [0, 1] indicates that the storage - is within quota. A value greater than 1 indicates that the storage exceeds - quota. -</api> - -<api name="OverQuota"> -@event -The module emits this event when your add-on's storage goes over its quota. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/tabs.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/tabs.md deleted file mode 100644 index a6a858f..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/tabs.md +++ /dev/null @@ -1,381 +0,0 @@ -<!-- contributed by Dietrich Ayala [dietrich@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `tabs` module provides easy access to tabs and tab-related events. - -The module itself can be used like a basic list of all opened -tabs across all windows. In particular, you can enumerate it: - - var tabs = require('tabs'); - for each (var tab in tabs) - console.log(tab.title); - -You can also access individual tabs by index: - - var tabs = require('tabs'); - - tabs.on('ready', function () { - console.log('first: ' + tabs[0].title); - console.log('last: ' + tabs[tabs.length-1].title); - }); - -You can open a new tab, specifying various properties including location: - - var tabs = require("tabs"); - tabs.open("http://www.example.com"); - -You can register event listeners to be notified when tabs open, close, finish -loading DOM content, or are made active or inactive: - - var tabs = require("tabs"); - - // Listen for tab openings. - tabs.on('open', function onOpen(tab) { - myOpenTabs.push(tab); - }); - - // Listen for tab content loads. - tabs.on('ready', function(tab) { - console.log('tab is loaded', tab.title, tab.url) - }); - -You can get and set various properties of tabs (but note that properties - relating to the tab's content, such as the URL, will not contain valid -values until after the tab's `ready` event fires). By setting the `url` -property you can load a new page in the tab: - - var tabs = require("tabs"); - tabs.on('activate', function(tab) { - tab.url = "http://www.example.com"; - }); - -You can attach a [content script](dev-guide/addon-development/web-content.html) -to the page hosted in a tab, and use that to access and manipulate the page's -content: - - var tabs = require("tabs"); - - tabs.on('activate', function(tab) { - tab.attach({ - contentScript: 'self.postMessage(document.body.innerHTML);', - onMessage: function (message) { - console.log(message); - } - }); - }); - -<api name="activeTab"> -@property {Tab} - -The currently active tab in the active window. This property is read-only. To -activate a `Tab` object, call its `activate` method. - -**Example** - - // Get the active tab's title. - var tabs = require("tabs"); - console.log("title of active tab is " + tabs.activeTab.title); -</api> - -<api name="length"> -@property {number} -The number of open tabs across all windows. -</api> - -<api name="open"> -@function -Opens a new tab. The new tab will open in the active window or in a new window, -depending on the `inNewWindow` option. - -**Example** - - var tabs = require("tabs"); - - // Open a new tab on active window and make tab active. - tabs.open("http://www.mysite.com"); - - // Open a new tab in a new window and make it active. - tabs.open({ - url: "http://www.mysite.com", - inNewWindow: true - }); - - // Open a new tab on active window in the background. - tabs.open({ - url: "http://www.mysite.com", - inBackground: true - }); - - // Open a new tab as an app tab and do something once it's open. - tabs.open({ - url: "http://www.mysite.com", - isPinned: true, - onOpen: function onOpen(tab) { - // do stuff like listen for content - // loading. - } - }); - -@param options {object} -An object containing configurable options for how and where the tab will be -opened, as well as a listeners for the tab events. - -If the only option being used is `url`, then a bare string URL can be passed to -`open` instead of adding at a property of the `options` object. - -@prop [url] {string} -String URL to be opened in the new tab. -This is a required property. - -@prop [inNewWindow] {boolean} -If present and true, a new browser window will be opened and the URL will be -opened in the first tab in that window. This is an optional property. - -@prop [inBackground] {boolean} -If present and true, the new tab will be opened to the right of the active tab -and will not be active. This is an optional property. - -@prop [isPinned] {boolean} -If present and true, then the new tab will be pinned as an -[app tab](http://support.mozilla.com/en-US/kb/what-are-app-tabs). - -@prop [onOpen] {function} -A callback function that will be registered for 'open' event. -This is an optional property. -@prop [onClose] {function} -A callback function that will be registered for 'close' event. -This is an optional property. -@prop [onReady] {function} -A callback function that will be registered for 'ready' event. -This is an optional property. -@prop [onActivate] {function} -A callback function that will be registered for 'activate' event. -This is an optional property. -@prop [onDeactivate] {function} -A callback function that will be registered for 'deactivate' event. -This is an optional property. -</api> - -<api name="Tab"> -@class -A `Tab` instance represents a single open tab. It contains various tab -properties, several methods for manipulation, as well as per-tab event -registration. - -Tabs emit all the events described in the Events section. Listeners are -passed the `Tab` object that triggered the event. - -<api name="title"> -@property {string} -The title of the page currently loaded in the tab. -This property can be set to change the tab title. -</api> - -<api name="url"> -@property {String} -The URL of the page currently loaded in the tab. -This property can be set to load a different URL in the tab. -</api> - -<api name="favicon"> -@property {string} -The URL of the favicon for the page currently loaded in the tab. -This property is read-only. -</api> - -<api name="index"> -@property {integer} -The index of the tab relative to other tabs in the application window. -This property can be set to change its relative position. -</api> - -<api name="isPinned"> -@property {boolean} -Whether or not tab is pinned as an [app tab][]. -This property is read-only. -[app tab]:http://support.mozilla.com/en-US/kb/what-are-app-tabs -</api> - -<api name="getThumbnail"> -@property {method} -Returns thumbnail data URI of the page currently loaded in this tab. -</api> - -<api name="pin"> -@method -Pins this tab as an [app tab][]. -[app tab]:http://support.mozilla.com/en-US/kb/what-are-app-tabs -</api> - -<api name="unpin"> -@method -Unpins this tab. -</api> - -<api name="close"> -@method -Closes this tab. - -@param [callback] {function} -A function to be called when the tab finishes its closing process. -This is an optional argument. -</api> - -<api name="reload"> -@method -Reloads this tab. -</api> - -<api name="activate"> -@method -Makes this tab active, which will bring this tab to the foreground. -</api> - -<api name="attach"> -@method - Create a page mod and attach it to the document in the tab. - -**Example** - - var tabs = require("tabs"); - - tabs.on('ready', function(tab) { - tab.attach({ - contentScript: - 'document.body.style.border = "5px solid red";' - }); - }); - -@param options {object} - Options for the page mod, 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. - 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. - -@returns {Worker} - See [Content Scripts guide](dev-guide/addon-development/web-content.html) - to learn how to use the `Worker` object to communicate with the content script. - -</api> - -<api name="close"> -@event - -This event is emitted when the tab is closed. It's also emitted when the -tab's window is closed. - -@argument {Tab} -Listeners are passed the tab object. -</api> - -<api name="ready"> -@event - -This event is emitted when the DOM for the tab's content is ready. It is -equivalent to the `DOMContentLoaded` event for the given content page. - -A single tab will emit this event every time the DOM is loaded: so it will be -emitted again if the tab's location changes or the content is reloaded. - -After this event has been emitted, all properties relating to the tab's -content can be used. - -@argument {Tab} -Listeners are passed the tab object. -</api> - -<api name="activate"> -@event - -This event is emitted when the tab is made active. - -@argument {Tab} -Listeners are passed the tab object. -</api> - -<api name="deactivate"> -@event - -This event is emitted when the tab is made inactive. - -@argument {Tab} -Listeners are passed the tab object. -</api> - -</api> - -<api name="open"> -@event - -This event is emitted when a new tab is opened. This does not mean that -the content has loaded, only that the browser tab itself is fully visible -to the user. - -Properties relating to the tab's content (for example: `title`, `favicon`, -and `url`) will not be correct at this point. If you need to access these -properties, listen for the `ready` event: - - var tabs = require("tabs"); - tabs.on('open', function(tab){ - tab.on('ready', function(tab){ - console.log(tab.url); - }); - }); - -@argument {Tab} -Listeners are passed the tab object that just opened. -</api> - -<api name="close"> -@event - -This event is emitted when a tab is closed. When a window is closed -this event will be emitted for each of the open tabs in that window. - -@argument {Tab} -Listeners are passed the tab object that has closed. -</api> - -<api name="ready"> -@event - -This event is emitted when the DOM for a tab's content is ready. -It is equivalent to the `DOMContentLoaded` event for the given content page. - -A single tab will emit this event every time the DOM is loaded: so it will be -emitted again if the tab's location changes or the content is reloaded. - -After this event has been emitted, all properties relating to the tab's -content can be used. - -@argument {Tab} -Listeners are passed the tab object that has loaded. -</api> - -<api name="activate"> -@event - -This event is emitted when an inactive tab is made active. - -@argument {Tab} -Listeners are passed the tab object that has become active. -</api> - -<api name="deactivate"> -@event - -This event is emitted when the active tab is made inactive. - -@argument {Tab} -Listeners are passed the tab object that has become inactive. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/timers.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/timers.md deleted file mode 100644 index bc36750..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/timers.md +++ /dev/null @@ -1,48 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> -<!-- contributed by Irakli Gozalishvil [gozala@mozilla.com] --> - -The `timers` module provides access to web-like timing functionality. - -<api name="setTimeout"> -@function - Schedules `callback` to be called in `ms` milliseconds. Any additional - arguments are passed straight through to the callback. -@returns {integer} - An ID that can later be used to undo this scheduling, if `callback` hasn't yet - been called. -@param callback {function} - Function to be called. -@param ms {integer} - Interval in milliseconds after which the function will be called. -</api> - -<api name="clearTimeout"> -@function - Given an ID returned from `setTimeout()`, prevents the callback with the ID - from being called (if it hasn't yet been called). -@param ID {integer} - An ID returned from `setTimeout()`. -</api> - -<api name="setInterval"> -@function - Schedules `callback` to be called repeatedly every `ms` milliseconds. Any - additional arguments are passed straight through to the callback. -@returns {integer} - An ID that can later be used to unschedule the callback. -@param callback {function} - Function to be called. -@param ms {integer} - Interval in milliseconds at which the function will be called. -</api> - -<api name="clearInterval"> -@function - Given an ID returned from `setInterval()`, prevents the callback with the ID - from being called again. -@param ID {integer} - An ID returned from `setInterval()`. -</api> - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/widget.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/widget.md deleted file mode 100644 index aa12cbe..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/widget.md +++ /dev/null @@ -1,692 +0,0 @@ -<!-- contributed by Dietrich Ayala [dietrich@mozilla.com] --> -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `widget` module provides your add-on with a simple user interface that is -consistent with other add-ons and blends in well with Firefox. - -## Introduction ## - -"Widgets" are small pieces of content that live in the Firefox 4 -[add-on bar](https://developer.mozilla.org/en/The_add-on_bar). -They can be simple icons or complex web pages. You can attach -[panels](packages/addon-kit/docs/panel.html) to them that open when they're -clicked, or you can define a custom click handler to perform some other action, -like opening a web page in a tab. - -There are a few advantages to using widgets over an ad hoc user interface. -First, your users will be accustomed to interacting with add-ons via widgets and -the add-on bar. Second, it allows Firefox to treat your interface as a -first-class citizen. For example, in the future Firefox may allow the user to -drag widgets from the add-on bar to other toolbars. By exposing your interface -as a widget, your add-on would automatically inherit such functionality. - -## Creation and Content ## - -Widgets can contain images or arbitrary web content. You can include this -content inline as a string by using the `content` property, or point to content -using a URL with the `contentURL` property. - -For example, this widget contains an image, so it looks like a simple icon: - - require("widget").Widget({ - id: "mozilla-icon", - label: "My Mozilla Widget", - contentURL: "http://www.mozilla.org/favicon.ico" - }); - -Upon creation, the widget is automatically added to the add-on bar. -You can set the width of a widget, but the height is fixed so as to fit in the -add-on bar. If the content is an image, it is automatically scaled to be 16x16 -pixels. - -This widget contains an entire web page: - - require("widget").Widget({ - id: "hello-display", - label: "My Hello Widget", - content: "Hello!", - width: 50 - }); - -Widgets are quite small by default, so this example used the `width` property to -grow it in order to show all the text. - -As with many SDK APIs, communication with the content inside your widgets is -handled by [content scripts](dev-guide/addon-development/web-content.html). -So, for example, to be notified when your widget's content has loaded, you can -make a small script that calls back to the widget when it finishes loading. - -## Attaching Panels to Widgets ## - -You can supply a [panel](packages/addon-kit/docs/panel.html) to the widget's -constructor: if you do this, the panel is automatically displayed when the -user clicks the widget. - -<!-- The icon the widget displays, shown in the screenshot, is taken from the -Circular icon set, http://prothemedesign.com/circular-icons/ which is made -available under the Creative Commons Attribution 2.5 Generic License: -http://creativecommons.org/licenses/by/2.5/ --> - -<img class="image-right" src="static-files/media/screenshots/widget-panel-clock.png" -alt="Panel attached to a widget"> - - data = require("self").data - - var clockPanel = require("panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") - }); - - require("widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png"), - panel: clockPanel - }); - -Note that this is, at the moment, the only way you can attach a panel to a widget. - -You must supply the panel in the widget's constructor for it to work. If you -assign the panel to the widget after construction, the panel can still be shown -but will not be anchored to the widget: - - data = require("self").data - - var clockPanel = require("panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") - }); - - widget = require("widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png") - }); - - widget.panel = clockPanel; - - // Will not be anchored - widget.panel.show(); - -Also, if you try to call `panel.show()` inside your widget's `click` event -listener, the panel will not be anchored: - - data = require("self").data - - var clockPanel = require("panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") - }); - - require("widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png"), - panel: clockPanel, - onClick: function() { - // Will not be anchored - this.panel.show(); - } - }); - -See [bug 638142](https://bugzilla.mozilla.org/show_bug.cgi?id=638142). - -## Examples ## - -For conciseness, these examples create their content scripts as strings and use -the `contentScript` property. In your own add-ons, you will probably want to -create your content scripts in separate files and pass their URLs using the -`contentScriptFile` property. See -[Working with Content Scripts](dev-guide/addon-development/web-content.html) for more -information. - - var widgets = require("widget"); - - // A basic click-able image widget. - widgets.Widget({ - id: "google-link", - label: "Widget with an image and a click handler", - contentURL: "http://www.google.com/favicon.ico", - onClick: function() { - require("tabs").activeTab.url = "http://www.google.com/"; - } - }); -<br> - - // A widget that changes display on mouseover. - widgets.Widget({ - id: "mouseover-effect", - label: "Widget with changing image on mouseover", - contentURL: "http://www.yahoo.com/favicon.ico", - onMouseover: function() { - this.contentURL = "http://www.bing.com/favicon.ico"; - }, - onMouseout: function() { - this.contentURL = "http://www.yahoo.com/favicon.ico"; - } - }); -<br> - - // A widget that updates content on a timer. - widgets.Widget({ - id: "auto-update-widget", - label: "Widget that updates content on a timer", - content: "0", - contentScript: 'setTimeout(function() {' + - ' document.body.innerHTML++;' + - '}, 2000)', - contentScriptWhen: "ready" - }); -<br> - - // A widget that loads a random Flickr photo every 5 minutes. - widgets.Widget({ - id: "random-flickr", - label: "Random Flickr Photo Widget", - contentURL: "http://www.flickr.com/explore/", - contentScriptWhen: "ready", - contentScript: 'postMessage(document.querySelector(".pc_img").src);' + - 'setTimeout(function() {' + - ' document.location = "http://www.flickr.com/explore/";' + - '}, 5 * 60 * 1000);', - onMessage: function(imgSrc) { - this.contentURL = imgSrc; - }, - onClick: function() { - require("tabs").activeTab.url = this.contentURL; - } - }); -<br> - - // A widget created with a specified width, that grows. - let myWidget = widgets.Widget({ - id: "widget-effect", - label: "Wide widget that grows wider on a timer", - content: "I'm getting longer.", - width: 50, - }); - require("timers").setInterval(function() { - myWidget.width += 10; - }, 1000); -<br> - - // A widget communicating bi-directionally with a content script. - let widget = widgets.Widget({ - id: "message-test", - label: "Bi-directional communication!", - content: "<foo>bar</foo>", - contentScriptWhen: "ready", - contentScript: 'on("message", function(message) {' + - ' alert("Got message: " + message);' + - '});' + - 'postMessage("ready");', - onMessage: function(message) { - if (message == "ready") - widget.postMessage("me too"); - } - }); - -<api-name="Widget"> -@class -Represents a widget object. - -<api name="Widget"> -@constructor {options} - Creates a new widget. The widget is immediately added to the add-on bar. - -@param options {object} - An object with the following keys: - - @prop label {string} - A required string description of the widget used for accessibility, - title bars, and error reporting. - - @prop id {string} - Mandatory string used to identify your widget in order to save its - location when the user moves it in the browser. - This string has to be unique and must not be changed over time. - - @prop [content] {string} - An optional string value containing the displayed content of the widget. - It may contain HTML. Widgets must have either the `content` property or the - `contentURL` property set. - - If the content is an image, it is automatically scaled to be 16x16 pixels. - - @prop [contentURL] {string} - An optional string URL to content to load into the widget. This can be - [local content](dev-guide/addon-development/web-content.html) or remote - content, an image or web content. Widgets must have either the `content` - property or the `contentURL` property set. - - If the content is an image, it is automatically scaled to be 16x16 pixels. - - @prop [panel] {Panel} - An optional [panel](packages/addon-kit/docs/panel.html) to open when the - user clicks on the widget. Note: If you also register a "click" listener, - it will be called instead of the panel being opened. However, you can show - the panel from the listener by calling `this.panel.show()`. - - @prop [width] {integer} - Optional width in pixels of the widget. If not given, a default width is - used. - - @prop [onClick] {function} - Include this to listen to the widget's `click` event. - - @prop [onMessage] {function} - Include this to listen to the widget's `message` event. - - @prop [onMouseover] {function} - Include this to listen to the widget's `mouseover` event. - - @prop [onMouseout] {function} - Include this to listen to the widget's `mouseout` event. - - @prop [onAttach] {function} - Include this to listen to the widget's `attach` event. - - @prop [tooltip] {string} - Optional text to show when the user's mouse hovers over the widget. If not - given, the `label` is used. - - @prop [allow] {object} - An optional object describing permissions for the content. It should - contain a single key named `script` whose value is a boolean that indicates - whether or not to execute script in the content. `script` defaults to true. - - @prop [contentScriptFile] {string,array} - A local file URL or an array of local file URLs of content scripts to load. - Content scripts specified by this property are loaded *before* those - specified by the `contentScript` property. - - @prop [contentScript] {string,array} - A string or an array of strings containing the texts of content scripts to - load. Content scripts specified by this property are loaded *after* those - specified by the `contentScriptFile` property. - - @prop [contentScriptWhen="end"] {string} - When to load the content scripts. This may take one of the following - values: - - * "start": load content scripts immediately after the document - element for the widget is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the widget has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - - This property is optional and defaults to "end". - -</api> - -<api name="destroy"> -@method - Removes the widget from the add-on bar. -</api> - -<api name="postMessage"> -@method - Sends a message to the widget's content scripts. -@param data {value} - The message to send. - The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="on"> -@method - Registers an event listener with the widget. -@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 an event listener from the widget. -@param type {string} - The type of event for which `listener` was registered. -@param listener {function} - The listener function that was registered. -</api> - -<api name="getView"> -@method - Retrieve a `WidgetView` instance of this widget relative to a browser window. -@param window {BrowserWindow} - The [BrowserWindow](packages/addon-kit/docs/windows.html) instance to match. -@returns {WidgetView} - A `WidgetView` instance associated with the browser window. Any changes - subsequently applied to this object will only be applied to the widget - attached to that window. -</api> - -<api name="label"> -@property {string} - The widget's label. Read-only. -</api> - -<api name="content"> -@property {string} - A string containing the widget's content. It can contain HTML. Setting it - updates the widget's appearance immediately. However, if the widget was - created using `contentURL`, then this property is meaningless, and setting it - has no effect. -</api> - -<api name="contentURL"> -@property {string} - The URL of content to load into the widget. This can be - [local content](dev-guide/addon-development/web-content.html) or remote - content, an image or web content. Setting it updates the widget's appearance - immediately. However, if the widget was created using `content`, then this - property is meaningless, and setting it has no effect. -</api> - -<api name="panel"> -@property {Panel} - A [panel](packages/addon-kit/docs/panel.html) to open when the user clicks on - the widget. -</api> - -<api name="width"> -@property {number} - The widget's width in pixels. Setting it updates the widget's appearance - immediately. -</api> - -<api name="tooltip"> -@property {string} - The text of the tooltip that appears when the user hovers over the widget. -</api> - -<api name="allow"> -@property {object} - A object describing permissions for the content. It contains a single key - named `script` whose value is a boolean that indicates whether or not to - execute script in the content. -</api> - -<api name="contentScriptFile"> -@property {string,array} - A local file URL or an array of local file URLs of content scripts to load. -</api> - -<api name="contentScript"> -@property {string,array} - A string or an array of strings containing the texts of content scripts to - load. -</api> - -<api name="contentScriptWhen"> -@property {string} - When to load the content scripts. This may have one of the following - values: - - * "start": load content scripts immediately after the document - element for the widget is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the widget has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - -</api> - -<api name="port"> -@property {EventEmitter} -[EventEmitter](packages/api-utils/docs/events.html) object that allows you to: - -* send events to the content script using the `port.emit` function -* receive events from the content script using the `port.on` function - -See the guide to -<a href="dev-guide/addon-development/content-scripts/using-port.html"> -communicating using <code>port</code></a> for details. -</api> - -<api name="attach"> -@event -This event is emitted when a new `WidgetView` object is created using the -`getView()` function. -</api> - -<api name="click"> -@event -This event is emitted when the widget is clicked. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this widget. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the widget's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="mouseover"> -@event -This event is emitted when the user moves the mouse over the widget. -</api> - -<api name="mouseout"> -@event -This event is emitted when the user moves the mouse away from the widget. -</api> - -</api> - - -<api-name="WidgetView"> -@class -Represents a widget instance specific to one browser window. - -Anything you do to an instance of this object will only be applied to the -instance attached to its browser window: widget instances attached to other -browser windows will be unaffected. - -By contrast, any changes you make to an instance of the normal `Widget` class -will be applied across all browser windows. - -This class has all the same methods, attributes and events as the `Widget` -class except for the `getView` method and the `attach` event. - -In this example `WidgetView` is used to display different content for -`http` and `https` schemes: - - // A widget that update its content specifically to each window. - let tabs = require("tabs"); - let windows = require("windows").browserWindows; - let widget = widgets.Widget({ - id: "window-specific-test", - label: "Widget with content specific to each window", - content: " ", - width: 50 - }); - // Observe tab switch or document changes in each existing tab: - function updateWidgetState(tab) { - let view = widget.getView(tab.window); - if (!view) return; - // Update widget displayed text: - view.content = tab.url.match(/^https/) ? "Secured" : "Unsafe"; - } - tabs.on('ready', updateWidgetState); - tabs.on('activate', updateWidgetState); - -<api name="destroy"> -@method - Removes the widget view from the add-on bar. -</api> - -<api name="postMessage"> -@method - Sends a message to the widget view's content scripts. -@param data {value} - The message to send. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="on"> -@method - Registers an event listener with the widget view. -@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 an event listener from the widget view. -@param type {string} - The type of event for which `listener` was registered. -@param listener {function} - The listener function that was registered. -</api> - -<api name="label"> -@property {string} - The widget view's label. Read-only. -</api> - -<api name="content"> -@property {string} - A string containing the widget view's content. It can contain HTML. - Setting it updates the widget view's appearance immediately. However, - if the widget view was created using `contentURL`, then this property - is meaningless, and setting it has no effect. -</api> - -<api name="contentURL"> -@property {string} - The URL of content to load into the widget view. This can be - [local content](dev-guide/addon-development/web-content.html) or remote - content, an image or web content. Setting it updates the widget view's - appearance immediately. However, if the widget view was created using - `content`, then this property is meaningless, and setting it has no effect. -</api> - -<api name="panel"> -@property {Panel} - A [panel](packages/addon-kit/docs/panel.html) to open when the user clicks on - the widget view. -</api> - -<api name="width"> -@property {number} - The widget view's width in pixels. Setting it updates the widget view's - appearance immediately. -</api> - -<api name="tooltip"> -@property {string} - The text of the tooltip that appears when the user hovers over the widget - view. -</api> - -<api name="allow"> -@property {object} - A object describing permissions for the content. It contains a single key - named `script` whose value is a boolean that indicates whether or not to - execute script in the content. -</api> - -<api name="contentScriptFile"> -@property {string,array} - A local file URL or an array of local file URLs of content scripts to load. -</api> - -<api name="contentScript"> -@property {string,array} - A string or an array of strings containing the texts of content scripts to - load. -</api> - -<api name="contentScriptWhen"> -@property {string} - When to load the content scripts. This may have one of the following - values: - - * "start": load content scripts immediately after the document - element for the widget view is inserted into the DOM, but before the DOM - content itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the widget view has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - -</api> - -<api name="port"> -@property {EventEmitter} -[EventEmitter](packages/api-utils/docs/events.html) object that allows you to: - -* send events to the content script using the `port.emit` function -* receive events from the content script using the `port.on` - -See the guide to -<a href="dev-guide/addon-development/content-scripts/using-port.html"> -communicating using <code>port</code></a> for details. -</api> - -<api name="detach"> -@event -The `detach` event is fired when the widget view is removed from its related -window. -This can occur if the window is closed, Firefox exits, or the add-on is -disabled. -</api> - -<api name="click"> -@event -This event is emitted when the widget view is clicked. -</api> - -<api name="message"> -@event -If you listen to this event you can receive message events from content -scripts associated with this widget view. When a content script posts a -message using `self.postMessage()`, the message is delivered to the add-on -code in the widget view's `message` event. - -@argument {value} -Listeners are passed a single argument which is the message posted -from the content script. The message can be any -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="mouseover"> -@event -This event is emitted when the user moves the mouse over the widget view. -</api> - -<api name="mouseout"> -@event -This event is emitted when the user moves the mouse away from the widget view. -</api> - -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/docs/windows.md b/tools/addon-sdk-1.4/packages/addon-kit/docs/windows.md deleted file mode 100644 index a5bed95..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/docs/windows.md +++ /dev/null @@ -1,187 +0,0 @@ -<!-- contributed by Felipe Gomes [felipc@gmail.com] --> - - -The `windows` module provides easy access to browser windows, their -tabs, and open/close related functions and events. - -This module currently only supports browser windows and does not provide -access to non-browser windows such as the Bookmarks Library, preferences -or other non-browser windows created via add-ons. - -<api name="browserWindows"> -@property {List} -An object that contains various properties and methods to access -functionality from browser windows, such as opening new windows, accessing -their tabs or switching the current active window. - -`browserWindows` provides access to all the currently open browser windows: - - var windows = require("windows"); - for each (var window in windows.browserWindows) { - console.log(window.title); - } - - console.log(windows.browserWindows.length); - -Object emits all the events listed under "Events" section. - -####Examples#### - - var windows = require("windows").browserWindows; - - // add a listener to the 'open' event - windows.on('open', function(window) { - myOpenWindows.push(window); - }); - - // add a listener to the 'close' event - windows.on('close', function(window) { - console.log("A window was closed."); - }); - -<api name="activeWindow"> -@property {BrowserWindow} - -The currently active window. This property is read-only. - -**Example** - - // get - var windows = require("windows"); - console.log("title of active window is " + - windows.browserWindows.activeWindow.title); - - anotherWindow.activate(); - // set - windows.activeWindow == anotherWindow // true -</api> - -</api> - -<api name="open"> -@function -Open a new window. - - var windows = require("windows").browserWindows; - - // Open a new window. - windows.open("http://www.example.com"); - - // Open a new window and set a listener for "open" event. - windows.open({ - url: "http://www.example.com", - onOpen: function(window) { - // do stuff like listen for content - // loading. - } - }); - -Returns the window that was opened: - - var widgets = require("widget"); - var windows = require("windows").browserWindows; - - var example = windows.open("http://www.example.com"); - - var widget = widgets.Widget({ - id: "close-window", - label: "Close window", - contentURL: "http://www.mozilla.org/favicon.ico", - onClick: function() { - example.close(); - } - }); - -@param options {object} -An object containing configurable options for how this window will be opened, -as well as a callback for being notified when the window has fully opened. - -If the only option being used is `url`, then a bare string URL can be passed to -`open` instead of specifying it as a property of the `options` object. - -@prop url {string} -String URL to be opened in the new window. -This is a required property. - -@prop [onOpen] {function} -A callback function that is called when the window has opened. This does not -mean that the URL content has loaded, only that the window itself is fully -functional and its properties can be accessed. This is an optional property. - -@prop [onClose] {function} -A callback function that is called when the window will be called. -This is an optional property. - -@returns {BrowserWindow} -</api> - -<api name="BrowserWindow"> -@class -A `BrowserWindow` instance represents a single open window. They can be -retrieved from the `browserWindows` property exported by this module. - - var windows = require("windows").browserWindows; - - //Print how many tabs the current window has - console.log("The active window has " + - windows.activeWindow.tabs.length + - " tabs."); - - // Print the title of all browser windows - for each (var window in windows) { - console.log(window.title); - } - - // close the active window - windows.activeWindow.close(); - - windows.activeWindow.close(function() { - console.log("The active window was closed"); - }); - -<api name="title"> -@property {string} -The current title of the window. Usually the title of the active tab, -plus an app identifier. -This property is read-only. -</api> - -<api name="tabs"> -@property {TabList} -A live list of tabs in this window. This object has the same interface as the -[`tabs` API](packages/addon-kit/docs/tabs.html), except it contains only the -tabs in this window, not all tabs in all windows. This property is read-only. -</api> - -<api name="activate"> -@method -Makes window active, which will focus that window and bring it to the -foreground. -</api> - -<api name="close"> -@method -Close the window. - -@param [callback] {function} -A function to be called when the window finishes its closing process. -This is an optional argument. -</api> - -</api> - -<api name="open"> -@event -Event emitted when a new window is open. -This does not mean that the content has loaded, only that the browser window -itself is fully visible to the user. -@argument {Window} -Listeners are passed the `window` object that triggered the event. -</api> - -<api name="close"> -@event -Event emitted when a window is closed. -@argument {Window} -Listeners are passed the `window` object that triggered the event. -</api> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/clipboard.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/clipboard.js deleted file mode 100644 index 24f4641..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/clipboard.js +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Paul O’Shannessy <paul@oshannessy.com> (Original Author) - * Dietrich Ayala <dietrich@mozilla.com> - * Myk Melez <myk@mozilla.org> - * Erik Vold <erikvvold@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -const errors = require("api-utils/errors"); -const apiUtils = require("api-utils/api-utils"); - -/* -While these data flavors resemble Internet media types, they do -no directly map to them. -*/ -const kAllowableFlavors = [ - "text/unicode", - "text/html" - /* CURRENTLY UNSUPPORTED FLAVORS - "text/plain", - "image/png", - "image/jpg", - "image/gif" - "text/x-moz-text-internal", - "AOLMAIL", - "application/x-moz-file", - "text/x-moz-url", - "text/x-moz-url-data", - "text/x-moz-url-desc", - "text/x-moz-url-priv", - "application/x-moz-nativeimage", - "application/x-moz-nativehtml", - "application/x-moz-file-promise-url", - "application/x-moz-file-promise-dest-filename", - "application/x-moz-file-promise", - "application/x-moz-file-promise-dir" - */ -]; - -/* -Aliases for common flavors. Not all flavors will -get an alias. New aliases must be approved by a -Jetpack API druid. -*/ -const kFlavorMap = [ - { short: "text", long: "text/unicode" }, - { short: "html", long: "text/html" } - // Images are currently unsupported. - //{ short: "image", long: "image/png" }, -]; - -let clipboardService = Cc["@mozilla.org/widget/clipboard;1"]. - getService(Ci.nsIClipboard); - -let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"]. - getService(Ci.nsIClipboardHelper); - - -exports.set = function(aData, aDataType) { - let options = { - data: aData, - datatype: aDataType || "text" - }; - options = apiUtils.validateOptions(options, { - data: { - is: ["string"] - }, - datatype: { - is: ["string"] - } - }); - - var flavor = fromJetpackFlavor(options.datatype); - - if (!flavor) - throw new Error("Invalid flavor"); - - // Additional checks for using the simple case - if (flavor == "text/unicode") { - clipboardHelper.copyString(options.data); - return true; - } - - // Below are the more complex cases where we actually have to work with a - // nsITransferable object - var xferable = Cc["@mozilla.org/widget/transferable;1"]. - createInstance(Ci.nsITransferable); - if (!xferable) - throw new Error("Couldn't set the clipboard due to an internal error " + - "(couldn't create a Transferable object)."); - - switch (flavor) { - case "text/html": - // add text/html flavor - let (str = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString)) - { - str.data = options.data; - xferable.addDataFlavor(flavor); - xferable.setTransferData(flavor, str, str.data.length * 2); - } - - // add a text/unicode flavor (html converted to plain text) - let (str = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString), - converter = Cc["@mozilla.org/feed-textconstruct;1"]. - createInstance(Ci.nsIFeedTextConstruct)) - { - converter.type = "html"; - converter.text = options.data; - str.data = converter.plainText(); - xferable.addDataFlavor("text/unicode"); - xferable.setTransferData("text/unicode", str, str.data.length * 2); - } - break; - // TODO: images! - default: - throw new Error("Unable to handle the flavor " + flavor + "."); - } - - // TODO: Not sure if this will ever actually throw. -zpao - try { - clipboardService.setData( - xferable, - null, - clipboardService.kGlobalClipboard - ); - } catch (e) { - throw new Error("Couldn't set clipboard data due to an internal error: " + e); - } - return true; -}; - - -exports.get = function(aDataType) { - let options = { - datatype: aDataType || "text" - }; - options = apiUtils.validateOptions(options, { - datatype: { - is: ["string"] - } - }); - - var xferable = Cc["@mozilla.org/widget/transferable;1"]. - createInstance(Ci.nsITransferable); - if (!xferable) - throw new Error("Couldn't set the clipboard due to an internal error " + - "(couldn't create a Transferable object)."); - - var flavor = fromJetpackFlavor(options.datatype); - - // Ensure that the user hasn't requested a flavor that we don't support. - if (!flavor) - throw new Error("Getting the clipboard with the flavor '" + flavor + - "' is > not supported."); - - // TODO: Check for matching flavor first? Probably not worth it. - - xferable.addDataFlavor(flavor); - - // Get the data into our transferable. - clipboardService.getData( - xferable, - clipboardService.kGlobalClipboard - ); - - var data = {}; - var dataLen = {}; - try { - xferable.getTransferData(flavor, data, dataLen); - } catch (e) { - // Clipboard doesn't contain data in flavor, return null. - return null; - } - - // There's no data available, return. - if (data.value === null) - return null; - - // TODO: Add flavors here as we support more in kAllowableFlavors. - switch (flavor) { - case "text/unicode": - case "text/html": - data = data.value.QueryInterface(Ci.nsISupportsString).data; - break; - default: - data = null; - } - - return data; -}; - -exports.__defineGetter__("currentFlavors", function() { - // Loop over kAllowableFlavors, calling hasDataMatchingFlavors for each. - // This doesn't seem like the most efficient way, but we can't get - // confirmation for specific flavors any other way. This is supposed to be - // an inexpensive call, so performance shouldn't be impacted (much). - var currentFlavors = []; - for each (var flavor in kAllowableFlavors) { - var matches = clipboardService.hasDataMatchingFlavors( - [flavor], - 1, - clipboardService.kGlobalClipboard - ); - if (matches) - currentFlavors.push(toJetpackFlavor(flavor)); - } - return currentFlavors; -}); - -// SUPPORT FUNCTIONS //////////////////////////////////////////////////////// - -function toJetpackFlavor(aFlavor) { - for each (let flavorMap in kFlavorMap) - if (flavorMap.long == aFlavor) - return flavorMap.short; - // Return null in the case where we don't match - return null; -} - -function fromJetpackFlavor(aJetpackFlavor) { - // TODO: Handle proper flavors better - for each (let flavorMap in kFlavorMap) - if (flavorMap.short == aJetpackFlavor || flavorMap.long == aJetpackFlavor) - return flavorMap.long; - // Return null in the case where we don't match. - return null; -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/context-menu.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/context-menu.js deleted file mode 100644 index c9f00f9..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/context-menu.js +++ /dev/null @@ -1,1526 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * Matteo Ferretti <zer0@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Ci} = require("chrome"); - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The context-menu module currently supports only Firefox. In the future ", - "we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information." - ].join("")); -} - -const apiUtils = require("api-utils/api-utils"); -const collection = require("api-utils/collection"); -const { Worker } = require("api-utils/content"); -const url = require("api-utils/url"); -const { MatchPattern } = require("api-utils/match-pattern"); -const { EventEmitterTrait: EventEmitter } = require("api-utils/events"); -const observerServ = require("api-utils/observer-service"); -const jpSelf = require("self"); -const winUtils = require("api-utils/window-utils"); -const { Trait } = require("api-utils/light-traits"); -const { Cortex } = require("api-utils/cortex"); -const timer = require("timer"); - -// All user items we add have this class name. -const ITEM_CLASS = "jetpack-context-menu-item"; - -// Items in the top-level context menu also have this class. -const TOPLEVEL_ITEM_CLASS = "jetpack-context-menu-item-toplevel"; - -// Items in the overflow submenu also have this class. -const OVERFLOW_ITEM_CLASS = "jetpack-context-menu-item-overflow"; - -// The ID of the menu separator that separates standard context menu items from -// our user items. -const SEPARATOR_ID = "jetpack-context-menu-separator"; - -// If more than this number of items are added to the context menu, all items -// overflow into a "Jetpack" submenu. -const OVERFLOW_THRESH_DEFAULT = 10; -const OVERFLOW_THRESH_PREF = - "extensions.addon-sdk.context-menu.overflowThreshold"; - -// The label of the overflow sub-xul:menu. -// -// TODO: Localize this. -const OVERFLOW_MENU_LABEL = "Add-ons"; - -// The ID of the overflow sub-xul:menu. -const OVERFLOW_MENU_ID = "jetpack-content-menu-overflow-menu"; - -// The ID of the overflow submenu's xul:menupopup. -const OVERFLOW_POPUP_ID = "jetpack-content-menu-overflow-popup"; - -// These are used by PageContext.isCurrent below. If the popupNode or any of -// its ancestors is one of these, Firefox uses a tailored context menu, and so -// the page context doesn't apply. -const NON_PAGE_CONTEXT_ELTS = [ - Ci.nsIDOMHTMLAnchorElement, - Ci.nsIDOMHTMLAppletElement, - Ci.nsIDOMHTMLAreaElement, - Ci.nsIDOMHTMLButtonElement, - Ci.nsIDOMHTMLCanvasElement, - Ci.nsIDOMHTMLEmbedElement, - Ci.nsIDOMHTMLImageElement, - Ci.nsIDOMHTMLInputElement, - Ci.nsIDOMHTMLMapElement, - Ci.nsIDOMHTMLMediaElement, - Ci.nsIDOMHTMLMenuElement, - Ci.nsIDOMHTMLObjectElement, - Ci.nsIDOMHTMLOptionElement, - Ci.nsIDOMHTMLSelectElement, - Ci.nsIDOMHTMLTextAreaElement, -]; - -// This is used to access private properties of Item and Menu instances. -const PRIVATE_PROPS_KEY = { - valueOf: function valueOf() "private properties key" -}; - -// Used as an internal ID for items and as part of a public ID for item DOM -// elements. Careful: This number is not necessarily unique to any one instance -// of the module. For each module instance, when the first item is created this -// number will be 0, when the second is created it will be 1, and so on. -let nextItemID = 0; - -// The number of items that haven't finished initializing yet. See -// AIT__finishActiveItemInit(). -let numItemsWithUnfinishedInit = 0; - -exports.Item = Item; -exports.Menu = Menu; -exports.Separator = Separator; - - -// A word about traits and privates. `this` inside of traits methods is an -// object private to the implementation. It should never be publicly leaked. -// We use Cortex in the exported menu item constructors to create public -// reflections of the private objects that hide private properties -- those -// prefixed with an underscore. Public reflections are attached to the private -// objects via the `_public` property. -// -// All item objects passed into the implementation by the client will be public -// reflections, not private objects. Likewise, all item objects passed out of -// the implementation to the client must be public, not private. Mixing up -// public and private is bad and easy to do, so not only are private objects -// restricted to the implementation, but as much as possible we try to restrict -// them to the Item, Menu, and Separator traits and constructors. Everybody -// else in the implementation should expect to be passed public reflections, and -// they must specifically request private objects via privateItem(). - -// Item, Menu, and Separator are composed of this trait. -const ItemBaseTrait = Trait({ - - _initBase: function IBT__initBase(opts, optRules, optsToNotSet) { - this._optRules = optRules; - for (let optName in optRules) - if (optsToNotSet.indexOf(optName) < 0) - this[optName] = opts[optName]; - optsToNotSet.forEach(function (opt) validateOpt(opts[opt], optRules[opt])); - this._isInited = true; - - this._id = nextItemID++; - this._parentMenu = null; - - // This makes the private properties accessible to anyone with access to - // PRIVATE_PROPS_KEY. Barring loader tricks, only this file has has access - // to it, so only this file has access to the private properties. - const self = this; - this.valueOf = function IBT_valueOf(key) { - return key === PRIVATE_PROPS_KEY ? self : self._public; - }; - }, - - destroy: function IBT_destroy() { - if (this._wasDestroyed) - return; - if (this.parentMenu) - this.parentMenu.removeItem(this._public); - else if (!(this instanceof Separator) && this._hasFinishedInit) - browserManager.removeTopLevelItem(this._public); - browserManager.unregisterItem(this._public); - this._wasDestroyed = true; - }, - - get parentMenu() { - return this._parentMenu; - }, - - set parentMenu(val) { - throw new Error("The 'parentMenu' property is not intended to be set. " + - "Use menu.addItem(item) instead."); - }, - - set _isTopLevel(val) { - if (val) - this._workerReg = new WorkerRegistry(this._public); - else { - this._workerReg.destroy(); - delete this._workerReg; - } - }, - - get _topLevelItem() { - let topLevelItem = this._public; - let parentMenu = this.parentMenu; - while (parentMenu) { - topLevelItem = parentMenu; - parentMenu = parentMenu.parentMenu; - } - return topLevelItem; - } -}); - -// Item and Menu are composed of this trait. -const ActiveItemTrait = Trait.compose(ItemBaseTrait, EventEmitter, Trait({ - - _initActiveItem: function AIT__initActiveItem(opts, optRules, optsToNotSet) { - this._initBase(opts, optRules, - optsToNotSet.concat(["onMessage", "context"])); - - if ("onMessage" in opts) - this.on("message", opts.onMessage); - - // When a URL context is removed (by calling context.remove(urlContext)), we - // may need to create workers for windows containing pages that the item now - // matches. Likewise, when a URL context is added, we need to destroy - // workers for windows containing pages that the item now does not match. - // - // collection doesn't provide a way to listen for removals. utils/registry - // does, but it doesn't allow its elements to be enumerated. So as a hack, - // use a collection for item.context and replace its add and remove methods. - collection.addCollectionProperty(this, "context"); - if (opts.context) - this.context.add(opts.context); - - const self = this; - - let add = this.context.add; - this.context.add = function itemContextAdd() { - let args = Array.slice(arguments); - add.apply(self.context, args); - if (self._workerReg && args.some(function (a) a instanceof URLContext)) - self._workerReg.destroyUnneededWorkers(); - }; - - let remove = this.context.remove; - this.context.remove = function itemContextRemove() { - let args = Array.slice(arguments); - remove.apply(self.context, args); - if (self._workerReg && args.some(function (a) a instanceof URLContext)) - self._workerReg.createNeededWorkers(); - }; - }, - - // Workers are only created for top-level menu items. When a top-level item - // is later added to a Menu, its workers are destroyed. Well, all items start - // out as top-level because there is, unfortunately, no contextMenu.add(). So - // when an item is created and immediately added to a Menu, workers for it are - // needlessly created and destroyed. The point of this timeout is to avoid - // that. Items that are created and added to Menus in the same turn of the - // event loop won't have workers created for them. - _finishActiveItemInit: function AIT__finishActiveItemInit() { - numItemsWithUnfinishedInit++; - const self = this; - timer.setTimeout(function AIT__finishActiveItemInitTimeout() { - if (!self.parentMenu && !self._wasDestroyed) - browserManager.addTopLevelItem(self._public); - self._hasFinishedInit = true; - numItemsWithUnfinishedInit--; - }, 0); - }, - - get label() { - return this._label; - }, - - set label(val) { - this._label = validateOpt(val, this._optRules.label); - if (this._isInited) - browserManager.setItemLabel(this, this._label); - return this._label; - }, - - get image() { - return this._image; - }, - - set image(val) { - this._image = validateOpt(val, this._optRules.image); - if (this._isInited) - browserManager.setItemImage(this, this._image); - return this._image; - }, - - get contentScript() { - return this._contentScript; - }, - - set contentScript(val) { - this._contentScript = validateOpt(val, this._optRules.contentScript); - return this._contentScript; - }, - - get contentScriptFile() { - return this._contentScriptFile; - }, - - set contentScriptFile(val) { - this._contentScriptFile = - validateOpt(val, this._optRules.contentScriptFile); - return this._contentScriptFile; - } -})); - -// Item is composed of this trait. -const ItemTrait = Trait.compose(ActiveItemTrait, Trait({ - - _initItem: function IT__initItem(opts, optRules) { - this._initActiveItem(opts, optRules, []); - }, - - get data() { - return this._data; - }, - - set data(val) { - this._data = validateOpt(val, this._optRules.data); - if (this._isInited) - browserManager.setItemData(this, this._data); - return this._data; - }, - - toString: function IT_toString() { - return '[object Item "' + this.label + '"]'; - } -})); - -// The exported Item constructor. -function Item(options) { - let optRules = optionsRules(); - optRules.data = { - map: function (v) v.toString(), - is: ["string", "undefined"] - }; - - let item = ItemTrait.create(Item.prototype); - item._initItem(options, optRules); - - item._public = Cortex(item); - browserManager.registerItem(item._public); - item._finishActiveItemInit(); - - return item._public; -} - -// Menu is composed of this trait. -const MenuTrait = Trait.compose( - ActiveItemTrait.resolve({ destroy: "_destroyThisItem" }), - Trait({ - - _initMenu: function MT__initMenu(opts, optRules, optsToNotSet) { - this._items = []; - this._initActiveItem(opts, optRules, optsToNotSet); - }, - - destroy: function MT_destroy() { - while (this.items.length) - this.items[0].destroy(); - this._destroyThisItem(); - }, - - get items() { - return this._items; - }, - - set items(val) { - let newItems = validateOpt(val, this._optRules.items); - while (this.items.length) - this.items[0].destroy(); - newItems.forEach(function (i) this.addItem(i), this); - return newItems; - }, - - addItem: function MT_addItem(item) { - // First, remove the item from its current parent. - let privates = privateItem(item); - if (item.parentMenu) - item.parentMenu.removeItem(item); - else if (!(item instanceof Separator) && privates._hasFinishedInit) - browserManager.removeTopLevelItem(item); - - // Now add the item to this menu. - this._items.push(item); - privates._parentMenu = this._public; - browserManager.addItemToMenu(item, this._public); - }, - - removeItem: function MT_removeItem(item) { - let idx = this._items.indexOf(item); - if (idx < 0) - return; - this._items.splice(idx, 1); - privateItem(item)._parentMenu = null; - browserManager.removeItemFromMenu(item, this._public); - }, - - toString: function MT_toString() { - return '[object Menu "' + this.label + '"]'; - } -})); - -// The exported Menu constructor. -function Menu(options) { - let optRules = optionsRules(); - optRules.items = { - is: ["array"], - ok: function (v) { - return v.every(function (item) { - return (item instanceof Item) || - (item instanceof Menu) || - (item instanceof Separator); - }); - }, - msg: "items must be an array, and each element in the array must be an " + - "Item, Menu, or Separator." - }; - - let menu = MenuTrait.create(Menu.prototype); - - // We can't rely on _initBase to set the `items` property, because the menu - // needs to be registered with and added to the browserManager before any - // child items are added to it. - menu._initMenu(options, optRules, ["items"]); - - menu._public = Cortex(menu); - browserManager.registerItem(menu._public); - menu.items = options.items; - menu._finishActiveItemInit(); - - return menu._public; -} - -// The exported Separator constructor. -function Separator() { - let sep = ItemBaseTrait.create(Separator.prototype); - sep._initBase({}, {}, []); - - sep._public = Cortex(sep); - browserManager.registerItem(sep._public); - sep._hasFinishedInit = true; - return sep._public; -} - - -function Context() {} - -function PageContext() { - this.isCurrent = function PageContext_isCurrent(popupNode) { - let win = popupNode.ownerDocument.defaultView; - if (win && !win.getSelection().isCollapsed) - return false; - - let cursor = popupNode; - while (cursor && !(cursor instanceof Ci.nsIDOMHTMLHtmlElement)) { - if (NON_PAGE_CONTEXT_ELTS.some(function (iface) cursor instanceof iface)) - return false; - cursor = cursor.parentNode; - } - return true; - }; -} - -PageContext.prototype = new Context(); - -function SelectorContext(selector) { - let opts = apiUtils.validateOptions({ selector: selector }, { - selector: { - is: ["string"], - msg: "selector must be a string." - } - }); - - this.adjustPopupNode = function SelectorContext_adjustPopupNode(node) { - return closestMatchingAncestor(node); - }; - - this.isCurrent = function SelectorContext_isCurrent(popupNode) { - return !!closestMatchingAncestor(popupNode); - }; - - // Returns node if it matches selector, or the closest ancestor of node that - // matches, or null if node and none of its ancestors matches. - function closestMatchingAncestor(node) { - let cursor = node; - while (cursor) { - if (cursor.mozMatchesSelector(selector)) - return cursor; - if (cursor instanceof Ci.nsIDOMHTMLHtmlElement) - break; - cursor = cursor.parentNode; - } - return null; - } -} - -SelectorContext.prototype = new Context(); - -function SelectionContext() { - this.isCurrent = function SelectionContext_isCurrent(popupNode) { - let win = popupNode.ownerDocument.defaultView; - if (!win) - return false; - - let hasSelection = !win.getSelection().isCollapsed; - if (!hasSelection) { - // window.getSelection doesn't return a selection for text selected in a - // form field (see bug 85686), so before returning false we want to check - // if the popupNode is a text field. - let { selectionStart, selectionEnd } = popupNode; - hasSelection = !isNaN(selectionStart) && - !isNaN(selectionEnd) && - selectionStart !== selectionEnd; - } - return hasSelection; - }; -} - -SelectionContext.prototype = new Context(); - -function URLContext(patterns) { - let opts = apiUtils.validateOptions({ patterns: patterns }, { - patterns: { - map: function (v) apiUtils.getTypeOf(v) === "array" ? v : [v], - ok: function (v) v.every(function (p) typeof(p) === "string"), - msg: "patterns must be a string or an array of strings." - } - }); - try { - patterns = opts.patterns.map(function (p) new MatchPattern(p)); - } - catch (err) { - console.error("Error creating URLContext match pattern:"); - throw err; - } - - const self = this; - - this.isCurrent = function URLContext_isCurrent(popupNode) { - return self.isCurrentForURL(popupNode.ownerDocument.URL); - }; - - this.isCurrentForURL = function URLContext_isCurrentForURL(url) { - return patterns.some(function (p) p.test(url)); - }; -} - -URLContext.prototype = new Context(); - -exports.PageContext = apiUtils.publicConstructor(PageContext); -exports.SelectorContext = apiUtils.publicConstructor(SelectorContext); -exports.SelectionContext = apiUtils.publicConstructor(SelectionContext); -exports.URLContext = apiUtils.publicConstructor(URLContext); - - -// Returns a version of opt validated against the given rule. -function validateOpt(opt, rule) { - return apiUtils.validateOptions({ opt: opt }, { opt: rule }).opt; -} - -// Returns rules for apiUtils.validateOptions() common to Item and Menu. -function optionsRules() { - return { - context: { - is: ["undefined", "object", "array"], - ok: function (v) { - if (!v) - return true; - let arr = apiUtils.getTypeOf(v) === "array" ? v : [v]; - return arr.every(function (o) o instanceof Context); - }, - msg: "The 'context' option must be a Context object or an array of " + - "Context objects." - }, - label: { - map: function (v) v.toString(), - is: ["string"], - ok: function (v) !!v, - msg: "The item must have a non-empty string label." - }, - image: { - map: function (v) v.toString(), - is: ["string", "undefined", "null"] - }, - contentScript: { - is: ["string", "array", "undefined"], - ok: function (v) { - return apiUtils.getTypeOf(v) !== "array" || - v.every(function (s) typeof(s) === "string"); - } - }, - contentScriptFile: { - is: ["string", "array", "undefined"], - ok: function (v) { - if (!v) - return true; - let arr = apiUtils.getTypeOf(v) === "array" ? v : [v]; - try { - return arr.every(function (s) { - return apiUtils.getTypeOf(s) === "string" && url.toFilename(s); - }); - } - catch (err) {} - return false; - }, - msg: "The 'contentScriptFile' option must be a local file URL or " + - "an array of local file URLs." - }, - onMessage: { - is: ["function", "undefined"] - } - }; -} - -// Does a binary search on elts, a NodeList, and returns the DOM element -// before which an item with targetLabel should be inserted. null is returned -// if the new item should be inserted at the end. -function insertionPoint(targetLabel, elts) { - let from = 0; - let to = elts.length - 1; - - while (from <= to) { - let i = Math.floor((from + to) / 2); - let comp = targetLabel.localeCompare(elts[i].getAttribute("label")); - if (comp < 0) - to = i - 1; - else if (comp > 0) - from = i + 1; - else - return elts[i]; - } - return elts[from] || null; -} - -// Builds an ID suitable for a DOM element from the given item ID. -// isInOverflowSubtree should be true if the returned element will be inserted -// into the DOM subtree rooted at the overflow menu. -function domEltIDFromItemID(itemID, isInOverflowSubtree) { - let suffix = isInOverflowSubtree ? "-overflow" : ""; - return jpSelf.id + "-context-menu-item-" + itemID + suffix; -} - -// Parses the item ID out of the given DOM element ID and returns it. If the -// element's ID is malformed or it indicates that the element was not created by -// the instance of the module calling this function, returns -1. -function itemIDFromDOMEltID(domEltID) { - let match = /^(.+?)-context-menu-item-([0-9]+)[-a-z]*$/.exec(domEltID); - return !match || match[1] !== jpSelf.id ? -1 : match[2]; -} - -// Returns the private version of the given public reflection. -function privateItem(publicItem) { - return publicItem.valueOf(PRIVATE_PROPS_KEY); -} - - -// A type of Worker tailored to our uses. -const ContextMenuWorker = Worker.compose({ - destroy: Worker.required, - - // Returns true if any context listeners are defined in the worker's port. - anyContextListeners: function CMW_anyContextListeners() { - return this._contentWorker._listeners("context").length > 0; - }, - - // Returns the first string or truthy value returned by a context listener in - // the worker's port. If none return a string or truthy value or if there are - // no context listeners, returns false. popupNode is the node that was - // context-clicked. - isAnyContextCurrent: function CMW_isAnyContextCurrent(popupNode) { - let listeners = this._contentWorker._listeners("context"); - for (let i = 0; i < listeners.length; i++) { - try { - let val = listeners[i].call(this._contentWorker._sandbox, popupNode); - if (typeof(val) === "string" || val) - return val; - } - catch (err) { - console.exception(err); - } - } - return false; - }, - - // Emits a click event in the worker's port. popupNode is the node that was - // context-clicked, and clickedItemData is the data of the item that was - // clicked. - fireClick: function CMW_fireClick(popupNode, clickedItemData) { - this._contentWorker._asyncEmit("click", popupNode, clickedItemData); - } -}); - - -// This class creates and stores content workers for pairs of menu items and -// content windows. Use one instance for each item. Not all pairs need a -// worker: if an item has a URL context that does not match a window's page, -// then no worker is created for the pair. -function WorkerRegistry(item) { - this.item = item; - - // inner window ID => { win, worker } - this.winWorkers = {}; - - // inner window ID => content window - this.winsWithoutWorkers = {}; -} - -WorkerRegistry.prototype = { - - // Registers a content window, creating a worker for it if it needs one. - registerContentWin: function WR_registerContentWin(win) { - let innerWinID = winUtils.getInnerId(win); - if ((innerWinID in this.winWorkers) || - (innerWinID in this.winsWithoutWorkers)) - return; - if (this._doesURLNeedWorker(win.document.URL)) - this.winWorkers[innerWinID] = { win: win, worker: this._makeWorker(win) }; - else - this.winsWithoutWorkers[innerWinID] = win; - }, - - // Unregisters a content window, destroying its related worker if it has one. - unregisterContentWin: function WR_unregisterContentWin(innerWinID) { - if (innerWinID in this.winWorkers) { - let winWorker = this.winWorkers[innerWinID]; - winWorker.worker.destroy(); - delete winWorker.worker; - delete winWorker.win; - delete this.winWorkers[innerWinID]; - } - else - delete this.winsWithoutWorkers[innerWinID]; - }, - - // Creates a worker for each window that needs a worker but doesn't have one. - createNeededWorkers: function WR_createNeededWorkers() { - for (let [innerWinID, win] in Iterator(this.winsWithoutWorkers)) { - delete this.winsWithoutWorkers[innerWinID]; - this.registerContentWin(win); - } - }, - - // Destroys the worker for each window that has a worker but doesn't need it. - destroyUnneededWorkers: function WR_destroyUnneededWorkers() { - for (let [innerWinID, winWorker] in Iterator(this.winWorkers)) { - if (!this._doesURLNeedWorker(winWorker.win.document.URL)) { - this.unregisterContentWin(innerWinID); - this.winsWithoutWorkers[innerWinID] = winWorker.win; - } - } - }, - - // Returns the worker for the item-window pair or null if none exists. - find: function WR_find(contentWin) { - let innerWinID = winUtils.getInnerId(contentWin); - return (innerWinID in this.winWorkers) ? - this.winWorkers[innerWinID].worker : - null; - }, - - // Unregisters all content windows from the registry, which destroys all - // workers. - destroy: function WR_destroy() { - for (let innerWinID in this.winWorkers) - this.unregisterContentWin(innerWinID); - for (let innerWinID in this.winsWithoutWorkers) - this.unregisterContentWin(innerWinID); - }, - - // Returns false if the item has a URL context that does not match the given - // URL. - _doesURLNeedWorker: function WR__doesURLNeedWorker(url) { - for (let ctxt in this.item.context) - if ((ctxt instanceof URLContext) && !ctxt.isCurrentForURL(url)) - return false; - return true; - }, - - _makeWorker: function WR__makeWorker(win) { - let worker = ContextMenuWorker({ - window: win, - contentScript: this.item.contentScript, - contentScriptFile: this.item.contentScriptFile, - onError: function (err) console.exception(err) - }); - let item = this.item; - worker.on("message", function workerOnMessage(msg) { - try { - privateItem(item)._emitOnObject(item, "message", msg); - } - catch (err) { - console.exception(err); - } - }); - return worker; - } -}; - - -// Mirrors state across all browser windows. Also responsible for detecting -// all content window loads and unloads. -let browserManager = { - topLevelItems: [], - browserWins: [], - - // inner window ID => content window - contentWins: {}, - - // Call this when a new item is created, top-level or not. - registerItem: function BM_registerItem(item) { - this.browserWins.forEach(function (w) w.registerItem(item)); - }, - - // Call this when an item is destroyed and won't be used again, top-level or - // not. - unregisterItem: function BM_unregisterItem(item) { - this.browserWins.forEach(function (w) w.unregisterItem(item)); - }, - - addTopLevelItem: function BM_addTopLevelItem(item) { - this.topLevelItems.push(item); - this.browserWins.forEach(function (w) w.addTopLevelItem(item)); - - // Create the item's worker registry and register all currently loaded - // content windows with it. - let privates = privateItem(item); - privates._isTopLevel = true; - for each (let win in this.contentWins) - privates._workerReg.registerContentWin(win); - }, - - removeTopLevelItem: function BM_removeTopLevelItem(item) { - let idx = this.topLevelItems.indexOf(item); - if (idx < 0) - throw new Error("Internal error: item not in top-level menu: " + item); - this.topLevelItems.splice(idx, 1); - this.browserWins.forEach(function (w) w.removeTopLevelItem(item)); - privateItem(item)._isTopLevel = false; - }, - - addItemToMenu: function BM_addItemToMenu(item, parentMenu) { - this.browserWins.forEach(function (w) w.addItemToMenu(item, parentMenu)); - }, - - removeItemFromMenu: function BM_removeItemFromMenu(item, parentMenu) { - this.browserWins.forEach(function (w) w.removeItemFromMenu(item, - parentMenu)); - }, - - setItemLabel: function BM_setItemLabel(item, label) { - this.browserWins.forEach(function (w) w.setItemLabel(item, label)); - }, - - setItemImage: function BM_setItemImage(item, imageURL) { - this.browserWins.forEach(function (w) w.setItemImage(item, imageURL)); - }, - - setItemData: function BM_setItemData(item, data) { - this.browserWins.forEach(function (w) w.setItemData(item, data)); - }, - - // Note that calling this method will cause onTrack to be called immediately - // for each currently open browser window. - init: function BM_init() { - require("api-utils/unload").ensure(this); - let windowTracker = new winUtils.WindowTracker(this); - - // Register content windows on content-document-global-created and - // unregister them on inner-window-destroyed. For rationale, see bug 667957 - // for the former and bug 642004 for the latter. - observerServ.add("content-document-global-created", - this._onDocGlobalCreated, this); - observerServ.add("inner-window-destroyed", - this._onInnerWinDestroyed, this); - }, - - _onDocGlobalCreated: function BM__onDocGlobalCreated(contentWin) { - let doc = contentWin.document; - if (doc.readyState == "loading") { - const self = this; - doc.addEventListener("readystatechange", function onReadyStateChange(e) { - if (e.target != doc || doc.readyState != "complete") - return; - doc.removeEventListener("readystatechange", onReadyStateChange, false); - self._registerContentWin(contentWin); - }, false); - } - else if (doc.readyState == "complete") - this._registerContentWin(contentWin); - }, - - _onInnerWinDestroyed: function BM__onInnerWinDestroyed(subj) { - this._unregisterContentWin( - subj.QueryInterface(Ci.nsISupportsPRUint64).data); - }, - - // Stores the given content window with the manager and registers it with each - // top-level item's worker registry. - _registerContentWin: function BM__registerContentWin(win) { - let innerID = winUtils.getInnerId(win); - - // It's an error to call this method for the same window more than once, but - // we allow it in one case: when onTrack races _onDocGlobalCreated. (See - // the comment in onTrack.) Make sure the window is registered only once. - if (innerID in this.contentWins) - return; - - this.contentWins[innerID] = win; - this.topLevelItems.forEach(function (item) { - privateItem(item)._workerReg.registerContentWin(win); - }); - }, - - // Removes the given content window from the manager and unregisters it from - // each top-level item's worker registry. - _unregisterContentWin: function BM__unregisterContentWin(innerID) { - delete this.contentWins[innerID]; - this.topLevelItems.forEach(function (item) { - privateItem(item)._workerReg.unregisterContentWin(innerID); - }); - }, - - unload: function BM_unload() { - // The window tracker is unloaded at the same time this method is called, - // which causes onUntrack to be called for each open browser window, so - // there's no need to clean up browser windows here. - - while (this.topLevelItems.length) { - let item = this.topLevelItems[0]; - this.removeTopLevelItem(item); - this.unregisterItem(item); - } - delete this.contentWins; - }, - - // Registers a browser window with the manager. This is a WindowTracker - // callback. Note that this is called in two cases: for each newly opened - // chrome window, and for each chrome window that is open when the loader - // loads this module. - onTrack: function BM_onTrack(window) { - if (!this._isBrowserWindow(window)) - return; - - let browserWin = new BrowserWindow(window); - this.browserWins.push(browserWin); - - // Register all loaded content windows in the browser window. Be sure to - // include frames and iframes. If onTrack is called as a result of a new - // browser window being opened, as opposed to the module being loaded, then - // this will race the content-document-global-created notification. That's - // OK, since _registerContentWin will not register the same content window - // more than once. - window.gBrowser.browsers.forEach(function (browser) { - let topContentWin = browser.contentWindow; - let allContentWins = Array.slice(topContentWin.frames); - allContentWins.push(topContentWin); - allContentWins.forEach(function (contentWin) { - if (contentWin.document.readyState == "complete") - this._registerContentWin(contentWin); - }, this); - }, this); - - // Add all top-level items and, recursively, their child items to the new - // browser window. - function addItemTree(item, parentMenu) { - browserWin.registerItem(item); - if (parentMenu) - browserWin.addItemToMenu(item, parentMenu); - else - browserWin.addTopLevelItem(item); - if (item instanceof Menu) - item.items.forEach(function (subitem) addItemTree(subitem, item)); - } - this.topLevelItems.forEach(function (item) addItemTree(item, null)); - }, - - // Unregisters a browser window from the manager. This is a WindowTracker - // callback. Note that this is called in two cases: for each newly closed - // chrome window, and for each chrome window that is open when this module is - // unloaded. - onUntrack: function BM_onUntrack(window) { - if (!this._isBrowserWindow(window)) - return; - - // Remove the window from the window list. - let idx = 0; - for (; idx < this.browserWins.length; idx++) - if (this.browserWins[idx].window == window) - break; - if (idx == this.browserWins.length) - throw new Error("Internal error: browser window not found"); - let browserWin = this.browserWins.splice(idx, 1)[0]; - - // Remove all top-level items from the window. - this.topLevelItems.forEach(function (i) browserWin.removeTopLevelItem(i)); - browserWin.destroy(); - }, - - _isBrowserWindow: function BM__isBrowserWindow(win) { - let winType = win.document.documentElement.getAttribute("windowtype"); - return winType === "navigator:browser"; - } -}; - - -// Responsible for creating and managing context menu item DOM elements for a -// browser window. Also responsible for providing a description of the window's -// current context and determining whether an item matches the current context. -// -// TODO: If other apps besides Firefox want to support the context menu in -// whatever way is appropriate for them, plugging in a substitute for or an -// adapter to this class should be the way to do it. Make it easy for them. -// See bug 560716. -function BrowserWindow(window) { - this.window = window; - this.doc = window.document; - - let popupDOMElt = this.doc.getElementById("contentAreaContextMenu"); - if (!popupDOMElt) - throw new Error("Internal error: Context menu popup not found."); - this.contextMenuPopup = new ContextMenuPopup(popupDOMElt, this); - - // item ID => { item, domElt, overflowDOMElt, popup, overflowPopup } - // item may or may not be top-level. domElt is the item's DOM element - // contained in the subtree rooted in the top-level context menu. - // overflowDOMElt is the item's DOM element contained in the subtree rooted in - // the overflow submenu. popup and overflowPopup are only defined if the item - // is a Menu; they're the Popup instances containing the Menu's child items, - // with the aforementioned distinction between top-level and overflow - // subtrees. - this.items = {}; -} - -BrowserWindow.prototype = { - - // Creates and stores DOM elements for the given item, top-level or not. - registerItem: function BW_registerItem(item) { - // this.items[id] is referenced by _makeMenu, so it needs to be defined - // before _makeDOMElt is called. - let props = { item: item }; - this.items[privateItem(item)._id] = props; - props.domElt = this._makeDOMElt(item, false); - props.overflowDOMElt = this._makeDOMElt(item, true); - }, - - // Removes the given item's DOM elements from the store. - unregisterItem: function BW_unregisterItem(item) { - delete this.items[privateItem(item)._id]; - }, - - addTopLevelItem: function BW_addTopLevelItem(item) { - this.contextMenuPopup.addItem(item); - }, - - removeTopLevelItem: function BW_removeTopLevelItem(item) { - this.contextMenuPopup.removeItem(item); - }, - - addItemToMenu: function BW_addItemToMenu(item, parentMenu) { - let { popup, overflowPopup } = this.items[privateItem(parentMenu)._id]; - popup.addItem(item); - overflowPopup.addItem(item); - }, - - removeItemFromMenu: function BW_removeItemFromMenu(item, parentMenu) { - let { popup, overflowPopup } = this.items[privateItem(parentMenu)._id]; - popup.removeItem(item); - overflowPopup.removeItem(item); - }, - - setItemLabel: function BW_setItemLabel(item, label) { - let privates = privateItem(item); - let { domElt, overflowDOMElt } = this.items[privates._id]; - this._setDOMEltLabel(domElt, label); - this._setDOMEltLabel(overflowDOMElt, label); - if (!item.parentMenu && privates._hasFinishedInit) - this.contextMenuPopup.itemLabelDidChange(item); - }, - - _setDOMEltLabel: function BW__setDOMEltLabel(domElt, label) { - domElt.setAttribute("label", label); - }, - - setItemImage: function BW_setItemImage(item, imageURL) { - let { domElt, overflowDOMElt } = this.items[privateItem(item)._id]; - let isMenu = item instanceof Menu; - this._setDOMEltImage(domElt, imageURL, isMenu); - this._setDOMEltImage(overflowDOMElt, imageURL, isMenu); - }, - - _setDOMEltImage: function BW__setDOMEltImage(domElt, imageURL, isMenu) { - if (!imageURL) { - domElt.removeAttribute("image"); - domElt.classList.remove("menu-iconic"); - domElt.classList.remove("menuitem-iconic"); - } - else { - domElt.setAttribute("image", imageURL); - domElt.classList.add(isMenu ? "menu-iconic" : "menuitem-iconic"); - } - }, - - setItemData: function BW_setItemData(item, data) { - let { domElt, overflowDOMElt } = this.items[privateItem(item)._id]; - this._setDOMEltData(domElt, data); - this._setDOMEltData(overflowDOMElt, data); - }, - - _setDOMEltData: function BW__setDOMEltData(domElt, data) { - domElt.setAttribute("value", data); - }, - - // The context specified for a top-level item may not match exactly the real - // context that triggers it. For example, if the user context-clicks a span - // inside an anchor, we want items that specify an anchor context to be - // triggered, but the real context will indicate that the span was clicked, - // not the anchor. Where the real context and an item's context conflict, - // clients should be given the item's context, and this method can be used to - // make such adjustments. Returns an adjusted popupNode. - adjustPopupNode: function BW_adjustPopupNode(popupNode, topLevelItem) { - for (let ctxt in topLevelItem.context) { - if (typeof(ctxt.adjustPopupNode) === "function") { - let ctxtNode = ctxt.adjustPopupNode(popupNode); - if (ctxtNode) { - popupNode = ctxtNode; - break; - } - } - } - return popupNode; - }, - - // Returns true if all of item's contexts are current in the window. - areAllContextsCurrent: function BW_areAllContextsCurrent(item, popupNode) { - let win = popupNode.ownerDocument.defaultView; - let worker = privateItem(item)._workerReg.find(win); - - // If the worker for the item-window pair doesn't exist (e.g., because the - // page hasn't loaded yet), we can't really make a good decision since the - // content script may have a context listener. So just don't show the item - // at all. - if (!worker) - return false; - - // If there are no contexts given at all, the page context applies. - let hasContentContext = worker.anyContextListeners(); - if (!hasContentContext && !item.context.length) - return new PageContext().isCurrent(popupNode); - - // Otherwise, determine if all given contexts are current. Evaluate the - // declarative contexts first and the worker's context listeners last. That - // way the listener might be able to avoid some work. - let curr = true; - for (let ctxt in item.context) { - curr = curr && ctxt.isCurrent(popupNode); - if (!curr) - return false; - } - return !hasContentContext || worker.isAnyContextCurrent(popupNode); - }, - - // Sets this.popupNode to the node the user context-clicked to invoke the - // context menu. For Gecko 2.0 and later, triggerNode is this node; if it's - // falsey, document.popupNode is used. Returns the popupNode. - capturePopupNode: function BW_capturePopupNode(triggerNode) { - this.popupNode = triggerNode || this.doc.popupNode; - if (!this.popupNode) - console.warn("popupNode is null."); - return this.popupNode; - }, - - destroy: function BW_destroy() { - this.contextMenuPopup.destroy(); - delete this.window; - delete this.doc; - delete this.items; - }, - - // Emits a click event in the port of the content worker related to given top- - // level item and popupNode's content window. Listeners will be passed - // popupNode and clickedItemData. - fireClick: function BW_fireClick(topLevelItem, popupNode, clickedItemData) { - let win = popupNode.ownerDocument.defaultView; - let worker = privateItem(topLevelItem)._workerReg.find(win); - if (worker) - worker.fireClick(popupNode, clickedItemData); - }, - - _makeDOMElt: function BW__makeDOMElt(item, isInOverflowSubtree) { - let elt = item instanceof Item ? this._makeMenuitem(item) : - item instanceof Menu ? this._makeMenu(item, isInOverflowSubtree) : - item instanceof Separator ? this._makeSeparator() : - null; - if (!elt) - throw new Error("Internal error: can't make element, unknown item type"); - - elt.id = domEltIDFromItemID(privateItem(item)._id, isInOverflowSubtree); - elt.classList.add(ITEM_CLASS); - return elt; - }, - - // Returns a new xul:menu representing the menu. - _makeMenu: function BW__makeMenu(menu, isInOverflowSubtree) { - let menuElt = this.doc.createElement("menu"); - this._setDOMEltLabel(menuElt, menu.label); - if (menu.image) - this._setDOMEltImage(menuElt, menu.image, true); - let popupElt = this.doc.createElement("menupopup"); - menuElt.appendChild(popupElt); - - let popup = new Popup(popupElt, this, isInOverflowSubtree); - let props = this.items[privateItem(menu)._id]; - if (isInOverflowSubtree) - props.overflowPopup = popup; - else - props.popup = popup; - - return menuElt; - }, - - // Returns a new xul:menuitem representing the item. - _makeMenuitem: function BW__makeMenuitem(item) { - let elt = this.doc.createElement("menuitem"); - this._setDOMEltLabel(elt, item.label); - if (item.image) - this._setDOMEltImage(elt, item.image, false); - if (item.data) - this._setDOMEltData(elt, item.data); - return elt; - }, - - // Returns a new xul:menuseparator. - _makeSeparator: function BW__makeSeparator() { - return this.doc.createElement("menuseparator"); - } -}; - - -// Responsible for adding DOM elements to and removing them from poupDOMElt. -function Popup(popupDOMElt, browserWin, isInOverflowSubtree) { - this.popupDOMElt = popupDOMElt; - this.browserWin = browserWin; - this.isInOverflowSubtree = isInOverflowSubtree; -} - -Popup.prototype = { - - addItem: function Popup_addItem(item) { - let props = this.browserWin.items[privateItem(item)._id]; - let elt = this.isInOverflowSubtree ? props.overflowDOMElt : props.domElt; - this.popupDOMElt.appendChild(elt); - }, - - removeItem: function Popup_removeItem(item) { - let props = this.browserWin.items[privateItem(item)._id]; - let elt = this.isInOverflowSubtree ? props.overflowDOMElt : props.domElt; - this.popupDOMElt.removeChild(elt); - } -}; - - -// Represents a browser window's context menu popup. Responsible for hiding and -// showing items according to the browser window's current context and for -// handling item clicks. -function ContextMenuPopup(popupDOMElt, browserWin) { - this.popupDOMElt = popupDOMElt; - this.browserWin = browserWin; - this.doc = popupDOMElt.ownerDocument; - - // item ID => item - // Calling this variable "topLevelItems" is redundant, since Popup and - // ContextMenuPopup are only responsible for their child items, not all their - // descendant items. But calling it "items" might encourage one to believe - // otherwise, so topLevelItems it is. - this.topLevelItems = {}; - - popupDOMElt.addEventListener("popupshowing", this, false); - popupDOMElt.addEventListener("command", this, false); -} - -ContextMenuPopup.prototype = { - - addItem: function CMP_addItem(item) { - this._ensureStaticEltsExist(); - let itemID = privateItem(item)._id; - this.topLevelItems[itemID] = item; - let props = this.browserWin.items[itemID]; - props.domElt.classList.add(TOPLEVEL_ITEM_CLASS); - props.overflowDOMElt.classList.add(OVERFLOW_ITEM_CLASS); - this._insertItemInSortedOrder(item); - }, - - removeItem: function CMP_removeItem(item) { - let itemID = privateItem(item)._id; - delete this.topLevelItems[itemID]; - let { domElt, overflowDOMElt } = this.browserWin.items[itemID]; - domElt.classList.remove(TOPLEVEL_ITEM_CLASS); - overflowDOMElt.classList.remove(OVERFLOW_ITEM_CLASS); - this.popupDOMElt.removeChild(domElt); - this._overflowPopup.removeChild(overflowDOMElt); - }, - - // Call this after the item's label changes. This re-inserts the item into - // the popup so that it remains in sorted order. - itemLabelDidChange: function CMP_itemLabelDidChange(item) { - let itemID = privateItem(item)._id; - let { domElt, overflowDOMElt } = this.browserWin.items[itemID]; - this.popupDOMElt.removeChild(domElt); - this._overflowPopup.removeChild(overflowDOMElt); - this._insertItemInSortedOrder(item); - }, - - destroy: function CMP_destroy() { - // If there are no more items from any instance of the module, remove the - // separator and overflow submenu, if they exist. - let elts = this._topLevelElts; - if (!elts.length) { - let submenu = this._overflowMenu; - if (submenu) - this.popupDOMElt.removeChild(submenu); - - let sep = this._separator; - if (sep) - this.popupDOMElt.removeChild(sep); - } - - this.popupDOMElt.removeEventListener("popupshowing", this, false); - this.popupDOMElt.removeEventListener("command", this, false); - }, - - handleEvent: function CMP_handleEvent(event) { - try { - if (event.type === "command") - this._handleClick(event.target); - else if (event.type === "popupshowing" && - event.target === this.popupDOMElt) - this._handlePopupShowing(); - } - catch (err) { - console.exception(err); - } - }, - - // command events bubble to the context menu's top-level xul:menupopup and are - // caught here. - _handleClick: function CMP__handleClick(clickedDOMElt) { - if (!clickedDOMElt.classList.contains(ITEM_CLASS)) - return; - let itemID = itemIDFromDOMEltID(clickedDOMElt.id); - if (itemID < 0) - return; - let { item, domElt, overflowDOMElt } = this.browserWin.items[itemID]; - - // Bail if the DOM element was not created by this module instance. In - // real-world add-ons, the itemID < 0 check above is sufficient, but for the - // unit test the JID never changes, making this necessary. - if (clickedDOMElt != domElt && clickedDOMElt != overflowDOMElt) - return; - - let topLevelItem = privateItem(item)._topLevelItem; - let popupNode = this.browserWin.adjustPopupNode(this.browserWin.popupNode, - topLevelItem); - this.browserWin.fireClick(topLevelItem, popupNode, item.data); - }, - - // popupshowing is used to show top-level items that match the browser - // window's current context and hide items that don't. Each module instance - // is responsible for showing and hiding the items it owns. - _handlePopupShowing: function CMP__handlePopupShowing() { - // If there are items queued up to finish initializing, let them go first. - // Otherwise the overflow submenu and menu separator may end up in an - // inappropriate state when those items are later added to the menu. - if (numItemsWithUnfinishedInit) { - const self = this; - timer.setTimeout(function popupShowingTryAgain() { - self._handlePopupShowing(); - }, 0); - return; - } - - // popupDOMElt.triggerNode was added in Gecko 2.0 by bug 383930. The || is - // to avoid a Spidermonkey strict warning on earlier versions. - let triggerNode = this.popupDOMElt.triggerNode || undefined; - let popupNode = this.browserWin.capturePopupNode(triggerNode); - - // Show and hide items. Set a "jetpackContextCurrent" property on the - // DOM elements to signal which of our items match the current context. - for (let [itemID, item] in Iterator(this.topLevelItems)) { - let areContextsCurr = - this.browserWin.areAllContextsCurrent(item, popupNode); - - // Change the item's label if the return value was a string. - if (typeof(areContextsCurr) === "string") { - item.label = areContextsCurr; - areContextsCurr = true; - } - - let { domElt, overflowDOMElt } = this.browserWin.items[itemID]; - domElt.jetpackContextCurrent = areContextsCurr; - domElt.hidden = !areContextsCurr; - overflowDOMElt.jetpackContextCurrent = areContextsCurr; - overflowDOMElt.hidden = !areContextsCurr; - } - - // Get the total number of items that match the current context. It's a - // little tricky: There may be other instances of this module loaded, - // each hiding and showing their items. So we can't base this number on - // only our items, or on the hidden state of items. That's why we set - // the jetpackContextCurrent property above. The last instance to run - // will leave the menupopup in the correct state. - let elts = this._topLevelElts; - let numShown = Array.reduce(elts, function (total, elt) { - return total + (elt.jetpackContextCurrent ? 1 : 0); - }, 0); - - // If too many items are shown, show the submenu and hide the top-level - // items. Otherwise, hide the submenu and show the top-level items. - let overflow = numShown > this._overflowThreshold; - if (overflow) - Array.forEach(elts, function (e) e.hidden = true); - - let submenu = this._overflowMenu; - if (submenu) - submenu.hidden = !overflow; - - // If no items are shown, hide the menu separator. - let sep = this._separator; - if (sep) - sep.hidden = numShown === 0; - }, - - // Adds the menu separator and overflow submenu if they don't exist. - _ensureStaticEltsExist: function CMP__ensureStaticEltsExist() { - let sep = this._separator; - if (!sep) { - sep = this._makeSeparator(); - this.popupDOMElt.appendChild(sep); - } - - let submenu = this._overflowMenu; - if (!submenu) { - submenu = this._makeOverflowMenu(); - submenu.hidden = true; - this.popupDOMElt.insertBefore(submenu, sep.nextSibling); - } - }, - - // Inserts the given item's DOM element into the popup in sorted order. - _insertItemInSortedOrder: function CMP__insertItemInSortedOrder(item) { - let props = this.browserWin.items[privateItem(item)._id]; - this.popupDOMElt.insertBefore( - props.domElt, insertionPoint(item.label, this._topLevelElts)); - this._overflowPopup.insertBefore( - props.overflowDOMElt, insertionPoint(item.label, this._overflowElts)); - }, - - // Creates and returns the xul:menu that's shown when too many items are added - // to the popup. - _makeOverflowMenu: function CMP__makeOverflowMenu() { - let submenu = this.doc.createElement("menu"); - submenu.id = OVERFLOW_MENU_ID; - submenu.setAttribute("label", OVERFLOW_MENU_LABEL); - let popup = this.doc.createElement("menupopup"); - popup.id = OVERFLOW_POPUP_ID; - submenu.appendChild(popup); - return submenu; - }, - - // Creates and returns the xul:menuseparator that separates the standard - // context menu items from our items. - _makeSeparator: function CMP__makeSeparator() { - let elt = this.doc.createElement("menuseparator"); - elt.id = SEPARATOR_ID; - return elt; - }, - - // Returns the item elements contained in the overflow menu, a NodeList. - get _overflowElts() { - return this._overflowPopup.getElementsByClassName(OVERFLOW_ITEM_CLASS); - }, - - // Returns the overflow xul:menu. - get _overflowMenu() { - return this.doc.getElementById(OVERFLOW_MENU_ID); - }, - - // Returns the overflow xul:menupopup. - get _overflowPopup() { - return this.doc.getElementById(OVERFLOW_POPUP_ID); - }, - - // Returns the OVERFLOW_THRESH_PREF pref value if it exists or - // OVERFLOW_THRESH_DEFAULT if it doesn't. - get _overflowThreshold() { - let prefs = require("api-utils/preferences-service"); - return prefs.get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT); - }, - - // Returns the xul:menuseparator. - get _separator() { - return this.doc.getElementById(SEPARATOR_ID); - }, - - // Returns the item elements contained in the top-level menu, a NodeList. - get _topLevelElts() { - return this.popupDOMElt.getElementsByClassName(TOPLEVEL_ITEM_CLASS); - } -}; - - -// Init the browserManager only after setting prototypes and such above, because -// it will cause browserManager.onTrack to be called immediately if there are -// open windows. -browserManager.init(); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/hotkeys.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/hotkeys.js deleted file mode 100644 index f8c6434..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/hotkeys.js +++ /dev/null @@ -1,71 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * Henri Wiechers <hwiechers@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const INVALID_HOTKEY = "Hotkey must have at least one modifier."; - -const { toJSON: jsonify, toString: stringify, - isFunctionKey } = require("api-utils/keyboard/utils"); -const { register, unregister } = require("api-utils/keyboard/hotkeys"); - -const Hotkey = exports.Hotkey = function Hotkey(options) { - if (!(this instanceof Hotkey)) - return new Hotkey(options); - - // Parsing key combination string. - let hotkey = jsonify(options.combo); - if (!isFunctionKey(hotkey.key) && !hotkey.modifiers.length) { - throw new TypeError(INVALID_HOTKEY); - } - - this.onPress = options.onPress; - this.toString = stringify.bind(null, hotkey); - // Registering listener on keyboard combination enclosed by this hotkey. - // Please note that `this.toString()` is a normalized version of - // `options.combination` where order of modifiers is sorted and `accel` is - // replaced with platform specific key. - register(this.toString(), this.onPress); - // We freeze instance before returning it in order to make it's properties - // read-only. - return Object.freeze(this); -}; -Hotkey.prototype.destroy = function destroy() { - unregister(this.toString(), this.onPress); -}; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/notifications.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/notifications.js deleted file mode 100644 index f2a4ea2..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/notifications.js +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci, Cr } = require("chrome"); -const apiUtils = require("api-utils/api-utils"); -const errors = require("api-utils/errors"); - -try { - let alertServ = Cc["@mozilla.org/alerts-service;1"]. - getService(Ci.nsIAlertsService); - - // The unit test sets this to a mock notification function. - var notify = alertServ.showAlertNotification.bind(alertServ); -} -catch (err) { - // An exception will be thrown if the platform doesn't provide an alert - // service, e.g., if Growl is not installed on OS X. In that case, use a - // mock notification function that just logs to the console. - notify = notifyUsingConsole; -} - -exports.notify = function notifications_notify(options) { - let valOpts = validateOptions(options); - let clickObserver = !valOpts.onClick ? null : { - observe: function notificationClickObserved(subject, topic, data) { - if (topic === "alertclickcallback") - errors.catchAndLog(valOpts.onClick).call(exports, valOpts.data); - } - }; - function notifyWithOpts(notifyFn) { - notifyFn(valOpts.iconURL, valOpts.title, valOpts.text, !!clickObserver, - valOpts.data, clickObserver); - } - try { - notifyWithOpts(notify); - } - catch (err if err instanceof Ci.nsIException && - err.result == Cr.NS_ERROR_FILE_NOT_FOUND) { - console.warn("The notification icon named by " + valOpts.iconURL + - " does not exist. A default icon will be used instead."); - delete valOpts.iconURL; - notifyWithOpts(notify); - } - catch (err) { - notifyWithOpts(notifyUsingConsole); - } -}; - -function notifyUsingConsole(iconURL, title, text) { - title = title ? "[" + title + "]" : ""; - text = text || ""; - let str = [title, text].filter(function (s) s).join(" "); - console.log(str); -} - -function validateOptions(options) { - return apiUtils.validateOptions(options, { - data: { - is: ["string", "undefined"] - }, - iconURL: { - is: ["string", "undefined"] - }, - onClick: { - is: ["function", "undefined"] - }, - text: { - is: ["string", "undefined"] - }, - title: { - is: ["string", "undefined"] - } - }); -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/page-mod.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/page-mod.js deleted file mode 100644 index d511464..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/page-mod.js +++ /dev/null @@ -1,229 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack Packages. - * - * The Initial Developer of the Original Code is Nickolay Ponomarev. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Nickolay Ponomarev <asqueella@gmail.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const observers = require("api-utils/observer-service"); -const { Worker, Loader } = require('api-utils/content'); -const { EventEmitter } = require('api-utils/events'); -const { List } = require('api-utils/list'); -const { Registry } = require('api-utils/utils/registry'); -const xulApp = require("api-utils/xul-app"); -const { MatchPattern } = require('api-utils/match-pattern'); - -// Whether or not the host application dispatches a document-element-inserted -// notification when the document element is inserted into the DOM of a page. -// The notification was added in Gecko 2.0b6, it's a better time to attach -// scripts with contentScriptWhen "start" than content-document-global-created, -// since libraries like jQuery assume the presence of the document element. -const HAS_DOCUMENT_ELEMENT_INSERTED = - xulApp.versionInRange(xulApp.platformVersion, "2.0b6", "*"); -const ON_CONTENT = HAS_DOCUMENT_ELEMENT_INSERTED ? 'document-element-inserted' : - 'content-document-global-created'; - -// Workaround bug 642145: document-element-inserted is fired multiple times. -// This bug is fixed in Firefox 4.0.1, but we want to keep FF 4.0 compatibility -// Tracking bug 641457. To be removed when 4.0 has disappeared from earth. -const HAS_BUG_642145_FIXED = - xulApp.versionInRange(xulApp.platformVersion, "2.0.1", "*"); - -// rules registry -const RULES = {}; - -const Rules = EventEmitter.resolve({ toString: null }).compose(List, { - add: function() Array.slice(arguments).forEach(function onAdd(rule) { - if (this._has(rule)) - return; - // registering rule to the rules registry - if (!(rule in RULES)) - RULES[rule] = new MatchPattern(rule); - this._add(rule); - this._emit('add', rule); - }.bind(this)), - remove: function() Array.slice(arguments).forEach(function onRemove(rule) { - if (!this._has(rule)) - return; - this._remove(rule); - this._emit('remove', rule); - }.bind(this)), -}); - -/** - * PageMod constructor (exported below). - * @constructor - */ -const PageMod = Loader.compose(EventEmitter, { - on: EventEmitter.required, - _listeners: EventEmitter.required, - contentScript: Loader.required, - contentScriptFile: Loader.required, - contentScriptWhen: Loader.required, - include: null, - constructor: function PageMod(options) { - this._onContent = this._onContent.bind(this); - options = options || {}; - - if ('contentScript' in options) - this.contentScript = options.contentScript; - if ('contentScriptFile' in options) - this.contentScriptFile = options.contentScriptFile; - if ('contentScriptWhen' in options) - this.contentScriptWhen = options.contentScriptWhen; - if ('onAttach' in options) - this.on('attach', options.onAttach); - if ('onError' in options) - this.on('error', options.onError); - - let include = options.include; - let rules = this.include = Rules(); - rules.on('add', this._onRuleAdd = this._onRuleAdd.bind(this)); - rules.on('remove', this._onRuleRemove = this._onRuleRemove.bind(this)); - - if (Array.isArray(include)) - rules.add.apply(null, include); - else - rules.add(include); - - this.on('error', this._onUncaughtError = this._onUncaughtError.bind(this)); - pageModManager.add(this._public); - - this._loadingWindows = []; - }, - - destroy: function destroy() { - for each (let rule in this.include) - this.include.remove(rule); - pageModManager.remove(this._public); - this._loadingWindows = []; - }, - - _loadingWindows: [], - - _onContent: function _onContent(window) { - // not registered yet - if (!pageModManager.has(this)) - return; - - if (!HAS_BUG_642145_FIXED) { - if (this._loadingWindows.indexOf(window) != -1) - return; - this._loadingWindows.push(window); - } - - if ('start' == this.contentScriptWhen) { - this._createWorker(window); - return; - } - - let eventName = 'end' == this.contentScriptWhen ? 'load' : 'DOMContentLoaded'; - let self = this; - window.addEventListener(eventName, function onReady(event) { - if (event.target.defaultView != window) - return; - window.removeEventListener(eventName, onReady, true); - - self._createWorker(window); - }, true); - }, - _createWorker: function _createWorker(window) { - let worker = Worker({ - window: window, - contentScript: this.contentScript, - contentScriptFile: this.contentScriptFile, - onError: this._onUncaughtError - }); - this._emit('attach', worker); - let self = this; - worker.once('detach', function detach() { - worker.destroy(); - - if (!HAS_BUG_642145_FIXED) { - let idx = self._loadingWindows.indexOf(window); - if (idx != -1) - self._loadingWindows.splice(idx, 1); - } - }); - }, - _onRuleAdd: function _onRuleAdd(url) { - pageModManager.on(url, this._onContent); - }, - _onRuleRemove: function _onRuleRemove(url) { - pageModManager.off(url, this._onContent); - }, - _onUncaughtError: function _onUncaughtError(e) { - if (this._listeners('error').length == 1) - console.exception(e); - } -}); -exports.PageMod = function(options) PageMod(options) -exports.PageMod.prototype = PageMod.prototype; - -const PageModManager = Registry.resolve({ - constructor: '_init', - _destructor: '_registryDestructor' -}).compose({ - constructor: function PageModRegistry(constructor) { - this._init(PageMod); - observers.add( - ON_CONTENT, this._onContentWindow = this._onContentWindow.bind(this) - ); - }, - _destructor: function _destructor() { - observers.remove(ON_CONTENT, this._onContentWindow); - for (let rule in RULES) { - this._removeAllListeners(rule); - delete RULES[rule]; - } - this._registryDestructor(); - }, - _onContentWindow: function _onContentWindow(domObj) { - let window = HAS_DOCUMENT_ELEMENT_INSERTED ? domObj.defaultView : domObj; - // XML documents don't have windows, and we don't yet support them. - if (!window) - return; - for (let rule in RULES) - if (RULES[rule].test(window.document.URL)) - this._emit(rule, window); - }, - off: function off(topic, listener) { - this.removeListener(topic, listener); - if (!this._listeners(topic).length) - delete RULES[topic]; - } -}); -const pageModManager = PageModManager(); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/page-worker.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/page-worker.js deleted file mode 100644 index 93750a1..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/page-worker.js +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Felipe Gomes <felipc@gmail.com> (Original Author) - * Myk Melez <myk@mozilla.org> - * Irakli Gozalishvili <gozala@mozilla.com> - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Symbiont } = require("api-utils/content"); -const { Trait } = require("api-utils/traits"); - -if (!require("api-utils/xul-app").isOneOf(["Firefox", "Thunderbird"])) { - throw new Error([ - "The page-worker module currently supports only Firefox and Thunderbird. ", - "In the future, we would like it to support other applications, however. ", - "Please see https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more ", - "information." - ].join("")); -} - -const Page = Trait.compose( - Symbiont.resolve({ - constructor: '_initSymbiont' - }), - { - _frame: Trait.required, - _initFrame: Trait.required, - postMessage: Symbiont.required, - on: Symbiont.required, - destroy: Symbiont.required, - - constructor: function Page(options) { - options = options || {}; - - this.contentURL = 'contentURL' in options ? options.contentURL - : 'about:blank'; - if ('contentScriptWhen' in options) - this.contentScriptWhen = options.contentScriptWhen; - if ('contentScriptFile' in options) - this.contentScriptFile = options.contentScriptFile; - if ('contentScript' in options) - this.contentScript = options.contentScript; - if ('allow' in options) - this.allow = options.allow; - if ('onError' in options) - this.on('error', options.onError); - if ('onMessage' in options) - this.on('message', options.onMessage); - - this.on('propertyChange', this._onChange.bind(this)); - - this._initSymbiont(); - }, - - _onChange: function _onChange(e) { - if ('contentURL' in e && this._frame) { - // Cleanup the worker before injecting the content script in the new - // document - this._workerCleanup(); - this._initFrame(this._frame); - } - } - } -); -exports.Page = function(options) Page(options); -exports.Page.prototype = Page.prototype; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/panel.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/panel.js deleted file mode 100644 index 442f6a9..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/panel.js +++ /dev/null @@ -1,403 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Myk Melez <myk@mozilla.org> (Original Author) - * Irakli Gozalishvili <gozala@mazilla.com> - * Mihai Sucan <mihai.sucan@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The panel module currently supports only Firefox. In the future ", - "we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=jetpack-panel-apps ", - "for more information." - ].join("")); -} - -const { Cc, Ci } = require("chrome"); - -const { validateOptions: valid } = require("api-utils/api-utils"); -const { Symbiont } = require("api-utils/content"); -const { EventEmitter } = require('api-utils/events'); -const timer = require("api-utils/timer"); -const runtime = require("api-utils/runtime"); - -const windowMediator = Cc['@mozilla.org/appshell/window-mediator;1']. - getService(Ci.nsIWindowMediator); - -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", - ON_SHOW = 'popupshown', - ON_HIDE = 'popuphidden', - validNumber = { is: ['number', 'undefined', 'null'] }; - -/** - * Emits show and hide events. - */ -const Panel = Symbiont.resolve({ - constructor: '_init', - _onInit: '_onSymbiontInit', - destroy: '_symbiontDestructor', - _documentUnload: '_workerDocumentUnload' -}).compose({ - _frame: Symbiont.required, - _init: Symbiont.required, - _onSymbiontInit: Symbiont.required, - _symbiontDestructor: Symbiont.required, - _emit: Symbiont.required, - _asyncEmit: Symbiont.required, - on: Symbiont.required, - removeListener: Symbiont.required, - - _inited: false, - - /** - * If set to `true` frame loaders between xul panel frame and - * hidden frame are swapped. If set to `false` frame loaders are - * set back to normal. Setting the value that was already set will - * have no effect. - */ - set _frameLoadersSwapped(value) { - if (this.__frameLoadersSwapped == value) return; - this._frame.QueryInterface(Ci.nsIFrameLoaderOwner) - .swapFrameLoaders(this._viewFrame); - this.__frameLoadersSwapped = value; - }, - __frameLoadersSwapped: false, - - constructor: function Panel(options) { - this._onShow = this._onShow.bind(this); - this._onHide = this._onHide.bind(this); - this.on('inited', this._onSymbiontInit.bind(this)); - - options = options || {}; - if ('onShow' in options) - this.on('show', options.onShow); - if ('onHide' in options) - this.on('hide', options.onHide); - if ('width' in options) - this.width = options.width; - if ('height' in options) - this.height = options.height; - if ('contentURL' in options) - this.contentURL = options.contentURL; - - this._init(options); - }, - _destructor: function _destructor() { - this.hide(); - this._removeAllListeners('show'); - // defer cleanup to be performed after panel gets hidden - this._xulPanel = null; - this._symbiontDestructor(this); - this._removeAllListeners(this, 'hide'); - }, - destroy: function destroy() { - this._destructor(); - }, - /* Public API: Panel.width */ - get width() this._width, - set width(value) - this._width = valid({ $: value }, { $: validNumber }).$ || this._width, - _width: 320, - /* Public API: Panel.height */ - get height() this._height, - set height(value) - this._height = valid({ $: value }, { $: validNumber }).$ || this._height, - _height: 240, - - /* Public API: Panel.isShowing */ - get isShowing() !!this._xulPanel && this._xulPanel.state == "open", - - /* Public API: Panel.show */ - show: function show(anchor) { - anchor = anchor || null; - let document = getWindow(anchor).document; - let xulPanel = this._xulPanel; - if (!xulPanel) { - xulPanel = this._xulPanel = document.createElementNS(XUL_NS, 'panel'); - xulPanel.setAttribute("type", "arrow"); - - // One anonymous node has a big padding that doesn't work well with - // Jetpack, as we would like to display an iframe that completely fills - // the panel. - // -> Use a XBL wrapper with inner stylesheet to remove this padding. - let css = ".panel-inner-arrowcontent, .panel-arrowcontent {padding: 0;}"; - let originalXBL = "chrome://global/content/bindings/popup.xml#arrowpanel"; - let binding = - '<bindings xmlns="http://www.mozilla.org/xbl">' + - '<binding id="id" extends="' + originalXBL + '">' + - '<resources>' + - '<stylesheet src="data:text/css,' + - document.defaultView.encodeURIComponent(css) + '"/>' + - '</resources>' + - '</binding>' + - '</bindings>'; - xulPanel.style.MozBinding = 'url("data:text/xml,' + - document.defaultView.encodeURIComponent(binding) + '")'; - - let frame = document.createElementNS(XUL_NS, 'iframe'); - frame.setAttribute('type', 'content'); - frame.setAttribute('flex', '1'); - frame.setAttribute('transparent', 'transparent'); - if (runtime.OS === "Darwin") { - frame.style.borderRadius = "6px"; - frame.style.padding = "1px"; - } - - // Load an empty document in order to have an immediatly loaded iframe, - // so swapFrameLoaders is going to work without having to wait for load. - frame.setAttribute("src","data:,"); - - xulPanel.appendChild(frame); - document.getElementById("mainPopupSet").appendChild(xulPanel); - } - let { width, height } = this, x, y, position; - - if (!anchor) { - // Open the popup in the middle of the window. - x = document.documentElement.clientWidth / 2 - width / 2; - y = document.documentElement.clientHeight / 2 - height / 2; - position = null; - } - else { - // Open the popup by the anchor. - let rect = anchor.getBoundingClientRect(); - - let window = anchor.ownerDocument.defaultView; - - let zoom = window.mozScreenPixelsPerCSSPixel; - let screenX = rect.left + window.mozInnerScreenX * zoom; - let screenY = rect.top + window.mozInnerScreenY * zoom; - - // Set up the vertical position of the popup relative to the anchor - // (always display the arrow on anchor center) - let horizontal, vertical; - if (screenY > window.screen.availHeight / 2 + height) - vertical = "top"; - else - vertical = "bottom"; - - if (screenY > window.screen.availWidth / 2 + width) - horizontal = "left"; - else - horizontal = "right"; - - let verticalInverse = vertical == "top" ? "bottom" : "top"; - position = vertical + "center " + verticalInverse + horizontal; - - // Allow panel to flip itself if the panel can't be displayed at the - // specified position (useful if we compute a bad position or if the - // user moves the window and panel remains visible) - xulPanel.setAttribute("flip","both"); - } - - // Resize the iframe instead of using panel.sizeTo - // because sizeTo doesn't work with arrow panels - xulPanel.firstChild.style.width = width + "px"; - xulPanel.firstChild.style.height = height + "px"; - - // Wait for the XBL binding to be constructed - function waitForBinding() { - if (!xulPanel.openPopup) { - timer.setTimeout(waitForBinding, 50); - return; - } - xulPanel.openPopup(anchor, position, x, y); - } - waitForBinding(); - - return this._public; - }, - /* Public API: Panel.hide */ - hide: function hide() { - // The popuphiding handler takes care of swapping back the frame loaders - // and removing the XUL panel from the application window, we just have to - // trigger it by hiding the popup. - // XXX Sometimes I get "TypeError: xulPanel.hidePopup is not a function" - // when quitting the host application while a panel is visible. To suppress - // them, this now checks for "hidePopup" in xulPanel before calling it. - // It's not clear if there's an actual issue or the error is just normal. - let xulPanel = this._xulPanel; - if (xulPanel && "hidePopup" in xulPanel) - xulPanel.hidePopup(); - return this._public; - }, - - /* Public API: Panel.resize */ - resize: function resize(width, height) { - this.width = width; - this.height = height; - // Resize the iframe instead of using panel.sizeTo - // because sizeTo doesn't work with arrow panels - let xulPanel = this._xulPanel; - if (xulPanel) { - xulPanel.firstChild.style.width = width + "px"; - xulPanel.firstChild.style.height = height + "px"; - } - }, - - // While the panel is visible, this is the XUL <panel> we use to display it. - // Otherwise, it's null. - get _xulPanel() this.__xulPanel, - set _xulPanel(value) { - let xulPanel = this.__xulPanel; - if (value === xulPanel) return; - if (xulPanel) { - xulPanel.removeEventListener(ON_HIDE, this._onHide, false); - xulPanel.removeEventListener(ON_SHOW, this._onShow, false); - xulPanel.parentNode.removeChild(xulPanel); - } - if (value) { - value.addEventListener(ON_HIDE, this._onHide, false); - value.addEventListener(ON_SHOW, this._onShow, false); - } - this.__xulPanel = value; - }, - __xulPanel: null, - get _viewFrame() this.__xulPanel.children[0], - /** - * When the XUL panel becomes hidden, we swap frame loaders back to move - * the content of the panel to the hidden frame & remove panel element. - */ - _onHide: function _onHide() { - try { - this._frameLoadersSwapped = false; - this._xulPanel = null; - this._emit('hide'); - } catch(e) { - this._emit('error', e); - } - }, - /** - * When the XUL panel becomes shown, we swap frame loaders between panel - * frame and hidden frame to preserve state of the content dom. - */ - _onShow: function _onShow() { - try { - if (!this._inited) { // defer if not initialized yet - this.on('inited', this._onShow.bind(this)); - } else { - this._frameLoadersSwapped = true; - - // Retrieve computed text color style in order to apply to the iframe - // document. As MacOS background is dark gray, we need to use skin's - // text color. - let win = this._xulPanel.ownerDocument.defaultView; - let node = win.document.getAnonymousElementByAttribute(this._xulPanel, - "class", "panel-inner-arrowcontent"); - let textColor = win.getComputedStyle(node).getPropertyValue("color"); - let doc = this._xulPanel.firstChild.contentDocument; - let style = doc.createElement("style"); - style.textContent = "body { color: " + textColor + "; }"; - let container = doc.head ? doc.head : doc.documentElement; - - if (container.firstChild) - container.insertBefore(style, container.firstChild); - else - container.appendChild(style); - - this._emit('show'); - } - } catch(e) { - this._emit('error', e); - } - }, - /** - * Notification that panel was fully initialized. - */ - _onInit: function _onInit() { - this._inited = true; - - // Avoid panel document from resizing the browser window - // New platform capability added through bug 635673 - if ("allowWindowControl" in this._frame.docShell) - this._frame.docShell.allowWindowControl = false; - - // perform all deferred tasks like initSymbiont, show, hide ... - // TODO: We're publicly exposing a private event here; this - // 'inited' event should really be made private, somehow. - this._emit('inited'); - }, - - // Catch document unload event in order to rebind load event listener with - // Symbiont._initFrame if Worker._documentUnload destroyed the worker - _documentUnload: function(subject, topic, data) { - if (this._workerDocumentUnload(subject, topic, data)) { - this._initFrame(this._frame); - return true; - } - return false; - } -}); -exports.Panel = function(options) Panel(options) -exports.Panel.prototype = Panel.prototype; - -function getWindow(anchor) { - let window; - - if (anchor) { - let anchorWindow = anchor.ownerDocument.defaultView.top; - let anchorDocument = anchorWindow.document; - - let enumerator = windowMediator.getEnumerator("navigator:browser"); - while (enumerator.hasMoreElements()) { - let enumWindow = enumerator.getNext(); - - // Check if the anchor is in this browser window. - if (enumWindow == anchorWindow) { - window = anchorWindow; - break; - } - - // Check if the anchor is in a browser tab in this browser window. - let browser = enumWindow.gBrowser.getBrowserForDocument(anchorDocument); - if (browser) { - window = enumWindow; - break; - } - - // Look in other subdocuments (sidebar, etc.)? - } - } - - // If we didn't find the anchor's window (or we have no anchor), - // return the most recent browser window. - if (!window) - window = windowMediator.getMostRecentWindow("navigator:browser"); - - return window; -} - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/passwords.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/passwords.js deleted file mode 100644 index 8225da9..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/passwords.js +++ /dev/null @@ -1,92 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -const { Trait } = require("api-utils/light-traits"); -const utils = require("api-utils/passwords/utils"); -const defer = require("api-utils/utils/function").Enqueued; - -/** - * Utility function that returns `onComplete` and `onError` callbacks form the - * given `options` objects. Also properties are removed from the passed - * `options` objects. - * @param {Object} options - * Object that is passed to the exported functions of this module. - * @returns {Function[]} - * Array with two elements `onComplete` and `onError` functions. - */ -function getCallbacks(options) { - let value = [ - 'onComplete' in options ? options.onComplete : null, - 'onError' in options ? defer(options.onError) : console.exception - ]; - - delete options.onComplete; - delete options.onError; - - return value; -}; - -/** - * Creates a wrapper function that tries to call `onComplete` with a return - * value of the wrapped function or falls back to `onError` if wrapped function - * throws an exception. - */ -function createWrapperMethod(wrapped) { - return function (options) { - let [ onComplete, onError ] = getCallbacks(options); - try { - let value = wrapped(options); - if (onComplete) { - defer(function() { - try { - onComplete(value); - } catch (exception) { - onError(exception); - } - })(); - } - } catch (exception) { - onError(exception); - } - }; -} - -exports.search = createWrapperMethod(utils.search); -exports.store = createWrapperMethod(utils.store); -exports.remove = createWrapperMethod(utils.remove); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/private-browsing.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/private-browsing.js deleted file mode 100644 index 8336e7b..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/private-browsing.js +++ /dev/null @@ -1,102 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Paul O’Shannessy <paul@oshannessy.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -const observers = require("api-utils/observer-service"); -const { EventEmitter } = require("api-utils/events"); -const { setTimeout } = require("api-utils/timer"); -const unload = require("api-utils/unload"); - -const ON_START = "start"; -const ON_STOP = "stop"; -const ON_TRANSITION = "private-browsing-transition-complete"; - -let pbService; -// Currently, only Firefox implements the private browsing service. -if (require("api-utils/xul-app").is("Firefox")) { - pbService = Cc["@mozilla.org/privatebrowsing;1"]. - getService(Ci.nsIPrivateBrowsingService); -} - -function toggleMode(value) pbService.privateBrowsingEnabled = !!value - -const privateBrowsing = EventEmitter.compose({ - constructor: function PrivateBrowsing() { - // Binding method to instance since it will be used with `setTimeout`. - this._emitOnObject = this._emitOnObject.bind(this); - this.unload = this.unload.bind(this); - // Report unhandled errors from listeners - this.on("error", console.exception.bind(console)); - unload.ensure(this); - // We only need to add observers if `pbService` exists. - if (pbService) { - observers.add(ON_TRANSITION, this.onTransition.bind(this)); - this._isActive = pbService.privateBrowsingEnabled; - } - }, - unload: function _destructor() { - this._removeAllListeners(ON_START); - this._removeAllListeners(ON_STOP); - }, - // We don't need to do anything with cancel here. - onTransition: function onTransition() { - let isActive = this._isActive = pbService.privateBrowsingEnabled; - setTimeout(this._emitOnObject, 0, exports, isActive ? ON_START : ON_STOP); - }, - get isActive() this._isActive, - set isActive(value) { - if (pbService) - // We toggle private browsing mode asynchronously in order to work around - // bug 659629. Since private browsing transitions are asynchronous - // anyway, this doesn't significantly change the behavior of the API. - setTimeout(toggleMode, 0, value); - }, - _isActive: false -})() - -Object.defineProperty(exports, "isActive", { - get: function() privateBrowsing.isActive -}); -exports.activate = function activate() privateBrowsing.isActive = true; -exports.deactivate = function deactivate() privateBrowsing.isActive = false; -exports.on = privateBrowsing.on; -exports.once = privateBrowsing.once; -exports.removeListener = privateBrowsing.removeListener; - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/request.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/request.js deleted file mode 100644 index a72b28c..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/request.js +++ /dev/null @@ -1,309 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Paul O’Shannessy <paul@oshannessy.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -const xpcom = require("api-utils/xpcom"); -const xhr = require("api-utils/xhr"); -const errors = require("api-utils/errors"); -const apiUtils = require("api-utils/api-utils"); - -// Ugly but will fix with: https://bugzilla.mozilla.org/show_bug.cgi?id=596248 -const EventEmitter = require('api-utils/events').EventEmitter.compose({ - constructor: function EventEmitter() this -}); - -// Instead of creating a new validator for each request, just make one and reuse it. -const validator = new OptionsValidator({ - url: { - //XXXzpao should probably verify that url is a valid url as well - is: ["string"] - }, - headers: { - map: function (v) v || {}, - is: ["object"], - }, - content: { - map: function (v) v || null, - is: ["string", "object", "null"], - }, - contentType: { - map: function (v) v || "application/x-www-form-urlencoded", - is: ["string"], - }, - overrideMimeType: { - map: function(v) v || null, - is: ["string", "null"], - } -}); - -const REUSE_ERROR = "This request object has been used already. You must " + - "create a new one to make a new request." - -function Request(options) { - const self = EventEmitter(), - _public = self._public; - // request will hold the actual XHR object - let request; - let response; - - if ('onComplete' in options) - self.on('complete', options.onComplete) - options = validator.validateOptions(options); - - // function to prep the request since it's the same between GET and POST - function makeRequest(mode) { - // If this request has already been used, then we can't reuse it. Throw an error. - if (request) { - throw new Error(REUSE_ERROR); - } - - request = new xhr.XMLHttpRequest(); - - let url = options.url; - // Build the data to be set. For GET requests, we want to append that to - // the URL before opening the request. - let data = makeQueryString(options.content); - if (mode == "GET" && data) { - // If the URL already has ? in it, then we want to just use & - url = url + (/\?/.test(url) ? "&" : "?") + data; - } - - // open the request - request.open(mode, url); - - // request header must be set after open, but before send - request.setRequestHeader("Content-Type", options.contentType); - - // set other headers - for (let k in options.headers) { - request.setRequestHeader(k, options.headers[k]); - } - - // set overrideMimeType - if (options.overrideMimeType) { - request.overrideMimeType(options.overrideMimeType); - } - - // handle the readystate, create the response, and call the callback - request.onreadystatechange = function () { - if (request.readyState == 4) { - response = new Response(request); - errors.catchAndLog(function () { - self._emit('complete', response); - })(); - } - } - - // actually send the request. we only want to send data on POST requests - request.send(mode == "POST" ? data : null); - } - - // Map these setters/getters to the options - ["url", "headers", "content", "contentType"].forEach(function (k) { - _public.__defineGetter__(k, function () options[k]); - _public.__defineSetter__(k, function (v) { - // This will automatically rethrow errors from apiUtils.validateOptions. - return options[k] = validator.validateSingleOption(k, v); - }); - }); - - // response should be available as a getter - _public.__defineGetter__("response", function () response); - - _public.get = function () { - makeRequest("GET"); - return this; - }; - - _public.post = function () { - makeRequest("POST"); - return this; - }; - - return _public; -} -exports.Request = Request; - -// Converts an object of unordered key-vals to a string that can be passed -// as part of a request -function makeQueryString(content) { - // Explicitly return null if we have null, and empty string, or empty object. - if (!content) { - return null; - } - - // If content is already a string, just return it as is. - if (typeof(content) == "string") { - return content; - } - - // At this point we have a k:v object. Iterate over it and encode each value. - // Arrays and nested objects will get encoded as needed. For example... - // - // { foo: [1, 2, { omg: "bbq", "all your base!": "are belong to us" }], bar: "baz" } - // - // will be encoded as - // - // foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz - // - // Keys (including "[" and "]") and values will be encoded with - // fixedEncodeURIComponent before returning. - // - // Execution was inspired by jQuery, but some details have changed and numeric - // array keys are included (whereas they are not in jQuery). - - let encodedContent = []; - function add(key, val) { - encodedContent.push(fixedEncodeURIComponent(key) + "=" + - fixedEncodeURIComponent(val)); - } - - function make(key, val) { - if (typeof(val) === "object" && val !== null) { - for ([k, v] in Iterator(val)) { - make(key + "[" + k + "]", v); - } - } - else { - add(key, val) - } - } - for ([k, v] in Iterator(content)) { - make(k, v); - } - return encodedContent.join("&"); - - //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had - // trouble getting that working. It would also be nice to stay - // backwards-compat as long as possible. Keeping this in for now... - // let formData = Cc["@mozilla.org/files/formdata;1"]. - // createInstance(Ci.nsIDOMFormData); - // for ([k, v] in Iterator(content)) { - // formData.append(k, v); - // } - // return formData; -} - - -// encodes a string safely for application/x-www-form-urlencoded -// adheres to RFC 3986 -// see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/encodeURIComponent -function fixedEncodeURIComponent (str) { - return encodeURIComponent(str).replace(/%20/g, "+").replace(/!/g, "%21"). - replace(/'/g, "%27").replace(/\(/g, "%28"). - replace(/\)/g, "%29").replace(/\*/g, "%2A"); -} - -function Response(request) { - // Define the straight mappings of our value to original request value - xpcom.utils.defineLazyGetter(this, "text", function () request.responseText); - xpcom.utils.defineLazyGetter(this, "xml", function () { - throw new Error("Sorry, the 'xml' property is no longer available. " + - "see bug 611042 for more information."); - }); - xpcom.utils.defineLazyGetter(this, "status", function () request.status); - xpcom.utils.defineLazyGetter(this, "statusText", function () request.statusText); - - // this.json should be the JS object, so we need to attempt to parse it. - xpcom.utils.defineLazyGetter(this, "json", function () { - let _json = null; - try { - _json = JSON.parse(this.text); - } - catch (e) {} - return _json; - }); - - // this.headers also should be a JS object, so we need to split up the raw - // headers string provided by the request. - xpcom.utils.defineLazyGetter(this, "headers", function () { - let _headers = {}; - let lastKey; - // Since getAllResponseHeaders() will return null if there are no headers, - // defend against it by defaulting to "" - let rawHeaders = request.getAllResponseHeaders() || ""; - rawHeaders.split("\n").forEach(function (h) { - // According to the HTTP spec, the header string is terminated by an empty - // line, so we can just skip it. - if (!h.length) { - return; - } - - let index = h.indexOf(":"); - // The spec allows for leading spaces, so instead of assuming a single - // leading space, just trim the values. - let key = h.substring(0, index).trim(), - val = h.substring(index + 1).trim(); - - // For empty keys, that means that the header value spanned multiple lines. - // In that case we should append the value to the value of lastKey with a - // new line. We'll assume lastKey will be set because there should never - // be an empty key on the first pass. - if (key) { - _headers[key] = val; - lastKey = key; - } - else { - _headers[lastKey] += "\n" + val; - } - }); - return _headers; - }) -} - -// apiUtils.validateOptions doesn't give the ability to easily validate single -// options, so this is a wrapper that provides that ability. -function OptionsValidator(rules) { - this.rules = rules; - - this.validateOptions = function (options) { - return apiUtils.validateOptions(options, this.rules); - } - - this.validateSingleOption = function (field, value) { - // We need to create a single rule object from our listed rules. To avoid - // JavaScript String warnings, check for the field & default to an empty object. - let singleRule = {}; - if (field in this.rules) { - singleRule[field] = this.rules[field]; - } - let singleOption = {}; - singleOption[field] = value; - // This should throw if it's invalid, which will bubble up & out. - return apiUtils.validateOptions(singleOption, singleRule)[field]; - } -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/selection.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/selection.js deleted file mode 100644 index 48db7fc..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/selection.js +++ /dev/null @@ -1,448 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Eric H. Jung <eric.jung@yahoo.com> - * Irakli Gozalishivili <gozala@mozilla.com> - * Matteo Ferretti <zer0@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The selection module currently supports only Firefox. In the future ", - "we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information." - ].join("")); -} - -let { Ci } = require("chrome"), - { setTimeout } = require("api-utils/timer"), - { EventEmitter } = require("api-utils/events"); - -// The selection type HTML -const HTML = 0x01; - -// The selection type TEXT -const TEXT = 0x02; - -// The selection type DOM (internal use only) -const DOM = 0x03; - -// A more developer-friendly message than the caught exception when is not -// possible change a selection. -const ERR_CANNOT_CHANGE_SELECTION = - "It isn't possible to change the selection, as there isn't currently a selection"; - -/** - * Creates an object from which a selection can be set, get, etc. Each - * object has an associated with a range number. Range numbers are the - * 0-indexed counter of selection ranges as explained at - * https://developer.mozilla.org/en/DOM/Selection. - * - * @param rangeNumber - * The zero-based range index into the selection - */ -function Selection(rangeNumber) { - - // In order to hide the private rangeNumber argument from API consumers while - // still enabling Selection getters/setters to access it, the getters/setters - // are defined as lexical closures in the Selector constructor. - - this.__defineGetter__("text", function () getSelection(TEXT, rangeNumber)); - this.__defineSetter__("text", function (str) setSelection(str, rangeNumber)); - - this.__defineGetter__("html", function () getSelection(HTML, rangeNumber)); - this.__defineSetter__("html", function (str) setSelection(str, rangeNumber)); - - this.__defineGetter__("isContiguous", function () { - let sel = getSelection(DOM); - - // If there are multiple ranges, the selection is definitely discontiguous. - // It returns `false` also if there are no selection; and `true` if there is - // a single non empty range, or a selection in a text field - contiguous or - // not (text field selection APIs doesn't support multiple selections). - - if (sel.rangeCount > 1) - return false; - - return !!(safeGetRange(sel, 0) || getElementWithSelection()); - }); -} - -require("api-utils/xpcom").utils.defineLazyServiceGetter(this, "windowMediator", - "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"); - -/** - * Returns the most recent content window - */ -function context() { - // Overlay names should probably go into the xul-app module instead of here - return windowMediator.getMostRecentWindow("navigator:browser").document. - commandDispatcher.focusedWindow; -} - -/** - * Returns the current selection from most recent content window. Depending on - * the specified |type|, the value returned can be a string of text, stringified - * HTML, or a DOM selection object as described at - * https://developer.mozilla.org/en/DOM/Selection. - * - * @param type - * Specifies the return type of the selection. Valid values are the one - * of the constants HTML, TEXT, or DOM. - * - * @param rangeNumber - * Specifies the zero-based range index of the returned selection. - */ -function getSelection(type, rangeNumber) { - let window, selection; - try { - window = context(); - selection = window.getSelection(); - } - catch (e) { - return null; - } - - // Get the selected content as the specified type - if (type == DOM) - return selection; - else if (type == TEXT) { - let range = safeGetRange(selection, rangeNumber); - - if (range) - return range.toString(); - - let node = getElementWithSelection(window); - - if (!node) - return null; - - return node.value.substring(node.selectionStart, node.selectionEnd); - } - else if (type == HTML) { - let range = safeGetRange(selection, rangeNumber); - // Another way, but this includes the xmlns attribute for all elements in - // Gecko 1.9.2+ : - // return Cc["@mozilla.org/xmlextras/xmlserializer;1"]. - // createInstance(Ci.nsIDOMSerializer).serializeToSTring(range. - // cloneContents()); - if (!range) - return null; - let node = window.document.createElement("span"); - node.appendChild(range.cloneContents()); - return node.innerHTML; - } - throw new Error("Type " + type + " is unrecognized."); -} - -/** - * Returns the specified range in a selection without throwing an exception. - * - * @param selection - * A selection object as described at - * https://developer.mozilla.org/en/DOM/Selection - * - * @param rangeNumber - * Specifies the zero-based range index of the returned selection. - */ -function safeGetRange(selection, rangeNumber) { - try { - let range = selection.getRangeAt(rangeNumber); - if (!range || range.toString() == "") - return null; - return range; - } - catch (e) { - return null; - } -} - -/** - * Returns a reference of the DOM's active element for the window given, if it - * supports the text field selection API and has a text selected. - * - * Note: - * we need this method because window.getSelection doesn't return a selection - * for text selected in a form field (see bug 85686) - * - * @param {nsIWindow} [window] - * A reference to a window - */ -function getElementWithSelection(window) { - let element; - - try { - element = (window || context()).document.activeElement; - } - catch (e) { - element = null; - } - - if (!element) - return null; - - let { value, selectionStart, selectionEnd } = element; - - let hasSelection = typeof value === "string" && - !isNaN(selectionStart) && - !isNaN(selectionEnd) && - selectionStart !== selectionEnd; - - return hasSelection ? element : null; -} -/** - * Sets the current selection of the most recent content document by changing - * the existing selected text/HTML range to the specified value. - * - * @param val - * The value for the new selection - * - * @param rangeNumber - * The zero-based range index of the selection to be set - * - */ -function setSelection(val, rangeNumber) { - // Make sure we have a window context & that there is a current selection. - // Selection cannot be set unless there is an existing selection. - let window, selection; - - try { - window = context(); - selection = window.getSelection(); - } - catch (e) { - throw new Error(ERR_CANNOT_CHANGE_SELECTION); - } - - let range = safeGetRange(selection, rangeNumber); - - if (range) { - // Get rid of the current selection and insert our own - range.deleteContents(); - let node = window.document.createElement("span"); - range.surroundContents(node); - - // Some relevant JEP-111 requirements: - - // Setting the text property replaces the selection with the value to - // which the property is set and sets the html property to the same value - // to which the text property is being set. - - // Setting the html property replaces the selection with the value to - // which the property is set and sets the text property to the text version - // of the HTML value. - - // This sets both the HTML and text properties. - node.innerHTML = val; - } else { - let node = getElementWithSelection(window); - - if (!node) - throw new Error(ERR_CANNOT_CHANGE_SELECTION); - - let { value, selectionStart, selectionEnd } = node; - - let newSelectionEnd = selectionStart + val.length; - - node.value = value.substring(0, selectionStart) + - val + - value.substring(selectionEnd, value.length); - - node.setSelectionRange(selectionStart, newSelectionEnd); - } -} - -function onLoad(event) { - SelectionListenerManager.onLoad(event); -} - -function onUnload(event) { - SelectionListenerManager.onUnload(event); -} - -function onSelect() { - SelectionListenerManager.onSelect(); -} - -let SelectionListenerManager = { - QueryInterface: require("api-utils/xpcom").utils. - generateQI([Ci.nsISelectionListener]), - - // The collection of listeners wanting to be notified of selection changes - listeners: EventEmitter.compose({ - emit: function emit(type) this._emitOnObject(exports, type), - off: function() this._removeAllListeners.apply(this, arguments) - })(), - /** - * This is the nsISelectionListener implementation. This function is called - * by Gecko when a selection is changed interactively. - * - * We only pay attention to the SELECTALL, KEYPRESS, and MOUSEUP selection - * reasons. All reasons are listed here: - * - * http://mxr.mozilla.org/mozilla1.9.2/source/content/base/public/ - * nsISelectionListener.idl - * - * The other reasons (NO_REASON, DRAG_REASON, MOUSEDOWN_REASON) aren't - * applicable to us. - */ - notifySelectionChanged: function notifySelectionChanged(document, selection, - reason) { - if (!["SELECTALL", "KEYPRESS", "MOUSEUP"].some(function(type) reason & - Ci.nsISelectionListener[type + "_REASON"]) || selection.toString() == "") - return; - - this.onSelect(); - }, - - onSelect : function onSelect() { - setTimeout(this.listeners.emit, 0, "select"); - }, - - /** - * Part of the Tracker implementation. This function is called by the - * tabs module when a browser is being tracked. Often, that means a new tab - * has been opened, but it can also mean an addon has been installed while - * tabs are already opened. In that case, this function is called for those - * already-opened tabs. - * - * @param browser - * The browser being tracked - */ - onTrack: function onTrack(browser) { - browser.addEventListener("load", onLoad, true); - browser.addEventListener("unload", onUnload, true); - }, - - onLoad: function onLoad(event) { - // Nothing to do without a useful window - let window = event.target.defaultView; - if (!window) - return; - - // Wrap the add selection call with some number of setTimeout 0 because some - // reason it's possible to add a selection listener "too early". 2 sometimes - // works for gmail, and more consistently with 3, so make it 5 to be safe. - let count = 0; - let self = this; - function wrap(count, func) { - if (count-- > 0) - require("api-utils/timer").setTimeout(wrap, 0); - else - self.addSelectionListener(window); - } - wrap(); - }, - - addSelectionListener: function addSelectionListener(window) { - if (window.jetpack_core_selection_listener) - return; - let selection = window.getSelection(); - if (selection instanceof Ci.nsISelectionPrivate) - selection.addSelectionListener(this); - - // nsISelectionListener implementation seems not fire a notification if - // a selection is in a text field, therefore we need to add a listener to - // window.onselect, that is fired only for text fields. - // https://developer.mozilla.org/en/DOM/window.onselect - window.addEventListener("select", onSelect, true); - - window.jetpack_core_selection_listener = true; - }, - - onUnload: function onUnload(event) { - // Nothing to do without a useful window - let window = event.target.defaultView; - if (!window) - return; - this.removeSelectionListener(window); - this.listeners.off('error'); - this.listeners.off('selection'); - }, - - removeSelectionListener: function removeSelectionListener(window) { - if (!window.jetpack_core_selection_listener) - return; - let selection = window.getSelection(); - if (selection instanceof Ci.nsISelectionPrivate) - selection.removeSelectionListener(this); - - window.removeEventListener("select", onSelect); - - window.jetpack_core_selection_listener = false; - }, - - /** - * Part of the TabTracker implementation. This function is called by the - * tabs module when a browser is being untracked. Usually, that means a tab - * has been closed. - * - * @param browser - * The browser being untracked - */ - onUntrack: function onUntrack(browser) { - browser.removeEventListener("load", onLoad, true); - browser.removeEventListener("unload", onUnload, true); - } -}; -SelectionListenerManager.listeners.on('error', console.error); - -/** - * Install |SelectionListenerManager| as tab tracker in order to watch - * tab opening/closing - */ -require("api-utils/tab-browser").Tracker(SelectionListenerManager); - -/** - * Exports an iterator so that discontiguous selections can be iterated. - * - * If discontiguous selections are in a text field, only the first one - * is returned because the text field selection APIs doesn't support - * multiple selections. - */ -exports.__iterator__ = function __iterator__() { - let sel = getSelection(DOM); - let rangeCount = sel.rangeCount || (getElementWithSelection() ? 1 : 0); - - for (let i = 0; i < rangeCount; i++) - yield new Selection(i); -}; - -exports.on = SelectionListenerManager.listeners.on; -exports.removeListener = SelectionListenerManager.listeners.removeListener; - -// Export the Selection singleton. Its rangeNumber is always zero. -Selection.call(exports, 0); - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-prefs.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-prefs.js deleted file mode 100644 index c7a059b..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-prefs.js +++ /dev/null @@ -1,107 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Hernan Rodriguez Colmeiro <colmeiro@gmail.com> (Original Author) - * Erik Vold <erikvvold@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const { Cc, Ci } = require("chrome"); -const observers = require("observer-service"); -const { EventEmitter } = require("events"); -const unload = require("unload"); -const prefService = require("preferences-service"); -const { jetpackID } = require("@packaging"); - -const ADDON_BRANCH = "extensions." + jetpackID + "."; -const BUTTON_PRESSED = jetpackID + "-cmdPressed"; - -// XXX Currently, only Firefox implements the inline preferences. -if (!require("xul-app").is("Firefox")) - throw Error("This API is only supported in Firefox"); - -let branch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefService). - getBranch(ADDON_BRANCH). - QueryInterface(Ci.nsIPrefBranch2); - -const events = EventEmitter.compose({ - constructor: function Prefs() { - // Log unhandled errors. - this.on("error", console.exception.bind(console)); - - // Make sure we remove all the listeners - unload.ensure(this); - - this._prefObserver = this._prefObserver.bind(this); - this._buttonObserver = this._buttonObserver.bind(this); - - // Listen to changes in the preferences - branch.addObserver("", this._prefObserver, false); - - // Listen to clicks on buttons - observers.add(BUTTON_PRESSED, this._buttonObserver, this); - }, - _prefObserver: function PrefsPrefObserver(subject, topic, prefName) { - if (topic == "nsPref:changed") { - this._emit(prefName, prefName); - } - }, - _buttonObserver: function PrefsButtonObserver(subject, data) { - this._emit(data); - }, - unload: function manager_unload() { - this._removeAllListeners("error"); - branch.removeObserver("", this._prefObserver); - }, -})(); - -const simple = Proxy.create({ - get: function(receiver, pref) { - return prefService.get(ADDON_BRANCH + pref); - }, - set: function(receiver, pref, val) { - prefService.set(ADDON_BRANCH + pref, val); - }, - delete: function(pref) { - prefService.reset(ADDON_BRANCH + pref); - return true; - }, - has: function(pref) { - return prefService.has(ADDON_BRANCH + pref); - } -}); - -exports.on = events.on; -exports.removeListener = events.removeListener; -exports.prefs = simple; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-storage.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-storage.js deleted file mode 100644 index b719e27..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/simple-storage.js +++ /dev/null @@ -1,263 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -const file = require("api-utils/file"); -const prefs = require("api-utils/preferences-service"); -const jpSelf = require("self"); -const timer = require("api-utils/timer"); -const unload = require("api-utils/unload"); -const { EventEmitter } = require("api-utils/events"); -const { Trait } = require("api-utils/traits"); - -const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod"; -const WRITE_PERIOD_DEFAULT = 300000; // 5 minutes - -const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota"; -const QUOTA_DEFAULT = 5242880; // 5 MiB - -const JETPACK_DIR_BASENAME = "jetpack"; - - -// simpleStorage.storage -exports.__defineGetter__("storage", function () manager.root); -exports.__defineSetter__("storage", function (val) manager.root = val); - -// simpleStorage.quotaUsage -exports.__defineGetter__("quotaUsage", function () manager.quotaUsage); - -// A generic JSON store backed by a file on disk. This should be isolated -// enough to move to its own module if need be... -function JsonStore(options) { - this.filename = options.filename; - this.quota = options.quota; - this.writePeriod = options.writePeriod; - this.onOverQuota = options.onOverQuota; - this.onWrite = options.onWrite; - - unload.ensure(this); - - this.writeTimer = timer.setInterval(this.write.bind(this), - this.writePeriod); -} - -JsonStore.prototype = { - // The store's root. - get root() { - return this.isRootInited ? this._root : {}; - }, - - // Performs some type checking. - set root(val) { - let types = ["array", "boolean", "null", "number", "object", "string"]; - if (types.indexOf(typeof(val)) < 0) { - throw new Error("storage must be one of the following types: " + - types.join(", ")); - } - this._root = val; - return val; - }, - - // True if the root has ever been set (either via the root setter or by the - // backing file's having been read). - get isRootInited() { - return this._root !== undefined; - }, - - // Percentage of quota used, as a number [0, Inf). > 1 implies over quota. - // Undefined if there is no quota. - get quotaUsage() { - return this.quota > 0 ? - JSON.stringify(this.root).length / this.quota : - undefined; - }, - - // Removes the backing file and all empty subdirectories. - purge: function JsonStore_purge() { - try { - // This'll throw if the file doesn't exist. - file.remove(this.filename); - let parentPath = this.filename; - do { - parentPath = file.dirname(parentPath); - // This'll throw if the dir isn't empty. - file.rmdir(parentPath); - } while (file.basename(parentPath) !== JETPACK_DIR_BASENAME); - } - catch (err) {} - }, - - // Initializes the root by reading the backing file. - read: function JsonStore_read() { - try { - let str = file.read(this.filename); - - // Ideally we'd log the parse error with console.error(), but logged - // errors cause tests to fail. Supporting "known" errors in the test - // harness appears to be non-trivial. Maybe later. - this.root = JSON.parse(str); - } - catch (err) { - this.root = {}; - } - }, - - // If the store is under quota, writes the root to the backing file. - // Otherwise quota observers are notified and nothing is written. - write: function JsonStore_write() { - if (this.quotaUsage > 1) - this.onOverQuota(this); - else - this._write(); - }, - - // Cleans up on unload. If unloading because of uninstall, the store is - // purged; otherwise it's written. - unload: function JsonStore_unload(reason) { - timer.clearInterval(this.writeTimer); - this.writeTimer = null; - - if (reason === "uninstall") - this.purge(); - else - this._write(); - }, - - // True if the root is an empty object. - get _isEmpty() { - if (this.root && typeof(this.root) === "object") { - let empty = true; - for (let key in this.root) { - empty = false; - break; - } - return empty; - } - return false; - }, - - // Writes the root to the backing file, notifying write observers when - // complete. If the store is over quota or if it's empty and the store has - // never been written, nothing is written and write observers aren't notified. - _write: function JsonStore__write() { - // Don't write if the root is uninitialized or if the store is empty and the - // backing file doesn't yet exist. - if (!this.isRootInited || (this._isEmpty && !file.exists(this.filename))) - return; - - // If the store is over quota, don't write. The current under-quota state - // should persist. - if (this.quotaUsage > 1) - return; - - // Finally, write. - let stream = file.open(this.filename, "w"); - try { - stream.writeAsync(JSON.stringify(this.root), function writeAsync(err) { - if (err) - console.error("Error writing simple storage file: " + this.filename); - else if (this.onWrite) - this.onWrite(this); - }.bind(this)); - } - catch (err) { - // writeAsync closes the stream after it's done, so only close on error. - stream.close(); - } - } -}; - - -// This manages a JsonStore singleton and tailors its use to simple storage. -// The root of the JsonStore is lazy-loaded: The backing file is only read the -// first time the root's gotten. -let manager = Trait.compose(EventEmitter, Trait.compose({ - jsonStore: null, - - // The filename of the store, based on the profile dir and extension ID. - get filename() { - let storeFile = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties). - get("ProfD", Ci.nsIFile); - storeFile.append(JETPACK_DIR_BASENAME); - storeFile.append(jpSelf.id); - storeFile.append("simple-storage"); - file.mkpath(storeFile.path); - storeFile.append("store.json"); - return storeFile.path; - }, - - get quotaUsage() { - return this.jsonStore.quotaUsage; - }, - - get root() { - if (!this.jsonStore.isRootInited) - this.jsonStore.read(); - return this.jsonStore.root; - }, - - set root(val) { - return this.jsonStore.root = val; - }, - - unload: function manager_unload() { - this._removeAllListeners("OverQuota"); - this._removeAllListeners("error"); - }, - - constructor: function manager_constructor() { - // Log unhandled errors. - this.on("error", console.exception.bind(console)); - unload.ensure(this); - - this.jsonStore = new JsonStore({ - filename: this.filename, - writePeriod: prefs.get(WRITE_PERIOD_PREF, WRITE_PERIOD_DEFAULT), - quota: prefs.get(QUOTA_PREF, QUOTA_DEFAULT), - onOverQuota: this._emitOnObject.bind(this, exports, "OverQuota") - }); - } -}))(); - -exports.on = manager.on; -exports.removeListener = manager.removeListener; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/tabs.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/tabs.js deleted file mode 100644 index 81681d6..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/tabs.js +++ /dev/null @@ -1,62 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dietrich Ayala <dietrich@mozilla.com> (Original author) - * Felipe Gomes <felipc@gmail.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The tabs module currently supports only Firefox. In the future ", - "we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information." - ].join("")); -} - -const { browserWindows } = require("./windows"); -const { tabs } = require("api-utils/windows/tabs"); - -Object.defineProperties(tabs, { - open: { value: function open(options) { - if (options.inNewWindow) - // `tabs` option is under review and may be removed. - return browserWindows.open({ tabs: [ options ] }); - // Open in active window if new window was not required. - return browserWindows.activeWindow.tabs.open(options); - }} -}); -// It's a hack but we will be able to remove it once will implement CommonJS -// feature that would allow us to override exports. -exports.__proto__ = tabs; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/timers.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/timers.js deleted file mode 100644 index 9373dea..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/timers.js +++ /dev/null @@ -1,40 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// This module just proxies to the low level equivalent "timer" in "api-utils". -module.exports = require("api-utils/timer"); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/widget.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/widget.js deleted file mode 100644 index 9a169f4..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/widget.js +++ /dev/null @@ -1,947 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dietrich Ayala <dietrich@mozilla.com> (Original Author) - * Drew Willcoxon <adw@mozilla.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * Alexandre Poirot <apoirot@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc, Ci} = require("chrome"); - -// Widget content types -const CONTENT_TYPE_URI = 1; -const CONTENT_TYPE_HTML = 2; -const CONTENT_TYPE_IMAGE = 3; - -const ERR_CONTENT = "No content or contentURL property found. Widgets must " - + "have one or the other.", - ERR_LABEL = "The widget must have a non-empty label property.", - ERR_ID = "You have to specify a unique value for the id property of " + - "your widget in order for the application to remember its " + - "position.", - ERR_DESTROYED = "The widget has been destroyed and can no longer be used."; - -// Supported events, mapping from DOM event names to our event names -const EVENTS = { - "click": "click", - "mouseover": "mouseover", - "mouseout": "mouseout", -}; - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The widget module currently supports only Firefox. In the future ", - "it will support other applications. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information." - ].join("")); -} - -const { validateOptions } = require("api-utils/api-utils"); -const panels = require("./panel"); -const { EventEmitter, EventEmitterTrait } = require("api-utils/events"); -const { Trait } = require("api-utils/traits"); -const LightTrait = require('api-utils/light-traits').Trait; -const { Loader, Symbiont } = require("api-utils/content"); -const timer = require("api-utils/timer"); -const { Cortex } = require('api-utils/cortex'); -const windowsAPI = require("./windows"); -const unload = require("api-utils/unload"); - -// Data types definition -const valid = { - number: { is: ["null", "undefined", "number"] }, - string: { is: ["null", "undefined", "string"] }, - id: { - is: ["string"], - ok: function (v) v.length > 0, - msg: ERR_ID, - readonly: true - }, - label: { - is: ["string"], - ok: function (v) v.length > 0, - msg: ERR_LABEL - }, - panel: { - is: ["null", "undefined", "object"], - ok: function(v) !v || v instanceof panels.Panel - }, - width: { - is: ["null", "undefined", "number"], - map: function (v) { - if (null === v || undefined === v) v = 16; - return v; - }, - defaultValue: 16 - }, - allow: { - is: ["null", "undefined", "object"], - map: function (v) { - if (!v) v = { script: true }; - return v; - }, - get defaultValue() ({ script: true }) - }, -}; - -// Widgets attributes definition -let widgetAttributes = { - label: valid.label, - id: valid.id, - tooltip: valid.string, - width: valid.width, - content: valid.string, - panel: valid.panel, - allow: valid.allow -}; - -// Import data definitions from loader, but don't compose with it as Model -// functions allow us to recreate easily all Loader code. -let loaderAttributes = require("api-utils/content/loader").validationAttributes; -for (let i in loaderAttributes) - widgetAttributes[i] = loaderAttributes[i]; - -widgetAttributes.contentURL.optional = true; - -// Widgets public events list, that are automatically binded in options object -const WIDGET_EVENTS = [ - "click", - "mouseover", - "mouseout", - "error", - "message", - "attach" -]; - -// `Model` utility functions that help creating these various Widgets objects -let model = { - - // Validate one attribute using api-utils.js:validateOptions function - _validate: function _validate(name, suspect, validation) { - let $1 = {}; - $1[name] = suspect; - let $2 = {}; - $2[name] = validation; - return validateOptions($1, $2)[name]; - }, - - /** - * This method has two purposes: - * 1/ Validate and define, on a given object, a set of attribute - * 2/ Emit a "change" event on this object when an attribute is changed - * - * @params {Object} object - * Object on which we can bind attributes on and watch for their changes. - * This object must have an EventEmitter interface, or, at least `_emit` - * method - * @params {Object} attrs - * Dictionary of attributes definition following api-utils:validateOptions - * scheme - * @params {Object} values - * Dictionary of attributes default values - */ - setAttributes: function setAttributes(object, attrs, values) { - let properties = {}; - for (let name in attrs) { - let value = values[name]; - let req = attrs[name]; - - // Retrieve default value from typedef if the value is not defined - if ((typeof value == "undefined" || value == null) && req.defaultValue) - value = req.defaultValue; - - // Check for valid value if value is defined or mandatory - if (!req.optional || typeof value != "undefined") - value = model._validate(name, value, req); - - // In any case, define this property on `object` - let property = null; - if (req.readonly) { - property = { - value: value, - writable: false, - enumerable: true, - configurable: false - }; - } - else { - property = model._createWritableProperty(name, value); - } - - properties[name] = property; - } - Object.defineProperties(object, properties); - }, - - // Generate ES5 property definition for a given attribute - _createWritableProperty: function _createWritableProperty(name, value) { - return { - get: function () { - return value; - }, - set: function (newValue) { - value = newValue; - // The main goal of all this Model stuff is here: - // We want to forward all changes to some listeners - this._emit("change", name, value); - }, - enumerable: true, - configurable: false - }; - }, - - /** - * Automagically register listeners in options dictionary - * by detecting listener attributes with name starting with `on` - * - * @params {Object} object - * Target object that need to follow EventEmitter interface, or, at least, - * having `on` method. - * @params {Array} events - * List of events name to automatically bind. - * @params {Object} listeners - * Dictionary of event listener functions to register. - */ - setEvents: function setEvents(object, events, listeners) { - for (let i = 0, l = events.length; i < l; i++) { - let name = events[i]; - let onName = "on" + name[0].toUpperCase() + name.substr(1); - if (!listeners[onName]) - continue; - object.on(name, listeners[onName].bind(object)); - } - } - -}; - - -/** - * Main Widget class: entry point of the widget API - * - * Allow to control all widget across all existing windows with a single object. - * Widget.getView allow to retrieve a WidgetView instance to control a widget - * specific to one window. - */ -const WidgetTrait = LightTrait.compose(EventEmitterTrait, LightTrait({ - - _initWidget: function _initWidget(options) { - model.setAttributes(this, widgetAttributes, options); - - browserManager.validate(this); - - // We must have at least content or contentURL defined - if (!(this.content || this.contentURL)) - throw new Error(ERR_CONTENT); - - this._views = []; - - // Set tooltip to label value if we don't have tooltip defined - if (!this.tooltip) - this.tooltip = this.label; - - model.setEvents(this, WIDGET_EVENTS, options); - - this.on('change', this._onChange.bind(this)); - - let self = this; - this._port = EventEmitterTrait.create({ - emit: function () { - let args = arguments; - self._views.forEach(function(v) v.port.emit.apply(v.port, args)); - } - }); - // expose wrapped port, that exposes only public properties. - this._port._public = Cortex(this._port); - - // Register this widget to browser manager in order to create new widget on - // all new windows - browserManager.addItem(this); - }, - - _onChange: function _onChange(name, value) { - // Set tooltip to label value if we don't have tooltip defined - if (name == 'tooltip' && !value) { - // we need to change tooltip again in order to change the value of the - // attribute itself - this.tooltip = this.label; - return; - } - - // Forward attributes changes to WidgetViews - if (['width', 'tooltip', 'content', 'contentURL'].indexOf(name) != -1) { - this._views.forEach(function(v) v[name] = value); - } - }, - - _onEvent: function _onEvent(type, eventData) { - this._emit(type, eventData); - }, - - _createView: function _createView() { - // Create a new WidgetView instance - let view = WidgetView(this); - - // Keep a reference to it - this._views.push(view); - - // Emit an `attach` event with a WidgetView instance without private attrs - this._emit("attach", view._public); - - return view; - }, - - // a WidgetView instance is destroyed - _onViewDestroyed: function _onViewDestroyed(view) { - let idx = this._views.indexOf(view); - this._views.splice(idx, 1); - }, - - /** - * Called on browser window closed, to destroy related WidgetViews - * @params {ChromeWindow} window - * Window that has been closed - */ - _onWindowClosed: function _onWindowClosed(window) { - for each (let view in this._views) { - if (view._isInChromeWindow(window)) { - view.destroy(); - break; - } - } - }, - - /** - * Get the WidgetView instance related to a BrowserWindow instance - * @params {BrowserWindow} window - * BrowserWindow reference from "windows" module - */ - getView: function getView(window) { - for each (let view in this._views) { - if (view._isInWindow(window)) { - return view._public; - } - } - return null; - }, - - get port() this._port._public, - set port(v) {}, // Work around Cortex failure with getter without setter - // See bug 653464 - _port: null, - - postMessage: function postMessage(message) { - this._views.forEach(function(v) v.postMessage(message)); - }, - - destroy: function destroy() { - if (this.panel) - this.panel.destroy(); - - // Dispatch destroy calls to views - // we need to go backward as we remove items from this array in - // _onViewDestroyed - for (let i = this._views.length - 1; i >= 0; i--) - this._views[i].destroy(); - - // Unregister widget to stop creating it over new windows - // and allow creation of new widget with same id - browserManager.removeItem(this); - } - -})); - -// Widget constructor -const Widget = function Widget(options) { - let w = WidgetTrait.create(Widget.prototype); - w._initWidget(options); - - // Return a Cortex of widget in order to hide private attributes like _onEvent - let _public = Cortex(w); - unload.ensure(_public, "destroy"); - return _public; -} -exports.Widget = Widget; - - - -/** - * WidgetView is an instance of a widget for a specific window. - * - * This is an external API that can be retrieved by calling Widget.getView or - * by watching `attach` event on Widget. - */ -const WidgetViewTrait = LightTrait.compose(EventEmitterTrait, LightTrait({ - - // Reference to the matching WidgetChrome - // set right after constructor call - _chrome: null, - - // Public interface of the WidgetView, passed in `attach` event or in - // Widget.getView - _public: null, - - _initWidgetView: function WidgetView__initWidgetView(baseWidget) { - this._baseWidget = baseWidget; - - model.setAttributes(this, widgetAttributes, baseWidget); - - this.on('change', this._onChange.bind(this)); - - let self = this; - this._port = EventEmitterTrait.create({ - emit: function () { - if (!self._chrome) - throw new Error(ERR_DESTROYED); - self._chrome.update(self._baseWidget, "emit", arguments); - } - }); - // expose wrapped port, that exposes only public properties. - this._port._public = Cortex(this._port); - - this._public = Cortex(this); - }, - - _onChange: function WidgetView__onChange(name, value) { - if (name == 'tooltip' && !value) { - this.tooltip = this.label; - return; - } - - // Forward attributes changes to WidgetChrome instance - if (['width', 'tooltip', 'content', 'contentURL'].indexOf(name) != -1) { - this._chrome.update(this._baseWidget, name, value); - } - }, - - _onEvent: function WidgetView__onEvent(type, eventData, domNode) { - // Dispatch event in view - this._emit(type, eventData); - - // And forward it to the main Widget object - if ("click" == type || type.indexOf("mouse") == 0) - this._baseWidget._onEvent(type, this._public); - else - this._baseWidget._onEvent(type, eventData); - - // Special case for click events: if the widget doesn't have a click - // handler, but it does have a panel, display the panel. - if ("click" == type && !this._listeners("click").length && this.panel) - this.panel.show(domNode); - }, - - _isInWindow: function WidgetView__isInWindow(window) { - return windowsAPI.BrowserWindow({ - window: this._chrome.window - }) == window; - }, - - _isInChromeWindow: function WidgetView__isInChromeWindow(window) { - return this._chrome.window == window; - }, - - _onPortEvent: function WidgetView__onPortEvent(args) { - let port = this._port; - port._emit.apply(port, args); - let basePort = this._baseWidget._port; - basePort._emit.apply(basePort, args); - }, - - get port() this._port._public, - set port(v) {}, // Work around Cortex failure with getter without setter - // See bug 653464 - _port: null, - - postMessage: function WidgetView_postMessage(message) { - if (!this._chrome) - throw new Error(ERR_DESTROYED); - this._chrome.update(this._baseWidget, "postMessage", message); - }, - - destroy: function WidgetView_destroy() { - this._chrome.destroy(); - delete this._chrome; - this._baseWidget._onViewDestroyed(this); - this._emit("detach"); - } - -})); - -const WidgetView = function WidgetView(baseWidget) { - let w = WidgetViewTrait.create(WidgetView.prototype); - w._initWidgetView(baseWidget); - return w; -} - - - -/** - * Keeps track of all browser windows. - * Exposes methods for adding/removing widgets - * across all open windows (and future ones). - * Create a new instance of BrowserWindow per window. - */ -let browserManager = { - items: [], - windows: [], - - // Registers the manager to listen for window openings and closings. Note - // that calling this method can cause onTrack to be called immediately if - // there are open windows. - init: function () { - let windowTracker = new (require("api-utils/window-utils").WindowTracker)(this); - unload.ensure(windowTracker); - }, - - // Registers a window with the manager. This is a WindowTracker callback. - onTrack: function browserManager_onTrack(window) { - if (this._isBrowserWindow(window)) { - let win = new BrowserWindow(window); - win.addItems(this.items); - this.windows.push(win); - } - }, - - // Unregisters a window from the manager. It's told to undo all - // modifications. This is a WindowTracker callback. Note that when - // WindowTracker is unloaded, it calls onUntrack for every currently opened - // window. The browserManager therefore doesn't need to specially handle - // unload itself, since unloading the browserManager means untracking all - // currently opened windows. - onUntrack: function browserManager_onUntrack(window) { - if (this._isBrowserWindow(window)) { - this.items.forEach(function(i) i._onWindowClosed(window)); - for (let i = 0; i < this.windows.length; i++) { - if (this.windows[i].window == window) { - this.windows.splice(i, 1)[0]; - return; - } - } - - } - }, - - // Used to validate widget by browserManager before adding it, - // in order to check input very early in widget constructor - validate : function (item) { - let idx = this.items.indexOf(item); - if (idx > -1) - throw new Error("The widget " + item + " has already been added."); - if (item.id) { - let sameId = this.items.filter(function(i) i.id == item.id); - if (sameId.length > 0) - throw new Error("This widget ID is already used: " + item.id); - } else { - item.id = this.items.length; - } - }, - - // Registers an item with the manager. It's added to all currently registered - // windows, and when new windows are registered it will be added to them, too. - addItem: function browserManager_addItem(item) { - this.items.push(item); - this.windows.forEach(function (w) w.addItems([item])); - }, - - // Unregisters an item from the manager. It's removed from all windows that - // are currently registered. - removeItem: function browserManager_removeItem(item) { - let idx = this.items.indexOf(item); - if (idx > -1) - this.items.splice(idx, 1); - }, - - _isBrowserWindow: function browserManager__isBrowserWindow(win) { - let winType = win.document.documentElement.getAttribute("windowtype"); - return winType === "navigator:browser"; - } -}; - - - -/** - * Keeps track of a single browser window. - * - * This is where the core of how a widget's content is added to a window lives. - */ -function BrowserWindow(window) { - this.window = window; - this.doc = window.document; -} - -BrowserWindow.prototype = { - - // Adds an array of items to the window. - addItems: function BW_addItems(items) { - items.forEach(this._addItemToWindow, this); - }, - - _addItemToWindow: function BW__addItemToWindow(baseWidget) { - // Create a WidgetView instance - let widget = baseWidget._createView(); - - // Create a WidgetChrome instance - let item = new WidgetChrome({ - widget: widget, - doc: this.doc, - window: this.window - }); - - widget._chrome = item; - - this._insertNodeInToolbar(item.node); - - // We need to insert Widget DOM Node before finishing widget view creation - // (because fill creates an iframe and tries to access its docShell) - item.fill(); - }, - - _insertNodeInToolbar: function BW__insertNodeInToolbar(node) { - // Add to the customization palette - let toolbox = this.doc.getElementById("navigator-toolbox"); - let palette = toolbox.palette; - palette.appendChild(node); - - // Search for widget toolbar by reading toolbar's currentset attribute - let container = null; - let toolbars = this.doc.getElementsByTagName("toolbar"); - let id = node.getAttribute("id"); - for (let i = 0, l = toolbars.length; i < l; i++) { - let toolbar = toolbars[i]; - if (toolbar.getAttribute("currentset").indexOf(id) == -1) - continue; - container = toolbar; - } - - // if widget isn't in any toolbar, add it to the addon-bar - // TODO: we may want some "first-launch" module to do this only on very - // first execution - if (!container) { - container = this.doc.getElementById("addon-bar"); - // TODO: find a way to make the following code work when we use "cfx run": - // http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#8586 - // until then, force display of addon bar directly from sdk code - // https://bugzilla.mozilla.org/show_bug.cgi?id=627484 - if (container.collapsed) - this.window.toggleAddonBar(); - } - - // Now retrieve a reference to the next toolbar item - // by reading currentset attribute on the toolbar - let nextNode = null; - let currentSet = container.getAttribute("currentset"); - let ids = (currentSet == "__empty") ? [] : currentSet.split(","); - let idx = ids.indexOf(id); - if (idx != -1) { - for (let i = idx; i < ids.length; i++) { - nextNode = this.doc.getElementById(ids[i]); - if (nextNode) - break; - } - } - - // Finally insert our widget in the right toolbar and in the right position - container.insertItem(id, nextNode, null, false); - - // Update DOM in order to save position if we remove/readd the widget - container.setAttribute("currentset", container.currentSet); - // Save DOM attribute in order to save position on new window opened - this.window.document.persist(container.id, "currentset"); - } -} - - -/** - * Final Widget class that handles chrome DOM Node: - * - create initial DOM nodes - * - receive instruction from WidgetView through update method and update DOM - * - watch for DOM events and forward them to WidgetView - */ -function WidgetChrome(options) { - this.window = options.window; - this._doc = options.doc; - this._widget = options.widget; - this._symbiont = null; // set later - this.node = null; // set later - - this._createNode(); -} - -// Update a property of a widget. -WidgetChrome.prototype.update = function WC_update(updatedItem, property, value) { - switch(property) { - case "contentURL": - case "content": - this.setContent(); - break; - case "width": - this.node.style.minWidth = value + "px"; - this.node.querySelector("iframe").style.width = value + "px"; - break; - case "tooltip": - this.node.setAttribute("tooltiptext", value); - break; - case "postMessage": - this._symbiont.postMessage(value); - break; - case "emit": - let port = this._symbiont.port; - port.emit.apply(port, value); - break; - } -} - -// Add a widget to this window. -WidgetChrome.prototype._createNode = function WC__createNode() { - // XUL element container for widget - let node = this._doc.createElement("toolbaritem"); - let guid = require("api-utils/xpcom").makeUuid().toString(); - - // Temporary work around require("self") failing on unit-test execution ... - let jetpackID = "testID"; - try { - jetpackID = require("self").id; - } catch(e) {} - - // Compute an unique and stable widget id with jetpack id and widget.id - let id = "widget:" + jetpackID + "-" + this._widget.id; - node.setAttribute("id", id); - node.setAttribute("label", this._widget.label); - node.setAttribute("tooltiptext", this._widget.tooltip); - node.setAttribute("align", "center"); - - // TODO move into a stylesheet, configurable by consumers. - // Either widget.style, exposing the style object, or a URL - // (eg, can load local stylesheet file). - node.setAttribute("style", [ - "overflow: hidden; margin: 1px 2px 1px 2px; padding: 0px;", - "min-height: 16px;", - ].join("")); - - node.style.minWidth = this._widget.width + "px"; - - this.node = node; -} - -// Initial population of a widget's content. -WidgetChrome.prototype.fill = function WC_fill() { - // Create element - var iframe = this._doc.createElement("iframe"); - iframe.setAttribute("type", "content"); - iframe.setAttribute("transparent", "transparent"); - iframe.style.overflow = "hidden"; - iframe.style.height = "16px"; - iframe.style.maxHeight = "16px"; - iframe.style.width = this._widget.width + "px"; - iframe.setAttribute("flex", "1"); - iframe.style.border = "none"; - iframe.style.padding = "0px"; - - // Do this early, because things like contentWindow are null - // until the node is attached to a document. - this.node.appendChild(iframe); - - // add event handlers - this.addEventHandlers(); - - // set content - this.setContent(); -} - -// Get widget content type. -WidgetChrome.prototype.getContentType = function WC_getContentType() { - if (this._widget.content) - return CONTENT_TYPE_HTML; - return (this._widget.contentURL && /\.(jpg|gif|png|ico)$/.test(this._widget.contentURL)) - ? CONTENT_TYPE_IMAGE : CONTENT_TYPE_URI; -} - -// Set widget content. -WidgetChrome.prototype.setContent = function WC_setContent() { - let type = this.getContentType(); - let contentURL = null; - - switch (type) { - case CONTENT_TYPE_HTML: - contentURL = "data:text/html," + encodeURIComponent(this._widget.content); - break; - case CONTENT_TYPE_URI: - contentURL = this._widget.contentURL; - break; - case CONTENT_TYPE_IMAGE: - let imageURL = this._widget.contentURL; - contentURL = "data:text/html,<html><body><img src='" + - encodeURI(imageURL) + "'></body></html>"; - break; - default: - throw new Error("The widget's type cannot be determined."); - } - - let iframe = this.node.firstElementChild; - - let self = this; - // Cleanup previously created symbiont (in case we are update content) - if (this._symbiont) - this._symbiont.destroy(); - - this._symbiont = Trait.compose(Symbiont.resolve({ - _onContentScriptEvent: "_onContentScriptEvent-not-used" - }), { - _onContentScriptEvent: function () { - // Redirect events to WidgetView - self._widget._onPortEvent(arguments); - } - })({ - frame: iframe, - contentURL: contentURL, - contentScriptFile: this._widget.contentScriptFile, - contentScript: this._widget.contentScript, - contentScriptWhen: this._widget.contentScriptWhen, - allow: this._widget.allow, - onMessage: function(message) { - timer.setTimeout(function() { - self._widget._onEvent("message", message); - }, 0); - } - }); -} - -// Detect if document consists of a single image. -WidgetChrome._isImageDoc = function WC__isImageDoc(doc) { - return doc.body.childNodes.length == 1 && - doc.body.firstElementChild && - doc.body.firstElementChild.tagName == "IMG"; -} - -// Set up all supported events for a widget. -WidgetChrome.prototype.addEventHandlers = function WC_addEventHandlers() { - let contentType = this.getContentType(); - - let self = this; - let listener = function(e) { - // Ignore event firings that target the iframe. - if (e.target == self.node.firstElementChild) - return; - - // The widget only supports left-click for now, - // so ignore right-clicks. - if (e.type == "click" && e.button == 2) - return; - - // Proxy event to the widget - timer.setTimeout(function() { - self._widget._onEvent(EVENTS[e.type], null, self.node); - }, 0); - }; - - this.eventListeners = {}; - let iframe = this.node.firstElementChild; - for (let [type, method] in Iterator(EVENTS)) { - iframe.addEventListener(type, listener, true, true); - - // Store listeners for later removal - this.eventListeners[type] = listener; - } - - // On document load, make modifications required for nice default - // presentation. - let self = this; - function loadListener(e) { - // Ignore event firings that target the iframe - if (e.target == iframe) - return; - // Ignore about:blank loads - if (e.type == "load" && e.target.location == "about:blank") - return; - - // We may have had an unload event before that cleaned up the symbiont - if (!self._symbiont) - self.setContent(); - - let doc = e.target; - if (contentType == CONTENT_TYPE_IMAGE || WidgetChrome._isImageDoc(doc)) { - // Force image content to size. - // Add-on authors must size their images correctly. - doc.body.firstElementChild.style.width = self._widget.width + "px"; - doc.body.firstElementChild.style.height = "16px"; - } - - // Allow all content to fill the box by default. - doc.body.style.margin = "0"; - } - iframe.addEventListener("load", loadListener, true); - this.eventListeners["load"] = loadListener; - - // Register a listener to unload symbiont if the toolbaritem is moved - // on user toolbars customization - function unloadListener(e) { - if (e.target.location == "about:blank") - return; - self._symbiont.destroy(); - self._symbiont = null; - // This may fail but not always, it depends on how the node is - // moved or removed - try { - self.setContent(); - } catch(e) {} - - } - - iframe.addEventListener("unload", unloadListener, true); - this.eventListeners["unload"] = unloadListener; -} - -// Remove and unregister the widget from everything -WidgetChrome.prototype.destroy = function WC_destroy(removedItems) { - // remove event listeners - for (let [type, listener] in Iterator(this.eventListeners)) - this.node.firstElementChild.removeEventListener(type, listener, true); - // remove dom node - this.node.parentNode.removeChild(this.node); - // cleanup symbiont - this._symbiont.destroy(); - // cleanup itself - this.eventListeners = null; - this._widget = null; - this._symbiont = null; -} - -// Init the browserManager only after setting prototypes and such above, because -// it will cause browserManager.onTrack to be called immediately if there are -// open windows. -browserManager.init(); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/lib/windows.js b/tools/addon-sdk-1.4/packages/addon-kit/lib/windows.js deleted file mode 100644 index e9e097b..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/lib/windows.js +++ /dev/null @@ -1,238 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Felipe Gomes <felipc@gmail.com> (Original author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -if (!require("api-utils/xul-app").is("Firefox")) { - throw new Error([ - "The windows module currently supports only Firefox. In the future", - " we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=571449 for more information." - ].join("")); -} - -const { Cc, Ci } = require('chrome'), - { Trait } = require('api-utils/traits'), - { List } = require('api-utils/list'), - { EventEmitter } = require('api-utils/events'), - { WindowTabs, WindowTabTracker } = require('api-utils/windows/tabs'), - { WindowDom } = require('api-utils/windows/dom'), - { WindowLoader } = require('api-utils/windows/loader'), - { WindowTrackerTrait } = require('api-utils/window-utils'), - { Options } = require('api-utils/tabs/tab'), - { utils } = require('api-utils/xpcom'), - apiUtils = require('api-utils/api-utils'), - unload = require('api-utils/unload'), - - WM = Cc['@mozilla.org/appshell/window-mediator;1']. - getService(Ci.nsIWindowMediator), - - BROWSER = 'navigator:browser'; - -/** - * Window trait composes safe wrappers for browser window that are E10S - * compatible. - */ -const BrowserWindowTrait = Trait.compose( - EventEmitter, - WindowDom.resolve({ close: '_close' }), - WindowTabs, - WindowTabTracker, - WindowLoader, - /* WindowSidebars, */ - Trait.compose({ - _emit: Trait.required, - _close: Trait.required, - _load: Trait.required, - /** - * Constructor returns wrapper of the specified chrome window. - * @param {nsIWindow} window - */ - constructor: function BrowserWindow(options) { - // Register this window ASAP, in order to avoid loop that would try - // to create this window instance over and over (see bug 648244) - windows.push(this); - - // make sure we don't have unhandled errors - this.on('error', console.exception.bind(console)); - - if ('onOpen' in options) - this.on('open', options.onOpen); - if ('onClose' in options) - this.on('close', options.onClose); - if ('window' in options) - this._window = options.window; - if ('tabs' in options) { - this._tabOptions = Array.isArray(options.tabs) ? - options.tabs.map(Options) : - [ Options(options.tabs) ]; - } - else if ('url' in options) { - this._tabOptions = [ Options(options.url) ]; - } - this._load(); - return this; - }, - _tabOptions: [], - _onLoad: function() { - try { - this._initWindowTabTracker(); - } catch(e) { - this._emit('error', e) - } - this._emitOnObject(browserWindows, 'open', this._public); - }, - _onUnload: function() { - this._destroyWindowTabTracker(); - this._emitOnObject(browserWindows, 'close', this._public); - this._window = null; - // Removing reference from the windows array. - windows.splice(windows.indexOf(this), 1); - this._removeAllListeners('close'); - this._removeAllListeners('open'); - this._removeAllListeners('ready'); - }, - close: function close(callback) { - // maybe we should deprecate this with message ? - if (callback) this.on('close', callback); - return this._close(); - } - }) -); -/** - * Wrapper for `BrowserWindowTrait`. Creates new instance if wrapper for - * window doesn't exists yet. If wrapper already exists then returns it - * instead. - * @params {Object} options - * Options that are passed to the the `BrowserWindowTrait` - * @returns {BrowserWindow} - * @see BrowserWindowTrait - */ -function BrowserWindow(options) { - let chromeWindow = options.window; - for each (let window in windows) { - if (chromeWindow == window._window) - return window._public - } - let window = BrowserWindowTrait(options); - return window._public; -} -// to have proper `instanceof` behavior will go away when #596248 is fixed. -BrowserWindow.prototype = BrowserWindowTrait.prototype; -exports.BrowserWindow = BrowserWindow -const windows = []; -/** - * `BrowserWindows` trait is composed out of `List` trait and it represents - * "live" list of currently open browser windows. Instance mutates itself - * whenever new browser window gets opened / closed. - */ -// Very stupid to resolve all `toStrings` but this will be fixed by #596248 -const browserWindows = Trait.resolve({ toString: null }).compose( - List.resolve({ constructor: '_initList' }), - EventEmitter.resolve({ toString: null }), - WindowTrackerTrait.resolve({ constructor: '_initTracker', toString: null }), - Trait.compose({ - _emit: Trait.required, - _add: Trait.required, - _remove: Trait.required, - - // public API - - /** - * Constructor creates instance of `Windows` that represents live list of open - * windows. - */ - constructor: function BrowserWindows() { - this._trackedWindows = []; - this._initList(); - this._initTracker(); - unload.ensure(this, "_destructor"); - }, - _destructor: function _destructor() { - this._removeAllListeners('open'); - this._removeAllListeners('close'); - }, - /** - * This property represents currently active window. - * Property is non-enumerable, in order to preserve array like enumeration. - * @type {Window|null} - */ - get activeWindow() { - let window = WM.getMostRecentWindow(BROWSER); - return this._isBrowser(window) ? BrowserWindow({ window: window }) : null; - }, - open: function open(options) { - if (typeof options === "string") - // `tabs` option is under review and may be removed. - options = { tabs: [Options(options)] }; - return BrowserWindow(options); - }, - /** - * Returns true if specified window is a browser window. - * @param {nsIWindow} window - * @returns {Boolean} - */ - _isBrowser: function _isBrowser(window) - BROWSER === window.document.documentElement.getAttribute("windowtype") - , - /** - * Internal listener which is called whenever new window gets open. - * Creates wrapper and adds to this list. - * @param {nsIWindow} chromeWindow - */ - _onTrack: function _onTrack(chromeWindow) { - if (!this._isBrowser(chromeWindow)) return; - let window = BrowserWindow({ window: chromeWindow }); - this._add(window); - this._emit('open', window); - }, - /** - * Internal listener which is called whenever window gets closed. - * Cleans up references and removes wrapper from this list. - * @param {nsIWindow} window - */ - _onUntrack: function _onUntrack(chromeWindow) { - if (!this._isBrowser(chromeWindow)) return; - let window = BrowserWindow({ window: chromeWindow }); - // `_onUnload` method of the `BrowserWindow` will remove `chromeWindow` - // from the `windows` array. - this._remove(window); - this._emit('close', window); - } - }).resolve({ toString: null }) -)(); -exports.browserWindows = browserWindows; - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/package.json b/tools/addon-sdk-1.4/packages/addon-kit/package.json deleted file mode 100644 index 9c62ae8..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "addon-kit", - "description": "Add-on development made easy.", - "keywords": ["javascript", "engine", "platform", "xulrunner"], - "author": "Atul Varma (http://toolness.com/) <atul@mozilla.com>", - "contributors": [ - "Myk Melez (http://melez.com/) <myk@mozilla.org>", - "Daniel Aquino <mr.danielaquino@gmail.com>" - ], - "license": "MPL 1.1/GPL 2.0/LGPL 2.1", - "dependencies": ["api-utils"] -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/helpers.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/helpers.js deleted file mode 100644 index bbfe911..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/helpers.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -const { Loader } = require("@loader"); - -exports.Loader = function(module, globals) { - var options = JSON.parse(JSON.stringify(require("@packaging"))); - options.globals = globals; - let loader = Loader.new(options); - return Object.create(loader, { - require: { value: Loader.require.bind(loader, module.path) }, - sandbox: { value: function sandbox(id) { - let path = options.manifest[module.path].requirements[id].path; - return loader.sandboxes[path].sandbox; - }}, - unload: { value: function unload(reason, callback) { - loader.unload(reason, callback); - }} - }) -}; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/pagemod-test-helpers.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/pagemod-test-helpers.js deleted file mode 100644 index 7e87a85..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/pagemod-test-helpers.js +++ /dev/null @@ -1,63 +0,0 @@ -"use strict"; - -const {Cc,Ci} = require("chrome"); -const timer = require("timer"); -const xulApp = require("xul-app"); -const { Loader } = require('./helpers'); - -/** - * A helper function that creates a PageMod, then opens the specified URL - * and checks the effect of the page mod on 'onload' event via testCallback. - */ -exports.testPageMod = function testPageMod(test, testURL, pageModOptions, - testCallback, timeout) { - if (!xulApp.versionInRange(xulApp.platformVersion, "1.9.3a3", "*") && - !xulApp.versionInRange(xulApp.platformVersion, "1.9.2.7", "1.9.2.*")) { - test.pass("Note: not testing PageMod, as it doesn't work on this platform version"); - return null; - } - - var wm = Cc['@mozilla.org/appshell/window-mediator;1'] - .getService(Ci.nsIWindowMediator); - var browserWindow = wm.getMostRecentWindow("navigator:browser"); - if (!browserWindow) { - test.pass("page-mod tests: could not find the browser window, so " + - "will not run. Use -a firefox to run the pagemod tests.") - return null; - } - - if (timeout !== undefined) - test.waitUntilDone(timeout); - else - test.waitUntilDone(); - - let loader = Loader(module); - let pageMod = loader.require("page-mod"); - - var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)]; - - var tabBrowser = browserWindow.gBrowser; - var newTab = tabBrowser.addTab(testURL); - tabBrowser.selectedTab = newTab; - var b = tabBrowser.getBrowserForTab(newTab); - - function onPageLoad() { - b.removeEventListener("load", onPageLoad, true); - // Delay callback execute as page-mod content scripts may be executed on - // load event. So page-mod actions may not be already done. - // If we delay even more contentScriptWhen:'end', we may want to modify - // this code again. - timer.setTimeout(testCallback, 0, - b.contentWindow.wrappedJSObject, - function done() { - pageMods.forEach(function(mod) mod.destroy()); - // XXX leaks reported if we don't close the tab? - tabBrowser.removeTab(newTab); - loader.unload(); - test.done(); - }); - } - b.addEventListener("load", onPageLoad, true); - - return pageMods; -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-clipboard.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-clipboard.js deleted file mode 100644 index 5f61d48..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-clipboard.js +++ /dev/null @@ -1,60 +0,0 @@ - -// Test the typical use case, setting & getting with no flavors specified -exports.testWithNoFlavor = function(test) { - var contents = "hello there"; - var flavor = "text"; - var fullFlavor = "text/unicode"; - var clip = require("clipboard"); - // Confirm we set the clipboard - test.assert(clip.set(contents)); - // Confirm flavor is set - test.assertEqual(clip.currentFlavors[0], flavor); - // Confirm we set the clipboard - test.assertEqual(clip.get(), contents); - // Confirm we can get the clipboard using the flavor - test.assertEqual(clip.get(flavor), contents); - // Confirm we can still get the clipboard using the full flavor - test.assertEqual(clip.get(fullFlavor), contents); -}; - -// Test the slightly less common case where we specify the flavor -exports.testWithFlavor = function(test) { - var contents = "<b>hello there</b>"; - var contentsText = "hello there"; - var flavor = "html"; - var fullFlavor = "text/html"; - var unicodeFlavor = "text"; - var unicodeFullFlavor = "text/unicode"; - var clip = require("clipboard"); - test.assert(clip.set(contents, flavor)); - test.assertEqual(clip.currentFlavors[0], unicodeFlavor); - test.assertEqual(clip.currentFlavors[1], flavor); - test.assertEqual(clip.get(), contentsText); - test.assertEqual(clip.get(flavor), contents); - test.assertEqual(clip.get(fullFlavor), contents); - test.assertEqual(clip.get(unicodeFlavor), contentsText); - test.assertEqual(clip.get(unicodeFullFlavor), contentsText); -}; - -// Test that the typical case still works when we specify the flavor to set -exports.testWithRedundantFlavor = function(test) { - var contents = "<b>hello there</b>"; - var flavor = "text"; - var fullFlavor = "text/unicode"; - var clip = require("clipboard"); - test.assert(clip.set(contents, flavor)); - test.assertEqual(clip.currentFlavors[0], flavor); - test.assertEqual(clip.get(), contents); - test.assertEqual(clip.get(flavor), contents); - test.assertEqual(clip.get(fullFlavor), contents); -}; - -exports.testNotInFlavor = function(test) { - var contents = "hello there"; - var flavor = "html"; - var clip = require("clipboard"); - test.assert(clip.set(contents)); - // If there's nothing on the clipboard with this flavor, should return null - test.assertEqual(clip.get(flavor), null); -}; -// TODO: Test error cases. diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.html b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.html deleted file mode 100644 index a0fb5cb..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.html +++ /dev/null @@ -1,78 +0,0 @@ -<!-- ***** BEGIN LICENSE BLOCK ***** - - Version: MPL 1.1/GPL 2.0/LGPL 2.1 - - - - The contents of this file are subject to the Mozilla Public License Version - - 1.1 (the "License"); you may not use this file except in compliance with - - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - - - Software distributed under the License is distributed on an "AS IS" basis, - - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - - for the specific language governing rights and limitations under the - - License. - - - - The Original Code is Jetpack. - - - - The Initial Developer of the Original Code is - - the Mozilla Foundation. - - Portions created by the Initial Developer are Copyright (C) 2010 - - the Initial Developer. All Rights Reserved. - - - - Contributor(s): - - Drew Willcoxon <adw@mozilla.com> (Original Author) - - - - Alternatively, the contents of this file may be used under the terms of - - either the GNU General Public License Version 2 or later (the "GPL"), or - - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - - in which case the provisions of the GPL or the LGPL are applicable instead - - of those above. If you wish to allow use of your version of this file only - - under the terms of either the GPL or the LGPL, and not to allow others to - - use your version of this file under the terms of the MPL, indicate your - - decision by deleting the provisions above and replace them with the notice - - and other provisions required by the LGPL or the GPL. If you do not delete - - the provisions above, a recipient may use your version of this file under - - the terms of any one of the MPL, the GPL or the LGPL. - - - - ***** END LICENSE BLOCK ***** --> - -<html> - <head> - <title>Context menu test</title> - </head> - <body> - <p> - <img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="> - </p> - - <p> - <a id="link" href=""> - A simple link. - </a> - </p> - - <p> - <a href=""> - <span id="span-link"> - A span inside a link. - </span> - </a> - </p> - - <p id="text"> - Some text. - </p> - - <p> - <textarea id="textfield"> - A text field, - with some text. - </textarea> - </p> - - <p> - <iframe id="iframe" src="data:text/html,An iframe." - width="200" height="100"> - </iframe> - </p> - </body> -</html> diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.js deleted file mode 100644 index 157edf1..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-context-menu.js +++ /dev/null @@ -1,2075 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * Matteo Ferretti <zer0@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -let {Cc,Ci} = require("chrome"); -const { Loader } = require('./helpers'); - -// These should match the same constants in the module. -const ITEM_CLASS = "jetpack-context-menu-item"; -const SEPARATOR_ID = "jetpack-context-menu-separator"; -const OVERFLOW_THRESH_DEFAULT = 10; -const OVERFLOW_THRESH_PREF = - "extensions.addon-sdk.context-menu.overflowThreshold"; -const OVERFLOW_MENU_ID = "jetpack-content-menu-overflow-menu"; -const OVERFLOW_POPUP_ID = "jetpack-content-menu-overflow-popup"; - -const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html"); - - -// Destroying items that were previously created should cause them to be absent -// from the menu. -exports.testConstructDestroy = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - // Create an item. - let item = new loader.cm.Item({ label: "item" }); - test.assertEqual(item.parentMenu, null, "item's parent menu should be null"); - - test.showMenu(null, function (popup) { - - // It should be present when the menu is shown. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Destroy the item. Multiple destroys should be harmless. - item.destroy(); - item.destroy(); - test.showMenu(null, function (popup) { - - // It should be removed from the menu. - test.checkMenu([], [], [item]); - test.done(); - }); - }); -}; - - -// Destroying an item twice should not cause an error. -exports.testDestroyTwice = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - item.destroy(); - item.destroy(); - - test.pass("Destroying an item twice should not cause an error."); - test.done(); -}; - - -// CSS selector contexts should cause their items to be present in the menu -// when the menu is invoked on nodes that match the selectors. -exports.testSelectorContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("img") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// CSS selector contexts should cause their items to be present in the menu -// when the menu is invoked on nodes that have ancestors that match the -// selectors. -exports.testSelectorAncestorContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("a[href]") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// CSS selector contexts should cause their items to be absent from the menu -// when the menu is not invoked on nodes that match or have ancestors that -// match the selectors. -exports.testSelectorContextNoMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); -}; - - -// Page contexts should cause their items to be present in the menu when the -// menu is not invoked on an active element. -exports.testPageContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 0" - }), - new loader.cm.Item({ - label: "item 1", - context: undefined - }), - new loader.cm.Item({ - label: "item 2", - context: loader.cm.PageContext() - }), - new loader.cm.Item({ - label: "item 3", - context: [loader.cm.PageContext()] - }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Page contexts should cause their items to be absent from the menu when the -// menu is invoked on an active element. -exports.testPageContextNoMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 0" - }), - new loader.cm.Item({ - label: "item 1", - context: undefined - }), - new loader.cm.Item({ - label: "item 2", - context: loader.cm.PageContext() - }), - new loader.cm.Item({ - label: "item 3", - context: [loader.cm.PageContext()] - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { - test.checkMenu([], items, []); - test.done(); - }); - }); -}; - - -// Selection contexts should cause items to appear when a selection exists. -exports.testSelectionContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - window.getSelection().selectAllChildren(doc.body); - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Selection contexts should cause items to appear when a selection exists in -// a text field. -exports.testSelectionContextMatchInTextField = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - let textfield = doc.getElementById("textfield"); - textfield.setSelectionRange(0, textfield.value.length); - test.showMenu(textfield, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Selection contexts should not cause items to appear when a selection does -// not exist in a text field. -exports.testSelectionContextNoMatchInTextField = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - let textfield = doc.getElementById("textfield"); - textfield.setSelectionRange(0, 0); - test.showMenu(textfield, function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); - }); -}; - - -// Selection contexts should not cause items to appear when a selection does -// not exist. -exports.testSelectionContextNoMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.showMenu(null, function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); -}; - - -// URL contexts should cause items to appear on pages that match. -exports.testURLContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - loader.cm.Item({ - label: "item 0", - context: loader.cm.URLContext(TEST_DOC_URL) - }), - loader.cm.Item({ - label: "item 1", - context: loader.cm.URLContext([TEST_DOC_URL, "*.bogus.com"]) - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// URL contexts should not cause items to appear on pages that do not match. -exports.testURLContextNoMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - loader.cm.Item({ - label: "item 0", - context: loader.cm.URLContext("*.bogus.com") - }), - loader.cm.Item({ - label: "item 1", - context: loader.cm.URLContext(["*.bogus.com", "*.gnarly.com"]) - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu([], items, []); - test.done(); - }); - }); -}; - - -// Removing a non-matching URL context after its item is created and the page is -// loaded should cause the item's content script to be evaluated. -exports.testURLContextRemove = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let shouldBeEvaled = false; - let context = loader.cm.URLContext("*.bogus.com"); - let item = loader.cm.Item({ - label: "item", - context: context, - contentScript: 'self.postMessage("ok");', - onMessage: function (msg) { - test.assert(shouldBeEvaled, - "content script should be evaluated when expected"); - shouldBeEvaled = false; - test.done(); - } - }); - - test.withTestDoc(function (window, doc) { - shouldBeEvaled = true; - item.context.remove(context); - }); -}; - - -// Adding a non-matching URL context after its item is created and the page is -// loaded should cause the item's worker to be destroyed. -exports.testURLContextAdd = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ label: "item" }); - - test.withTestDoc(function (window, doc) { - let privatePropsKey = loader.globalScope.PRIVATE_PROPS_KEY; - let workerReg = item.valueOf(privatePropsKey)._workerReg; - - let found = false; - for each (let winWorker in workerReg.winWorkers) { - if (winWorker.win === window) { - found = true; - break; - } - } - this.test.assert(found, "window should be present in worker registry"); - - item.context.add(loader.cm.URLContext("*.bogus.com")); - - for each (let winWorker in workerReg.winWorkers) - this.test.assertNotEqual(winWorker.win, window, - "window should not be present in worker registry"); - - test.done(); - }); -}; - - -// Content contexts that return true should cause their items to be present -// in the menu. -exports.testContentContextMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", function () true);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// Content contexts that return false should cause their items to be absent -// from the menu. -exports.testContentContextNoMatch = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", function () false);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); -}; - - -// Content contexts that return a string should cause their items to be present -// in the menu and the items' labels to be updated. -exports.testContentContextMatchString = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "first label", - contentScript: 'self.on("context", function () "second label");' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.assertEqual(item.label, "second label", - "item's label should be updated"); - test.done(); - }); -}; - - -// The args passed to context listeners should be correct. -exports.testContentContextArgs = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - let callbacks = 0; - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", function (node) {' + - ' let Ci = Components.interfaces;' + - ' self.postMessage(node instanceof Ci.nsIDOMHTMLElement);' + - ' return false;' + - '});', - onMessage: function (isElt) { - test.assert(isElt, "node should be an HTML element"); - if (++callbacks == 2) test.done(); - } - }); - - test.showMenu(null, function () { - if (++callbacks == 2) test.done(); - }); -}; - -// Multiple contexts imply intersection, not union, and content context -// listeners should not be called if all declarative contexts are not current. -exports.testMultipleContexts = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - context: [loader.cm.SelectorContext("a[href]"), loader.cm.PageContext()], - contentScript: 'self.on("context", function () self.postMessage());', - onMessage: function () { - test.fail("Context listener should not be called"); - } - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); - }); -}; - - -// Once a context is removed, it should no longer cause its item to appear. -exports.testRemoveContext = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let ctxt = loader.cm.SelectorContext("img"); - let item = new loader.cm.Item({ - label: "item", - context: ctxt - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("image"), function (popup) { - - // The item should be present at first. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Remove the img context and check again. - item.context.remove(ctxt); - test.showMenu(doc.getElementById("image"), function (popup) { - test.checkMenu([], [item], []); - test.done(); - }); - }); - }); -}; - - -// Lots of items should overflow into the overflow submenu. -exports.testOverflow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT + 1; i++) { - let item = new loader.cm.Item({ label: "item " + i }); - items.push(item); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Module unload should cause all items to be removed. -exports.testUnload = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - - // The menu should contain the item. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Unload the module. - loader.unload(); - test.showMenu(null, function (popup) { - - // The item should be removed from the menu. - test.checkMenu([], [], [item]); - test.done(); - }); - }); -}; - - -// Using multiple module instances to add items without causing overflow should -// work OK. Assumes OVERFLOW_THRESH_DEFAULT <= 2. -exports.testMultipleModulesAdd = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ label: "item 0" }); - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain both items. - test.checkMenu([item0, item1], [], []); - popup.hidePopup(); - - // Unload the first module. - loader0.unload(); - test.showMenu(null, function (popup) { - - // The first item should be removed from the menu. - test.checkMenu([item1], [], [item0]); - popup.hidePopup(); - - // Unload the second module. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to add items causing overflow should work OK. -exports.testMultipleModulesAddOverflow = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - // Use module 0 to add OVERFLOW_THRESH_DEFAULT items. - let items0 = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { - let item = new loader0.cm.Item({ label: "item 0 " + i }); - items0.push(item); - } - - // Use module 1 to add one item. - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let allItems = items0.concat(item1); - - test.showMenu(null, function (popup) { - - // The menu should contain all items in overflow. - test.checkMenu(allItems, [], []); - popup.hidePopup(); - - // Unload the first module. - loader0.unload(); - test.showMenu(null, function (popup) { - - // The first items should be removed from the menu, which should not - // overflow. - test.checkMenu([item1], [], items0); - popup.hidePopup(); - - // Unload the second module. - loader1.unload(); - test.showMenu(null, function (popup) { - - // All items should be removed from the menu. - test.checkMenu([], [], allItems); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader0 create item -> loader1 create item -> loader0.unload -> -// loader1.unload -exports.testMultipleModulesDiffContexts1 = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item1], [item0], []); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // item0 should be removed from the menu. - test.checkMenu([item1], [], [item0]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader1 create item -> loader0 create item -> loader0.unload -> -// loader1.unload -exports.testMultipleModulesDiffContexts2 = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item1], [item0], []); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // item0 should be removed from the menu. - test.checkMenu([item1], [], [item0]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader0 create item -> loader1 create item -> loader1.unload -> -// loader0.unload -exports.testMultipleModulesDiffContexts3 = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item1], [item0], []); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // item1 should be removed from the menu. - test.checkMenu([], [item0], [item1]); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader1 create item -> loader0 create item -> loader1.unload -> -// loader0.unload -exports.testMultipleModulesDiffContexts4 = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item1], [item0], []); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // item1 should be removed from the menu. - test.checkMenu([], [item0], [item1]); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Test interactions between a loaded module, unloading another module, and the -// menu separator and overflow submenu. -exports.testMultipleModulesAddRemove = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item = new loader0.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - - // The menu should contain the item. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Remove the item. - item.destroy(); - test.showMenu(null, function (popup) { - - // The item should be removed from the menu. - test.checkMenu([], [], [item]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // There shouldn't be any errors involving the menu separator or - // overflow submenu. - test.checkMenu([], [], [item]); - test.done(); - }); - }); - }); -}; - - -// An item's click listener should work. -exports.testItemClick = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item data", - contentScript: 'self.on("click", function (node, data) {' + - ' let Ci = Components.interfaces;' + - ' self.postMessage({' + - ' isElt: node instanceof Ci.nsIDOMHTMLElement,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - test.assertEqual(this, item, "`this` inside onMessage should be item"); - test.assert(data.isElt, "node should be an HTML element"); - test.assertEqual(data.data, item.data, "data should be item data"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - let elt = test.getItemElt(popup, item); - elt.click(); - }); -}; - - -// A menu's click listener should work and receive bubbling clicks from -// sub-items appropriately. This also tests menus and ensures that when a CSS -// selector context matches the clicked node's ancestor, the matching ancestor -// is passed to listeners as the clicked node. -exports.testMenuClick = function (test) { - // Create a top-level menu, submenu, and item, like this: - // topMenu -> submenu -> item - // Click the item and make sure the click bubbles. - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "submenu item", - data: "submenu item data" - }); - - let submenu = new loader.cm.Menu({ - label: "submenu", - items: [item] - }); - - let topMenu = new loader.cm.Menu({ - label: "top menu", - contentScript: 'self.on("click", function (node, data) {' + - ' let Ci = Components.interfaces;' + - ' self.postMessage({' + - ' isAnchor: node instanceof Ci.nsIDOMHTMLAnchorElement,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - test.assertEqual(this, topMenu, "`this` inside top menu should be menu"); - test.assert(data.isAnchor, "Clicked node should be anchor"); - test.assertEqual(data.data, item.data, - "Clicked item data should be correct"); - test.done(); - }, - items: [submenu], - context: loader.cm.SelectorContext("a") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu(doc.getElementById("span-link"), function (popup) { - test.checkMenu([topMenu], [], []); - let topMenuElt = test.getItemElt(popup, topMenu); - let topMenuPopup = topMenuElt.firstChild; - let submenuElt = test.getItemElt(topMenuPopup, submenu); - let submenuPopup = submenuElt.firstChild; - let itemElt = test.getItemElt(submenuPopup, item); - itemElt.click(); - }); - }); -}; - - -// Click listeners should work when multiple modules are loaded. -exports.testItemClickMultipleModules = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = loader0.cm.Item({ - label: "loader 0 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.fail("loader 0 item should not emit click event"); - } - }); - let item1 = loader1.cm.Item({ - label: "loader 1 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.pass("loader 1 item clicked as expected"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item0, item1], [], []); - let item1Elt = test.getItemElt(popup, item1); - item1Elt.click(); - }); -}; - - -// Adding a separator to a submenu should work OK. -exports.testSeparator = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = new loader.cm.Menu({ - label: "submenu", - items: [new loader.cm.Separator()] - }); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Existing context menu modifications should apply to new windows. -exports.testNewWindow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.withNewWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// When a new window is opened, items added by an unloaded module should not -// be present in the menu. -exports.testNewWindowMultipleModules = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - loader.unload(); - test.withNewWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([], [], []); - test.done(); - }); - }); - }); -}; - - -// Items in the context menu should be sorted according to locale. -exports.testSorting = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - // Make an unsorted items list. It'll look like this: - // item 1, item 0, item 3, item 2, item 5, item 4, ... - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i += 2) { - items.push(new loader.cm.Item({ label: "item " + (i + 1) })); - items.push(new loader.cm.Item({ label: "item " + i })); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Items in the overflow menu should be sorted according to locale. -exports.testSortingOverflow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - // Make an unsorted items list. It'll look like this: - // item 1, item 0, item 3, item 2, item 5, item 4, ... - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT * 2; i += 2) { - items.push(new loader.cm.Item({ label: "item " + (i + 1) })); - items.push(new loader.cm.Item({ label: "item " + i })); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Multiple modules shouldn't interfere with sorting. -exports.testSortingMultipleModules = function (test) { - test = new TestHelper(test); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let items0 = []; - let items1 = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { - if (i % 2) { - let item = new loader0.cm.Item({ label: "item " + i }); - items0.push(item); - } - else { - let item = new loader1.cm.Item({ label: "item " + i }); - items1.push(item); - } - } - let allItems = items0.concat(items1); - - test.showMenu(null, function (popup) { - - // All items should be present and sorted. - test.checkMenu(allItems, [], []); - popup.hidePopup(); - loader0.unload(); - loader1.unload(); - test.showMenu(null, function (popup) { - - // All items should be removed. - test.checkMenu([], [], allItems); - test.done(); - }); - }); -}; - - -// The binary search of insertionPoint should work OK. -exports.testInsertionPoint = function (test) { - function mockElts(labels) { - return labels.map(function (label) { - return { label: label, getAttribute: function (l) label }; - }); - } - - test = new TestHelper(test); - let loader = test.newLoader(); - let insertionPoint = loader.globalScope.insertionPoint; - - let ip = insertionPoint("a", []); - test.assertStrictEqual(ip, null, "Insertion point should be null"); - - ip = insertionPoint("a", mockElts(["b"])); - test.assertEqual(ip.label, "b", "Insertion point should be 'b'"); - - ip = insertionPoint("c", mockElts(["b"])); - test.assertStrictEqual(ip, null, "Insertion point should be null"); - - ip = insertionPoint("b", mockElts(["a", "c"])); - test.assertEqual(ip.label, "c", "Insertion point should be 'c'"); - - ip = insertionPoint("c", mockElts(["a", "b", "d"])); - test.assertEqual(ip.label, "d", "Insertion point should be 'd'"); - - ip = insertionPoint("a", mockElts(["b", "c", "d"])); - test.assertEqual(ip.label, "b", "Insertion point should be 'b'"); - - ip = insertionPoint("d", mockElts(["a", "b", "c"])); - test.assertStrictEqual(ip, null, "Insertion point should be null"); - - test.done(); -}; - - -// Content click handlers and context handlers should be able to communicate, -// i.e., they're eval'ed in the same worker and sandbox. -exports.testContentCommunication = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'var potato;' + - 'self.on("context", function () {' + - ' potato = "potato";' + - ' return true;' + - '});' + - 'self.on("click", function () {' + - ' self.postMessage(potato);' + - '});', - }); - - item.on("message", function (data) { - test.assertEqual(data, "potato", "That's a lot of potatoes!"); - test.done(); - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - let elt = test.getItemElt(popup, item); - elt.click(); - }); -}; - - -// When the context menu is invoked on a tab that was already open when the -// module was loaded, it should contain the expected items and content workers -// should function as expected. -exports.testLoadWithOpenTab = function (test) { - test = new TestHelper(test); - test.withTestDoc(function (window, doc) { - let loader = test.newLoader(); - let item = new loader.cm.Item({ - label: "item", - contentScript: - 'self.on("click", function () self.postMessage("click"));', - onMessage: function (msg) { - if (msg === "click") - test.done(); - } - }); - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.getItemElt(popup, item).click(); - }); - }); -}; - - -// Setting an item's label before the menu is ever shown should correctly change -// its label and, if necessary, its order within the menu. -exports.testSetLabelBeforeShow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ] - items[0].label = "z"; - test.assertEqual(items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu([items[1], items[0]], [], []); - test.done(); - }); -}; - - -// Setting an item's label after the menu is shown should correctly change its -// label and, if necessary, its order within the menu. -exports.testSetLabelAfterShow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - popup.hidePopup(); - - items[0].label = "z"; - test.assertEqual(items[0].label, "z"); - test.showMenu(null, function (popup) { - test.checkMenu([items[1], items[0]], [], []); - test.done(); - }); - }); -}; - - -// Setting an item's label before the menu is ever shown should correctly change -// its label and, if necessary, its order within the menu if the item is in the -// overflow submenu. -exports.testSetLabelBeforeShowOverflow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let prefs = loader.loader.require("preferences-service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ] - items[0].label = "z"; - test.assertEqual(items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu([items[1], items[0]], [], []); - prefs.set(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT); - test.done(); - }); -}; - - -// Setting an item's label after the menu is shown should correctly change its -// label and, if necessary, its order within the menu if the item is in the -// overflow submenu. -exports.testSetLabelAfterShowOverflow = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let prefs = loader.loader.require("preferences-service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - popup.hidePopup(); - - items[0].label = "z"; - test.assertEqual(items[0].label, "z"); - test.showMenu(null, function (popup) { - test.checkMenu([items[1], items[0]], [], []); - prefs.set(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT); - test.done(); - }); - }); -}; - - -// Setting the label of an item in a Menu should work. -exports.testSetLabelMenuItem = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [loader.cm.Item({ label: "a" })] - }); - menu.items[0].label = "z"; - - test.assertEqual(menu.items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Menu.addItem() should work. -exports.testMenuAddItem = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }) - ] - }); - menu.addItem(loader.cm.Item({ label: "item 1" })); - menu.addItem(loader.cm.Item({ label: "item 2" })); - - test.assertEqual(menu.items.length, 3, - "menu should have correct number of items"); - for (let i = 0; i < 3; i++) { - test.assertEqual(menu.items[i].label, "item " + i, - "item label should be correct"); - test.assertEqual(menu.items[i].parentMenu, menu, - "item's parent menu should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Adding the same item twice to a menu should work as expected. -exports.testMenuAddItemTwice = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [] - }); - let subitem = loader.cm.Item({ label: "item 1" }) - menu.addItem(subitem); - menu.addItem(loader.cm.Item({ label: "item 0" })); - menu.addItem(subitem); - - test.assertEqual(menu.items.length, 2, - "menu should have correct number of items"); - for (let i = 0; i < 2; i++) { - test.assertEqual(menu.items[i].label, "item " + i, - "item label should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Menu.removeItem() should work. -exports.testMenuRemoveItem = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item 1" }); - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }), - subitem, - loader.cm.Item({ label: "item 2" }) - ] - }); - - // Removing twice should be harmless. - menu.removeItem(subitem); - menu.removeItem(subitem); - - test.assertEqual(subitem.parentMenu, null, - "item's parent menu should be correct"); - - test.assertEqual(menu.items.length, 2, - "menu should have correct number of items"); - test.assertEqual(menu.items[0].label, "item 0", - "item label should be correct"); - test.assertEqual(menu.items[1].label, "item 2", - "item label should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Adding an item currently contained in one menu to another menu should work. -exports.testMenuItemSwap = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item" }); - let menu0 = loader.cm.Menu({ - label: "menu 0", - items: [subitem] - }); - let menu1 = loader.cm.Menu({ - label: "menu 1", - items: [] - }); - menu1.addItem(subitem); - - test.assertEqual(menu0.items.length, 0, - "menu should have correct number of items"); - - test.assertEqual(menu1.items.length, 1, - "menu should have correct number of items"); - test.assertEqual(menu1.items[0].label, "item", - "item label should be correct"); - - test.assertEqual(subitem.parentMenu, menu1, - "item's parent menu should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu0, menu1], [], []); - test.done(); - }); -}; - - -// Destroying an item should remove it from its parent menu. -exports.testMenuItemDestroy = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item" }); - let menu = loader.cm.Menu({ - label: "menu", - items: [subitem] - }); - subitem.destroy(); - - test.assertEqual(menu.items.length, 0, - "menu should have correct number of items"); - test.assertEqual(subitem.parentMenu, null, - "item's parent menu should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Setting Menu.items should work. -exports.testMenuItemsSetter = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "old item 0" }), - loader.cm.Item({ label: "old item 1" }) - ] - }); - menu.items = [ - loader.cm.Item({ label: "new item 0" }), - loader.cm.Item({ label: "new item 1" }), - loader.cm.Item({ label: "new item 2" }) - ]; - - test.assertEqual(menu.items.length, 3, - "menu should have correct number of items"); - for (let i = 0; i < 3; i++) { - test.assertEqual(menu.items[i].label, "new item " + i, - "item label should be correct"); - test.assertEqual(menu.items[i].parentMenu, menu, - "item's parent menu should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Setting Item.data should work. -exports.testItemDataSetter = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let item = loader.cm.Item({ label: "old item 0", data: "old" }); - item.data = "new"; - - test.assertEqual(item.data, "new", "item should have correct data"); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// Open the test doc, load the module, make sure items appear when context- -// clicking the iframe. -exports.testAlreadyOpenIframe = function (test) { - test = new TestHelper(test); - test.withTestDoc(function (window, doc) { - let loader = test.newLoader(); - let item = new loader.cm.Item({ - label: "item" - }); - test.showMenu(doc.getElementById("iframe"), function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Test image support. -exports.testItemImage = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let imageURL = require("self").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: [] }); - - test.showMenu(null, function (popup) { - test.checkMenu([item, menu], [], []); - - let imageURL2 = require("self").data.url("dummy.ico"); - item.image = imageURL2; - menu.image = imageURL2; - test.checkMenu([item, menu], [], []); - - item.image = null; - menu.image = null; - test.checkMenu([item, menu], [], []); - - test.done(); - }); -}; - - -// Menu.destroy should destroy the item tree rooted at that menu. -exports.testMenuDestroy = function (test) { - test = new TestHelper(test); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }), - loader.cm.Menu({ - label: "item 1", - items: [ - loader.cm.Item({ label: "subitem 0" }), - loader.cm.Item({ label: "subitem 1" }), - loader.cm.Item({ label: "subitem 2" }) - ] - }), - loader.cm.Item({ label: "item 2" }) - ] - }); - menu.destroy(); - - let numRegistryEntries = 0; - loader.globalScope.browserManager.browserWins.forEach(function (bwin) { - for (let itemID in bwin.items) - numRegistryEntries++; - }); - test.assertEqual(numRegistryEntries, 0, "All items should be unregistered."); - - test.showMenu(null, function (popup) { - test.checkMenu([], [], [menu]); - test.done(); - }); -}; - - -// NO TESTS BELOW THIS LINE! /////////////////////////////////////////////////// - -// Run only a dummy test if context-menu doesn't support the host app. -if (!require("xul-app").is("Firefox")) { - for (let [prop, val] in Iterator(exports)) - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - exports.testAppNotSupported = function (test) { - test.pass("context-menu does not support this application."); - }; -} - - -// This makes it easier to run tests by handling things like opening the menu, -// opening new windows, making assertions, etc. Methods on |test| can be called -// on instances of this class. Don't forget to call done() to end the test! -// WARNING: This looks up items in popups by comparing labels, so don't give two -// items the same label. -function TestHelper(test) { - // default waitUntilDone timeout is 10s, which is too short on the win7 - // buildslave - test.waitUntilDone(30*1000); - this.test = test; - this.loaders = []; - this.browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); -} - -TestHelper.prototype = { - get contextMenuPopup() { - return this.browserWindow.document.getElementById("contentAreaContextMenu"); - }, - - get contextMenuSeparator() { - return this.browserWindow.document.getElementById(SEPARATOR_ID); - }, - - get overflowPopup() { - return this.browserWindow.document.getElementById(OVERFLOW_POPUP_ID); - }, - - get overflowSubmenu() { - return this.browserWindow.document.getElementById(OVERFLOW_MENU_ID); - }, - - get tabBrowser() { - return this.browserWindow.gBrowser; - }, - - // Methods on the wrapped test can be called on this object. - __noSuchMethod__: function (methodName, args) { - this.test[methodName].apply(this.test, args); - }, - - // Asserts that absentItems -- an array of items that should not match the - // current context -- aren't present in the menu. - checkAbsentItems: function (presentItems, absentItems) { - for (let i = 0; i < absentItems.length; i++) { - let item = absentItems[i]; - let elt = this.getItemElt(this.contextMenuPopup, item); - - // The implementation actually hides items rather than removing or not - // adding them in the first place, but that's an implementation detail. - this.test.assert(!elt || elt.hidden, - "Item should not be present in top-level menu"); - - if (this.shouldOverflow(presentItems)) { - elt = getItemElt(this.overflowPopup, item); - this.test.assert(!elt || elt.hidden, - "Item should not be present in overflow submenu"); - } - } - }, - - // Asserts that elt, a DOM element representing item, looks OK. - checkItemElt: function (elt, item) { - let itemType = this.getItemType(item); - - switch (itemType) { - case "Item": - this.test.assertEqual(elt.localName, "menuitem", - "Item DOM element should be a xul:menuitem"); - if (typeof(item.data) === "string") { - this.test.assertEqual(elt.getAttribute("value"), item.data, - "Item should have correct data"); - } - break - case "Menu": - this.test.assertEqual(elt.localName, "menu", - "Menu DOM element should be a xul:menu"); - let subPopup = elt.firstChild; - this.test.assert(subPopup, "xul:menu should have a child"); - this.test.assertEqual(subPopup.localName, "menupopup", - "xul:menu's first child should be a menupopup"); - break; - case "Separator": - this.test.assertEqual(elt.localName, "menuseparator", - "Separator DOM element should be a xul:menuseparator"); - break; - } - - if (itemType === "Item" || itemType === "Menu") { - this.test.assertEqual(elt.getAttribute("label"), item.label, - "Item should have correct title"); - if (typeof(item.image) === "string") - this.test.assertEqual(elt.getAttribute("image"), item.image, - "Item should have correct image"); - else - this.test.assert(!elt.hasAttribute("image"), - "Item should not have image"); - } - }, - - // Asserts that the context menu looks OK given the arguments. presentItems - // are items that should match the current context. absentItems are items - // that shouldn't. removedItems are items that have been removed from the - // menu. - checkMenu: function (presentItems, absentItems, removedItems) { - this.checkSeparator(presentItems); - this.checkOverflow(presentItems); - this.checkPresentItems(presentItems); - this.checkAbsentItems(presentItems, absentItems); - this.checkRemovedItems(removedItems); - this.checkSort(presentItems); - }, - - // Asserts that the overflow submenu is present or absent as appropriate for - // presentItems. - checkOverflow: function (presentItems) { - let submenu = this.overflowSubmenu; - if (this.shouldOverflow(presentItems)) { - this.test.assert(submenu && !submenu.hidden, - "Overflow submenu should be present"); - this.test.assert(submenu.localName, "menu", - "Overflow submenu should be a <menu>"); - let overflowPopup = this.overflowPopup; - this.test.assert(overflowPopup, - "Overflow submenu popup should be present"); - this.test.assert(overflowPopup.localName, "menupopup", - "Overflow submenu popup should be a <menupopup>"); - } - else { - this.test.assert(!submenu || submenu.hidden, - "Overflow submenu should be absent"); - } - }, - - // Asserts that the items that are present in the menu because they match the - // current context look OK. - checkPresentItems: function (presentItems) { - function recurse(popup, items, isTopLevel) { - items.forEach(function (item) { - let elt = this.getItemElt(popup, item); - - if (isTopLevel) { - if (this.shouldOverflow(items)) { - this.test.assert(!elt || elt.hidden, - "Item should not be present in top-level menu"); - - let overflowPopup = this.overflowPopup; - this.test.assert(overflowPopup, - "Overflow submenu should be present"); - - elt = this.getItemElt(overflowPopup, item); - this.test.assert(elt && !elt.hidden, - "Item should be present in overflow submenu"); - } - else { - this.test.assert(elt && !elt.hidden, - "Item should be present in top-level menu"); - } - } - else { - this.test.assert(elt && !elt.hidden, - "Item should be present in menu"); - } - - this.checkItemElt(elt, item); - if (this.getItemType(item) === "Menu") - recurse.call(this, elt.firstChild, item.items, false); - }, this); - } - - recurse.call(this, this.contextMenuPopup, presentItems, true); - }, - - // Asserts that items that have been removed from the menu are really removed. - checkRemovedItems: function (removedItems) { - for (let i = 0; i < removedItems.length; i++) { - let item = removedItems[i]; - - let elt = this.getItemElt(this.contextMenuPopup, item); - this.test.assert(!elt, "Item should be removed from top-level menu"); - - let overflowPopup = this.overflowPopup; - if (overflowPopup) { - elt = this.getItemElt(overflowPopup, item); - this.test.assert(!elt, "Item should be removed from overflow submenu"); - } - } - }, - - // Asserts that the menu separator separating standard items from our items - // looks OK. - checkSeparator: function (presentItems) { - let sep = this.contextMenuSeparator; - if (presentItems.length) { - this.test.assert(sep && !sep.hidden, "Menu separator should be present"); - this.test.assertEqual(sep.localName, "menuseparator", - "Menu separator should be a <menuseparator>"); - } - else { - this.test.assert(!sep || sep.hidden, "Menu separator should be absent"); - } - }, - - // Asserts that our items are sorted. - checkSort: function (presentItems) { - // Get the first item in sorted order, get its elt, walk the nextSibling - // chain, making sure each is greater than the previous. - if (presentItems.length) { - let sorted = presentItems.slice(0). - sort(function (a, b) a.label.localeCompare(b.label)); - let elt = this.shouldOverflow(presentItems) ? - this.getItemElt(this.overflowPopup, sorted[0]) : - this.getItemElt(this.contextMenuPopup, sorted[0]); - let numElts = 1; - while (elt.nextSibling && - elt.nextSibling.className.split(/\s+/).indexOf(ITEM_CLASS) >= 0) { - let eltLabel = elt.getAttribute("label"); - let nextLabel = elt.nextSibling.getAttribute("label"); - this.test.assert(eltLabel.localeCompare(nextLabel) < 0, - "Item label should be < next item's label"); - elt = elt.nextSibling; - numElts++; - } - this.test.assertEqual(numElts, presentItems.length, - "The first item in sorted order should have the " + - "first element in sorted order"); - } - }, - - // Attaches an event listener to node. The listener is automatically removed - // when it's fired (so it's assumed it will fire), and callback is called - // after a short delay. Since the module we're testing relies on the same - // event listeners to do its work, this is to give them a little breathing - // room before callback runs. Inside callback |this| is this object. - delayedEventListener: function (node, event, callback, useCapture) { - const self = this; - node.addEventListener(event, function handler(evt) { - node.removeEventListener(event, handler, useCapture); - require("timer").setTimeout(function () { - try { - callback.call(self, evt); - } - catch (err) { - self.test.exception(err); - self.test.done(); - } - }, 20); - }, useCapture); - }, - - // Call to finish the test. - done: function () { - function commonDone() { - if (this.tab) { - this.tabBrowser.removeTab(this.tab); - this.tabBrowser.selectedTab = this.oldSelectedTab; - } - while (this.loaders.length) { - let browserManager = this.loaders[0].globalScope.browserManager; - let topLevelItems = browserManager.topLevelItems.slice(); - let privatePropsKey = this.loaders[0].globalScope.PRIVATE_PROPS_KEY; - let workerRegs = topLevelItems.map(function (item) { - return item.valueOf(privatePropsKey)._workerReg; - }); - - this.loaders[0].unload(); - - // Make sure the browser manager is cleaned up. - this.test.assertEqual(browserManager.browserWins.length, 0, - "browserManager should have no windows left"); - this.test.assertEqual(browserManager.topLevelItems.length, 0, - "browserManager should have no items left"); - this.test.assert(!("contentWins" in browserManager), - "browserManager should have no content windows left"); - - // Make sure the items' worker registries are cleaned up. - topLevelItems.forEach(function (item) { - this.test.assert(!("_workerReg" in item.valueOf(privatePropsKey)), - "item's worker registry should be removed"); - }, this); - workerRegs.forEach(function (workerReg) { - this.test.assertEqual(Object.keys(workerReg.winWorkers).length, 0, - "worker registry should be empty"); - this.test.assertEqual( - Object.keys(workerReg.winsWithoutWorkers).length, 0, - "worker registry list of windows without workers should be empty"); - }, this); - } - this.test.done(); - } - - function closeBrowserWindow() { - if (this.oldBrowserWindow) { - this.delayedEventListener(this.browserWindow, "unload", commonDone, - false); - this.browserWindow.close(); - this.browserWindow = this.oldBrowserWindow; - delete this.oldBrowserWindow; - } - else { - commonDone.call(this); - } - }; - - if (this.contextMenuPopup.state == "closed") { - closeBrowserWindow.call(this); - } - else { - this.delayedEventListener(this.contextMenuPopup, "popuphidden", - function () closeBrowserWindow.call(this), - false); - this.contextMenuPopup.hidePopup(); - } - }, - - // Returns the DOM element in popup corresponding to item. - // WARNING: The element is found by comparing labels, so don't give two items - // the same label. - getItemElt: function (popup, item) { - let nodes = popup.childNodes; - for (let i = nodes.length - 1; i >= 0; i--) { - if (this.getItemType(item) === "Separator") { - if (nodes[i].localName === "menuseparator") - return nodes[i]; - } - else if (nodes[i].getAttribute("label") === item.label) - return nodes[i]; - } - return null; - }, - - // Returns "Item", "Menu", or "Separator". - getItemType: function (item) { - // Could use instanceof here, but that would require accessing the loader - // that created the item, and I don't want to A) somehow search through the - // this.loaders list to find it, and B) assume there are any live loaders at - // all. - return /^\[object (Item|Menu|Separator)/.exec(item.toString())[1]; - }, - - // Returns a wrapper around a new loader: { loader, cm, unload, globalScope }. - // loader is a Cuddlefish sandboxed loader, cm is the context menu module, - // globalScope is the context menu module's global scope, and unload is a - // function that unloads the loader and associated resources. - newLoader: function () { - const self = this; - let loader = Loader(module); - let wrapper = { - loader: loader, - cm: loader.require("context-menu"), - globalScope: loader.sandbox("context-menu"), - unload: function () { - loader.unload(); - let idx = self.loaders.indexOf(wrapper); - if (idx < 0) - throw new Error("Test error: tried to unload nonexistent loader"); - self.loaders.splice(idx, 1); - } - }; - this.loaders.push(wrapper); - return wrapper; - }, - - // Returns true if the number of presentItems crosses the overflow threshold. - shouldOverflow: function (presentItems) { - return presentItems.length > - (this.loaders.length ? - this.loaders[0].loader.require("preferences-service"). - get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT) : - OVERFLOW_THRESH_DEFAULT); - }, - - // Opens the context menu on the current page. If targetNode is null, the - // menu is opened in the top-left corner. onShowncallback is passed the - // popup. - showMenu: function(targetNode, onshownCallback) { - function sendEvent() { - this.delayedEventListener(this.browserWindow, "popupshowing", - function (e) { - let popup = e.target; - onshownCallback.call(this, popup); - }, false); - - let rect = targetNode ? - targetNode.getBoundingClientRect() : - { left: 0, top: 0, width: 0, height: 0 }; - let contentWin = this.browserWindow.content; - contentWin. - QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils). - sendMouseEvent("contextmenu", - rect.left + (rect.width / 2), - rect.top + (rect.height / 2), - 2, 1, 0); - } - - // If a new tab or window has not yet been opened, open a new tab now. For - // some reason using the tab already opened when the test starts causes - // leaks. See bug 566351 for details. - if (!targetNode && !this.oldSelectedTab && !this.oldBrowserWindow) { - this.oldSelectedTab = this.tabBrowser.selectedTab; - this.tab = this.tabBrowser.addTab("about:blank"); - let browser = this.tabBrowser.getBrowserForTab(this.tab); - - this.delayedEventListener(browser, "load", function () { - this.tabBrowser.selectedTab = this.tab; - sendEvent.call(this); - }, true); - } - else - sendEvent.call(this); - }, - - // Opens a new browser window. The window will be closed automatically when - // done() is called. - withNewWindow: function (onloadCallback) { - let win = this.browserWindow.OpenBrowserWindow(); - this.delayedEventListener(win, "load", onloadCallback, true); - this.oldBrowserWindow = this.browserWindow; - this.browserWindow = win; - }, - - // Opens a new tab with our test page in the current window. The tab will - // be closed automatically when done() is called. - withTestDoc: function (onloadCallback) { - this.oldSelectedTab = this.tabBrowser.selectedTab; - this.tab = this.tabBrowser.addTab(TEST_DOC_URL); - let browser = this.tabBrowser.getBrowserForTab(this.tab); - - this.delayedEventListener(browser, "load", function () { - this.tabBrowser.selectedTab = this.tab; - onloadCallback.call(this, browser.contentWindow, browser.contentDocument); - }, true); - } -}; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-hotkeys.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-hotkeys.js deleted file mode 100644 index 3b69a28..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-hotkeys.js +++ /dev/null @@ -1,156 +0,0 @@ -"use strict"; - -const { Hotkey } = require("hotkeys"); -const { keyDown } = require("dom/events/keys"); -const { Loader } = require('./helpers'); - -exports["test hotkey: function key"] = function(assert, done) { - var element = require("window-utils").activeBrowserWindow.document.documentElement; - var showHotKey = Hotkey({ - combo: "f1", - onPress: function() { - assert.pass("first callback is called"); - keyDown(element, "f2"); - showHotKey.destroy(); - } - }); - - var hideHotKey = Hotkey({ - combo: "f2", - onPress: function() { - assert.pass("second callback is called"); - hideHotKey.destroy(); - done(); - } - }); - - keyDown(element, "f1"); -}; - -exports["test hotkey: accel alt shift"] = function(assert, done) { - var element = require("window-utils").activeBrowserWindow.document.documentElement; - var showHotKey = Hotkey({ - combo: "accel-shift-6", - onPress: function() { - assert.pass("first callback is called"); - keyDown(element, "accel-alt-shift-6"); - showHotKey.destroy(); - } - }); - - var hideHotKey = Hotkey({ - combo: "accel-alt-shift-6", - onPress: function() { - assert.pass("second callback is called"); - hideHotKey.destroy(); - done(); - } - }); - - keyDown(element, "accel-shift-6"); -}; - -exports["test hotkey meta & control"] = function(assert, done) { - var element = require("window-utils").activeBrowserWindow.document.documentElement; - var showHotKey = Hotkey({ - combo: "meta-3", - onPress: function() { - assert.pass("first callback is called"); - keyDown(element, "alt-control-shift-b"); - showHotKey.destroy(); - } - }); - - var hideHotKey = Hotkey({ - combo: "Ctrl-Alt-Shift-B", - onPress: function() { - assert.pass("second callback is called"); - hideHotKey.destroy(); - done(); - } - }); - - keyDown(element, "meta-3"); -}; - -exports["test hotkey: control-1 / meta--"] = function(assert, done) { - var element = require("window-utils").activeBrowserWindow.document.documentElement; - var showHotKey = Hotkey({ - combo: "control-1", - onPress: function() { - assert.pass("first callback is called"); - keyDown(element, "meta--"); - showHotKey.destroy(); - } - }); - - var hideHotKey = Hotkey({ - combo: "meta--", - onPress: function() { - assert.pass("second callback is called"); - hideHotKey.destroy(); - done(); - } - }); - - keyDown(element, "control-1"); -}; - -exports["test invalid combos"] = function(assert) { - assert.throws(function() { - Hotkey({ - combo: "d", - onPress: function() {} - }); - }, "throws if no modifier is present"); - assert.throws(function() { - Hotkey({ - combo: "alt", - onPress: function() {} - }); - }, "throws if no key is present"); - assert.throws(function() { - Hotkey({ - combo: "alt p b", - onPress: function() {} - }); - }, "throws if more then one key is present"); -}; - -exports["test no exception on unmodified keypress"] = function(assert) { - var element = require("window-utils").activeBrowserWindow.document.documentElement; - var someHotkey = Hotkey({ - combo: "control-alt-1", - onPress: function() { - } - }); - keyDown(element, "a"); - assert.pass("No exception throw, unmodified keypress passed"); -}; - -exports["test hotkey: automatic destroy"] = function(assert, done) { - // Hacky way to be able to create unloadable modules via makeSandboxedLoader. - let loader = Loader(module); - - var called = false; - var element = loader.require("window-utils").activeBrowserWindow.document.documentElement; - var hotkey = loader.require("hotkeys").Hotkey({ - combo: "accel-shift-x", - onPress: function() { - called = true; - } - }); - - // Unload the module so that previous hotkey is automatically destroyed - loader.unload(); - - // Ensure that the hotkey is really destroyed - keyDown(element, "accel-shift-x"); - - require("timer").setTimeout(function () { - assert.ok(!called, "Hotkey is destroyed and not called."); - done(); - }, 0); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-module.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-module.js deleted file mode 100644 index c62f923..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-module.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; - -/** Disabled because of Bug 672199 -exports["test module exports are frozen"] = function(assert) { - assert.ok(Object.isFrozen(require("addon-kit/hotkeys")), - "module exports are frozen"); -}; - -exports["test redefine exported property"] = function(assert) { - let hotkeys = require("addon-kit/hotkeys"); - let { Hotkey } = hotkeys; - try { Object.defineProperty(hotkeys, 'Hotkey', { value: {} }); } catch(e) {} - assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be redefined"); -}; -*/ - -exports["test can't delete exported property"] = function(assert) { - let hotkeys = require("addon-kit/hotkeys"); - let { Hotkey } = hotkeys; - - try { delete hotkeys.Hotkey; } catch(e) {} - assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be deleted"); -}; - -exports["test can't override exported property"] = function(assert) { - let hotkeys = require("addon-kit/hotkeys"); - let { Hotkey } = hotkeys; - - try { hotkeys.Hotkey = Object } catch(e) {} - assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be overriden"); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-notifications.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-notifications.js deleted file mode 100644 index 1eb6190..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-notifications.js +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const { Loader } = require('./helpers'); - -exports.testOnClick = function (test) { - let [loader, mockAlertServ] = makeLoader(module); - let notifs = loader.require("notifications"); - let data = "test data"; - let opts = { - onClick: function (clickedData) { - test.assertEqual(this, notifs, "|this| should be notifications module"); - test.assertEqual(clickedData, data, - "data passed to onClick should be correct"); - }, - data: data, - title: "test title", - text: "test text", - iconURL: "test icon URL" - }; - notifs.notify(opts); - mockAlertServ.click(); - loader.unload(); -}; - -// Returns [loader, mockAlertService]. -function makeLoader(test) { - let loader = Loader(module); - let mockAlertServ = { - showAlertNotification: function (imageUrl, title, text, textClickable, - cookie, alertListener, name) { - this._cookie = cookie; - this._alertListener = alertListener; - }, - click: function () { - this._alertListener.observe(null, "alertclickcallback", this._cookie); - } - }; - loader.require("notifications"); - let scope = loader.sandbox("notifications"); - scope.notify = mockAlertServ.showAlertNotification.bind(mockAlertServ); - return [loader, mockAlertServ]; -}; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-mod.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-mod.js deleted file mode 100644 index 2b38946..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-mod.js +++ /dev/null @@ -1,416 +0,0 @@ -"use strict"; - -var pageMod = require("page-mod"); -var testPageMod = require("pagemod-test-helpers").testPageMod; -const { Loader } = require('./helpers'); -const tabs = require("tabs"); - -/* XXX This can be used to delay closing the test Firefox instance for interactive - * testing or visual inspection. This test is registered first so that it runs - * the last. */ -exports.delay = function(test) { - if (false) { - test.waitUntilDone(60000); - require("timer").setTimeout(function() {test.done();}, 4000); - } else - test.pass(); -} - -/* Tests for the PageMod APIs */ - -exports.testPageMod1 = function(test) { - let mods = testPageMod(test, "about:", [{ - include: /about:/, - contentScriptWhen: 'end', - contentScript: 'new ' + function WorkerScope() { - window.document.body.setAttribute("JEP-107", "worked"); - }, - onAttach: function() { - test.assertEqual(this, mods[0], "The 'this' object is the page mod."); - } - }], - function(win, done) { - test.assertEqual( - win.document.body.getAttribute("JEP-107"), - "worked", - "PageMod.onReady test" - ); - done(); - } - ); -}; - -exports.testPageMod2 = function(test) { - testPageMod(test, "about:", [{ - include: "about:*", - contentScript: [ - 'new ' + function contentScript() { - window.AUQLUE = function() { return 42; } - try { - window.AUQLUE() - } - catch(e) { - throw new Error("PageMod scripts executed in order"); - } - document.documentElement.setAttribute("first", "true"); - }, - 'new ' + function contentScript() { - document.documentElement.setAttribute("second", "true"); - } - ] - }], function(win, done) { - test.assertEqual(win.document.documentElement.getAttribute("first"), - "true", - "PageMod test #2: first script has run"); - test.assertEqual(win.document.documentElement.getAttribute("second"), - "true", - "PageMod test #2: second script has run"); - test.assertEqual("AUQLUE" in win, false, - "PageMod test #2: scripts get a wrapped window"); - done(); - }); -}; - -exports.testPageModIncludes = function(test) { - var asserts = []; - function createPageModTest(include, expectedMatch) { - // Create an 'onload' test function... - asserts.push(function(test, win) { - var matches = include in win.localStorage; - test.assert(expectedMatch ? matches : !matches, - "'" + include + "' match test, expected: " + expectedMatch); - }); - // ...and corresponding PageMod options - return { - include: include, - contentScript: 'new ' + function() { - self.on("message", function(msg) { - window.localStorage[msg] = true; - }); - }, - // The testPageMod callback with test assertions is called on 'end', - // and we want this page mod to be attached before it gets called, - // so we attach it on 'start'. - contentScriptWhen: 'start', - onAttach: function(worker) { - worker.postMessage(this.include[0]); - } - }; - } - - testPageMod(test, "about:buildconfig", [ - createPageModTest("*", false), - createPageModTest("*.google.com", false), - createPageModTest("about:*", true), - createPageModTest("about:", false), - createPageModTest("about:buildconfig", true) - ], - function (win, done) { - test.waitUntil(function () win.localStorage["about:buildconfig"], - "about:buildconfig page-mod to be executed") - .then(function () { - asserts.forEach(function(fn) { - fn(test, win); - }); - done(); - }); - } - ); -}; - -exports.testPageModErrorHandling = function(test) { - test.assertRaises(function() { - new pageMod.PageMod(); - }, - 'pattern is undefined', - "PageMod() throws when 'include' option is not specified."); -}; - -/* Tests for internal functions. */ -exports.testCommunication1 = function(test) { - let workerDone = false, - callbackDone = null; - - testPageMod(test, "about:", [{ - include: "about:*", - contentScriptWhen: 'end', - contentScript: 'new ' + function WorkerScope() { - self.on('message', function(msg) { - document.body.setAttribute('JEP-107', 'worked'); - self.postMessage(document.body.getAttribute('JEP-107')); - }) - }, - onAttach: function(worker) { - worker.on('error', function(e) { - test.fail('Errors where reported'); - }); - worker.on('message', function(value) { - test.assertEqual( - "worked", - value, - "test comunication" - ); - workerDone = true; - if (callbackDone) - callbackDone(); - }); - worker.postMessage('do it!') - } - }], - function(win, done) { - (callbackDone = function() { - if (workerDone) { - test.assertEqual( - 'worked', - win.document.body.getAttribute('JEP-107'), - 'attribute should be modified' - ); - done(); - } - })(); - } - ); -}; - -exports.testCommunication2 = function(test) { - let callbackDone = null, - window; - - testPageMod(test, "about:", [{ - include: "about:*", - contentScriptWhen: 'start', - contentScript: 'new ' + function WorkerScope() { - document.documentElement.setAttribute('AUQLUE', 42); - window.addEventListener('load', function listener() { - self.postMessage('onload'); - }, false); - self.on("message", function() { - self.postMessage(document.documentElement.getAttribute("test")) - }); - }, - onAttach: function(worker) { - worker.on('error', function(e) { - test.fail('Errors where reported'); - }); - worker.on('message', function(msg) { - if ('onload' == msg) { - test.assertEqual( - '42', - window.document.documentElement.getAttribute('AUQLUE'), - 'PageMod scripts executed in order' - ); - window.document.documentElement.setAttribute('test', 'changes in window'); - worker.postMessage('get window.test') - } else { - test.assertEqual( - 'changes in window', - msg, - 'PageMod test #2: second script has run' - ) - callbackDone(); - } - }); - } - }], - function(win, done) { - window = win; - callbackDone = done; - } - ); -}; - -exports.testEventEmitter = function(test) { - let workerDone = false, - callbackDone = null; - - testPageMod(test, "about:", [{ - include: "about:*", - contentScript: 'new ' + function WorkerScope() { - self.port.on('addon-to-content', function(data) { - self.port.emit('content-to-addon', data); - }); - }, - onAttach: function(worker) { - worker.on('error', function(e) { - test.fail('Errors were reported : '+e); - }); - worker.port.on('content-to-addon', function(value) { - test.assertEqual( - "worked", - value, - "EventEmitter API works!" - ); - if (callbackDone) - callbackDone(); - else - workerDone = true; - }); - worker.port.emit('addon-to-content', 'worked'); - } - }], - function(win, done) { - if (workerDone) - done(); - else - callbackDone = done; - } - ); -}; - -// Execute two concurrent page mods on same document to ensure that their -// JS contexts are different -exports.testMixedContext = function(test) { - let doneCallback = null; - let messages = 0; - let modObject = { - include: "data:text/html,", - contentScript: 'new ' + function WorkerScope() { - // Both scripts will execute this, - // context is shared if one script see the other one modification. - let isContextShared = "sharedAttribute" in document; - self.postMessage(isContextShared); - document.sharedAttribute = true; - }, - onAttach: function(w) { - w.on("message", function (isContextShared) { - if (isContextShared) { - test.fail("Page mod contexts are mixed."); - doneCallback(); - } - else if (++messages == 2) { - test.pass("Page mod contexts are different."); - doneCallback(); - } - }); - } - }; - testPageMod(test, "data:text/html,", [modObject, modObject], - function(win, done) { - doneCallback = done; - } - ); -}; - -exports.testHistory = function(test) { - // 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("self").data.url("test-page-mod.html"); - let callbackDone = null; - testPageMod(test, url, [{ - include: url, - contentScriptWhen: 'end', - contentScript: 'new ' + function WorkerScope() { - history.pushState({}, "", "#"); - history.replaceState({foo: "bar"}, "", "#"); - self.postMessage(history.state); - }, - onAttach: function(worker) { - worker.on('message', function (data) { - test.assertEqual(JSON.stringify(data), JSON.stringify({foo: "bar"}), - "History API works!"); - callbackDone(); - }); - } - }], - function(win, done) { - callbackDone = done; - } - ); -}; - -exports.testRelatedTab = function(test) { - test.waitUntilDone(); - - let tab; - let { PageMod } = require("page-mod"); - let pageMod = new PageMod({ - include: "about:*", - onAttach: function(worker) { - test.assertEqual(tab, worker.tab, "Worker.tab is valid"); - pageMod.destroy(); - tab.close(); - test.done(); - } - }); - - tabs.open({ - url: "about:", - onOpen: function onOpen(t) { - tab = t; - } - }); - -}; - -exports['test tab worker on message'] = function(test) { - test.waitUntilDone(); - - let { browserWindows } = require("windows"); - let tabs = require("tabs"); - let { PageMod } = require("page-mod"); - - let url1 = "data:text/html,<title>tab1</title><h1>worker1.tab</h1>"; - let url2 = "data:text/html,<title>tab2</title><h1>worker2.tab</h1>"; - let worker1 = null; - - let mod = PageMod({ - include: "data:text/html,*", - contentScriptWhen: "ready", - contentScript: "self.postMessage('#1');", - onAttach: function onAttach(worker) { - worker.on("message", function onMessage() { - this.tab.attach({ - contentScriptWhen: "ready", - contentScript: "self.postMessage({ url: window.location.href, title: document.title });", - onMessage: function onMessage(data) { - test.assertEqual(this.tab.url, data.url, "location is correct"); - test.assertEqual(this.tab.title, data.title, "title is correct"); - if (this.tab.url === url1) { - worker1 = this; - tabs.open({ url: url2, inBackground: true }); - } - else if (this.tab.url === url2) { - mod.destroy(); - worker1.tab.close(); - worker1.destroy(); - worker.tab.close(); - worker.destroy(); - test.done(); - } - } - }); - }); - } - }); - - tabs.open(url1); -}; - -exports.testAutomaticDestroy = function(test) { - test.waitUntilDone(); - let loader = Loader(module); - - let pageMod = loader.require("page-mod").PageMod({ - include: "about:*", - contentScriptWhen: "start", - onAttach: function(w) { - test.fail("Page-mod should have been detroyed during module unload"); - } - }); - - // Unload the page-mod module so that our page mod is destroyed - loader.unload(); - - // Then create a second tab to ensure that it is correctly destroyed - let tabs = require("tabs"); - tabs.open({ - url: "about:", - onReady: function onReady(tab) { - test.pass("check automatic destroy"); - tab.close(); - test.done(); - } - }); - -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-worker.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-worker.js deleted file mode 100644 index 89cdf45..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-page-worker.js +++ /dev/null @@ -1,362 +0,0 @@ -let tests = {}, Pages, Page; -const { Loader } = require('./helpers'); - -const ERR_DESTROYED = - "The page has been destroyed and can no longer be used."; - -tests.testSimplePageCreation = function(test) { - test.waitUntilDone(); - - let page = new Page({ - contentScript: "self.postMessage(window.location.href)", - contentScriptWhen: "end", - onMessage: function (message) { - test.assertEqual(message, "about:blank", - "Page Worker should start with a blank page by default"); - test.assertEqual(this, page, "The 'this' object is the page itself."); - test.done(); - } - }); -} - -/* - * Tests that we can't be tricked by document overloads as we have access - * to wrapped nodes - */ -tests.testWrappedDOM = function(test) { - test.waitUntilDone(); - - let page = Page({ - allow: { script: true }, - contentURL: "data:text/html,<script>document.getElementById=3;window.scrollTo=3;</script>", - contentScript: "window.addEventListener('load', function () " + - "self.postMessage([typeof(document.getElementById), " + - "typeof(window.scrollTo)]), true)", - onMessage: function (message) { - test.assertEqual(message[0], - "function", - "getElementById from content script is the native one"); - - test.assertEqual(message[1], - "function", - "scrollTo from content script is the native one"); - - test.done(); - } - }); -} - -/* -// We do not offer unwrapped access to DOM since bug 601295 landed -// See 660780 to track progress of unwrap feature -tests.testUnwrappedDOM = function(test) { - test.waitUntilDone(); - - let page = Page({ - allow: { script: true }, - contentURL: "data:text/html,<script>document.getElementById=3;window.scrollTo=3;</script>", - contentScript: "window.addEventListener('load', function () " + - "self.postMessage([typeof(unsafeWindow.document.getElementById), " + - "typeof(unsafeWindow.scrollTo)]), true)", - onMessage: function (message) { - test.assertEqual(message[0], - "number", - "document inside page is free to be changed"); - - test.assertEqual(message[1], - "number", - "window inside page is free to be changed"); - - test.done(); - } - }); -} -*/ - -tests.testPageProperties = function(test) { - let page = new Page(); - - for each (let prop in ['contentURL', 'allow', 'contentScriptFile', - 'contentScript', 'contentScriptWhen', 'on', - 'postMessage', 'removeListener']) { - test.assert(prop in page, prop + " property is defined on page."); - } - - test.assert(function () page.postMessage("foo") || true, - "postMessage doesn't throw exception on page."); -} - -tests.testConstructorAndDestructor = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let Pages = loader.require("page-worker"); - let global = loader.sandbox("page-worker"); - - let pagesReady = 0; - - let page1 = Pages.Page({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: pageReady - }); - let page2 = Pages.Page({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: pageReady - }); - - test.assertNotEqual(page1, page2, - "Page 1 and page 2 should be different objects."); - - function pageReady() { - if (++pagesReady == 2) { - page1.destroy(); - page2.destroy(); - - test.assert(isDestroyed(page1), "page1 correctly unloaded."); - test.assert(isDestroyed(page2), "page2 correctly unloaded."); - - loader.unload(); - test.done(); - } - } -} - -tests.testAutoDestructor = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let Pages = loader.require("page-worker"); - - let page = Pages.Page({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: function() { - loader.unload(); - test.assert(isDestroyed(page), "Page correctly unloaded."); - test.done(); - } - }); -} - -tests.testValidateOptions = function(test) { - test.assertRaises( - function () Page({ contentURL: 'home' }), - "The `contentURL` option must be a valid URL.", - "Validation correctly denied a non-URL contentURL" - ); - - test.assertRaises( - function () Page({ onMessage: "This is not a function."}), - "The event listener must be a function.", - "Validation correctly denied a non-function onMessage." - ); - - test.pass("Options validation is working."); -} - -tests.testContentAndAllowGettersAndSetters = function(test) { - test.waitUntilDone(); - let content = "data:text/html,<script>window.localStorage.allowScript=3;</script>"; - let page = Page({ - contentURL: content, - contentScript: "self.postMessage(window.localStorage.allowScript)", - contentScriptWhen: "end", - onMessage: step0 - }); - - function step0(message) { - test.assertEqual(message, "3", - "Correct value expected for allowScript - 3"); - test.assertEqual(page.contentURL, content, - "Correct content expected"); - page.removeListener('message', step0); - page.on('message', step1); - page.allow = { script: false }; - page.contentURL = content = - "data:text/html,<script>window.localStorage.allowScript='f'</script>"; - } - - function step1(message) { - test.assertEqual(message, "3", - "Correct value expected for allowScript - 3"); - test.assertEqual(page.contentURL, content, "Correct content expected"); - page.removeListener('message', step1); - page.on('message', step2); - page.allow = { script: true }; - page.contentURL = content = - "data:text/html,<script>window.localStorage.allowScript='g'</script>"; - } - - function step2(message) { - test.assertEqual(message, "g", - "Correct value expected for allowScript - g"); - test.assertEqual(page.contentURL, content, "Correct content expected"); - page.removeListener('message', step2); - page.on('message', step3); - page.allow.script = false; - page.contentURL = content = - "data:text/html,<script>window.localStorage.allowScript=3</script>"; - } - - function step3(message) { - test.assertEqual(message, "g", - "Correct value expected for allowScript - g"); - test.assertEqual(page.contentURL, content, "Correct content expected"); - page.removeListener('message', step3); - page.on('message', step4); - page.allow.script = true; - page.contentURL = content = - "data:text/html,<script>window.localStorage.allowScript=4</script>"; - } - - function step4(message) { - test.assertEqual(message, "4", - "Correct value expected for allowScript - 4"); - test.assertEqual(page.contentURL, content, "Correct content expected"); - test.done(); - } - -} - -tests.testOnMessageCallback = function(test) { - test.waitUntilDone(); - - Page({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: function() { - test.pass("onMessage callback called"); - test.done(); - } - }); -} - -tests.testMultipleOnMessageCallbacks = function(test) { - test.waitUntilDone(); - - let count = 0; - let page = Page({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: function() count += 1 - }); - page.on('message', function() count += 2); - page.on('message', function() count *= 3); - page.on('message', function() - test.assertEqual(count, 9, "All callbacks were called, in order.")); - page.on('message', function() test.done()); - -} - -tests.testLoadContentPage = function(test) { - - test.waitUntilDone(); - - let page = Page({ - onMessage: function(message) { - // The message is an array whose first item is the test method to call - // and the rest of whose items are arguments to pass it. - test[message.shift()].apply(test, message); - }, - contentURL: require("self").data.url("test-page-worker.html"), - contentScriptFile: require("self").data.url("test-page-worker.js"), - contentScriptWhen: "ready" - }); - -} - -tests.testAllowScriptDefault = function(test) { - - test.waitUntilDone(); - - let page = Page({ - onMessage: function(message) { - test.assert(message, "Script is allowed to run by default."); - test.done(); - }, - contentURL: "data:text/html,<script>document.documentElement.setAttribute('foo', 3);</script>", - contentScript: "self.postMessage(document.documentElement.getAttribute('foo'))", - contentScriptWhen: "ready" - }); -} - -tests.testAllowScript = function(test) { - - test.waitUntilDone(); - - let page = Page({ - onMessage: function(message) { - test.assert(message, "Script runs when allowed to do so."); - test.done(); - }, - allow: { script: true }, - contentURL: "data:text/html,<script>document.documentElement.setAttribute('foo', 3);</script>", - contentScript: "self.postMessage(document.documentElement.hasAttribute('foo') && " + - " document.documentElement.getAttribute('foo') == 3)", - contentScriptWhen: "ready" - }); -} - -tests.testPingPong = function(test) { - test.waitUntilDone(); - let page = Page({ - contentURL: 'data:text/html,ping-pong', - contentScript: 'self.on("message", function(message) self.postMessage("pong"));' - + 'self.postMessage("ready");', - onMessage: function(message) { - if ('ready' == message) { - page.postMessage('ping'); - } - else { - test.assert(message, 'pong', 'Callback from contentScript'); - test.done(); - } - } - }); -}; - -tests.testMultipleDestroys = function(test) { - let page = Page(); - page.destroy(); - page.destroy(); - test.pass("Multiple destroys should not cause an error"); -}; - - -function isDestroyed(page) { - try { - page.postMessage("foo"); - } - catch (err if err.message == ERR_DESTROYED) { - return true; - } - return false; -} - - -let pageWorkerSupported = true; - -try { - Pages = require("page-worker"); - Page = Pages.Page; -} -catch (ex if ex.message == [ - "The page-worker module currently supports only Firefox and Thunderbird. ", - "In the future, we would like it to support other applications, however. ", - "Please see https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more ", - "information." - ].join("")) { - pageWorkerSupported = false; -} - -if (pageWorkerSupported) { - for (let test in tests) { - exports[test] = tests[test]; - } -} else { - exports.testPageWorkerNotSupported = function(test) { - test.pass("The page-worker module is not supported on this app."); - } -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-panel.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-panel.js deleted file mode 100644 index 3e240db..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-panel.js +++ /dev/null @@ -1,437 +0,0 @@ -let { Cc, Ci } = require("chrome"); -let panels = require('panel'); -let tests = {}, panels, Panel; -const { Loader } = require('./helpers'); - -tests.testPanel = function(test) { - test.waitUntilDone(); - let panel = Panel({ - contentURL: "about:buildconfig", - contentScript: "self.postMessage(1); self.on('message', function() self.postMessage(2));", - onMessage: function (message) { - test.assertEqual(this, panel, "The 'this' object is the panel."); - switch(message) { - case 1: - test.pass("The panel was loaded."); - panel.postMessage(''); - break; - case 2: - test.pass("The panel posted a message and received a response."); - panel.destroy(); - test.done(); - break; - } - } - }); -}; - -tests.testPanelEmit = function(test) { - test.waitUntilDone(); - let panel = Panel({ - contentURL: "about:buildconfig", - contentScript: "self.port.emit('loaded');" + - "self.port.on('addon-to-content', " + - " function() self.port.emit('received'));", - }); - panel.port.on("loaded", function () { - test.pass("The panel was loaded and sent a first event."); - panel.port.emit("addon-to-content"); - }); - panel.port.on("received", function () { - test.pass("The panel posted a message and received a response."); - panel.destroy(); - test.done(); - }); -}; - -tests.testPanelEmitEarly = function(test) { - test.waitUntilDone(); - let panel = Panel({ - contentURL: "about:buildconfig", - contentScript: "self.port.on('addon-to-content', " + - " function() self.port.emit('received'));", - }); - panel.port.on("received", function () { - test.pass("The panel posted a message early and received a response."); - panel.destroy(); - test.done(); - }); - panel.port.emit("addon-to-content"); -}; - -tests.testShowHidePanel = function(test) { - test.waitUntilDone(); - let panel = Panel({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - onMessage: function (message) { - panel.show(); - }, - onShow: function () { - test.pass("The panel was shown."); - test.assertEqual(this, panel, "The 'this' object is the panel."); - test.assertEqual(this.isShowing, true, "panel.isShowing == true."); - panel.hide(); - }, - onHide: function () { - test.pass("The panel was hidden."); - test.assertEqual(this, panel, "The 'this' object is the panel."); - test.assertEqual(this.isShowing, false, "panel.isShowing == false."); - panel.destroy(); - test.done(); - } - }); -}; - -tests.testDocumentReload = function(test) { - test.waitUntilDone(); - let content = - "<script>" + - "setTimeout(function () {" + - " window.location = 'about:blank';" + - "}, 250);" + - "</script>"; - let messageCount = 0; - let panel = Panel({ - contentURL: "data:text/html," + encodeURIComponent(content), - contentScript: "self.postMessage(window.location.href)", - onMessage: function (message) { - messageCount++; - if (messageCount == 1) { - test.assertMatches(message, /data:text\/html,/, "First document had a content script"); - } - else if (messageCount == 2) { - test.assertEqual(message, "about:blank", "Second document too"); - panel.destroy(); - test.done(); - } - } - }); -}; - -tests.testParentResizeHack = function(test) { - let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); - let docShell = browserWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - if (!("allowWindowControl" in docShell)) { - // bug 635673 is not fixed in this firefox build - test.pass("allowWindowControl attribute that allow to fix browser window " + - "resize is not available on this build."); - return; - } - - test.waitUntilDone(30000); - - let previousWidth = browserWindow.outerWidth, previousHeight = browserWindow.outerHeight; - - let content = "<script>" + - "function contentResize() {" + - " resizeTo(200,200);" + - " resizeBy(200,200);" + - "}" + - "</script>" + - "Try to resize browser window"; - let panel = Panel({ - contentURL: "data:text/html," + encodeURIComponent(content), - contentScript: "self.on('message', function(message){" + - " if (message=='resize') " + - " unsafeWindow.contentResize();" + - "});", - contentScriptWhen: "ready", - onMessage: function (message) { - - }, - onShow: function () { - panel.postMessage('resize'); - require("timer").setTimeout(function () { - test.assertEqual(previousWidth,browserWindow.outerWidth,"Size doesn't change by calling resizeTo/By/..."); - test.assertEqual(previousHeight,browserWindow.outerHeight,"Size doesn't change by calling resizeTo/By/..."); - panel.destroy(); - test.done(); - },0); - } - }); - panel.show(); -} - -tests.testResizePanel = function(test) { - test.waitUntilDone(); - - // These tests fail on Linux if the browser window in which the panel - // is displayed is not active. And depending on what other tests have run - // before this one, it might not be (the untitled window in which the test - // runner executes is often active). So we make sure the browser window - // is focused by focusing it before running the tests. Then, to be the best - // possible test citizen, we refocus whatever window was focused before we - // started running these tests. - - let activeWindow = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher). - activeWindow; - let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); - - - function onFocus() { - browserWindow.removeEventListener("focus", onFocus, true); - - let panel = Panel({ - contentScript: "self.postMessage('')", - contentScriptWhen: "end", - height: 10, - width: 10, - onMessage: function (message) { - panel.show(); - }, - onShow: function () { - panel.resize(100,100); - panel.hide(); - }, - onHide: function () { - test.assert((panel.width == 100) && (panel.height == 100), - "The panel was resized."); - if (activeWindow) - activeWindow.focus(); - test.done(); - } - }); - } - - if (browserWindow === activeWindow) { - onFocus(); - } - else { - browserWindow.addEventListener("focus", onFocus, true); - browserWindow.focus(); - } -}; - -tests.testHideBeforeShow = function(test) { - test.waitUntilDone(); - let showCalled = false; - let panel = Panel({ - onShow: function () { - showCalled = true; - }, - onHide: function () { - test.assert(!showCalled, 'must not emit show if was hidden before'); - test.done(); - } - }); - panel.show(); - panel.hide(); -}; - -tests.testSeveralShowHides = function(test) { - test.waitUntilDone(); - let hideCalled = 0; - let panel = panels.Panel({ - contentURL: "about:buildconfig", - onShow: function () { - panel.hide(); - }, - onHide: function () { - hideCalled++; - if (hideCalled < 3) - panel.show(); - else { - test.pass("onHide called three times as expected"); - test.done(); - } - } - }); - panel.on('error', function(e) { - test.fail('error was emitted:' + e.message + '\n' + e.stack); - }); - panel.show(); -}; - -tests.testAnchorAndArrow = function(test) { - test.waitUntilDone(20000); - let count = 0; - function newPanel(tab, anchor) { - let panel = panels.Panel({ - contentURL: "data:text/html,<html><body style='padding: 0; margin: 0; " + - "background: gray; text-align: center;'>Anchor: " + - anchor.id + "</body></html>", - width: 200, - height: 100, - onShow: function () { - count++; - panel.destroy(); - if (count==5) { - test.pass("All anchored panel test displayed"); - tab.close(function () { - test.done(); - }); - } - } - }); - panel.show(anchor); - } - - let tabs= require("tabs"); - let url = 'data:text/html,' + - '<html><head><title>foo</title></head><body>' + - '<style>div {background: gray; position: absolute; width: 300px; ' + - 'border: 2px solid black;}</style>' + - '<div id="tl" style="top: 0px; left: 0px;">Top Left</div>' + - '<div id="tr" style="top: 0px; right: 0px;">Top Right</div>' + - '<div id="bl" style="bottom: 0px; left: 0px;">Bottom Left</div>' + - '<div id="br" style="bottom: 0px; right: 0px;">Bottom right</div>' + - '</body></html>'; - - tabs.open({ - url: url, - onReady: function(tab) { - let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); - let window = browserWindow.content; - newPanel(tab, window.document.getElementById('tl')); - newPanel(tab, window.document.getElementById('tr')); - newPanel(tab, window.document.getElementById('bl')); - newPanel(tab, window.document.getElementById('br')); - let anchor = browserWindow.document.getElementById("identity-box"); - newPanel(tab, anchor); - } - }); - - - -}; - -tests.testPanelTextColor = function(test) { - test.waitUntilDone(); - let html = "<html><head><style>body {color: yellow}</style></head>" + - "<body><p>Foo</p></body></html>"; - let panel = Panel({ - contentURL: "data:text/html," + encodeURI(html), - contentScript: "self.port.emit('color', " + - "window.getComputedStyle(document.body.firstChild, null). " + - " getPropertyValue('color'));" - }); - panel.port.on("color", function (color) { - test.assertEqual(color, "rgb(255, 255, 0)", - "The panel text color style is preserved when a style exists."); - panel.destroy(); - test.done(); - }); -}; - -function makeEventOrderTest(options) { - let expectedEvents = []; - - return function(test) { - let panel = panels.Panel({ contentURL: "about:buildconfig" }); - - function expect(event, cb) { - expectedEvents.push(event); - panel.on(event, function() { - test.assertEqual(event, expectedEvents.shift()); - if (cb) - require("timer").setTimeout(cb, 1); - }); - return {then: expect}; - } - - test.waitUntilDone(); - options.test(test, expect, panel); - } -} - -tests.testAutomaticDestroy = function(test) { - let loader = Loader(module); - let panel = loader.require("panel").Panel({ - contentURL: "about:buildconfig", - contentScript: - "self.port.on('event', function() self.port.emit('event-back'));" - }); - - loader.unload(); - - panel.port.on("event-back", function () { - test.fail("Panel should have been destroyed on module unload"); - }); - panel.port.emit("event"); - test.pass("check automatic destroy"); -}; - -tests.testWaitForInitThenShowThenDestroy = makeEventOrderTest({ - test: function(test, expect, panel) { - expect('inited', function() { panel.show(); }). - then('show', function() { panel.destroy(); }). - then('hide', function() { test.done(); }); - } -}); - -tests.testShowThenWaitForInitThenDestroy = makeEventOrderTest({ - test: function(test, expect, panel) { - panel.show(); - expect('inited'). - then('show', function() { panel.destroy(); }). - then('hide', function() { test.done(); }); - } -}); - -tests.testShowThenHideThenDestroy = makeEventOrderTest({ - test: function(test, expect, panel) { - panel.show(); - expect('show', function() { panel.hide(); }). - then('hide', function() { panel.destroy(); test.done(); }); - } -}); - -tests.testContentURLOption = function(test) { - const URL_STRING = "about:buildconfig"; - const HTML_CONTENT = "<html><title>Test</title><p>This is a test.</p></html>"; - - let (panel = Panel({ contentURL: URL_STRING })) { - test.pass("contentURL accepts a string URL."); - test.assertEqual(panel.contentURL, URL_STRING, - "contentURL is the string to which it was set."); - } - - let dataURL = "data:text/html," + encodeURIComponent(HTML_CONTENT); - let (panel = Panel({ contentURL: dataURL })) { - test.pass("contentURL accepts a data: URL."); - } - - let (panel = Panel({})) { - test.assert(panel.contentURL == null, - "contentURL is undefined."); - } - - test.assertRaises(function () Panel({ contentURL: "foo" }), - "The `contentURL` option must be a valid URL.", - "Panel throws an exception if contentURL is not a URL."); -}; - -let panelSupported = true; - -try { - panels = require("panel"); - Panel = panels.Panel; -} -catch(ex if ex.message == [ - "The panel module currently supports only Firefox. In the future ", - "we would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=jetpack-panel-apps ", - "for more information." - ].join("")) { - panelSupported = false; -} - -if (panelSupported) { - for (let test in tests) - exports[test] = tests[test]; -} -else { - exports.testPanelNotSupported = function(test) { - test.pass("The panel module is not supported on this app."); - } -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-passwords.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-passwords.js deleted file mode 100644 index e799b48..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-passwords.js +++ /dev/null @@ -1,277 +0,0 @@ -"use strict"; - -const { store, search, remove } = require("passwords"); - -exports["test store requires `password` field"] = function(assert, done) { - store({ - username: "foo", - realm: "bar", - onComplete: function onComplete() { - assert.fail("onComplete should not be called"); - }, - onError: function onError() { - assert.pass("'`password` is required"); - done(); - } - }); -}; - -exports["test store requires `username` field"] = function(assert, done) { - store({ - password: "foo", - realm: "bar", - onComplete: function onComplete() { - assert.fail("onComplete should not be called"); - }, - onError: function onError() { - assert.pass("'`username` is required"); - done(); - } - }); -}; - -exports["test onComplete is optional"] = function(assert, done) { - store({ - realm: "bla", - username: "bla", - password: "bla", - onError: function onError() { - assert.fail("onError was called"); - } - }); - assert.pass("exception is not thrown if `onComplete is missing") - done(); -}; - -exports["test exceptions in onComplete are reported"] = function(assert, done) { - store({ - realm: "throws", - username: "error", - password: "boom!", - onComplete: function onComplete(error) { - throw new Error("Boom!") - }, - onError: function onError(error) { - assert.equal(error.message, "Boom!", "Error thrown is reported"); - done(); - } - }); -}; - -exports["test store requires `realm` field"] = function(assert, done) { - store({ - username: "foo", - password: "bar", - onComplete: function onComplete() { - assert.fail("onComplete should not be called"); - }, - onError: function onError() { - assert.pass("'`realm` is required"); - done(); - } - }); -}; - -exports["test can't store same login twice"] = function(assert, done) { - store({ - username: "user", - password: "pass", - realm: "realm", - onComplete: function onComplete() { - assert.pass("credential saved"); - - store({ - username: "user", - password: "pass", - realm: "realm", - onComplete: function onComplete() { - assert.fail("onComplete should not be called"); - }, - onError: function onError() { - assert.pass("re-saving credential failed"); - - remove({ - username: "user", - password: "pass", - realm: "realm", - onComplete: function onComplete() { - assert.pass("credential was removed"); - done(); - }, - onError: function onError() { - assert.fail("remove should not fail"); - } - }); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); -}; - -exports["test remove fails if no login found"] = function(assert, done) { - remove({ - username: "foo", - password: "bar", - realm: "baz", - onComplete: function onComplete() { - assert.fail("should not be able to remove unstored credentials"); - }, - onError: function onError() { - assert.pass("can't remove unstored credentials"); - done(); - } - }); -}; - -exports["test addon associated credentials"] = function(assert, done) { - store({ - username: "foo", - password: "bar", - realm: "baz", - onComplete: function onComplete() { - search({ - username: "foo", - password: "bar", - realm: "baz", - onComplete: function onComplete([credential]) { - assert.equal(credential.url.indexOf("addon:"), 0, - "`addon:` uri is used for add-on credentials"); - assert.equal(credential.username, "foo", - "username matches"); - assert.equal(credential.password, "bar", - "password matches"); - assert.equal(credential.realm, "baz", "realm matches"); - assert.equal(credential.formSubmitURL, null, - "`formSubmitURL` is `null` for add-on credentials"); - assert.equal(credential.usernameField, "", "usernameField is empty"); - assert.equal(credential.passwordField, "", "passwordField is empty"); - - remove({ - username: credential.username, - password: credential.password, - realm: credential.realm, - onComplete: function onComplete() { - assert.pass("credential is removed"); - done(); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); -}; - -exports["test web page associated credentials"] = function(assert, done) { - store({ - url: "http://bar.foo.com/authentication/?login", - formSubmitURL: "http://login.foo.com/authenticate.cgi", - username: "user", - password: "pass", - usernameField: "user-f", - passwordField: "pass-f", - onComplete: function onComplete() { - search({ - username: "user", - password: "pass", - url: "http://bar.foo.com", - formSubmitURL: "http://login.foo.com", - onComplete: function onComplete([credential]) { - assert.equal(credential.url, "http://bar.foo.com", "url matches"); - assert.equal(credential.username, "user", "username matches"); - assert.equal(credential.password, "pass", "password matches"); - assert.equal(credential.realm, null, "realm is null"); - assert.equal(credential.formSubmitURL, "http://login.foo.com", - "formSubmitURL matches"); - assert.equal(credential.usernameField, "user-f", - "usernameField is matches"); - assert.equal(credential.passwordField, "pass-f", - "passwordField matches"); - - remove({ - url: credential.url, - formSubmitURL: credential.formSubmitURL, - username: credential.username, - password: credential.password, - usernameField: credential.usernameField, - passwordField: credential.passwordField, - - onComplete: function onComplete() { - assert.pass("credential is removed"); - done(); - }, - onError: function onError(e) { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); -}; - -exports["test site authentication credentials"] = function(assert, done) { - store({ - url: "http://authentication.com", - username: "U", - password: "P", - realm: "R", - onComplete: function onComplete() { - search({ - url: "http://authentication.com", - username: "U", - password: "P", - realm: "R", - onComplete: function onComplete([credential]) { - assert.equal(credential.url,"http://authentication.com", - "url matches"); - assert.equal(credential.username, "U", "username matches"); - assert.equal(credential.password, "P", "password matches"); - assert.equal(credential.realm, "R", "realm matches"); - assert.equal(credential.formSubmitURL, null, "formSubmitURL is null"); - assert.equal(credential.usernameField, "", "usernameField is empty"); - assert.equal(credential.passwordField, "", "passwordField is empty"); - - remove({ - url: credential.url, - username: credential.username, - password: credential.password, - realm: credential.realm, - onComplete: function onComplete() { - assert.pass("credential is removed"); - done(); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); - }, - onError: function onError() { - assert.fail("onError should not be called"); - } - }); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-private-browsing.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-private-browsing.js deleted file mode 100644 index a3c1519..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-private-browsing.js +++ /dev/null @@ -1,238 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Paul O’Shannessy <paul@oshannessy.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -let pb = require("private-browsing"); -let {Cc,Ci} = require("chrome"); -const { Loader } = require('./helpers'); - -let pbService; -// Currently, only Firefox implements the private browsing service. -if (require("xul-app").is("Firefox")) { - pbService = Cc["@mozilla.org/privatebrowsing;1"]. - getService(Ci.nsIPrivateBrowsingService); -} - -if (pbService) { - - // tests that isActive has the same value as the private browsing service - // expects - exports.testGetIsActive = function (test) { - test.assertEqual(pb.isActive, false, - "private-browsing.isActive is correct without modifying PB service"); - - pbService.privateBrowsingEnabled = true; - test.assert(pb.isActive, - "private-browsing.isActive is correct after modifying PB service"); - - // Switch back to normal mode. - pbService.privateBrowsingEnabled = false; - }; - - // tests that activating does put the browser into private browsing mode - exports.testActivateDeactivate = function (test) { - test.waitUntilDone(); - pb.once("start", function onStart() { - test.assertEqual(pbService.privateBrowsingEnabled, true, - "private browsing mode was activated"); - pb.deactivate(); - }); - pb.once("stop", function onStop() { - test.assertEqual(pbService.privateBrowsingEnabled, false, - "private browsing mode was deactivate"); - test.done(); - }); - pb.activate(); - }; - - exports.testStart = function(test) { - test.waitUntilDone(); - pb.on("start", function onStart() { - test.assertEqual(this, pb, "`this` should be private-browsing module"); - test.assert(pbService.privateBrowsingEnabled, - 'private mode is active when "start" event is emitted'); - test.assert(pb.isActive, - '`isActive` is `true` when "start" event is emitted'); - pb.removeListener("start", onStart); - test.done(); - }); - pb.activate(); - }; - - exports.testStop = function(test) { - test.waitUntilDone(); - pb.on("stop", function onStop() { - test.assertEqual(this, pb, "`this` should be private-browsing module"); - test.assertEqual(pbService.privateBrowsingEnabled, false, - "private mode is disabled when stop event is emitted"); - test.assertEqual(pb.isActive, false, - "`isActive` is `false` when stop event is emitted"); - pb.removeListener("stop", onStop); - test.done(); - }); - pb.activate(); - pb.deactivate(); - }; - - exports.testAutomaticUnload = function(test) { - test.waitUntilDone(); - // Create another private browsing instance and unload it - let loader = Loader(module); - let pb2 = loader.require("private-browsing"); - let called = false; - pb2.on("start", function onStart() { - called = true; - test.fail("should not be called:x"); - }); - loader.unload(); - - // Then switch to private mode in order to check that the previous instance - // is correctly destroyed - pb.activate(); - pb.once("start", function onStart() { - require("timer").setTimeout(function () { - test.assert(!called, - "First private browsing instance is destroyed and inactive"); - - // Must reset to normal mode, so that next test starts with it. - pb.deactivate(); - test.done(); - }, 0); - }); - }; - - exports.testBothListeners = function(test) { - test.waitUntilDone(); - let stop = false; - let start = false; - - function onStop() { - test.assertEqual(stop, false, - "stop callback must be called only once"); - test.assertEqual(pbService.privateBrowsingEnabled, false, - "private mode is disabled when stop event is emitted"); - test.assertEqual(pb.isActive, false, - "`isActive` is `false` when stop event is emitted"); - - pb.on("start", finish); - pb.removeListener("start", onStart); - pb.removeListener("start", onStart2); - pb.activate(); - stop = true; - } - - function onStart() { - test.assertEqual(false, start, - "stop callback must be called only once"); - test.assert(pbService.privateBrowsingEnabled, - "private mode is active when start event is emitted"); - test.assert(pb.isActive, - "`isActive` is `true` when start event is emitted"); - - pb.on("stop", onStop); - pb.deactivate(); - start = true; - } - - function onStart2() { - test.assert(start, "start listener must be called already"); - test.assertEqual(false, stop, "stop callback must not be called yet"); - } - - function finish() { - test.assert(pbService.privateBrowsingEnabled, true, - "private mode is active when start event is emitted"); - test.assert(pb.isActive, - "`isActive` is `true` when start event is emitted"); - - pb.removeListener("start", finish); - pb.removeListener("stop", onStop); - - pb.deactivate(); - pb.once("stop", function () { - test.assertEqual(pbService.privateBrowsingEnabled, false); - test.assertEqual(pb.isActive, false); - - test.done(); - }); - } - - pb.on("start", onStart); - pb.on("start", onStart2); - pbService.privateBrowsingEnabled = true; - }; - - exports["test activate private mode via handler"] = function(test) { - const tabs = require("tabs"); - - test.waitUntilDone(); - function onReady(tab) { - if (tab.url == "about:robots") - tab.close(function() pb.activate()); - } - function cleanup(tab) { - if (tab.url == "about:") { - tabs.removeListener("ready", cleanup); - tab.close(function onClose() { - test.done(); - }); - } - } - - tabs.on("ready", onReady); - pb.once("start", function onStart() { - test.pass("private mode was activated"); - pb.deactivate(); - }); - pb.once("stop", function onStop() { - test.pass("private mode was deactivated"); - tabs.removeListener("ready", onReady); - tabs.on("ready", cleanup); - }); - tabs.once("open", function onOpen() { - tabs.open("about:robots"); - }); - tabs.open("about:"); - }; -} -else { - // tests for the case where private browsing doesn't exist - exports.testNoImpl = function (test) { - test.assertEqual(pb.isActive, false, - "pb.isActive returns false when private browsing isn't supported"); - }; -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-request.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-request.js deleted file mode 100644 index 8b8300e..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-request.js +++ /dev/null @@ -1,358 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Paul O’Shannessy <paul@oshannessy.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const Request = require("request").Request; - -var port = 8080; -var data = require("self").data; -var testFilePath = require("url").toFilename(data.url("test-request.txt")); -var basePath = require("file").dirname(testFilePath); - -var {startServerAsync} = require("httpd"); - -exports.testOptionsValidator = function(test) { - // First, a simple test to make sure we didn't break normal functionality. - test.assertRaises(function () { - Request({ - url: null - }); - }, 'The option "url" must be one of the following types: string'); - - // Next we'll have a Request that doesn't throw from c'tor, but from a setter. - let req = Request({ - url: "http://playground.zpao.com/jetpack/request/text.php", - onComplete: function () {} - }); - test.assertRaises(function () { - req.url = null; - }, 'The option "url" must be one of the following types: string'); - // The url shouldn't have changed, so check that - test.assertEqual(req.url, "http://playground.zpao.com/jetpack/request/text.php"); -} - -exports.testContentValidator = function(test) { - test.waitUntilDone(); - Request({ - url: "data:text/html,response", - content: { 'key1' : null, 'key2' : 'some value' }, - onComplete: function(response) { - test.assertEqual(response.text, "response?key1=null&key2=some+value"); - test.done(); - } - }).get(); -}; - -// All tests below here require a network connection. They will be commented out -// when checked in. If you'd like to run them, simply uncomment them. -// -// When we have the means, these tests will be converted so that they don't -// require an external server nor a network connection. - -// This is a request to a file that exists. -exports.testStatus200 = function (test) { - var srv = startServerAsync(port, basePath); - - test.waitUntilDone(); - var req = Request({ - url: "http://localhost:" + port + "/test-request.txt", - onComplete: function (response) { - test.assertEqual(this, req, "`this` should be request"); - test.assertEqual(response.status, 200); - test.assertEqual(response.statusText, "OK"); - test.assertEqual(response.headers["Content-Type"], "text/plain"); - test.assertEqual(response.text, "Look ma, no hands!\n"); - srv.stop(function() test.done()); - } - }).get(); -} - -// This tries to get a file that doesn't exist -exports.testStatus404 = function (test) { - var srv = startServerAsync(port, basePath); - - test.waitUntilDone(); - Request({ - // the following URL doesn't exist - url: "http://localhost:" + port + "/test-request-404.txt", - onComplete: function (response) { - test.assertEqual(response.status, 404); - test.assertEqual(response.statusText, "Not Found"); - srv.stop(function() test.done()); - } - }).get(); -} - -/* -// a simple file with a known header -exports.testKnownHeader = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/headers.php", - onComplete: function (response) { - test.assertEqual(response.headers["x-zpao-header"], "Jamba Juice"); - test.done(); - } - }).get(); -} - -// complex headers -exports.testKnownHeader = function (test) { - let headers = { - "x-zpao-header": "Jamba Juice is: delicious", - "x-zpao-header-2": "foo, bar", - "Set-Cookie": "foo=bar\nbaz=foo" - } - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/complex_headers.php", - onComplete: function (response) { - for (k in headers) { - test.assertEqual(response.headers[k], headers[k]); - } - test.done(); - } - }).get(); -} -*/ - -exports.testSimpleJSON = function (test) { - var srv = startServerAsync(port, basePath); - - test.waitUntilDone(); - Request({ - url: "http://localhost:" + port + "/test-request.json", - onComplete: function (response) { - assertDeepEqual(test, response.json, { foo: "bar" }); - srv.stop(function() test.done()); - } - }).get(); -} - -exports.testInvalidJSON = function (test) { - var srv = startServerAsync(port, basePath); - - test.waitUntilDone(); - Request({ - url: "http://localhost:" + port + "/test-request-invalid.json", - onComplete: function (response) { - test.assertEqual(response.json, null); - srv.stop(function() test.done()); - } - }).get(); -} - -/* -exports.testGetWithParamsNotContent = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar", - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: "bar" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testGetWithContent = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: { foo: "bar" }, - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: "bar" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testGetWithParamsAndContent = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar", - content: { baz: "foo" }, - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: "bar", baz: "foo" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testSimplePost = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: { foo: "bar" }, - onComplete: function (response) { - let expected = { - "POST": { foo: "bar" }, - "GET" : [] - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).post(); -} - -exports.testEncodedContent = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: "foo=bar&baz=foo", - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: "bar", baz: "foo" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testEncodedContentWithSpaces = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: "foo=bar+hop!&baz=foo", - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: "bar hop!", baz: "foo" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testGetWithArray = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: { foo: [1, 2], baz: "foo" }, - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : { foo: [1, 2], baz: "foo" } - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testGetWithNestedArray = function (test) { - test.waitUntilDone(); - Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: { foo: [1, 2, [3, 4]], bar: "baz" }, - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : this.content - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} - -exports.testGetWithNestedArray = function (test) { - test.waitUntilDone(); - let request = Request({ - url: "http://playground.zpao.com/jetpack/request/getpost.php", - content: { - foo: [1, 2, { - omg: "bbq", - "all your base!": "are belong to us" - }], - bar: "baz" - }, - onComplete: function (response) { - let expected = { - "POST": [], - "GET" : request.content - }; - assertDeepEqual(test, response.json, expected); - test.done(); - } - }).get(); -} -*/ - -// This is not a proper testing for deep equal, but it's good enough for my uses -// here. It will do type coercion to check equality, but that's good here. Data -// coming from the server will be stringified and so "0" should be equal to 0. -function assertDeepEqual(test, obj1, obj2, msg) { - function equal(o1, o2) { - // cover our non-object cases well enough - if (o1 == o2) - return true; - if (typeof(o1) != typeof(o2)) - return false; - if (typeof(o1) != "object") - return o1 == o2; - - let e = true; - for (let [key, val] in Iterator(o1)) { - e = e && key in o2 && equal(o2[key], val); - if (!e) - break; - } - for (let [key, val] in Iterator(o2)) { - e = e && key in o1 && equal(o1[key], val); - if (!e) - break; - } - return e; - } - msg = msg || "objects not equal - " + JSON.stringify(obj1) + " != " + - JSON.stringify(obj2); - test.assert(equal(obj1, obj2), msg); -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-selection.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-selection.js deleted file mode 100644 index cd96072..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-selection.js +++ /dev/null @@ -1,490 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Eric H. Jung <eric.jung@yahoo.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -let timer = require("timer"); -let {Cc,Ci} = require("chrome"); - -// Arbitrary delay needed to avoid weird behavior. -// TODO: We need to find all uses of this and replace them -// with more deterministic solutions. -const ARB_DELAY = 100; - -// Select all divs elements in an HTML document -function selectAllDivs(window) { - let divs = window.document.getElementsByTagName("div"); - let s = window.getSelection(); - if (s.rangeCount > 0) - s.removeAllRanges(); - for (let i = 0; i < divs.length; i++) { - let range = window.document.createRange(); - range.selectNode(divs[i]); - s.addRange(range); - } -} - -function selectTextarea(window, from, to) { - let textarea = window.document.getElementsByTagName("textarea")[0]; - - from = from || 0; - to = to || textarea.value.length; - - textarea.setSelectionRange(from, to); - textarea.focus(); -} - -function primeTestCase(html, test, callback) { - let tabBrowser = require("tab-browser"); - let dataURL = "data:text/html," + encodeURI(html); - let tracker = tabBrowser.whenContentLoaded( - function(window) { - if (window.document.location.href != dataURL) - return; - callback(window, test); - timer.setTimeout(function() { - tracker.unload(); - test.done(); - window.close(); - }, - ARB_DELAY); - } - ); - tabBrowser.addTab(dataURL); -} - -const DIV1 = '<div id="foo">bar</div>'; -const DIV2 = '<div>noodles</div>'; -const HTML_MULTIPLE = '<html><body>' + DIV1 + DIV2 + '</body></html>'; -const HTML_SINGLE = '<html><body>' + DIV1 + '</body></html>'; - -// Tests of contiguous - -exports.testContiguousMultiple = function testContiguousMultiple(test) { - let selection = require("selection"); - primeTestCase(HTML_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.isContiguous, false, - "selection.isContiguous multiple works."); - }); - - test.waitUntilDone(5000); -}; - -exports.testContiguousSingle = function testContiguousSingle(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.isContiguous, true, - "selection.isContiguous single works."); - }); - - test.waitUntilDone(5000); -}; - -exports.testContiguousWithoutSelection = - function testContiguousWithoutSelection(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - test.assertEqual(selection.isContiguous, false, - "selection.isContiguous without selection works."); - }); - - test.waitUntilDone(5000); -}; - -/** - * Test that setting the contiguous property has no effect. - */ -/*exports.testSetContiguous = function testSetContiguous(test) { - let selection = require("selection"); - primeTestCase(HTML_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - try { - selection.isContiguous = true; - test.assertEqual(selection.isContiguous, false, - "setting selection.isContiguous doesn't work (as expected)."); - } - catch (e) { - test.pass("setting selection.isContiguous doesn't work (as expected)."); - } - }); - - test.waitUntilDone(5000); -};*/ - - -// HTML tests - -exports.testGetHTMLSingleSelection = function testGetHTMLSingleSelection(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.html, DIV1, "get html selection works"); - }); - - test.waitUntilDone(5000); -}; - -/* Myk's comments: This is fine. However, it reminds me to figure out and - specify whether iteration is ordered. If so, we'll want to change this - test in the future to test that the discontiguous selections are returned in - the appropriate order. In the meantime, add a comment to that effect here */ -exports.testGetHTMLMultipleSelection = - function testGetHTMLMultipleSelection(test) { - let selection = require("selection"); - primeTestCase(HTML_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - let assertions = false; - for each (let i in selection) { - test.assertEqual(true, [DIV1, DIV2].some(function(t) t == i.html), - "get multiple selection html works"); - assertions = true; - } - // Ensure we ran at least one assertEqual() - test.assert(assertions, "No assertions were called"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetHTMLNull = function testGetHTMLNull(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - test.assertEqual(selection.html, null, "get html null works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetHTMLWeird = function testGetHTMLWeird(test) { - let selection = require("selection"); - // If the getter is used when there are contiguous selections, the first - // selection should be returned - primeTestCase(HTML_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.html, DIV1, "get html weird works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetHTMLNullInTextareaSelection = - function testGetHTMLNullInTextareaSelection(test) { - let selection = require("selection"); - - primeTestCase(TEXT_FIELD, test, function(window, test) { - selectTextarea(window); - - test.assertEqual(selection.html, null, "get html null in textarea works") - }); - - test.waitUntilDone(5000); -}; - -const REPLACEMENT_HTML = "<b>Lorem ipsum dolor sit amet</b>"; - -exports.testSetHTMLSelection = function testSetHTMLSelection(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - selectAllDivs(window); - selection.html = REPLACEMENT_HTML; - test.assertEqual(selection.html, "<span>" + REPLACEMENT_HTML + - "</span>", "selection html works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testSetHTMLException = function testSetHTMLException(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - try { - selection.html = REPLACEMENT_HTML; - test.fail("set HTML throws when there's no selection."); - } - catch (e) { - test.pass("set HTML throws when there's no selection."); - } - }); - - test.waitUntilDone(5000); -}; - -const TEXT1 = "foo"; -const TEXT2 = "noodles"; -const TEXT_MULTIPLE = "<html><body><div>" + TEXT1 + "</div><div>" + TEXT2 + - "</div></body></html>"; -const TEXT_SINGLE = "<html><body><div>" + TEXT1 + "</div></body></html>"; -const TEXT_FIELD = "<html><body><textarea>" + TEXT1 + "</textarea></body></html>"; - -// Text tests - -exports.testSetHTMLinTextareaSelection = - function testSetHTMLinTextareaSelection(test) { - let selection = require("selection"); - - primeTestCase(TEXT_FIELD, test, function(window, test) { - selectTextarea(window); - - // HTML string is set as plain text in textareas, that's because - // `selection.html` and `selection.text` are basically aliases when a - // value is set. See bug 677269 - selection.html = REPLACEMENT_HTML; - - test.assertEqual(selection.text, REPLACEMENT_HTML, - "set selection html in textarea works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextSingleSelection = - function testGetTextSingleSelection(test) { - let selection = require("selection"); - primeTestCase(TEXT_SINGLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.text, TEXT1, "get text selection works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextMultipleSelection = - function testGetTextMultipleSelection(test) { - let selection = require("selection"); - primeTestCase(TEXT_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - let assertions = false; - for each (let i in selection) { - test.assertEqual(true, [TEXT1, TEXT2].some(function(t) t == i.text), - "get multiple selection text works"); - assertions = true; - } - // Ensure we ran at least one assertEqual() - test.assert(assertions, "No assertions were called"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextNull = function testGetTextNull(test) { - let selection = require("selection"); - primeTestCase(TEXT_SINGLE, test, function(window, test) { - test.assertEqual(selection.text, null, "get text null works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextWeird = function testGetTextWeird(test) { - let selection = require("selection"); - // If the getter is used when there are contiguous selections, the first - // selection should be returned - primeTestCase(TEXT_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - test.assertEqual(selection.text, TEXT1, "get text weird works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextNullInTextareaSelection = - function testGetTextInTextareaSelection(test) { - let selection = require("selection"); - - primeTestCase(TEXT_FIELD, test, function(window, test) { - test.assertEqual(selection.text, null, "get text null in textarea works") - }); - - test.waitUntilDone(5000); -}; - -exports.testGetTextInTextareaSelection = - function testGetTextInTextareaSelection(test) { - let selection = require("selection"); - - primeTestCase(TEXT_FIELD, test, function(window, test) { - selectTextarea(window); - - test.assertEqual(selection.text, TEXT1, "get text null in textarea works") - }); - - test.waitUntilDone(5000); -}; - -const REPLACEMENT_TEXT = "Lorem ipsum dolor sit amet"; - -exports.testSetTextSelection = function testSetTextSelection(test) { - let selection = require("selection"); - primeTestCase(TEXT_SINGLE, test, function(window, test) { - selectAllDivs(window); - selection.text = REPLACEMENT_TEXT; - test.assertEqual(selection.text, REPLACEMENT_TEXT, "selection text works"); - }); - - test.waitUntilDone(5000); -}; - -exports.testSetHTMLException = function testSetHTMLException(test) { - let selection = require("selection"); - primeTestCase(TEXT_SINGLE, test, function(window, test) { - try { - selection.text = REPLACEMENT_TEXT; - test.fail("set HTML throws when there's no selection."); - } - catch (e) { - test.pass("set HTML throws when there's no selection."); - } - }); - - test.waitUntilDone(5000); -}; - -exports.testSetTextInTextareaSelection = - function testSetTextInTextareaSelection(test) { - let selection = require("selection"); - - primeTestCase(TEXT_FIELD, test, function(window, test) { - selectTextarea(window); - - selection.text = REPLACEMENT_TEXT; - - test.assertEqual(selection.text, REPLACEMENT_TEXT, - "set selection text in textarea works"); - }); - - test.waitUntilDone(5000); -}; - -// Iterator tests - -exports.testIterator = function testIterator(test) { - let selection = require("selection"); - let selectionCount = 0; - primeTestCase(TEXT_MULTIPLE, test, function(window, test) { - selectAllDivs(window); - for each (let i in selection) - selectionCount++; - test.assertEqual(2, selectionCount, "iterator works."); - }); - - test.waitUntilDone(5000); -}; - -exports.testIteratorWithTextareaSelection = - function testIteratorWithTextareaSelection(test) { - let selection = require("selection"); - let selectionCount = 0; - - primeTestCase(TEXT_FIELD, test, function(window, test) { - selectTextarea(window); - - for each (let i in selection) - selectionCount++; - - test.assertEqual(1, selectionCount, "iterator works in textarea."); - }); - - test.waitUntilDone(5000); -}; - -/* onSelect tests */ - -/* -function sendSelectionSetEvent(window) { - const Ci = Components.interfaces; - let utils = window.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils); - if (!utils.sendSelectionSetEvent(0, 1, false)) - dump("**** sendSelectionSetEvent did not select anything\n"); - else - dump("**** sendSelectionSetEvent succeeded\n"); -} - -// testOnSelect() requires nsIDOMWindowUtils, which is only available in -// Firefox 3.7+. -exports.testOnSelect = function testOnSelect(test) { - let selection = require("selection"); - let callbackCount = 0; - primeTestCase(TEXT_SINGLE, test, function(window, test) { - selection.onSelect = function() {callbackCount++}; - // Now simulate the user selecting stuff - sendSelectionSetEvent(window); - selection.text = REPLACEMENT_TEXT; - test.assertEqual(1, callbackCount, "onSelect text listener works."); - //test.pass(); - //test.done(); - }); - - test.waitUntilDone(5000); -}; - -// testOnSelectExceptionNoBubble() requires nsIDOMWindowUtils, which is only -// available in Firefox 3.7+. -exports.testOnSelectExceptionNoBubble = - function testOnSelectTextSelection(test) { - let selection = require("selection"); - primeTestCase(HTML_SINGLE, test, function(window, test) { - selection.onSelect = function() { - throw new Error("Exception thrown in testOnSelectExceptionNoBubble"); - }; - // Now simulate the user selecting stuff - sendSelectionSetEvent(window); - test.pass("onSelect catches exceptions."); - }); - - test.waitUntilDone(5000); -}; -*/ - -// 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. -try { - require("selection"); -} -catch (err) { - // This bug should be mentioned in the error message. - let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=560716"; - if (err.message.indexOf(bug) < 0) - throw err; - for (let [prop, val] in Iterator(exports)) { - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - } - exports.testAppNotSupported = function (test) { - test.pass("The selection module does not support this application."); - }; -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-prefs.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-prefs.js deleted file mode 100644 index 581eca1..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-prefs.js +++ /dev/null @@ -1,180 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Erik Vold <erikvvold@gmail.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -const { Loader } = require("./helpers"); -const setTimeout = require("timers").setTimeout; -const notify = require("observer-service").notify; -const { jetpackID } = require("@packaging"); - -exports.testSetGetBool = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs").prefs; - - test.assertEqual(sp.test, undefined, "Value should not exist"); - sp.test = true; - test.assert(sp.test, "Value read should be the value previously set"); - - loader.unload(); - test.done(); -}; - -exports.testSetGetInt = function(test) { - test.waitUntilDone(); - - // Load the module once, set a value. - let loader = Loader(module); - let sp = loader.require("simple-prefs").prefs; - - test.assertEqual(sp["test-int"], undefined, "Value should not exist"); - sp["test-int"] = 1; - test.assertEqual(sp["test-int"], 1, "Value read should be the value previously set"); - - loader.unload(); - test.done(); -}; - -exports.testSetComplex = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs").prefs; - - try { - sp["test-complex"] = {test: true}; - test.fail("Complex values are not allowed"); - } - catch (e) { - test.pass("Complex values are not allowed"); - } - - loader.unload(); - test.done(); -}; - -exports.testSetGetString = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs").prefs; - - test.assertEqual(sp["test-string"], undefined, "Value should not exist"); - sp["test-string"] = "test"; - test.assertEqual(sp["test-string"], "test", "Value read should be the value previously set"); - - loader.unload(); - test.done(); -}; - -exports.testHasAndRemove = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs").prefs; - - sp.test = true; - test.assert(("test" in sp), "Value exists"); - delete sp.test; - test.assertEqual(sp.test, undefined, "Value should be undefined"); - - loader.unload(); - test.done(); - -}; - -exports.testPrefListener = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs"); - - let listener = function(prefName) { - test.assertEqual(prefName, "test-listen", "The prefs listener heard the right event"); - test.done(); - }; - - sp.on("test-listen", listener); - - sp.prefs["test-listen"] = true; - loader.unload(); -}; - -exports.testBtnListener = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs"); - - sp.on("test-btn-listen", function() { - test.pass("Button press event was heard"); - test.done(); - }); - notify((jetpackID + "-cmdPressed"), "", "test-btn-listen"); - - loader.unload(); -}; - -exports.testPrefRemoveListener = function(test) { - test.waitUntilDone(); - - let loader = Loader(module); - let sp = loader.require("simple-prefs"); - let counter = 0; - - let listener = function() { - test.pass("The prefs listener was not removed yet"); - - if (++counter > 1) - test.fail("The prefs listener was not removed"); - - sp.removeListener("test-listen2", listener); - - sp.prefs["test-listen2"] = false; - - setTimeout(function() { - test.pass("The prefs listener was removed"); - loader.unload(); - test.done(); - }, 250); - }; - - sp.on("test-listen2", listener); - - sp.prefs["test-listen2"] = true; -}; diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-storage.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-storage.js deleted file mode 100644 index 95e4689..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-simple-storage.js +++ /dev/null @@ -1,346 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const file = require("file"); -const prefs = require("preferences-service"); - -const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota"; - -let {Cc,Ci} = require("chrome"); - -const { Loader } = require("./helpers"); -const options = require("@packaging"); - -let storeFile = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties). - get("ProfD", Ci.nsIFile); -storeFile.append("jetpack"); -storeFile.append(options.jetpackID); -storeFile.append("simple-storage"); -storeFile.append("store.json"); -let storeFilename = storeFile.path; - -exports.testSetGet = function (test) { - test.waitUntilDone(); - - // Load the module once, set a value. - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function (storage) { - test.assert(file.exists(storeFilename), "Store file should exist"); - - // Load the module again and make sure the value stuck. - loader = newLoader(test); - ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function (storage) { - file.remove(storeFilename); - test.done(); - }; - test.assertEqual(ss.storage.foo, val, "Value should persist"); - loader.unload(); - }; - let val = "foo"; - ss.storage.foo = val; - test.assertEqual(ss.storage.foo, val, "Value read should be value set"); - loader.unload(); -}; - -exports.testSetGetRootArray = function (test) { - setGetRoot(test, [1, 2, 3], function (arr1, arr2) { - if (arr1.length !== arr2.length) - return false; - for (let i = 0; i < arr1.length; i++) { - if (arr1[i] !== arr2[i]) - return false; - } - return true; - }); -}; - -exports.testSetGetRootBool = function (test) { - setGetRoot(test, true); -}; - -exports.testSetGetRootFunction = function (test) { - setGetRootError(test, function () {}, - "Setting storage to a function should fail"); -}; - -exports.testSetGetRootNull = function (test) { - setGetRoot(test, null); -}; - -exports.testSetGetRootNumber = function (test) { - setGetRoot(test, 3.14); -}; - -exports.testSetGetRootObject = function (test) { - setGetRoot(test, { foo: 1, bar: 2 }, function (obj1, obj2) { - for (let [prop, val] in Iterator(obj1)) { - if (!(prop in obj2) || obj2[prop] !== val) - return false; - } - for (let [prop, val] in Iterator(obj2)) { - if (!(prop in obj1) || obj1[prop] !== val) - return false; - } - return true; - }); -}; - -exports.testSetGetRootString = function (test) { - setGetRoot(test, "sho' 'nuff"); -}; - -exports.testSetGetRootUndefined = function (test) { - setGetRootError(test, undefined, "Setting storage to undefined should fail"); -}; - -exports.testEmpty = function (test) { - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - loader.unload(); - test.assert(!file.exists(storeFilename), "Store file should not exist"); -}; - -exports.testMalformed = function (test) { - let stream = file.open(storeFilename, "w"); - stream.write("i'm not json"); - stream.close(); - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - let empty = true; - for (let key in ss.storage) { - empty = false; - break; - } - test.assert(empty, "Malformed storage should cause root to be empty"); - loader.unload(); -}; - -// Go over quota and handle it by listener. -exports.testQuotaExceededHandle = function (test) { - test.waitUntilDone(); - prefs.set(QUOTA_PREF, 18); - - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - ss.on("OverQuota", function () { - test.pass("OverQuota was emitted as expected"); - test.assertEqual(this, ss, "`this` should be simple storage"); - ss.storage = { x: 4, y: 5 }; - - manager(loader).jsonStore.onWrite = function () { - loader = newLoader(test); - ss = loader.require("simple-storage"); - let numProps = 0; - for (let prop in ss.storage) - numProps++; - test.assert(numProps, 2, - "Store should contain 2 values: " + ss.storage.toSource()); - test.assertEqual(ss.storage.x, 4, "x value should be correct"); - test.assertEqual(ss.storage.y, 5, "y value should be correct"); - manager(loader).jsonStore.onWrite = function (storage) { - prefs.reset(QUOTA_PREF); - test.done(); - }; - loader.unload(); - }; - loader.unload(); - }); - // This will be JSON.stringify()ed to: {"a":1,"b":2,"c":3} (19 bytes) - ss.storage = { a: 1, b: 2, c: 3 }; - manager(loader).jsonStore.write(); -}; - -// Go over quota but don't handle it. The last good state should still persist. -exports.testQuotaExceededNoHandle = function (test) { - test.waitUntilDone(); - prefs.set(QUOTA_PREF, 5); - - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - - manager(loader).jsonStore.onWrite = function (storage) { - loader = newLoader(test); - ss = loader.require("simple-storage"); - test.assertEqual(ss.storage, val, - "Value should have persisted: " + ss.storage); - ss.storage = "some very long string that is very long"; - ss.on("OverQuota", function () { - test.pass("OverQuota emitted as expected"); - manager(loader).jsonStore.onWrite = function () { - test.fail("Over-quota value should not have been written"); - }; - loader.unload(); - - loader = newLoader(test); - ss = loader.require("simple-storage"); - test.assertEqual(ss.storage, val, - "Over-quota value should not have been written, " + - "old value should have persisted: " + ss.storage); - loader.unload(); - prefs.reset(QUOTA_PREF); - test.done(); - }); - manager(loader).jsonStore.write(); - }; - - let val = "foo"; - ss.storage = val; - loader.unload(); -}; - -exports.testQuotaUsage = function (test) { - test.waitUntilDone(); - - let quota = 21; - prefs.set(QUOTA_PREF, quota); - - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - - // {"a":1} (7 bytes) - ss.storage = { a: 1 }; - test.assertEqual(ss.quotaUsage, 7 / quota, "quotaUsage should be correct"); - - // {"a":1,"bb":2} (14 bytes) - ss.storage = { a: 1, bb: 2 }; - test.assertEqual(ss.quotaUsage, 14 / quota, "quotaUsage should be correct"); - - // {"a":1,"bb":2,"cc":3} (21 bytes) - ss.storage = { a: 1, bb: 2, cc: 3 }; - test.assertEqual(ss.quotaUsage, 21 / quota, "quotaUsage should be correct"); - - manager(loader).jsonStore.onWrite = function () { - prefs.reset(QUOTA_PREF); - test.done(); - }; - loader.unload(); -}; - -exports.testUninstall = function (test) { - test.waitUntilDone(); - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function () { - test.assert(file.exists(storeFilename), "Store file should exist"); - - loader = newLoader(test); - ss = loader.require("simple-storage"); - loader.unload("uninstall"); - test.assert(!file.exists(storeFilename), "Store file should be removed"); - test.done(); - }; - ss.storage.foo = "foo"; - loader.unload(); -}; - -exports.testSetNoSetRead = function (test) { - test.waitUntilDone(); - - // Load the module, set a value. - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function (storage) { - test.assert(file.exists(storeFilename), "Store file should exist"); - - // Load the module again but don't access ss.storage. - loader = newLoader(test); - ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function (storage) { - test.fail("Nothing should be written since `storage` was not accessed."); - }; - loader.unload(); - - // Load the module a third time and make sure the value stuck. - loader = newLoader(test); - ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function (storage) { - file.remove(storeFilename); - test.done(); - }; - test.assertEqual(ss.storage.foo, val, "Value should persist"); - loader.unload(); - }; - let val = "foo"; - ss.storage.foo = val; - test.assertEqual(ss.storage.foo, val, "Value read should be value set"); - loader.unload(); -}; - -function manager(loader) loader.sandbox("simple-storage").manager; - -function newLoader() Loader(module); - -function setGetRoot(test, val, compare) { - test.waitUntilDone(); - - compare = compare || function (a, b) a === b; - - // Load the module once, set a value. - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function () { - test.assert(file.exists(storeFilename), "Store file should exist"); - - // Load the module again and make sure the value stuck. - loader = newLoader(test); - ss = loader.require("simple-storage"); - manager(loader).jsonStore.onWrite = function () { - file.remove(storeFilename); - test.done(); - }; - test.assert(compare(ss.storage, val), "Value should persist"); - loader.unload(); - }; - ss.storage = val; - test.assert(compare(ss.storage, val), "Value read should be value set"); - loader.unload(); -} - -function setGetRootError(test, val, msg) { - let pred = "storage must be one of the following types: " + - "array, boolean, null, number, object, string"; - let loader = newLoader(test); - let ss = loader.require("simple-storage"); - test.assertRaises(function () ss.storage = val, pred, msg); - loader.unload(); -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-tabs.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-tabs.js deleted file mode 100644 index ae98312..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-tabs.js +++ /dev/null @@ -1,905 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dietrich Ayala <dietrich@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -var {Cc,Ci} = require("chrome"); -const { Loader } = require("./helpers"); - -// test tab.activeTab getter -exports.testActiveTab_getter = function(test) { - test.waitUntilDone(); - - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - - let url = "data:text/html,<html><head><title>foo</title></head></html>"; - require("tab-browser").addTab( - url, - { - onLoad: function(e) { - test.assert(tabs.activeTab); - test.assertEqual(tabs.activeTab.url, url); - test.assertEqual(tabs.activeTab.title, "foo"); - closeBrowserWindow(window, function() test.done()); - } - } - ); - }); -}; - -// test 'BrowserWindow' instance creation on tab 'activate' event -// See bug 648244: there was a infinite loop. -exports.testBrowserWindowCreationOnActivate = function(test) { - test.waitUntilDone(); - - let windows = require("windows").browserWindows; - let tabs = require("tabs"); - - let gotActivate = false; - - tabs.once('activate', function onActivate(eventTab) { - test.assert(windows.activeWindow, "Is able to fetch activeWindow"); - gotActivate = true; - }); - - openBrowserWindow(function(window, browser) { - test.assert(gotActivate, "Received activate event before openBrowserWindow's callback is called"); - closeBrowserWindow(window, function () test.done()); - }); -} - -// test tab.activeTab setter -exports.testActiveTab_setter = function(test) { - test.waitUntilDone(); - - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,<html><head><title>foo</title></head></html>"; - - tabs.on('ready', function onReady(tab) { - tabs.removeListener('ready', onReady); - test.assertEqual(tabs.activeTab.url, "about:blank", "activeTab url has not changed"); - test.assertEqual(tab.url, url, "url of new background tab matches"); - tabs.on('activate', function onActivate(eventTab) { - tabs.removeListener('activate', onActivate); - test.assertEqual(tabs.activeTab.url, url, "url after activeTab setter matches"); - test.assertEqual(eventTab, tab, "event argument is the activated tab"); - test.assertEqual(eventTab, tabs.activeTab, "the tab is the active one"); - closeBrowserWindow(window, function() test.done()); - }); - tab.activate(); - }) - - tabs.open({ - url: url, - inBackground: true - }); - }); -}; - -exports.testAutomaticDestroy = function(test) { - test.waitUntilDone(); - - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - - // Create a second tab instance that we will destroy - let called = false; - - let loader = Loader(module); - let tabs2 = loader.require("tabs"); - tabs2.on('open', function onOpen(tab) { - called = true; - }); - - loader.unload(); - - // Fire a tab event an ensure that this destroyed tab is inactive - tabs.once('open', function () { - require("timer").setTimeout(function () { - test.assert(!called, "Unloaded tab module is destroyed and inactive"); - closeBrowserWindow(window, function() test.done()); - }, 0); - }); - - tabs.open("data:text/html,foo"); - - }); -}; - -// test tab properties -exports.testTabProperties = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs= require("tabs"); - let url = "data:text/html,<html><head><title>foo</title></head><body>foo</body></html>"; - tabs.open({ - url: url, - onReady: function(tab) { - test.assertEqual(tab.title, "foo", "title of the new tab matches"); - test.assertEqual(tab.url, url, "URL of the new tab matches"); - test.assert(tab.favicon, "favicon of the new tab is not empty"); - test.assertEqual(tab.style, null, "style of the new tab matches"); - test.assertEqual(tab.index, 1, "index of the new tab matches"); - test.assertNotEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// test tabs iterator and length property -exports.testTabsIteratorAndLength = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let startCount = 0; - for each (let t in tabs) startCount++; - test.assertEqual(startCount, tabs.length, "length property is correct"); - let url = "data:text/html,default"; - tabs.open(url); - tabs.open(url); - tabs.open({ - url: url, - onOpen: function(tab) { - let count = 0; - for each (let t in tabs) count++; - test.assertEqual(count, startCount + 3, "iterated tab count matches"); - test.assertEqual(startCount + 3, tabs.length, "iterated tab count matches length property"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// test tab.url setter -exports.testTabLocation = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url1 = "data:text/html,foo"; - let url2 = "data:text/html,bar"; - - tabs.on('ready', function onReady(tab) { - if (tab.url != url2) - return; - tabs.removeListener('ready', onReady); - test.pass("tab.load() loaded the correct url"); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.open({ - url: url1, - onOpen: function(tab) { - tab.url = url2 - } - }); - }); -}; - -// test tab.close() -exports.testTabClose = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,foo"; - - test.assertNotEqual(tabs.activeTab.url, url, "tab is now the active tab"); - tabs.on('ready', function onReady(tab) { - tabs.removeListener('ready', onReady); - test.assertEqual(tabs.activeTab.url, tab.url, "tab is now the active tab"); - tab.close(function() { - closeBrowserWindow(window, function() test.done()); - }); - test.assertNotEqual(tabs.activeTab.url, url, "tab is no longer the active tab"); - }); - - tabs.open(url); - }); -}; - -// test tab.reload() -exports.testTabReload = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,<!doctype%20html><title></title>"; - - tabs.open({ url: url, onReady: function onReady(tab) { - tab.removeListener("ready", onReady); - - browser.addEventListener( - "load", - function onLoad() { - browser.removeEventListener("load", onLoad, true); - - browser.addEventListener( - "load", - function onReload() { - browser.removeEventListener("load", onReload, true); - test.pass("the tab was loaded again"); - test.assertEqual(tab.url, url, "the tab has the same URL"); - closeBrowserWindow(window, function() test.done()); - }, - true - ); - tab.reload(); - }, - true - ); - }}); - }); -}; - -// test tab.move() -exports.testTabMove = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,foo"; - - tabs.open({ - url: url, - onOpen: function(tab) { - test.assertEqual(tab.index, 1, "tab index before move matches"); - tab.index = 0; - test.assertEqual(tab.index, 0, "tab index after move matches"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// open tab with default options -exports.testOpen = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,default"; - tabs.open({ - url: url, - onReady: function(tab) { - test.assertEqual(tab.url, url, "URL of the new tab matches"); - test.assertEqual(window.content.location, url, "URL of active tab in the current window matches"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// open pinned tab -exports.testOpenPinned = function(test) { - const xulApp = require("xul-app"); - if (xulApp.versionInRange(xulApp.platformVersion, "2.0b2", "*")) { - // test tab pinning - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,default"; - tabs.open({ - url: url, - isPinned: true, - onOpen: function(tab) { - test.assertEqual(tab.isPinned, true, "The new tab is pinned"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); - } - else { - test.pass("Pinned tabs are not supported in this application."); - } -}; - -// pin/unpin opened tab -exports.testPinUnpin = function(test) { - const xulApp = require("xul-app"); - if (xulApp.versionInRange(xulApp.platformVersion, "2.0b2", "*")) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let url = "data:text/html,default"; - tabs.open({ - url: url, - onOpen: function(tab) { - tab.pin(); - test.assertEqual(tab.isPinned, true, "The tab was pinned correctly"); - tab.unpin(); - test.assertEqual(tab.isPinned, false, "The tab was unpinned correctly"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); - } - else { - test.pass("Pinned tabs are not supported in this application."); - } -}; - -// open tab in background -exports.testInBackground = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let activeUrl = tabs.activeTab.url; - let url = "data:text/html,background"; - test.assertEqual(activeWindow, window, "activeWindow matches this window"); - tabs.on('ready', function onReady(tab) { - tabs.removeListener('ready', onReady); - test.assertEqual(tabs.activeTab.url, activeUrl, "URL of active tab has not changed"); - test.assertEqual(tab.url, url, "URL of the new background tab matches"); - test.assertEqual(activeWindow, window, "a new window was not opened"); - test.assertNotEqual(tabs.activeTab.url, url, "URL of active tab is not the new URL"); - closeBrowserWindow(window, function() test.done()); - }); - tabs.open({ - url: url, - inBackground: true - }); - }); -}; - -// open tab in new window -exports.testOpenInNewWindow = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - - let cache = []; - let windowUtils = require("window-utils"); - let wt = new windowUtils.WindowTracker({ - onTrack: function(win) { - cache.push(win); - }, - onUntrack: function(win) { - cache.splice(cache.indexOf(win), 1) - } - }); - let startWindowCount = cache.length; - - let url = "data:text/html,newwindow"; - tabs.open({ - url: url, - inNewWindow: true, - onReady: function(tab) { - let newWindow = cache[cache.length - 1]; - test.assertEqual(cache.length, startWindowCount + 1, "a new window was opened"); - test.assertEqual(activeWindow, newWindow, "new window is active"); - test.assertEqual(tab.url, url, "URL of the new tab matches"); - test.assertEqual(newWindow.content.location, url, "URL of new tab in new window matches"); - test.assertEqual(tabs.activeTab.url, url, "URL of activeTab matches"); - for (var i in cache) cache[i] = null; - wt.unload(); - closeBrowserWindow(newWindow, function() { - closeBrowserWindow(window, function() test.done()); - }); - } - }); - }); -}; - -// onOpen event handler -exports.testTabsEvent_onOpen = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let url = "data:text/html,1"; - let eventCount = 0; - - // add listener via property assignment - function listener1(tab) { - eventCount++; - }; - tabs.on('open', listener1); - - // add listener via collection add - tabs.on('open', function listener2(tab) { - test.assertEqual(++eventCount, 2, "both listeners notified"); - tabs.removeListener('open', listener1); - tabs.removeListener('open', listener2); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.open(url); - }); -}; - -// onClose event handler -exports.testTabsEvent_onClose = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let url = "data:text/html,onclose"; - let eventCount = 0; - - // add listener via property assignment - function listener1(tab) { - eventCount++; - } - tabs.on('close', listener1); - - // add listener via collection add - tabs.on('close', function listener2(tab) { - test.assertEqual(++eventCount, 2, "both listeners notified"); - tabs.removeListener('close', listener1); - tabs.removeListener('close', listener2); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.on('ready', function onReady(tab) { - tabs.removeListener('ready', onReady); - tab.close(); - }); - - tabs.open(url); - }); -}; - -// onClose event handler when a window is closed -exports.testTabsEvent_onCloseWindow = function(test) { - test.waitUntilDone(); - - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - - let closeCount = 0, individualCloseCount = 0; - function listener() { - closeCount++; - } - tabs.on('close', listener); - - // One tab is already open with the window - let openTabs = 1; - function testCasePossiblyLoaded() { - if (++openTabs == 4) { - beginCloseWindow(); - } - } - - tabs.open({ - url: "data:text/html,tab2", - onOpen: function() testCasePossiblyLoaded(), - onClose: function() individualCloseCount++ - }); - - tabs.open({ - url: "data:text/html,tab3", - onOpen: function() testCasePossiblyLoaded(), - onClose: function() individualCloseCount++ - }); - - tabs.open({ - url: "data:text/html,tab4", - onOpen: function() testCasePossiblyLoaded(), - onClose: function() individualCloseCount++ - }); - - function beginCloseWindow() { - closeBrowserWindow(window, function testFinished() { - tabs.removeListener("close", listener); - - test.assertEqual(closeCount, 4, "Correct number of close events received"); - test.assertEqual(individualCloseCount, 3, - "Each tab with an attached onClose listener received a close " + - "event when the window was closed"); - - test.done(); - }); - } - - }); -} - -// onReady event handler -exports.testTabsEvent_onReady = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let url = "data:text/html,onready"; - let eventCount = 0; - - // add listener via property assignment - function listener1(tab) { - eventCount++; - }; - tabs.on('ready', listener1); - - // add listener via collection add - tabs.on('ready', function listener2(tab) { - test.assertEqual(++eventCount, 2, "both listeners notified"); - tabs.removeListener('ready', listener1); - tabs.removeListener('ready', listener2); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.open(url); - }); -}; - -// onActivate event handler -exports.testTabsEvent_onActivate = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let url = "data:text/html,onactivate"; - let eventCount = 0; - - // add listener via property assignment - function listener1(tab) { - eventCount++; - }; - tabs.on('activate', listener1); - - // add listener via collection add - tabs.on('activate', function listener2(tab) { - test.assertEqual(++eventCount, 2, "both listeners notified"); - tabs.removeListener('activate', listener1); - tabs.removeListener('activate', listener2); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.open(url); - }); -}; - -// onDeactivate event handler -exports.testTabsEvent_onDeactivate = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let url = "data:text/html,ondeactivate"; - let eventCount = 0; - - // add listener via property assignment - function listener1(tab) { - eventCount++; - }; - tabs.on('deactivate', listener1); - - // add listener via collection add - tabs.on('deactivate', function listener2(tab) { - test.assertEqual(++eventCount, 2, "both listeners notified"); - tabs.removeListener('deactivate', listener1); - tabs.removeListener('deactivate', listener2); - closeBrowserWindow(window, function() test.done()); - }); - - tabs.on('open', function onOpen(tab) { - tabs.removeListener('open', onOpen); - tabs.open("data:text/html,foo"); - }); - - tabs.open(url); - }); -}; - -// per-tab event handlers -exports.testPerTabEvents = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - var tabs = require("tabs"); - let eventCount = 0; - - tabs.open({ - url: "data:text/html,foo", - onOpen: function(tab) { - // add listener via property assignment - function listener1() { - eventCount++; - }; - tab.on('ready', listener1); - - // add listener via collection add - tab.on('ready', function listener2() { - test.assertEqual(eventCount, 1, "both listeners notified"); - tab.removeListener('ready', listener1); - tab.removeListener('ready', listener2); - closeBrowserWindow(window, function() test.done()); - }); - } - }); - }); -}; - -exports.testAttachOnOpen = function (test) { - // Take care that attach has to be called on tab ready and not on tab open. - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - - tabs.open({ - url: "data:text/html,foobar", - onOpen: function (tab) { - let worker = tab.attach({ - contentScript: 'self.postMessage(document.location.href); ', - onMessage: function (msg) { - test.assertEqual(msg, "about:blank", - "Worker document url is about:blank on open"); - worker.destroy(); - closeBrowserWindow(window, function() test.done()); - } - }); - } - }); - - }); -} - -exports.testAttachOnMultipleDocuments = function (test) { - // Example of attach that process multiple tab documents - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let firstLocation = "data:text/html,foobar"; - let secondLocation = "data:text/html,bar"; - let thirdLocation = "data:text/html,fox"; - let onReadyCount = 0; - let worker1 = null; - let worker2 = null; - let detachEventCount = 0; - tabs.open({ - url: firstLocation, - onReady: function (tab) { - onReadyCount++; - if (onReadyCount == 1) { - worker1 = tab.attach({ - contentScript: 'self.on("message", ' + - ' function () self.postMessage(document.location.href)' + - ');', - onMessage: function (msg) { - test.assertEqual(msg, firstLocation, - "Worker url is equal to the 1st document"); - tab.url = secondLocation; - }, - onDetach: function () { - detachEventCount++; - test.pass("Got worker1 detach event"); - test.assertRaises(function () { - worker1.postMessage("ex-1"); - }, - /The page has been destroyed/, - "postMessage throw because worker1 is destroyed"); - checkEnd(); - } - }); - worker1.postMessage("new-doc-1"); - } - else if (onReadyCount == 2) { - - worker2 = tab.attach({ - contentScript: 'self.on("message", ' + - ' function () self.postMessage(document.location.href)' + - ');', - onMessage: function (msg) { - test.assertEqual(msg, secondLocation, - "Worker url is equal to the 2nd document"); - tab.url = thirdLocation; - }, - onDetach: function () { - detachEventCount++; - test.pass("Got worker2 detach event"); - test.assertRaises(function () { - worker2.postMessage("ex-2"); - }, - /The page has been destroyed/, - "postMessage throw because worker2 is destroyed"); - checkEnd(); - } - }); - worker2.postMessage("new-doc-2"); - } - else if (onReadyCount == 3) { - - tab.close(); - - } - - } - }); - - function checkEnd() { - if (detachEventCount != 2) - return; - - test.pass("Got all detach events"); - - closeBrowserWindow(window, function() test.done()); - } - - }); -} - - -exports.testAttachWrappers = function (test) { - // Check that content script has access to wrapped values by default - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let document = "data:text/html,<script>var globalJSVar = true; " + - " document.getElementById = 3;</script>"; - let count = 0; - - tabs.open({ - url: document, - onReady: function (tab) { - let worker = tab.attach({ - contentScript: 'try {' + - ' self.postMessage(!("globalJSVar" in window));' + - ' self.postMessage(typeof window.globalJSVar == "undefined");' + - '} catch(e) {' + - ' self.postMessage(e.message);' + - '}', - onMessage: function (msg) { - test.assertEqual(msg, true, "Worker has wrapped objects ("+count+")"); - if (count++ == 1) - closeBrowserWindow(window, function() test.done()); - } - }); - } - }); - - }); -} - -/* -// We do not offer unwrapped access to DOM since bug 601295 landed -// See 660780 to track progress of unwrap feature -exports.testAttachUnwrapped = function (test) { - // Check that content script has access to unwrapped values through unsafeWindow - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - let tabs = require("tabs"); - let document = "data:text/html,<script>var globalJSVar=true;</script>"; - let count = 0; - - tabs.open({ - url: document, - onReady: function (tab) { - let worker = tab.attach({ - contentScript: 'try {' + - ' self.postMessage(unsafeWindow.globalJSVar);' + - '} catch(e) {' + - ' self.postMessage(e.message);' + - '}', - onMessage: function (msg) { - test.assertEqual(msg, true, "Worker has access to javascript content globals ("+count+")"); - closeBrowserWindow(window, function() test.done()); - } - }); - } - }); - - }); -} -*/ - -exports['test window focus changes active tab'] = function(test) { - test.waitUntilDone(); - let win1 = openBrowserWindow(function() { - let win2 = openBrowserWindow(function() { - let tabs = require("tabs"); - tabs.on("activate", function onActivate() { - tabs.removeListener("activate", onActivate); - test.pass("activate was called on windows focus change."); - closeBrowserWindow(win1, function() { - closeBrowserWindow(win2, function() { test.done(); }); - }); - }); - win1.focus(); - }, "data:text/html,test window focus changes active tab</br><h1>Window #2"); - }, "data:text/html,test window focus changes active tab</br><h1>Window #1"); -}; - -exports['test ready event on new window tab'] = function(test) { - test.waitUntilDone(); - let uri = encodeURI("data:text/html,Waiting for ready event!"); - - require("tabs").on("ready", function onReady(tab) { - if (tab.url === uri) { - require("tabs").removeListener("ready", onReady); - test.pass("ready event was emitted"); - closeBrowserWindow(window, function() { - test.done(); - }); - } - }); - - let window = openBrowserWindow(function(){}, uri); -}; -/******************* helpers *********************/ - -// Helper for getting the active window -this.__defineGetter__("activeWindow", function activeWindow() { - return Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); -}); - -// Utility function to open a new browser window. -function openBrowserWindow(callback, url) { - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - let urlString = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - urlString.data = url; - let window = ww.openWindow(null, "chrome://browser/content/browser.xul", - "_blank", "chrome,all,dialog=no", urlString); - - if (callback) { - window.addEventListener("load", function onLoad(event) { - if (event.target && event.target.defaultView == window) { - window.removeEventListener("load", onLoad, true); - let browsers = window.document.getElementsByTagName("tabbrowser"); - try { - require("timer").setTimeout(function () { - callback(window, browsers[0]); - }, 10); - } catch (e) { console.exception(e); } - } - }, true); - } - - return window; -} - -// Helper for calling code at window close -function closeBrowserWindow(window, callback) { - window.addEventListener("unload", function unload() { - window.removeEventListener("unload", unload, false); - callback(); - }, false); - window.close(); -} - -// 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. -try { - require("tabs"); -} -catch (err) { - // This bug should be mentioned in the error message. - let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=560716"; - if (err.message.indexOf(bug) < 0) - throw err; - for (let [prop, val] in Iterator(exports)) { - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - } - exports.testAppNotSupported = function (test) { - test.pass("the tabs module does not support this application."); - }; -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-timers.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-timers.js deleted file mode 100644 index 98ea613..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-timers.js +++ /dev/null @@ -1,44 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Shane Tomlinson <stomlinson@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -const timers = require("timers"); - -exports.testTimeout = function (test) { - test.waitUntilDone(); - timers.setTimeout(function () { - test.pass("timers.setTimeout works"); - test.done(); - }, 0); -} diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-widget.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-widget.js deleted file mode 100644 index a5ab83c..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-widget.js +++ /dev/null @@ -1,950 +0,0 @@ -const {Cc,Ci} = require("chrome"); -const { Loader } = require('./helpers'); - -exports.testConstructor = function(test) { - - const tabBrowser = require("tab-browser"); - - test.waitUntilDone(30000); - - const widgets = require("widget"); - const url = require("url"); - const windowUtils = require("window-utils"); - - let browserWindow = windowUtils.activeBrowserWindow; - let doc = browserWindow.document; - let AddonsMgrListener = browserWindow.AddonsMgrListener; - - function container() doc.getElementById("addon-bar"); - function widgetCount() container() ? container().getElementsByTagName("toolbaritem").length : 0; - let widgetStartCount = widgetCount(); - function widgetNode(index) container() ? container().getElementsByTagName("toolbaritem")[index] : null; - - // Test basic construct/destroy - AddonsMgrListener.onInstalling(); - let w = widgets.Widget({ id: "fooID", label: "foo", content: "bar" }); - AddonsMgrListener.onInstalled(); - test.assertEqual(widgetCount(), widgetStartCount + 1, "panel has correct number of child elements after widget construction"); - - // test widget height - test.assertEqual(widgetNode(0).firstChild.boxObject.height, 16, "widget has correct default height"); - - AddonsMgrListener.onUninstalling(); - w.destroy(); - AddonsMgrListener.onUninstalled(); - w.destroy(); - test.pass("Multiple destroys do not cause an error"); - test.assertEqual(widgetCount(), widgetStartCount, "panel has correct number of child elements after destroy"); - - // Test automatic widget destroy on unload - let loader = Loader(module); - let widgetsFromLoader = loader.require("widget"); - let widgetStartCount = widgetCount(); - let w = widgetsFromLoader.Widget({ id: "fooID", label: "foo", content: "bar" }); - test.assertEqual(widgetCount(), widgetStartCount + 1, "widget has been correctly added"); - loader.unload(); - test.assertEqual(widgetCount(), widgetStartCount, "widget has been destroyed on module unload"); - - // Test nothing - test.assertRaises( - function() widgets.Widget({}), - "The widget must have a non-empty label property.", - "throws on no properties"); - - // Test no label - test.assertRaises( - function() widgets.Widget({content: "foo"}), - "The widget must have a non-empty label property.", - "throws on no label"); - - // Test empty label - test.assertRaises( - function() widgets.Widget({label: "", content: "foo"}), - "The widget must have a non-empty label property.", - "throws on empty label"); - - // Test no content or image - test.assertRaises( - function() widgets.Widget({id: "fooID", label: "foo"}), - "No content or contentURL property found. Widgets must have one or the other.", - "throws on no content"); - - // Test empty content, no image - test.assertRaises( - function() widgets.Widget({id:"fooID", label: "foo", content: ""}), - "No content or contentURL property found. Widgets must have one or the other.", - "throws on empty content"); - - // Test empty image, no content - test.assertRaises( - function() widgets.Widget({id:"fooID", label: "foo", image: ""}), - "No content or contentURL property found. Widgets must have one or the other.", - "throws on empty content"); - - // Test empty content, empty image - test.assertRaises( - function() widgets.Widget({id:"fooID", label: "foo", content: "", image: ""}), - "No content or contentURL property found. Widgets must have one or the other.", - "throws on empty content"); - - // Test duplicated ID - let duplicateID = widgets.Widget({id: "foo", label: "foo", content: "bar"}); - test.assertRaises( - function() widgets.Widget({id: "foo", label: "bar", content: "bar"}), - /This widget ID is already used:/, - "throws on duplicated id"); - duplicateID.destroy(); - - // Test duplicate label, different ID - let w1 = widgets.Widget({id: "id1", label: "foo", content: "bar"}); - let w2 = widgets.Widget({id: "id2", label: "foo", content: "bar"}); - w1.destroy(); - w2.destroy(); - - // Test position restore on create/destroy/create - // Create 3 ordered widgets - let w1 = widgets.Widget({id: "first", label:"first", content: "bar"}); - let w2 = widgets.Widget({id: "second", label:"second", content: "bar"}); - let w3 = widgets.Widget({id: "third", label:"third", content: "bar"}); - // Remove the middle widget - test.assertEqual(widgetNode(1).getAttribute("label"), "second", "second widget is the second widget inserted"); - w2.destroy(); - test.assertEqual(widgetNode(1).getAttribute("label"), "third", "second widget is removed, so second widget is now the third one"); - w2 = widgets.Widget({id: "second", label:"second", content: "bar"}); - test.assertEqual(widgetNode(1).getAttribute("label"), "second", "second widget is created again, at the same location"); - // Cleanup this testcase - AddonsMgrListener.onUninstalling(); - w1.destroy(); - w2.destroy(); - w3.destroy(); - AddonsMgrListener.onUninstalled(); - - // Test concurrent widget module instances on addon-bar hiding - let loader = Loader(module); - let anotherWidgetsInstance = loader.require("widget"); - test.assert(container().collapsed, "UI is hidden when no widgets"); - AddonsMgrListener.onInstalling(); - let w1 = widgets.Widget({id: "foo", label: "foo", content: "bar"}); - // Ideally we would let AddonsMgrListener display the addon bar - // But, for now, addon bar is immediatly displayed by sdk code - // https://bugzilla.mozilla.org/show_bug.cgi?id=627484 - test.assert(!container().collapsed, "UI is already visible when we just added the widget"); - AddonsMgrListener.onInstalled(); - test.assert(!container().collapsed, "UI become visible when we notify AddonsMgrListener about end of addon installation"); - let w2 = anotherWidgetsInstance.Widget({id: "bar", label: "bar", content: "foo"}); - test.assert(!container().collapsed, "UI still visible when we add a second widget"); - AddonsMgrListener.onUninstalling(); - w1.destroy(); - AddonsMgrListener.onUninstalled(); - test.assert(!container().collapsed, "UI still visible when we remove one of two widgets"); - AddonsMgrListener.onUninstalling(); - w2.destroy(); - test.assert(!container().collapsed, "UI is still visible when we have removed all widget but still not called onUninstalled"); - AddonsMgrListener.onUninstalled(); - test.assert(container().collapsed, "UI is hidden when we have removed all widget and called onUninstalled"); - - // Helper for testing a single widget. - // Confirms proper addition and content setup. - function testSingleWidget(widgetOptions) { - // We have to display which test is being run, because here we do not - // use the regular test framework but rather a custom one that iterates - // the `tests` array. - console.info("executing: " + widgetOptions.id); - - let startCount = widgetCount(); - let widget = widgets.Widget(widgetOptions); - let node = widgetNode(startCount); - test.assert(node, "widget node at index"); - test.assertEqual(node.tagName, "toolbaritem", "widget element is correct"); - test.assertEqual(widget.width + "px", node.style.minWidth, "widget width is correct"); - test.assertEqual(widgetCount(), startCount + 1, "container has correct number of child elements"); - let content = node.firstElementChild; - test.assert(content, "found content"); - test.assertMatches(content.tagName, /iframe|image/, "content is iframe or image"); - return widget; - } - - // Array of widgets to test - // and a function to test them. - let tests = []; - function nextTest() { - test.assertEqual(widgetCount(), 0, "widget in last test property cleaned itself up"); - if (!tests.length) - test.done(); - else - require("timer").setTimeout(tests.shift(), 0); - } - function doneTest() nextTest(); - - // text widget - tests.push(function testTextWidget() testSingleWidget({ - id: "text", - label: "text widget", - content: "oh yeah", - contentScript: "self.postMessage(document.body.innerHTML);", - contentScriptWhen: "end", - onMessage: function (message) { - test.assertEqual(this.content, message, "content matches"); - this.destroy(); - doneTest(); - } - })); - - // html widget - tests.push(function testHTMLWidget() testSingleWidget({ - id: "html", - label: "html widget", - content: "<div>oh yeah</div>", - contentScript: "self.postMessage(document.body.innerHTML);", - contentScriptWhen: "end", - onMessage: function (message) { - test.assertEqual(this.content, message, "content matches"); - this.destroy(); - doneTest(); - } - })); - - // image url widget - tests.push(function testImageURLWidget() testSingleWidget({ - id: "image", - label: "image url widget", - contentURL: require("self").data.url("test.html"), - contentScript: "self.postMessage({title: document.title, " + - "tag: document.body.firstElementChild.tagName, " + - "content: document.body.firstElementChild.innerHTML});", - contentScriptWhen: "end", - onMessage: function (message) { - test.assertEqual(message.title, "foo", "title matches"); - test.assertEqual(message.tag, "P", "element matches"); - test.assertEqual(message.content, "bar", "element content matches"); - this.destroy(); - doneTest(); - } - })); - - // web uri widget - tests.push(function testWebURIWidget() testSingleWidget({ - id: "web", - label: "web uri widget", - contentURL: require("self").data.url("test.html"), - contentScript: "self.postMessage({title: document.title, " + - "tag: document.body.firstElementChild.tagName, " + - "content: document.body.firstElementChild.innerHTML});", - contentScriptWhen: "end", - onMessage: function (message) { - test.assertEqual(message.title, "foo", "title matches"); - test.assertEqual(message.tag, "P", "element matches"); - test.assertEqual(message.content, "bar", "element content matches"); - this.destroy(); - doneTest(); - } - })); - - // event: onclick + content - tests.push(function testOnclickEventContent() testSingleWidget({ - id: "click", - label: "click test widget - content", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.getElementById('me').dispatchEvent(evt);", - contentScriptWhen: "end", - onClick: function() { - test.pass("onClick called"); - this.destroy(); - doneTest(); - } - })); - - // event: onmouseover + content - tests.push(function testOnmouseoverEventContent() testSingleWidget({ - id: "mouseover", - label: "mouseover test widget - content", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('mouseover', true, true ); " + - "document.getElementById('me').dispatchEvent(evt);", - contentScriptWhen: "end", - onMouseover: function() { - test.pass("onMouseover called"); - this.destroy(); - doneTest(); - } - })); - - // event: onmouseout + content - tests.push(function testOnmouseoutEventContent() testSingleWidget({ - id: "mouseout", - label: "mouseout test widget - content", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('mouseout', true, true ); " + - "document.getElementById('me').dispatchEvent(evt);", - contentScriptWhen: "end", - onMouseout: function() { - test.pass("onMouseout called"); - this.destroy(); - doneTest(); - } - })); - - // event: onclick + image - tests.push(function testOnclickEventImage() testSingleWidget({ - id: "click", - label: "click test widget - image", - contentURL: require("self").data.url("moz_favicon.ico"), - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.body.firstElementChild.dispatchEvent(evt);", - contentScriptWhen: "end", - onClick: function() { - test.pass("onClick called"); - this.destroy(); - doneTest(); - } - })); - - // event: onmouseover + image - tests.push(function testOnmouseoverEventImage() testSingleWidget({ - id: "mouseover", - label: "mouseover test widget - image", - contentURL: require("self").data.url("moz_favicon.ico"), - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('mouseover', true, true ); " + - "document.body.firstElementChild.dispatchEvent(evt);", - contentScriptWhen: "end", - onMouseover: function() { - test.pass("onMouseover called"); - this.destroy(); - doneTest(); - } - })); - - // event: onmouseout + image - tests.push(function testOnmouseoutEventImage() testSingleWidget({ - id: "mouseout", - label: "mouseout test widget - image", - contentURL: require("self").data.url("moz_favicon.ico"), - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('mouseout', true, true ); " + - "document.body.firstElementChild.dispatchEvent(evt);", - contentScriptWhen: "end", - onMouseout: function() { - test.pass("onMouseout called"); - this.destroy(); - doneTest(); - } - })); - - // test multiple widgets - tests.push(function testMultipleWidgets() { - let w1 = widgets.Widget({id: "first", label: "first widget", content: "first content"}); - let w2 = widgets.Widget({id: "second", label: "second widget", content: "second content"}); - - w1.destroy(); - w2.destroy(); - - doneTest(); - }); - - // test updating widget content - let loads = 0; - tests.push(function testUpdatingWidgetContent() testSingleWidget({ - id: "content", - label: "content update test widget", - content: "<div id='me'>foo</div>", - contentScript: "self.postMessage(1)", - contentScriptWhen: "ready", - onMessage: function(message) { - if (!this.flag) { - this.content = "<div id='me'>bar</div>"; - this.flag = 1; - } - else { - test.assertEqual(this.content, "<div id='me'>bar</div>"); - this.destroy(); - doneTest(); - } - } - })); - - // test updating widget contentURL - let url1 = "data:text/html,<body>foodle</body>"; - let url2 = "data:text/html,<body>nistel</body>"; - - tests.push(function testUpdatingContentURL() testSingleWidget({ - id: "content", - label: "content update test widget", - contentURL: url1, - contentScript: "self.postMessage(document.location.href);", - contentScriptWhen: "end", - onMessage: function(message) { - if (!this.flag) { - test.assertEqual(this.contentURL.toString(), url1); - test.assertEqual(message, url1); - this.contentURL = url2; - this.flag = 1; - } - else { - test.assertEqual(this.contentURL.toString(), url2); - test.assertEqual(message, url2); - this.destroy(); - doneTest(); - } - } - })); - - // test tooltip - tests.push(function testTooltip() testSingleWidget({ - id: "text", - label: "text widget", - content: "oh yeah", - tooltip: "foo", - contentScript: "self.postMessage(1)", - contentScriptWhen: "ready", - onMessage: function(message) { - test.assertEqual(this.tooltip, "foo", "tooltip matches"); - this.destroy(); - doneTest(); - } - })); - - // test tooltip fallback to label - tests.push(function testTooltipFallback() testSingleWidget({ - id: "fallback", - label: "fallback", - content: "oh yeah", - contentScript: "self.postMessage(1)", - contentScriptWhen: "ready", - onMessage: function(message) { - test.assertEqual(this.tooltip, this.label, "tooltip fallbacks to label"); - this.destroy(); - doneTest(); - } - })); - - // test updating widget tooltip - let updated = false; - tests.push(function testUpdatingTooltip() testSingleWidget({ - id: "tooltip", - label: "tooltip update test widget", - tooltip: "foo", - content: "<div id='me'>foo</div>", - contentScript: "self.postMessage(1)", - contentScriptWhen: "ready", - onMessage: function(message) { - this.tooltip = "bar"; - test.assertEqual(this.tooltip, "bar", "tooltip gets updated"); - this.destroy(); - doneTest(); - } - })); - - // test allow attribute - tests.push(function testDefaultAllow() testSingleWidget({ - id: "allow", - label: "allow.script attribute", - content: "<script>document.title = 'ok';</script>", - contentScript: "self.postMessage(document.title)", - onMessage: function(message) { - test.assertEqual(message, "ok", "scripts are evaluated by default"); - this.destroy(); - doneTest(); - } - })); - - tests.push(function testExplicitAllow() testSingleWidget({ - id: "allow", - label: "allow.script attribute", - allow: {script: true}, - content: "<script>document.title = 'ok';</script>", - contentScript: "self.postMessage(document.title)", - onMessage: function(message) { - test.assertEqual(message, "ok", "scripts are evaluated when we want to"); - this.destroy(); - doneTest(); - } - })); - - tests.push(function testExplicitDisallow() testSingleWidget({ - id: "allow", - label: "allow.script attribute", - content: "<script>document.title = 'ok';</script>", - allow: {script: false}, - contentScript: "self.postMessage(document.title)", - onMessage: function(message) { - test.assertNotEqual(message, "ok", "scripts aren't evaluated when " + - "explicitly blocked it"); - this.destroy(); - doneTest(); - } - })); - - // test multiple windows - tests.push(function testMultipleWindows() { - tabBrowser.addTab("about:blank", { inNewWindow: true, onLoad: function(e) { - let browserWindow = e.target.defaultView; - let doc = browserWindow.document; - function container() doc.getElementById("addon-bar"); - function widgetCount2() container() ? container().childNodes.length : 0; - let widgetStartCount2 = widgetCount2(); - - let w1Opts = {id:"first", label: "first widget", content: "first content"}; - let w1 = testSingleWidget(w1Opts); - test.assertEqual(widgetCount2(), widgetStartCount2 + 1, "2nd window has correct number of child elements after first widget"); - - let w2Opts = {id:"second", label: "second widget", content: "second content"}; - let w2 = testSingleWidget(w2Opts); - test.assertEqual(widgetCount2(), widgetStartCount2 + 2, "2nd window has correct number of child elements after second widget"); - - w1.destroy(); - test.assertEqual(widgetCount2(), widgetStartCount2 + 1, "2nd window has correct number of child elements after first destroy"); - w2.destroy(); - test.assertEqual(widgetCount2(), widgetStartCount2, "2nd window has correct number of child elements after second destroy"); - - closeBrowserWindow(browserWindow, function() { - doneTest(); - }); - }}); - }); - - // test window closing - tests.push(function testWindowClosing() { - // 1/ Create a new widget - let w1Opts = { - id:"first", - label: "first widget", - content: "first content", - contentScript: "self.port.on('event', function () self.port.emit('event'))" - }; - let widget = testSingleWidget(w1Opts); - let windows = require("windows").browserWindows; - - // 2/ Retrieve a WidgetView for the initial browser window - let acceptDetach = false; - let mainView = widget.getView(windows.activeWindow); - test.assert(mainView, "Got first widget view"); - mainView.on("detach", function () { - // 8/ End of our test. Accept detach event only when it occurs after - // widget.destroy() - if (acceptDetach) - doneTest(); - else - test.fail("View on initial window should not be destroyed"); - }); - mainView.port.on("event", function () { - // 7/ Receive event sent during 6/ and cleanup our test - acceptDetach = true; - widget.destroy(); - }); - - // 3/ First: open a new browser window - windows.open({ - url: "about:blank", - onOpen: function(window) { - // 4/ Retrieve a WidgetView for this new window - let view = widget.getView(window); - test.assert(view, "Got second widget view"); - view.port.on("event", function () { - test.fail("We should not receive event on the detach view"); - }); - view.on("detach", function () { - // The related view is destroyed - // 6/ Send a custom event - test.assertRaises(function () { - view.port.emit("event"); - }, - /The widget has been destroyed and can no longer be used./, - "emit on a destroyed view should throw"); - widget.port.emit("event"); - }); - - // 5/ Destroy this window - window.close(); - } - }); - }); - - tests.push(function testAddonBarHide() { - // Hide the addon-bar - browserWindow.setToolbarVisibility(container(), false); - - // Then open a browser window and verify that the addon-bar remains hidden - tabBrowser.addTab("about:blank", { inNewWindow: true, onLoad: function(e) { - let browserWindow = e.target.defaultView; - let doc = browserWindow.document; - function container2() doc.getElementById("addon-bar"); - function widgetCount2() container2() ? container2().childNodes.length : 0; - let widgetStartCount2 = widgetCount2(); - - let w1Opts = {id:"first", label: "first widget", content: "first content"}; - let w1 = testSingleWidget(w1Opts); - test.assertEqual(widgetCount2(), widgetStartCount2 + 1, "2nd window has correct number of child elements after widget creation"); - - w1.destroy(); - test.assertEqual(widgetCount2(), widgetStartCount2, "2nd window has correct number of child elements after widget destroy"); - - test.assert(container().collapsed, "1st window has an hidden addon-bar"); - test.assert(container2().collapsed, "2nd window has an hidden addon-bar"); - - browserWindow.setToolbarVisibility(container(), true); - - closeBrowserWindow(browserWindow, function() { - doneTest(); - }); - }}); - }); - - // test widget.width - tests.push(function testWidgetWidth() testSingleWidget({ - id: "text", - label: "test widget.width", - content: "test width", - width: 200, - contentScript: "self.postMessage(1)", - contentScriptWhen: "ready", - onMessage: function(message) { - test.assertEqual(this.width, 200); - - let node = widgetNode(0); - test.assertEqual(this.width, node.style.minWidth.replace("px", "")); - test.assertEqual(this.width, node.firstElementChild.style.width.replace("px", "")); - this.width = 300; - test.assertEqual(this.width, node.style.minWidth.replace("px", "")); - test.assertEqual(this.width, node.firstElementChild.style.width.replace("px", "")); - - this.destroy(); - doneTest(); - } - })); - - // test click handler not respond to right-click - let clickCount = 0; - tests.push(function testNoRightClick() testSingleWidget({ - id: "click-content", - label: "click test widget - content", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('MouseEvents'); " + - "evt.initMouseEvent('click', true, true, window, " + - " 0, 0, 0, 0, 0, false, false, false, false, 2, null); " + - "document.getElementById('me').dispatchEvent(evt); " + - "evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.getElementById('me').dispatchEvent(evt); " + - "evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('mouseover', true, true ); " + - "document.getElementById('me').dispatchEvent(evt);", - contentScriptWhen: "end", - onClick: function() clickCount++, - onMouseover: function() { - test.assertEqual(clickCount, 1, "right click wasn't sent to click handler"); - this.destroy(); - doneTest(); - } - })); - - // kick off test execution - doneTest(); -}; - -exports.testPanelWidget1 = function testPanelWidget1(test) { - const widgets = require("widget"); - - let widget1 = widgets.Widget({ - id: "panel1", - label: "panel widget 1", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.body.dispatchEvent(evt);", - contentScriptWhen: "end", - panel: require("panel").Panel({ - contentURL: "data:text/html,<body>Look ma, a panel!</body>", - onShow: function() { - widget1.destroy(); - test.pass("panel displayed on click"); - test.done(); - } - }) - }); - test.waitUntilDone(); -}; - -exports.testPanelWidget2 = function testPanelWidget2(test) { - const widgets = require("widget"); - test.assertRaises( - function() { - widgets.Widget({ - id: "panel2", - label: "panel widget 2", - panel: {} - }); - }, - "The option \"panel\" must be one of the following types: null, undefined, object", - "widget.panel must be a Panel object" - ); -}; - -exports.testPanelWidget3 = function testPanelWidget3(test) { - const widgets = require("widget"); - let onClickCalled = false; - let widget3 = widgets.Widget({ - id: "panel3", - label: "panel widget 3", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.body.firstElementChild.dispatchEvent(evt);", - contentScriptWhen: "end", - onClick: function() { - onClickCalled = true; - this.panel.show(); - }, - panel: require("panel").Panel({ - contentURL: "data:text/html,<body>Look ma, a panel!</body>", - onShow: function() { - test.assert( - onClickCalled, - "onClick called on click for widget with both panel and onClick" - ); - widget3.destroy(); - test.done(); - } - }) - }); - test.waitUntilDone(); -}; - -exports.testWidgetMessaging = function testWidgetMessaging(test) { - test.waitUntilDone(); - let origMessage = "foo"; - const widgets = require("widget"); - let widget = widgets.Widget({ - id: "foo", - label: "foo", - content: "<bar>baz</bar>", - contentScriptWhen: "end", - contentScript: "self.on('message', function(data) { self.postMessage(data); }); self.postMessage('ready');", - onMessage: function(message) { - if (message == "ready") - widget.postMessage(origMessage); - else { - test.assertEqual(origMessage, message); - widget.destroy(); - test.done(); - } - } - }); -}; - -exports.testWidgetViews = function testWidgetViews(test) { - test.waitUntilDone(); - const widgets = require("widget"); - let widget = widgets.Widget({ - id: "foo", - label: "foo", - content: "<bar>baz</bar>", - contentScriptWhen: "ready", - contentScript: "self.on('message', function(data) self.postMessage(data)); self.postMessage('ready')", - onAttach: function(view) { - test.pass("WidgetView created"); - view.on("message", function () { - test.pass("Got message in WidgetView"); - widget.destroy(); - }); - view.on("detach", function () { - test.pass("WidgetView destroyed"); - test.done(); - }); - } - }); - -}; - -exports.testWidgetViewsUIEvents = function testWidgetViewsUIEvents(test) { - test.waitUntilDone(); - const widgets = require("widget"); - let view = null; - let widget = widgets.Widget({ - id: "foo", - label: "foo", - content: "<div id='me'>foo</div>", - contentScript: "var evt = document.createEvent('HTMLEvents'); " + - "evt.initEvent('click', true, true ); " + - "document.getElementById('me').dispatchEvent(evt);", - contentScriptWhen: "ready", - onAttach: function(attachView) { - view = attachView; - test.pass("Got attach event"); - }, - onClick: function (eventView) { - test.assertEqual(view, eventView, - "event first argument is equal to the WidgetView"); - let view2 = widget.getView(require("windows").browserWindows.activeWindow); - test.assertEqual(view, view2, - "widget.getView return the same WidgetView"); - widget.destroy(); - test.done(); - } - }); -}; - -exports.testWidgetViewsCustomEvents = function testWidgetViewsCustomEvents(test) { - test.waitUntilDone(); - const widgets = require("widget"); - let widget = widgets.Widget({ - id: "foo", - label: "foo", - content: "<div id='me'>foo</div>", - contentScript: "self.port.emit('event', 'ok');", - contentScriptWhen: "ready", - onAttach: function(view) { - view.port.on("event", function (data) { - test.assertEqual(data, "ok", - "event argument is valid on WidgetView"); - }); - }, - }); - widget.port.on("event", function (data) { - test.assertEqual(data, "ok", - "event argument is valid on Widget"); - widget.destroy(); - test.done(); - }); -}; - -exports.testWidgetViewsTooltip = function testWidgetViewsTooltip(test) { - test.waitUntilDone(); - const widgets = require("widget"); - - let widget = new widgets.Widget({ - id: "foo", - label: "foo", - content: "foo" - }); - let view = widget.getView(require("windows").browserWindows.activeWindow); - widget.tooltip = null; - test.assertEqual(view.tooltip, "foo", - "view tooltip defaults to base widget label"); - test.assertEqual(widget.tooltip, "foo", - "tooltip defaults to base widget label"); - widget.destroy(); - test.done(); -}; - -exports.testWidgetMove = function testWidgetMove(test) { - test.waitUntilDone(); - - let windowUtils = require("window-utils"); - let widgets = require("widget"); - - let browserWindow = windowUtils.activeBrowserWindow; - let doc = browserWindow.document; - - let label = "unique-widget-label"; - let origMessage = "message after node move"; - let gotFirstReady = false; - - let widget = widgets.Widget({ - id: "foo", - label: label, - content: "<bar>baz</bar>", - contentScriptWhen: "ready", - contentScript: "self.on('message', function(data) { self.postMessage(data); }); self.postMessage('ready');", - onMessage: function(message) { - if (message == "ready") { - if (!gotFirstReady) { - test.pass("Got first ready event"); - let widgetNode = doc.querySelector('toolbaritem[label="' + label + '"]'); - let parent = widgetNode.parentNode; - parent.insertBefore(widgetNode, parent.firstChild); - gotFirstReady = true; - } else { - test.pass("Got second ready event"); - widget.postMessage(origMessage); - } - } - else { - test.assertEqual(origMessage, message, "Got message after node move"); - widget.destroy(); - test.done(); - } - } - }); -}; - -/* -The bug is exhibited when a widget with HTML content has it's content -changed to new HTML content with a pound in it. Because the src of HTML -content is converted to a data URI, the underlying iframe doesn't -consider the content change a navigation change, so doesn't load -the new content. -*/ -exports.testWidgetWithPound = function testWidgetWithPound(test) { - test.waitUntilDone(); - - function getWidgetContent(widget) { - let windowUtils = require("window-utils"); - let browserWindow = windowUtils.activeBrowserWindow; - let doc = browserWindow.document; - let widgetNode = doc.querySelector('toolbaritem[label="' + widget.label + '"]'); - test.assert(widgetNode, 'found widget node in the front-end'); - return widgetNode.firstChild.contentDocument.body.innerHTML; - } - - let widgets = require("widget"); - let count = 0; - let widget = widgets.Widget({ - id: "1", - label: "foo", - content: "foo", - contentScript: "window.addEventListener('load', self.postMessage, false);", - onMessage: function() { - count++; - if (count == 1) { - widget.content = "foo#"; - } - else { - test.assertEqual(getWidgetContent(widget), "foo#", "content updated to pound?"); - widget.destroy(); - test.done(); - } - } - }); -}; - -/******************* helpers *********************/ - -// Helper for calling code at window close -function closeBrowserWindow(window, callback) { - require("timer").setTimeout(function() { - window.addEventListener("unload", function onUnload() { - window.removeEventListener("unload", onUnload, false); - callback(); - }, false); - window.close(); - }, 0); -} - -// ADD NO TESTS BELOW THIS LINE! /////////////////////////////////////////////// - -// 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. -try { - require("widget"); -} -catch (err) { - // This bug should be mentioned in the error message. - let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=560716"; - if (err.message.indexOf(bug) < 0) - throw err; - for (let [prop, val] in Iterator(exports)) { - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - } - exports.testAppNotSupported = function (test) { - test.pass("context-menu does not support this application."); - }; -} - diff --git a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-windows.js b/tools/addon-sdk-1.4/packages/addon-kit/tests/test-windows.js deleted file mode 100644 index e2824f8..0000000 --- a/tools/addon-sdk-1.4/packages/addon-kit/tests/test-windows.js +++ /dev/null @@ -1,342 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Felipe Gomes <felipc@gmail.com> (Original author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const {Cc, Ci} = require("chrome"); -const { setTimeout } = require("timer"); -const { Loader } = require('./helpers'); -const wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); -let browserWindows; - -function getTestRunnerWindow() wm.getMostRecentWindow("test:runner") - -exports.testOpenAndCloseWindow = function(test) { - test.waitUntilDone(); - - test.assertEqual(browserWindows.length, 1, "Only one window open"); - - browserWindows.open({ - url: "data:text/html,<title>windows API test</title>", - onOpen: function(window) { - test.assertEqual(this, browserWindows, - "The 'this' object is the windows object."); - test.assertEqual(window.tabs.length, 1, "Only one tab open"); - test.assertEqual(browserWindows.length, 2, "Two windows open"); - window.tabs.activeTab.on('ready', function onReady(tab) { - tab.removeListener('ready', onReady); - test.assert(window.title.indexOf("windows API test") != -1, - "URL correctly loaded"); - window.close(); - }); - }, - onClose: function(window) { - test.assertEqual(window.tabs.length, 0, "Tabs were cleared"); - test.assertEqual(browserWindows.length, 1, "Only one window open"); - test.done(); - } - }); -}; - -exports.testAutomaticDestroy = function(test) { - - test.waitUntilDone(); - let windows = browserWindows; - - // Create a second windows instance that we will unload - let called = false; - let loader = Loader(module); - let windows2 = loader.require("windows").browserWindows; - windows2.on("open", function() { - called = true; - }); - - loader.unload(); - - // Fire a windows event and check that this unloaded instance is inactive - windows.open({ - url: "data:text/html,foo", - onOpen: function(window) { - setTimeout(function () { - test.assert(!called, - "Unloaded windows instance is destroyed and inactive"); - window.close(function () { - test.done(); - }); - }); - } - }); - -}; - -exports.testOnOpenOnCloseListeners = function(test) { - test.waitUntilDone(); - let windows = browserWindows; - - test.assertEqual(browserWindows.length, 1, "Only one window open"); - - let received = { - listener1: false, - listener2: false, - listener3: false, - listener4: false - } - - function listener1() { - test.assertEqual(this, windows, "The 'this' object is the windows object."); - if (received.listener1) - test.fail("Event received twice"); - received.listener1 = true; - } - - function listener2() { - if (received.listener2) - test.fail("Event received twice"); - received.listener2 = true; - } - - function listener3() { - test.assertEqual(this, windows, "The 'this' object is the windows object."); - if (received.listener3) - test.fail("Event received twice"); - received.listener3 = true; - } - - function listener4() { - if (received.listener4) - test.fail("Event received twice"); - received.listener4 = true; - } - - windows.on('open', listener1); - windows.on('open', listener2); - windows.on('close', listener3); - windows.on('close', listener4); - - function verify() { - test.assert(received.listener1, "onOpen handler called"); - test.assert(received.listener2, "onOpen handler called"); - test.assert(received.listener3, "onClose handler called"); - test.assert(received.listener4, "onClose handler called"); - - windows.removeListener('open', listener1); - windows.removeListener('open', listener2); - windows.removeListener('close', listener3); - windows.removeListener('close', listener4); - test.done(); - } - - - windows.open({ - url: "data:text/html,foo", - onOpen: function(window) { - window.close(verify); - } - }); -}; - -exports.testWindowTabsObject = function(test) { - test.waitUntilDone(); - - browserWindows.open({ - url: "data:text/html,<title>tab 1</title>", - onOpen: function onOpen(window) { - test.assertEqual(window.tabs.length, 1, "Only 1 tab open"); - - window.tabs.open({ - url: "data:text/html,<title>tab 2</title>", - inBackground: true, - onReady: function onReady(newTab) { - test.assertEqual(window.tabs.length, 2, "New tab open"); - test.assertEqual(newTab.title, "tab 2", "Correct new tab title"); - test.assertEqual(window.tabs.activeTab.title, "tab 1", "Correct active tab"); - - let i = 1; - for each (let tab in window.tabs) - test.assertEqual(tab.title, "tab " + i++, "Correct title"); - - window.close(); - } - }); - }, - onClose: function onClose(window) { - test.assertEqual(window.tabs.length, 0, "No more tabs on closed window"); - test.done(); - } - }); -}; - -exports.testActiveWindow = function(test) { - const xulApp = require("xul-app"); - if (xulApp.versionInRange(xulApp.platformVersion, "1.9.2", "1.9.2.*")) { - test.pass("This test is disabled on 3.6. For more information, see bug 598525"); - return; - } - - let windows = browserWindows; - - // API window objects - let window2, window3; - - // Raw window objects - let nonBrowserWindow = getTestRunnerWindow(), rawWindow2, rawWindow3; - - test.waitUntilDone(); - - let testSteps = [ - function() { - test.assertEqual(windows.length, 3, "Correct number of browser windows"); - let count = 0; - for (let window in windows) - count++; - test.assertEqual(count, 3, "Correct number of windows returned by iterator"); - - rawWindow2.focus(); - continueAfterFocus(rawWindow2); - }, - function() { - nonBrowserWindow.focus(); - continueAfterFocus(nonBrowserWindow); - }, - function() { - /** - * Bug 614079: This test fails intermittently on some specific linux - * environnements, without being able to reproduce it in same - * distribution with same window manager. - * Disable it until being able to reproduce it easily. - - // On linux, focus is not consistent, so we can't be sure - // what window will be on top. - // Here when we focus "non-browser" window, - // Any Browser window may be selected as "active". - test.assert(windows.activeWindow == window2 || windows.activeWindow == window3, - "Non-browser windows aren't handled by this module"); - */ - window2.activate(); - continueAfterFocus(rawWindow2); - }, - function() { - test.assertEqual(windows.activeWindow.title, window2.title, "Correct active window - 2"); - window3.activate(); - continueAfterFocus(rawWindow3); - }, - function() { - test.assertEqual(windows.activeWindow.title, window3.title, "Correct active window - 3"); - nonBrowserWindow.focus(); - finishTest(); - } - ]; - - windows.open({ - url: "data:text/html,<title>window 2</title>", - onOpen: function(window) { - window2 = window; - rawWindow2 = wm.getMostRecentWindow("navigator:browser"); - - windows.open({ - url: "data:text/html,<title>window 3</title>", - onOpen: function(window) { - window.tabs.activeTab.on('ready', function onReady() { - window3 = window; - rawWindow3 = wm.getMostRecentWindow("navigator:browser"); - nextStep() - }); - } - }); - } - }); - - function nextStep() { - if (testSteps.length > 0) - testSteps.shift()(); - } - - function continueAfterFocus(targetWindow) { - - // Based on SimpleTest.waitForFocus - var fm = Cc["@mozilla.org/focus-manager;1"]. - getService(Ci.nsIFocusManager); - - var childTargetWindow = {}; - fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow); - childTargetWindow = childTargetWindow.value; - - var focusedChildWindow = {}; - if (fm.activeWindow) { - fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow); - focusedChildWindow = focusedChildWindow.value; - } - - var focused = (focusedChildWindow == childTargetWindow); - if (focused) { - nextStep(); - } else { - childTargetWindow.addEventListener("focus", function focusListener() { - childTargetWindow.removeEventListener("focus", focusListener, true); - nextStep(); - }, true); - } - - } - - function finishTest() { - window3.close(function() { - window2.close(function() { - test.done(); - }); - }); - } -}; - -// 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. -try { - browserWindows = require("windows").browserWindows; -} -catch (err) { - // This bug should be mentioned in the error message. - let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=571449"; - if (err.message.indexOf(bug) < 0) - throw err; - for (let [prop, val] in Iterator(exports)) { - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - } - exports.testAppNotSupported = function (test) { - test.pass("the windows module does not support this application."); - }; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/README.md b/tools/addon-sdk-1.4/packages/api-utils/README.md deleted file mode 100644 index e973e4c..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/README.md +++ /dev/null @@ -1,31 +0,0 @@ -API Utils provides a basic CommonJS infrastructure for -developing traditional XULRunner add-ons and applications. It is -the basis for the Add-on SDK. - -To address issues present in traditional add-on development, -API Utils provides mechanisms for: - -* writing and executing test cases, inspired by Python's [nose][] - package, -* tracking JS objects of interest to aid in memory profiling and leak - detection, -* registering callbacks that perform cleanup tasks when modules are - unloaded, -* easily reporting errors with full stack tracebacks. - -API Utils also has the following characteristics: - -* Beautiful, concise documentation. -* A rigorous test suite ensuring that the library doesn't break as the - Mozilla platform evolves. -* Solid developer ergonomics ensuring that developers can easily find - out why something they're doing isn't working. - -API Utils is intended to be very small and only contain the bare -minimum of functionality that all add-ons need. - -Note that the API Utils package has not fully stabilized yet, meaning that -we do still expect to make incompatible changes to its APIs in future releases -of the SDK. - - [nose]: http://code.google.com/p/python-nose/ diff --git a/tools/addon-sdk-1.4/packages/api-utils/data/content-proxy.js b/tools/addon-sdk-1.4/packages/api-utils/data/content-proxy.js deleted file mode 100644 index 6eadce9..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/data/content-proxy.js +++ /dev/null @@ -1,834 +0,0 @@ -"use strict"; - -let Ci = Components.interfaces; - -/** - * Access key that allows privileged code to unwrap proxy wrappers through - * valueOf: - * let xpcWrapper = proxyWrapper.valueOf(UNWRAP_ACCESS_KEY); - * This key should only be used by proxy unit test. - */ - const UNWRAP_ACCESS_KEY = {}; - - - /** - * Returns a closure that wraps arguments before calling the given function, - * which can be given to native functions that accept a function, such that when - * the closure is called, the given function is called with wrapped arguments. - * - * @param fun {Function} - * the function for which to create a closure wrapping its arguments - * @param obj {Object} - * target object from which `fun` comes from - * (optional, for debugging purpose) - * @param name {String} - * name of the attribute from which `fun` is binded on `obj` - * (optional, for debugging purpose) - * - * Example: - * function contentScriptListener(event) {} - * let wrapper = ContentScriptFunctionWrapper(contentScriptListener); - * xray.addEventListener("...", wrapper, false); - * -> Allow to `event` to be wrapped - */ -function ContentScriptFunctionWrapper(fun, obj, name) { - if ("___proxy" in fun && typeof fun.___proxy == "function") - return fun.___proxy; - - let wrappedFun = function () { - let args = []; - for (let i = 0, l = arguments.length; i < l; i++) - args.push(wrap(arguments[i])); - - //console.log("Called from native :"+obj+"."+name); - //console.log(">args "+arguments.length); - //console.log(fun); - - // Native code can execute this callback with `this` being the wrapped - // function. For example, window.mozRequestAnimationFrame. - if (this == wrappedFun) - return fun.apply(fun, args); - - return fun.apply(wrap(this), args); - }; - - Object.defineProperty(fun, "___proxy", {value : wrappedFun, - writable : false, - enumerable : false, - configurable : false}); - - return wrappedFun; -} - -/** - * Returns a closure that unwraps arguments before calling the `fun` function, - * which can be used to build a wrapper for a native function that accepts - * wrapped arguments, since native function only accept unwrapped arguments. - * - * @param fun {Function} - * the function to wrap - * @param originalObject {Object} - * target object from which `fun` comes from - * (optional, for debugging purpose) - * @param name {String} - * name of the attribute from which `fun` is binded on `originalObject` - * (optional, for debugging purpose) - * - * Example: - * wrapper.appendChild = NativeFunctionWrapper(xray.appendChild, xray); - * wrapper.appendChild(anotherWrapper); - * -> Allow to call xray.appendChild with unwrapped version of anotherWrapper - */ -function NativeFunctionWrapper(fun, originalObject, name) { - return function () { - let args = []; - let obj = this && typeof this.valueOf == "function" ? - this.valueOf(UNWRAP_ACCESS_KEY) : this; - - for (let i = 0, l = arguments.length; i < l; i++) - args.push( unwrap(arguments[i], obj, name) ); - - //if (name != "toString") - //console.log(">>calling native ["+(name?name:'#closure#')+"]: \n"+fun.apply+"\n"+obj+"\n("+args.join(', ')+")\nthis :"+obj+"from:"+originalObject+"\n"); - - // Need to use Function.prototype.apply.apply because XMLHttpRequest - // is a function (typeof return 'function') and fun.apply is null :/ - let unwrapResult = Function.prototype.apply.apply(fun, [obj, args]); - let result = wrap(unwrapResult, obj, name); - - //console.log("<< "+rr+" -> "+r); - - return result; - }; -} - -/* - * Unwrap a JS value that comes from the content script. - * Mainly converts proxy wrapper to XPCNativeWrapper. - */ -function unwrap(value, obj, name) { - //console.log("unwrap : "+value+" ("+name+")"); - if (!value) - return value; - let type = typeof value; - - // In case of proxy, unwrap them recursively - // (it should not be recursive, just in case of) - if (["object", "function"].indexOf(type) !== -1 && - "__isWrappedProxy" in value) { - while("__isWrappedProxy" in value) - value = value.valueOf(UNWRAP_ACCESS_KEY); - return value; - } - - // In case of functions we need to return a wrapper that converts native - // arguments applied to this function into proxies. - if (type == "function") - return ContentScriptFunctionWrapper(value, obj, name); - - // We must wrap objects coming from content script too, as they may have - // a function that will be called by a native method. - // For example: - // addEventListener(..., { handleEvent: function(event) {} }, ...); - if (type == "object") - return ContentScriptObjectWrapper(value); - - if (["string", "number", "boolean"].indexOf(type) !== -1) - return value; - //console.log("return non-wrapped to native : "+typeof value+" -- "+value); - return value; -} - -/** - * Returns an XrayWrapper proxy object that allow to wrap any of its function - * though `ContentScriptFunctionWrapper`. These proxies are given to - * XrayWrappers in order to automatically wrap values when they call a method - * of these proxies. So that they are only used internaly and content script, - * nor web page have ever access to them. As a conclusion, we can consider - * this code as being safe regarding web pages overload. - * - * - * @param obj {Object} - * object coming from content script context to wrap - * - * Example: - * let myListener = { handleEvent: function (event) {} }; - * node.addEventListener("click", myListener, false); - * `event` has to be wrapped, so handleEvent has to be wrapped using - * `ContentScriptFunctionWrapper` function. - * In order to do so, we build this new kind of proxies. - */ -function ContentScriptObjectWrapper(obj) { - if ("___proxy" in obj && typeof obj.___proxy == "object") - return obj.___proxy; - - function valueOf(key) { - if (key === UNWRAP_ACCESS_KEY) - return obj; - return this; - } - - let proxy = Proxy.create({ - // Fundamental traps - getPropertyDescriptor: function(name) { - return Object.getOwnPropertyDescriptor(obj, name); - }, - defineProperty: function(name, desc) { - return Object.defineProperty(obj, name, desc); - }, - getOwnPropertyNames: function () { - return Object.getOwnPropertyNames(obj); - }, - delete: function(name) { - return delete obj[name]; - }, - // derived traps - has: function(name) { - return name === "__isXrayWrapperProxy" || - name in obj; - }, - hasOwn: function(name) { - return Object.prototype.hasOwnProperty.call(obj, name); - }, - get: function(receiver, name) { - if (name == "valueOf") - return valueOf; - let value = obj[name]; - if (!value) - return value; - - return unwrap(value); - }, - set: function(receiver, name, val) { - obj[name] = val; - return true; - }, - enumerate: function() { - var result = []; - for each (let name in obj) { - result.push(name); - }; - return result; - }, - keys: function() { - return Object.keys(obj); - } - }); - - Object.defineProperty(obj, "___proxy", {value : proxy, - writable : false, - enumerable : false, - configurable : false}); - - return proxy; -} - -// List of all existing typed arrays. -// Can be found here: -// http://mxr.mozilla.org/mozilla-central/source/js/src/jsapi.cpp#1790 -const typedArraysCtor = [ - ArrayBuffer, - Int8Array, - Uint8Array, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - Uint8ClampedArray -]; - -/* - * Wrap a JS value coming from the document by building a proxy wrapper. - */ -function wrap(value, obj, name, debug) { - if (!value) - return value; - let type = typeof value; - if (type == "object") { - // Bug 671016: Typed arrays don't need to be proxified. - // We avoid checking the whole constructor list on all objects - // by doing this check only on non-extensible objects: - if (!Object.isExtensible(value) && - typedArraysCtor.indexOf(value.constructor) !== -1) - return value; - - // We may have a XrayWrapper proxy. - // For example: - // let myListener = { handleEvent: function () {} }; - // node.addEventListener("click", myListener, false); - // When native code want to call handleEvent, - // we go though ContentScriptFunctionWrapper that calls `wrap(this)` - // `this` is the XrayWrapper proxy of myListener. - // We return this object without building a CS proxy as it is already - // a value coming from the CS. - if ("__isXrayWrapperProxy" in value) - return value.valueOf(UNWRAP_ACCESS_KEY); - - // Unwrap object before wrapping it. - // It should not happen with CS proxy objects. - while("__isWrappedProxy" in value) { - value = value.valueOf(UNWRAP_ACCESS_KEY); - } - - if (XPCNativeWrapper.unwrap(value) !== value) - return getProxyForObject(value); - // In case of Event, HTMLCollection or NodeList or ??? - // XPCNativeWrapper.unwrap(value) === value - // but it's still a XrayWrapper so let's build a proxy - return getProxyForObject(value); - } - if (type == "function") { - if (XPCNativeWrapper.unwrap(value) !== value - || (typeof value.toString === "function" && - value.toString().match(/\[native code\]/))) { - return getProxyForFunction(value, NativeFunctionWrapper(value, obj, name)); - } - return value; - } - if (type == "string") - return value; - if (type == "number") - return value; - if (type == "boolean") - return value; - //console.log("return non-wrapped to wrapped : "+value); - return value; -} - -/* - * Wrap an object from the document to a proxy wrapper - */ -function getProxyForObject(obj) { - if (typeof obj != "object") { - let msg = "tried to proxify something other than an object: " + typeof obj; - console.warn(msg); - throw msg; - } - if ("__isWrappedProxy" in obj) { - return obj; - } - // Check if there is a proxy cached on this wrapper, - // but take care of prototype ___proxy attribute inheritance! - if (obj && obj.___proxy && obj.___proxy.valueOf(UNWRAP_ACCESS_KEY) === obj) { - return obj.___proxy; - } - - let proxy = Proxy.create(handlerMaker(obj)); - - Object.defineProperty(obj, "___proxy", {value : proxy, - writable : false, - enumerable : false, - configurable : false}); - return proxy; -} - -/* - * Wrap a function from the document to a proxy wrapper - */ -function getProxyForFunction(fun, callTrap) { - if (typeof fun != "function") { - let msg = "tried to proxify something other than a function: " + typeof fun; - console.warn(msg); - throw msg; - } - if ("__isWrappedProxy" in fun) - return obj; - if ("___proxy" in fun) - return fun.___proxy; - - let proxy = Proxy.createFunction(handlerMaker(fun), callTrap); - - Object.defineProperty(fun, "___proxy", {value : proxy, - writable : false, - enumerable : false, - configurable : false}); - - return proxy; -} - -/* - * Check if a DOM attribute name is an event name. - */ -function isEventName(id) { - if (id.indexOf("on") != 0 || id.length == 2) - return false; - // Taken from: - // http://mxr.mozilla.org/mozilla-central/source/dom/base/nsDOMClassInfo.cpp#7616 - switch (id[2]) { - case 'a' : - return (id == "onabort" || - id == "onafterscriptexecute" || - id == "onafterprint"); - case 'b' : - return (id == "onbeforeunload" || - id == "onbeforescriptexecute" || - id == "onblur" || - id == "onbeforeprint"); - case 'c' : - return (id == "onchange" || - id == "onclick" || - id == "oncontextmenu" || - id == "oncopy" || - id == "oncut" || - id == "oncanplay" || - id == "oncanplaythrough"); - case 'd' : - return (id == "ondblclick" || - id == "ondrag" || - id == "ondragend" || - id == "ondragenter" || - id == "ondragleave" || - id == "ondragover" || - id == "ondragstart" || - id == "ondrop" || - id == "ondurationchange"); - case 'e' : - return (id == "onerror" || - id == "onemptied" || - id == "onended"); - case 'f' : - return id == "onfocus"; - case 'h' : - return id == "onhashchange"; - case 'i' : - return (id == "oninput" || - id == "oninvalid"); - case 'k' : - return (id == "onkeydown" || - id == "onkeypress" || - id == "onkeyup"); - case 'l' : - return (id == "onload" || - id == "onloadeddata" || - id == "onloadedmetadata" || - id == "onloadstart"); - case 'm' : - return (id == "onmousemove" || - id == "onmouseout" || - id == "onmouseover" || - id == "onmouseup" || - id == "onmousedown" || - id == "onmessage"); - case 'p' : - return (id == "onpaint" || - id == "onpageshow" || - id == "onpagehide" || - id == "onpaste" || - id == "onpopstate" || - id == "onpause" || - id == "onplay" || - id == "onplaying" || - id == "onprogress"); - case 'r' : - return (id == "onreadystatechange" || - id == "onreset" || - id == "onresize" || - id == "onratechange"); - case 's' : - return (id == "onscroll" || - id == "onselect" || - id == "onsubmit" || - id == "onseeked" || - id == "onseeking" || - id == "onstalled" || - id == "onsuspend"); - case 't': - return id == "ontimeupdate" - /* - // TODO: Make it work for mobile version - || - (nsDOMTouchEvent::PrefEnabled() && - (id == "ontouchstart" || - id == "ontouchend" || - id == "ontouchmove" || - id == "ontouchenter" || - id == "ontouchleave" || - id == "ontouchcancel"))*/; - - case 'u' : - return id == "onunload"; - case 'v': - return id == "onvolumechange"; - case 'w': - return id == "onwaiting"; - } - - return false; -} - -// XrayWrappers miss some attributes. -// Here is a list of functions that return a value when it detects a miss: -const NODES_INDEXED_BY_NAME = ["IMG", "FORM", "APPLET", "EMBED", "OBJECT"]; -const xRayWrappersMissFixes = [ - - // Fix bug with XPCNativeWrapper on HTMLCollection - // We can only access array item once, then it's undefined :o - function (obj, name) { - let i = parseInt(name); - if (obj.toString().match(/HTMLCollection|NodeList/) && - i >= 0 && i < obj.length) { - return wrap(XPCNativeWrapper(obj.wrappedJSObject[name]), obj, name); - } - return null; - }, - - // Trap access to document["form name"] - // that may refer to an existing form node - // http://mxr.mozilla.org/mozilla-central/source/dom/base/nsDOMClassInfo.cpp#9285 - function (obj, name) { - if ("nodeType" in obj && obj.nodeType == 9) { - let node = obj.wrappedJSObject[name]; - // List of supported tag: - // http://mxr.mozilla.org/mozilla-central/source/content/html/content/src/nsGenericHTMLElement.cpp#1267 - if (node && NODES_INDEXED_BY_NAME.indexOf(node.tagName) != -1) - return wrap(XPCNativeWrapper(node)); - } - return null; - }, - - // Trap access to window["frame name"] and window.frames[i] - // that refer to an (i)frame internal window object - // http://mxr.mozilla.org/mozilla-central/source/dom/base/nsDOMClassInfo.cpp#6824 - function (obj, name) { - if (typeof obj == "object" && "document" in obj) { - // Ensure that we are on a window object - try { - obj.QueryInterface(Ci.nsIDOMWindow); - } - catch(e) { - return null; - } - - // Integer case: - let i = parseInt(name); - if (i >= 0 && i in obj) { - return wrap(XPCNativeWrapper(obj[i])); - } - - // String name case: - if (name in obj.wrappedJSObject) { - let win = obj.wrappedJSObject[name]; - let nodes = obj.document.getElementsByName(name); - for (let i = 0, l = nodes.length; i < l; i++) { - let node = nodes[i]; - if ("contentWindow" in node && node.contentWindow == win) - return wrap(node.contentWindow); - } - } - } - return null; - }, - - // Trap access to form["node name"] - // http://mxr.mozilla.org/mozilla-central/source/dom/base/nsDOMClassInfo.cpp#9477 - function (obj, name) { - if (typeof obj == "object" && obj.tagName == "FORM") { - let match = obj.wrappedJSObject[name]; - let nodes = obj.ownerDocument.getElementsByName(name); - for (let i = 0, l = nodes.length; i < l; i++) { - let node = nodes[i]; - if (node == match) - return wrap(node); - } - } - return null; - }, - - // Fix XPathResult's constants being undefined on XrayWrappers - // these constants are defined here: - // http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/xpath/nsIDOMXPathResult.idl - // and are only numbers. - // The platform bug 665279 was fixed in Gecko 10.0a1. - // FIXME: remove this workaround once the SDK no longer supports Firefox 9. - function (obj, name) { - if (typeof obj == "object" && name in Ci.nsIDOMXPathResult) { - let value = Ci.nsIDOMXPathResult[name]; - if (typeof value == "number" && value === obj.wrappedJSObject[name]) - return value; - } - return null; - } - -]; - -// XrayWrappers have some buggy methods. -// Here is the list of them with functions returning some replacement -// for a given object `obj`: -const xRayWrappersMethodsFixes = { - // postMessage method is checking the Javascript global - // and it expects it to be a window object. - // But in our case, the global object is our sandbox global object. - // See nsGlobalWindow::CallerInnerWindow(): - // http://mxr.mozilla.org/mozilla-central/source/dom/base/nsGlobalWindow.cpp#5893 - // nsCOMPtr<nsPIDOMWindow> win = do_QueryWrappedNative(wrapper); - // win is null - postMessage: function (obj) { - // Ensure that we are on a window object - try { - obj.QueryInterface(Ci.nsIDOMWindow); - } - catch(e) { - return null; - } - // Create a wrapper that is going to call `postMessage` through `eval` - let f = function postMessage(message, targetOrigin) { - message = message.toString().replace(/['\\]/g,"\\$&"); - targetOrigin = targetOrigin.toString().replace(/['\\]/g,"\\$&"); - - let jscode = "this.postMessage('" + message + "', '" + - targetOrigin + "')"; - return this.wrappedJSObject.eval(jscode); - }; - return getProxyForFunction(f, NativeFunctionWrapper(f)); - }, - - // Fix mozMatchesSelector uses that is broken on XrayWrappers - // when we use document.documentElement.mozMatchesSelector.call(node, expr) - // It's only working if we call mozMatchesSelector on the node itself. - // SEE BUG 658909: mozMatchesSelector returns incorrect results with XrayWrappers - mozMatchesSelector: function (obj) { - // Ensure that we are on an object to expose this buggy method - try { - // Bug 707576 removed nsIDOMNSElement. - // Can be simplified as soon as Firefox 11 become the minversion - obj.QueryInterface("nsIDOMElement" in Ci ? Ci.nsIDOMElement : - Ci.nsIDOMNSElement); - } - catch(e) { - return null; - } - // We can't use `wrap` function as `f` is not a native function, - // so wrap it manually: - let f = function mozMatchesSelector(selectors) { - return this.mozMatchesSelector(selectors); - }; - - return getProxyForFunction(f, NativeFunctionWrapper(f)); - }, - - // Bug 679054: History API doesn't work with Proxy objects. We have to pass - // regular JS objects on `pushState` and `replaceState` methods. - // In addition, the first argument has to come from the same compartment. - pushState: function (obj) { - // Ensure that we are on an object that expose History API - try { - obj.QueryInterface(Ci.nsIDOMHistory); - } - catch(e) { - return null; - } - let f = function fix() { - // Call native method with JSON objects - // (need to convert `arguments` to an array via `slice`) - return this.pushState.apply(this, JSON.parse(JSON.stringify(Array.slice(arguments)))); - }; - - return getProxyForFunction(f, NativeFunctionWrapper(f)); - }, - replaceState: function (obj) { - // Ensure that we are on an object that expose History API - try { - obj.QueryInterface(Ci.nsIDOMHistory); - } - catch(e) { - return null; - } - let f = function fix() { - // Call native method with JSON objects - // (need to convert `arguments` to an array via `slice`) - return this.replaceState.apply(this, JSON.parse(JSON.stringify(Array.slice(arguments)))); - }; - - return getProxyForFunction(f, NativeFunctionWrapper(f)); - } -}; - -/* - * Generate handler for proxy wrapper - */ -function handlerMaker(obj) { - // Overloaded attributes dictionary - let overload = {}; - // Expando attributes dictionary (i.e. onclick, onfocus, on* ...) - let expando = {}; - // Cache of methods overloaded to fix XrayWrapper bug - let methodFixes = {}; - return { - // Fundamental traps - getPropertyDescriptor: function(name) { - return Object.getOwnPropertyDescriptor(obj, name); - }, - defineProperty: function(name, desc) { - return Object.defineProperty(obj, name, desc); - }, - getOwnPropertyNames: function () { - return Object.getOwnPropertyNames(obj); - }, - delete: function(name) { - delete expando[name]; - delete overload[name]; - return delete obj[name]; - }, - - // derived traps - has: function(name) { - if (name == "___proxy") return false; - if (isEventName(name)) { - // XrayWrappers throw exception when we try to access expando attributes - // even on "name in wrapper". So avoid doing it! - return name in expando; - } - return name in obj || name in overload || name == "__isWrappedProxy" || - undefined !== this.get(null, name); - }, - hasOwn: function(name) { - return Object.prototype.hasOwnProperty.call(obj, name); - }, - get: function(receiver, name) { - if (name == "___proxy") - return undefined; - - // Overload toString in order to avoid returning "[XrayWrapper [object HTMLElement]]" - // or "[object Function]" for function's Proxy - if (name == "toString") { - if ("wrappedJSObject" in obj) { - // Bug 714778: we should not pass obj.wrappedJSObject.toString - // in order to avoid sharing its proxy over contents scripts: - return wrap(function () { - return obj.wrappedJSObject.toString.call( - this.valueOf(UNWRAP_ACCESS_KEY), arguments); - }, obj, name); - } - else { - return wrap(obj.toString, obj, name); - } - } - - // Offer a way to retrieve XrayWrapper from a proxified node through `valueOf` - if (name == "valueOf") - return function (key) { - if (key === UNWRAP_ACCESS_KEY) - return obj; - return this; - }; - - // Return overloaded value if there is one. - // It allows to overload native methods like addEventListener that - // are not saved, even on the wrapper itself. - // (And avoid some methods like toSource from being returned here! [__proto__ test]) - if (name in overload && - overload[name] != Object.getPrototypeOf(overload)[name] && - name != "__proto__") { - return overload[name]; - } - - // Catch exceptions thrown by XrayWrappers when we try to access on* - // attributes like onclick, onfocus, ... - if (isEventName(name)) { - //console.log("expando:"+obj+" - "+obj.nodeType); - return name in expando ? expando[name].original : undefined; - } - - // Overload some XrayWrappers method in order to fix its bugs - if (name in methodFixes && - methodFixes[name] != Object.getPrototypeOf(methodFixes)[name] && - name != "__proto__") - return methodFixes[name]; - if (Object.keys(xRayWrappersMethodsFixes).indexOf(name) !== -1) { - let fix = xRayWrappersMethodsFixes[name](obj); - if (fix) - return methodFixes[name] = fix; - } - - let o = obj[name]; - - // XrayWrapper miss some attributes, try to catch these and return a value - if (!o) { - for each(let atttributeFixer in xRayWrappersMissFixes) { - let fix = atttributeFixer(obj, name); - if (fix) - return fix; - } - } - - // Generic case - return wrap(o, obj, name); - - }, - - set: function(receiver, name, val) { - - if (isEventName(name)) { - //console.log("SET on* attribute : " + name + " / " + val + "/" + obj); - let shortName = name.replace(/^on/,""); - - // Unregister previously set listener - if (expando[name]) { - obj.removeEventListener(shortName, expando[name], true); - delete expando[name]; - } - - // Only accept functions - if (typeof val != "function") - return false; - - // Register a new listener - let original = val; - val = ContentScriptFunctionWrapper(val); - expando[name] = val; - val.original = original; - obj.addEventListener(name.replace(/^on/, ""), val, true); - return true; - } - - obj[name] = val; - - // Handle native method not overloaded on XrayWrappers: - // obj.addEventListener = val; -> obj.addEventlistener = native method - // And, XPCNativeWrapper bug where nested values appear to be wrapped: - // obj.customNestedAttribute = val -> obj.customNestedAttribute !== val - // obj.customNestedAttribute = "waive wrapper something" - // SEE BUG 658560: Fix identity problem with CrossOriginWrappers - // TODO: check that DOM can't be updated by the document itself and so overloaded value becomes wrong - // but I think such behavior is limited to primitive type - if ((typeof val == "function" || typeof val == "object") && name) { - overload[name] = val; - } - - return true; - }, - - enumerate: function() { - var result = []; - for each (let name in Object.keys(obj)) { - result.push(name); - }; - return result; - }, - - keys: function() { - return Object.keys(obj); - } - }; -}; - - -/* - * Wrap an object from the document to a proxy wrapper. - */ -function create(object) { - if ("wrappedJSObject" in object) - object = object.wrappedJSObject; - let xpcWrapper = XPCNativeWrapper(object); - // If we can't build an XPCNativeWrapper, it doesn't make sense to build - // a proxy. All proxy code is based on having such wrapper that store - // different JS attributes set. - // (we can't build XPCNativeWrapper when object is from the same - // principal/domain) - if (object === xpcWrapper) { - return object; - } - return getProxyForObject(xpcWrapper); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/data/test-content-symbiont.js b/tools/addon-sdk-1.4/packages/api-utils/data/test-content-symbiont.js deleted file mode 100644 index 808af37..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/data/test-content-symbiont.js +++ /dev/null @@ -1 +0,0 @@ -// test-content-symbiont diff --git a/tools/addon-sdk-1.4/packages/api-utils/data/test-httpd.txt b/tools/addon-sdk-1.4/packages/api-utils/data/test-httpd.txt deleted file mode 100644 index 7956d3a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/data/test-httpd.txt +++ /dev/null @@ -1 +0,0 @@ -This is the HTTPD test file. diff --git a/tools/addon-sdk-1.4/packages/api-utils/data/test-trusted-document.html b/tools/addon-sdk-1.4/packages/api-utils/data/test-trusted-document.html deleted file mode 100644 index 166009d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/data/test-trusted-document.html +++ /dev/null @@ -1,13 +0,0 @@ -<html>
-<head>
- <title>Worker test</title>
-</head>
-<body>
- <p id="paragraph">Lorem ipsum dolor sit amet.</p>
- <script>
- addon.port.on('addon-to-document', function (arg) {
- addon.port.emit('document-to-addon', arg);
- });
- </script>
-</body>
-</html>
diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/api-utils.md b/tools/addon-sdk-1.4/packages/api-utils/docs/api-utils.md deleted file mode 100644 index d87acdb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/api-utils.md +++ /dev/null @@ -1,153 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `api-utils` module provides some helpers useful to the SDK's high-level API -implementations. - -Introduction ------------- - -The SDK high-level API design guidelines make a number of recommendations. -This module implements some of those patterns so that your own implementations -don't need to reinvent them. - -For example, public constructors should be callable both with and without the -`new` keyword. Your module can implement this recommendation using the -`publicConstructor` function. - -Options objects or "dictionaries" are also common throughout the high-level -APIs. The guidelines recommend that public constructors should generally define -a single `options` parameter rather than defining many parameters. Since one of -the SDK's principles is to be friendly to developers, ideally all properties on -options dictionaries should be checked for correct type, and informative error -messages should be generated when clients make mistakes. With the -`validateOptions` function, your module can easily do so. - -And objects are sometimes iterable over a custom set of key/value pairs. -Such objects should have custom iterators that let consumers iterate keys, -values, or [key, value] pairs. The `addIterator` function makes it easy to do -so in a way that is consistent with the behavior of default iterators during -`for...in`, `for each...in`, and `for...in Iterator()` loops. - -<api name="publicConstructor"> -@function -Returns a function *C* that creates an instance of `privateConstructor`. *C* -may be called with or without the `new` keyword. - -The prototype of each instance returned from *C* is *C*.`prototype`, and -*C*.`prototype` is an object whose prototype is -`privateConstructor.prototype`. Instances returned from *C* are therefore -instances of both *C* and `privateConstructor`. - -Additionally, the constructor of each instance returned from *C* is *C*. - -Instances returned from *C* are automatically memory tracked using -`memory.track` under the bin name `privateConstructor.name`. - -**Example** - - function MyObject() {} - exports.MyObject = apiUtils.publicConstructor(MyObject); - -@returns {function} -A function that makes new instances of `privateConstructor`. - -@param privateConstructor {constructor} -</api> - -<api name="validateOptions"> -@function -A function to validate an options dictionary according to the specified -constraints. - -`map`, `is`, and `ok` are used in that order. - -The return value is an object whose keys are those keys in `requirements` that -are also in `options` and whose values are the corresponding return values of -`map` or the corresponding values in `options`. Note that any keys not shared -by both `requirements` and `options` are not in the returned object. - -**Examples** - -A typical use: - - var opts = { foo: 1337 }; - var requirements = { - foo: { - map: function (val) val.toString(), - is: ["string"], - ok: function (val) val.length > 0, - msg: "foo must be a non-empty string." - } - }; - var validatedOpts = apiUtils.validateOptions(opts, requirements); - // validatedOpts == { foo: "1337" } - -If the key `foo` is optional and doesn't need to be mapped: - - var opts = { foo: 1337 }; - var validatedOpts = apiUtils.validateOptions(opts, { foo: {} }); - // validatedOpts == { foo: 1337 } - - opts = {}; - validatedOpts = apiUtils.validateOptions(opts, { foo: {} }); - // validatedOpts == {} - -@returns {object} -A validated options dictionary given some requirements. If any of the -requirements are not met, an exception is thrown. - -@param options {object} -The options dictionary to validate. It's not modified. If it's null or -otherwise falsey, an empty object is assumed. - -@param requirements {object} -An object whose keys are the expected keys in `options`. Any key in -`options` that is not present in `requirements` is ignored. Each -value in `requirements` is itself an object describing the requirements -of its key. The keys of that object are the following, and each is optional: - -@prop [map] {function} -A function that's passed the value of the key in the `options`. `map`'s -return value is taken as the key's value in the final validated options, -`is`, and `ok`. If `map` throws an exception it is caught and discarded, -and the key's value is its value in `options`. - -@prop [is] {array} -An array containing the number of `typeof` type names. If the key's value is -none of these types it fails validation. Arrays and nulls are identified by -the special type names "array" and "null"; "object" will not match either. -No type coercion is done. - -@prop [ok] {function} -A function that is passed the key's value. If it returns false, the value -fails validation. - -@prop [msg] {string} -If the key's value fails validation, an exception is thrown. This string -will be used as its message. If undefined, a generic message is used, unless -`is` is defined, in which case the message will state that the value needs to -be one of the given types. -</api> - -<api name="addIterator"> -@function -Adds an iterator to the specified object that iterates keys, values, -or [key, value] pairs depending on how it is invoked, i.e.: - - for (var key in obj) { ... } // iterate keys - for each (var val in obj) { ... } // iterate values - for (var [key, val] in Iterator(obj)) { ... } // iterate pairs - -If your object only iterates either keys or values, you don't need this -function. Simply assign a generator function that iterates the keys/values -to your object's `__iterator__` property instead, f.e.: - - obj.__iterator__ = function () { for each (var i in items) yield i; } - -@param obj {object} -the object to which to add the iterator - -@param keysValsGen {function} -a generator function that yields [key, value] pairs -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/app-strings.md b/tools/addon-sdk-1.4/packages/api-utils/docs/app-strings.md deleted file mode 100644 index 3e4d358..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/app-strings.md +++ /dev/null @@ -1,61 +0,0 @@ -The `app-strings` module gives you access to the host application's localized -string bundles (`.properties` files). - -The module exports the `StringBundle` constructor function. To access a string -bundle, construct an instance of `StringBundle`, passing it the bundle's URL: - - var StringBundle = require("app-strings").StringBundle; - var bundle = StringBundle("chrome://browser/locale/browser.properties"); - -To get the value of a string, call the object's `get` method, passing it -the name of the string: - - var accessKey = bundle.get("contextMenuSearchText.accesskey"); - // "S" in the en-US locale - -To get the formatted value of a string that accepts arguments, call the object's -`get` method, passing it the name of the string and an array of arguments -with which to format the string: - - var searchText = bundle.get("contextMenuSearchText", - ["universe", "signs of intelligent life"]); - // 'Search universe for "signs of intelligent life"' in the en-US locale - -To get all strings in the bundle, iterate the object, which returns arrays -of the form [name, value]: - - for (var [name, value] in Iterator(bundle)) - console.log(name + " = " + value); - -Iteration ---------- - -<code>for (var name in bundle) { ... }</code> - -Iterate the names of strings in the bundle. - -<code>for each (var val in bundle) { ... }</code> - -Iterate the values of strings in the bundle. - -<code>for (var [name, value] in Iterator(bundle)) { ... }</code> - -Iterate the names and values of strings in the bundle. - - -<api name="StringBundle"> -@class -The `StringBundle` object represents a string bundle. -<api name="StringBundle"> -@constructor -Creates a StringBundle object that gives you access to a string bundle. -@param url {string} the URL of the string bundle -@returns {StringBundle} the string bundle -</api> -<api name="get"> -@method Get the value of the string with the given name. -@param [name] {string} the name of the string to get -@param [args] {array} (optional) strings that replace placeholders in the string -@returns {string} the value of the string -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/byte-streams.md b/tools/addon-sdk-1.4/packages/api-utils/docs/byte-streams.md deleted file mode 100644 index f7cffe8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/byte-streams.md +++ /dev/null @@ -1,64 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `byte-streams` module provides streams for reading and writing bytes. - -<api name="ByteReader"> -@class -<api name="ByteReader"> -@constructor - Creates a binary input stream that reads bytes from a backing stream. -@param inputStream {stream} - The backing stream, an <a href="http://mxr.mozilla.org/mozilla-central/ -source/xpcom/io/nsIInputStream.idl"><code>nsIInputStream</code></a>. -</api> -<api name="closed"> -@property {boolean} - True if the stream is closed. -</api> - -<api name="close"> -@method - Closes both the stream and its backing stream. If the stream is already - closed, an exception is thrown. -</api> - -<api name="read"> -@method - Reads a string from the stream. If the stream is closed, an exception is - thrown. -@param [numBytes] {number} - The number of bytes to read. If not given, the remainder of the entire stream - is read. -@returns {string} - A string containing the bytes read. If the stream is at the end, returns the - empty string. -</api> -</api> - -<api name="ByteWriter"> -@class -<api name="ByteWriter"> -@constructor - Creates a binary output stream that writes bytes to a backing stream. -@param outputStream {stream} - The backing stream, an <a href="http://mxr.mozilla.org/mozilla-central/ -source/xpcom/io/nsIOutputStream.idl"><code>nsIOutputStream</code></a>. -</api> -<api name="closed"> -@property {boolean} - True if the stream is closed. -</api> -<api name="close"> -@method - Closes both the stream and its backing stream. If the stream is already - closed, an exception is thrown. -</api> -<api name="write"> -@method - Writes a string to the stream. If the stream is closed, an exception is - thrown. -@param str {string} - The string to write. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/collection.md b/tools/addon-sdk-1.4/packages/api-utils/docs/collection.md deleted file mode 100644 index 796289a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/collection.md +++ /dev/null @@ -1,73 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `collection` module provides a simple list-like class and utilities for -using it. A collection is ordered, like an array, but its items are unique, -like a set. - -<api name="Collection"> -@class -A collection object provides for...in-loop iteration. Items are yielded in the -order they were added. For example, the following code... - - var collection = require("collection"); - var c = new collection.Collection(); - c.add(1); - c.add(2); - c.add(3); - for (item in c) - console.log(item); - -... would print this to the console: - -<pre> - 1 - 2 - 3 -</pre> - -Iteration proceeds over a copy of the collection made before iteration begins, -so it is safe to mutate the collection during iteration; doing so does not -affect the results of the iteration. - -<api name="Collection"> -@constructor -Creates a new collection. The collection is backed by an array. -@param [array] {array} -If *array* is given, it will be used as the backing array. This way the caller -can fully control the collection. Otherwise a new empty array will be used, and -no one but the collection will have access to it. -</api> -<api name="length"> -@property {number} -The number of items in the collection array. -</api> -<api name="add"> -@method -Adds a single item or an array of items to the collection. Any items already -contained in the collection are ignored. -@param itemOrItems {object} An item or array of items. -@returns {Collection} The Collection. -</api> -<api name="remove"> -@method -Removes a single item or an array of items from the collection. Any items not -contained in the collection are ignored. -@param itemOrItems {object} An item or array of items. -@returns {Collection} The Collection. -</api> -</api> - -<api name="addCollectionProperty"> -@function -Adds a collection property to the given object. Setting the property to a -scalar value empties the collection and adds the value. Setting it to an array -empties the collection and adds all the items in the array. -@param object {object} -The property will be defined on this object. -@param propName {string} -The name of the property. -@param [backingArray] {array} -If given, this will be used as the collection's backing array. -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/content.md b/tools/addon-sdk-1.4/packages/api-utils/docs/content.md deleted file mode 100644 index b258d02..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/content.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `content` module exports three different traits [Loader][], [Worker][] and -[Symbiont][]. None of this traits is intended to be used directly by programs. -Rather, they are intended to be used by other modules that provide high -level APIs to programs or libraries. - -[Loader]:packages/api-utils/docs/content/loader.html -[Worker]:packages/api-utils/docs/content/worker.html -[Symbiont]:packages/api-utils/docs/content/symbiont.html - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/content/loader.md b/tools/addon-sdk-1.4/packages/api-utils/docs/content/loader.md deleted file mode 100644 index 83b6276..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/content/loader.md +++ /dev/null @@ -1,88 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -Loader is base trait and it provides set of core properties and associated -validations. Trait is useful for all the compositions providing high level -APIs for creating JavaScript contexts that can access web content. - -Loader is composed from the -[EventEmitter](packages/api-utils/docs/events.html) trait, therefore -instances of Loader and their descendants expose all the public properties -exposed by EventEmitter along with additional public properties: - -Value changes on all of the above mentioned properties emit `propertyChange` -events on an instances. - -**Example:** - -The following code creates a wrapper on hidden frame that reloads a web page -in frame every time `contentURL` property is changed: - - var hiddenFrames = require("hidden-frame"); - var { Loader } = require("content"); - var PageLoader = Loader.compose({ - constructor: function PageLoader(options) { - options = options || {}; - if (options.contentURL) - this.contentURL = options.contentURL; - this.on('propertyChange', this._onChange = this._onChange.bind(this)); - let self = this; - hiddenFrames.add(hiddenFrames.HiddenFrame({ - onReady: function onReady() { - let frame = self._frame = this.element; - self._emit('propertyChange', { contentURL: self.contentURL }); - } - })); - }, - _onChange: function _onChange(e) { - if ('contentURL' in e) - this._frame.setAttribute('src', this._contentURL); - } - }); - -<api name="Loader"> -@class -<api name="contentScriptFile"> -@property {array} -The local file URLs of content scripts to load. Content scripts specified by -this property are loaded *before* those specified by the `contentScript` -property. -</api> - -<api name="contentScript"> -@property {array} -The texts of content scripts to load. Content scripts specified by this -property are loaded *after* those specified by the `contentScriptFile` property. -</api> - -<api name="contentScriptWhen"> -@property {string} -When to load the content scripts. This may take one of the following -values: - -* "start": load content scripts immediately after the document -element for the page is inserted into the DOM, but before the DOM content -itself has been loaded -* "ready": load content scripts once DOM content has been loaded, -corresponding to the -[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) -event -* "end": load content scripts once all the content (DOM, JS, CSS, -images) for the page has been loaded, at the time the -[window.onload event](https://developer.mozilla.org/en/DOM/window.onload) -fires - -</api> - -<api name="contentURL"> -@property {string} -The URL of the content loaded. -</api> - -<api name="allow"> -@property {object} -Permissions for the content, with the following keys: -@prop script {boolean} - Whether or not to execute script in the content. Defaults to true. -</api> -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/content/proxy.md b/tools/addon-sdk-1.4/packages/api-utils/docs/content/proxy.md deleted file mode 100644 index 012fbc7..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/content/proxy.md +++ /dev/null @@ -1,237 +0,0 @@ -<!-- contributed by Alexandre Poirot [apoirot@mozilla.com] --> - -Content scripts need access to the DOM of the pages they are attached to. -However, those pages should be considered to be hostile environments: we -have no control over any other scripts loaded by the web page that may be -executing in the same context. If the content scripts and scripts loaded -by the web page were to access the same DOM objects, there are two possible -security problems: - -First, a malicious page might redefine functions and properties of DOM -objects so they don't do what the add-on expects. For example, if a -content script calls `document.getElementById()` to retrieve a DOM -element, then a malicious page could redefine its behavior to return -something unexpected: - -<pre><code> -// If the web document contains the following script: -document.getElementById = function (str) { - // Overload indexOf method of all string instances - str.__proto__.indexOf = function () {return -1;}; - // Overload toString method of all object instances - str.__proto__.__proto__.toString = function () {return "evil";}; -}; -// After the following line, the content script will be compromised: -var node = document.getElementById("element"); -// Then your content script is totally out of control. -</code></pre> - -Second, changes the content script made to the DOM objects would be visible -to the page, leaking information to it. - -The general approach to fixing these problems is to wrap DOM objects in -[`XrayWrappers`](https://developer.mozilla.org/en/XPCNativeWrapper) -(also know as `XPCNativeWrapper`). This guarantees that: - -* when the content script accesses DOM properties and functions it gets the -original native version of them, ignoring any modifications made by the web -page -* changes to the DOM made by the content script are not visible to scripts -running in the page. - -However, `XrayWrapper` has some limitations and bugs, which break many -popular web frameworks. In particular, you can't: - -* define attributes like `onclick`: you have to use `addEventListener` syntax -* overload native methods on DOM objects, like this: -<pre><code> -proxy.addEventListener = function () {}; -</code></pre> -* access named elements using properties like `window[framename]` or -`document[formname]` -* use some other features that have bugs in the `XrayWrapper` -implementation, like `mozMatchesSelector` - -The `proxy` module uses `XrayWrapper` in combination with the -experimental -[Proxy API](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy) -to address both the security vulnerabilities of content scripts and the -limitations of `XrayWrapper`. - -<pre> - /--------------------\ /------------------------\ - | Web document | | Content script sandbox | - | http://mozilla.org | | data/worker.js | - | | require('content-proxy'). | | - | window >-----------|- create(window) -|-> window | - \--------------------/ \------------------------/ -</pre> - - -## The Big Picture ## - -The implementation defines two different kinds of proxy: - - 1. Content script proxies that wrap DOM objects that are exposed to - content scripts as described above. - 2. XrayWrapper proxies that wrap objects from content scripts before handing - them over to XrayWrapper functions. These proxies are internal - and are not exposed to content scripts or document content. - -<pre> - /--------------------\ /------------------------\ - | Web document | | Content script sandbox | - | http://mozilla.org | | data/worker.js | - | | /-------|-> myObject = {} | - | | /----------------v--\ | | - | | | XrayWrapper Proxy | | - document | - | | \---------v---------/ \----^-------------------/ - | | v | - | | /-------------\ /----------\ | - | - document >-------|->| XrayWrapper |<-| CS proxy |-/ - \--------------------/ \-------------/ \----------/ -</pre> - -Everything begins with a single call to the `create` function exported by the -content-proxy module: - - // Retrieve the unwrapped reference to the current web page window object - var win = gBrowser.contentDocument.defaultView.wrappedJSObject; - // Or in addon sdk style - var win = require("tab-browser").activeTab.linkedBrowser.contentWindow.wrappedJSObject; - // Now create a content script proxy for the window object - var windowProxy = require("api-utils/content/content-proxy").create(win); - - // We finally use this window object as sandbox prototype, - // so that all web page globals are accessible in CS too: - var contentScriptSandbox = new Cu.Sandbox(win, { - sandboxPrototype: windowProxy - }); - -Then all other proxies are created from this one. Attempts to access DOM -attributes of this proxy are trapped, and the proxy constructs and returns -content script proxies for those attributes: - - // For example, if you simply do this: - var document = window.document; - // accessing the `document` attribute will be trapped by the `window` content script - // proxy, and that proxy will that create another content script proxy for `document` - -So the main responsibility of the content script proxy implementation is to -ensure that we always return content script proxies to the content script. - -## Internal Implementation ## - -Each content script proxy keeps a reference to the `XrayWrapper` that enables -it to be sure of calling native DOM methods. - -There are two internal functions to convert between content script proxy -values and `XrayWrapper` values. - -1. __`wrap`__ takes an XrayWrapper value and wraps it in a content script -proxy if needed. - This method is called when: - * a content script accesses an attribute of a content script proxy. - * XrayWrapper code calls a callback function defined in the content -script, so that arguments passed into the function by the XrayWrapper are -converted into content script proxies. For example, if a content script -calls `addEventListener`, then the listener function will expect any arguments -to be content script proxies. -<br/><br/> -2. __`unwrap`__ takes an object coming from the content script context and: - * if the object is a content script proxy, unwraps it back to an -XrayWrapper reference - * if the object is not a content script proxy, wraps it in an XrayWrapper -proxy. -<br/><br/> -This means we can call a XrayWrapper method either with: - - * a raw XrayWrapper object. - - // The following line doesn't work if child is a content script proxy, - // it has to be a raw XrayWrapper reference - xrayWrapper.appendChild(child) - - * an XrayWrapper proxy when you pass a custom object from the content -script context. - - var myListener = { - handleEvent: function(event) { - // `event` should be a content script proxy - } - }; - // `myListener` has to be another kind of Proxy: XrayWrapper proxy, - // that aims to catch the call to `handleEvent` in order to wrap its - // arguments in a content script proxy. - xrayWrapper.addEventListener("click", myListener, false); - - -## Stack Traces ## - -The following code: - - function listener(event) { - - } - csProxy.addEventListener("message", listener, false); - -generates the following internal calls: - - -> CS Proxy:: get("addEventListener") - -> wrap(xrayWrapper.addEventListener) - -> NativeFunctionWrapper(xrayWrapper.addEventListener) - // NativeFunctionWrapper generates: - function ("message", listener, false) { - return xraywrapper.addEventListener("message", unwrap(listener), false); - } - -> unwrap(listener) - -> ContentScriptFunctionWrapper(listener) - // ContentScriptFunctionWrapper generates: - function (event) { - return listener(wrap(event)); - } - -<br> - - // First, create an object from content script context - var myListener = { - handleEvent: function (event) { - - } - }; - // Then, pass this object as an argument to a CS proxy method - window.addEventListener("message", myListener, false); - - // Generates the following internal calls: - -> CS Proxy:: get("addEventListener") - -> wrap(xrayWrapper.addEventListener) - -> NativeFunctionWrapper(xrayWrapper.addEventListener) - // Generate the following function: - function ("message", myListener, false) { - return xraywrapper.addEventListener("message", unwrap(myListener), false); - } - -> unwrap(myListener) - -> ContentScriptObjectWrapper(myListener) - // Generate an XrayWrapper proxy and give it to xrayWrapper method. - // Then when native code fires an event, the proxy will catch it: - -> XrayWrapper Proxy:: get("handleEvent") - -> unwrap(myListener.handleEvent) - -> ContentScriptFunctionWrapper(myListener.handleEvent) - // Generate following function: - function (event) { - return myListener.handleEvent(wrap(event)); - } - - -<api name="create"> -@function - Create a content script proxy. <br/> - Doesn't create a proxy if we are not able to create a XrayWrapper for - this object: for example, if the object comes from system principal. - -@param object {Object} - The object to proxify. - -@returns {Object} - A content script proxy that wraps `object`. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/content/symbiont.md b/tools/addon-sdk-1.4/packages/api-utils/docs/content/symbiont.md deleted file mode 100644 index 7519e52..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/content/symbiont.md +++ /dev/null @@ -1,136 +0,0 @@ -<!-- contributed by Myk Melez [myk@mozilla.org] --> -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - - -This module is not intended to be used directly by programs. Rather, it is -intended to be used by other modules that provide APIs to programs. - - -This module exports `Symbiont` trait that can be used for creating JavaScript -contexts that can access web content in host application frames (i.e. XUL -`<iframe>` and `<browser>` elements) and communicate with programs via -asynchronous JSON pipes. It is useful in the construction of APIs that -are compatible with the execution model codenamed "electrolysis" in which -programs run in separate processes from web content. - -Introduction ------------- - -`Symbiont` constructs a content symbiont for a given frame, it loads the -specified contentURL and scripts into it, and plumbs an asynchronous -JSON pipe between the content symbiont object and the content symbiont -context. If frame is not provided hidden frame will be created. - -Examples --------- - - var { Symbiont } = require('content'); - var Thing = Symbiont.resolve({ constructor: '_init' }).compose({ - constructor: function Thing(options) { - // `getMyFrame` returns the host application frame in which - // the page is loaded. - this._frame = getMyFrame(); - this._init(options) - } - }); - -See the [panel][] module for a real-world example of usage of this module. - -[panel]:packages/addon-kit/docs/panel.html - -Reference ---------- - -<api name="Symbiont"> -@class -Symbiont is composed from the [Worker][] trait, therefore instances -of Symbiont and their descendants expose all the public properties -exposed by [Worker][] along with additional public properties that -are listed below: - -[Worker]:packages/api-utils/docs/content/worker.html - -<api name="Symbiont"> -@constructor -Creates a content symbiont. -@param options {object} - Options for the constructor. Includes all the keys that -the [Worker](packages/api-utils/docs/content/worker.html) -constructor accepts and a few more: - - @prop [frame] {object} - The host application frame in which the page is loaded. - If frame is not provided hidden one will be created. - @prop [contentScriptWhen="end"] {string} - When to load the content scripts. This may take one of the following - values: - - * "start": load content scripts immediately after the document - element for the page is inserted into the DOM, but before the DOM content - itself has been loaded - * "ready": load content scripts once DOM content has been loaded, - corresponding to the - [DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) - event - * "end": load content scripts once all the content (DOM, JS, CSS, - images) for the page has been loaded, at the time the - [window.onload event](https://developer.mozilla.org/en/DOM/window.onload) - fires - - This property is optional and defaults to "end". - - @prop [allow] {object} - Permissions for the content, with the following keys: - @prop [script] {boolean} - Whether or not to execute script in the content. Defaults to true. - Optional. - Optional. -</api> - -<api name="contentScriptFile"> -@property {array} -The local file URLs of content scripts to load. Content scripts specified by -this property are loaded *before* those specified by the `contentScript` -property. -</api> - -<api name="contentScript"> -@property {array} -The texts of content scripts to load. Content scripts specified by this -property are loaded *after* those specified by the `contentScriptFile` property. -</api> - -<api name="contentScriptWhen"> -@property {string} -When to load the content scripts. This may have one of the following -values: - -* "start": load content scripts immediately after the document -element for the page is inserted into the DOM, but before the DOM content -itself has been loaded -* "ready": load content scripts once DOM content has been loaded, -corresponding to the -[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events) -event -* "end": load content scripts once all the content (DOM, JS, CSS, -images) for the page has been loaded, at the time the -[window.onload event](https://developer.mozilla.org/en/DOM/window.onload) -fires - -</api> - -<api name="contentURL"> -@property {string} -The URL of the content loaded. -</api> - -<api name="allow"> -@property {object} -Permissions for the content, with a single boolean key called `script` which -defaults to true and indicates whether or not to execute scripts in the -content. -</api> - -</api> - - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/content/worker.md b/tools/addon-sdk-1.4/packages/api-utils/docs/content/worker.md deleted file mode 100644 index ec9bb3a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/content/worker.md +++ /dev/null @@ -1,126 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -This module exports the `Worker` trait, which may be used to construct objects -implementing the [Worker][] interface defined by the W3C, with minor -differences. - -Content workers are message-passing facilities for communication between -[content scripts](dev-guide/addon-development/web-content.html) and the main -add-on code. - -It is important to note that unlike "web workers," these workers run in the -same process as web content and browser chrome, so code within workers can -block the UI. - -[Worker]:http://www.w3.org/TR/workers/#worker - -<api name="Worker"> -@class -Worker is composed from the [EventEmitter][] trait, therefore instances -of Worker and their descendants expose all the public properties -exposed by [EventEmitter][] along with additional public properties that -are listed below. - -**Example** - - var workers = require("content/worker"); - let worker = workers.Worker({ - window: require("window-utils").activeWindow, - contentScript: - "self.port.on('hello', function(name) { " + - " self.port.emit('response', window.location); " + - "});" - }); - worker.port.emit("hello", { name: "worker"}); - worker.port.on("response", function (location) { - console.log(location); - }); - -[EventEmitter]:packages/api-utils/docs/events.html - -<api name="Worker"> -@constructor -Creates a content worker. -@param options {object} -Options for the constructor, with the following keys: - @prop window {object} - The content window to create JavaScript sandbox for communication with. - @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. - Optional. - @prop [onMessage] {function} - Functions that will registered as a listener to a 'message' events. - @prop [onError] {function} - Functions that will registered as a listener to an 'error' events. -</api> - -<api name="port"> -@property {EventEmitter} -[EventEmitter](packages/api-utils/docs/events.html) object that allows you to: - -* send customized messages to the worker using the `port.emit` function -* receive events from the worker using the `port.on` function - -</api> - -<api name="postMessage"> -@method -Asynchronously emits `"message"` events in the enclosed worker, where content -script was loaded. -@param data {number,string,JSON} -The data to send. Must be stringifiable to JSON. -</api> - -<api name="destroy"> -@method -Destroy the worker by removing the content script from the page and removing -all registered listeners. A `detach` event is fired just before removal. -</api> - -<api name="url"> -@property {string} -The URL of the content. -</api> - -<api name="tab"> -@property {object} -If this worker is attached to a content document, returns the related -[tab](packages/addon-kit/docs/tabs.html). -</api> - -<api name="message"> -@event -This event allows the content worker to receive messages from its associated -content scripts. Calling the `self.postMessage()` function from a content -script will asynchronously emit the `message` event on the corresponding -worker. - -@argument {value} -The event listener is passed the message, which must be a -<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>. -</api> - -<api name="error"> -@event -This event allows the content worker to react to an uncaught runtime script -error that occurs in one of the content scripts. - -@argument {Error} -The event listener is passed a single argument which is an -[Error](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error) -object. -</api> - -<api name="detach"> -@event -This event is emitted when the document associated with this worker is unloaded -or the worker's `destroy()` method is called. -</api> - -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/cortex.md b/tools/addon-sdk-1.4/packages/api-utils/docs/cortex.md deleted file mode 100644 index 87a8eda..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/cortex.md +++ /dev/null @@ -1,156 +0,0 @@ - -## Property Encapsulation ## - -In JavaScript it is not possible to create properties that have limited or -controlled accessibility. It is possible to create non-enumerable and -non-writable properties, but still they can be discovered and accessed. -Usually so called "closure capturing" is used to encapsulate such properties -in lexical scope: - - function Foo() { - var _secret = 'secret'; - this.hello = function hello() { - return 'Hello ' + _secret; - } - } - -This provides desired result, but has side effect of degrading code readability, -especially with object-oriented programs. Another disadvantage with this pattern -is that there is no immediate solution for inheriting access to the privates -(illustrated by the following example): - - function Derived() { - this.hello = function hello() { - return _secret; - } - this.bye = function bye() { - return _secret; - } - } - Derived.prototype = Object.create(Foo.prototype); - -## Facade Objects ## - -Alternatively constructor can returned facade objects - proxies to the -instance's public properties: - - function Foo() { - var foo = Object.create(Foo.prototype); - return { - bar: foo.hello.bind(foo); - } - } - Foo.prototype._secret = 'secret'; - Foo.prototype.hello = function hello() { - return 'Hello ' + this._secret; - } - - function Derived() { - var derived = Object.create(Derived.prototype); - return { - bar: derived.hello.bind(derived); - bye: derived.bye.bind(derived); - } - } - Derived.prototype = Object.create(Foo.prototype); - Derived.prototype.bye = function bye() { - return 'Bye ' + this._secret; - }; - -While this solution solves given issue and provides proper encapsulation for -both own and inherited private properties, it does not addresses following: - - - Privates defined on the `prototype` can be compromised, since they are - accessible through the constructor (`Foo.prototype._secret`). - - Behavior of `instanceof` is broken, since `new Derived() instanceof Derived` - is going to evaluate to `false`. - -## Tamper Proofing with Property Descriptor Maps ## - -In ES5 new property descriptor maps were introduced, which can be used as a -building blocks for defining reusable peace of functionality. To some degree -they are similar to a `prototype` objects, and can be used so to define pieces -of functionality that is considered to be private (In contrast to `prototype` -they are not exposed by default). - - function Foo() { - var foo = Object.create(Foo.prototype, FooDescriptor); - var facade = Object.create(Foo.prototype); - facade.hello = foo.hello.bind(foo); - return facade; - } - Foo.prototype.hello = function hello() { - return 'Hello ' + this._secret; - } - var FooDescriptor = { - _secret: { value: 'secret' }; - } - - function Derived() { - var derived = Object.create(Derived.prototype, DerivedDescriptor); - var facade = Object.create(Derived.prototype); - facade.hello = derived.hello.bind(derived); - facade.bye = derived.bye.bind(derived); - return facade; - } - Derived.prototype = Object.create(Foo.prototype); - Derived.prototype.bye = function bye() { - return 'Bye ' + this._secret; - }; - DerivedDescriptor = {}; - - Object.keys(FooDescriptor).forEach(function(key) { - DerivedDescriptor[key] = FooDescriptor[key]; - }); - -## Cortex Objects ## - -Last approach solves all of the concerns, but adds complexity, verbosity -and decreases code readability. Combination of `Cortex`'s and `Trait`'s -will gracefully solve all these issues and keep code clean: - - var Cortex = require('cortex').Cortex; - var Trait = require('light-traits').Trait; - - var FooTrait = Trait({ - _secret: 'secret', - hello: function hello() { - return 'Hello ' + this._secret; - } - }); - function Foo() { - return Cortex(FooTrait.create(Foo.prototype)); - } - - var DerivedTrait = Trait.compose(FooTrait, Trait({ - bye: function bye() { - return 'Bye ' + this._secret; - } - })); - function Derived() { - var derived = DerivedTrait.create(Derived.prototype); - return Cortex(derived); - } - -Function `Cortex` takes any object and returns a proxy for its public -properties. By default properties are considered to be public if they don't -start with `"_"`, but default behavior can be overridden if needed, by passing -array of public property names as a second argument. - -## Gotchas ## - -`Cortex` is just a utility function to create a proxy object, and it does not -solve the `prototype`-related issues highlighted earlier, but since traits make -use of property descriptor maps instead of `prototype`s, there aren't any -issues with using `Cortex` to wrap objects created from traits. - -If you want to use `Cortex` with an object that uses a `prototype` chain, -however, you should either make sure you don't have any private properties -in the prototype chain or pass the optional third `prototype` argument. - -In the latter case, the returned proxy will inherit from the given prototype, -and the `prototype` chain of the wrapped object will be inaccessible. -However, note that the behavior of the `instanceof` operator will vary, -as `proxy instanceof Constructor` will return false even if the Constructor -function's prototype is in the wrapped object's prototype chain. - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/cuddlefish.md b/tools/addon-sdk-1.4/packages/api-utils/docs/cuddlefish.md deleted file mode 100644 index 6177c53..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/cuddlefish.md +++ /dev/null @@ -1,5 +0,0 @@ -`cuddlefish` is the name of the SDK's module loader. It builds on -`securable-module` to provide many SDK-specific globals such as `console` -and `memory`. - -This module still needs to be documented. diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/environment.md b/tools/addon-sdk-1.4/packages/api-utils/docs/environment.md deleted file mode 100644 index 5697a4f..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/environment.md +++ /dev/null @@ -1,39 +0,0 @@ -Module provides API to access, set and unset environment variables via exported -`env` object. - - var { env } = require('api-utils/environment'); - -You can get the value of an environment variable, by accessing property that -has name of desired variable: - - var PATH = env.PATH; - -You can check existence of an environment variable by checking if property with -such variable name exists: - - console.log('PATH' in env); // true - console.log('FOO' in env); // false - -You can set value of an environment variable by setting a property: - - env.FOO = 'foo'; - env.PATH += ':/my/path/' - -You can unset environment variable by deleting a property: - - delete env.FOO; - -## Limitations ## - -There is no way to enumerate existing environment variables, also `env` -won't have any enumerable properties: - - console.log(Object.keys(env)); // [] - -Environment variable will be unset, show up as non-existing if it's set -to `null`, `undefined` or `''`. - - env.FOO = null; - console.log('FOO' in env); // false - env.BAR = ''; - console.log(env.BAR); // undefined diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/errors.md b/tools/addon-sdk-1.4/packages/api-utils/docs/errors.md deleted file mode 100644 index 3ce5b19..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/errors.md +++ /dev/null @@ -1,38 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> - -The `errors` module provides helpers for safely invoking user callbacks. - -<api name="catchAndLog"> -@function - Wraps a callback in a function that when invoked will catch and log any - exception thrown by the callback. -@param callback {function} - The callback to wrap. -@param [defaultResponse] {value} - This value will be returned by the wrapper if `callback` throws an exception. - If not given, `undefined` is used. -@param [logException] {function} - When `callback` throws an exception, it will be passed to this function. If - not given, the exception is logged using `console.exception()`. -@returns {function} - A function that will invoke `callback` when called. The return value of this - function is the return value of `callback` unless `callback` throws an - exception. In that case, `defaultResponse` is returned or `undefined` if - `defaultResponse` is not given. -</api> - -<api name="catchAndLogProps"> -@function - Replaces methods of an object with wrapped versions of those methods returned - by `catchAndLog()`. -@param object {object} - The object whose methods to replace. -@param props {string,array} - The names of the methods of `object` to replace, either a string for a single - method or an array of strings for multiple methods. -@param [defaultResponse] {value} - This value will be returned by any wrapper whose wrapped method throws an - exception. If not given, `undefined` is used. -@param [logException] {function} - See `catchAndLog()`. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/es5.md b/tools/addon-sdk-1.4/packages/api-utils/docs/es5.md deleted file mode 100644 index 0906b0d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/es5.md +++ /dev/null @@ -1,52 +0,0 @@ -The `es5` module provides shim layer to a versions of Firefox that do not yet -implement certain EcmaScript 5 features. - -For more information on EcmaScript 5: - -* The new APIs are described in the official [ES5 specification][]. -* A good [introduction][] to the new APIs by John Resig. -* A Google tech talk on [changes to JavaScript][]. - -**There is no need to `require` this module** since it gets preloaded into -all sandboxes automatically. - -Usage of new ES5 API's is encouraged, but since not everything can be -provided to all the versions of firefox, there are few things to be aware of: - -`Object.freeze`, `Object.seal`, `Object.preventExtensions` does not really -prevents any mutations. One thing it guarantees though, `Object.isFrozen`, -`Object.isSealed`, `Object.isExtensible` checks will behave as defined in -specification. - -`Object.defineProperty` is only partially compliant with the specification: - -- Non configurable properties will be created as configurable ones. - -- Instead of non-writable properties getters and setters will be defined, -but `Object.getOwnPropertyDescriptor` will still behave as expected -(will return property descriptor for non-writable property not a getter) - -- Defining properties using ES5 functions will break your - [custom iterators][] if you have any. Think twice before employing - custom iterators, because in most cases you can just make properties - non enumerable. If you really need to have a custom iterator, add it - after running ES5 functions and don't ignore previous iterators. - For example: - - let object = Object.create({}, { - myField: { value: 6 } - }); - object.__iterator__ = (function(original) { - return function myIterator() { - this.__iterator__ = original; - for (let key in this) { - // your logic here - } - this.__iterator__ = myIterator; - } - })(object.__iterator__); - -[custom iterators]:https://developer.mozilla.org/en/New_in_JavaScript_1.7#Iterators -[ES5 specification]:http://www.ecmascript.org/docs/tc39-2009-043.pdf -[introduction]:http://ejohn.org/blog/ecmascript-5-objects-and-properties/ -[changes to JavaScript]:http://www.youtube.com/watch?v=Kq4FpMe6cRs diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/events.md b/tools/addon-sdk-1.4/packages/api-utils/docs/events.md deleted file mode 100644 index cb74c77..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/events.md +++ /dev/null @@ -1,74 +0,0 @@ -The `events` module provides base API for emitting events. - -This module is not intended to be used directly by programs. Rather, it is -intended to be used by other modules that provide APIs to programs. - -<api name="EventEmitter"> -@class -The EventEmitter is the base building block for all compositions that -would need to broadcast data to multiple consumers. - -Please note that `EventEmitter` does not expose either a method for emitting -events or a list of available event listeners as its public API. Obviously -both are accessible but from the instance itself through the private API. -<api name="EventEmitter"> -@constructor -Creates an EventEmitter object. -</api> - -<api name="on"> -@method -Registers an event `listener` that will be called when events of -specified `type` are emitted. - -If the `listener` is already registered for this `type`, a call to this -method has no effect. - -If the event listener is being registered while an event is being processed, -the event listener is not called during the current emit. - -**Example:** - - // worker is instance of EventEmitter - worker.on('message', function (data) { - console.log('data received: ' + data) - }); - -@param type {String} - The type of the event. -@param listener {Function} - The listener function that processes the event. -</api> - -<api name="once"> -@method -Registers an event `listener` that will only be called once, the next time -an event of the specified `type` is emitted. - -If the event listener is registered while an event of the specified `type` -is being emitted, the event listener will not be called during the current -emit. - -@param type {String} - The type of the event. -@param listener {Function} - The listener function that processes the event. -</api> - -<api name="removeListener"> -@method -Unregisters an event `listener` for the specified event `type`. - -If the `listener` is not registered for this `type`, a call to this -method has no effect. - -If an event listener is removed while an event is being processed, it is -still triggered by the current emit. After it is removed, the event listener -is never invoked again (unless registered again for future processing). - -@param type {String} - The type of the event. -@param listener {Function} - The listener function that processes the event. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/file.md b/tools/addon-sdk-1.4/packages/api-utils/docs/file.md deleted file mode 100644 index 3dd4fb2..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/file.md +++ /dev/null @@ -1,147 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `file` module provides access to the local filesystem. - - -Paths ------ - -Path specifications in this API are platform-specific. This means that on -Windows paths are specified using the backslash path separator (`\`), and on -Unix-like systems like Linux and OS X paths are specified using the forward -slash path separator (`/`). - -If your add-on uses literal Windows-style path specifications with this API, -your add-on likely won't work when users run it on Unix-like systems. Likewise, -if your add-on uses literal Unix-style path specifications, it won't work for -users on Windows. - -To ensure your add-on works for everyone, generate paths using the -[`join`](packages/api-utils/docs/file.html#join(...)) function. Unfortunately -this API does not currently provide a way to obtain an absolute base path which -you could then use with `join`. For now, you need to -[`require("chrome")`](dev-guide/module-development/chrome.html) and use the -XPCOM directory service as described at -[MDN](https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FO#Getting_special_files). - -Note that if you do decide to hardcode Windows-style paths, be sure to escape -backslashes in strings. For example, to specify the file at `C:\Users\Myk`, you -need to use the string `"C:\\Users\\Myk"`, not `"C:\Users\Myk"`. You can read -more about escaping characters in strings at -[MDN](https://developer.mozilla.org/en/JavaScript/Guide/Values,_Variables,_and_Literals#Escaping_Characters). - - -<api name="basename"> -@function - Returns the last component of the given path. For example, - `basename("/foo/bar/baz")` returns `"baz"`. If the path has no components, - the empty string is returned. -@param path {string} - The path of a file. -@returns {string} - The last component of the given path. -</api> - -<api name="dirname"> -@function - Returns the path of the directory containing the given file. If the file is - at the top of the volume, the empty string is returned. -@param path {string} - The path of a file. -@returns {string} - The path of the directory containing the file. -</api> - -<api name="exists"> -@function - Returns true if a file exists at the given path and false otherwise. -@param path {string} - The path of a file. -@returns {boolean} - True if the file exists and false otherwise. -</api> - -<api name="join"> -@function - Takes a variable number of strings, joins them on the file system's path - separator, and returns the result. -@param ... {strings} - A variable number of strings to join. The first string must be an absolute - path. -@returns {string} - A single string formed by joining the strings on the file system's path - separator. -</api> - -<api name="list"> -@function - Returns an array of file names in the given directory. -@param path {string} - The path of the directory. -@returns {array} - An array of file names. Each is a basename, not a full path. -</api> - -<api name="mkpath"> -@function - Makes a new directory named by the given path. Any subdirectories that do not - exist are also created. `mkpath` can be called multiple times on the same - path. -@param path {string} - The path to create. -</api> - -<api name="open"> -@function - Returns a stream providing access to the contents of a file. -@param path {string} - The path of the file to open. -@param [mode] {string} - An optional string, each character of which describes a characteristic of the - returned stream. If the string contains `"r"`, the file is opened in - read-only mode. `"w"` opens the file in write-only mode. `"b"` opens the - file in binary mode. If `"b"` is not present, the file is opened in text - mode, and its contents are assumed to be UTF-8. If *`mode`* is not given, - `"r"` is assumed, and the file is opened in read-only text mode. -@returns {stream} - If the file is opened in text read-only `mode`, a `TextReader` is returned, - and if text write-only mode, a `TextWriter` is returned. See - [`text-streams`](packages/api-utils/docs/text-streams.html) for information on - these text stream objects. If the file is opened in binary read-only `mode`, - a `ByteReader` is returned, and if binary write-only mode, a `ByteWriter` is - returned. See - [`byte-streams`](packages/api-utils/docs/byte-streams.html) for more - information on these byte stream objects. Opened files should always be - closed after use by calling `close` on the returned stream. -</api> - -<api name="read"> -@function - Opens a file and returns a string containing its entire contents. -@param path {string} - The path of the file to read. -@param [mode] {string} - An optional string, each character of which describes a characteristic of the - returned stream. If the string contains `"b"`, the contents will be returned - in binary mode. If `"b"` is not present or `mode` is not given, the file - contents will be returned in text mode. -@returns {string} - A string containing the file's entire contents. -</api> - -<api name="remove"> -@function - Removes a file from the file system. To remove directories, use `rmdir`. -@param path {string} - The path of the file to remove. -</api> - -<api name="rmdir"> -@function - Removes a directory from the file system. If the directory is not empty, an - exception is thrown. -@param path {string} - The path of the directory to remove. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/hidden-frame.md b/tools/addon-sdk-1.4/packages/api-utils/docs/hidden-frame.md deleted file mode 100644 index 47cd23b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/hidden-frame.md +++ /dev/null @@ -1,79 +0,0 @@ -<!-- contributed by Myk Melez [myk@mozilla.org] --> - -The `hidden-frame` module creates host application frames (i.e. XUL `<iframe>` -elements) that are not displayed to the user. It is useful in the construction -of APIs that load web content not intended to be directly seen or accessed -by users, like `page-worker`. It is also useful in the construction of APIs -that load web content for intermittent display, such as `panel`. - -This module is not intended to be used directly by programs. Rather, it is -intended to be used by other modules that provide APIs to programs. - -Introduction ------------- - -The module exports a constructor function, `HiddenFrame`, and two other -functions, `add` and `remove`. - -`HiddenFrame` constructs a new hidden frame. `add` registers a hidden frame, -preparing it to load content. `remove` unregisters a frame, unloading any -content that was loaded in it. - -Examples --------- - -The following code creates a hidden frame, loads a web page into it, and then -logs its title: - - var hiddenFrames = require("hidden-frame"); - let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({ - onReady: function() { - this.element.contentWindow.location = "http://www.mozilla.org/"; - let self = this; - this.element.addEventListener("DOMContentLoaded", function() { - console.log(self.element.contentDocument.title); - }, true, true); - } - })); - -See the `panel` module for a real-world example of usage of this module. - -Reference ---------- -<api name="HiddenFrame"> -@class -`HiddenFrame` objects represent hidden frames. -<api name="HiddenFrame"> -@constructor -Creates a hidden frame. -@param options {object} - Options for the frame, with the following keys: - @prop onReady {function,array} - Functions to call when the frame is ready to load content. You must specify - an `onReady` callback and refrain from using the hidden frame until - the callback gets called, because hidden frames are not always ready to load - content the moment they are added. -</api> - -<api name="add"> -@function -Register a hidden frame, preparing it to load content. -@param hiddenFrame {HiddenFrame} the frame to add -</api> - -<api name="remove"> -@function -Unregister a hidden frame, unloading any content that was loaded in it. -@param hiddenFrame {HiddenFrame} the frame to remove -</api> - -<api name="element"> -@property {DOMElement} -The host application frame in which the page is loaded. -</api> - -<api name="onReady"> -@property {array} -Functions to call when the frame is ready to load content. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/httpd.md b/tools/addon-sdk-1.4/packages/api-utils/docs/httpd.md deleted file mode 100644 index 53964a3..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/httpd.md +++ /dev/null @@ -1,27 +0,0 @@ -Provides an HTTP server written in JavaScript for the Mozilla platform, which -can be used in unit tests. - -The most basic usage is: - - var {startServerAsync} = require("httpd"); - var srv = startServerAsync(port, basePath); - require("unload").when(function cleanup() { - srv.stop(function() { // you should continue execution from this point. - }) - }); - -This starts a server in background (assuming you're running this code in an -application that has an event loop, such as Firefox). The server listens at -http://localhost:port/ and serves files from the specified directory. You -can serve static content or use SJS scripts, as described in documentation -on developer.mozilla.org. - -You can also use `nsHttpServer` to start the server manually: - - var {nsHttpServer} = require("httpd"); - var srv = new nsHttpServer(); - // further documentation on developer.mozilla.org - -See -[HTTP server for unit tests](https://developer.mozilla.org/En/HTTP_server_for_unit_tests) -for general information. diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/light-traits.md b/tools/addon-sdk-1.4/packages/api-utils/docs/light-traits.md deleted file mode 100644 index 1257c2a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/light-traits.md +++ /dev/null @@ -1,291 +0,0 @@ - -[Traits](http://en.wikipedia.org/wiki/Trait_%28computer_science%29) are a simple -mechanism for structuring object-oriented programs. They represent reusable and -composable building blocks of functionality that factor out the common -attributes and behavior of objects. - -They are a more robust alternative to -[mixins](http://en.wikipedia.org/wiki/Mixins) and -[multiple inheritance](http://en.wikipedia.org/wiki/Multiple_inheritance), -because name clashes must be explicitly resolved and composition is commutative -and associative (i.e. the order of traits in a composition is irrelevant). - -Use traits to share functionality between similar objects without duplicating -code or creating complex inheritance chains. - -## Trait Creation ## - -To create a trait, call the `Trait` constructor function exported by this -module, passing it a JavaScript object that specifies the properties of the -trait. - - let Trait = require('light-traits').Trait; - let t = Trait({ - foo: "foo", - bar: function bar() { - return "Hi!" - }, - baz: Trait.required - }); - -Traits can both provide and require properties. A *provided* property is a -property for which the trait itself provides a value. A *required* property is a -property that the trait needs in order to function correctly but for which -it doesn't provide a value. - -Required properties must be provided by another trait or by an object with a -trait. Creation of an object with a trait will fail if required properties are -not provided. Specify a required property by setting the value of the property -to `Trait.required`. - -## Object Creation ## - -Create objects with a single trait by calling the trait's `create` method. The -method takes a single argument, the object to serve as the new object's -prototype. If no prototype is specified, the new object's prototype will be -`Object.prototype`. - - let t = Trait({ - foo: 'foo', - bar: 2 - }); - let foo1 = t.create(); - let foo2 = t.create({ name: 'Super' }); - -## Trait Composition ## - -Traits are designed to be composed with other traits to create objects with the -properties of multiple traits. To compose an object with multiple traits, you -first create a composite trait and then use it to create the object. A composite -trait is a trait that contains all of the properties of the traits from which it -is composed. In the following example, MagnitudeTrait is a composite trait. - - let EqualityTrait = Trait({ - equal: Trait.required, - notEqual: function notEqual(x) { - return !this.equal(x) - } - }); - - let ComparisonTrait = Trait({ - less: Trait.required, - notEqual: Trait.required, - greater: function greater(x) { - return !this.less(x) && this.notEqual(x) - } - }); - - let MagnitudeTrait = Trait.compose(EqualityTrait, ComparisonTrait); - -<?xml version="1.0"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-11 121 490 190" width="490px" height="190px"> - <defs> - <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="SharpArrow_Marker" viewBox="-4 -4 10 8" markerWidth="10" markerHeight="8" color="black"> - <g> - <path d="M 5 0 L -3 -3 L 0 0 L 0 0 L -3 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1px"/> - </g> - </marker> - </defs> - <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"> - <g> - <rect x="9" y="165.33334" width="141" height="14"/> - <rect x="9" y="165.33334" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 165.33334)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="47.373047">notEqual</tspan> - </text> - <rect x="9" y="151.33334" width="141" height="14"/> - <rect x="9" y="151.33334" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 151.33334)" fill="red"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="29.361328">equal</tspan> - </text> - <rect x="9" y="137.33334" width="141" height="14"/> - <rect x="9" y="137.33334" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 137.33334)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="bold" x="38.49707" y="11" textLength="54.00586">EqualityTrait</tspan> - </text> - <rect x="9" y="273" width="141" height="14"/> - <rect x="9" y="273" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 273)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="38.021484">greater</tspan> - </text> - <rect x="9" y="259" width="141" height="14"/> - <rect x="9" y="259" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 259)" fill="red"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="47.373047">notEqual</tspan> - </text> - <rect x="9" y="245" width="141" height="14"/> - <rect x="9" y="245" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 245)" fill="red"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="21.339844">less</tspan> - </text> - <rect x="9" y="231" width="141" height="14"/> - <rect x="9" y="231" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(14 231)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".15332031" y="11" textLength="112.67578">ComparisonTrait</tspan> - </text> - <rect x="317.75" y="235.5" width="141" height="14"/> - <rect x="317.75" y="235.5" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(322.75 235.5)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="38.021484">greater</tspan> - </text> - <rect x="317.75" y="221.5" width="141" height="14"/> - <rect x="317.75" y="221.5" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(322.75 221.5)" fill="red"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="21.339844">less</tspan> - </text> - <rect x="317.75" y="207.5" width="141" height="14"/> - <rect x="317.75" y="207.5" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(322.75 207.5)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="47.373047">notEqual</tspan> - </text> - <rect x="317.75" y="193.5" width="141" height="14"/> - <rect x="317.75" y="193.5" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(322.75 193.5)" fill="red"> - <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="29.361328">equal</tspan> - </text> - <rect x="317.75" y="179.5" width="141" height="14"/> - <rect x="317.75" y="179.5" width="141" height="14" stroke="black" stroke-width="1px"/> - <text transform="translate(322.75 179.5)" fill="black"> - <tspan font-family="Helvetica" font-size="12" font-weight="bold" x="31.83789" y="11" textLength="67.32422">MagnitudeTrait</tspan> - </text> - <path d="M 150 248.83887 L 158.89999 248.83887 L 235.9 248.83887 L 235.9 224.66113 L 308.85 224.66113 L 310.85 224.66113" marker-end="url(#SharpArrow_Marker)" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1px"/> - <path d="M 150 171.15845 L 158.89999 171.15845 L 233.9 171.15845 L 233.9 201.6749 L 308.85 201.6749 L 310.85 201.6749" marker-end="url(#SharpArrow_Marker)" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1px"/> - </g> - </g> -</svg> - -## Trait Resolution ## - -Composite traits have conflicts when two of the traits in the composition -provide properties with the same name but different values (when compared using -the `===` strict equality operator). In the following example, `TC` has a -conflict because `T1` and `T2` both define a `foo` property: - - let T1 = Trait({ - foo: function () { - // do something - }, - bar: 'bar', - t1: 1 - }); - - let T2 = Trait({ - foo: function() { - // do something else - }, - bar: 'bar', - t2: 2 - }); - - let TC = Trait.compose(T1, T2); - -Attempting to create an object from a composite trait with conflicts throws a -`remaining conflicting property` exception. To create objects from such traits, -you must resolve the conflict. - -You do so by excluding or renaming the conflicting property of one of the -traits. Excluding a property removes it from the composition, so the composition -only acquires the property from the other trait. Renaming a property gives it a -new, non-conflicting name at which it can be accessed. - -In both cases, you call the `resolve` method on the trait whose property you -want to exclude or rename, passing it an object. Each key in the object is the -name of a conflicting property; each value is either `null` to exclude the -property or a string representing the new name of the property. - -For example, the conflict in the previous example could be resolved by excluding -the `foo` property of the second trait. - - let TC = Trait(T1, T2.resolve({ foo: null })); - -It could also be resolved by renaming the `foo` property of the first trait to -`foo2`: - - let TC = Trait(T1.resolve({ foo: "foo2" }), T2); - -When you resolve a conflict, the same-named property of the other trait (the one -that wasn't excluded or renamed) remains available in the composition under its -original name. - -## Constructor Functions ## - -When your code is going to create more than one object with traits, you may want -to define a constructor function to create them. To do so, create a composite -trait representing the traits the created objects should have, then define a -constructor function that creates objects with that trait and whose prototype is -the prototype of the constructor: - - let PointTrait = Trait.compose(T1, T2, T3); - function Point(options) { - let point = PointTrait.create(Point.prototype); - return point; - } - -## Property Descriptor Maps ## - -Traits are designed to work with the new object manipulation APIs defined in -[ECMAScript-262, Edition -5](http://www.ecma-international.org/publications/standards/Ecma-262.htm) (ES5). -Traits are also property descriptor maps that inherit from `Trait.prototype` to -expose methods for creating objects and resolving conflicts. - -The following trait definition: - - let FooTrait = Trait({ - foo: "foo", - bar: function bar() { - return "Hi!" - }, - baz: Trait.required - }); - -Creates the following property descriptor map: - - { - foo: { - value: 'foo', - enumerable: true, - configurable: true, - writable: true - }, - - bar: { - value: function b() { - return 'bar' - }, - enumerable: true, - configurable: true, - writable: true - }, - - baz: { - get baz() { throw new Error('Missing required property: `baz`') } - set baz() { throw new Error('Missing required property: `baz`') } - }, - - __proto__: Trait.prototype - } - -Since Traits are also property descriptor maps, they can be used with built-in -`Object.*` methods that accept such maps: - - Object.create(proto, FooTrait); - Object.defineProperties(myObject, FooTrait); - -Note that conflicting and required properties won't cause exceptions to be -thrown when traits are used with the `Object.*` methods, since those methods are -not aware of those constraints. However, such exceptions will be thrown when the -property with the conflict or the required but missing property is accessed. - -Property descriptor maps can also be used in compositions. This may be useful -for defining non-enumerable properties, for example: - - let TC = Trait.compose( - Trait({ foo: 'foo' }), - { bar: { value: 'bar', enumerable: false } } - ); - -_When using property descriptor maps in this way, make sure the map is not the -only argument to `Trait.compose`, since in that case it will be interpreted as -an object literal with properties to be defined._ - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/list.md b/tools/addon-sdk-1.4/packages/api-utils/docs/list.md deleted file mode 100644 index 8e1a522..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/list.md +++ /dev/null @@ -1,94 +0,0 @@ -<!-- contributed by Irakli Gozalishvili [gozala@mozilla.com] --> - -The `"list"` module provides base building blocks for composing lists. - -<api name="Iterable"> -@class -Base trait that can be used to compose traits with non-standard -enumeration behaviors. - -This trait is supposed to be used as part of a composition, since it only -provides custom enumeration behavior to a composed object. -It defines one required `_keyValueMap` property, that is used as a hash of -"key-values" to iterate on during enumeration. - -<api name="Iterable"> -@constructor -Constructs an `Iterable` object. -</api> - -<api name="_keyValueMap"> -@property {Object} -Hash map of key-values to iterate over. _Required_ property: that is, the -property must be supplied by objects that compose this trait. -_Note: That this property can be a getter if you need dynamic behavior._ -</api> - -</api> - -<api name="List"> -@class -An ordered collection (also known as a sequence) disallowing duplicate -elements. List is composed out of `Iterable`, therefore it provides custom -enumeration behavior that is similar to array (enumerates only on the -elements of the list). - -List is a base trait and is meant to be part of a -composition, since all of its API is private except for the `length` property. - -**Examples:** - - var MyList = List.compose({ - add: function add(item1, item2, /*item3...*/) { - Array.slice(arguments).forEach(this._add.bind(this)); - }, - remove: function remove(item1, item2, /*item3...*/) { - Array.slice(arguments).forEach(this._remove.bind(this)); - } - }); - MyList('foo', 'bar', 'baz').length == 3; // true - new MyList('new', 'keyword').length == 2; // true - MyList.apply(null, [1, 2, 3]).length == 3; // true - let list = MyList(); - list.length == 0; // true - list.add(1, 2, 3) == 3; // true - -<api name="List"> -@constructor -Constructor can takes any number of elements and creates an instance of -`List` populated with the specified elements. -@param [element1] {Object|String|Number} -@param [element2] {Object|String|Number} -@param [...] {Object|String|Number} -</api> - -<api name="length"> -@property {Number} -Number of elements in this list. -</api> - -<api name="_has"> -@method -@param element {Object|Number|String} -Returns `true` if this list contains the specified `element`. -</api> -<api name="_add"> -@method -@param element {Object|Number|String} -Appends the specified `element` to the end of this list, if it doesn't -contain it. - -_Ignores the call if `element` is already contained._ -</api> -<api name="_remove"> -@method -@param element {Object|Number|String} -Removes specified `element` from this list, if it contains it. - -_Ignores the call if `element` is not contained._ -</api> -<api name="_clear"> -@method -Removes all of the elements from this list. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/match-pattern.md b/tools/addon-sdk-1.4/packages/api-utils/docs/match-pattern.md deleted file mode 100644 index 125f89e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/match-pattern.md +++ /dev/null @@ -1,242 +0,0 @@ -The `match-pattern` module can be used to test strings containing URLs -against simple patterns. - -## Specifying Patterns ## - -There are three ways you can specify patterns: - -* as an exact match string -* using a wildcard in a string -* using a regular expression - -### Exact Matches ### - -**A URL** matches only that URL. The URL must start with a scheme, end with a -slash, and contain no wildcards. - -<table> - - <colgroup> - <col width="30%"> - <col width="35%"> - <col width="35%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - <th>Example non-matching URLs</th> - </tr> - - <tr> - <td><code>"http://example.com/"</code></td> - <td><code>http://example.com/</code></td> - <td><code>http://example.com</code><br> - <code>http://example.com/foo</code><br> - <code>https://example.com/</code><br> - <code>http://foo.example.com/</code></td> - </tr> - -</table> - -### Wildcards ### - -**A single asterisk** matches any URL with an `http`, `https`, or `ftp` -scheme. For other schemes like `file`, use a scheme followed by an -asterisk, as below. - -<table> - - <colgroup> - <col width="30%"> - <col width="35%"> - <col width="35%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - <th>Example non-matching URLs</th> - </tr> - - <tr> - <td><code>"*"</code></td> - <td><code>http://example.com/</code><br> - <code>https://example.com/</code><br> - <code>ftp://example.com/</code><br> - <code>http://bar.com/foo.js</code><br> - <code>http://foo.com/</code></td> - <td><code>file://example.js</code></td> - </tr> - -</table> - -**A domain name prefixed with an asterisk and dot** matches any URL of that -domain or a subdomain, using any of `http`, `https`, `ftp`. - -<table> - - <colgroup> - <col width="30%"> - <col width="35%"> - <col width="35%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - <th>Example non-matching URLs</th> - </tr> - - <tr> - <td><code>"*.example.com"</code></td> - <td><code>http://example.com/</code><br> - <code>http://foo.example.com/</code><br> - <code>https://example.com/</code><br> - <code>http://example.com/foo</code><br> - <code>ftp://foo.example.com/</code></td> - <td><code>ldap://example.com</code><br> - <code>http://example.foo.com/</code></td> - </tr> - -</table> - -**A URL followed by an asterisk** matches that URL and any URL prefixed with -the pattern. - -<table> - - <colgroup> - <col width="30%"> - <col width="35%"> - <col width="35%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - <th>Example non-matching URLs</th> - </tr> - - <tr> - <td><code>"https://foo.com/*"</code></td> - <td><code>https://foo.com/</code><br> - <code>https://foo.com/bar</code></td> - <td><code>http://foo.com/</code><br> - <code>https://foo.com</code><br> - <code>https://bar.foo.com/</code></td> - </tr> - -</table> - -**A scheme followed by an asterisk** matches all URLs with that scheme. To -match local files, use `file://*`. - -<table> - - <colgroup> - <col width="30%"> - <col width="70%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - </tr> - - <tr> - <td><code>"file://*"</code></td> - <td><code>file://C:/file.html</code><br> - <code>file:///home/file.png</code></td> - </tr> - -</table> - -### Regular Expressions ### - -You can specify patterns using a -[regular expression](https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions): - - var { MatchPattern } = require("match-pattern"); - var pattern = new MatchPattern(/.*example.*/); - -The regular expression is subject to restrictions based on those applied to the -[HTML5 pattern attribute](http://dev.w3.org/html5/spec/common-input-element-attributes.html#attr-input-pattern). In particular: - -* The pattern must match the entire value, not just any subset. For example, the -pattern `/moz.*/` will not match the URL `http://mozilla.org`. - -* The expression is compiled with the `global`, `ignoreCase`, and `multiline` flags - disabled. The `MatchPattern` constructor will throw an exception - if you try to set any of these flags. - -<table> - - <colgroup> - <col width="30%"> - <col width="35%"> - <col width="35%"> - </colgroup> - - <tr> - <th>Example pattern</th> - <th>Example matching URLs</th> - <th>Example non-matching URLs</th> - </tr> - - <tr> - <td><code>/.*moz.*/</code></td> - <td><code>http://foo.mozilla.org/</code><br> - <code>http://mozilla.org</code><br> - <code>https://mozilla.org</code><br> - <code>http://foo.com/mozilla</code><br> - <code>http://hemozoon.org</code><br> - <code>mozscheme://foo.org</code><br></td> - <td><code>http://foo.org</code><br> - </tr> - - <tr> - <td><code>/http:\/\/moz.*/</code></td> - <td><code>http://mozilla.org</code><br> - <code>http://mozzarella.com</code></td> - <td><code>https://mozilla.org</code><br> - <code>http://foo.mozilla.org/</code><br> - <code>http://foo.com/moz</code></td> - </tr> - - <tr> - <td><code>/http.*moz.*/</code><br></td> - <td><code>http://foo.mozilla.org/</code><br> - <code>http://mozilla.org</code><br> - <code>http://hemozoon.org/</code></td> - <td><code>ftp://http/mozilla.org</code></td> - </tr> - -</table> - -## Examples ## - - var { MatchPattern } = require("match-pattern"); - var pattern = new MatchPattern("http://example.com/*"); - console.log(pattern.test("http://example.com/")); // true - console.log(pattern.test("http://example.com/foo")); // true - console.log(pattern.test("http://foo.com/")); // false! - -<api name="MatchPattern"> -@class -<api name="MatchPattern"> -@constructor - This constructor creates match pattern objects that can be used to test URLs. -@param pattern {string} - The pattern to use. See Patterns above. -</api> - -<api name="test"> -@method - Tests a URL against the match pattern. -@param url {string} - The URL to test. -@returns {boolean} - True if the URL matches the pattern and false otherwise. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/memory.md b/tools/addon-sdk-1.4/packages/api-utils/docs/memory.md deleted file mode 100644 index c90f613..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/memory.md +++ /dev/null @@ -1,3 +0,0 @@ -The `memory` module provides a concrete default implementation for the SDK's -`memory` global. For documentation on the `memory` global, see the -[Globals](dev-guide/module-development/globals.html) reference. diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/namespace.md b/tools/addon-sdk-1.4/packages/api-utils/docs/namespace.md deleted file mode 100644 index 4a308b8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/namespace.md +++ /dev/null @@ -1,66 +0,0 @@ -Provides an API for creating namespaces for any given objects, which -effectively may be used for creating fields that are not part of objects -public API. - - let { Namespace } = require('api-utils/namespace'); - let ns = Namespace(); - - ns(publicAPI).secret = secret; - -One namespace may be used with multiple objects: - - let { Namespace } = require('api-utils/namespace'); - let dom = Namespace(); - - function View(element) { - let view = Object.create(View.prototype); - dom(view).element = element; - // .... - } - View.prototype.destroy = function destroy() { - let { element } = dom(this); - element.parentNode.removeChild(element); - // ... - }; - // ... - exports.View = View; - // ... - -Also, multiple namespaces can be used with one object: - - // ./widget.js - - let { Cu } = require('chrome'); - let { Namespace } = require('api-utils/namespace'); - let { View } = require('./view'); - - // Note this is completely independent from View's internal Namespace object. - let ns = Namespace(); - - function Widget(options) { - let { element, contentScript } = options; - let widget = Object.create(Widget.prototype); - View.call(widget, options.element); - ns(widget).sandbox = Cu.Sandbox(element.ownerDocument.defaultView); - // ... - } - Widget.prototype = Object.create(View.prototype); - Widget.prototype.postMessage = function postMessage(message) { - let { sandbox } = ns(this); - sandbox.postMessage(JSON.stringify(JSON.parse(message))); - ... - }; - Widget.prototype.destroy = function destroy() { - View.prototype.destroy.call(this); - // ... - delete ns(this).sandbox; - }; - exports.Widget = Widget; - -In addition access to the namespace can be shared with other code by just -handing them a namespace accessor function. - - let { dom } = require('./view'); - Widget.prototype.setInnerHTML = function setInnerHTML(html) { - dom(this).element.innerHTML = String(html); - }; diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/observer-service.md b/tools/addon-sdk-1.4/packages/api-utils/docs/observer-service.md deleted file mode 100644 index a2041f3..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/observer-service.md +++ /dev/null @@ -1,69 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `observer-service` module provides access to the -application-wide observer service singleton. - -For a list of common observer topics across a variety of Mozilla-based -applications, see the MDC page on -[Observer Notifications](https://developer.mozilla.org/en/Observer_Notifications). - -## Observer Callbacks ## - -Observer callbacks are functions of the following form: - - function callback(subject, data) { - /* Respond to the event notification here... */ - } - -In the above example, `subject` is any JavaScript object, as is -`data`. The particulars of what the two contain are specific -to the notification topic. - -<api name="add"> -@function - Adds an observer callback to be triggered whenever a notification matching the - topic is broadcast throughout the application. - -@param topic {string} - The topic to observe. - -@param callback {function,object} - Either a function or an object that implements [`nsIObserver`](http://mxr.mozilla.org/mozilla-central/source/xpcom/ds/nsIObserver.idl). - If a function, then it is called when the notification occurs. If an object, - then its `observe()` method is called when the notification occurs. - -@param [thisObject] {object} - An optional object to use as `this` when a function callback is called. -</api> - -<api name="remove"> -@function - Unsubscribes a callback from being triggered whenever a notification - matching the topic is broadcast throughout the application. - -@param topic {string} - The topic being observed by the previous call to `add()`. - -@param callback {function,object} - The callback subscribed in the previous call to `add()`, either a function or - object. - -@param [thisObject] {object} - If `thisObject` was passed to the previous call to `add()`, it should be - passed to `remove()` as well. -</api> - -<api name="notify"> -@function - Broadcasts a notification event for a topic, passing a subject and data to all - applicable observers in the application. - -@param topic {string} - The topic about which to broadcast a notification. - -@param [subject] {value} - Optional information about the topic. This can be any JS object or primitive. - If you have multiple values to pass to observers, wrap them in an object, - e.g., `{ foo: 1, bar: "some string", baz: myObject }`. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/plain-text-console.md b/tools/addon-sdk-1.4/packages/api-utils/docs/plain-text-console.md deleted file mode 100644 index 3c7a5a6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/plain-text-console.md +++ /dev/null @@ -1,3 +0,0 @@ -The `plain-text-console` module provides a minimalist implementation -of the [console](dev-guide/addon-development/console.html) global, -which simply logs all messages to standard output. diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/preferences-service.md b/tools/addon-sdk-1.4/packages/api-utils/docs/preferences-service.md deleted file mode 100644 index 348fb60..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/preferences-service.md +++ /dev/null @@ -1,80 +0,0 @@ -<!-- contributed by Myk Melez [myk@mozilla.org] --> -<!-- contributed by Daniel Aquino [mr.danielaquino@gmail.com] --> -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `preferences-service` module provides access to the -application-wide preferences service singleton. - - -<api name="set"> -@function -Sets the application preference `name` to `value`. -@param name {string} Preference name. -@param value {string,number,bool} Preference value. - -**Example:** - - var name = "extensions.checkCompatibility.nightly"; - require("preferences-service").set(name, false); -</api> - - -<api name="get"> -@function -Gets the application preference `name`. -@param name {string} -@param defaultValue {string,number,bool} Preference value. -@returns {string,number,bool} Preference value, returns a default value if no -preference is set. - -**Example:** - - var name = "extensions.checkCompatibility.nightly"; - var nightlyCompatChk = require("preferences-service").get(name); -</api> - - -<api name="has"> -@function -@param name {string} Preference name. -@returns {bool} Returns whether or not the application preference `name` exists. - -**Example:** - - var name = "extensions.checkCompatibility.nightly"; - if (require("preferences-service").has(name)) { - // ... - } -</api> - - -<api name="isSet"> -@function -@param name {string} Preference name. -@returns {bool} -Returns whether or not the application preference `name` both exists -and has been set to a non-default value by the user (or a program -acting on the user's behalf). - -**Example:** - - var name = "extensions.checkCompatibility.nightly"; - if (require("preferences-service").isSet(name)) { - // ... - } -</api> - - -<api name="reset"> -@function -Clears a non-default, user-set value from the application preference -`name`. If no user-set value is defined on `name`, the function -does nothing. -@param name {string} Preference name. - -**Example:** - - var name = "extensions.checkCompatibility.nightly"; - require("preferences-service").reset(name); -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/runtime.md b/tools/addon-sdk-1.4/packages/api-utils/docs/runtime.md deleted file mode 100644 index e4a7ee5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/runtime.md +++ /dev/null @@ -1,71 +0,0 @@ -<!-- contributed by Wes Kocher [kwierso@gmail.com] --> - -The `runtime` module provides access to information about Firefox's -runtime environment. All properties exposed are read-only. - -For more information, see [nsIXULRuntime][nsIXULRuntime]. -[nsIXULRuntime]: https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIXULRuntime - -<api name="inSafeMode"> -@property {boolean} - This value is `true` if Firefox was started in safe mode, - otherwise `false`. -</api> - -<api name="OS"> -@property {string} - A string identifying the current operating system. For example, . - `"WINNT"`, `"Darwin"`, or `"Linux"`. See [OS_TARGET][OS_TARGET] - for a more complete list of possible values. - -[OS_TARGET]: https://developer.mozilla.org/en/OS_TARGET -</api> - -<api name="processType"> -@property {long} - The type of the caller's process, which will be one of these constants\: -<table> - <tr> - <th>Constant</th> - <th>Value</th> - <th>Description</th> - </tr> - - <tr> - <td>PROCESS_TYPE_DEFAULT</td> - <td>0</td> - <td>The default (chrome) process.</td> - </tr> - - <tr> - <td>PROCESS_TYPE_PLUGIN</td> - <td>1</td> - <td>A plugin subprocess.</td> - </tr> - - <tr> - <td>PROCESS_TYPE_CONTENT</td> - <td>2</td> - <td>A content subprocess.</td> - </tr> - - <tr> - <td>PROCESS_TYPE_IPDLUNITTEST</td> - <td>3</td> - <td>An IPDL unit testing subprocess.</td> - </tr> -</table> -</api> - -<api name="widgetToolkit"> -@property {string} - A string identifying the target widget toolkit in use. -</api> - -<api name="XPCOMABI"> -@property {string} - A string identifying the [ABI][ABI] of the current processor and compiler vtable. - This string takes the form \<`processor`\>-\<`compilerABI`\>, - for example\: "`x86-msvc`" or "`ppc-gcc3`". -[ABI]: https://developer.mozilla.org/en/XPCOM_ABI -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/securable-module.md b/tools/addon-sdk-1.4/packages/api-utils/docs/securable-module.md deleted file mode 100644 index d1d392d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/securable-module.md +++ /dev/null @@ -1,93 +0,0 @@ -The `securable-module` module allows for the recursive loading -and sandboxing of -[CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0) -(formerly called SecurableModules). This allows, for instance, -the creation of "mini platforms" that manage the sandboxed evaluation of code. - -## Loader Objects ## - -Loader objects encapsulate the sandboxed loading of SecurableModules -and the execution of code that relies upon them. - -<code>Loader.**runScript**(*options*)</code> - -Runs JavaScript code in the context of the Loader. *options* is an -object with the following keys: - -<table> - <tr> - <td><code>contents</code></td> - <td>A string of JavaScript code.</td> - </tr> - <tr> - <td><code>filename</code></td> - <td>An absolute URL naming the file from which the code - originates; useful for error reporting and debugging. If omitted, - this option defaults to <code>"<string>"</code>.</td> - </tr> - <tr> - <td><code>lineNo</code></td> - <td>An integer representing the line from the file which the - beginning of the code corresponds to. If ommitted, this option - defaults to <code>1</code>.</td> - </tr> - <tr> - <td><code>jsVersion</code></td> - <td>A string representing the JavaScript version that the code - should be interpreted under. If omitted, this options defaults to - the latest version of JavaScript supported by the platform.</td> - </tr> -</table> - -This method returns the most recent value evaluated by the given code. - -<code>Loader.**runScript**(*code*)</code> - -If *code* is a string of JavaScript code, this is a convenient -shorthand for `Loader.runScript({contents: code}}`. - -<code>Loader.**require**(*module*)</code> - -This loads the given module name using the standard `require()` -semantics and returns the loaded module. - -## Functions ## - -<code>securable-module.**Loader**(*options*)</code> - -Creates a new SecurableModule Loader. *options* is an object with -the following keys: - -<table> - <tr> - <td><code>rootPaths</code></td> - <td>A list of absolute URLs that will be searched, in order, for - SecurableModules when <code>require()</code> is called by any code - executing within the context of the Loader.</td> - </tr> - <tr> - <td><code>rootPath</code></td> - <td>A single absolute URL; this is a convenience option, - synonymous with setting <code>rootPaths</code> to an array containing - a single URL.</td> - </tr> - <tr> - <td><code>defaultPrincipal</code></td> - <td>A string representing the default principal given to any code - that is executed by the Loader. This can be <code>"system"</code>, in - which case code executed has full chrome access (including access - to the <code>Components</code> object which allows it to access the - Mozilla platform unrestricted). - Alternatively, it can be a URL, such as <code>"http://www.foo.com"</code>, - in which case it is treated like web content. If left unspecified, - the default value of this option is <code>"http://www.mozilla.org"</code>. - </td> - </tr> - <tr> - <td><code>globals</code></td> - <td>An object containing the names and values of all variables - that will be injected into the global scope of all code executed - by the Loader.</td> - </tr> -</table> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/tab-browser.md b/tools/addon-sdk-1.4/packages/api-utils/docs/tab-browser.md deleted file mode 100644 index b844206..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/tab-browser.md +++ /dev/null @@ -1,136 +0,0 @@ -<!-- contributed by Dietrich Ayala [dietrich@mozilla.com] --> - -The `tab-browser` module is a low-level API that provides privileged -access to browser tab events and actions. - -Introduction ------------- - -The `tab-browser` module contains helpers for tracking tabbrowser elements -and tabs, as well as a few utilities for actions such as opening a new -tab, and catching all tab content loads. - -This is a low-level API that has full privileges, and is intended to be used -by SDK internal modules. If you just need easy access to tab events for your -add-on, use the Tabs module (JEP 110). - -<api name="activeTab"> -@property {element} -The XUL tab element of the currently active tab. -</api> - -<api name="addTab"> -@function -Adds a new tab. - -**Example** - - var tabBrowser = require("tab-browser"); - tabBrowser.addTab("http://google.com"); - - var tabBrowser = require("tab-browser"); - tabBrowser.addTab("http://google.com", { - inBackground: true - }); - - var tabBrowser = require("tab-browser"); - tabBrowser.addTab("http://google.com", { - inNewWindow: true, - onLoad: function(tab) { - console.log("tab is open."); - } - }); - -@returns {element} -The XUL tab element of the newly created tab. - -@param URL {string} -The URL to be opened in the new tab. - -@param options {object} -Options for how and where to open the new tab. - -@prop [inNewWindow] {boolean} -An optional parameter whose key can be set in `options`. -If true, the tab is opened in a new window. Default is false. - -@prop [inBackground] {boolean} -An optional parameter whose key can be set in `options`. -If true, the tab is opened adjacent to the active tab, but not -switched to. Default is false. - -@prop [onLoad] {function} -An optional parameter whose key can be set in `options`. -A callback function that is called once the tab has loaded. -The XUL element for the tab is passed as a parameter to -this function. -</api> - -<api name="Tracker"> -@function -Register a delegate object to be notified when tabbrowsers are created -and destroyed. - -The onTrack method will be called once per pre-existing tabbrowser, upon -tracker registration. - -**Example** - - var tabBrowser = require("tab-browser"); - let tracker = { - onTrack: function(tabbrowser) { - console.log("A new tabbrowser is being tracked."); - }, - onUntrack: function(tabbrowser) { - console.log("A tabbrowser is no longer being tracked."); - } - }; - tabBrowser.Tracker(tracker); - -@param delegate {object} -Delegate object to be notified each time a tabbrowser is created or destroyed. -The object should contain the following methods: - -@prop [onTrack] {function} -Method of delegate that is called when a new tabbrowser starts to be tracked. -The tabbrowser element is passed as a parameter to this method. - -@prop [onUntrack] {function} -Method of delegate that is called when a tabbrowser stops being tracked. -The tabbrowser element is passed as a parameter to this method. -</api> - -<api name="TabTracker"> -@function -Register a delegate object to be notified when tabs are opened and closed. - - -The onTrack method will be called once per pre-existing tab, upon -tracker registration. - -**Example** - - var tabBrowser = require("tab-browser"); - let tracker = { - onTrack: function(tab) { - console.log("A new tab is being tracked."); - }, - onUntrack: function(tab) { - console.log("A tab is no longer being tracked."); - } - }; - tabBrowser.TabTracker(tracker); - -@param delegate {object} -Delegate object to be notified each time a tab is opened or closed. -The object should contain the following methods: - -@prop [onTrack] {function} -Method of delegate that is called when a new tab starts to be tracked. -The tab element is passed as a parameter to this method. - -@prop [onUntrack] {function} -Method of delegate that is called when a tab stops being tracked. -The tab element is passed as a parameter to this method. -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/text-streams.md b/tools/addon-sdk-1.4/packages/api-utils/docs/text-streams.md deleted file mode 100644 index c057e06..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/text-streams.md +++ /dev/null @@ -1,98 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `text-streams` module provides streams for reading and writing text using -particular character encodings. - -<api name="TextReader"> -@class -<api name="TextReader"> -@constructor - Creates a buffered input stream that reads text from a backing stream using a - given text encoding. -@param inputStream {stream} - The backing stream, an [`nsIInputStream`](http://mxr.mozilla.org/mozilla-central/source/xpcom/io/nsIInputStream.idl). - It must already be opened. -@param [charset] {string} - `inputStream` is expected to be in the character encoding named by this value. - If not specified, "UTF-8" is assumed. See [`nsICharsetConverterManager.idl`](http://mxr.mozilla.org/mozilla-central/source/intl/uconv/idl/nsICharsetConverterManager.idl) - for documentation on how to determine other valid values for this. -</api> - -<api name="closed"> -@property {boolean} - True if the stream is closed. -</api> - -<api name="close"> -@method - Closes both the stream and its backing stream. -</api> - -<api name="read"> -@method - Reads and returns a string from the stream. If the stream is closed, an - exception is thrown. -@param [numChars] {number} - The number of characters to read. If not given, the remainder of the stream - is read. -@returns {string} - The string read. If the stream is at the end, the empty string is returned. -</api> - -</api> - - -<api name="TextWriter"> -@class -<api name="TextWriter"> -@constructor - Creates a buffered output stream that writes text to a backing stream using a - given text encoding. -@param outputStream {stream} - The backing stream, an [`nsIOutputStream`](http://mxr.mozilla.org/mozilla-central/source/xpcom/io/nsIOutputStream.idl). - It must already be opened. -@param [charset] {string} - Text will be written to `outputStream` using the character encoding named by - this value. If not specified, "UTF-8" is assumed. See [`nsICharsetConverterManager.idl`](http://mxr.mozilla.org/mozilla-central/source/intl/uconv/idl/nsICharsetConverterManager.idl) - for documentation on how to determine other valid values for this. -</api> - -<api name="closed"> -@property {boolean} - True if the stream is closed. -</api> - -<api name="close"> -@method - Flushes the backing stream's buffer and closes both the stream and the backing - stream. If the stream is already closed, an exception is thrown. -</api> - -<api name="flush"> -@method - Flushes the backing stream's buffer. -</api> - -<api name="write"> -@method - Writes a string to the stream. If the stream is closed, an exception is - thrown. -@param str {string} - The string to write. -</api> - -<api name="writeAsync"> -@method - Writes a string on a background thread. After the write completes, the - backing stream's buffer is flushed, and both the stream and the backing stream - are closed, also on the background thread. If the stream is already closed, - an exception is thrown immediately. -@param str {string} - The string to write. -@param [callback] {callback} - *`callback`*, if given, must be a function. It's called as `callback(error)` - when the write completes. `error` is an `Error` object or undefined if there - was no error. Inside *`callback`*, `this` is the `TextWriter` object. -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/traceback.md b/tools/addon-sdk-1.4/packages/api-utils/docs/traceback.md deleted file mode 100644 index fd7ddb5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/traceback.md +++ /dev/null @@ -1,62 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - - -The `traceback` module contains functionality similar to -Python's [traceback](http://docs.python.org/library/traceback.html) module. - -## JSON Traceback Objects ## - -Tracebacks are stored in JSON format. The stack is represented as an -array in which the most recent stack frame is the last element; each -element thus represents a stack frame and has the following keys: - -<table> - <tr> - <td><code>filename</code></td> - <td>The name of the file that the stack frame takes place in.</td> - </tr> - <tr> - <td><code>lineNo</code></td> - <td>The line number is being executed at the stack frame.</td> - </tr> - <tr> - <td><code>funcName</code></td> - <td>The name of the function being executed at the stack frame, or - <code>null</code> if the function is anonymous or the stack frame is - being executed in a top-level script or module.</td> - </tr> -</table> - -<api name="fromException"> -@function - Attempts to extract the traceback from *`exception`*. - -@returns {traceback} - JSON representation of the traceback or `null` if not found. - -@param exception {exception} - exception where exception is an `nsIException`. -</api> - -See [nsIException](https://developer.mozilla.org/en/NsIException) for more -information. - -<api name="get"> -@function - -@returns {JSON} - Returns the JSON representation of the stack at the point that this - function is called. -</api> - -<api name="format"> -@function -Given a JSON representation of the stack or an exception instance, -returns a formatted plain text representation of it, similar to -Python's formatted stack tracebacks. If no argument is provided, the -stack at the point this function is called is used. - -@param [tbOrException] {object} -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/traits.md b/tools/addon-sdk-1.4/packages/api-utils/docs/traits.md deleted file mode 100644 index 66e8f02..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/traits.md +++ /dev/null @@ -1,240 +0,0 @@ -<!-- contributed by Irakli Gozalishvil [gozala@mozilla.com] --> - -The `traits` module provides base building blocks for secure object -composition. It exports base trait / constructor function that -constructs an instance of `Trait`. - -[Traits](http://en.wikipedia.org/wiki/Trait_%28computer_science%29) are a -simple composition mechanism for structuring object-oriented programs. Traits -are similar to -[interfaces](http://en.wikipedia.org/wiki/Interface_%28object-oriented_programming%29), -except that they often define only a part of an object's data and behavior and -are intended to be used in conjunction with other traits to completely define -the object. - -Traits are also considered to be a more robust alternative to -[mixins](http://en.wikipedia.org/wiki/Mixins) because, name conflicts have to -be resolved explicitly by composer & because trait composition is -order-independent (hence more declarative). - - -There are some other implementations of traits in JavaScript & some ideas / -APIs are borrowed from them: - -- [traitsjs](http://www.traitsjs.org/) -- [joose](http://code.google.com/p/joose-js/) - -Object-capability security model --------------------------------- - -Implementation uses an -[object-capability security model](http://en.wikipedia.org/wiki/Object-capability_model) -to allow protection of private APIs. At the same private APIs can be shared -between among trait composition parties. To put it simply: All the properties -whose names start with `"_"` are considered to be **private**, and are -unaccessible from anywhere except other **public** methods / accessors of the -instance that had been defined during composition. - -<api name="Trait"> -@class -<api name="Trait"> -@constructor -Creates an instance of Trait and returns it if it has no `constructor` method -defined. If instance has `constructor` method, then it is called with all the -arguments passed to this function and returned value is returned instead, -unless it's `undefined`. In that case instance is returned. - -`Trait` function represents a base trait. As with any other trait it represents -a constructor function for creating instances of its own & a placeholder -for a trait compositions functions. -</api> - -<api name="compose"> -@method -Composes new trait out of itself and traits / property maps passed as an -arguments. If two or more traits / property maps have properties with the same -name, the new trait will contain a "conflict" property for that name (see -examples in Examples section to find out more about "conflict" properties). -This is a commutative and associative operation, and the order of its -arguments is not significant. - -**Examples:** - -Let's say we want to define a reusable piece of code for a lists of elements. - - var { Trait } = require('traits'); - var List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = []; - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.splice(index, 1); - } - }); - -Instances of `List` can be created by calling `List` function with or without -`new` keyword. - - let l1 = List(); - l1 instanceof List; // true - let l2 = new List(); - l2 instanceof List; // true - -As you can see `add` and `remove` functions are capable of accessing private -`_list` property, but thats about it, there's nothing else that will be able -to access this property: - - '_list' in l1; // false - '_list' in l2; // false - '_list' in List.protoype; // false - l1.has = function(name) name in this - l1.has('_list'); // false - l1.length; // 0 - l1.add('test') - l1.length // 1 - -@param trait1 {Object|Function} - Trait or property map to compose new trait from. -@param trait2 {Object|Function} - Trait or property map to compose new trait from. -@param ... {Object|Function} - Traits or property maps to compose new trait from. - -@returns {Function} - New trait containing the combined properties of all the traits. -</api> - -<api name="required"> -@property {Object} -Singleton, used during trait composition to define "required" properties. - -**Example:** - - var Enumerable = Trait.compose({ - list: Trait.required, - forEach: function forEach(consumer) { - return this.list.forEach(consumer); - } - }); - - let c1 = Enumerable(); // Error: Missing required property: list - - var EnumerableList = List.compose({ - get list() this._list.slice(0) - }, Enumerable); - - let c2 = EnumerableList(); - c2.add('test') - c2.length // 1 - c2.list[0] // 'test' - c2.forEach(console.log) // > info: 'test 0 test' - -</api> - - -<api name="resolve"> -@method -Composes a new trait that has all the same properties -as the trait on which it is called, except that each property listed -in the `resolutions` argument will be renamed from the name -of the property in the `resolutions` argument to its value. -And if its value is `null`, the property will become required. - -**Example:** - - var Range = List.resolve({ - constructor: null, - add: '_add', - }).compose({ - min: null, - max: null, - get list() this._list.slice(0), - constructor: function Range(min, max) { - this.min = min; - this.max = max; - this._list = []; - }, - add: function(item) { - if (item <= this.max && item >= this.min) - this._add(item) - } - }); - - - let r = Range(0, 10); - r.min; // 0 - r.max; // 10 - r.length; // 0; - r.add(5); - r.length; // 1 - r.add(12); - r.length; // 1 (12 was not in a range) - -@param resolutions {Object} -@returns {Function} - New resolved trait. -</api> - -<api name="override"> -@method -Composes a new trait with all of the combined properties of `this` and the -argument traits. In contrast to `compose`, `override` immediately resolves -all conflicts resulting from this composition by overriding the properties of -later traits. Trait priority is from left to right. I.e. the properties of -the leftmost trait are never overridden. - -**Example:** - - // will compose trait with conflict property 'constructor' - var ConstructableList = List.compose({ - constructor: function List() this._list = Array.slice(arguments) - }); - // throws error with message 'Remaining conflicting property: constructor' - ConstructableList(1, 2, 3); - - var ConstructableList = List.override({ - constructor: function List() this._list = Array.slice(arguments) - }); - ConstructableList(1, 2, 3).length // 3 - -@param trait1 {Object|Function} - Trait or property map to compose new trait from. -@param trait2 {Object|Function} - Trait or property map to compose new trait from. -@param ... {Object|Function} - Traits or property maps to compose new trait from. - -@returns {Function} - New trait containing the combined properties of all the traits. -</api> - -<api name="_public"> -@property {Object} -Internal property of instance representing public API that is exposed to the -consumers of an instance. -</api> - -<api name='toString'> -@method -Textual representation of an object. All the traits will return: -`'[object Trait]'` string, unless they have `constructor` property, in that -case string `'Trait'` is replaced with the name of `constructor` property. - -**Example:** - - var MyTrait = Trait.compose({ - constructor: function MyTrait() { - // do your initialization here - } - }); - MyTrait().toString(); // [object MyTrait] - -</api> -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/unit-test.md b/tools/addon-sdk-1.4/packages/api-utils/docs/unit-test.md deleted file mode 100644 index 401b551..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/unit-test.md +++ /dev/null @@ -1,389 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> -<!-- edited by Shane Tomlinson[stomlinson@mozilla.com] --> - -The `unit-test` module makes it easy to find and run unit tests. - -<api name="test"> -@class -Each function which represents a test case is passed a single argument -`test`, which represents the test runner. - -<api name="pass"> -@method - Marks a test as passing, with the given optional message. - -@param [message] {string} - Optional passing message. -</api> - - -<api name="fail"> -@method - Marks a test as failing, with the given optional message. - -@param [message] {string} - Optional failure message. -</api> - -<api name="expectFail"> -@method - *experimental* Expect the test enclosed within `func` to fail. - -@param func {function} - A function that should contain a test that is expected to fail. -</api> - -<api name="exception"> -@method - Marks a test as failing due to the given exception having been thrown. - This can be put in a `catch` clause. - -@param e {exception} - An exception. -</api> - -<api name="assert"> -@method - Ensures that `a` has a truthy value. - -@param a {value} - Value to verify. -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - -<api name="assertEqual"> -@method - Ensures that `a == b` without recursing into `a` or `b`. - -@param a {value} - A value. - -@param b {value} - Another value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - -<api name="assertNotEqual"> -@method - Ensures that `a != b` without recursing into `a` or `b`. - -@param a {value} - A value. - -@param b {value} - Another value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - -<api name="assertStrictEqual"> -@method - Ensures that `a === b` without recursing into `a` or `b`. - -@param a {value} - A value. - -@param b {value} - Another value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - -<api name="assertNotStrictEqual"> -@method - Ensures that `a !== b` without recursing into `a` or `b`. - -@param a {value} - A value. - -@param b {value} - Another value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - -<api name="assertMatches"> -@method - Ensures that the given string matches the given regular expression. - If it does, marks a test as passing, otherwise marks a test as - failing. - -@param string {string} - The string to test. - -@param regexp {regexp} - The string should match this regular expression. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - -<api name="assertRaises"> -@method - Calls the function `func` with no arguments, expecting an exception - to be raised. If nothing is raised, marks the test as failing. If an - exception is raised, the exception's `message` property is - compared with `predicate`: if `predicate` is a string, then a - simple equality comparison is done with `message`. Otherwise, - if `predicate` is a regular expression, `message` is tested - against it. - -@param func {function} - A function that should raise an exception when called. - -@param predicate {string,regexp} - A string or regular expression to compare to the exception's message. - -@param [message] {string} - Depending on the outcome, a test is marked as passing or failing, and - *message* is logged. -</api> - - -<api name="assertFunction"> -@method - Ensures that `a` is a function. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertUndefined"> -@method - Ensures that `a` is `undefined`. `null`, `0`, and `false` will all fail. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertNotUndefined"> -@method - Ensures that `a` is not `undefined`. `null`, `0`, and `false` will all pass. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertNull"> -@method - Ensures that `a` is `null`. `undefined`, `0`, and `false` will all fail. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertNotNull"> -@method - Ensures that `a` is not `null`. `undefined`, `0`, and `false` will all pass. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertObject"> -@method - Ensures that `a` is an object. A function, string, or number will fail. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertString"> -@method - Ensures that `a` is a string. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertArray"> -@method - Ensures that `a` is an array. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="assertNumber"> -@method - Ensures that `a` is a number. - -@param a {value} - A value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. - -</api> - - -<api name="waitUntilDone"> -@method - Puts the test runner into asynchronous testing mode, waiting up to - *timeout* milliseconds for `test.done()` to be called. This - is intended for use in situations where a test suite schedules a - callback, calls `test.waitUntilDone()`, and then calls - `test.done()` in the callback. - -@param [timeout] {integer} - If this number of milliseconds elapses and `test.done()` has not yet been - called, the test is marked as failing. -</api> - - -<api name="done"> -@method - Marks a test as being complete. Assumes a previous call to - `test.waitUntilDone()`. -</api> - -</api> - - -<api name="waitUntil"> -@method - Ensures that `a` returns a truthy value within a reasonable amount of time. - -@param a {function} - Function that returns the value to verify. -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - -<api name="waitUntilEqual"> -@method - Ensures that `a == b` returned values or values without without recursing - into `a` or `b`. - -@param a {Function} - A value, or a function that returns a value. - -@param b {value} - Another value, or a function that returns value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - -<api name="waitUntilNotEqual"> -@method - Ensures that `a != b` without recursing into `a` or `b`. - -@param a {Function} - A value, or a function that returns a value. - -@param b {value} - Another value, or a function that returns another value. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - -<api name="waitUntilMatches"> -@method - Ensures that the given string matches the given regular expression. - If it does, marks the test as passing, otherwise marks the test as - failing. - -@param string {Function} - A function that returns the string to test. - -@param regexp {regexp} - The string should match this regular expression. - -@param [message] {string} - The test is marked as passing or failing depending on the result, logging - *message* with it. -</api> - - - -<api name="findAndRunTests"> -@function - The list of directories is searched for SecurableModules that start - with the prefix `test-`. Each module matching this criteria is - expected to export functions that are test cases or a suite of test - cases; each is called with a single argument, which is a Test Runner - Object. - -@param options {object} - An object with the following properties: - @prop dirs {string} - A list of absolute paths representing directories to search - for tests in. It's assumed that all of these directories are also - in the module search path, i.e. any JS files found in them are - SecurableModules that can be loaded via a call to - `require()`. - @prop onDone {function} - A function to call when testing is complete. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/unload.md b/tools/addon-sdk-1.4/packages/api-utils/docs/unload.md deleted file mode 100644 index a7e3f3f..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/unload.md +++ /dev/null @@ -1,57 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `unload` module allows modules to register callbacks that are called -when they are unloaded. It is similar to the CommonJS module of the same -name in the [Narwhal][] platform. - -[Narwhal]: http://narwhaljs.org/ - -<api name="ensure"> -@function - Calling `ensure()` on an object does two things: - - 1. It replaces a destructor method with a wrapper method that will never call - the destructor more than once. - 2. It ensures that this wrapper method is called when `send()` is - called. - - Therefore, when you register an object with `ensure()`, you can call its - destructor method yourself, you can let it happen for you, or you can do both. - - The destructor will be called with a single argument describing the reason - for the unload; see `when()`. If `object` does not have the expected - destructor method, then an exception is thrown when `ensure()` is called. - -@param object {object} - An object that defines a destructor method. -@param [name] {string} - Optional name of the destructor method. Default is `unload`. -</api> - -<api name="when"> -@function - Registers a function to be called when `send()` is called. - -@param callback {function} - A function that will be called when `send()` is called. It is called with a - single argument, one of the following strings describing the reason for - unload: `"uninstall"`, `"disable"`, `"shutdown"`, `"upgrade"`, or - `"downgrade"`. (On Gecko 1.9.2-based applications such as Firefox 3.6, - `"upgrade"` and `"downgrade"` are not available, and `"shutdown"` will be sent - in their place.) If a reason could not be determined, `undefined` will be - passed instead. Note that if an add-on is unloaded with reason `"disable"`, - it will not be notified about `"uninstall"` while it is disabled. A solution - to this issue is being investigated; see bug 571049. -</api> - -<api name="send"> -@function - Sends an "unload signal", thereby triggering all callbacks registered via - `when()`. In general, this function need not be manually called; it is - automatically triggered by the embedder. - -@param [reason] {string} - An optional string describing the reason for unload; see `unload.when()`. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/url.md b/tools/addon-sdk-1.4/packages/api-utils/docs/url.md deleted file mode 100644 index dee0580..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/url.md +++ /dev/null @@ -1,81 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - - -The `url` module provides functionality for the parsing and retrieving of URLs. - -<api name="URL"> -@class -<api name="URL"> -@constructor - The URL constructor creates an object that represents a URL, verifying that - the provided string is a valid URL in the process. Any API in the SDK which - has a URL parameter will accept `URL` objects, not raw strings, unless - otherwise noted. - -@param source {string} - A string to be converted into a URL. If `source` is not a valid URI, this - constructor will throw an exception. - -@param [base] {string} - An optional string used to resolve relative `source` URLs into absolute ones. -</api> - -<api name="scheme"> -@property {string} - The name of the protocol in the URL. -</api> - -<api name="userPass"> -@property {string} - The username:password part of the URL, `null` if not present. -</api> - -<api name="host"> -@property {string} - The host of the URL, `null` if not present. -</api> - -<api name="port"> -@property {integer} - The port number of the URL, `null` if none was specified. -</api> - -<api name="path"> -@property {string} - The path component of the URL. -</api> - -<api name="toString"> -@method - Returns a string representation of the URL. -@returns {string} - The URL as a string. -</api> -</api> - -<api name="toFilename"> -@function - Attempts to convert the given URL to a native file path. This function will - automatically attempt to resolve non-file protocols, such as the `resource:` - protocol, to their place on the file system. An exception is raised if the URL - can't be converted; otherwise, the native file path is returned as a string. - -@param url {string} - The URL, as a string, to be converted. - -@returns {string} - The converted native file path as a string. -</api> - -<api name="fromFilename"> -@function - Converts the given native file path to a `file:` URL. - -@param path {string} - The native file path, as a string, to be converted. - -@returns {string} - The converted URL as a string. -</api> - diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/window-utils.md b/tools/addon-sdk-1.4/packages/api-utils/docs/window-utils.md deleted file mode 100644 index 3de84b5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/window-utils.md +++ /dev/null @@ -1,84 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> -<!-- edited by Erik Vold [erikvvold@gmail.com] --> - -The `window-utils` module provides helpers for accessing and tracking -application windows. These windows implement the [`nsIDOMWindow`][nsIDOMWindow] -interface. - -[nsIDOMWindow]: http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/base/nsIDOMWindow.idl - -<api name="WindowTracker"> -@class -`WindowTracker` objects make it easy to "monkeypatch" windows when a program is -loaded and "un-monkeypatch" those windows when the program is unloaded. For -example, if a Firefox add-on needs to add a status bar icon to all browser -windows, it can use a single `WindowTracker` object to gain access to windows -when they are opened and closed and also when the add-on is loaded and unloaded. - -When a window is opened or closed, a `WindowTracker` notifies its delegate -object, which is passed to the constructor. The delegate is also notified of -all windows that are open at the time that the `WindowTracker` is created and -all windows that are open at the time that the `WindowTracker` is unloaded. The -caller can therefore use the same code to act on all windows, regardless of -whether they are currently open or are opened in the future, or whether they are -closed while the parent program is loaded or remain open when the program is -unloaded. - -When a window is opened or when a window is open at the time that the -`WindowTracker` is created, the delegate's `onTrack()` method is called and -passed the window. - -When a window is closed or when a window is open at the time that the -`WindowTracker` is unloaded, the delegate's `onUntrack()` method is called and -passed the window. (The `WindowTracker` is unloaded when its its `unload()` -method is called, or when its parent program is unloaded, disabled, or -uninstalled, whichever comes first.) - -**Example** - - var delegate = { - onTrack: function (window) { - console.log("Tracking a window: " + window.location); - // Modify the window! - }, - onUntrack: function (window) { - console.log("Untracking a window: " + window.location); - // Undo your modifications! - } - }; - var winUtils = require("window-utils"); - var tracker = new winUtils.WindowTracker(delegate); - -<api name="WindowTracker"> -@constructor - A `WindowTracker` object listens for openings and closings of application - windows. -@param delegate {object} - An object that implements `onTrack()` and `onUntrack()` methods. -@prop onTrack {function} - A function to be called when a window is open or loads, with the window as the - first and only argument. -@prop [onUntrack] {function} - A function to be called when a window unloads, with the window as the first - and only argument. -</api> -</api> - -<api name="windowIterator"> -@function - An iterator for windows currently open in the application. - -**Example** - - var winUtils = require("window-utils"); - for (window in winUtils.windowIterator()) - console.log("An open window! " + window.location); - -</api> - -<api name="closeOnUnload"> -@function - Marks an application window to be closed when the program is unloaded. -@param window {window} - The window to close. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/xhr.md b/tools/addon-sdk-1.4/packages/api-utils/docs/xhr.md deleted file mode 100644 index f2d3ee3..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/xhr.md +++ /dev/null @@ -1,91 +0,0 @@ -<!-- contributed by Atul Varma [atul@mozilla.com] --> -<!-- edited by Noelle Murata [fiveinchpixie@gmail.com] --> - -The `xhr` module provides access to `XMLHttpRequest` functionality, also known -as AJAX. - -## Limitations ## - -The `XMLHttpRequest` object is currently fairly limited, and does not -yet implement the `addEventListener()` or `removeEventListener()` -methods. It also doesn't yet implement the `upload` property. - -Furthermore, the `XMLHttpRequest` object does not currently support -the `mozBackgroundRequest` property. All security UI, such as -username/password prompts, are automatically suppressed, so if -required authentication information isn't passed to the `open()` -method, the request will fail. - -## Resource Use ## - -Whenever this module is unloaded, all in-progress requests are immediately -aborted. - -## Security Concerns ## - -By default, the `XMLHttpRequest` object grants full access to any -protocol scheme, which means that it can be used to read from (but not -write to) the host system's entire filesystem. It also has unfettered -access to any local area networks, VPNs, and the internet. - -### Threat Model ### - -The `XMLHttpRequest` object can be used by an add-on to "phone -home" and transmit potentially sensitive user data to third -parties. - -If access to the filesystem isn't prevented, it could easily be used -to access sensitive user data, though this may be inconsequential if -the client can't access the network. - -If access to local area networks isn't prevented, malicious code could access -sensitive data. - -If transmission of cookies isn't prevented, malicious code could access -sensitive data. - -Attenuating access based on a regular expression may be ineffective if -it's easy to write a regular expression that *looks* safe but contains -a special character or two that makes it far less secure than it seems -at first glance. - -### Possible Attenuations ### - -<span class="aside"> -We may also want to consider attenuating further based on domain name -and possibly even restricting the protocol to `https:` only, to reduce -risk. -</span> - -Before being exposed to unprivileged code, this object needs -to be attenuated in such a way that, at the very least, it can't -access the user's filesystem. This can probably be done most securely -by white-listing the protocols that can be used in the URL passed to -the `open()` method, and limiting them to `http:`, `https:`, and -possibly a special scheme that can be used to access the add-on's -packaged, read-only resources. - -Finally, we need to also consider attenuating http/https requests such -that they're "sandboxed" and don't communicate potentially sensitive -cookie information. - -<api name="XMLHttpRequest"> -@class - -<api name="XMLHttpRequest"> -@constructor - Creates an `XMLHttpRequest`. This is a constructor, so its use should always - be preceded by the `new` operator. For more information about - `XMLHttpRequest` objects, see the MDC page on - [Using XMLHttpRequest](https://developer.mozilla.org/En/Using_XMLHttpRequest) - and the Limitations section in this page. -</api> -</api> - -<api name="getRequestCount"> -@function - Returns the number of `XMLHttpRequest` objects that are alive (i.e., currently - active or about to be). -@returns {integer} - The number of live `XMLHttpRequest` objects. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/xpcom.md b/tools/addon-sdk-1.4/packages/api-utils/docs/xpcom.md deleted file mode 100644 index 6cb5428..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/xpcom.md +++ /dev/null @@ -1,223 +0,0 @@ -Using this module you can: - -* register a component with -[XPCOM](https://developer.mozilla.org/en/Creating_XPCOM_Components), -making it available to all XPCOM clients -* retrieve a factory for a given XPCOM component -* generate a UUID - -The module also exposes the -[XPCOMUtils](https://developer.mozilla.org/en/JavaScript_code_modules/XPCOMUtils.jsm) -module. - -<api name="register"> -@function - -Makes a component available through XPCOM. - -This function creates and registers a factory for a component given a -constructor for it and some metadata: a -[class ID](https://developer.mozilla.org/en/Creating_XPCOM_Components/An_Overview_of_XPCOM#CID), a [contract ID](https://developer.mozilla.org/en/Creating_XPCOM_Components/An_Overview_of_XPCOM#Contract_ID), -and a name. - -<span class="aside">In this example the HelloWorld component is available to JavaScript only, so we use the technique documented under the "Using wrappedJSObject" section of [How to Build an XPCOM Component in JavaScript](https://developer.mozilla.org/en/How_to_Build_an_XPCOM_Component_in_Javascript).</span> - - var xpcom = require("xpcom"); - - function HelloWorld() { - this.wrappedJSObject = this; - } - - HelloWorld.prototype = { - QueryInterface: xpcom.utils.generateQI(), - hello: function() { - return "Hello World!"; - } - }; - - xpcom.register({name: "Hello World Component", - contractID: "@me.org/myComponent", - create: HelloWorld}); - -XPCOM clients can subsequently access this factory and use it to create -instances of the component. - - var {Ci} = require("chrome"); - - var factory = xpcom.getClass("@me.org/myComponent", Ci.nsIFactory); - var helloWorld = factory.createInstance(null, Ci.nsISupports).wrappedJSObject; - console.log(helloWorld.hello()); - -`register()` returns a Factory object for the component which implements -the `createInstance()` and `QueryInterface()` functions of the -[`nsIFactory`](https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFactory) and -[`nsISupports`](https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsISupports) -interfaces, as well as defining an `unregister()` function to remove the -component from XPCOM. - -When the module is unloaded, all components registered via the `register()` -function are automatically unregistered. - -@param options {object} - -@prop [uuid] {nsIDPtr} -A [UUID](https://developer.mozilla.org/en/Generating_GUIDs) which will be -used as the -[class ID](https://developer.mozilla.org/en/Creating_XPCOM_Components/An_Overview_of_XPCOM#CID) -for this component. If you don't include this option, the `register()` -function will generate a new UUID. - -@prop create {function} -The constructor for the component. - -@prop name {string} -A human-readable name for the component. - -@prop contractID {string} -A human-readable string which will be used as the -[contract ID](https://developer.mozilla.org/en/Creating_XPCOM_Components/An_Overview_of_XPCOM#Contract_ID) -for the component. An XPCOM client will be able to use this value to access -the component. - -@returns {Factory} -See the documentation for the `Factory` class in this page. -</api> - -<api name="getClass"> -@function -Returns the factory object for the class specified by `contractID`. - -For example, given a registered XPCOM component which is identified with -the contract ID "@me.org/myComponent", we can access a factory and then -use it to instantiate the component in the following way: - - var xpcom = require("xpcom"); - var {Ci} = require("chrome"); - - var factory = xpcom.getClass("@me.org/myComponent", Ci.nsIFactory); - var helloWorld = factory.createInstance(null, Ci.nsISupports).wrappedJSObject; - console.log(helloWorld.hello()); - -@param contractID {string} -The -[contract ID](https://developer.mozilla.org/en/Creating_XPCOM_Components/An_Overview_of_XPCOM#Contract_ID) -for the component whose factory will be returned. - -@param [iid] {iid} -The interface type to be returned. These objects are usually accessed through -the `Components.interfaces`, or `Ci`, object. - -The methods of this interface will be callable on the returned factory object. -Usually you want this to be -[`Ci.nsIFactory`](https://developer.mozilla.org/En/nsIFactory), but if you know -a component has a factory that implements a more specific type of factory -interface, you can pass that interface here. If you don't include this option -only the methods of -[`nsISupports`](https://developer.mozilla.org/En/NsISupports) -will be callable, which is probably not what you want. - -@returns {object} -The factory object. The type of this object will depend on the value of the -`iid` argument. If no `iid` argument is specified it will be of type -[`nsISupports`](https://developer.mozilla.org/En/NsISupports). - -Note that this object is not a `Factory` object as defined by this module. -If you previously registered the component by calling the `register()` -function and you need to access the `Factory` object for the component, for -example to call the `Factory`'s `unregister()` method, you can do so by -getting the -[`wrappedJSObject`](https://developer.mozilla.org/en/wrappedJSObject) -property of the returned object: - - var factory = xpcom.getClass("@me.org/myComp", Ci.nsIFactory).wrappedJSObject; - factory.unregister(); - -</api> - -<api name="utils"> -@property {object} -The -[XPCOMUtils](https://developer.mozilla.org/en/JavaScript_code_modules/XPCOMUtils.jsm) -module. -</api> - -<api name="makeUuid"> -@function -Generates and returns a new -[UUID](https://developer.mozilla.org/en/Generating_GUIDs). - -Calling `toString()` on this object will yield the UUID in string form. -@returns {nsIDPtr} -</api> - -<api name="Factory"> -@class - -When a component is made available through XPCOM using the `register()` -function, `register()` returns a `Factory` object that can be used to -instantiate the component using its `createInstance()` function: - - var factory = require("xpcom").register({ - name: "My Component", - contractID: "@me.org/myComponent", - create: MyComponent - }); - - var {Ci} = require("chrome"); - var component = factory.createInstance(null, Ci.nsISupports).wrappedJSObject; - -In this example we haven't defined a custom interface ID for the component. -Instead we pass `Ci.nsISupports` as the interface ID, and use `wrappedJSObject` -to retrieve the component. For more details on this technique see the -[guide to building XPCOM components in JavaScript](https://developer.mozilla.org/en/How_to_Build_an_XPCOM_Component_in_Javascript). - -`Factory` also implements its own `unregister()` function, -which unregisters the component from XPCOM. - -<api name="createInstance"> -@method -Creates an instance of the component associated with this factory. - -@param outer {nsISupports} -This argument must be `null`, or the function throws -`Cr.NS_ERROR_NO_AGGREGATION`. - -@param iid {iid} -Interface identifier. These objects are usually accessed through -the `Components.interfaces`, or `Ci`, object. The methods of this -interface will be callable on the returned object. - -If the object implements an interface that's already defined in XPCOM, you -can pass that in here: - - var about = aboutFactory.createInstance(null, Ci.nsIAboutModule); - // You can now access the nsIAboutModule interface of the 'about' object - -If you will be getting the `wrappedJSObject` property from the returned -object to access its JavaScript implementation, pass `Ci.nsISupports` here: - - var custom = factory.createInstance(null, Ci.nsISupports).wrappedJSObject; - // You can now access the interface defined for the 'custom' object - -</api> - -<api name="QueryInterface"> -@method -This method is called automatically by XPCOM, so usually you don't need -to call it yourself. It returns the `Factory` object itself such that the -methods of the given interface are callable on it. - -@param interfaces {iid} -There are only two legal values for this parameter: `Ci.nsIFactory` and -`Ci.nsISupports`. Any other value will cause this method to throw -`Cr.NS_ERROR_NO_INTERFACE`. - -@returns {Factory} -</api> - -<api name="unregister"> -@method -Unregisters the factory's component. -</api> - -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/docs/xul-app.md b/tools/addon-sdk-1.4/packages/api-utils/docs/xul-app.md deleted file mode 100644 index 00379db..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/docs/xul-app.md +++ /dev/null @@ -1,72 +0,0 @@ -<!-- contributed by Drew Willcoxon [adw@mozilla.com] --> - -The `xul-app` module provides facilities for introspecting the application on -which your program is running. - -With the exception of `ids`, each of these properties exposes the attribute of -the same name on the [`nsIXULAppInfo`][nsIXULAppInfo] interface. For more -information, see the [MDC documentation][]. - -[nsIXULAppInfo]: http://mxr.mozilla.org/mozilla-central/source/xpcom/system/nsIXULAppInfo.idl -[MDC documentation]: https://developer.mozilla.org/en/nsIXULAppInfo - -<api name="ID"> -@property {string} - The GUID of the host application. For example, for Firefox this value is - `"{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"`. -</api> - -<api name="name"> -@property {string} - The host application name. For example, `"Firefox"`. -</api> - -<api name="version"> -@property {string} - The host application version. -</api> - -<api name="platformVersion"> -@property {string} - The Gecko/XULRunner platform version. -</api> - -<api name="ids"> -@property {object} - A mapping of application names to their IDs. For example, - `ids["Firefox"] == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"`. -</api> - -<api name="is"> -@function - Checks whether the host application is the given application. -@param name {string} - A host application name. -@returns {boolean} - True if the host application is `name` and false otherwise. -</api> - -<api name="isOneOf"> -@function - Checks whether the host application is one of the given applications. -@param names {array} - An array of host application names. -@returns {boolean} - True if the host application is one of the `names` and false otherwise. -</api> - -<api name="versionInRange"> -@function - Compares a given version to a version range. See the [MDC documentation](https://developer.mozilla.org/en/Toolkit_version_format#Comparing_versions) - for details on version comparisons. -@param version {string} - The version to compare. -@param lowInclusive {string} - The lower bound of the version range to compare. The range includes this - bound. -@param highExclusive {string} - The upper bound of the version range to compare. The range does not include - this bound. -@returns {boolean} - True if `version` falls in the given range and false otherwise. -</api> diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/api-utils.js b/tools/addon-sdk-1.4/packages/api-utils/lib/api-utils.js deleted file mode 100644 index 17d18cc..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/api-utils.js +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * Edward Lee <edilee@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// The possible return values of getTypeOf. -const VALID_TYPES = [ - "array", - "boolean", - "function", - "null", - "number", - "object", - "string", - "undefined", -]; - -/** - * Returns a function C that creates instances of privateCtor. C may be called - * with or without the new keyword. The prototype of each instance returned - * from C is C.prototype, and C.prototype is an object whose prototype is - * privateCtor.prototype. Instances returned from C will therefore be instances - * of both C and privateCtor. Additionally, the constructor of each instance - * returned from C is C. - * - * @param privateCtor - * A constructor. - * @return A function that makes new instances of privateCtor. - */ -exports.publicConstructor = function publicConstructor(privateCtor) { - function PublicCtor() { - let obj = { constructor: PublicCtor, __proto__: PublicCtor.prototype }; - memory.track(obj, privateCtor.name); - privateCtor.apply(obj, arguments); - return obj; - } - PublicCtor.prototype = { __proto__: privateCtor.prototype }; - return PublicCtor; -}; - -/** - * Returns a validated options dictionary given some requirements. If any of - * the requirements are not met, an exception is thrown. - * - * @param options - * An object, the options dictionary to validate. It's not modified. - * If it's null or otherwise falsey, an empty object is assumed. - * @param requirements - * An object whose keys are the expected keys in options. Any key in - * options that is not present in requirements is ignored. Each value - * in requirements is itself an object describing the requirements of - * its key. There are four optional keys in this object: - * map: A function that's passed the value of the key in options. - * map's return value is taken as the key's value in the final - * validated options, is, and ok. If map throws an exception - * it's caught and discarded, and the key's value is its value in - * options. - * is: An array containing any number of the typeof type names. If - * the key's value is none of these types, it fails validation. - * Arrays and null are identified by the special type names - * "array" and "null"; "object" will not match either. No type - * coercion is done. - * ok: A function that's passed the key's value. If it returns - * false, the value fails validation. - * msg: If the key's value fails validation, an exception is thrown. - * This string will be used as its message. If undefined, a - * generic message is used, unless is is defined, in which case - * the message will state that the value needs to be one of the - * given types. - * @return An object whose keys are those keys in requirements that are also in - * options and whose values are the corresponding return values of map - * or the corresponding values in options. Note that any keys not - * shared by both requirements and options are not in the returned - * object. - */ -exports.validateOptions = function validateOptions(options, requirements) { - options = options || {}; - let validatedOptions = {}; - let mapThrew = false; - - for (let [key, req] in Iterator(requirements)) { - let [optsVal, keyInOpts] = (key in options) ? - [options[key], true] : - [undefined, false]; - if (req.map) { - try { - optsVal = req.map(optsVal); - } - catch (err) { - mapThrew = true; - } - } - if (req.is) { - // Sanity check the caller's type names. - req.is.forEach(function (typ) { - if (VALID_TYPES.indexOf(typ) < 0) { - let msg = 'Internal error: invalid requirement type "' + typ + '".'; - throw new Error(msg); - } - }); - if (req.is.indexOf(getTypeOf(optsVal)) < 0) - throw requirementError(key, req); - } - if (req.ok && !req.ok(optsVal)) - throw requirementError(key, req); - - if (keyInOpts || (req.map && !mapThrew)) - validatedOptions[key] = optsVal; - } - - return validatedOptions; -}; - -exports.addIterator = function addIterator(obj, keysValsGenerator) { - obj.__iterator__ = function(keysOnly, keysVals) { - let keysValsIterator = keysValsGenerator.call(this); - - // "for (.. in ..)" gets only keys, "for each (.. in ..)" gets values, - // and "for (.. in Iterator(..))" gets [key, value] pairs. - let index = keysOnly ? 0 : 1; - while (true) - yield keysVals ? keysValsIterator.next() : keysValsIterator.next()[index]; - }; -}; - -// Similar to typeof, except arrays and null are identified by "array" and -// "null", not "object". -let getTypeOf = exports.getTypeOf = function getTypeOf(val) { - let typ = typeof(val); - if (typ === "object") { - if (!val) - return "null"; - if (Array.isArray(val)) - return "array"; - } - return typ; -} - -// Returns a new Error with a nice message. -function requirementError(key, requirement) { - let msg = requirement.msg; - if (!msg) { - msg = 'The option "' + key + '" '; - msg += requirement.is ? - "must be one of the following types: " + requirement.is.join(", ") : - "is invalid."; - } - return new Error(msg); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/app-strings.js b/tools/addon-sdk-1.4/packages/api-utils/lib/app-strings.js deleted file mode 100644 index 120c26e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/app-strings.js +++ /dev/null @@ -1,95 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is String Bundle. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Myk Melez <myk@mozilla.org> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -const apiUtils = require("./api-utils"); - -/** - * A bundle of strings. - * - * @param url {String} - * the URL of the string bundle - */ -exports.StringBundle = apiUtils.publicConstructor(function StringBundle(url) { - - let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle(url); - - this.__defineGetter__("url", function () url); - - /** - * Get a string from the bundle. - * - * @param name {String} - * the name of the string to get - * @param args {array} [optional] - * an array of arguments that replace occurrences of %S in the string - * - * @returns {String} the value of the string - */ - this.get = function strings_get(name, args) { - try { - if (args) - return stringBundle.formatStringFromName(name, args, args.length); - else - return stringBundle.GetStringFromName(name); - } - catch(ex) { - // f.e. "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) - // [nsIStringBundle.GetStringFromName]" - throw new Error("String '" + name + "' could not be retrieved from the " + - "bundle due to an unknown error (it doesn't exist?)."); - } - }, - - /** - * Iterate the strings in the bundle. - * - */ - apiUtils.addIterator( - this, - function keysValsGen() { - let enumerator = stringBundle.getSimpleEnumeration(); - while (enumerator.hasMoreElements()) { - let elem = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); - yield [elem.key, elem.value]; - } - } - ); -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/array.js b/tools/addon-sdk-1.4/packages/api-utils/lib/array.js deleted file mode 100644 index a41acdd..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/array.js +++ /dev/null @@ -1,102 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -/** - * Returns `true` if given `array` contain given `element` or `false` - * otherwise. - * @param {Array} array - * Target array. - * @param {Object|String|Number|Boolean} element - * Element being looked up. - * @returns {Boolean} - */ -var has = exports.has = function has(array, element) { - // shorter and faster equivalent of `array.indexOf(element) >= 0` - return !!~array.indexOf(element); -}; - -/** - * Adds given `element` to the given `array` if it does not contain it yet. - * `true` is returned if element was added otherwise `false` is returned. - * @param {Array} array - * Target array. - * @param {Object|String|Number|Boolean} element - * Element to be added. - * @returns {Boolean} - */ -var add = exports.add = function add(array, element) { - var result; - if ((result = !has(array, element))) - array.push(element); - - return result; -}; - -/** - * Removes first occurrence of the given `element` from the given `array`. If - * `array` does not contain given `element` `false` is returned otherwise - * `true` is returned. - * @param {Array} array - * Target array. - * @param {Object|String|Number|Boolean} element - * Element to be removed. - * @returns {Boolean} - */ -exports.remove = function remove(array, element) { - var result; - if ((result = has(array, element))) - array.splice(array.indexOf(element), 1); - - return result; -}; - -/** - * Produces a duplicate-free version of the given `array`. - * @param {Array} array - * Source array. - * @returns {Array} - */ -exports.unique = function unique(array) { - var value = []; - return array.forEach(function(element) { - add(value, element); - }); - return value; -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/byte-streams.js b/tools/addon-sdk-1.4/packages/api-utils/lib/byte-streams.js deleted file mode 100644 index b44357e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/byte-streams.js +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -exports.ByteReader = ByteReader; -exports.ByteWriter = ByteWriter; - -const {Cc, Ci} = require("chrome"); - -// This just controls the maximum number of bytes we read in at one time. -const BUFFER_BYTE_LEN = 0x8000; - -function ByteReader(inputStream) { - const self = this; - - let stream = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - stream.setInputStream(inputStream); - - let manager = new StreamManager(this, stream); - - this.read = function ByteReader_read(numBytes) { - manager.ensureOpened(); - if (typeof(numBytes) !== "number") - numBytes = Infinity; - - let data = ""; - let read = 0; - try { - while (true) { - let avail = stream.available(); - let toRead = Math.min(numBytes - read, avail, BUFFER_BYTE_LEN); - if (toRead <= 0) - break; - data += stream.readBytes(toRead); - read += toRead; - } - } - catch (err) { - throw new Error("Error reading from stream: " + err); - } - - return data; - }; -} - -function ByteWriter(outputStream) { - const self = this; - - let stream = Cc["@mozilla.org/binaryoutputstream;1"]. - createInstance(Ci.nsIBinaryOutputStream); - stream.setOutputStream(outputStream); - - let manager = new StreamManager(this, stream); - - this.write = function ByteWriter_write(str) { - manager.ensureOpened(); - try { - stream.writeBytes(str, str.length); - } - catch (err) { - throw new Error("Error writing to stream: " + err); - } - }; -} - - -// This manages the lifetime of stream, a ByteReader or ByteWriter. It defines -// closed and close() on stream and registers an unload listener that closes -// rawStream if it's still opened. It also provides ensureOpened(), which -// throws an exception if the stream is closed. -function StreamManager(stream, rawStream) { - const self = this; - this.rawStream = rawStream; - this.opened = true; - - stream.__defineGetter__("closed", function stream_closed() { - return !self.opened; - }); - - stream.close = function stream_close() { - self.ensureOpened(); - self.unload(); - }; - - require("./unload").ensure(this); -} - -StreamManager.prototype = { - ensureOpened: function StreamManager_ensureOpened() { - if (!this.opened) - throw new Error("The stream is closed and cannot be used."); - }, - unload: function StreamManager_unload() { - this.rawStream.close(); - this.opened = false; - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/channel.js b/tools/addon-sdk-1.4/packages/api-utils/lib/channel.js deleted file mode 100644 index b7f1e61..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/channel.js +++ /dev/null @@ -1,67 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const { jetpackID } = require('@packaging'); - -// TODO: Create a bug report and remove this workaround once it's fixed. -// Only function needs defined in the context of the message manager window -// can be registered via `addMessageListener`. -function listener(callee) { - return function listener() { return callee.apply(this, arguments); }; -} -function messageListener(scope, callee) { - return scope ? scope.eval('(' + listener + ')')(callee) : callee -} - -exports.channel = function channel(scope, messageManager, address, raw) { - address = jetpackID + ':' + address - return { - input: function input(next, stop) { - let listener = messageListener(scope, function onMessage(message) { - if (false === next(raw ? message : message.json)) - messageManager.removeMessageListener(address, listener); - }); - messageManager.addMessageListener(address, listener); - }, - output: function output(data) { - messageManager.sendAsyncMessage(address, data); - }, - sync: !messageManager.sendSyncMessage ? null : function sync(data) { - messageManager.sendSyncMessage(address, data); - } - }; -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/collection.js b/tools/addon-sdk-1.4/packages/api-utils/lib/collection.js deleted file mode 100644 index 5525a5a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/collection.js +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -exports.Collection = Collection; - -/** - * Adds a collection property to the given object. Setting the property to a - * scalar value empties the collection and adds the value. Setting it to an - * array empties the collection and adds all the items in the array. - * - * @param obj - * The property will be defined on this object. - * @param propName - * The name of the property. - * @param array - * If given, this will be used as the collection's backing array. - */ -exports.addCollectionProperty = function addCollProperty(obj, propName, array) { - array = array || []; - let publicIface = new Collection(array); - - obj.__defineSetter__(propName, function (itemOrItems) { - array.splice(0, array.length); - publicIface.add(itemOrItems); - }); - - obj.__defineGetter__(propName, function () { - return publicIface; - }); -}; - -/** - * A collection is ordered, like an array, but its items are unique, like a set. - * - * @param array - * The collection is backed by an array. If this is given, it will be - * used as the backing array. This way the caller can fully control the - * collection. Otherwise a new empty array will be used, and no one but - * the collection will have access to it. - */ -function Collection(array) { - array = array || []; - - /** - * Provides iteration over the collection. Items are yielded in the order - * they were added. - */ - this.__iterator__ = function Collection___iterator__() { - let items = array.slice(); - for (let i = 0; i < items.length; i++) - yield items[i]; - }; - - /** - * The number of items in the collection. - */ - this.__defineGetter__("length", function Collection_get_length() { - return array.length; - }); - - /** - * Adds a single item or an array of items to the collection. Any items - * already contained in the collection are ignored. - * - * @param itemOrItems - * An item or array of items. - * @return The collection. - */ - this.add = function Collection_add(itemOrItems) { - let items = toArray(itemOrItems); - for (let i = 0; i < items.length; i++) { - let item = items[i]; - if (array.indexOf(item) < 0) - array.push(item); - } - return this; - }; - - /** - * Removes a single item or an array of items from the collection. Any items - * not contained in the collection are ignored. - * - * @param itemOrItems - * An item or array of items. - * @return The collection. - */ - this.remove = function Collection_remove(itemOrItems) { - let items = toArray(itemOrItems); - for (let i = 0; i < items.length; i++) { - let idx = array.indexOf(items[i]); - if (idx >= 0) - array.splice(idx, 1); - } - return this; - }; -}; - -function toArray(itemOrItems) { - let isArr = itemOrItems && - itemOrItems.constructor && - itemOrItems.constructor.name === "Array"; - return isArr ? itemOrItems : [itemOrItems]; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/content.js b/tools/addon-sdk-1.4/packages/api-utils/lib/content.js deleted file mode 100644 index a46a5ff..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/content.js +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -exports.Loader = require('./content/loader').Loader; -exports.Symbiont = require('./content/symbiont').Symbiont; -exports.Worker = require('./content/worker').Worker; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/content/loader.js b/tools/addon-sdk-1.4/packages/api-utils/lib/content/loader.js deleted file mode 100644 index 25bc651..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/content/loader.js +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { EventEmitter } = require('../events'); -const { validateOptions, getTypeOf } = require('../api-utils'); -const { URL, toFilename } = require('../url'); -const file = require('../file'); - -// map of property validations -const valid = { - contentURL: { - ok: function (value) { - try { - URL(value); - } - catch(e) { - return false; - } - return true; - }, - msg: 'The `contentURL` option must be a valid URL.' - }, - contentScriptFile: { - is: ['undefined', 'null', 'string', 'array'], - map: function(value) 'undefined' === getTypeOf(value) ? null : value, - ok: function(value) { - if (getTypeOf(value) === 'array') { - // Make sure every item is a local file URL. - return value.every(function (item) { - try { - toFilename(item); - return true; - } - catch(e) { - return false; - } - }); - } - return true; - }, - msg: 'The `contentScriptFile` option must be a local file URL or an array of' - + 'URLs.' - }, - contentScript: { - is: ['undefined', 'null', 'string', 'array'], - map: function(value) 'undefined' === getTypeOf(value) ? null : value, - ok: function(value) 'array' !== getTypeOf(value) ? true : - value.every(function(item) 'string' === getTypeOf(item)) - , - msg: 'The script option must be a string or an array of strings.' - }, - contentScriptWhen: { - is: ['string'], - ok: function(value) ['start', 'ready', 'end'].indexOf(value) >= 0, - map: function(value) { - return value || 'end'; - }, - msg: 'The `contentScriptWhen` option must be either "start", "ready" or "end".' - } -}; -exports.validationAttributes = valid; - -/** - * Shortcut function to validate property with validation. - * @param {Object|Number|String} suspect - * value to validate - * @param {Object} validation - * validation rule passed to `api-utils` - */ -function validate(suspect, validation) validateOptions( - { $: suspect }, - { $: validation } -).$ - -function Allow(script) ({ - get script() script, - set script(value) script = !!value -}) - -/** - * Trait is intended to be used in some composition. It provides set of core - * properties and bounded validations to them. Trait is useful for all the - * compositions providing high level APIs for interaction with content. - * Property changes emit `"propertyChange"` events on instances. - */ -const Loader = EventEmitter.compose({ - /** - * Permissions for the content, with the following keys: - * @property {Object} [allow = { script: true }] - * @property {Boolean} [allow.script = true] - * Whether or not to execute script in the content. Defaults to true. - */ - get allow() this._allow || (this._allow = Allow(true)), - set allow(value) this.allow.script = value && value.script, - _allow: null, - /** - * The content to load. Either a string of HTML or a URL. - * @type {String} - */ - get contentURL() this._contentURL, - set contentURL(value) { - value = validate(value, valid.contentURL); - if (this._contentURL != value) { - this._emit('propertyChange', { - contentURL: this._contentURL = value - }); - } - }, - _contentURL: null, - /** - * When to load the content scripts. - * Possible values are "end" (default), which loads them once all page - * contents have been loaded, "ready", which loads them once DOM nodes are - * ready (ie like DOMContentLoaded event), and "start", which loads them once - * the `window` object for the page has been created, but before any scripts - * specified by the page have been loaded. - * Property change emits `propertyChange` event on instance with this key - * and new value. - * @type {'start'|'ready'|'end'} - */ - get contentScriptWhen() this._contentScriptWhen, - set contentScriptWhen(value) { - value = validate(value, valid.contentScriptWhen); - if (value !== this._contentScriptWhen) { - this._emit('propertyChange', { - contentScriptWhen: this._contentScriptWhen = value - }); - } - }, - _contentScriptWhen: 'end', - /** - * The URLs of content scripts. - * Property change emits `propertyChange` event on instance with this key - * and new value. - * @type {String[]} - */ - get contentScriptFile() this._contentScriptFile, - set contentScriptFile(value) { - value = validate(value, valid.contentScriptFile); - if (value != this._contentScriptFile) { - this._emit('propertyChange', { - contentScriptFile: this._contentScriptFile = value - }); - } - }, - _contentScriptFile: null, - /** - * The texts of content script. - * Property change emits `propertyChange` event on instance with this key - * and new value. - * @type {String|undefined} - */ - get contentScript() this._contentScript, - set contentScript(value) { - value = validate(value, valid.contentScript); - if (value != this._contentScript) { - this._emit('propertyChange', { - contentScript: this._contentScript = value - }); - } - }, - _contentScript: null -}); -exports.Loader = Loader; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/content/symbiont.js b/tools/addon-sdk-1.4/packages/api-utils/lib/content/symbiont.js deleted file mode 100644 index d6dbf38..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/content/symbiont.js +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Myk Melez <myk@mozilla.org> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Worker } = require('./worker'); -const { Loader } = require('./loader'); -const hiddenFrames = require('../hidden-frame'); -const observers = require('../observer-service'); -const unload = require('../unload'); - -/** - * This trait is layered on top of `Worker` and in contrast to symbiont - * Worker constructor requires `content` option that represents content - * that will be loaded in the provided frame, if frame is not provided - * Worker will create hidden one. - */ -const Symbiont = Worker.resolve({ - constructor: '_initWorker', - destroy: '_workerDestroy' - }).compose(Loader, { - - /** - * The constructor requires all the options that are required by - * `require('content').Worker` with the difference that the `frame` option - * is optional. If `frame` is not provided, `contentURL` is expected. - * @param {Object} options - * @param {String} options.contentURL - * URL of a content to load into `this._frame` and create worker for. - * @param {Element} [options.frame] - * iframe element that is used to load `options.contentURL` into. - * if frame is not provided hidden iframe will be created. - */ - constructor: function Symbiont(options) { - options = options || {}; - - if ('contentURL' in options) - this.contentURL = options.contentURL; - if ('contentScriptWhen' in options) - this.contentScriptWhen = options.contentScriptWhen; - if ('contentScriptFile' in options) - this.contentScriptFile = options.contentScriptFile; - if ('contentScript' in options) - this.contentScript = options.contentScript; - if ('allow' in options) - this.allow = options.allow; - if ('onError' in options) - this.on('error', options.onError); - if ('onMessage' in options) - this.on('message', options.onMessage); - if ('frame' in options) { - this._initFrame(options.frame); - } - else { - let self = this; - this._hiddenFrame = hiddenFrames.HiddenFrame({ - onReady: function onFrame() { - self._initFrame(this.element); - } - }); - hiddenFrames.add(this._hiddenFrame); - } - - unload.ensure(this._public, "destroy"); - }, - - destroy: function destroy() { - this._workerDestroy(); - this._unregisterListener(); - this._frame = null; - if (this._hiddenFrame) { - hiddenFrames.remove(this._hiddenFrame); - this._hiddenFrame = null; - } - }, - - /** - * XUL iframe or browser elements with attribute `type` being `content`. - * Used to create `ContentSymbiont` from. - * @type {nsIFrame|nsIBrowser} - */ - _frame: null, - - /** - * Listener to the `'frameReady"` event (emitted when `iframe` is ready). - * Removes listener, sets right permissions to the frame and loads content. - */ - _initFrame: function _initFrame(frame) { - if (this._loadListener) - this._unregisterListener(); - - this._frame = frame; - frame.docShell.allowJavascript = this.allow.script; - frame.setAttribute("src", this._contentURL); - - // Inject `addon` object in document if we load a document from - // one of our addon folder and if no content script are defined. bug 612726 - let isDataResource = - typeof this._contentURL == "string" && - this._contentURL.indexOf(require("@packaging").uriPrefix) == 0; - let hasContentScript = - (Array.isArray(this.contentScript) ? this.contentScript.length > 0 - : !!this.contentScript) || - (Array.isArray(this.contentScriptFile) ? this.contentScriptFile.length > 0 - : !!this.contentScriptFile); - // If we have to inject `addon` we have to do it before document - // script execution, so during `start`: - this._injectInDocument = isDataResource && !hasContentScript; - if (this._injectInDocument) - this.contentScriptWhen = "start"; - - if ((frame.contentDocument.readyState == "complete" || - (frame.contentDocument.readyState == "interactive" && - this.contentScriptWhen != 'end' )) && - frame.contentDocument.location == this._contentURL) { - // In some cases src doesn't change and document is already ready - // (for ex: when the user moves a widget while customizing toolbars.) - this._onInit(); - return; - } - - let self = this; - - if ('start' == this.contentScriptWhen) { - this._loadEvent = 'start'; - observers.add('document-element-inserted', - this._loadListener = function onStart(doc) { - - let window = doc.defaultView; - if (window && window == frame.contentWindow) { - self._unregisterListener(); - self._onInit(); - } - - }); - return; - } - - let eventName = 'end' == this.contentScriptWhen ? 'load' : 'DOMContentLoaded'; - let self = this; - this._loadEvent = eventName; - frame.addEventListener(eventName, - this._loadListener = function _onReady(event) { - - if (event.target != frame.contentDocument) - return; - self._unregisterListener(); - - self._onInit(); - - }, true); - - }, - - /** - * Unregister listener that watchs for document being ready to be injected. - * This listener is registered in `Symbiont._initFrame`. - */ - _unregisterListener: function _unregisterListener() { - if (!this._loadListener) - return; - if (this._loadEvent == "start") { - observers.remove('document-element-inserted', this._loadListener); - } - else { - this._frame.removeEventListener(this._loadEvent, this._loadListener, - true); - } - this._loadListener = null; - }, - - /** - * Called by Symbiont itself when the frame is ready to load - * content scripts according to contentScriptWhen. Overloaded by Panel. - */ - _onInit: function () { - this._initWorker({ window: this._frame.contentWindow }); - } - -}); -exports.Symbiont = Symbiont; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/content/worker.js b/tools/addon-sdk-1.4/packages/api-utils/lib/content/worker.js deleted file mode 100644 index 6ded506..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/content/worker.js +++ /dev/null @@ -1,662 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Trait } = require('../traits'); -const { EventEmitter, EventEmitterTrait } = require('../events'); -const { Ci, Cu, Cc } = require('chrome'); -const timer = require('../timer'); -const { toFilename } = require('../url'); -const file = require('../file'); -const unload = require('../unload'); -const observers = require('../observer-service'); -const { Cortex } = require('../cortex'); -const { Enqueued } = require('../utils/function'); -const self = require("self"); -const scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Ci.mozIJSSubScriptLoader); - -const CONTENT_PROXY_URL = self.data.url("content-proxy.js"); - -const JS_VERSION = '1.8'; - -const ERR_DESTROYED = - "The page has been destroyed and can no longer be used."; - -/** - * This key is not exported and should only be used for proxy tests. - * The following `PRIVATE_KEY` is used in addon module scope in order to tell - * Worker API to expose `UNWRAP_ACCESS_KEY` in content script. - * This key allows test-content-proxy.js to unwrap proxy with valueOf: - * let xpcWrapper = proxyWrapper.valueOf(UNWRAP_ACCESS_KEY); - */ -const PRIVATE_KEY = {}; - -function ensureArgumentsAreJSON(array, window) { - // JSON.stringify is buggy with cross-sandbox values, - // it may return "{}" on functions. Use a replacer to match them correctly. - function replacer(k, v) { - return typeof v === "function" ? undefined : v; - } - // If a window is given, we use its `JSON.parse` object in order to - // create JS objects for its compartments (See bug 714891) - let parse = JSON.parse; - if (window) { - // As we can't directly rely on `window.wrappedJSObject.JSON`, we create - // a temporary sandbox in order to get access to a safe `JSON` object: - parse = Cu.Sandbox(window).JSON.parse; - } - return parse(JSON.stringify(array, replacer)); -} - -/** - * Extended `EventEmitter` allowing us to emit events asynchronously. - */ -const AsyncEventEmitter = EventEmitter.compose({ - /** - * Emits event in the next turn of event loop. - */ - _asyncEmit: function _asyncEmit() { - timer.setTimeout(function emitter(emit, scope, params) { - emit.apply(scope, params); - }, 0, this._emit, this, arguments) - } -}); - -/** - * Local trait providing implementation of the workers global scope. - * Used to configure global object in the sandbox. - * @see http://www.w3.org/TR/workers/#workerglobalscope - */ -const WorkerGlobalScope = AsyncEventEmitter.compose({ - on: Trait.required, - _removeAllListeners: Trait.required, - - // wrapped functions from `'timer'` module. - // Wrapper adds `try catch` blocks to the callbacks in order to - // emit `error` event on a symbiont if exception is thrown in - // the Worker global scope. - // @see http://www.w3.org/TR/workers/#workerutils - - // List of all living timeouts/intervals - _timers: null, - - setTimeout: function setTimeout(callback, delay) { - let params = Array.slice(arguments, 2); - let id = timer.setTimeout(function(self) { - try { - delete self._timers[id]; - callback.apply(null, params); - } catch(e) { - self._addonWorker._asyncEmit('error', e); - } - }, delay, this); - this._timers[id] = true; - return id; - }, - clearTimeout: function clearTimeout(id){ - delete this._timers[id]; - return timer.clearTimeout(id); - }, - - setInterval: function setInterval(callback, delay) { - let params = Array.slice(arguments, 2); - let id = timer.setInterval(function(self) { - try { - callback.apply(null, params); - } catch(e) { - self._addonWorker._asyncEmit('error', e); - } - }, delay, this); - this._timers[id] = true; - return id; - }, - clearInterval: function clearInterval(id) { - delete this._timers[id]; - return timer.clearInterval(id); - }, - - /** - * `onMessage` function defined in the global scope of the worker context. - */ - get _onMessage() this.__onMessage, - set _onMessage(value) { - let listener = this.__onMessage; - if (listener && value !== listener) { - this.removeListener('message', listener); - this.__onMessage = undefined; - } - if (value) - this.on('message', this.__onMessage = value); - }, - __onMessage: undefined, - - /** - * Function for sending data to the addon side. - * Validates that data is a `JSON` or primitive value and emits - * 'message' event on the worker in the next turn of the event loop. - * _Later this will be sending data across process boundaries._ - * @param {JSON|String|Number|Boolean} data - */ - postMessage: function postMessage(data) { - if (!this._addonWorker) - throw new Error(ERR_DESTROYED); - this._addonWorker._asyncEmit('message', ensureArgumentsAreJSON(data)); - }, - - /** - * EventEmitter, that behaves (calls listeners) asynchronously. - * A way to send customized messages to / from the worker. - * Events from in the worker can be observed / emitted via self.on / self.emit - */ - get port() this._port._public, - - /** - * Same object than this.port but private API. - * Allow access to _asyncEmit, in order to send event to port. - */ - _port: null, - - /** - * Alias to the global scope in the context of worker. Similar to - * `window` concept. - */ - get self() this._public, - - /** - * Configures sandbox and loads content scripts into it. - * @param {Worker} worker - * content worker - */ - constructor: function WorkerGlobalScope(worker) { - this._addonWorker = worker; - - // Hack in order to allow addon worker to access _asyncEmit - // as this is the private object of WorkerGlobalScope - worker._contentWorker = this; - - // create an event emitter that receive and send events from/to the addon - let contentWorker = this; - this._port = EventEmitterTrait.create({ - emit: function () { - let addonWorker = contentWorker._addonWorker; - if (!addonWorker) - throw new Error(ERR_DESTROYED); - addonWorker._onContentScriptEvent.apply(addonWorker, arguments); - } - }); - // create emit that executes in next turn of event loop. - this._port._asyncEmit = Enqueued(this._port._emit); - // expose wrapped port, that exposes only public properties. - this._port._public = Cortex(this._port); - - // We receive an unwrapped window, with raw js access - let window = worker._window; - - let proto = window; - let proxySandbox = null; - // Build content proxies only if the document has a non-system principal - if (window.wrappedJSObject) { - // Instantiate the proxy code in another Sandbox in order to prevent - // content script from polluting globals used by proxy code - proxySandbox = Cu.Sandbox(window, { - wantXrays: true - }); - proxySandbox.console = console; - // Execute the proxy code - scriptLoader.loadSubScript(CONTENT_PROXY_URL, proxySandbox); - // Get a reference of the window's proxy - proto = proxySandbox.create(window); - } - - // Create the sandbox and bind it to window in order for content scripts to - // have access to all standard globals (window, document, ...) - let sandbox = this._sandbox = new Cu.Sandbox(window, { - sandboxPrototype: proto, - wantXrays: true - }); - Object.defineProperties(sandbox, { - // We need "this === window === top" to be true in toplevel scope: - window: { get: function() sandbox }, - top: { get: function() sandbox }, - // Use the Greasemonkey naming convention to provide access to the - // unwrapped window object so the content script can access document - // JavaScript values. - // NOTE: this functionality is experimental and may change or go away - // at any time! - unsafeWindow: { get: function () window.wrappedJSObject } - }); - - // Internal feature that is only used by SDK tests: - // Expose unlock key to content script context. - // See `PRIVATE_KEY` definition for more information. - if (proxySandbox && worker._expose_key) - sandbox.UNWRAP_ACCESS_KEY = proxySandbox.UNWRAP_ACCESS_KEY; - // Initialize timer lists - this._timers = {}; - - let publicAPI = this._public; - - // List of content script globals: - let keys = ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', - 'self']; - for each (let key in keys) { - Object.defineProperty( - sandbox, key, Object.getOwnPropertyDescriptor(publicAPI, key) - ); - } - let self = this; - Object.defineProperties(sandbox, { - onMessage: { - get: function() self._onMessage, - set: function(value) { - console.warn("The global `onMessage` function in content scripts " + - "is deprecated in favor of the `self.on()` function. " + - "Replace `onMessage = function (data){}` definitions " + - "with calls to `self.on('message', function (data){})`. " + - "For more info on `self.on`, see " + - "<https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/addon-development/web-content.html>."); - self._onMessage = value; - }, - configurable: true - }, - console: { value: console, configurable: true }, - - // Deprecated use of on/postMessage from globals - on: { - value: function () { - console.warn("The global `on()` function in content scripts is " + - "deprecated in favor of the `self.on()` function, " + - "which works the same. Replace calls to `on()` with " + - "calls to `self.on()`" + - "For more info on `self.on`, see " + - "<https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/addon-development/web-content.html>."); - publicAPI.on.apply(publicAPI, arguments); - }, - configurable: true - }, - postMessage: { - value: function () { - console.warn("The global `postMessage()` function in content " + - "scripts is deprecated in favor of the " + - "`self.postMessage()` function, which works the same. " + - "Replace calls to `postMessage()` with calls to " + - "`self.postMessage()`." + - "For more info on `self.on`, see " + - "<https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/addon-development/web-content.html>."); - publicAPI.postMessage.apply(publicAPI, arguments); - }, - configurable: true - } - }); - - // Temporary fix for test-widget, that pass self.postMessage to proxy code - // that first try to access to `___proxy` and then call it through `apply`. - // We need to move function given to content script to a sandbox - // with same principal than the content script. - // In the meantime, we need to allow such access explicitly - // by using `__exposedProps__` property, documented here: - // https://developer.mozilla.org/en/XPConnect_wrappers - sandbox.self.postMessage.__exposedProps__ = { - ___proxy: 'rw', - apply: 'rw' - } - - // Inject `addon` global into target document if document is trusted, - // `addon` in document is equivalent to `self` in content script. - if (worker._injectInDocument) { - let win = window.wrappedJSObject ? window.wrappedJSObject : window; - Object.defineProperty(win, "addon", { - get: function () publicAPI - } - ); - } - - // The order of `contentScriptFile` and `contentScript` evaluation is - // intentional, so programs can load libraries like jQuery from script URLs - // and use them in scripts. - let contentScriptFile = ('contentScriptFile' in worker) ? worker.contentScriptFile - : null, - contentScript = ('contentScript' in worker) ? worker.contentScript : null; - - if (contentScriptFile) { - if (Array.isArray(contentScriptFile)) - this._importScripts.apply(this, contentScriptFile); - else - this._importScripts(contentScriptFile); - } - if (contentScript) { - this._evaluate( - Array.isArray(contentScript) ? contentScript.join(';\n') : contentScript - ); - } - }, - _destructor: function _destructor() { - this._removeAllListeners(); - // Unregister all setTimeout/setInterval - // We can use `clearTimeout` for both setTimeout/setInterval - // as internal implementation of timer module use same method for both. - for (let id in this._timers) - timer.clearTimeout(id); - this._sandbox = null; - this._addonWorker = null; - this.__onMessage = undefined; - }, - - /** - * JavaScript sandbox where all the content scripts are evaluated. - * {Sandbox} - */ - _sandbox: null, - - /** - * Reference to the addon side of the worker. - * @type {Worker} - */ - _addonWorker: null, - - /** - * Evaluates code in the sandbox. - * @param {String} code - * JavaScript source to evaluate. - * @param {String} [filename='javascript:' + code] - * Name of the file - */ - _evaluate: function(code, filename) { - filename = filename || 'javascript:' + code; - try { - Cu.evalInSandbox(code, this._sandbox, JS_VERSION, filename, 1); - } - catch(e) { - this._addonWorker._asyncEmit('error', e); - } - }, - /** - * Imports scripts to the sandbox by reading files under urls and - * evaluating its source. If exception occurs during evaluation - * `"error"` event is emitted on the worker. - * This is actually an analog to the `importScript` method in web - * workers but in our case it's not exposed even though content - * scripts may be able to do it synchronously since IO operation - * takes place in the UI process. - */ - _importScripts: function _importScripts(url) { - let urls = Array.slice(arguments, 0); - for each (let contentScriptFile in urls) { - try { - let filename = toFilename(contentScriptFile); - this._evaluate(file.read(filename), filename); - } - catch(e) { - this._addonWorker._asyncEmit('error', e) - } - } - } -}); - -/** - * Message-passing facility for communication between code running - * in the content and add-on process. - * @see https://jetpack.mozillalabs.com/sdk/latest/docs/#module/api-utils/content/worker - */ -const Worker = AsyncEventEmitter.compose({ - on: Trait.required, - _asyncEmit: Trait.required, - _removeAllListeners: Trait.required, - - /** - * Sends a message to the worker's global scope. Method takes single - * argument, which represents data to be sent to the worker. The data may - * be any primitive type value or `JSON`. Call of this method asynchronously - * emits `message` event with data value in the global scope of this - * symbiont. - * - * `message` event listeners can be set either by calling - * `self.on` with a first argument string `"message"` or by - * implementing `onMessage` function in the global scope of this worker. - * @param {Number|String|JSON} data - */ - postMessage: function postMessage(data) { - if (!this._contentWorker) - throw new Error(ERR_DESTROYED); - this._contentWorker._asyncEmit('message', - ensureArgumentsAreJSON(data, this._window)); - }, - - /** - * EventEmitter, that behaves (calls listeners) asynchronously. - * A way to send customized messages to / from the worker. - * Events from in the worker can be observed / emitted via - * worker.on / worker.emit. - */ - get port() { - // We generate dynamically this attribute as it needs to be accessible - // before Worker.constructor gets called. (For ex: Panel) - - // create an event emitter that receive and send events from/to the worker - let self = this; - this._port = EventEmitterTrait.create({ - emit: function () self._emitEventToContent(arguments) - }); - // create emit that executes in next turn of event loop. - this._port._asyncEmit = Enqueued(this._port._emit); - // expose wrapped port, that exposes only public properties: - // We need to destroy this getter in order to be able to set the - // final value. We need to update only public port attribute as we never - // try to access port attribute from private API. - delete this._public.port; - this._public.port = Cortex(this._port); - // Replicate public port to the private object - delete this.port; - this.port = this._public.port; - - return this._port; - }, - - /** - * Same object than this.port but private API. - * Allow access to _asyncEmit, in order to send event to port. - */ - _port: null, - - /** - * Emit a custom event to the content script, - * i.e. emit this event on `self.port` - */ - _emitEventToContent: function _emitEventToContent(args) { - // We need to save events that are emitted before the worker is - // initialized - if (!this._inited) { - this._earlyEvents.push(args); - return; - } - - // We throw exception when the worker has been destroyed - if (!this._contentWorker) { - throw new Error(ERR_DESTROYED); - } - - let scope = this._contentWorker._port; - // Ensure that we pass only JSON values - let array = Array.prototype.slice.call(args); - scope._asyncEmit.apply(scope, ensureArgumentsAreJSON(array, this._window)); - }, - - // Is worker connected to the content worker (i.e. WorkerGlobalScope) ? - _inited: false, - - // List of custom events fired before worker is initialized - get _earlyEvents() { - delete this._earlyEvents; - this._earlyEvents = []; - return this._earlyEvents; - }, - - constructor: function Worker(options) { - options = options || {}; - - if ('window' in options) - this._window = options.window; - if ('contentScriptFile' in options) - this.contentScriptFile = options.contentScriptFile; - if ('contentScript' in options) - this.contentScript = options.contentScript; - if ('onError' in options) - this.on('error', options.onError); - if ('onMessage' in options) - this.on('message', options.onMessage); - if ('onDetach' in options) - this.on('detach', options.onDetach); - - // Internal feature that is only used by SDK unit tests. - // See `PRIVATE_KEY` definition for more information. - if ('exposeUnlockKey' in options && options.exposeUnlockKey === PRIVATE_KEY) - this._expose_key = true; - - // Track document unload to destroy this worker. - // We can't watch for unload event on page's window object as it - // prevents bfcache from working: - // https://developer.mozilla.org/En/Working_with_BFCache - this._windowID = this._window. - QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils). - currentInnerWindowID; - observers.add("inner-window-destroyed", - this._documentUnload = this._documentUnload.bind(this)); - - unload.ensure(this._public, "destroy"); - - // Ensure that worker._port is initialized for contentWorker to be able - // to send use event during WorkerGlobalScope(this) - this.port; - - // will set this._contentWorker pointing to the private API: - WorkerGlobalScope(this); - - // Mainly enable worker.port.emit to send event to the content worker - this._inited = true; - - // Flush all events that have been fired before the worker is initialized. - this._earlyEvents.forEach((function (args) this._emitEventToContent(args)). - bind(this)); - }, - - _documentUnload: function _documentUnload(subject, topic, data) { - let innerWinID = subject.QueryInterface(Ci.nsISupportsPRUint64).data; - if (innerWinID != this._windowID) return false; - this._workerCleanup(); - return true; - }, - - get url() { - // this._window will be null after detach - return this._window ? this._window.document.location.href : null; - }, - - get tab() { - if (this._window) { - let tab = require("../tabs/tab"); - // this._window will be null after detach - return tab.getTabForWindow(this._window); - } - return null; - }, - - /** - * Tells content worker to unload itself and - * removes all the references from itself. - */ - destroy: function destroy() { - this._workerCleanup(); - this._removeAllListeners('message'); - this._removeAllListeners('error'); - this._removeAllListeners('detach'); - }, - - /** - * Remove all internal references to the attached document - * Tells _port to unload itself and removes all the references from itself. - */ - _workerCleanup: function _workerCleanup() { - // maybe unloaded before content side is created - // As Symbiont call worker.constructor on document load - if (this._contentWorker) - this._contentWorker._destructor(); - this._contentWorker = null; - this._window = null; - // This method may be called multiple times, - // avoid dispatching `detach` event more than once - if (this._windowID) { - this._windowID = null; - observers.remove("inner-window-destroyed", this._documentUnload); - this._earlyEvents.slice(0, this._earlyEvents.length); - this._emit("detach"); - } - }, - - /** - * Receive an event from the content script that need to be sent to - * worker.port. Provide a way for composed object to catch all events. - */ - _onContentScriptEvent: function _onContentScriptEvent() { - // Ensure that we pass only JSON values - let array = Array.prototype.slice.call(arguments); - this._port._asyncEmit.apply(this._port, ensureArgumentsAreJSON(array)); - }, - - /** - * Reference to the content side of the worker. - * @type {WorkerGlobalScope} - */ - _contentWorker: null, - - /** - * Reference to the window that is accessible from - * the content scripts. - * @type {Object} - */ - _window: null, - - /** - * Flag to enable `addon` object injection in document. (bug 612726) - * @type {Boolean} - */ - _injectInDocument: false -}); -exports.Worker = Worker; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/cortex.js b/tools/addon-sdk-1.4/packages/api-utils/lib/cortex.js deleted file mode 100644 index 059d9de..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/cortex.js +++ /dev/null @@ -1,139 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// `var` is being used in the module in order to make it reusable in -// environments in which `let` and `const` is not yet supported. - -// Returns `object`'s property value, where `name` is a name of the property. -function get(object, name) { - return object[name]; -} - -// Assigns `value` to the `object`'s property, where `name` is the name of the -// property. -function set(object, name, value) { - return object[name] = value; -} - -/** - * Given an `object` containing a property with the given `name`, create - * a property descriptor that can be used to define alias/proxy properties - * on other objects. A change in the value of an alias will propagate - * to the aliased property and vice versa. - */ -function createAliasProperty(object, name) { - // Getting own property descriptor of an `object` for the given `name` as - // we are going to create proxy analog. - var property = Object.getOwnPropertyDescriptor(object, name); - var descriptor = { - configurable: property.configurable, - enumerable: property.enumerable, - alias: true - }; - - // If the original property has a getter and/or setter, bind a - // corresponding getter/setter in the alias descriptor to the original - // object, so the `this` object in the getter/setter is the original object - // rather than the alias. - if ("get" in property && property.get) - descriptor.get = property.get.bind(object); - if ("set" in property && property.set) - descriptor.set = property.set.bind(object); - - // If original property was a value property. - if ("value" in property) { - // If original property is a method using it's `object` bounded copy. - if (typeof property.value === "function") { - descriptor.value = property.value.bind(object); - // Also preserving writability of the original property. - descriptor.writable = property.writable; - } - - // If the original property was just a data property, we create proxy - // accessors using our custom get/set functions to propagate changes to the - // original `object` and vice versa. - else { - descriptor.get = get.bind(null, object, name); - descriptor.set = set.bind(null, object, name); - } - } - return descriptor; -} - -// Defines property on `object` object with a name `alias` if given if not -// defaults to `name` that represents an alias of `source[name]`. If aliased -// property was an assessor or a method `this` pseudo-variable will be `source` -// when invoked. If aliased property was a data property changes on any of the -// aliases will propagate to the `source[name]` and also other way round. -function defineAlias(source, target, name, alias) { - return Object.defineProperty(target, alias || name, - createAliasProperty(source, name)); -} - -/** - * Function takes any `object` and returns a proxy for its own public - * properties. By default properties are considered to be public if they don't - * start with `"_"`, but default behavior can be overridden if needed, by - * passing array of public property `names` as a second argument. By default - * returned object will be direct decedent of the given `object`'s prototype, - * but this can be overridden by passing third optional argument, that will be - * used as `prototype` instead. - * @param {Object} object - * Object to create cortex for. - * @param {String[]} [names] - * Optional array of public property names. - * @param {Object} [prototype] - * Optional argument that will be used as `prototype` of the returned object, - * if not provided `Object.getPrototypeOf(object)` is used instead. - */ -exports.Cortex = function Cortex(object, names, prototype) { - // Creating a cortex object from the given `prototype`, if one was not - // provided then `prototype` of a given `object` is used. This allows - // consumer to define expected behavior `instanceof`. In common case - // `prototype` argument can be omitted to preserve same behavior of - // `instanceof` as on original `object`. - var cortex = Object.create(prototype || Object.getPrototypeOf(object)); - // Creating alias properties on the `cortex` object for all the own - // properties of the original `object` that are contained in `names` array. - // If `names` array is not provided then all the properties that don't - // start with `"_"` are aliased. - Object.getOwnPropertyNames(object).forEach(function (name) { - if ((!names && "_" !== name.charAt(0)) || (names && ~names.indexOf(name))) - defineAlias(object, cortex, name); - }); - return cortex; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/cuddlefish.js b/tools/addon-sdk-1.4/packages/api-utils/lib/cuddlefish.js deleted file mode 100644 index c0c9935..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/cuddlefish.js +++ /dev/null @@ -1,320 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 expandtab */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -var EXPORTED_SYMBOLS = [ 'Loader' ]; - -!function(exports) { - -"use strict"; - -const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu, - results: Cr, manager: Cm } = Components; -const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(); -const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']. - getService(Ci.mozIJSSubScriptLoader); - -const Sandbox = { - new: function (prototype, principal) { - let sandbox = Object.create(Sandbox, { - sandbox: { - value: Cu.Sandbox(principal || Sandbox.principal, { - sandboxPrototype: prototype || Sandbox.prototype, - wantXrays: Sandbox.wantXrays - }) - } - }); - // There are few properties (dump, Iterator) that by default appear in - // sandboxes shadowing properties provided by a prototype. To workaround - // this we override all such properties by copying them directly to the - // sandbox. - Object.keys(prototype).forEach(function onEach(key) { - if (sandbox.sandbox[key] !== prototype[key]) - sandbox.sandbox[key] = prototype[key]; - }); - return sandbox; - }, - evaluate: function evaluate(source, uri, lineNumber) { - return Cu.evalInSandbox( - source, - this.sandbox, - this.version, - uri, - lineNumber || this.lineNumber - ); - }, - load: function load(uri) { - scriptLoader.loadSubScript(uri, this.sandbox); - }, - merge: function merge(properties) { - Object.getOwnPropertyNames(properties).forEach(function(name) { - Object.defineProperty(this.sandbox, name, - Object.getOwnPropertyDescriptor(properties, name)); - }, this); - }, - principal: systemPrincipal, - version: '1.8', - lineNumber: 1, - wantXrays: false, - prototype: {} -}; - -// the Module object made available to CommonJS modules when they are -// evaluated, along with 'exports' and 'uri' -const Module = { - new: function(id, path, uri) { - let module = Object.create(this); - - module.id = id; - module.path = path; - module.uri = uri; - module.exports = {}; - - return module; - }, - // TODO: I'd like to remove this, it's not used adds complexity and does - // not has much adoption in commonjs either. - setExports: function setExports(exports) { - this.exports = exports; - } -}; - -const Loader = { - new: function (options) { - let loader = Object.create(Loader, { - // Manifest generated by a linker, containing map of module url's mapped - // to it's requirements, comes from harness-options.json - manifest: { value: options.manifest || {} }, - - // Following property may be passed in (usually for mocking purposes) in - // order to override default modules cache. - modules: { value: options.modules || Object.create(Loader.modules) }, - globals: { value: options.globals || {} }, - - uriPrefix: { value: options.uriPrefix }, - - sandboxes: { value: {} } - }); - loader.require = this.require.bind(loader, options.loader); - - // some 'magic' modules, that have no corresponding .js file - loader.modules['@packaging'] = Object.freeze({ - id: '@packaging', - exports: JSON.parse(JSON.stringify(options)) - }); - loader.modules['@loader'] = Object.freeze({ - exports: Object.freeze({ Loader: Loader }), - id: '@loader' - }); - - // This special module defines globals which will be added to every - // module this loader creates - let globals = loader.require('api-utils/globals!'); - Object.getOwnPropertyNames(globals).forEach(function(name) { - Object.defineProperty(loader.globals, name, - Object.getOwnPropertyDescriptor(globals, name)); - }); - // Freeze globals so that modules won't have a chance to mutate scope of - // other modules. - Object.freeze(globals); - - // Override global `dump` so that it behaves same as in any other module ( - // currently we override dump to write to a file instead of `stdout` so that - // python can read it on windows). - dump = globals.dump; - - return Object.freeze(loader); - }, - modules: { - 'chrome': Object.freeze({ - exports: Object.freeze({ - Cc: Cc, - CC: CC, - Ci: Ci, - Cu: Cu, - Cr: Cr, - Cm: Cm, - components: Components, - messageManager: 'addMessageListener' in exports ? exports : null - }), - id: 'chrome' - }), - 'self': function self(loader, requirer) { - return loader.require('api-utils/self!').create(requirer.path); - }, - }, - - // populate a Module by evaluating the CommonJS module code in the sandbox - load: function load(module) { - let require = Loader.require.bind(this, module.path); - require.main = this.main; - let sandbox = this.sandboxes[module.path] = Sandbox.new(this.globals); - sandbox.merge({ - require: require, - module: module, - exports: module.exports - }); - - sandbox.load(module.uri); - - // Workaround for bug 674195. Freezing objects from other sandboxes fail, - // so we create descendant and freeze it instead. - if (typeof(module.exports) === 'object') { - module.exports = Object.prototype.isPrototypeOf(module.exports) ? - Object.freeze(module.exports) : - Object.freeze(Object.create(module.exports)); - } - }, - - // this require() is the main entry point for regular CommonJS modules. The - // bind() in load (above) causes those modules to get a very restricted - // form of this require(): one which can only ever reference this one - // loader, and which always uses their URI as a "base" (so they're limited - // to their own manifest entries, and can't import anything off the - // manifest). - require: function require(base, id) { - let module, manifest = this.manifest[base], requirer = this.modules[base]; - - if (!id) - throw Error("you must provide a module name when calling require() from " - + (requirer && requirer.id), base, id); - - // If we have a manifest for requirer, then all it's requirements have been - // registered by linker and we should have a `path` to the required module. - // Even pseudo-modules like 'chrome', 'self', '@packaging', and '@loader' - // have pseudo-paths: exactly those same names. - // details see: Bug-697422. - let requirement = manifest && manifest.requirements[id]; - if (!requirement) - throw Error("Module: " + (requirer && requirer.id) + ' located at ' + - base + " has no authority to load: " + id); - let path = requirement.path; - - if (path in this.modules) { - module = this.modules[path]; - } - else { - let uri = this.uriPrefix + path; - module = this.modules[path] = Module.new(id, path, uri); - this.load(module); - Object.freeze(module); - } - - // "magic" modules which have contents that depend upon who imports them - // (like "self") are expressed in the Loader's pre-populated 'modules' - // table as callable functions, which are given the reference to this - // Loader and a copy of the importer's URI - // - // TODO: Find a better way to implement `self`. - // Maybe something like require('self!path/to/data') - if (typeof(module) === 'function') - module = module(this, requirer); - - return module.exports; - }, - - // process.process() will eventually cause a call to main() to be evaluated - // in the addon's context. This function loads and executes the addon's - // entry point module. - main: function main(id, path) { - try { - let uri = this.uriPrefix + path; - let module = this.modules[path] = Module.new(id, path, uri); - this.load(module); // this is where the addon's main.js finally runs - let program = Object.freeze(module).exports; - - if (typeof(program.onUnload) === 'function') - this.require('api-utils/unload').when(program.onUnload); - - if (program.main) { - let { exit, staticArgs } = this.require('api-utils/system'); - let { loadReason } = this.require('@packaging'); - program.main({ loadReason: loadReason, staticArgs: staticArgs }, - { print: function($) dump($ + '\n'), quit: exit }); - } - } catch (error) { - Cu.reportError(error); - if (this.globals.console) this.globals.console.exception(error); - throw error; - } - }, - - // This is the main entry-point: bootstrap.js calls this when the add-on is - // installed. The order of calls is a bit confusing, but here's what - // happens (in temporal order): - // * process.spawn creates a new XUL 'browser' element which will house the - // main addon code. When e10s is active, this uses a real separate OS - // process. When e10s is disabled, this element lives in the one original - // process. Either way, its API is the same. - // * Grab the channel named "require!" and attach a handler which will load - // modules (in the chrome process) when requested to by the addon - // process. This handler uses Loader.require to import the module, then - // calls the module's .initialize() function to connect a new channel. - // The remote caller winds up with a channel reference, which they can - // use to send messages to the newly loaded module. This is for e10s. - // * After the channel handler is attached, process.process() (invoked by - // process.spawn()) will use loadScript() to evaluate code in the - // 'browser' element (which is where the main addon code starts running), - // to do the following: - // * create a Loader, initialized with the same manifest and - // harness-options.json that we've got - // * invoke it's main() method, with the name and path of the addon's - // entry module (which comes from linker via harness-options.js, and is - // usually main.js). That executes main(), above. - // * main() loads the addon's main.js, which executes all top-level - // forms. If the module defines an "exports.main=" function, we invoke - // that too. This is where the addon finally gets to run. - spawn: function spawn(id, path) { - let loader = this; - let process = this.require('api-utils/process'); - process.spawn(id, path)(function(addon) { - // Listen to `require!` channel's input messages from the add-on process - // and load modules being required. - addon.channel('require!').input(function({ requirer: { path }, id }) { - try { - Loader.require.call(loader, path, id).initialize(addon.channel(id)); - } catch (error) { - this.globals.console.exception(error); - } - }); - }); - }, - unload: function unload(reason, callback) { - this.require('api-utils/unload').send(reason, callback); - } -}; -exports.Loader = Loader; - -}(this); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events.js b/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events.js deleted file mode 100644 index da9c93d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events.js +++ /dev/null @@ -1,169 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// Utility function that returns copy of the given `text` with last character -// removed if it is `"s"`. -function singularify(text) { - return text[text.length - 1] === "s" ? text.substr(0, text.length - 1) : text; -} - -// Utility function that takes event type, argument is passed to -// `document.createEvent` and returns name of the initializer method of the -// given event. Please note that there are some event types whose initializer -// methods can't be guessed by this function. For more details see following -// link: https://developer.mozilla.org/En/DOM/Document.createEvent -function getInitializerName(category) { - return "init" + singularify(category); -} - -/** - * Registers an event `listener` on a given `element`, that will be called - * when events of specified `type` is dispatched on the `element`. - * @param {Element} element - * Dom element to register listener on. - * @param {String} type - * A string representing the - * [event type](https://developer.mozilla.org/en/DOM/event.type) to - * listen for. - * @param {Function} listener - * Function that is called whenever an event of the specified `type` - * occurs. - * @param {Boolean} capture - * If true, indicates that the user wishes to initiate capture. After - * initiating capture, all events of the specified type will be dispatched - * to the registered listener before being dispatched to any `EventTarget`s - * beneath it in the DOM tree. Events which are bubbling upward through - * the tree will not trigger a listener designated to use capture. - * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) - * for a detailed explanation. - */ -function on(element, type, listener, capture) { - // `capture` defaults to `false`. - capture = capture || false; - element.addEventListener(type, listener, capture); -} -exports.on = on; - -/** - * Registers an event `listener` on a given `element`, that will be called - * only once, next time event of specified `type` is dispatched on the - * `element`. - * @param {Element} element - * Dom element to register listener on. - * @param {String} type - * A string representing the - * [event type](https://developer.mozilla.org/en/DOM/event.type) to - * listen for. - * @param {Function} listener - * Function that is called whenever an event of the specified `type` - * occurs. - * @param {Boolean} capture - * If true, indicates that the user wishes to initiate capture. After - * initiating capture, all events of the specified type will be dispatched - * to the registered listener before being dispatched to any `EventTarget`s - * beneath it in the DOM tree. Events which are bubbling upward through - * the tree will not trigger a listener designated to use capture. - * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) - * for a detailed explanation. - */ -function once(element, type, listener, capture) { - on(element, type, function selfRemovableListener(event) { - removeListener(element, type, selfRemovableListener, capture); - listener.apply(this, arguments); - }, capture); -} -exports.once = once; - -/** - * Unregisters an event `listener` on a given `element` for the events of the - * specified `type`. - * - * @param {Element} element - * Dom element to unregister listener from. - * @param {String} type - * A string representing the - * [event type](https://developer.mozilla.org/en/DOM/event.type) to - * listen for. - * @param {Function} listener - * Function that is called whenever an event of the specified `type` - * occurs. - * @param {Boolean} capture - * If true, indicates that the user wishes to initiate capture. After - * initiating capture, all events of the specified type will be dispatched - * to the registered listener before being dispatched to any `EventTarget`s - * beneath it in the DOM tree. Events which are bubbling upward through - * the tree will not trigger a listener designated to use capture. - * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) - * for a detailed explanation. - */ -function removeListener(element, type, listener, capture) { - element.removeEventListener(type, listener, capture); -} -exports.removeListener = removeListener; - -/** - * Emits event of the specified `type` and `category` on the given `element`. - * Specified `settings` are used to initialize event before dispatching it. - * @param {Element} element - * Dom element to dispatch event on. - * @param {String} type - * A string representing the - * [event type](https://developer.mozilla.org/en/DOM/event.type). - * @param {Object} options - * Options object containing following properties: - * - `category`: String passed to the `document.createEvent`. Option is - * optional and defaults to "UIEvents". - * - `initializer`: If passed it will be used as name of the method used - * to initialize event. If omitted name will be generated from the - * `category` field by prefixing it with `"init"` and removing last - * character if it matches `"s"`. - * - `settings`: Array of settings that are forwarded to the event - * initializer after firs `type` argument. - * @see https://developer.mozilla.org/En/DOM/Document.createEvent - */ -function emit(element, type, { category, initializer, settings }) { - category = category || "UIEvents"; - initializer = initializer || getInitializerName(category); - let document = element.ownerDocument; - let event = document.createEvent(category); - event[initializer].apply(event, [type].concat(settings)); - element.dispatchEvent(event); -}; -exports.emit = emit; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events/keys.js b/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events/keys.js deleted file mode 100644 index 155625a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/dom/events/keys.js +++ /dev/null @@ -1,93 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { emit } = require("../events"); -const { getCodeForKey, toJSON } = require("../../keyboard/utils"); -const { has } = require("../../array"); -const { isString } = require("../../type"); - -const INITIALIZER = "initKeyEvent"; -const CATEGORY = "KeyboardEvent"; - -function Options(options) { - if (!isString(options)) - return options; - - var { key, modifiers } = toJSON(options); - return { - key: key, - control: has(modifiers, "control"), - alt: has(modifiers, "alt"), - shift: has(modifiers, "shift"), - meta: has(modifiers, "meta") - }; -} - -var keyEvent = exports.keyEvent = function keyEvent(element, type, options) { - - emit(element, type, { - initializer: INITIALIZER, - category: CATEGORY, - settings: [ - !("bubbles" in options) || options.bubbles !== false, - !("cancelable" in options) || options.cancelable !== false, - "window" in options && options.window ? options.window : null, - "control" in options && !!options.control, - "alt" in options && !!options.alt, - "shift" in options && !!options.shift, - "meta" in options && !!options.meta, - getCodeForKey(options.key) || 0, - options.key.length === 1 ? options.key.charCodeAt(0) : 0 - ] - }); -} - -exports.keyDown = function keyDown(element, options) { - keyEvent(element, "keydown", Options(options)); -}; - -exports.keyUp = function keyUp(element, options) { - keyEvent(element, "keyup", Options(options)); -}; - -exports.keyPress = function keyPress(element, options) { - keyEvent(element, "keypress", Options(options)); -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/env!.js b/tools/addon-sdk-1.4/packages/api-utils/lib/env!.js deleted file mode 100644 index 642d599..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/env!.js +++ /dev/null @@ -1,52 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 expandtab */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const { messageManager } = require("chrome"); -const { channel } = require("./channel"); - -module.exports = function load(module) { - return { - require: function require(id) { - // Load required module on the chrome process. - channel(messageManager, messageManager, 'require!').sync({ - requirer: module, - id: id - }); - return channel(messageManager, messageManager, id); - } - }; -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/environment.js b/tools/addon-sdk-1.4/packages/api-utils/lib/environment.js deleted file mode 100644 index 5753801..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/environment.js +++ /dev/null @@ -1,86 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 expandtab */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -'use strict'; - -const { Cc, Ci } = require('chrome'); -const { get, set, exists } = Cc['@mozilla.org/process/environment;1']. - getService(Ci.nsIEnvironment); - -exports.env = Proxy.create({ - // XPCOM does not provides a way to enumerate environment variables, so we - // just don't support enumeration. - getPropertyNames: function() [], - getOwnPropertyNames: function() [], - enumerate: function() [], - keys: function() [], - // We do not support freezing, cause it would make it impossible to set new - // environment variables. - fix: function() undefined, - // We present all environment variables as own properties of this object, - // so we just delegate this call to `getOwnPropertyDescriptor`. - getPropertyDescriptor: function(name) this.getOwnPropertyDescriptor(name), - // If environment variable with this name is defined, we generate proprety - // descriptor for it, otherwise fall back to `undefined` so that for consumer - // this property does not exists. - getOwnPropertyDescriptor: function(name) { - return !exists(name) ? undefined : { - value: get(name), - enumerable: false, // Non-enumerable as we don't support enumeration. - configurable: true, // Configurable as it may be deleted. - writable: true // Writable as we do support set. - } - }, - - // New environment variables can be defined just by defining properties - // on this object. - defineProperty: function(name, { value }) set(name, value), - delete: function(name) set(name, null), - - // We present all properties as own, there for we just delegate to `hasOwn`. - has: function(name) this.hasOwn(name), - // We do support checks for existence of an environment variable, via `in` - // operator on this object. - hasOwn: function(name) exists(name), - - // On property get / set we do read / write appropriate environment variables, - // please note though, that variables with names of standard object properties - // intentionally (so that this behaves as normal object) can not be - // read / set. - get: function(proxy, name) Object.prototype[name] || get(name) || undefined, - set: function(proxy, name, value) Object.prototype[name] || set(name, value) -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/errors.js b/tools/addon-sdk-1.4/packages/api-utils/lib/errors.js deleted file mode 100644 index 56be526..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/errors.js +++ /dev/null @@ -1,92 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -function logToConsole(e) { - console.exception(e); -} - -var catchAndLog = exports.catchAndLog = function(callback, - defaultResponse, - logException) { - if (!logException) - logException = logToConsole; - - return function() { - try { - return callback.apply(this, arguments); - } catch (e) { - logException(e); - return defaultResponse; - } - }; -}; - -exports.catchAndLogProps = function catchAndLogProps(object, - props, - defaultResponse, - logException) { - if (typeof(props) == "string") - props = [props]; - props.forEach( - function(property) { - object[property] = catchAndLog(object[property], - defaultResponse, - logException); - }); -}; - -/** - * Catch and return an exception while calling the callback. If the callback - * doesn't throw, return the return value of the callback in a way that makes it - * possible to distinguish between a return value and an exception. - * - * This function is useful when you need to pass the result of a call across - * a process boundary (across which exceptions don't propagate). It probably - * doesn't need to be factored out into this module, since it is only used by - * a single caller, but putting it here works around bug 625560. - */ -exports.catchAndReturn = function(callback) { - return function() { - try { - return { returnValue: callback.apply(this, arguments) }; - } - catch (exception) { - return { exception: exception }; - } - }; -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/events.js b/tools/addon-sdk-1.4/packages/api-utils/lib/events.js deleted file mode 100644 index 4e36c00..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/events.js +++ /dev/null @@ -1,202 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const ERROR_TYPE = 'error', - UNCAUGHT_ERROR = 'An error event was dispatched for which there was' - + ' no listener.', - BAD_LISTENER = 'The event listener must be a function.'; -/** - * This object is used to create an `EventEmitter` that, useful for composing - * objects that emit events. It implements an interface like `EventTarget` from - * DOM Level 2, which is implemented by Node objects in implementations that - * support the DOM Event Model. - * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget - * @see http://nodejs.org/api.html#EventEmitter - * @see http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/EventDispatcher.html - */ -const eventEmitter = { - /** - * Registers an event `listener` that is called every time events of - * specified `type` are emitted. - * @param {String} type - * The type of event. - * @param {Function} listener - * The listener function that processes the event. - * @example - * worker.on('message', function (data) { - * console.log('data received: ' + data) - * }) - */ - on: function on(type, listener) { - if ('function' !== typeof listener) - throw new Error(BAD_LISTENER); - let listeners = this._listeners(type); - if (0 > listeners.indexOf(listener)) - listeners.push(listener); - // Use of `_public` is required by the legacy traits code that will go away - // once bug-637633 is fixed. - return this._public || this; - }, - - /** - * Registers an event `listener` that is called once the next time an event - * of the specified `type` is emitted. - * @param {String} type - * The type of the event. - * @param {Function} listener - * The listener function that processes the event. - */ - once: function once(type, listener) { - this.on(type, function selfRemovableListener() { - this.removeListener(type, selfRemovableListener); - listener.apply(this, arguments); - }); - }, - - /** - * Unregister `listener` for the specified event type. - * @param {String} type - * The type of event. - * @param {Function} listener - * The listener function that processes the event. - */ - removeListener: function removeListener(type, listener) { - if ('function' !== typeof listener) - throw new Error(BAD_LISTENER); - let listeners = this._listeners(type), - index = listeners.indexOf(listener); - if (0 <= index) - listeners.splice(index, 1); - // Use of `_public` is required by the legacy traits code, that will go away - // once bug-637633 is fixed. - return this._public || this; - }, - - /** - * Hash of listeners on this EventEmitter. - */ - _events: null, - - /** - * Returns an array of listeners for the specified event `type`. This array - * can be manipulated, e.g. to remove listeners. - * @param {String} type - * The type of event. - */ - _listeners: function listeners(type) { - let events = this._events || (this._events = {}); - return events[type] || (events[type] = []); - }, - - /** - * Execute each of the listeners in order with the supplied arguments. - * Returns `true` if listener for this event was called, `false` if there are - * no listeners for this event `type`. - * - * All the exceptions that are thrown by listeners during the emit - * are caught and can be handled by listeners of 'error' event. Thrown - * exceptions are passed as an argument to an 'error' event listener. - * If no 'error' listener is registered exception will propagate to a - * caller of this method. - * - * **It's recommended to have a default 'error' listener in all the complete - * composition that in worst case may dump errors to the console.** - * - * @param {String} type - * The type of event. - * @params {Object|Number|String|Boolean} - * Arguments that will be passed to listeners. - * @returns {Boolean} - */ - _emit: function _emit(type, event) { - let args = Array.slice(arguments); - // Use of `_public` is required by the legacy traits code that will go away - // once bug-637633 is fixed. - args.unshift(this._public || this); - return this._emitOnObject.apply(this, args); - }, - - /** - * A version of _emit that lets you specify the object on which listeners are - * called. This is a hack that is sometimes necessary when such an object - * (exports, for example) cannot be an EventEmitter for some reason, but other - * object(s) managing events for the object are EventEmitters. Once bug - * 577782 is fixed, this method shouldn't be necessary. - * - * @param {object} targetObj - * The object on which listeners will be called. - * @param {string} type - * The event name. - * @param {value} event - * The first argument to pass to listeners. - * @param {value} ... - * More arguments to pass to listeners. - * @returns {boolean} - */ - _emitOnObject: function _emitOnObject(targetObj, type, event /* , ... */) { - let listeners = this._listeners(type).slice(0); - // If there is no 'error' event listener then throw. - if (type === ERROR_TYPE && !listeners.length) - console.exception(event); - if (!listeners.length) - return false; - let params = Array.slice(arguments, 2); - for each (let listener in listeners) { - try { - listener.apply(targetObj, params); - } catch(e) { - this._emit('error', e); - } - } - return true; - }, - - /** - * Removes all the event listeners for the specified event `type`. - * @param {String} type - * The type of event. - */ - _removeAllListeners: function _removeAllListeners(type) { - this._listeners(type).splice(0); - return this; - } -}; -exports.EventEmitter = require("./traits").Trait.compose(eventEmitter); -exports.EventEmitterTrait = require('./light-traits').Trait(eventEmitter); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/events/assembler.js b/tools/addon-sdk-1.4/packages/api-utils/lib/events/assembler.js deleted file mode 100644 index 26860d6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/events/assembler.js +++ /dev/null @@ -1,86 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Trait } = require("../light-traits"); -const { removeListener, on } = require("../dom/events"); - -/** - * Trait may be used for building objects / composing traits that wish to handle - * multiple dom events from multiple event targets in one place. Event targets - * can be added / removed by calling `observe / ignore` methods. Composer should - * provide array of event types it wishes to handle as property - * `supportedEventsTypes` and function for handling all those events as - * `handleEvent` property. - */ -exports.DOMEventAssembler = Trait({ - /** - * Function that is supposed to handle all the supported events (that are - * present in the `supportedEventsTypes`) from all the observed - * `eventTargets`. - * @param {Event} event - * Event being dispatched. - */ - handleEvent: Trait.required, - /** - * Array of supported event names. - * @type {String[]} - */ - supportedEventsTypes: Trait.required, - /** - * Adds `eventTarget` to the list of observed `eventTarget`s. Listeners for - * supported events will be registered on the given `eventTarget`. - * @param {EventTarget} eventTarget - */ - observe: function observe(eventTarget) { - this.supportedEventsTypes.forEach(function(eventType) { - on(eventTarget, eventType, this); - }, this); - }, - /** - * Removes `eventTarget` from the list of observed `eventTarget`s. Listeners - * for all supported events will be unregistered from the given `eventTarget`. - * @param {EventTarget} eventTarget - */ - ignore: function ignore(eventTarget) { - this.supportedEventsTypes.forEach(function(eventType) { - removeListener(eventTarget, eventType, this); - }, this); - } -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/file.js b/tools/addon-sdk-1.4/packages/api-utils/lib/file.js deleted file mode 100644 index 30cb356..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/file.js +++ /dev/null @@ -1,227 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is nsINarwhal. - * - * The Initial Developer of the Original Code is - * Irakli Gozalishvili <rfobic@gmail.com>. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <rfobic@gmail.com> - * Atul Varma <atul@mozilla.com> - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,Cr} = require("chrome"); -const byteStreams = require("./byte-streams"); -const textStreams = require("./text-streams"); - -// Flags passed when opening a file. See nsprpub/pr/include/prio.h. -const OPEN_FLAGS = { - RDONLY: parseInt("0x01"), - WRONLY: parseInt("0x02"), - CREATE_FILE: parseInt("0x08"), - APPEND: parseInt("0x10"), - TRUNCATE: parseInt("0x20"), - EXCL: parseInt("0x80") -}; - -var dirsvc = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - -function MozFile(path) { - var file = Cc['@mozilla.org/file/local;1'] - .createInstance(Ci.nsILocalFile); - file.initWithPath(path); - return file; -} - -function ensureReadable(file) { - if (!file.isReadable()) - throw new Error("path is not readable: " + file.path); -} - -function ensureDir(file) { - ensureExists(file); - if (!file.isDirectory()) - throw new Error("path is not a directory: " + file.path); -} - -function ensureFile(file) { - ensureExists(file); - if (!file.isFile()) - throw new Error("path is not a file: " + file.path); -} - -function ensureExists(file) { - if (!file.exists()) - throw friendlyError(Cr.NS_ERROR_FILE_NOT_FOUND, file.path); -} - -function friendlyError(errOrResult, filename) { - var isResult = typeof(errOrResult) === "number"; - var result = isResult ? errOrResult : errOrResult.result; - switch (result) { - case Cr.NS_ERROR_FILE_NOT_FOUND: - return new Error("path does not exist: " + filename); - } - return isResult ? new Error("XPCOM error code: " + errOrResult) : errOrResult; -} - -exports.exists = function exists(filename) { - return MozFile(filename).exists(); -}; - -exports.isFile = function isFile(filename) { - return MozFile(filename).isFile(); -}; - -exports.read = function read(filename, mode) { - if (typeof(mode) !== "string") - mode = ""; - - // Ensure mode is read-only. - mode = /b/.test(mode) ? "b" : ""; - - var stream = exports.open(filename, mode); - try { - var str = stream.read(); - } - finally { - stream.close(); - } - - return str; -}; - -exports.join = function join(base) { - if (arguments.length < 2) - throw new Error("need at least 2 args"); - base = MozFile(base); - for (var i = 1; i < arguments.length; i++) - base.append(arguments[i]); - return base.path; -}; - -exports.dirname = function dirname(path) { - var parent = MozFile(path).parent; - return parent ? parent.path : ""; -}; - -exports.basename = function basename(path) { - var leafName = MozFile(path).leafName; - - // On Windows, leafName when the path is a volume letter and colon ("c:") is - // the path itself. But such a path has no basename, so we want the empty - // string. - return leafName == path ? "" : leafName; -}; - -exports.list = function list(path) { - var file = MozFile(path); - ensureDir(file); - ensureReadable(file); - - var entries = file.directoryEntries; - var entryNames = []; - while(entries.hasMoreElements()) { - var entry = entries.getNext(); - entry.QueryInterface(Ci.nsIFile); - entryNames.push(entry.leafName); - } - return entryNames; -}; - -exports.open = function open(filename, mode) { - var file = MozFile(filename); - if (typeof(mode) !== "string") - mode = ""; - - // File opened for write only. - if (/w/.test(mode)) { - if (file.exists()) - ensureFile(file); - var stream = Cc['@mozilla.org/network/file-output-stream;1']. - createInstance(Ci.nsIFileOutputStream); - var openFlags = OPEN_FLAGS.WRONLY | - OPEN_FLAGS.CREATE_FILE | - OPEN_FLAGS.TRUNCATE; - var permFlags = parseInt("0644"); // u+rw go+r - try { - stream.init(file, openFlags, permFlags, 0); - } - catch (err) { - throw friendlyError(err, filename); - } - return /b/.test(mode) ? - new byteStreams.ByteWriter(stream) : - new textStreams.TextWriter(stream); - } - - // File opened for read only, the default. - ensureFile(file); - stream = Cc['@mozilla.org/network/file-input-stream;1']. - createInstance(Ci.nsIFileInputStream); - try { - stream.init(file, OPEN_FLAGS.RDONLY, 0, 0); - } - catch (err) { - throw friendlyError(err, filename); - } - return /b/.test(mode) ? - new byteStreams.ByteReader(stream) : - new textStreams.TextReader(stream); -}; - -exports.remove = function remove(path) { - var file = MozFile(path); - ensureFile(file); - file.remove(false); -}; - -exports.mkpath = function mkpath(path) { - var file = MozFile(path); - if (!file.exists()) - file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755")); // u+rwx go+rx - else if (!file.isDirectory()) - throw new Error("The path already exists and is not a directory: " + path); -}; - -exports.rmdir = function rmdir(path) { - var file = MozFile(path); - ensureDir(file); - try { - file.remove(false); - } - catch (err) { - // Bug 566950 explains why we're not catching a specific exception here. - throw new Error("The directory is not empty: " + path); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/find-tests.js b/tools/addon-sdk-1.4/packages/api-utils/lib/find-tests.js deleted file mode 100644 index be29d19..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/find-tests.js +++ /dev/null @@ -1 +0,0 @@ -// this file left intentionally blank diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/globals!.js b/tools/addon-sdk-1.4/packages/api-utils/lib/globals!.js deleted file mode 100644 index 27fd8ba..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/globals!.js +++ /dev/null @@ -1,113 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 expandtab */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -let { Cc, Ci } = require('chrome'); -let { PlainTextConsole } = require('./plain-text-console'); -let options = require('@packaging'); - -// On windows dump does not writes into stdout so cfx can't read thous dumps. -// To workaround this issue we write to a special file from which cfx will -// read and print to the console. -// For more details see: bug-673383 -exports.dump = (function define(global) { - const PR_WRONLY = 0x02; - const PR_CREATE_FILE = 0x08; - const PR_APPEND = 0x10; - let print = Object.getPrototypeOf(global).dump - if (print) return print; - if ('logFile' in options) { - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); - file.initWithPath(options.logFile); - let stream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - stream.init(file, PR_WRONLY|PR_CREATE_FILE|PR_APPEND, -1, 0); - - return function print(message) { - message = String(message); - stream.write(message, message.length); - stream.flush(); - }; - } - return dump; -})(this); - -// Override the default Iterator function with one that passes -// a second argument to custom iterator methods that identifies -// the call as originating from an Iterator function so the custom -// iterator method can return [key, value] pairs just like default -// iterators called via the default Iterator function. -exports.Iterator = (function(DefaultIterator) { - return function Iterator(obj, keysOnly) { - if ("__iterator__" in obj && !keysOnly) - return obj.__iterator__.call(obj, false, true); - return DefaultIterator(obj, keysOnly); - }; -})(Iterator); - -// TODO: Remove memory from the globals, as it raises security concerns and -// there is no real reason to favor global memory over -// `require('api-utils/memory')`. For details see: Bug-620559 -exports.memory = require('./memory'); -exports.console = new PlainTextConsole(exports.dump); - -// Provide CommonJS `define` to allow authoring modules in a format that can be -// loaded both into jetpack and into browser via AMD loaders. -Object.defineProperty(exports, 'define', { - // `define` is provided as a lazy getter that binds below defined `define` - // function to the module scope, so that require, exports and module - // variables remain accessible. - configurable: true, - get: (function() { - function define(factory) { - factory = Array.slice(arguments).pop(); - factory.call(this, this.require, this.exports, this.module); - } - - return function getter() { - // Redefine `define` as a static property to make sure that module - // gets access to the same function so that `define === define` is - // `true`. - Object.defineProperty(this, 'define', { - configurable: false, - value: define.bind(this) - }); - return this.define; - } - })() -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/hidden-frame.js b/tools/addon-sdk-1.4/packages/api-utils/lib/hidden-frame.js deleted file mode 100644 index 241a4bc..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/hidden-frame.js +++ /dev/null @@ -1,200 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Felipe Gomes <felipc@gmail.com> (Original Author) - * Myk Melez <myk@mozilla.org> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc, Ci} = require("chrome"); -const errors = require("./errors"); -const apiUtils = require("./api-utils"); -const timer = require("./timer"); - -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - -let hostFrame, hostDocument, hiddenWindow, isHostFrameReady = false; - -if (!require("./xul-app").isOneOf(["Firefox", "Thunderbird"])) { - throw new Error([ - "The hidden-frame module currently supports only Firefox and Thunderbird. ", - "In the future, we would like it to support other applications, however. ", - "Please see https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more ", - "information." - ].join("")); -} - -let appShellService = Cc["@mozilla.org/appshell/appShellService;1"]. - getService(Ci.nsIAppShellService); -hiddenWindow = appShellService.hiddenDOMWindow; - -if (!hiddenWindow) { - throw new Error([ - "The hidden-frame module needs an app that supports a hidden window. ", - "We would like it to support other applications, however. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more information." - ].join("")); -} - -// Check if we can use the hidden window itself to host our iframes. -// If it's not a suitable host, the hostFrame will be lazily created -// by the first HiddenFrame instance. -if (hiddenWindow.location.protocol == "chrome:" && - (hiddenWindow.document.contentType == "application/vnd.mozilla.xul+xml" || - hiddenWindow.document.contentType == "application/xhtml+xml")) { - hostFrame = hiddenWindow; - hostDocument = hiddenWindow.document; - isHostFrameReady = true; -} - -function setHostFrameReady() { - hostDocument = hostFrame.contentDocument; - hostFrame.removeEventListener("DOMContentLoaded", setHostFrameReady, false); - isHostFrameReady = true; -} - -// This cache is used to access friend properties between functions -// without exposing them on the public API. -let cache = []; - -exports.HiddenFrame = apiUtils.publicConstructor(HiddenFrame); - -function HiddenFrame(options) { - options = options || {}; - let self = this; - - for each (let [key, val] in Iterator(apiUtils.validateOptions(options, { - onReady: { - is: ["undefined", "function", "array"], - ok: function(v) { - if (apiUtils.getTypeOf(v) === "array") { - // make sure every item is a function - return v.every(function (item) typeof(item) === "function") - } - return true; - } - } - }))) { - if (typeof(val) != "undefined") - options[key] = val; - } - - require("./collection").addCollectionProperty(this, "onReady"); - if (options.onReady) - this.onReady.add(options.onReady); - - if (!hostFrame) { - hostFrame = hiddenWindow.document.createElement("iframe"); - - // ugly ugly hack. This is the most lightweight chrome:// file I could find on the tree - // This hack should be removed by proper platform support on bug 565388 - hostFrame.setAttribute("src", "chrome://global/content/mozilla.xhtml"); - hostFrame.addEventListener("DOMContentLoaded", setHostFrameReady, false); - - hiddenWindow.document.body.appendChild(hostFrame); - } - - this.toString = function toString() "[object Frame]"; -} - -exports.add = function JP_SDK_Frame_add(frame) { - if (!(frame instanceof HiddenFrame)) - throw new Error("The object to be added must be a HiddenFrame."); - - // This instance was already added. - if (cache.filter(function (v) v.frame === frame)[0]) - return frame; - - function createElement() { - hostFrame.removeEventListener("DOMContentLoaded", createElement, false); - - let element = hostDocument.createElementNS(XUL_NS, "iframe"); - - element.setAttribute("type", "content"); - hostDocument.documentElement.appendChild(element); - - /* Public API: hiddenFrame.element */ - frame.__defineGetter__("element", function () element); - - // Notify consumers that the frame is ready. - function onReadyListener(event) { - element.removeEventListener("DOMContentLoaded", onReadyListener, false); - if (event.target == element.contentDocument) { - for (let handler in frame.onReady) - errors.catchAndLog(function () handler.call(frame))(); - } - } - element.addEventListener("DOMContentLoaded", onReadyListener, false); - - cache.push({ - frame: frame, - element: element, - unload: function unload() { - hostDocument.documentElement.removeChild(element); - } - }); - } - - /* Begin element construction or schedule it for later */ - if (isHostFrameReady) { - createElement(); - } else { - hostFrame.addEventListener("DOMContentLoaded", createElement, false); - } - - return frame; -} - -exports.remove = function remove(frame) { - if (!(frame instanceof HiddenFrame)) - throw new Error("The object to be removed must be a HiddenFrame."); - - let entry = cache.filter(function (v) v.frame === frame)[0]; - if (!entry) - return; - - entry.unload(); - cache.splice(cache.indexOf(entry), 1); -} - -require("./unload").when(function () { - for each (let entry in cache.slice()) - exports.remove(entry.frame); - - if (hostFrame && hostFrame !== hiddenWindow) - hiddenWindow.document.body.removeChild(hostFrame); -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/httpd.js b/tools/addon-sdk-1.4/packages/api-utils/lib/httpd.js deleted file mode 100644 index ebf3643..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/httpd.js +++ /dev/null @@ -1,5202 +0,0 @@ -/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** -* Version: MPL 1.1/GPL 2.0/LGPL 2.1 -* -* The contents of this file are subject to the Mozilla Public License Version -* 1.1 (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS IS" basis, -* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -* for the specific language governing rights and limitations under the -* License. -* -* The Original Code is the httpd.js server. -* -* The Initial Developer of the Original Code is -* Mozilla Corporation. -* Portions created by the Initial Developer are Copyright (C) 2006 -* the Initial Developer. All Rights Reserved. -* -* Contributor(s): -* Darin Fisher (v1, netwerk/test/TestServ.js) -* Christian Biesinger (v2, netwerk/test/unit/head_http_server.js) -* Jeff Walden <jwalden+code@mit.edu> (v3, netwerk/test/httpserver/httpd.js) -* Robert Sayre <sayrer@gmail.com> -* -* Alternatively, the contents of this file may be used under the terms of -* either the GNU General Public License Version 2 or later (the "GPL"), or -* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -* in which case the provisions of the GPL or the LGPL are applicable instead -* of those above. If you wish to allow use of your version of this file only -* under the terms of either the GPL or the LGPL, and not to allow others to -* use your version of this file under the terms of the MPL, indicate your -* decision by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL or the LGPL. If you do not delete -* the provisions above, a recipient may use your version of this file under -* the terms of any one of the MPL, the GPL or the LGPL. -* -* ***** END LICENSE BLOCK ***** */ - -/* -* An implementation of an HTTP server both as a loadable script and as an XPCOM -* component. See the accompanying README file for user documentation on -* httpd.js. -*/ - - -var {components,Cc,Ci,Cr,Cu} = require("chrome"); -components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - -const CC = components.Constructor; - -const PR_UINT32_MAX = Math.pow(2, 32) - 1; - -/** True if debugging output is enabled, false otherwise. */ -var DEBUG = false; // non-const *only* so tweakable in server tests - -/** True if debugging output should be timestamped. */ -var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests - -var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance(); - -/** -* Asserts that the given condition holds. If it doesn't, the given message is -* dumped, a stack trace is printed, and an exception is thrown to attempt to -* stop execution (which unfortunately must rely upon the exception not being -* accidentally swallowed by the code that uses it). -*/ -function NS_ASSERT(cond, msg) -{ - if (DEBUG && !cond) - { - dumpn("###!!!"); - dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!")); - dumpn("###!!! Stack follows:"); - - var stack = new Error().stack.split(/\n/); - dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n")); - - throw Cr.NS_ERROR_ABORT; - } -} - -/** Constructs an HTTP error object. */ -function HttpError(code, description) -{ - this.code = code; - this.description = description; -} -HttpError.prototype = -{ - toString: function() - { - return this.code + " " + this.description; - } -}; - -/** -* Errors thrown to trigger specific HTTP server responses. -*/ -const HTTP_400 = new HttpError(400, "Bad Request"); -const HTTP_401 = new HttpError(401, "Unauthorized"); -const HTTP_402 = new HttpError(402, "Payment Required"); -const HTTP_403 = new HttpError(403, "Forbidden"); -const HTTP_404 = new HttpError(404, "Not Found"); -const HTTP_405 = new HttpError(405, "Method Not Allowed"); -const HTTP_406 = new HttpError(406, "Not Acceptable"); -const HTTP_407 = new HttpError(407, "Proxy Authentication Required"); -const HTTP_408 = new HttpError(408, "Request Timeout"); -const HTTP_409 = new HttpError(409, "Conflict"); -const HTTP_410 = new HttpError(410, "Gone"); -const HTTP_411 = new HttpError(411, "Length Required"); -const HTTP_412 = new HttpError(412, "Precondition Failed"); -const HTTP_413 = new HttpError(413, "Request Entity Too Large"); -const HTTP_414 = new HttpError(414, "Request-URI Too Long"); -const HTTP_415 = new HttpError(415, "Unsupported Media Type"); -const HTTP_417 = new HttpError(417, "Expectation Failed"); - -const HTTP_500 = new HttpError(500, "Internal Server Error"); -const HTTP_501 = new HttpError(501, "Not Implemented"); -const HTTP_502 = new HttpError(502, "Bad Gateway"); -const HTTP_503 = new HttpError(503, "Service Unavailable"); -const HTTP_504 = new HttpError(504, "Gateway Timeout"); -const HTTP_505 = new HttpError(505, "HTTP Version Not Supported"); - -/** Creates a hash with fields corresponding to the values in arr. */ -function array2obj(arr) -{ - var obj = {}; - for (var i = 0; i < arr.length; i++) - obj[arr[i]] = arr[i]; - return obj; -} - -/** Returns an array of the integers x through y, inclusive. */ -function range(x, y) -{ - var arr = []; - for (var i = x; i <= y; i++) - arr.push(i); - return arr; -} - -/** An object (hash) whose fields are the numbers of all HTTP error codes. */ -const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505))); - - -/** -* The character used to distinguish hidden files from non-hidden files, a la -* the leading dot in Apache. Since that mechanism also hides files from -* easy display in LXR, ls output, etc. however, we choose instead to use a -* suffix character. If a requested file ends with it, we append another -* when getting the file on the server. If it doesn't, we just look up that -* file. Therefore, any file whose name ends with exactly one of the character -* is "hidden" and available for use by the server. -*/ -const HIDDEN_CHAR = "^"; - -/** -* The file name suffix indicating the file containing overridden headers for -* a requested file. -*/ -const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR; - -/** Type used to denote SJS scripts for CGI-like functionality. */ -const SJS_TYPE = "sjs"; - -/** Base for relative timestamps produced by dumpn(). */ -var firstStamp = 0; - -/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */ -function dumpn(str) -{ - if (DEBUG) - { - var prefix = "HTTPD-INFO | "; - if (DEBUG_TIMESTAMP) - { - if (firstStamp === 0) - firstStamp = Date.now(); - - var elapsed = Date.now() - firstStamp; // milliseconds - var min = Math.floor(elapsed / 60000); - var sec = (elapsed % 60000) / 1000; - - if (sec < 10) - prefix += min + ":0" + sec.toFixed(3) + " | "; - else - prefix += min + ":" + sec.toFixed(3) + " | "; - } - - dump(prefix + str + "\n"); - } -} - -/** Dumps the current JS stack if DEBUG. */ -function dumpStack() -{ - // peel off the frames for dumpStack() and Error() - var stack = new Error().stack.split(/\n/).slice(2); - stack.forEach(dumpn); -} - - -/** The XPCOM thread manager. */ -var gThreadManager = null; - -/** The XPCOM prefs service. */ -var gRootPrefBranch = null; -function getRootPrefBranch() -{ - if (!gRootPrefBranch) - { - gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefBranch); - } - return gRootPrefBranch; -} - -/** -* JavaScript constructors for commonly-used classes; precreating these is a -* speedup over doing the same from base principles. See the docs at -* http://developer.mozilla.org/en/docs/components.Constructor for details. -*/ -const ServerSocket = CC("@mozilla.org/network/server-socket;1", - "nsIServerSocket", - "init"); -const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1", - "nsIScriptableInputStream", - "init"); -const Pipe = CC("@mozilla.org/pipe;1", - "nsIPipe", - "init"); -const FileInputStream = CC("@mozilla.org/network/file-input-stream;1", - "nsIFileInputStream", - "init"); -const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1", - "nsIConverterInputStream", - "init"); -const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1", - "nsIWritablePropertyBag2"); -const SupportsString = CC("@mozilla.org/supports-string;1", - "nsISupportsString"); - -/* These two are non-const only so a test can overwrite them. */ -var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", - "nsIBinaryInputStream", - "setInputStream"); -var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", - "nsIBinaryOutputStream", - "setOutputStream"); - -/** -* Returns the RFC 822/1123 representation of a date. -* -* @param date : Number -* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT -* @returns string -* the representation of the given date -*/ -function toDateString(date) -{ - // - // rfc1123-date = wkday "," SP date1 SP time SP "GMT" - // date1 = 2DIGIT SP month SP 4DIGIT - // ; day month year (e.g., 02 Jun 1982) - // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT - // ; 00:00:00 - 23:59:59 - // wkday = "Mon" | "Tue" | "Wed" - // | "Thu" | "Fri" | "Sat" | "Sun" - // month = "Jan" | "Feb" | "Mar" | "Apr" - // | "May" | "Jun" | "Jul" | "Aug" - // | "Sep" | "Oct" | "Nov" | "Dec" - // - - const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - - /** -* Processes a date and returns the encoded UTC time as a string according to -* the format specified in RFC 2616. -* -* @param date : Date -* the date to process -* @returns string -* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59" -*/ - function toTime(date) - { - var hrs = date.getUTCHours(); - var rv = (hrs < 10) ? "0" + hrs : hrs; - - var mins = date.getUTCMinutes(); - rv += ":"; - rv += (mins < 10) ? "0" + mins : mins; - - var secs = date.getUTCSeconds(); - rv += ":"; - rv += (secs < 10) ? "0" + secs : secs; - - return rv; - } - - /** -* Processes a date and returns the encoded UTC date as a string according to -* the date1 format specified in RFC 2616. -* -* @param date : Date -* the date to process -* @returns string -* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59" -*/ - function toDate1(date) - { - var day = date.getUTCDate(); - var month = date.getUTCMonth(); - var year = date.getUTCFullYear(); - - var rv = (day < 10) ? "0" + day : day; - rv += " " + monthStrings[month]; - rv += " " + year; - - return rv; - } - - date = new Date(date); - - const fmtString = "%wkday%, %date1% %time% GMT"; - var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]); - rv = rv.replace("%time%", toTime(date)); - return rv.replace("%date1%", toDate1(date)); -} - -/** -* Prints out a human-readable representation of the object o and its fields, -* omitting those whose names begin with "_" if showMembers != true (to ignore -* "private" properties exposed via getters/setters). -*/ -function printObj(o, showMembers) -{ - var s = "******************************\n"; - s += "o = {\n"; - for (var i in o) - { - if (typeof(i) != "string" || - (showMembers || (i.length > 0 && i[0] != "_"))) - s+= " " + i + ": " + o[i] + ",\n"; - } - s += " };\n"; - s += "******************************"; - dumpn(s); -} - -/** -* Instantiates a new HTTP server. -*/ -function nsHttpServer() -{ - if (!gThreadManager) - gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService(); - - /** The port on which this server listens. */ - this._port = undefined; - - /** The socket associated with this. */ - this._socket = null; - - /** The handler used to process requests to this server. */ - this._handler = new ServerHandler(this); - - /** Naming information for this server. */ - this._identity = new ServerIdentity(); - - /** -* Indicates when the server is to be shut down at the end of the request. -*/ - this._doQuit = false; - - /** -* True if the socket in this is closed (and closure notifications have been -* sent and processed if the socket was ever opened), false otherwise. -*/ - this._socketClosed = true; - - /** -* Used for tracking existing connections and ensuring that all connections -* are properly cleaned up before server shutdown; increases by 1 for every -* new incoming connection. -*/ - this._connectionGen = 0; - - /** -* Hash of all open connections, indexed by connection number at time of -* creation. -*/ - this._connections = {}; -} -nsHttpServer.prototype = -{ - classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"), - - // NSISERVERSOCKETLISTENER - - /** -* Processes an incoming request coming in on the given socket and contained -* in the given transport. -* -* @param socket : nsIServerSocket -* the socket through which the request was served -* @param trans : nsISocketTransport -* the transport for the request/response -* @see nsIServerSocketListener.onSocketAccepted -*/ - onSocketAccepted: function(socket, trans) - { - dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")"); - - dumpn(">>> new connection on " + trans.host + ":" + trans.port); - - const SEGMENT_SIZE = 8192; - const SEGMENT_COUNT = 1024; - try - { - var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT) - .QueryInterface(Ci.nsIAsyncInputStream); - var output = trans.openOutputStream(0, 0, 0); - } - catch (e) - { - dumpn("*** error opening transport streams: " + e); - trans.close(Cr.NS_BINDING_ABORTED); - return; - } - - var connectionNumber = ++this._connectionGen; - - try - { - var conn = new Connection(input, output, this, socket.port, trans.port, - connectionNumber); - var reader = new RequestReader(conn); - - // XXX add request timeout functionality here! - - // Note: must use main thread here, or we might get a GC that will cause - // threadsafety assertions. We really need to fix XPConnect so that - // you can actually do things in multi-threaded JS. :-( - input.asyncWait(reader, 0, 0, gThreadManager.mainThread); - } - catch (e) - { - // Assume this connection can't be salvaged and bail on it completely; - // don't attempt to close it so that we can assert that any connection - // being closed is in this._connections. - dumpn("*** error in initial request-processing stages: " + e); - trans.close(Cr.NS_BINDING_ABORTED); - return; - } - - this._connections[connectionNumber] = conn; - dumpn("*** starting connection " + connectionNumber); - }, - - /** -* Called when the socket associated with this is closed. -* -* @param socket : nsIServerSocket -* the socket being closed -* @param status : nsresult -* the reason the socket stopped listening (NS_BINDING_ABORTED if the server -* was stopped using nsIHttpServer.stop) -* @see nsIServerSocketListener.onStopListening -*/ - onStopListening: function(socket, status) - { - dumpn(">>> shutting down server on port " + socket.port); - this._socketClosed = true; - if (!this._hasOpenConnections()) - { - dumpn("*** no open connections, notifying async from onStopListening"); - - // Notify asynchronously so that any pending teardown in stop() has a - // chance to run first. - var self = this; - var stopEvent = - { - run: function() - { - dumpn("*** _notifyStopped async callback"); - self._notifyStopped(); - } - }; - gThreadManager.currentThread - .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL); - } - }, - - // NSIHTTPSERVER - - // - // see nsIHttpServer.start - // - start: function(port) - { - this._start(port, "localhost") - }, - - _start: function(port, host) - { - if (this._socket) - throw Cr.NS_ERROR_ALREADY_INITIALIZED; - - this._port = port; - this._doQuit = this._socketClosed = false; - - this._host = host; - - // The listen queue needs to be long enough to handle - // network.http.max-connections-per-server concurrent connections, - // plus a safety margin in case some other process is talking to - // the server as well. - var prefs = getRootPrefBranch(); - var maxConnections = - prefs.getIntPref("network.http.max-connections-per-server") + 5; - - try - { - var loopback = true; - if (this._host != "127.0.0.1" && this._host != "localhost") { - var loopback = false; - } - - var socket = new ServerSocket(this._port, - loopback, // true = localhost, false = everybody - maxConnections); - dumpn(">>> listening on port " + socket.port + ", " + maxConnections + - " pending connections"); - socket.asyncListen(this); - this._identity._initialize(port, host, true); - this._socket = socket; - } - catch (e) - { - dumpn("!!! could not start server on port " + port + ": " + e); - throw Cr.NS_ERROR_NOT_AVAILABLE; - } - }, - - // - // see nsIHttpServer.stop - // - stop: function(callback) - { - if (!callback) - throw Cr.NS_ERROR_NULL_POINTER; - if (!this._socket) - throw Cr.NS_ERROR_UNEXPECTED; - - this._stopCallback = typeof callback === "function" - ? callback - : function() { callback.onStopped(); }; - - dumpn(">>> stopping listening on port " + this._socket.port); - this._socket.close(); - this._socket = null; - - // We can't have this identity any more, and the port on which we're running - // this server now could be meaningless the next time around. - this._identity._teardown(); - - this._doQuit = false; - - // socket-close notification and pending request completion happen async - }, - - // - // see nsIHttpServer.registerFile - // - registerFile: function(path, file) - { - if (file && (!file.exists() || file.isDirectory())) - throw Cr.NS_ERROR_INVALID_ARG; - - this._handler.registerFile(path, file); - }, - - // - // see nsIHttpServer.registerDirectory - // - registerDirectory: function(path, directory) - { - // XXX true path validation! - if (path.charAt(0) != "/" || - path.charAt(path.length - 1) != "/" || - (directory && - (!directory.exists() || !directory.isDirectory()))) - throw Cr.NS_ERROR_INVALID_ARG; - - // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping - // exists! - - this._handler.registerDirectory(path, directory); - }, - - // - // see nsIHttpServer.registerPathHandler - // - registerPathHandler: function(path, handler) - { - this._handler.registerPathHandler(path, handler); - }, - - // - // see nsIHttpServer.registerErrorHandler - // - registerErrorHandler: function(code, handler) - { - this._handler.registerErrorHandler(code, handler); - }, - - // - // see nsIHttpServer.setIndexHandler - // - setIndexHandler: function(handler) - { - this._handler.setIndexHandler(handler); - }, - - // - // see nsIHttpServer.registerContentType - // - registerContentType: function(ext, type) - { - this._handler.registerContentType(ext, type); - }, - - // - // see nsIHttpServer.serverIdentity - // - get identity() - { - return this._identity; - }, - - // - // see nsIHttpServer.getState - // - getState: function(path, k) - { - return this._handler._getState(path, k); - }, - - // - // see nsIHttpServer.setState - // - setState: function(path, k, v) - { - return this._handler._setState(path, k, v); - }, - - // - // see nsIHttpServer.getSharedState - // - getSharedState: function(k) - { - return this._handler._getSharedState(k); - }, - - // - // see nsIHttpServer.setSharedState - // - setSharedState: function(k, v) - { - return this._handler._setSharedState(k, v); - }, - - // - // see nsIHttpServer.getObjectState - // - getObjectState: function(k) - { - return this._handler._getObjectState(k); - }, - - // - // see nsIHttpServer.setObjectState - // - setObjectState: function(k, v) - { - return this._handler._setObjectState(k, v); - }, - - - // NSISUPPORTS - - // - // see nsISupports.QueryInterface - // - QueryInterface: function(iid) - { - if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // NON-XPCOM PUBLIC API - - /** -* Returns true iff this server is not running (and is not in the process of -* serving any requests still to be processed when the server was last -* stopped after being run). -*/ - isStopped: function() - { - return this._socketClosed && !this._hasOpenConnections(); - }, - - // PRIVATE IMPLEMENTATION - - /** True if this server has any open connections to it, false otherwise. */ - _hasOpenConnections: function() - { - // - // If we have any open connections, they're tracked as numeric properties on - // |this._connections|. The non-standard __count__ property could be used - // to check whether there are any properties, but standard-wise, even - // looking forward to ES5, there's no less ugly yet still O(1) way to do - // this. - // - for (var n in this._connections) - return true; - return false; - }, - - /** Calls the server-stopped callback provided when stop() was called. */ - _notifyStopped: function() - { - NS_ASSERT(this._stopCallback !== null, "double-notifying?"); - NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now"); - - // - // NB: We have to grab this now, null out the member, *then* call the - // callback here, or otherwise the callback could (indirectly) futz with - // this._stopCallback by starting and immediately stopping this, at - // which point we'd be nulling out a field we no longer have a right to - // modify. - // - var callback = this._stopCallback; - this._stopCallback = null; - try - { - callback(); - } - catch (e) - { - // not throwing because this is specified as being usually (but not - // always) asynchronous - dump("!!! error running onStopped callback: " + e + "\n"); - } - }, - - /** -* Notifies this server that the given connection has been closed. -* -* @param connection : Connection -* the connection that was closed -*/ - _connectionClosed: function(connection) - { - NS_ASSERT(connection.number in this._connections, - "closing a connection " + this + " that we never added to the " + - "set of open connections?"); - NS_ASSERT(this._connections[connection.number] === connection, - "connection number mismatch? " + - this._connections[connection.number]); - delete this._connections[connection.number]; - - // Fire a pending server-stopped notification if it's our responsibility. - if (!this._hasOpenConnections() && this._socketClosed) - this._notifyStopped(); - }, - - /** -* Requests that the server be shut down when possible. -*/ - _requestQuit: function() - { - dumpn(">>> requesting a quit"); - dumpStack(); - this._doQuit = true; - } -}; - - -// -// RFC 2396 section 3.2.2: -// -// host = hostname | IPv4address -// hostname = *( domainlabel "." ) toplabel [ "." ] -// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum -// toplabel = alpha | alpha *( alphanum | "-" ) alphanum -// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit -// - -const HOST_REGEX = - new RegExp("^(?:" + - // *( domainlabel "." ) - "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" + - // toplabel - "[a-z](?:[a-z0-9-]*[a-z0-9])?" + - "|" + - // IPv4 address - "\\d+\\.\\d+\\.\\d+\\.\\d+" + - ")$", - "i"); - - -/** -* Represents the identity of a server. An identity consists of a set of -* (scheme, host, port) tuples denoted as locations (allowing a single server to -* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any -* host/port). Any incoming request must be to one of these locations, or it -* will be rejected with an HTTP 400 error. One location, denoted as the -* primary location, is the location assigned in contexts where a location -* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests. -* -* A single identity may contain at most one location per unique host/port pair; -* other than that, no restrictions are placed upon what locations may -* constitute an identity. -*/ -function ServerIdentity() -{ - /** The scheme of the primary location. */ - this._primaryScheme = "http"; - - /** The hostname of the primary location. */ - this._primaryHost = "127.0.0.1" - - /** The port number of the primary location. */ - this._primaryPort = -1; - - /** -* The current port number for the corresponding server, stored so that a new -* primary location can always be set if the current one is removed. -*/ - this._defaultPort = -1; - - /** -* Maps hosts to maps of ports to schemes, e.g. the following would represent -* https://example.com:789/ and http://example.org/: -* -* { -* "xexample.com": { 789: "https" }, -* "xexample.org": { 80: "http" } -* } -* -* Note the "x" prefix on hostnames, which prevents collisions with special -* JS names like "prototype". -*/ - this._locations = { "xlocalhost": {} }; -} -ServerIdentity.prototype = -{ - // NSIHTTPSERVERIDENTITY - - // - // see nsIHttpServerIdentity.primaryScheme - // - get primaryScheme() - { - if (this._primaryPort === -1) - throw Cr.NS_ERROR_NOT_INITIALIZED; - return this._primaryScheme; - }, - - // - // see nsIHttpServerIdentity.primaryHost - // - get primaryHost() - { - if (this._primaryPort === -1) - throw Cr.NS_ERROR_NOT_INITIALIZED; - return this._primaryHost; - }, - - // - // see nsIHttpServerIdentity.primaryPort - // - get primaryPort() - { - if (this._primaryPort === -1) - throw Cr.NS_ERROR_NOT_INITIALIZED; - return this._primaryPort; - }, - - // - // see nsIHttpServerIdentity.add - // - add: function(scheme, host, port) - { - this._validate(scheme, host, port); - - var entry = this._locations["x" + host]; - if (!entry) - this._locations["x" + host] = entry = {}; - - entry[port] = scheme; - }, - - // - // see nsIHttpServerIdentity.remove - // - remove: function(scheme, host, port) - { - this._validate(scheme, host, port); - - var entry = this._locations["x" + host]; - if (!entry) - return false; - - var present = port in entry; - delete entry[port]; - - if (this._primaryScheme == scheme && - this._primaryHost == host && - this._primaryPort == port && - this._defaultPort !== -1) - { - // Always keep at least one identity in existence at any time, unless - // we're in the process of shutting down (the last condition above). - this._primaryPort = -1; - this._initialize(this._defaultPort, host, false); - } - - return present; - }, - - // - // see nsIHttpServerIdentity.has - // - has: function(scheme, host, port) - { - this._validate(scheme, host, port); - - return "x" + host in this._locations && - scheme === this._locations["x" + host][port]; - }, - - // - // see nsIHttpServerIdentity.has - // - getScheme: function(host, port) - { - this._validate("http", host, port); - - var entry = this._locations["x" + host]; - if (!entry) - return ""; - - return entry[port] || ""; - }, - - // - // see nsIHttpServerIdentity.setPrimary - // - setPrimary: function(scheme, host, port) - { - this._validate(scheme, host, port); - - this.add(scheme, host, port); - - this._primaryScheme = scheme; - this._primaryHost = host; - this._primaryPort = port; - }, - - - // NSISUPPORTS - - // - // see nsISupports.QueryInterface - // - QueryInterface: function(iid) - { - if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // PRIVATE IMPLEMENTATION - - /** -* Initializes the primary name for the corresponding server, based on the -* provided port number. -*/ - _initialize: function(port, host, addSecondaryDefault) - { - this._host = host; - if (this._primaryPort !== -1) - this.add("http", host, port); - else - this.setPrimary("http", "localhost", port); - this._defaultPort = port; - - // Only add this if we're being called at server startup - if (addSecondaryDefault && host != "127.0.0.1") - this.add("http", "127.0.0.1", port); - }, - - /** -* Called at server shutdown time, unsets the primary location only if it was -* the default-assigned location and removes the default location from the -* set of locations used. -*/ - _teardown: function() - { - if (this._host != "127.0.0.1") { - // Not the default primary location, nothing special to do here - this.remove("http", "127.0.0.1", this._defaultPort); - } - - // This is a *very* tricky bit of reasoning here; make absolutely sure the - // tests for this code pass before you commit changes to it. - if (this._primaryScheme == "http" && - this._primaryHost == this._host && - this._primaryPort == this._defaultPort) - { - // Make sure we don't trigger the readding logic in .remove(), then remove - // the default location. - var port = this._defaultPort; - this._defaultPort = -1; - this.remove("http", this._host, port); - - // Ensure a server start triggers the setPrimary() path in ._initialize() - this._primaryPort = -1; - } - else - { - // No reason not to remove directly as it's not our primary location - this.remove("http", this._host, this._defaultPort); - } - }, - - /** -* Ensures scheme, host, and port are all valid with respect to RFC 2396. -* -* @throws NS_ERROR_ILLEGAL_VALUE -* if any argument doesn't match the corresponding production -*/ - _validate: function(scheme, host, port) - { - if (scheme !== "http" && scheme !== "https") - { - dumpn("*** server only supports http/https schemes: '" + scheme + "'"); - dumpStack(); - throw Cr.NS_ERROR_ILLEGAL_VALUE; - } - if (!HOST_REGEX.test(host)) - { - dumpn("*** unexpected host: '" + host + "'"); - throw Cr.NS_ERROR_ILLEGAL_VALUE; - } - if (port < 0 || port > 65535) - { - dumpn("*** unexpected port: '" + port + "'"); - throw Cr.NS_ERROR_ILLEGAL_VALUE; - } - } -}; - - -/** -* Represents a connection to the server (and possibly in the future the thread -* on which the connection is processed). -* -* @param input : nsIInputStream -* stream from which incoming data on the connection is read -* @param output : nsIOutputStream -* stream to write data out the connection -* @param server : nsHttpServer -* the server handling the connection -* @param port : int -* the port on which the server is running -* @param outgoingPort : int -* the outgoing port used by this connection -* @param number : uint -* a serial number used to uniquely identify this connection -*/ -function Connection(input, output, server, port, outgoingPort, number) -{ - dumpn("*** opening new connection " + number + " on port " + outgoingPort); - - /** Stream of incoming data. */ - this.input = input; - - /** Stream for outgoing data. */ - this.output = output; - - /** The server associated with this request. */ - this.server = server; - - /** The port on which the server is running. */ - this.port = port; - - /** The outgoing poort used by this connection. */ - this._outgoingPort = outgoingPort; - - /** The serial number of this connection. */ - this.number = number; - - /** -* The request for which a response is being generated, null if the -* incoming request has not been fully received or if it had errors. -*/ - this.request = null; - - /** State variables for debugging. */ - this._closed = this._processed = false; -} -Connection.prototype = -{ - /** Closes this connection's input/output streams. */ - close: function() - { - dumpn("*** closing connection " + this.number + - " on port " + this._outgoingPort); - - this.input.close(); - this.output.close(); - this._closed = true; - - var server = this.server; - server._connectionClosed(this); - - // If an error triggered a server shutdown, act on it now - if (server._doQuit) - server.stop(function() { /* not like we can do anything better */ }); - }, - - /** -* Initiates processing of this connection, using the data in the given -* request. -* -* @param request : Request -* the request which should be processed -*/ - process: function(request) - { - NS_ASSERT(!this._closed && !this._processed); - - this._processed = true; - - this.request = request; - this.server._handler.handleResponse(this); - }, - - /** -* Initiates processing of this connection, generating a response with the -* given HTTP error code. -* -* @param code : uint -* an HTTP code, so in the range [0, 1000) -* @param request : Request -* incomplete data about the incoming request (since there were errors -* during its processing -*/ - processError: function(code, request) - { - NS_ASSERT(!this._closed && !this._processed); - - this._processed = true; - this.request = request; - this.server._handler.handleError(code, this); - }, - - /** Converts this to a string for debugging purposes. */ - toString: function() - { - return "<Connection(" + this.number + - (this.request ? ", " + this.request.path : "") +"): " + - (this._closed ? "closed" : "open") + ">"; - } -}; - - - -/** Returns an array of count bytes from the given input stream. */ -function readBytes(inputStream, count) -{ - return new BinaryInputStream(inputStream).readByteArray(count); -} - - - -/** Request reader processing states; see RequestReader for details. */ -const READER_IN_REQUEST_LINE = 0; -const READER_IN_HEADERS = 1; -const READER_IN_BODY = 2; -const READER_FINISHED = 3; - - -/** -* Reads incoming request data asynchronously, does any necessary preprocessing, -* and forwards it to the request handler. Processing occurs in three states: -* -* READER_IN_REQUEST_LINE Reading the request's status line -* READER_IN_HEADERS Reading headers in the request -* READER_IN_BODY Reading the body of the request -* READER_FINISHED Entire request has been read and processed -* -* During the first two stages, initial metadata about the request is gathered -* into a Request object. Once the status line and headers have been processed, -* we start processing the body of the request into the Request. Finally, when -* the entire body has been read, we create a Response and hand it off to the -* ServerHandler to be given to the appropriate request handler. -* -* @param connection : Connection -* the connection for the request being read -*/ -function RequestReader(connection) -{ - /** Connection metadata for this request. */ - this._connection = connection; - - /** -* A container providing line-by-line access to the raw bytes that make up the -* data which has been read from the connection but has not yet been acted -* upon (by passing it to the request handler or by extracting request -* metadata from it). -*/ - this._data = new LineData(); - - /** -* The amount of data remaining to be read from the body of this request. -* After all headers in the request have been read this is the value in the -* Content-Length header, but as the body is read its value decreases to zero. -*/ - this._contentLength = 0; - - /** The current state of parsing the incoming request. */ - this._state = READER_IN_REQUEST_LINE; - - /** Metadata constructed from the incoming request for the request handler. */ - this._metadata = new Request(connection.port); - - /** -* Used to preserve state if we run out of line data midway through a -* multi-line header. _lastHeaderName stores the name of the header, while -* _lastHeaderValue stores the value we've seen so far for the header. -* -* These fields are always either both undefined or both strings. -*/ - this._lastHeaderName = this._lastHeaderValue = undefined; -} -RequestReader.prototype = -{ - // NSIINPUTSTREAMCALLBACK - - /** -* Called when more data from the incoming request is available. This method -* then reads the available data from input and deals with that data as -* necessary, depending upon the syntax of already-downloaded data. -* -* @param input : nsIAsyncInputStream -* the stream of incoming data from the connection -*/ - onInputStreamReady: function(input) - { - dumpn("*** onInputStreamReady(input=" + input + ") on thread " + - gThreadManager.currentThread + " (main is " + - gThreadManager.mainThread + ")"); - dumpn("*** this._state == " + this._state); - - // Handle cases where we get more data after a request error has been - // discovered but *before* we can close the connection. - var data = this._data; - if (!data) - return; - - try - { - data.appendBytes(readBytes(input, input.available())); - } - catch (e) - { - if (streamClosed(e)) - { - dumpn("*** WARNING: unexpected error when reading from socket; will " + - "be treated as if the input stream had been closed"); - dumpn("*** WARNING: actual error was: " + e); - } - - // We've lost a race -- input has been closed, but we're still expecting - // to read more data. available() will throw in this case, and since - // we're dead in the water now, destroy the connection. - dumpn("*** onInputStreamReady called on a closed input, destroying " + - "connection"); - this._connection.close(); - return; - } - - switch (this._state) - { - default: - NS_ASSERT(false, "invalid state: " + this._state); - break; - - case READER_IN_REQUEST_LINE: - if (!this._processRequestLine()) - break; - /* fall through */ - - case READER_IN_HEADERS: - if (!this._processHeaders()) - break; - /* fall through */ - - case READER_IN_BODY: - this._processBody(); - } - - if (this._state != READER_FINISHED) - input.asyncWait(this, 0, 0, gThreadManager.currentThread); - }, - - // - // see nsISupports.QueryInterface - // - QueryInterface: function(aIID) - { - if (aIID.equals(Ci.nsIInputStreamCallback) || - aIID.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // PRIVATE API - - /** -* Processes unprocessed, downloaded data as a request line. -* -* @returns boolean -* true iff the request line has been fully processed -*/ - _processRequestLine: function() - { - NS_ASSERT(this._state == READER_IN_REQUEST_LINE); - - // Servers SHOULD ignore any empty line(s) received where a Request-Line - // is expected (section 4.1). - var data = this._data; - var line = {}; - var readSuccess; - while ((readSuccess = data.readLine(line)) && line.value == "") - dumpn("*** ignoring beginning blank line..."); - - // if we don't have a full line, wait until we do - if (!readSuccess) - return false; - - // we have the first non-blank line - try - { - this._parseRequestLine(line.value); - this._state = READER_IN_HEADERS; - return true; - } - catch (e) - { - this._handleError(e); - return false; - } - }, - - /** -* Processes stored data, assuming it is either at the beginning or in -* the middle of processing request headers. -* -* @returns boolean -* true iff header data in the request has been fully processed -*/ - _processHeaders: function() - { - NS_ASSERT(this._state == READER_IN_HEADERS); - - // XXX things to fix here: - // - // - need to support RFC 2047-encoded non-US-ASCII characters - - try - { - var done = this._parseHeaders(); - if (done) - { - var request = this._metadata; - - // XXX this is wrong for requests with transfer-encodings applied to - // them, particularly chunked (which by its nature can have no - // meaningful Content-Length header)! - this._contentLength = request.hasHeader("Content-Length") - ? parseInt(request.getHeader("Content-Length"), 10) - : 0; - dumpn("_processHeaders, Content-length=" + this._contentLength); - - this._state = READER_IN_BODY; - } - return done; - } - catch (e) - { - this._handleError(e); - return false; - } - }, - - /** -* Processes stored data, assuming it is either at the beginning or in -* the middle of processing the request body. -* -* @returns boolean -* true iff the request body has been fully processed -*/ - _processBody: function() - { - NS_ASSERT(this._state == READER_IN_BODY); - - // XXX handle chunked transfer-coding request bodies! - - try - { - if (this._contentLength > 0) - { - var data = this._data.purge(); - var count = Math.min(data.length, this._contentLength); - dumpn("*** loading data=" + data + " len=" + data.length + - " excess=" + (data.length - count)); - - var bos = new BinaryOutputStream(this._metadata._bodyOutputStream); - bos.writeByteArray(data, count); - this._contentLength -= count; - } - - dumpn("*** remaining body data len=" + this._contentLength); - if (this._contentLength == 0) - { - this._validateRequest(); - this._state = READER_FINISHED; - this._handleResponse(); - return true; - } - - return false; - } - catch (e) - { - this._handleError(e); - return false; - } - }, - - /** -* Does various post-header checks on the data in this request. -* -* @throws : HttpError -* if the request was malformed in some way -*/ - _validateRequest: function() - { - NS_ASSERT(this._state == READER_IN_BODY); - - dumpn("*** _validateRequest"); - - var metadata = this._metadata; - var headers = metadata._headers; - - // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header - var identity = this._connection.server.identity; - if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1)) - { - if (!headers.hasHeader("Host")) - { - dumpn("*** malformed HTTP/1.1 or greater request with no Host header!"); - throw HTTP_400; - } - - // If the Request-URI wasn't absolute, then we need to determine our host. - // We have to determine what scheme was used to access us based on the - // server identity data at this point, because the request just doesn't - // contain enough data on its own to do this, sadly. - if (!metadata._host) - { - var host, port; - var hostPort = headers.getHeader("Host"); - var colon = hostPort.indexOf(":"); - if (colon < 0) - { - host = hostPort; - port = ""; - } - else - { - host = hostPort.substring(0, colon); - port = hostPort.substring(colon + 1); - } - - // NB: We allow an empty port here because, oddly, a colon may be - // present even without a port number, e.g. "example.com:"; in this - // case the default port applies. - if (!HOST_REGEX.test(host) || !/^\d*$/.test(port)) - { - dumpn("*** malformed hostname (" + hostPort + ") in Host " + - "header, 400 time"); - throw HTTP_400; - } - - // If we're not given a port, we're stuck, because we don't know what - // scheme to use to look up the correct port here, in general. Since - // the HTTPS case requires a tunnel/proxy and thus requires that the - // requested URI be absolute (and thus contain the necessary - // information), let's assume HTTP will prevail and use that. - port = +port || 80; - - var scheme = identity.getScheme(host, port); - if (!scheme) - { - dumpn("*** unrecognized hostname (" + hostPort + ") in Host " + - "header, 400 time"); - throw HTTP_400; - } - - metadata._scheme = scheme; - metadata._host = host; - metadata._port = port; - } - } - else - { - NS_ASSERT(metadata._host === undefined, - "HTTP/1.0 doesn't allow absolute paths in the request line!"); - - metadata._scheme = identity.primaryScheme; - metadata._host = identity.primaryHost; - metadata._port = identity.primaryPort; - } - - NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port), - "must have a location we recognize by now!"); - }, - - /** -* Handles responses in case of error, either in the server or in the request. -* -* @param e -* the specific error encountered, which is an HttpError in the case where -* the request is in some way invalid or cannot be fulfilled; if this isn't -* an HttpError we're going to be paranoid and shut down, because that -* shouldn't happen, ever -*/ - _handleError: function(e) - { - // Don't fall back into normal processing! - this._state = READER_FINISHED; - - var server = this._connection.server; - if (e instanceof HttpError) - { - var code = e.code; - } - else - { - dumpn("!!! UNEXPECTED ERROR: " + e + - (e.lineNumber ? ", line " + e.lineNumber : "")); - - // no idea what happened -- be paranoid and shut down - code = 500; - server._requestQuit(); - } - - // make attempted reuse of data an error - this._data = null; - - this._connection.processError(code, this._metadata); - }, - - /** -* Now that we've read the request line and headers, we can actually hand off -* the request to be handled. -* -* This method is called once per request, after the request line and all -* headers and the body, if any, have been received. -*/ - _handleResponse: function() - { - NS_ASSERT(this._state == READER_FINISHED); - - // We don't need the line-based data any more, so make attempted reuse an - // error. - this._data = null; - - this._connection.process(this._metadata); - }, - - - // PARSING - - /** -* Parses the request line for the HTTP request associated with this. -* -* @param line : string -* the request line -*/ - _parseRequestLine: function(line) - { - NS_ASSERT(this._state == READER_IN_REQUEST_LINE); - - dumpn("*** _parseRequestLine('" + line + "')"); - - var metadata = this._metadata; - - // clients and servers SHOULD accept any amount of SP or HT characters - // between fields, even though only a single SP is required (section 19.3) - var request = line.split(/[ \t]+/); - if (!request || request.length != 3) - throw HTTP_400; - - metadata._method = request[0]; - - // get the HTTP version - var ver = request[2]; - var match = ver.match(/^HTTP\/(\d+\.\d+)$/); - if (!match) - throw HTTP_400; - - // determine HTTP version - try - { - metadata._httpVersion = new nsHttpVersion(match[1]); - if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0)) - throw "unsupported HTTP version"; - } - catch (e) - { - // we support HTTP/1.0 and HTTP/1.1 only - throw HTTP_501; - } - - - var fullPath = request[1]; - var serverIdentity = this._connection.server.identity; - - var scheme, host, port; - - if (fullPath.charAt(0) != "/") - { - // No absolute paths in the request line in HTTP prior to 1.1 - if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1)) - throw HTTP_400; - - try - { - var uri = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .newURI(fullPath, null, null); - fullPath = uri.path; - scheme = uri.scheme; - host = metadata._host = uri.asciiHost; - port = uri.port; - if (port === -1) - { - if (scheme === "http") - port = 80; - else if (scheme === "https") - port = 443; - else - throw HTTP_400; - } - } - catch (e) - { - // If the host is not a valid host on the server, the response MUST be a - // 400 (Bad Request) error message (section 5.2). Alternately, the URI - // is malformed. - throw HTTP_400; - } - - if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/") - throw HTTP_400; - } - - var splitter = fullPath.indexOf("?"); - if (splitter < 0) - { - // _queryString already set in ctor - metadata._path = fullPath; - } - else - { - metadata._path = fullPath.substring(0, splitter); - metadata._queryString = fullPath.substring(splitter + 1); - } - - metadata._scheme = scheme; - metadata._host = host; - metadata._port = port; - }, - - /** -* Parses all available HTTP headers in this until the header-ending CRLFCRLF, -* adding them to the store of headers in the request. -* -* @throws -* HTTP_400 if the headers are malformed -* @returns boolean -* true if all headers have now been processed, false otherwise -*/ - _parseHeaders: function() - { - NS_ASSERT(this._state == READER_IN_HEADERS); - - dumpn("*** _parseHeaders"); - - var data = this._data; - - var headers = this._metadata._headers; - var lastName = this._lastHeaderName; - var lastVal = this._lastHeaderValue; - - var line = {}; - while (true) - { - NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)), - lastName === undefined ? - "lastVal without lastName? lastVal: '" + lastVal + "'" : - "lastName without lastVal? lastName: '" + lastName + "'"); - - if (!data.readLine(line)) - { - // save any data we have from the header we might still be processing - this._lastHeaderName = lastName; - this._lastHeaderValue = lastVal; - return false; - } - - var lineText = line.value; - var firstChar = lineText.charAt(0); - - // blank line means end of headers - if (lineText == "") - { - // we're finished with the previous header - if (lastName) - { - try - { - headers.setHeader(lastName, lastVal, true); - } - catch (e) - { - dumpn("*** e == " + e); - throw HTTP_400; - } - } - else - { - // no headers in request -- valid for HTTP/1.0 requests - } - - // either way, we're done processing headers - this._state = READER_IN_BODY; - return true; - } - else if (firstChar == " " || firstChar == "\t") - { - // multi-line header if we've already seen a header line - if (!lastName) - { - // we don't have a header to continue! - throw HTTP_400; - } - - // append this line's text to the value; starts with SP/HT, so no need - // for separating whitespace - lastVal += lineText; - } - else - { - // we have a new header, so set the old one (if one existed) - if (lastName) - { - try - { - headers.setHeader(lastName, lastVal, true); - } - catch (e) - { - dumpn("*** e == " + e); - throw HTTP_400; - } - } - - var colon = lineText.indexOf(":"); // first colon must be splitter - if (colon < 1) - { - // no colon or missing header field-name - throw HTTP_400; - } - - // set header name, value (to be set in the next loop, usually) - lastName = lineText.substring(0, colon); - lastVal = lineText.substring(colon + 1); - } // empty, continuation, start of header - } // while (true) - } -}; - - -/** The character codes for CR and LF. */ -const CR = 0x0D, LF = 0x0A; - -/** -* Calculates the number of characters before the first CRLF pair in array, or -* -1 if the array contains no CRLF pair. -* -* @param array : Array -* an array of numbers in the range [0, 256), each representing a single -* character; the first CRLF is the lowest index i where -* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|, -* if such an |i| exists, and -1 otherwise -* @returns int -* the index of the first CRLF if any were present, -1 otherwise -*/ -function findCRLF(array) -{ - for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1)) - { - if (array[i + 1] == LF) - return i; - } - return -1; -} - - -/** -* A container which provides line-by-line access to the arrays of bytes with -* which it is seeded. -*/ -function LineData() -{ - /** An array of queued bytes from which to get line-based characters. */ - this._data = []; -} -LineData.prototype = -{ - /** -* Appends the bytes in the given array to the internal data cache maintained -* by this. -*/ - appendBytes: function(bytes) - { - Array.prototype.push.apply(this._data, bytes); - }, - - /** -* Removes and returns a line of data, delimited by CRLF, from this. -* -* @param out -* an object whose "value" property will be set to the first line of text -* present in this, sans CRLF, if this contains a full CRLF-delimited line -* of text; if this doesn't contain enough data, the value of the property -* is undefined -* @returns boolean -* true if a full line of data could be read from the data in this, false -* otherwise -*/ - readLine: function(out) - { - var data = this._data; - var length = findCRLF(data); - if (length < 0) - return false; - - // - // We have the index of the CR, so remove all the characters, including - // CRLF, from the array with splice, and convert the removed array into the - // corresponding string, from which we then strip the trailing CRLF. - // - // Getting the line in this matter acknowledges that substring is an O(1) - // operation in SpiderMonkey because strings are immutable, whereas two - // splices, both from the beginning of the data, are less likely to be as - // cheap as a single splice plus two extra character conversions. - // - var line = String.fromCharCode.apply(null, data.splice(0, length + 2)); - out.value = line.substring(0, length); - - return true; - }, - - /** -* Removes the bytes currently within this and returns them in an array. -* -* @returns Array -* the bytes within this when this method is called -*/ - purge: function() - { - var data = this._data; - this._data = []; - return data; - } -}; - - - -/** -* Creates a request-handling function for an nsIHttpRequestHandler object. -*/ -function createHandlerFunc(handler) -{ - return function(metadata, response) { handler.handle(metadata, response); }; -} - - -/** -* The default handler for directories; writes an HTML response containing a -* slightly-formatted directory listing. -*/ -function defaultIndexHandler(metadata, response) -{ - response.setHeader("Content-Type", "text/html", false); - - var path = htmlEscape(decodeURI(metadata.path)); - - // - // Just do a very basic bit of directory listings -- no need for too much - // fanciness, especially since we don't have a style sheet in which we can - // stick rules (don't want to pollute the default path-space). - // - - var body = '<html>\ -<head>\ -<title>' + path + '</title>\ -</head>\ -<body>\ -<h1>' + path + '</h1>\ -<ol style="list-style-type: none">'; - - var directory = metadata.getProperty("directory").QueryInterface(Ci.nsILocalFile); - NS_ASSERT(directory && directory.isDirectory()); - - var fileList = []; - var files = directory.directoryEntries; - while (files.hasMoreElements()) - { - var f = files.getNext().QueryInterface(Ci.nsIFile); - var name = f.leafName; - if (!f.isHidden() && - (name.charAt(name.length - 1) != HIDDEN_CHAR || - name.charAt(name.length - 2) == HIDDEN_CHAR)) - fileList.push(f); - } - - fileList.sort(fileSort); - - for (var i = 0; i < fileList.length; i++) - { - var file = fileList[i]; - try - { - var name = file.leafName; - if (name.charAt(name.length - 1) == HIDDEN_CHAR) - name = name.substring(0, name.length - 1); - var sep = file.isDirectory() ? "/" : ""; - - // Note: using " to delimit the attribute here because encodeURIComponent - // passes through '. - var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' + - htmlEscape(name) + sep + - '</a></li>'; - - body += item; - } - catch (e) { /* some file system error, ignore the file */ } - } - - body += ' </ol>\ -</body>\ -</html>'; - - response.bodyOutputStream.write(body, body.length); -} - -/** -* Sorts a and b (nsIFile objects) into an aesthetically pleasing order. -*/ -function fileSort(a, b) -{ - var dira = a.isDirectory(), dirb = b.isDirectory(); - - if (dira && !dirb) - return -1; - if (dirb && !dira) - return 1; - - var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase(); - return nameb > namea ? -1 : 1; -} - - -/** -* Converts an externally-provided path into an internal path for use in -* determining file mappings. -* -* @param path -* the path to convert -* @param encoded -* true if the given path should be passed through decodeURI prior to -* conversion -* @throws URIError -* if path is incorrectly encoded -*/ -function toInternalPath(path, encoded) -{ - if (encoded) - path = decodeURI(path); - - var comps = path.split("/"); - for (var i = 0, sz = comps.length; i < sz; i++) - { - var comp = comps[i]; - if (comp.charAt(comp.length - 1) == HIDDEN_CHAR) - comps[i] = comp + HIDDEN_CHAR; - } - return comps.join("/"); -} - - -/** -* Adds custom-specified headers for the given file to the given response, if -* any such headers are specified. -* -* @param file -* the file on the disk which is to be written -* @param metadata -* metadata about the incoming request -* @param response -* the Response to which any specified headers/data should be written -* @throws HTTP_500 -* if an error occurred while processing custom-specified headers -*/ -function maybeAddHeaders(file, metadata, response) -{ - var name = file.leafName; - if (name.charAt(name.length - 1) == HIDDEN_CHAR) - name = name.substring(0, name.length - 1); - - var headerFile = file.parent; - headerFile.append(name + HEADERS_SUFFIX); - - if (!headerFile.exists()) - return; - - const PR_RDONLY = 0x01; - var fis = new FileInputStream(headerFile, PR_RDONLY, parseInt("444", 8), - Ci.nsIFileInputStream.CLOSE_ON_EOF); - - try - { - var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0); - lis.QueryInterface(Ci.nsIUnicharLineInputStream); - - var line = {value: ""}; - var more = lis.readLine(line); - - if (!more && line.value == "") - return; - - - // request line - - var status = line.value; - if (status.indexOf("HTTP ") == 0) - { - status = status.substring(5); - var space = status.indexOf(" "); - var code, description; - if (space < 0) - { - code = status; - description = ""; - } - else - { - code = status.substring(0, space); - description = status.substring(space + 1, status.length); - } - - response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description); - - line.value = ""; - more = lis.readLine(line); - } - - // headers - while (more || line.value != "") - { - var header = line.value; - var colon = header.indexOf(":"); - - response.setHeader(header.substring(0, colon), - header.substring(colon + 1, header.length), - false); // allow overriding server-set headers - - line.value = ""; - more = lis.readLine(line); - } - } - catch (e) - { - dumpn("WARNING: error in headers for " + metadata.path + ": " + e); - throw HTTP_500; - } - finally - { - fis.close(); - } -} - - -/** -* An object which handles requests for a server, executing default and -* overridden behaviors as instructed by the code which uses and manipulates it. -* Default behavior includes the paths / and /trace (diagnostics), with some -* support for HTTP error pages for various codes and fallback to HTTP 500 if -* those codes fail for any reason. -* -* @param server : nsHttpServer -* the server in which this handler is being used -*/ -function ServerHandler(server) -{ - // FIELDS - - /** -* The nsHttpServer instance associated with this handler. -*/ - this._server = server; - - /** -* A FileMap object containing the set of path->nsILocalFile mappings for -* all directory mappings set in the server (e.g., "/" for /var/www/html/, -* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2). -* -* Note carefully: the leading and trailing "/" in each path (not file) are -* removed before insertion to simplify the code which uses this. You have -* been warned! -*/ - this._pathDirectoryMap = new FileMap(); - - /** -* Custom request handlers for the server in which this resides. Path-handler -* pairs are stored as property-value pairs in this property. -* -* @see ServerHandler.prototype._defaultPaths -*/ - this._overridePaths = {}; - - /** -* Custom request handlers for the error handlers in the server in which this -* resides. Path-handler pairs are stored as property-value pairs in this -* property. -* -* @see ServerHandler.prototype._defaultErrors -*/ - this._overrideErrors = {}; - - /** -* Maps file extensions to their MIME types in the server, overriding any -* mapping that might or might not exist in the MIME service. -*/ - this._mimeMappings = {}; - - /** -* The default handler for requests for directories, used to serve directories -* when no index file is present. -*/ - this._indexHandler = defaultIndexHandler; - - /** Per-path state storage for the server. */ - this._state = {}; - - /** Entire-server state storage. */ - this._sharedState = {}; - - /** Entire-server state storage for nsISupports values. */ - this._objectState = {}; -} -ServerHandler.prototype = -{ - // PUBLIC API - - /** -* Handles a request to this server, responding to the request appropriately -* and initiating server shutdown if necessary. -* -* This method never throws an exception. -* -* @param connection : Connection -* the connection for this request -*/ - handleResponse: function(connection) - { - var request = connection.request; - var response = new Response(connection); - - var path = request.path; - dumpn("*** path == " + path); - - try - { - try - { - if (path in this._overridePaths) - { - // explicit paths first, then files based on existing directory mappings, - // then (if the file doesn't exist) built-in server default paths - dumpn("calling override for " + path); - this._overridePaths[path](request, response); - } - else - { - this._handleDefault(request, response); - } - } - catch (e) - { - if (response.partiallySent()) - { - response.abort(e); - return; - } - - if (!(e instanceof HttpError)) - { - dumpn("*** unexpected error: e == " + e); - throw HTTP_500; - } - if (e.code !== 404) - throw e; - - dumpn("*** default: " + (path in this._defaultPaths)); - - response = new Response(connection); - if (path in this._defaultPaths) - this._defaultPaths[path](request, response); - else - throw HTTP_404; - } - } - catch (e) - { - if (response.partiallySent()) - { - response.abort(e); - return; - } - - var errorCode = "internal"; - - try - { - if (!(e instanceof HttpError)) - throw e; - - errorCode = e.code; - dumpn("*** errorCode == " + errorCode); - - response = new Response(connection); - if (e.customErrorHandling) - e.customErrorHandling(response); - this._handleError(errorCode, request, response); - return; - } - catch (e2) - { - dumpn("*** error handling " + errorCode + " error: " + - "e2 == " + e2 + ", shutting down server"); - - connection.server._requestQuit(); - response.abort(e2); - return; - } - } - - response.complete(); - }, - - // - // see nsIHttpServer.registerFile - // - registerFile: function(path, file) - { - if (!file) - { - dumpn("*** unregistering '" + path + "' mapping"); - delete this._overridePaths[path]; - return; - } - - dumpn("*** registering '" + path + "' as mapping to " + file.path); - file = file.clone(); - - var self = this; - this._overridePaths[path] = - function(request, response) - { - if (!file.exists()) - throw HTTP_404; - - response.setStatusLine(request.httpVersion, 200, "OK"); - self._writeFileResponse(request, file, response, 0, file.fileSize); - }; - }, - - // - // see nsIHttpServer.registerPathHandler - // - registerPathHandler: function(path, handler) - { - // XXX true path validation! - if (path.charAt(0) != "/") - throw Cr.NS_ERROR_INVALID_ARG; - - this._handlerToField(handler, this._overridePaths, path); - }, - - // - // see nsIHttpServer.registerDirectory - // - registerDirectory: function(path, directory) - { - // strip off leading and trailing '/' so that we can use lastIndexOf when - // determining exactly how a path maps onto a mapped directory -- - // conditional is required here to deal with "/".substring(1, 0) being - // converted to "/".substring(0, 1) per the JS specification - var key = path.length == 1 ? "" : path.substring(1, path.length - 1); - - // the path-to-directory mapping code requires that the first character not - // be "/", or it will go into an infinite loop - if (key.charAt(0) == "/") - throw Cr.NS_ERROR_INVALID_ARG; - - key = toInternalPath(key, false); - - if (directory) - { - dumpn("*** mapping '" + path + "' to the location " + directory.path); - this._pathDirectoryMap.put(key, directory); - } - else - { - dumpn("*** removing mapping for '" + path + "'"); - this._pathDirectoryMap.put(key, null); - } - }, - - // - // see nsIHttpServer.registerErrorHandler - // - registerErrorHandler: function(err, handler) - { - if (!(err in HTTP_ERROR_CODES)) - dumpn("*** WARNING: registering non-HTTP/1.1 error code " + - "(" + err + ") handler -- was this intentional?"); - - this._handlerToField(handler, this._overrideErrors, err); - }, - - // - // see nsIHttpServer.setIndexHandler - // - setIndexHandler: function(handler) - { - if (!handler) - handler = defaultIndexHandler; - else if (typeof(handler) != "function") - handler = createHandlerFunc(handler); - - this._indexHandler = handler; - }, - - // - // see nsIHttpServer.registerContentType - // - registerContentType: function(ext, type) - { - if (!type) - delete this._mimeMappings[ext]; - else - this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type); - }, - - // PRIVATE API - - /** -* Sets or remove (if handler is null) a handler in an object with a key. -* -* @param handler -* a handler, either function or an nsIHttpRequestHandler -* @param dict -* The object to attach the handler to. -* @param key -* The field name of the handler. -*/ - _handlerToField: function(handler, dict, key) - { - // for convenience, handler can be a function if this is run from xpcshell - if (typeof(handler) == "function") - dict[key] = handler; - else if (handler) - dict[key] = createHandlerFunc(handler); - else - delete dict[key]; - }, - - /** -* Handles a request which maps to a file in the local filesystem (if a base -* path has already been set; otherwise the 404 error is thrown). -* -* @param metadata : Request -* metadata for the incoming request -* @param response : Response -* an uninitialized Response to the given request, to be initialized by a -* request handler -* @throws HTTP_### -* if an HTTP error occurred (usually HTTP_404); note that in this case the -* calling code must handle post-processing of the response -*/ - _handleDefault: function(metadata, response) - { - dumpn("*** _handleDefault()"); - - response.setStatusLine(metadata.httpVersion, 200, "OK"); - - var path = metadata.path; - NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">"); - - // determine the actual on-disk file; this requires finding the deepest - // path-to-directory mapping in the requested URL - var file = this._getFileForPath(path); - - // the "file" might be a directory, in which case we either serve the - // contained index.html or make the index handler write the response - if (file.exists() && file.isDirectory()) - { - file.append("index.html"); // make configurable? - if (!file.exists() || file.isDirectory()) - { - metadata._ensurePropertyBag(); - metadata._bag.setPropertyAsInterface("directory", file.parent); - this._indexHandler(metadata, response); - return; - } - } - - // alternately, the file might not exist - if (!file.exists()) - throw HTTP_404; - - var start, end; - if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) && - metadata.hasHeader("Range") && - this._getTypeFromFile(file) !== SJS_TYPE) - { - var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/); - if (!rangeMatch) - throw HTTP_400; - - if (rangeMatch[1] !== undefined) - start = parseInt(rangeMatch[1], 10); - - if (rangeMatch[2] !== undefined) - end = parseInt(rangeMatch[2], 10); - - if (start === undefined && end === undefined) - throw HTTP_400; - - // No start given, so the end is really the count of bytes from the - // end of the file. - if (start === undefined) - { - start = Math.max(0, file.fileSize - end); - end = file.fileSize - 1; - } - - // start and end are inclusive - if (end === undefined || end >= file.fileSize) - end = file.fileSize - 1; - - if (start !== undefined && start >= file.fileSize) { - var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable"); - HTTP_416.customErrorHandling = function(errorResponse) - { - maybeAddHeaders(file, metadata, errorResponse); - }; - throw HTTP_416; - } - - if (end < start) - { - response.setStatusLine(metadata.httpVersion, 200, "OK"); - start = 0; - end = file.fileSize - 1; - } - else - { - response.setStatusLine(metadata.httpVersion, 206, "Partial Content"); - var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize; - response.setHeader("Content-Range", contentRange); - } - } - else - { - start = 0; - end = file.fileSize - 1; - } - - // finally... - dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " + - start + " to " + end + " inclusive"); - this._writeFileResponse(metadata, file, response, start, end - start + 1); - }, - - /** -* Writes an HTTP response for the given file, including setting headers for -* file metadata. -* -* @param metadata : Request -* the Request for which a response is being generated -* @param file : nsILocalFile -* the file which is to be sent in the response -* @param response : Response -* the response to which the file should be written -* @param offset: uint -* the byte offset to skip to when writing -* @param count: uint -* the number of bytes to write -*/ - _writeFileResponse: function(metadata, file, response, offset, count) - { - const PR_RDONLY = 0x01; - - var type = this._getTypeFromFile(file); - if (type === SJS_TYPE) - { - var fis = new FileInputStream(file, PR_RDONLY, parseInt("444", 8), - Ci.nsIFileInputStream.CLOSE_ON_EOF); - - try - { - var sis = new ScriptableInputStream(fis); - var s = Cu.Sandbox(gGlobalObject); - s.importFunction(dump, "dump"); - - // Define a basic key-value state-preservation API across requests, with - // keys initially corresponding to the empty string. - var self = this; - var path = metadata.path; - s.importFunction(function getState(k) - { - return self._getState(path, k); - }); - s.importFunction(function setState(k, v) - { - self._setState(path, k, v); - }); - s.importFunction(function getSharedState(k) - { - return self._getSharedState(k); - }); - s.importFunction(function setSharedState(k, v) - { - self._setSharedState(k, v); - }); - s.importFunction(function getObjectState(k, callback) - { - callback(self._getObjectState(k)); - }); - s.importFunction(function setObjectState(k, v) - { - self._setObjectState(k, v); - }); - s.importFunction(function registerPathHandler(p, h) - { - self.registerPathHandler(p, h); - }); - - // Make it possible for sjs files to access their location - this._setState(path, "__LOCATION__", file.path); - - try - { - // Alas, the line number in errors dumped to console when calling the - // request handler is simply an offset from where we load the SJS file. - // Work around this in a reasonably non-fragile way by dynamically - // getting the line number where we evaluate the SJS file. Don't - // separate these two lines! - var line = new Error().lineNumber; - Cu.evalInSandbox(sis.read(file.fileSize), s); - } - catch (e) - { - dumpn("*** syntax error in SJS at " + file.path + ": " + e); - throw HTTP_500; - } - - try - { - s.handleRequest(metadata, response); - } - catch (e) - { - dump("*** error running SJS at " + file.path + ": " + - e + " on line " + - (e instanceof Error - ? e.lineNumber + " in httpd.js" - : (e.lineNumber - line)) + "\n"); - throw HTTP_500; - } - } - finally - { - fis.close(); - } - } - else - { - try - { - response.setHeader("Last-Modified", - toDateString(file.lastModifiedTime), - false); - } - catch (e) { /* lastModifiedTime threw, ignore */ } - - response.setHeader("Content-Type", type, false); - maybeAddHeaders(file, metadata, response); - response.setHeader("Content-Length", "" + count, false); - - var fis = new FileInputStream(file, PR_RDONLY, parseInt("444", 8), - Ci.nsIFileInputStream.CLOSE_ON_EOF); - - offset = offset || 0; - count = count || file.fileSize; - NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset"); - NS_ASSERT(count >= 0, "bad count"); - NS_ASSERT(offset + count <= file.fileSize, "bad total data size"); - - try - { - if (offset !== 0) - { - // Seek (or read, if seeking isn't supported) to the correct offset so - // the data sent to the client matches the requested range. - if (fis instanceof Ci.nsISeekableStream) - fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset); - else - new ScriptableInputStream(fis).read(offset); - } - } - catch (e) - { - fis.close(); - throw e; - } - - function writeMore() - { - gThreadManager.currentThread - .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL); - } - - var input = new BinaryInputStream(fis); - var output = new BinaryOutputStream(response.bodyOutputStream); - var writeData = - { - run: function() - { - var chunkSize = Math.min(65536, count); - count -= chunkSize; - NS_ASSERT(count >= 0, "underflow"); - - try - { - var data = input.readByteArray(chunkSize); - NS_ASSERT(data.length === chunkSize, - "incorrect data returned? got " + data.length + - ", expected " + chunkSize); - output.writeByteArray(data, data.length); - if (count === 0) - { - fis.close(); - response.finish(); - } - else - { - writeMore(); - } - } - catch (e) - { - try - { - fis.close(); - } - finally - { - response.finish(); - } - throw e; - } - } - }; - - writeMore(); - - // Now that we know copying will start, flag the response as async. - response.processAsync(); - } - }, - - /** -* Get the value corresponding to a given key for the given path for SJS state -* preservation across requests. -* -* @param path : string -* the path from which the given state is to be retrieved -* @param k : string -* the key whose corresponding value is to be returned -* @returns string -* the corresponding value, which is initially the empty string -*/ - _getState: function(path, k) - { - var state = this._state; - if (path in state && k in state[path]) - return state[path][k]; - return ""; - }, - - /** -* Set the value corresponding to a given key for the given path for SJS state -* preservation across requests. -* -* @param path : string -* the path from which the given state is to be retrieved -* @param k : string -* the key whose corresponding value is to be set -* @param v : string -* the value to be set -*/ - _setState: function(path, k, v) - { - if (typeof v !== "string") - throw new Error("non-string value passed"); - var state = this._state; - if (!(path in state)) - state[path] = {}; - state[path][k] = v; - }, - - /** -* Get the value corresponding to a given key for SJS state preservation -* across requests. -* -* @param k : string -* the key whose corresponding value is to be returned -* @returns string -* the corresponding value, which is initially the empty string -*/ - _getSharedState: function(k) - { - var state = this._sharedState; - if (k in state) - return state[k]; - return ""; - }, - - /** -* Set the value corresponding to a given key for SJS state preservation -* across requests. -* -* @param k : string -* the key whose corresponding value is to be set -* @param v : string -* the value to be set -*/ - _setSharedState: function(k, v) - { - if (typeof v !== "string") - throw new Error("non-string value passed"); - this._sharedState[k] = v; - }, - - /** -* Returns the object associated with the given key in the server for SJS -* state preservation across requests. -* -* @param k : string -* the key whose corresponding object is to be returned -* @returns nsISupports -* the corresponding object, or null if none was present -*/ - _getObjectState: function(k) - { - if (typeof k !== "string") - throw new Error("non-string key passed"); - return this._objectState[k] || null; - }, - - /** -* Sets the object associated with the given key in the server for SJS -* state preservation across requests. -* -* @param k : string -* the key whose corresponding object is to be set -* @param v : nsISupports -* the object to be associated with the given key; may be null -*/ - _setObjectState: function(k, v) - { - if (typeof k !== "string") - throw new Error("non-string key passed"); - if (typeof v !== "object") - throw new Error("non-object value passed"); - if (v && !("QueryInterface" in v)) - { - throw new Error("must pass an nsISupports; use wrappedJSObject to ease " + - "pain when using the server from JS"); - } - - this._objectState[k] = v; - }, - - /** -* Gets a content-type for the given file, first by checking for any custom -* MIME-types registered with this handler for the file's extension, second by -* asking the global MIME service for a content-type, and finally by failing -* over to application/octet-stream. -* -* @param file : nsIFile -* the nsIFile for which to get a file type -* @returns string -* the best content-type which can be determined for the file -*/ - _getTypeFromFile: function(file) - { - try - { - var name = file.leafName; - var dot = name.lastIndexOf("."); - if (dot > 0) - { - var ext = name.slice(dot + 1); - if (ext in this._mimeMappings) - return this._mimeMappings[ext]; - } - return Cc["@mozilla.org/uriloader/external-helper-app-service;1"] - .getService(Ci.nsIMIMEService) - .getTypeFromFile(file); - } - catch (e) - { - return "application/octet-stream"; - } - }, - - /** -* Returns the nsILocalFile which corresponds to the path, as determined using -* all registered path->directory mappings and any paths which are explicitly -* overridden. -* -* @param path : string -* the server path for which a file should be retrieved, e.g. "/foo/bar" -* @throws HttpError -* when the correct action is the corresponding HTTP error (i.e., because no -* mapping was found for a directory in path, the referenced file doesn't -* exist, etc.) -* @returns nsILocalFile -* the file to be sent as the response to a request for the path -*/ - _getFileForPath: function(path) - { - // decode and add underscores as necessary - try - { - path = toInternalPath(path, true); - } - catch (e) - { - throw HTTP_400; // malformed path - } - - // next, get the directory which contains this path - var pathMap = this._pathDirectoryMap; - - // An example progression of tmp for a path "/foo/bar/baz/" might be: - // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", "" - var tmp = path.substring(1); - while (true) - { - // do we have a match for current head of the path? - var file = pathMap.get(tmp); - if (file) - { - // XXX hack; basically disable showing mapping for /foo/bar/ when the - // requested path was /foo/bar, because relative links on the page - // will all be incorrect -- we really need the ability to easily - // redirect here instead - if (tmp == path.substring(1) && - tmp.length != 0 && - tmp.charAt(tmp.length - 1) != "/") - file = null; - else - break; - } - - // if we've finished trying all prefixes, exit - if (tmp == "") - break; - - tmp = tmp.substring(0, tmp.lastIndexOf("/")); - } - - // no mapping applies, so 404 - if (!file) - throw HTTP_404; - - - // last, get the file for the path within the determined directory - var parentFolder = file.parent; - var dirIsRoot = (parentFolder == null); - - // Strategy here is to append components individually, making sure we - // never move above the given directory; this allows paths such as - // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling"; - // this component-wise approach also means the code works even on platforms - // which don't use "/" as the directory separator, such as Windows - var leafPath = path.substring(tmp.length + 1); - var comps = leafPath.split("/"); - for (var i = 0, sz = comps.length; i < sz; i++) - { - var comp = comps[i]; - - if (comp == "..") - file = file.parent; - else if (comp == "." || comp == "") - continue; - else - file.append(comp); - - if (!dirIsRoot && file.equals(parentFolder)) - throw HTTP_403; - } - - return file; - }, - - /** -* Writes the error page for the given HTTP error code over the given -* connection. -* -* @param errorCode : uint -* the HTTP error code to be used -* @param connection : Connection -* the connection on which the error occurred -*/ - handleError: function(errorCode, connection) - { - var response = new Response(connection); - - dumpn("*** error in request: " + errorCode); - - this._handleError(errorCode, new Request(connection.port), response); - }, - - /** -* Handles a request which generates the given error code, using the -* user-defined error handler if one has been set, gracefully falling back to -* the x00 status code if the code has no handler, and failing to status code -* 500 if all else fails. -* -* @param errorCode : uint -* the HTTP error which is to be returned -* @param metadata : Request -* metadata for the request, which will often be incomplete since this is an -* error -* @param response : Response -* an uninitialized Response should be initialized when this method -* completes with information which represents the desired error code in the -* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a -* fallback for 505, per HTTP specs) -*/ - _handleError: function(errorCode, metadata, response) - { - if (!metadata) - throw Cr.NS_ERROR_NULL_POINTER; - - var errorX00 = errorCode - (errorCode % 100); - - try - { - if (!(errorCode in HTTP_ERROR_CODES)) - dumpn("*** WARNING: requested invalid error: " + errorCode); - - // RFC 2616 says that we should try to handle an error by its class if we - // can't otherwise handle it -- if that fails, we revert to handling it as - // a 500 internal server error, and if that fails we throw and shut down - // the server - - // actually handle the error - try - { - if (errorCode in this._overrideErrors) - this._overrideErrors[errorCode](metadata, response); - else - this._defaultErrors[errorCode](metadata, response); - } - catch (e) - { - if (response.partiallySent()) - { - response.abort(e); - return; - } - - // don't retry the handler that threw - if (errorX00 == errorCode) - throw HTTP_500; - - dumpn("*** error in handling for error code " + errorCode + ", " + - "falling back to " + errorX00 + "..."); - response = new Response(response._connection); - if (errorX00 in this._overrideErrors) - this._overrideErrors[errorX00](metadata, response); - else if (errorX00 in this._defaultErrors) - this._defaultErrors[errorX00](metadata, response); - else - throw HTTP_500; - } - } - catch (e) - { - if (response.partiallySent()) - { - response.abort(); - return; - } - - // we've tried everything possible for a meaningful error -- now try 500 - dumpn("*** error in handling for error code " + errorX00 + ", falling " + - "back to 500..."); - - try - { - response = new Response(response._connection); - if (500 in this._overrideErrors) - this._overrideErrors[500](metadata, response); - else - this._defaultErrors[500](metadata, response); - } - catch (e2) - { - dumpn("*** multiple errors in default error handlers!"); - dumpn("*** e == " + e + ", e2 == " + e2); - response.abort(e2); - return; - } - } - - response.complete(); - }, - - // FIELDS - - /** -* This object contains the default handlers for the various HTTP error codes. -*/ - _defaultErrors: - { - 400: function(metadata, response) - { - // none of the data in metadata is reliable, so hard-code everything here - response.setStatusLine("1.1", 400, "Bad Request"); - response.setHeader("Content-Type", "text/plain", false); - - var body = "Bad request\n"; - response.bodyOutputStream.write(body, body.length); - }, - 403: function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, 403, "Forbidden"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>403 Forbidden</title></head>\ -<body>\ -<h1>403 Forbidden</h1>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - }, - 404: function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, 404, "Not Found"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>404 Not Found</title></head>\ -<body>\ -<h1>404 Not Found</h1>\ -<p>\ -<span style='font-family: monospace;'>" + - htmlEscape(metadata.path) + - "</span> was not found.\ -</p>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - }, - 416: function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, - 416, - "Requested Range Not Satisfiable"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head>\ -<title>416 Requested Range Not Satisfiable</title></head>\ -<body>\ -<h1>416 Requested Range Not Satisfiable</h1>\ -<p>The byte range was not valid for the\ -requested resource.\ -</p>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - }, - 500: function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, - 500, - "Internal Server Error"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>500 Internal Server Error</title></head>\ -<body>\ -<h1>500 Internal Server Error</h1>\ -<p>Something's broken in this server and\ -needs to be fixed.</p>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - }, - 501: function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, 501, "Not Implemented"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>501 Not Implemented</title></head>\ -<body>\ -<h1>501 Not Implemented</h1>\ -<p>This server is not (yet) Apache.</p>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - }, - 505: function(metadata, response) - { - response.setStatusLine("1.1", 505, "HTTP Version Not Supported"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>505 HTTP Version Not Supported</title></head>\ -<body>\ -<h1>505 HTTP Version Not Supported</h1>\ -<p>This server only supports HTTP/1.0 and HTTP/1.1\ -connections.</p>\ -</body>\ -</html>"; - response.bodyOutputStream.write(body, body.length); - } - }, - - /** -* Contains handlers for the default set of URIs contained in this server. -*/ - _defaultPaths: - { - "/": function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "text/html", false); - - var body = "<html>\ -<head><title>httpd.js</title></head>\ -<body>\ -<h1>httpd.js</h1>\ -<p>If you're seeing this page, httpd.js is up and\ -serving requests! Now set a base path and serve some\ -files!</p>\ -</body>\ -</html>"; - - response.bodyOutputStream.write(body, body.length); - }, - - "/trace": function(metadata, response) - { - response.setStatusLine(metadata.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "text/plain", false); - - var body = "Request-URI: " + - metadata.scheme + "://" + metadata.host + ":" + metadata.port + - metadata.path + "\n\n"; - body += "Request (semantically equivalent, slightly reformatted):\n\n"; - body += metadata.method + " " + metadata.path; - - if (metadata.queryString) - body += "?" + metadata.queryString; - - body += " HTTP/" + metadata.httpVersion + "\r\n"; - - var headEnum = metadata.headers; - while (headEnum.hasMoreElements()) - { - var fieldName = headEnum.getNext() - .QueryInterface(Ci.nsISupportsString) - .data; - body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n"; - } - - response.bodyOutputStream.write(body, body.length); - } - } -}; - - -/** -* Maps absolute paths to files on the local file system (as nsILocalFiles). -*/ -function FileMap() -{ - /** Hash which will map paths to nsILocalFiles. */ - this._map = {}; -} -FileMap.prototype = -{ - // PUBLIC API - - /** -* Maps key to a clone of the nsILocalFile value if value is non-null; -* otherwise, removes any extant mapping for key. -* -* @param key : string -* string to which a clone of value is mapped -* @param value : nsILocalFile -* the file to map to key, or null to remove a mapping -*/ - put: function(key, value) - { - if (value) - this._map[key] = value.clone(); - else - delete this._map[key]; - }, - - /** -* Returns a clone of the nsILocalFile mapped to key, or null if no such -* mapping exists. -* -* @param key : string -* key to which the returned file maps -* @returns nsILocalFile -* a clone of the mapped file, or null if no mapping exists -*/ - get: function(key) - { - var val = this._map[key]; - return val ? val.clone() : null; - } -}; - - -// Response CONSTANTS - -// token = *<any CHAR except CTLs or separators> -// CHAR = <any US-ASCII character (0-127)> -// CTL = <any US-ASCII control character (0-31) and DEL (127)> -// separators = "(" | ")" | "<" | ">" | "@" -// | "," | ";" | ":" | "\" | <"> -// | "/" | "[" | "]" | "?" | "=" -// | "{" | "}" | SP | HT -const IS_TOKEN_ARRAY = - [0, 0, 0, 0, 0, 0, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 0, 0, 0, 0, 0, 0, 0, 0, // 24 - - 0, 1, 0, 1, 1, 1, 1, 1, // 32 - 0, 0, 1, 1, 0, 1, 1, 0, // 40 - 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 1, 1, 0, 0, 0, 0, 0, 0, // 56 - - 0, 1, 1, 1, 1, 1, 1, 1, // 64 - 1, 1, 1, 1, 1, 1, 1, 1, // 72 - 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 1, 1, 1, 0, 0, 0, 1, 1, // 88 - - 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 1, 1, 1, 1, 1, 1, 1, 1, // 104 - 1, 1, 1, 1, 1, 1, 1, 1, // 112 - 1, 1, 1, 0, 1, 0, 1]; // 120 - - -/** -* Determines whether the given character code is a CTL. -* -* @param code : uint -* the character code -* @returns boolean -* true if code is a CTL, false otherwise -*/ -function isCTL(code) -{ - return (code >= 0 && code <= 31) || (code == 127); -} - -/** -* Represents a response to an HTTP request, encapsulating all details of that -* response. This includes all headers, the HTTP version, status code and -* explanation, and the entity itself. -* -* @param connection : Connection -* the connection over which this response is to be written -*/ -function Response(connection) -{ - /** The connection over which this response will be written. */ - this._connection = connection; - - /** -* The HTTP version of this response; defaults to 1.1 if not set by the -* handler. -*/ - this._httpVersion = nsHttpVersion.HTTP_1_1; - - /** -* The HTTP code of this response; defaults to 200. -*/ - this._httpCode = 200; - - /** -* The description of the HTTP code in this response; defaults to "OK". -*/ - this._httpDescription = "OK"; - - /** -* An nsIHttpHeaders object in which the headers in this response should be -* stored. This property is null after the status line and headers have been -* written to the network, and it may be modified up until it is cleared, -* except if this._finished is set first (in which case headers are written -* asynchronously in response to a finish() call not preceded by -* flushHeaders()). -*/ - this._headers = new nsHttpHeaders(); - - /** -* Set to true when this response is ended (completely constructed if possible -* and the connection closed); further actions on this will then fail. -*/ - this._ended = false; - - /** -* A stream used to hold data written to the body of this response. -*/ - this._bodyOutputStream = null; - - /** -* A stream containing all data that has been written to the body of this -* response so far. (Async handlers make the data contained in this -* unreliable as a way of determining content length in general, but auxiliary -* saved information can sometimes be used to guarantee reliability.) -*/ - this._bodyInputStream = null; - - /** -* A stream copier which copies data to the network. It is initially null -* until replaced with a copier for response headers; when headers have been -* fully sent it is replaced with a copier for the response body, remaining -* so for the duration of response processing. -*/ - this._asyncCopier = null; - - /** -* True if this response has been designated as being processed -* asynchronously rather than for the duration of a single call to -* nsIHttpRequestHandler.handle. -*/ - this._processAsync = false; - - /** -* True iff finish() has been called on this, signaling that no more changes -* to this may be made. -*/ - this._finished = false; - - /** -* True iff powerSeized() has been called on this, signaling that this -* response is to be handled manually by the response handler (which may then -* send arbitrary data in response, even non-HTTP responses). -*/ - this._powerSeized = false; -} -Response.prototype = -{ - // PUBLIC CONSTRUCTION API - - // - // see nsIHttpResponse.bodyOutputStream - // - get bodyOutputStream() - { - if (this._finished) - throw Cr.NS_ERROR_NOT_AVAILABLE; - - if (!this._bodyOutputStream) - { - var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX, - null); - this._bodyOutputStream = pipe.outputStream; - this._bodyInputStream = pipe.inputStream; - if (this._processAsync || this._powerSeized) - this._startAsyncProcessor(); - } - - return this._bodyOutputStream; - }, - - // - // see nsIHttpResponse.write - // - write: function(data) - { - if (this._finished) - throw Cr.NS_ERROR_NOT_AVAILABLE; - - var dataAsString = String(data); - this.bodyOutputStream.write(dataAsString, dataAsString.length); - }, - - // - // see nsIHttpResponse.setStatusLine - // - setStatusLine: function(httpVersion, code, description) - { - if (!this._headers || this._finished || this._powerSeized) - throw Cr.NS_ERROR_NOT_AVAILABLE; - this._ensureAlive(); - - if (!(code >= 0 && code < 1000)) - throw Cr.NS_ERROR_INVALID_ARG; - - try - { - var httpVer; - // avoid version construction for the most common cases - if (!httpVersion || httpVersion == "1.1") - httpVer = nsHttpVersion.HTTP_1_1; - else if (httpVersion == "1.0") - httpVer = nsHttpVersion.HTTP_1_0; - else - httpVer = new nsHttpVersion(httpVersion); - } - catch (e) - { - throw Cr.NS_ERROR_INVALID_ARG; - } - - // Reason-Phrase = *<TEXT, excluding CR, LF> - // TEXT = <any OCTET except CTLs, but including LWS> - // - // XXX this ends up disallowing octets which aren't Unicode, I think -- not - // much to do if description is IDL'd as string - if (!description) - description = ""; - for (var i = 0; i < description.length; i++) - if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t") - throw Cr.NS_ERROR_INVALID_ARG; - - // set the values only after validation to preserve atomicity - this._httpDescription = description; - this._httpCode = code; - this._httpVersion = httpVer; - }, - - // - // see nsIHttpResponse.setHeader - // - setHeader: function(name, value, merge) - { - if (!this._headers || this._finished || this._powerSeized) - throw Cr.NS_ERROR_NOT_AVAILABLE; - this._ensureAlive(); - - this._headers.setHeader(name, value, merge); - }, - - // - // see nsIHttpResponse.processAsync - // - processAsync: function() - { - if (this._finished) - throw Cr.NS_ERROR_UNEXPECTED; - if (this._powerSeized) - throw Cr.NS_ERROR_NOT_AVAILABLE; - if (this._processAsync) - return; - this._ensureAlive(); - - dumpn("*** processing connection " + this._connection.number + " async"); - this._processAsync = true; - - /* -* Either the bodyOutputStream getter or this method is responsible for -* starting the asynchronous processor and catching writes of data to the -* response body of async responses as they happen, for the purpose of -* forwarding those writes to the actual connection's output stream. -* If bodyOutputStream is accessed first, calling this method will create -* the processor (when it first is clear that body data is to be written -* immediately, not buffered). If this method is called first, accessing -* bodyOutputStream will create the processor. If only this method is -* called, we'll write nothing, neither headers nor the nonexistent body, -* until finish() is called. Since that delay is easily avoided by simply -* getting bodyOutputStream or calling write(""), we don't worry about it. -*/ - if (this._bodyOutputStream && !this._asyncCopier) - this._startAsyncProcessor(); - }, - - // - // see nsIHttpResponse.seizePower - // - seizePower: function() - { - if (this._processAsync) - throw Cr.NS_ERROR_NOT_AVAILABLE; - if (this._finished) - throw Cr.NS_ERROR_UNEXPECTED; - if (this._powerSeized) - return; - this._ensureAlive(); - - dumpn("*** forcefully seizing power over connection " + - this._connection.number + "..."); - - // Purge any already-written data without sending it. We could as easily - // swap out the streams entirely, but that makes it possible to acquire and - // unknowingly use a stale reference, so we require there only be one of - // each stream ever for any response to avoid this complication. - if (this._asyncCopier) - this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED); - this._asyncCopier = null; - if (this._bodyOutputStream) - { - var input = new BinaryInputStream(this._bodyInputStream); - var avail; - while ((avail = input.available()) > 0) - input.readByteArray(avail); - } - - this._powerSeized = true; - if (this._bodyOutputStream) - this._startAsyncProcessor(); - }, - - // - // see nsIHttpResponse.finish - // - finish: function() - { - if (!this._processAsync && !this._powerSeized) - throw Cr.NS_ERROR_UNEXPECTED; - if (this._finished) - return; - - dumpn("*** finishing connection " + this._connection.number); - this._startAsyncProcessor(); // in case bodyOutputStream was never accessed - if (this._bodyOutputStream) - this._bodyOutputStream.close(); - this._finished = true; - }, - - - // NSISUPPORTS - - // - // see nsISupports.QueryInterface - // - QueryInterface: function(iid) - { - if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // POST-CONSTRUCTION API (not exposed externally) - - /** -* The HTTP version number of this, as a string (e.g. "1.1"). -*/ - get httpVersion() - { - this._ensureAlive(); - return this._httpVersion.toString(); - }, - - /** -* The HTTP status code of this response, as a string of three characters per -* RFC 2616. -*/ - get httpCode() - { - this._ensureAlive(); - - var codeString = (this._httpCode < 10 ? "0" : "") + - (this._httpCode < 100 ? "0" : "") + - this._httpCode; - return codeString; - }, - - /** -* The description of the HTTP status code of this response, or "" if none is -* set. -*/ - get httpDescription() - { - this._ensureAlive(); - - return this._httpDescription; - }, - - /** -* The headers in this response, as an nsHttpHeaders object. -*/ - get headers() - { - this._ensureAlive(); - - return this._headers; - }, - - // - // see nsHttpHeaders.getHeader - // - getHeader: function(name) - { - this._ensureAlive(); - - return this._headers.getHeader(name); - }, - - /** -* Determines whether this response may be abandoned in favor of a newly -* constructed response. A response may be abandoned only if it is not being -* sent asynchronously and if raw control over it has not been taken from the -* server. -* -* @returns boolean -* true iff no data has been written to the network -*/ - partiallySent: function() - { - dumpn("*** partiallySent()"); - return this._processAsync || this._powerSeized; - }, - - /** -* If necessary, kicks off the remaining request processing needed to be done -* after a request handler performs its initial work upon this response. -*/ - complete: function() - { - dumpn("*** complete()"); - if (this._processAsync || this._powerSeized) - { - NS_ASSERT(this._processAsync ^ this._powerSeized, - "can't both send async and relinquish power"); - return; - } - - NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?"); - - this._startAsyncProcessor(); - - // Now make sure we finish processing this request! - if (this._bodyOutputStream) - this._bodyOutputStream.close(); - }, - - /** -* Abruptly ends processing of this response, usually due to an error in an -* incoming request but potentially due to a bad error handler. Since we -* cannot handle the error in the usual way (giving an HTTP error page in -* response) because data may already have been sent (or because the response -* might be expected to have been generated asynchronously or completely from -* scratch by the handler), we stop processing this response and abruptly -* close the connection. -* -* @param e : Error -* the exception which precipitated this abort, or null if no such exception -* was generated -*/ - abort: function(e) - { - dumpn("*** abort(<" + e + ">)"); - - // This response will be ended by the processor if one was created. - var copier = this._asyncCopier; - if (copier) - { - // We dispatch asynchronously here so that any pending writes of data to - // the connection will be deterministically written. This makes it easier - // to specify exact behavior, and it makes observable behavior more - // predictable for clients. Note that the correctness of this depends on - // callbacks in response to _waitToReadData in WriteThroughCopier - // happening asynchronously with respect to the actual writing of data to - // bodyOutputStream, as they currently do; if they happened synchronously, - // an event which ran before this one could write more data to the - // response body before we get around to canceling the copier. We have - // tests for this in test_seizepower.js, however, and I can't think of a - // way to handle both cases without removing bodyOutputStream access and - // moving its effective write(data, length) method onto Response, which - // would be slower and require more code than this anyway. - gThreadManager.currentThread.dispatch({ - run: function() - { - dumpn("*** canceling copy asynchronously..."); - copier.cancel(Cr.NS_ERROR_UNEXPECTED); - } - }, Ci.nsIThread.DISPATCH_NORMAL); - } - else - { - this.end(); - } - }, - - /** -* Closes this response's network connection, marks the response as finished, -* and notifies the server handler that the request is done being processed. -*/ - end: function() - { - NS_ASSERT(!this._ended, "ending this response twice?!?!"); - - this._connection.close(); - if (this._bodyOutputStream) - this._bodyOutputStream.close(); - - this._finished = true; - this._ended = true; - }, - - // PRIVATE IMPLEMENTATION - - /** -* Sends the status line and headers of this response if they haven't been -* sent and initiates the process of copying data written to this response's -* body to the network. -*/ - _startAsyncProcessor: function() - { - dumpn("*** _startAsyncProcessor()"); - - // Handle cases where we're being called a second time. The former case - // happens when this is triggered both by complete() and by processAsync(), - // while the latter happens when processAsync() in conjunction with sent - // data causes abort() to be called. - if (this._asyncCopier || this._ended) - { - dumpn("*** ignoring second call to _startAsyncProcessor"); - return; - } - - // Send headers if they haven't been sent already and should be sent, then - // asynchronously continue to send the body. - if (this._headers && !this._powerSeized) - { - this._sendHeaders(); - return; - } - - this._headers = null; - this._sendBody(); - }, - - /** -* Signals that all modifications to the response status line and headers are -* complete and then sends that data over the network to the client. Once -* this method completes, a different response to the request that resulted -* in this response cannot be sent -- the only possible action in case of -* error is to abort the response and close the connection. -*/ - _sendHeaders: function() - { - dumpn("*** _sendHeaders()"); - - NS_ASSERT(this._headers); - NS_ASSERT(!this._powerSeized); - - // request-line - var statusLine = "HTTP/" + this.httpVersion + " " + - this.httpCode + " " + - this.httpDescription + "\r\n"; - - // header post-processing - - var headers = this._headers; - headers.setHeader("Connection", "close", false); - headers.setHeader("Server", "httpd.js", false); - if (!headers.hasHeader("Date")) - headers.setHeader("Date", toDateString(Date.now()), false); - - // Any response not being processed asynchronously must have an associated - // Content-Length header for reasons of backwards compatibility with the - // initial server, which fully buffered every response before sending it. - // Beyond that, however, it's good to do this anyway because otherwise it's - // impossible to test behaviors that depend on the presence or absence of a - // Content-Length header. - if (!this._processAsync) - { - dumpn("*** non-async response, set Content-Length"); - - var bodyStream = this._bodyInputStream; - var avail = bodyStream ? bodyStream.available() : 0; - - // XXX assumes stream will always report the full amount of data available - headers.setHeader("Content-Length", "" + avail, false); - } - - - // construct and send response - dumpn("*** header post-processing completed, sending response head..."); - - // request-line - var preambleData = [statusLine]; - - // headers - var headEnum = headers.enumerator; - while (headEnum.hasMoreElements()) - { - var fieldName = headEnum.getNext() - .QueryInterface(Ci.nsISupportsString) - .data; - var values = headers.getHeaderValues(fieldName); - for (var i = 0, sz = values.length; i < sz; i++) - preambleData.push(fieldName + ": " + values[i] + "\r\n"); - } - - // end request-line/headers - preambleData.push("\r\n"); - - var preamble = preambleData.join(""); - - var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null); - responseHeadPipe.outputStream.write(preamble, preamble.length); - - var response = this; - var copyObserver = - { - onStartRequest: function(request, cx) - { - dumpn("*** preamble copying started"); - }, - - onStopRequest: function(request, cx, statusCode) - { - dumpn("*** preamble copying complete " + - "[status=0x" + statusCode.toString(16) + "]"); - - if (!components.isSuccessCode(statusCode)) - { - dumpn("!!! header copying problems: non-success statusCode, " + - "ending response"); - - response.end(); - } - else - { - response._sendBody(); - } - }, - - QueryInterface: function(aIID) - { - if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - - var headerCopier = this._asyncCopier = - new WriteThroughCopier(responseHeadPipe.inputStream, - this._connection.output, - copyObserver, null); - - responseHeadPipe.outputStream.close(); - - // Forbid setting any more headers or modifying the request line. - this._headers = null; - }, - - /** -* Asynchronously writes the body of the response (or the entire response, if -* seizePower() has been called) to the network. -*/ - _sendBody: function() - { - dumpn("*** _sendBody"); - - NS_ASSERT(!this._headers, "still have headers around but sending body?"); - - // If no body data was written, we're done - if (!this._bodyInputStream) - { - dumpn("*** empty body, response finished"); - this.end(); - return; - } - - var response = this; - var copyObserver = - { - onStartRequest: function(request, context) - { - dumpn("*** onStartRequest"); - }, - - onStopRequest: function(request, cx, statusCode) - { - dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]"); - - if (statusCode === Cr.NS_BINDING_ABORTED) - { - dumpn("*** terminating copy observer without ending the response"); - } - else - { - if (!components.isSuccessCode(statusCode)) - dumpn("*** WARNING: non-success statusCode in onStopRequest"); - - response.end(); - } - }, - - QueryInterface: function(aIID) - { - if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - - dumpn("*** starting async copier of body data..."); - this._asyncCopier = - new WriteThroughCopier(this._bodyInputStream, this._connection.output, - copyObserver, null); - }, - - /** Ensures that this hasn't been ended. */ - _ensureAlive: function() - { - NS_ASSERT(!this._ended, "not handling response lifetime correctly"); - } -}; - -/** -* Size of the segments in the buffer used in storing response data and writing -* it to the socket. -*/ -Response.SEGMENT_SIZE = 8192; - -/** Serves double duty in WriteThroughCopier implementation. */ -function notImplemented() -{ - throw Cr.NS_ERROR_NOT_IMPLEMENTED; -} - -/** Returns true iff the given exception represents stream closure. */ -function streamClosed(e) -{ - return e === Cr.NS_BASE_STREAM_CLOSED || - (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED); -} - -/** Returns true iff the given exception represents a blocked stream. */ -function wouldBlock(e) -{ - return e === Cr.NS_BASE_STREAM_WOULD_BLOCK || - (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK); -} - -/** -* Copies data from source to sink as it becomes available, when that data can -* be written to sink without blocking. -* -* @param source : nsIAsyncInputStream -* the stream from which data is to be read -* @param sink : nsIAsyncOutputStream -* the stream to which data is to be copied -* @param observer : nsIRequestObserver -* an observer which will be notified when the copy starts and finishes -* @param context : nsISupports -* context passed to observer when notified of start/stop -* @throws NS_ERROR_NULL_POINTER -* if source, sink, or observer are null -*/ -function WriteThroughCopier(source, sink, observer, context) -{ - if (!source || !sink || !observer) - throw Cr.NS_ERROR_NULL_POINTER; - - /** Stream from which data is being read. */ - this._source = source; - - /** Stream to which data is being written. */ - this._sink = sink; - - /** Observer watching this copy. */ - this._observer = observer; - - /** Context for the observer watching this. */ - this._context = context; - - /** -* True iff this is currently being canceled (cancel has been called, the -* callback may not yet have been made). -*/ - this._canceled = false; - - /** -* False until all data has been read from input and written to output, at -* which point this copy is completed and cancel() is asynchronously called. -*/ - this._completed = false; - - /** Required by nsIRequest, meaningless. */ - this.loadFlags = 0; - /** Required by nsIRequest, meaningless. */ - this.loadGroup = null; - /** Required by nsIRequest, meaningless. */ - this.name = "response-body-copy"; - - /** Status of this request. */ - this.status = Cr.NS_OK; - - /** Arrays of byte strings waiting to be written to output. */ - this._pendingData = []; - - // start copying - try - { - observer.onStartRequest(this, context); - this._waitToReadData(); - this._waitForSinkClosure(); - } - catch (e) - { - dumpn("!!! error starting copy: " + e + - ("lineNumber" in e ? ", line " + e.lineNumber : "")); - dumpn(e.stack); - this.cancel(Cr.NS_ERROR_UNEXPECTED); - } -} -WriteThroughCopier.prototype = -{ - /* nsISupports implementation */ - - QueryInterface: function(iid) - { - if (iid.equals(Ci.nsIInputStreamCallback) || - iid.equals(Ci.nsIOutputStreamCallback) || - iid.equals(Ci.nsIRequest) || - iid.equals(Ci.nsISupports)) - { - return this; - } - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // NSIINPUTSTREAMCALLBACK - - /** -* Receives a more-data-in-input notification and writes the corresponding -* data to the output. -* -* @param input : nsIAsyncInputStream -* the input stream on whose data we have been waiting -*/ - onInputStreamReady: function(input) - { - if (this._source === null) - return; - - dumpn("*** onInputStreamReady"); - - // - // Ordinarily we'll read a non-zero amount of data from input, queue it up - // to be written and then wait for further callbacks. The complications in - // this method are the cases where we deviate from that behavior when errors - // occur or when copying is drawing to a finish. - // - // The edge cases when reading data are: - // - // Zero data is read - // If zero data was read, we're at the end of available data, so we can - // should stop reading and move on to writing out what we have (or, if - // we've already done that, onto notifying of completion). - // A stream-closed exception is thrown - // This is effectively a less kind version of zero data being read; the - // only difference is that we notify of completion with that result - // rather than with NS_OK. - // Some other exception is thrown - // This is the least kind result. We don't know what happened, so we - // act as though the stream closed except that we notify of completion - // with the result NS_ERROR_UNEXPECTED. - // - - var bytesWanted = 0, bytesConsumed = -1; - try - { - input = new BinaryInputStream(input); - - bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE); - dumpn("*** input wanted: " + bytesWanted); - - if (bytesWanted > 0) - { - var data = input.readByteArray(bytesWanted); - bytesConsumed = data.length; - this._pendingData.push(String.fromCharCode.apply(String, data)); - } - - dumpn("*** " + bytesConsumed + " bytes read"); - - // Handle the zero-data edge case in the same place as all other edge - // cases are handled. - if (bytesWanted === 0) - throw Cr.NS_BASE_STREAM_CLOSED; - } - catch (e) - { - if (streamClosed(e)) - { - dumpn("*** input stream closed"); - e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED; - } - else - { - dumpn("!!! unexpected error reading from input, canceling: " + e); - e = Cr.NS_ERROR_UNEXPECTED; - } - - this._doneReadingSource(e); - return; - } - - var pendingData = this._pendingData; - - NS_ASSERT(bytesConsumed > 0); - NS_ASSERT(pendingData.length > 0, "no pending data somehow?"); - NS_ASSERT(pendingData[pendingData.length - 1].length > 0, - "buffered zero bytes of data?"); - - NS_ASSERT(this._source !== null); - - // Reading has gone great, and we've gotten data to write now. What if we - // don't have a place to write that data, because output went away just - // before this read? Drop everything on the floor, including new data, and - // cancel at this point. - if (this._sink === null) - { - pendingData.length = 0; - this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED); - return; - } - - // Okay, we've read the data, and we know we have a place to write it. We - // need to queue up the data to be written, but *only* if none is queued - // already -- if data's already queued, the code that actually writes the - // data will make sure to wait on unconsumed pending data. - try - { - if (pendingData.length === 1) - this._waitToWriteData(); - } - catch (e) - { - dumpn("!!! error waiting to write data just read, swallowing and " + - "writing only what we already have: " + e); - this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED); - return; - } - - // Whee! We successfully read some data, and it's successfully queued up to - // be written. All that remains now is to wait for more data to read. - try - { - this._waitToReadData(); - } - catch (e) - { - dumpn("!!! error waiting to read more data: " + e); - this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED); - } - }, - - - // NSIOUTPUTSTREAMCALLBACK - - /** -* Callback when data may be written to the output stream without blocking, or -* when the output stream has been closed. -* -* @param output : nsIAsyncOutputStream -* the output stream on whose writability we've been waiting, also known as -* this._sink -*/ - onOutputStreamReady: function(output) - { - if (this._sink === null) - return; - - dumpn("*** onOutputStreamReady"); - - var pendingData = this._pendingData; - if (pendingData.length === 0) - { - // There's no pending data to write. The only way this can happen is if - // we're waiting on the output stream's closure, so we can respond to a - // copying failure as quickly as possible (rather than waiting for data to - // be available to read and then fail to be copied). Therefore, we must - // be done now -- don't bother to attempt to write anything and wrap - // things up. - dumpn("!!! output stream closed prematurely, ending copy"); - - this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED); - return; - } - - - NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?"); - - // - // Write out the first pending quantum of data. The possible errors here - // are: - // - // The write might fail because we can't write that much data - // Okay, we've written what we can now, so re-queue what's left and - // finish writing it out later. - // The write failed because the stream was closed - // Discard pending data that we can no longer write, stop reading, and - // signal that copying finished. - // Some other error occurred. - // Same as if the stream were closed, but notify with the status - // NS_ERROR_UNEXPECTED so the observer knows something was wonky. - // - - try - { - var quantum = pendingData[0]; - - // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on - // undefined behavior! We're only using this because writeByteArray - // is unusably broken for asynchronous output streams; see bug 532834 - // for details. - var bytesWritten = output.write(quantum, quantum.length); - if (bytesWritten === quantum.length) - pendingData.shift(); - else - pendingData[0] = quantum.substring(bytesWritten); - - dumpn("*** wrote " + bytesWritten + " bytes of data"); - } - catch (e) - { - if (wouldBlock(e)) - { - NS_ASSERT(pendingData.length > 0, - "stream-blocking exception with no data to write?"); - NS_ASSERT(pendingData[0].length > 0, - "stream-blocking exception with empty quantum?"); - this._waitToWriteData(); - return; - } - - if (streamClosed(e)) - dumpn("!!! output stream prematurely closed, signaling error..."); - else - dumpn("!!! unknown error: " + e + ", quantum=" + quantum); - - this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED); - return; - } - - // The day is ours! Quantum written, now let's see if we have more data - // still to write. - try - { - if (pendingData.length > 0) - { - this._waitToWriteData(); - return; - } - } - catch (e) - { - dumpn("!!! unexpected error waiting to write pending data: " + e); - this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED); - return; - } - - // Okay, we have no more pending data to write -- but might we get more in - // the future? - if (this._source !== null) - { - /* -* If we might, then wait for the output stream to be closed. (We wait -* only for closure because we have no data to write -- and if we waited -* for a specific amount of data, we would get repeatedly notified for no -* reason if over time the output stream permitted more and more data to -* be written to it without blocking.) -*/ - this._waitForSinkClosure(); - } - else - { - /* -* On the other hand, if we can't have more data because the input -* stream's gone away, then it's time to notify of copy completion. -* Victory! -*/ - this._sink = null; - this._cancelOrDispatchCancelCallback(Cr.NS_OK); - } - }, - - - // NSIREQUEST - - /** Returns true if the cancel observer hasn't been notified yet. */ - isPending: function() - { - return !this._completed; - }, - - /** Not implemented, don't use! */ - suspend: notImplemented, - /** Not implemented, don't use! */ - resume: notImplemented, - - /** -* Cancels data reading from input, asynchronously writes out any pending -* data, and causes the observer to be notified with the given error code when -* all writing has finished. -* -* @param status : nsresult -* the status to pass to the observer when data copying has been canceled -*/ - cancel: function(status) - { - dumpn("*** cancel(" + status.toString(16) + ")"); - - if (this._canceled) - { - dumpn("*** suppressing a late cancel"); - return; - } - - this._canceled = true; - this.status = status; - - // We could be in the middle of absolutely anything at this point. Both - // input and output might still be around, we might have pending data to - // write, and in general we know nothing about the state of the world. We - // therefore must assume everything's in progress and take everything to its - // final steady state (or so far as it can go before we need to finish - // writing out remaining data). - - this._doneReadingSource(status); - }, - - - // PRIVATE IMPLEMENTATION - - /** -* Stop reading input if we haven't already done so, passing e as the status -* when closing the stream, and kick off a copy-completion notice if no more -* data remains to be written. -* -* @param e : nsresult -* the status to be used when closing the input stream -*/ - _doneReadingSource: function(e) - { - dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")"); - - this._finishSource(e); - if (this._pendingData.length === 0) - this._sink = null; - else - NS_ASSERT(this._sink !== null, "null output?"); - - // If we've written out all data read up to this point, then it's time to - // signal completion. - if (this._sink === null) - { - NS_ASSERT(this._pendingData.length === 0, "pending data still?"); - this._cancelOrDispatchCancelCallback(e); - } - }, - - /** -* Stop writing output if we haven't already done so, discard any data that -* remained to be sent, close off input if it wasn't already closed, and kick -* off a copy-completion notice. -* -* @param e : nsresult -* the status to be used when closing input if it wasn't already closed -*/ - _doneWritingToSink: function(e) - { - dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")"); - - this._pendingData.length = 0; - this._sink = null; - this._doneReadingSource(e); - }, - - /** -* Completes processing of this copy: either by canceling the copy if it -* hasn't already been canceled using the provided status, or by dispatching -* the cancel callback event (with the originally provided status, of course) -* if it already has been canceled. -* -* @param status : nsresult -* the status code to use to cancel this, if this hasn't already been -* canceled -*/ - _cancelOrDispatchCancelCallback: function(status) - { - dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")"); - - NS_ASSERT(this._source === null, "should have finished input"); - NS_ASSERT(this._sink === null, "should have finished output"); - NS_ASSERT(this._pendingData.length === 0, "should have no pending data"); - - if (!this._canceled) - { - this.cancel(status); - return; - } - - var self = this; - var event = - { - run: function() - { - dumpn("*** onStopRequest async callback"); - - self._completed = true; - try - { - self._observer.onStopRequest(self, self._context, self.status); - } - catch (e) - { - NS_ASSERT(false, - "how are we throwing an exception here? we control " + - "all the callers! " + e); - } - } - }; - - gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL); - }, - - /** -* Kicks off another wait for more data to be available from the input stream. -*/ - _waitToReadData: function() - { - dumpn("*** _waitToReadData"); - this._source.asyncWait(this, 0, Response.SEGMENT_SIZE, - gThreadManager.mainThread); - }, - - /** -* Kicks off another wait until data can be written to the output stream. -*/ - _waitToWriteData: function() - { - dumpn("*** _waitToWriteData"); - - var pendingData = this._pendingData; - NS_ASSERT(pendingData.length > 0, "no pending data to write?"); - NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?"); - - this._sink.asyncWait(this, 0, pendingData[0].length, - gThreadManager.mainThread); - }, - - /** -* Kicks off a wait for the sink to which data is being copied to be closed. -* We wait for stream closure when we don't have any data to be copied, rather -* than waiting to write a specific amount of data. We can't wait to write -* data because the sink might be infinitely writable, and if no data appears -* in the source for a long time we might have to spin quite a bit waiting to -* write, waiting to write again, &c. Waiting on stream closure instead means -* we'll get just one notification if the sink dies. Note that when data -* starts arriving from the sink we'll resume waiting for data to be written, -* dropping this closure-only callback entirely. -*/ - _waitForSinkClosure: function() - { - dumpn("*** _waitForSinkClosure"); - - this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0, - gThreadManager.mainThread); - }, - - /** -* Closes input with the given status, if it hasn't already been closed; -* otherwise a no-op. -* -* @param status : nsresult -* status code use to close the source stream if necessary -*/ - _finishSource: function(status) - { - dumpn("*** _finishSource(" + status.toString(16) + ")"); - - if (this._source !== null) - { - this._source.closeWithStatus(status); - this._source = null; - } - } -}; - - -/** -* A container for utility functions used with HTTP headers. -*/ -const headerUtils = -{ - /** -* Normalizes fieldName (by converting it to lowercase) and ensures it is a -* valid header field name (although not necessarily one specified in RFC -* 2616). -* -* @throws NS_ERROR_INVALID_ARG -* if fieldName does not match the field-name production in RFC 2616 -* @returns string -* fieldName converted to lowercase if it is a valid header, for characters -* where case conversion is possible -*/ - normalizeFieldName: function(fieldName) - { - if (fieldName == "") - throw Cr.NS_ERROR_INVALID_ARG; - - for (var i = 0, sz = fieldName.length; i < sz; i++) - { - if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)]) - { - dumpn(fieldName + " is not a valid header field name!"); - throw Cr.NS_ERROR_INVALID_ARG; - } - } - - return fieldName.toLowerCase(); - }, - - /** -* Ensures that fieldValue is a valid header field value (although not -* necessarily as specified in RFC 2616 if the corresponding field name is -* part of the HTTP protocol), normalizes the value if it is, and -* returns the normalized value. -* -* @param fieldValue : string -* a value to be normalized as an HTTP header field value -* @throws NS_ERROR_INVALID_ARG -* if fieldValue does not match the field-value production in RFC 2616 -* @returns string -* fieldValue as a normalized HTTP header field value -*/ - normalizeFieldValue: function(fieldValue) - { - // field-value = *( field-content | LWS ) - // field-content = <the OCTETs making up the field-value - // and consisting of either *TEXT or combinations - // of token, separators, and quoted-string> - // TEXT = <any OCTET except CTLs, - // but including LWS> - // LWS = [CRLF] 1*( SP | HT ) - // - // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) - // qdtext = <any TEXT except <">> - // quoted-pair = "\" CHAR - // CHAR = <any US-ASCII character (octets 0 - 127)> - - // Any LWS that occurs between field-content MAY be replaced with a single - // SP before interpreting the field value or forwarding the message - // downstream (section 4.2); we replace 1*LWS with a single SP - var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " "); - - // remove leading/trailing LWS (which has been converted to SP) - val = val.replace(/^ +/, "").replace(/ +$/, ""); - - // that should have taken care of all CTLs, so val should contain no CTLs - for (var i = 0, len = val.length; i < len; i++) - if (isCTL(val.charCodeAt(i))) - throw Cr.NS_ERROR_INVALID_ARG; - - // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly - // normalize, however, so this can be construed as a tightening of the - // spec and not entirely as a bug - return val; - } -}; - - - -/** -* Converts the given string into a string which is safe for use in an HTML -* context. -* -* @param str : string -* the string to make HTML-safe -* @returns string -* an HTML-safe version of str -*/ -function htmlEscape(str) -{ - // this is naive, but it'll work - var s = ""; - for (var i = 0; i < str.length; i++) - s += "&#" + str.charCodeAt(i) + ";"; - return s; -} - - -/** -* Constructs an object representing an HTTP version (see section 3.1). -* -* @param versionString -* a string of the form "#.#", where # is an non-negative decimal integer with -* or without leading zeros -* @throws -* if versionString does not specify a valid HTTP version number -*/ -function nsHttpVersion(versionString) -{ - var matches = /^(\d+)\.(\d+)$/.exec(versionString); - if (!matches) - throw "Not a valid HTTP version!"; - - /** The major version number of this, as a number. */ - this.major = parseInt(matches[1], 10); - - /** The minor version number of this, as a number. */ - this.minor = parseInt(matches[2], 10); - - if (isNaN(this.major) || isNaN(this.minor) || - this.major < 0 || this.minor < 0) - throw "Not a valid HTTP version!"; -} -nsHttpVersion.prototype = -{ - /** -* Returns the standard string representation of the HTTP version represented -* by this (e.g., "1.1"). -*/ - toString: function () - { - return this.major + "." + this.minor; - }, - - /** -* Returns true if this represents the same HTTP version as otherVersion, -* false otherwise. -* -* @param otherVersion : nsHttpVersion -* the version to compare against this -*/ - equals: function (otherVersion) - { - return this.major == otherVersion.major && - this.minor == otherVersion.minor; - }, - - /** True if this >= otherVersion, false otherwise. */ - atLeast: function(otherVersion) - { - return this.major > otherVersion.major || - (this.major == otherVersion.major && - this.minor >= otherVersion.minor); - } -}; - -nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0"); -nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1"); - - -/** -* An object which stores HTTP headers for a request or response. -* -* Note that since headers are case-insensitive, this object converts headers to -* lowercase before storing them. This allows the getHeader and hasHeader -* methods to work correctly for any case of a header, but it means that the -* values returned by .enumerator may not be equal case-sensitively to the -* values passed to setHeader when adding headers to this. -*/ -function nsHttpHeaders() -{ - /** -* A hash of headers, with header field names as the keys and header field -* values as the values. Header field names are case-insensitive, but upon -* insertion here they are converted to lowercase. Header field values are -* normalized upon insertion to contain no leading or trailing whitespace. -* -* Note also that per RFC 2616, section 4.2, two headers with the same name in -* a message may be treated as one header with the same field name and a field -* value consisting of the separate field values joined together with a "," in -* their original order. This hash stores multiple headers with the same name -* in this manner. -*/ - this._headers = {}; -} -nsHttpHeaders.prototype = -{ - /** -* Sets the header represented by name and value in this. -* -* @param name : string -* the header name -* @param value : string -* the header value -* @throws NS_ERROR_INVALID_ARG -* if name or value is not a valid header component -*/ - setHeader: function(fieldName, fieldValue, merge) - { - var name = headerUtils.normalizeFieldName(fieldName); - var value = headerUtils.normalizeFieldValue(fieldValue); - - // The following three headers are stored as arrays because their real-world - // syntax prevents joining individual headers into a single header using - // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77> - if (merge && name in this._headers) - { - if (name === "www-authenticate" || - name === "proxy-authenticate" || - name === "set-cookie") - { - this._headers[name].push(value); - } - else - { - this._headers[name][0] += "," + value; - NS_ASSERT(this._headers[name].length === 1, - "how'd a non-special header have multiple values?") - } - } - else - { - this._headers[name] = [value]; - } - }, - - /** -* Returns the value for the header specified by this. -* -* @throws NS_ERROR_INVALID_ARG -* if fieldName does not constitute a valid header field name -* @throws NS_ERROR_NOT_AVAILABLE -* if the given header does not exist in this -* @returns string -* the field value for the given header, possibly with non-semantic changes -* (i.e., leading/trailing whitespace stripped, whitespace runs replaced -* with spaces, etc.) at the option of the implementation; multiple -* instances of the header will be combined with a comma, except for -* the three headers noted in the description of getHeaderValues -*/ - getHeader: function(fieldName) - { - return this.getHeaderValues(fieldName).join("\n"); - }, - - /** -* Returns the value for the header specified by fieldName as an array. -* -* @throws NS_ERROR_INVALID_ARG -* if fieldName does not constitute a valid header field name -* @throws NS_ERROR_NOT_AVAILABLE -* if the given header does not exist in this -* @returns [string] -* an array of all the header values in this for the given -* header name. Header values will generally be collapsed -* into a single header by joining all header values together -* with commas, but certain headers (Proxy-Authenticate, -* WWW-Authenticate, and Set-Cookie) violate the HTTP spec -* and cannot be collapsed in this manner. For these headers -* only, the returned array may contain multiple elements if -* that header has been added more than once. -*/ - getHeaderValues: function(fieldName) - { - var name = headerUtils.normalizeFieldName(fieldName); - - if (name in this._headers) - return this._headers[name]; - else - throw Cr.NS_ERROR_NOT_AVAILABLE; - }, - - /** -* Returns true if a header with the given field name exists in this, false -* otherwise. -* -* @param fieldName : string -* the field name whose existence is to be determined in this -* @throws NS_ERROR_INVALID_ARG -* if fieldName does not constitute a valid header field name -* @returns boolean -* true if the header's present, false otherwise -*/ - hasHeader: function(fieldName) - { - var name = headerUtils.normalizeFieldName(fieldName); - return (name in this._headers); - }, - - /** -* Returns a new enumerator over the field names of the headers in this, as -* nsISupportsStrings. The names returned will be in lowercase, regardless of -* how they were input using setHeader (header names are case-insensitive per -* RFC 2616). -*/ - get enumerator() - { - var headers = []; - for (var i in this._headers) - { - var supports = new SupportsString(); - supports.data = i; - headers.push(supports); - } - - return new nsSimpleEnumerator(headers); - } -}; - - -/** -* Constructs an nsISimpleEnumerator for the given array of items. -* -* @param items : Array -* the items, which must all implement nsISupports -*/ -function nsSimpleEnumerator(items) -{ - this._items = items; - this._nextIndex = 0; -} -nsSimpleEnumerator.prototype = -{ - hasMoreElements: function() - { - return this._nextIndex < this._items.length; - }, - getNext: function() - { - if (!this.hasMoreElements()) - throw Cr.NS_ERROR_NOT_AVAILABLE; - - return this._items[this._nextIndex++]; - }, - QueryInterface: function(aIID) - { - if (Ci.nsISimpleEnumerator.equals(aIID) || - Ci.nsISupports.equals(aIID)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; - - -/** -* A representation of the data in an HTTP request. -* -* @param port : uint -* the port on which the server receiving this request runs -*/ -function Request(port) -{ - /** Method of this request, e.g. GET or POST. */ - this._method = ""; - - /** Path of the requested resource; empty paths are converted to '/'. */ - this._path = ""; - - /** Query string, if any, associated with this request (not including '?'). */ - this._queryString = ""; - - /** Scheme of requested resource, usually http, always lowercase. */ - this._scheme = "http"; - - /** Hostname on which the requested resource resides. */ - this._host = undefined; - - /** Port number over which the request was received. */ - this._port = port; - - var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null); - - /** Stream from which data in this request's body may be read. */ - this._bodyInputStream = bodyPipe.inputStream; - - /** Stream to which data in this request's body is written. */ - this._bodyOutputStream = bodyPipe.outputStream; - - /** -* The headers in this request. -*/ - this._headers = new nsHttpHeaders(); - - /** -* For the addition of ad-hoc properties and new functionality without having -* to change nsIHttpRequest every time; currently lazily created, as its only -* use is in directory listings. -*/ - this._bag = null; -} -Request.prototype = -{ - // SERVER METADATA - - // - // see nsIHttpRequest.scheme - // - get scheme() - { - return this._scheme; - }, - - // - // see nsIHttpRequest.host - // - get host() - { - return this._host; - }, - - // - // see nsIHttpRequest.port - // - get port() - { - return this._port; - }, - - // REQUEST LINE - - // - // see nsIHttpRequest.method - // - get method() - { - return this._method; - }, - - // - // see nsIHttpRequest.httpVersion - // - get httpVersion() - { - return this._httpVersion.toString(); - }, - - // - // see nsIHttpRequest.path - // - get path() - { - return this._path; - }, - - // - // see nsIHttpRequest.queryString - // - get queryString() - { - return this._queryString; - }, - - // HEADERS - - // - // see nsIHttpRequest.getHeader - // - getHeader: function(name) - { - return this._headers.getHeader(name); - }, - - // - // see nsIHttpRequest.hasHeader - // - hasHeader: function(name) - { - return this._headers.hasHeader(name); - }, - - // - // see nsIHttpRequest.headers - // - get headers() - { - return this._headers.enumerator; - }, - - // - // see nsIPropertyBag.enumerator - // - get enumerator() - { - this._ensurePropertyBag(); - return this._bag.enumerator; - }, - - // - // see nsIHttpRequest.headers - // - get bodyInputStream() - { - return this._bodyInputStream; - }, - - // - // see nsIPropertyBag.getProperty - // - getProperty: function(name) - { - this._ensurePropertyBag(); - return this._bag.getProperty(name); - }, - - - // NSISUPPORTS - - // - // see nsISupports.QueryInterface - // - QueryInterface: function(iid) - { - if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - - // PRIVATE IMPLEMENTATION - - /** Ensures a property bag has been created for ad-hoc behaviors. */ - _ensurePropertyBag: function() - { - if (!this._bag) - this._bag = new WritablePropertyBag(); - } -}; - - -// XPCOM trappings -if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason... - "generateNSGetFactory" in XPCOMUtils) { - var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]); -} - - - -/** -* Creates a new HTTP server listening for loopback traffic on the given port, -* starts it, and runs the server until the server processes a shutdown request, -* spinning an event loop so that events posted by the server's socket are -* processed. -* -* This method is primarily intended for use in running this script from within -* xpcshell and running a functional HTTP server without having to deal with -* non-essential details. -* -* Note that running multiple servers using variants of this method probably -* doesn't work, simply due to how the internal event loop is spun and stopped. -* -* @note -* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code); -* you should use this server as a component in Mozilla 1.8. -* @param port -* the port on which the server will run, or -1 if there exists no preference -* for a specific port; note that attempting to use some values for this -* parameter (particularly those below 1024) may cause this method to throw or -* may result in the server being prematurely shut down -* @param basePath -* a local directory from which requests will be served (i.e., if this is -* "/home/jwalden/" then a request to /index.html will load -* /home/jwalden/index.html); if this is omitted, only the default URLs in -* this server implementation will be functional -*/ -function server(port, basePath) -{ - if (basePath) - { - var lp = Cc["@mozilla.org/file/local;1"] - .createInstance(Ci.nsILocalFile); - lp.initWithPath(basePath); - } - - // if you're running this, you probably want to see debugging info - DEBUG = true; - - var srv = new nsHttpServer(); - if (lp) - srv.registerDirectory("/", lp); - srv.registerContentType("sjs", SJS_TYPE); - srv.identity.setPrimary("http", "localhost", port); - srv.start(port); - - var thread = gThreadManager.currentThread; - while (!srv.isStopped()) - thread.processNextEvent(true); - - // get rid of any pending requests - while (thread.hasPendingEvents()) - thread.processNextEvent(true); - - DEBUG = false; -} - -function startServerAsync(port, basePath) -{ - if (basePath) - { - var lp = Cc["@mozilla.org/file/local;1"] - .createInstance(Ci.nsILocalFile); - lp.initWithPath(basePath); - } - - var srv = new nsHttpServer(); - if (lp) - srv.registerDirectory("/", lp); - srv.registerContentType("sjs", "sjs"); - srv.identity.setPrimary("http", "localhost", port); - srv.start(port); - return srv; -} - -exports.nsHttpServer = nsHttpServer; -exports.ScriptableInputStream = ScriptableInputStream; -exports.server = server; -exports.startServerAsync = startServerAsync; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/hotkeys.js b/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/hotkeys.js deleted file mode 100644 index 6851671..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/hotkeys.js +++ /dev/null @@ -1,141 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * Paul Vet <original.roju@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { observer: keyboardObserver } = require("./observer"); -const { getKeyForCode, normalize, isFunctionKey, - MODIFIERS } = require("./utils"); - -/** - * Register a global `hotkey` that executes `listener` when the key combination - * in `hotkey` is pressed. If more then one `listener` is registered on the same - * key combination only last one will be executed. - * - * @param {string} hotkey - * Key combination in the format of 'modifier key'. - * - * Examples: - * - * "accel s" - * "meta shift i" - * "control alt d" - * - * Modifier keynames: - * - * - **shift**: The Shift key. - * - **alt**: The Alt key. On the Macintosh, this is the Option key. On - * Macintosh this can only be used in conjunction with another modifier, - * since `Alt+Letter` combinations are reserved for entering special - * characters in text. - * - **meta**: The Meta key. On the Macintosh, this is the Command key. - * - **control**: The Control key. - * - **accel**: The key used for keyboard shortcuts on the user's platform, - * which is Control on Windows and Linux, and Command on Mac. Usually, this - * would be the value you would use. - * - * @param {function} listener - * Function to execute when the `hotkey` is executed. - */ -exports.register = function register(hotkey, listener) { - hotkey = normalize(hotkey); - hotkeys[hotkey] = listener; -}; - -/** - * Unregister a global `hotkey`. If passed `listener` is not the one registered - * for the given `hotkey`, the call to this function will be ignored. - * - * @param {string} hotkey - * Key combination in the format of 'modifier key'. - * @param {function} listener - * Function that will be invoked when the `hotkey` is pressed. - */ -exports.unregister = function unregister(hotkey, listener) { - hotkey = normalize(hotkey); - if (hotkeys[hotkey] === listener) - delete hotkeys[hotkey]; -}; - -/** - * Map of hotkeys and associated functions. - */ -const hotkeys = exports.hotkeys = {}; - -keyboardObserver.on("keydown", function onKeypress(event, window) { - let key, modifiers = []; - let isChar = "isChar" in event && event.isChar; - let which = "which" in event ? event.which : null; - let keyCode = "keyCode" in event ? event.keyCode : null; - - if ("shiftKey" in event && event.shiftKey) - modifiers.push("shift"); - if ("altKey" in event && event.altKey) - modifiers.push("alt"); - if ("ctrlKey" in event && event.ctrlKey) - modifiers.push("control"); - if ("metaKey" in event && event.metaKey) - modifiers.push("meta"); - - // If it's not a printable character then we fall back to a human readable - // equivalent of one of the following constants. - // http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/events/nsIDOMKeyEvent.idl - key = getKeyForCode(keyCode); - - // If only non-function (f1 - f24) key or only modifiers are pressed we don't - // have a valid combination so we return immediately (Also, sometimes - // `keyCode` may be one for the modifier which means we do not have a - // modifier). - if (!key || (!isFunctionKey(key) && !modifiers.length) || key in MODIFIERS) - return; - - let combination = normalize({ key: key, modifiers: modifiers }); - let hotkey = hotkeys[combination]; - - if (hotkey) { - try { - hotkey(); - } catch (exception) { - console.exception(exception); - } finally { - // Work around bug 582052 by preventing the (nonexistent) default action. - event.preventDefault(); - } - } -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/observer.js b/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/observer.js deleted file mode 100644 index 6968551..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/observer.js +++ /dev/null @@ -1,86 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Trait } = require("../light-traits"); -const { EventEmitterTrait: EventEmitter } = require("../events"); -const { DOMEventAssembler } = require("../events/assembler"); -const { browserWindowIterator, isBrowser } = require('../window-utils'); -const { observer: windowObserver } = require("../windows/observer"); - -// Event emitter objects used to register listeners and emit events on them -// when they occur. -const observer = Trait.compose(DOMEventAssembler, EventEmitter).create({ - /** - * Method is implemented by `EventEmitter` and is used just for emitting - * events on registered listeners. - */ - _emit: Trait.required, - /** - * Events that are supported and emitted by the module. - */ - supportedEventsTypes: [ "keydown", "keyup", "keypress" ], - /** - * Function handles all the supported events on all the windows that are - * observed. Method is used to proxy events to the listeners registered on - * this event emitter. - * @param {Event} event - * Keyboard event being emitted. - */ - handleEvent: function handleEvent(event) { - this._emit(event.type, event, event.target.ownerDocument.defaultView); - } -}); - -// Adding each opened window to a list of observed windows. -windowObserver.on("open", function onOpen(window) { - if (isBrowser(window)) - observer.observe(window); -}); -// Removing each closed window form the list of observed windows. -windowObserver.on("close", function onClose(window) { - if (isBrowser(window)) - observer.ignore(window); -}); - -// Making observer aware of already opened windows. -for each (let window in browserWindowIterator()) - observer.observe(window); - -exports.observer = observer; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/utils.js b/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/utils.js deleted file mode 100644 index 0c9a7fb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/keyboard/utils.js +++ /dev/null @@ -1,220 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * Henri Wiechers <hwiechers@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci } = require("chrome"); -const runtime = require("../runtime"); -const { isString } = require("../type"); -const array = require("../array"); - - -const SWP = "{{SEPARATOR}}"; -const SEPARATOR = "-" -const INVALID_COMBINATION = "Hotkey key combination must contain one or more " + - "modifiers and only one key"; - -// Map of modifier key mappings. -const MODIFIERS = exports.MODIFIERS = { - 'accel': runtime.OS === "Darwin" ? 'meta' : 'control', - 'meta': 'meta', - 'control': 'control', - 'ctrl': 'control', - 'option': 'alt', - 'command': 'meta', - 'alt': 'alt', - 'shift': 'shift' -}; - -// Hash of key:code pairs for all the chars supported by `nsIDOMKeyEvent`. -// This is just a copy of the `nsIDOMKeyEvent` hash with normalized names. -// @See: http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/events/nsIDOMKeyEvent.idl -const CODES = exports.CODES = new function Codes() { - let nsIDOMKeyEvent = Ci.nsIDOMKeyEvent; - // Names that will be substituted with a shorter analogs. - let aliases = { - 'subtract': '-', - 'add': '+', - 'equals': '=', - 'slash': '/', - 'backslash': '\\', - 'openbracket': '[', - 'closebracket': ']', - 'quote': '\'', - 'backquote': '`', - 'period': '.', - 'semicolon': ';', - 'comma': ',' - }; - - // Normalizing keys and copying values to `this` object. - Object.keys(nsIDOMKeyEvent).filter(function(key) { - // Filter out only key codes. - return key.indexOf('DOM_VK') === 0; - }).map(function(key) { - // Map to key:values - return [ key, nsIDOMKeyEvent[key] ]; - }).map(function([key, value]) { - return [ key.replace('DOM_VK_', '').replace('_', '').toLowerCase(), value ]; - }).forEach(function ([ key, value ]) { - this[aliases[key] || key] = value; - }, this); -}; - -// Inverted `CODES` hash of `code:key`. -const KEYS = exports.KEYS = new function Keys() { - Object.keys(CODES).forEach(function(key) { - this[CODES[key]] = key; - }, this) -} - -exports.getKeyForCode = function getKeyForCode(code) { - return (code in KEYS) && KEYS[code]; -}; -exports.getCodeForKey = function getCodeForKey(key) { - return (key in CODES) && CODES[key]; -}; - -/** - * Utility function that takes string or JSON that defines a `hotkey` and - * returns normalized string version of it. - * @param {JSON|String} hotkey - * @param {String} [separator=" "] - * Optional string that represents separator used to concatenate keys in the - * given `hotkey`. - * @returns {String} - * @examples - * - * require("keyboard/hotkeys").normalize("b Shift accel"); - * // 'control shift b' -> on windows & linux - * // 'meta shift b' -> on mac - * require("keyboard/hotkeys").normalize("alt-d-shift", "-"); - * // 'alt shift d' - */ -var normalize = exports.normalize = function normalize(hotkey, separator) { - if (!isString(hotkey)) - hotkey = toString(hotkey, separator); - return toString(toJSON(hotkey, separator), separator); -}; - -/* - * Utility function that splits a string of characters that defines a `hotkey` - * into modifier keys and the defining key. - * @param {String} hotkey - * @param {String} [separator=" "] - * Optional string that represents separator used to concatenate keys in the - * given `hotkey`. - * @returns {JSON} - * @examples - * - * require("keyboard/hotkeys").toJSON("accel shift b"); - * // { key: 'b', modifiers: [ 'control', 'shift' ] } -> on windows & linux - * // { key: 'b', modifiers: [ 'meta', 'shift' ] } -> on mac - * - * require("keyboard/hotkeys").normalize("alt-d-shift", "-"); - * // { key: 'd', modifiers: [ 'alt', 'shift' ] } - */ -var toJSON = exports.toJSON = function toJSON(hotkey, separator) { - separator = separator || SEPARATOR; - // Since default separator is `-`, combination may take form of `alt--`. To - // avoid misbehavior we replace `--` with `-{{SEPARATOR}}` where - // `{{SEPARATOR}}` can be swapped later. - hotkey = hotkey.toLowerCase().replace(separator + separator, separator + SWP); - - let value = {}; - let modifiers = []; - let keys = hotkey.split(separator); - keys.forEach(function(name) { - // If name is `SEPARATOR` than we swap it back. - if (name === SWP) - name = separator; - if (name in MODIFIERS) { - array.add(modifiers, MODIFIERS[name]); - } else { - if (!value.key) - value.key = name; - else - throw new TypeError(INVALID_COMBINATION); - } - }); - - if (!value.key) - throw new TypeError(INVALID_COMBINATION); - - value.modifiers = modifiers.sort(); - return value; -}; - -/** - * Utility function that takes object that defines a `hotkey` and returns - * string representation of it. - * - * _Please note that this function does not validates data neither it normalizes - * it, if you are unsure that data is well formed use `normalize` function - * instead. - * - * @param {JSON} hotkey - * @param {String} [separator=" "] - * Optional string that represents separator used to concatenate keys in the - * given `hotkey`. - * @returns {String} - * @examples - * - * require("keyboard/hotkeys").toString({ - * key: 'b', - * modifiers: [ 'control', 'shift' ] - * }, '+'); - * // 'control+shift+b - * - */ -var toString = exports.toString = function toString(hotkey, separator) { - let keys = hotkey.modifiers.slice(); - keys.push(hotkey.key); - return keys.join(separator || SEPARATOR); -}; - -/** - * Utility function takes `key` name and returns `true` if it's function key - * (F1, ..., F24) and `false` if it's not. - */ -var isFunctionKey = exports.isFunctionKey = function isFunctionKey(key) { - var $ - return key[0].toLowerCase() === 'f' && - ($ = parseInt(key.substr(1)), 0 < $ && $ < 25); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/light-traits.js b/tools/addon-sdk-1.4/packages/api-utils/lib/light-traits.js deleted file mode 100644 index 1afaad5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/light-traits.js +++ /dev/null @@ -1,626 +0,0 @@ -/* vim:ts=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <rfobic@gmail.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// `var` is being used in the module in order to make it reusable in -// environments in which `let` is not yet supported. - -// Shortcut to `Object.prototype.hasOwnProperty.call`. -// owns(object, name) would be the same as -// Object.prototype.hasOwnProperty.call(object, name); -var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty); - -/** - * Whether or not given property descriptors are equivalent. They are - * equivalent either if both are marked as 'conflict' or 'required' property - * or if all the properties of descriptors are equal. - * @param {Object} actual - * @param {Object} expected - */ -function equivalentDescriptors(actual, expected) { - return (actual.conflict && expected.conflict) || - (actual.required && expected.required) || - equalDescriptors(actual, expected); -} -/** - * Whether or not given property descriptors define equal properties. - */ -function equalDescriptors(actual, expected) { - return actual.get === expected.get && - actual.set === expected.set && - actual.value === expected.value && - !!actual.enumerable === !!expected.enumerable && - !!actual.configurable === !!expected.configurable && - !!actual.writable === !!expected.writable; -} - -// Utilities that throwing exceptions for a properties that are marked -// as "required" or "conflict" properties. -function throwConflictPropertyError(name) { - throw new Error("Remaining conflicting property: `" + name + "`"); -} -function throwRequiredPropertyError(name) { - throw new Error("Missing required property: `" + name + "`"); -} - -/** - * Generates custom **required** property descriptor. Descriptor contains - * non-standard property `required` that is equal to `true`. - * @param {String} name - * property name to generate descriptor for. - * @returns {Object} - * custom property descriptor - */ -function RequiredPropertyDescriptor(name) { - // Creating function by binding first argument to a property `name` on the - // `throwConflictPropertyError` function. Created function is used as a - // getter & setter of the created property descriptor. This way we ensure - // that we throw exception late (on property access) if object with - // `required` property was instantiated using built-in `Object.create`. - var accessor = throwRequiredPropertyError.bind(null, name); - return { get: accessor, set: accessor, required: true }; -} - -/** - * Generates custom **conflicting** property descriptor. Descriptor contains - * non-standard property `conflict` that is equal to `true`. - * @param {String} name - * property name to generate descriptor for. - * @returns {Object} - * custom property descriptor - */ -function ConflictPropertyDescriptor(name) { - // For details see `RequiredPropertyDescriptor` since idea is same. - var accessor = throwConflictPropertyError.bind(null, name); - return { get: accessor, set: accessor, conflict: true }; -} - -/** - * Tests if property is marked as `required` property. - */ -function isRequiredProperty(object, name) { - return !!object[name].required; -} - -/** - * Tests if property is marked as `conflict` property. - */ -function isConflictProperty(object, name) { - return !!object[name].conflict; -} - -/** - * Function tests whether or not method of the `source` object with a given - * `name` is inherited from `Object.prototype`. - */ -function isBuiltInMethod(name, source) { - var target = Object.prototype[name]; - - // If methods are equal then we know it's `true`. - return target == source || - // If `source` object comes form a different sandbox `==` will evaluate - // to `false`, in that case we check if functions names and sources match. - (String(target) === String(source) && target.name === source.name); -} - -/** - * Function overrides `toString` and `constructor` methods of a given `target` - * object with a same-named methods of a given `source` if methods of `target` - * object are inherited / copied from `Object.prototype`. - * @see create - */ -function overrideBuiltInMethods(target, source) { - if (isBuiltInMethod("toString", target.toString)) { - Object.defineProperty(target, "toString", { - value: source.toString, - configurable: true, - enumerable: false - }); - } - - if (isBuiltInMethod("constructor", target.constructor)) { - Object.defineProperty(target, "constructor", { - value: source.constructor, - configurable: true, - enumerable: false - }); - } -} - -/** - * Composes new trait with the same own properties as the original trait, - * except that all property names appearing in the first argument are replaced - * by "required" property descriptors. - * @param {String[]} keys - * Array of strings property names. - * @param {Object} trait - * A trait some properties of which should be excluded. - * @returns {Object} - * @example - * var newTrait = exclude(["name", ...], trait) - */ -function exclude(names, trait) { - var map = {}; - - Object.keys(trait).forEach(function(name) { - - // If property is not excluded (the array of names does not contain it), - // or it is a "required" property, copy it to the property descriptor `map` - // that will be used for creation of resulting trait. - if (!~names.indexOf(name) || isRequiredProperty(trait, name)) - map[name] = { value: trait[name], enumerable: true }; - - // For all the `names` in the exclude name array we create required - // property descriptors and copy them to the `map`. - else - map[name] = { value: RequiredPropertyDescriptor(name), enumerable: true }; - }); - - return Object.create(Trait.prototype, map); -} - -/** - * Composes new instance of `Trait` with a properties of a given `trait`, - * except that all properties whose name is an own property of `renames` will - * be renamed to `renames[name]` and a `"required"` property for name will be - * added instead. - * - * For each renamed property, a required property is generated. If - * the `renames` map two properties to the same name, a conflict is generated. - * If the `renames` map a property to an existing unrenamed property, a - * conflict is generated. - * - * @param {Object} renames - * An object whose own properties serve as a mapping from old names to new - * names. - * @param {Object} trait - * A new trait with renamed properties. - * @returns {Object} - * @example - * - * // Return trait with `bar` property equal to `trait.foo` and with - * // `foo` and `baz` "required" properties. - * var renamedTrait = rename({ foo: "bar", baz: null }), trait); - * - * // t1 and t2 are equivalent traits - * var t1 = rename({a: "b"}, t); - * var t2 = compose(exclude(["a"], t), { a: { required: true }, b: t[a] }); - */ -function rename(renames, trait) { - var map = {}; - - // Loop over all the properties of the given `trait` and copy them to a - // property descriptor `map` that will be used for the creation of the - // resulting trait. Also, rename properties in the `map` as specified by - // `renames`. - Object.keys(trait).forEach(function(name) { - var alias; - - // If the property is in the `renames` map, and it isn't a "required" - // property (which should never need to be aliased because "required" - // properties never conflict), then we must try to rename it. - if (owns(renames, name) && !isRequiredProperty(trait, name)) { - alias = renames[name]; - - // If the `map` already has the `alias`, and it isn't a "required" - // property, that means the `alias` conflicts with an existing name for a - // provided trait (that can happen if >=2 properties are aliased to the - // same name). In this case we mark it as a conflicting property. - // Otherwise, everything is fine, and we copy property with an `alias` - // name. - if (owns(map, alias) && !map[alias].value.required) { - map[alias] = { - value: ConflictPropertyDescriptor(alias), - enumerable: true - }; - } - else { - map[alias] = { - value: trait[name], - enumerable: true - }; - } - - // Regardless of whether or not the rename was successful, we check to - // see if the original `name` exists in the map (such a property - // could exist if previous another property was aliased to this `name`). - // If it isn't, we mark it as "required", to make sure the caller - // provides another value for the old name, which methods of the trait - // might continue to reference. - if (!owns(map, name)) { - map[name] = { - value: RequiredPropertyDescriptor(name), - enumerable: true - }; - } - } - - // Otherwise, either the property isn't in the `renames` map (thus the - // caller is not trying to rename it) or it is a "required" property. - // Either way, we don't have to alias the property, we just have to copy it - // to the map. - else { - // The property isn't in the map yet, so we copy it over. - if (!owns(map, name)) { - map[name] = { value: trait[name], enumerable: true }; - } - - // The property is already in the map (that means another property was - // aliased with this `name`, which creates a conflict if the property is - // not marked as "required"), so we have to mark it as a "conflict" - // property. - else if (!isRequiredProperty(trait, name)) { - map[name] = { - value: ConflictPropertyDescriptor(name), - enumerable: true - }; - } - } - }); - return Object.create(Trait.prototype, map); -} - -/** - * Composes new resolved trait, with all the same properties as the original - * `trait`, except that all properties whose name is an own property of - * `resolutions` will be renamed to `resolutions[name]`. - * - * If `resolutions[name]` is `null`, the value is mapped to a property - * descriptor that is marked as a "required" property. - */ -function resolve(resolutions, trait) { - var renames = {}; - var exclusions = []; - - // Go through each mapping in `resolutions` object and distribute it either - // to `renames` or `exclusions`. - Object.keys(resolutions).forEach(function(name) { - - // If `resolutions[name]` is a truthy value then it's a mapping old -> new - // so we copy it to `renames` map. - if (resolutions[name]) - renames[name] = resolutions[name]; - - // Otherwise it's not a mapping but an exclusion instead in which case we - // add it to the `exclusions` array. - else - exclusions.push(name); - }); - - // First `exclude` **then** `rename` and order is important since - // `exclude` and `rename` are not associative. - return rename(renames, exclude(exclusions, trait)); -} - -/** - * Create a Trait (a custom property descriptor map) that represents the given - * `object`'s own properties. Property descriptor map is a "custom", because it - * inherits from `Trait.prototype` and it's property descriptors may contain - * two attributes that is not part of the ES5 specification: - * - * - "required" (this property must be provided by another trait - * before an instance of this trait can be created) - * - "conflict" (when the trait is composed with another trait, - * a unique value for this property is provided by two or more traits) - * - * Data properties bound to the `Trait.required` singleton exported by - * this module will be marked as "required" properties. - * - * @param {Object} object - * Map of properties to compose trait from. - * @returns {Trait} - * Trait / Property descriptor map containing all the own properties of the - * given argument. - */ -function trait(object) { - var map; - var trait = object; - - if (!(object instanceof Trait)) { - // If the passed `object` is not already an instance of `Trait`, we create - // a property descriptor `map` containing descriptors for the own properties - // of the given `object`. `map` is then used to create a `Trait` instance - // after all properties are mapped. Note that we can't create a trait and - // then just copy properties into it since that will fail for inherited - // read-only properties. - map = {}; - - // Each own property of the given `object` is mapped to a data property - // whose value is a property descriptor. - Object.keys(object).forEach(function (name) { - - // If property of an `object` is equal to a `Trait.required`, it means - // that it was marked as "required" property, in which case we map it - // to "required" property. - if (Trait.required == - Object.getOwnPropertyDescriptor(object, name).value) { - map[name] = { - value: RequiredPropertyDescriptor(name), - enumerable: true - }; - } - // Otherwise property is mapped to it's property descriptor. - else { - map[name] = { - value: Object.getOwnPropertyDescriptor(object, name), - enumerable: true - }; - } - }); - - trait = Object.create(Trait.prototype, map); - } - return trait; -} - -/** - * Compose a property descriptor map that inherits from `Trait.prototype` and - * contains property descriptors for all the own properties of the passed - * traits. - * - * If two or more traits have own properties with the same name, the returned - * trait will contain a "conflict" property for that name. Composition is a - * commutative and associative operation, and the order of its arguments is - * irrelevant. - */ -function compose(trait1, trait2/*, ...*/) { - // Create a new property descriptor `map` to which all the own properties - // of the passed traits are copied. This map will be used to create a `Trait` - // instance that will be the result of this composition. - var map = {}; - - // Properties of each passed trait are copied to the composition. - Array.prototype.forEach.call(arguments, function(trait) { - // Copying each property of the given trait. - Object.keys(trait).forEach(function(name) { - - // If `map` already owns a property with the `name` and it is not - // marked "required". - if (owns(map, name) && !map[name].value.required) { - - // If the source trait's property with the `name` is marked as - // "required", we do nothing, as the requirement was already resolved - // by a property in the `map` (because it already contains a - // non-required property with that `name`). But if properties are just - // different, we have a name clash and we substitute it with a property - // that is marked "conflict". - if (!isRequiredProperty(trait, name) && - !equivalentDescriptors(map[name].value, trait[name]) - ) { - map[name] = { - value: ConflictPropertyDescriptor(name), - enumerable: true - }; - } - } - - // Otherwise, the `map` does not have an own property with the `name`, or - // it is marked "required". Either way, the trait's property is copied to - // the map (if the property of the `map` is marked "required", it is going - // to be resolved by the property that is being copied). - else { - map[name] = { value: trait[name], enumerable: true }; - } - }); - }); - - return Object.create(Trait.prototype, map); -} - -/** - * `defineProperties` is like `Object.defineProperties`, except that it - * ensures that: - * - An exception is thrown if any property in a given `properties` map - * is marked as "required" property and same named property is not - * found in a given `prototype`. - * - An exception is thrown if any property in a given `properties` map - * is marked as "conflict" property. - * @param {Object} object - * Object to define properties on. - * @param {Object} properties - * Properties descriptor map. - * @returns {Object} - * `object` that was passed as a first argument. - */ -function defineProperties(object, properties) { - - // Create a map into which we will copy each verified property from the given - // `properties` description map. We use it to verify that none of the - // provided properties is marked as a "conflict" property and that all - // "required" properties are resolved by a property of an `object`, so we - // can throw an exception before mutating object if that isn't the case. - var verifiedProperties = {}; - - // Coping each property from a given `properties` descriptor map to a - // verified map of property descriptors. - Object.keys(properties).forEach(function(name) { - - // If property is marked as "required" property and we don't have a same - // named property in a given `object` we throw an exception. If `object` - // has same named property just skip this property since required property - // is was inherited and there for requirement was satisfied. - if (isRequiredProperty(properties, name)) { - if (!(name in object)) - throwRequiredPropertyError(name); - } - - // If property is marked as "conflict" property we throw an exception. - else if (isConflictProperty(properties, name)) { - throwConflictPropertyError(name); - } - - // If property is not marked neither as "required" nor "conflict" property - // we copy it to verified properties map. - else { - verifiedProperties[name] = properties[name]; - } - }); - - // If no exceptions were thrown yet, we know that our verified property - // descriptor map has no properties marked as "conflict" or "required", - // so we just delegate to the built-in `Object.defineProperties`. - return Object.defineProperties(object, verifiedProperties); -} - -/** - * `create` is like `Object.create`, except that it ensures that: - * - An exception is thrown if any property in a given `properties` map - * is marked as "required" property and same named property is not - * found in a given `prototype`. - * - An exception is thrown if any property in a given `properties` map - * is marked as "conflict" property. - * @param {Object} prototype - * prototype of the composed object - * @param {Object} properties - * Properties descriptor map. - * @returns {Object} - * An object that inherits form a given `prototype` and implements all the - * properties defined by a given `properties` descriptor map. - */ -function create(prototype, properties) { - - // Creating an instance of the given `prototype`. - var object = Object.create(prototype); - - // Overriding `toString`, `constructor` methods if they are just inherited - // from `Object.prototype` with a same named methods of the `Trait.prototype` - // that will have more relevant behavior. - overrideBuiltInMethods(object, Trait.prototype); - - // Trying to define given `properties` on the `object`. We use our custom - // `defineProperties` function instead of build-in `Object.defineProperties` - // that behaves exactly the same, except that it will throw if any - // property in the given `properties` descriptor is marked as "required" or - // "conflict" property. - return defineProperties(object, properties); -} - -/** - * Composes new trait. If two or more traits have own properties with the - * same name, the new trait will contain a "conflict" property for that name. - * "compose" is a commutative and associative operation, and the order of its - * arguments is not significant. - * - * **Note:** Use `Trait.compose` instead of calling this function with more - * than one argument. The multiple-argument functionality is strictly for - * backward compatibility. - * - * @params {Object} trait - * Takes traits as an arguments - * @returns {Object} - * New trait containing the combined own properties of all the traits. - * @example - * var newTrait = compose(trait_1, trait_2, ..., trait_N) - */ -function Trait(trait1, trait2) { - - // If the function was called with one argument, the argument should be - // an object whose properties are mapped to property descriptors on a new - // instance of Trait, so we delegate to the trait function. - // If the function was called with more than one argument, those arguments - // should be instances of Trait or plain property descriptor maps - // whose properties should be mixed into a new instance of Trait, - // so we delegate to the compose function. - - return trait2 === undefined ? trait(trait1) : compose.apply(null, arguments); -} - -Object.freeze(Object.defineProperties(Trait.prototype, { - toString: { - value: function toString() { - return "[object " + this.constructor.name + "]"; - } - }, - - /** - * `create` is like `Object.create`, except that it ensures that: - * - An exception is thrown if this trait defines a property that is - * marked as required property and same named property is not - * found in a given `prototype`. - * - An exception is thrown if this trait contains property that is - * marked as "conflict" property. - * @param {Object} - * prototype of the compared object - * @returns {Object} - * An object with all of the properties described by the trait. - */ - create: { - value: function createTrait(prototype) { - return create(undefined === prototype ? Object.prototype : prototype, - this); - }, - enumerable: true - }, - - /** - * Composes a new resolved trait, with all the same properties as the original - * trait, except that all properties whose name is an own property of - * `resolutions` will be renamed to the value of `resolutions[name]`. If - * `resolutions[name]` is `null`, the property is marked as "required". - * @param {Object} resolutions - * An object whose own properties serve as a mapping from old names to new - * names, or to `null` if the property should be excluded. - * @returns {Object} - * New trait with the same own properties as the original trait but renamed. - */ - resolve: { - value: function resolveTrait(resolutions) { - return resolve(resolutions, this); - }, - enumerable: true - } -})); - -/** - * @see compose - */ -Trait.compose = Object.freeze(compose); -Object.freeze(compose.prototype); - -/** - * Constant singleton, representing placeholder for required properties. - * @type {Object} - */ -Trait.required = Object.freeze(Object.create(Object.prototype, { - toString: { - value: Object.freeze(function toString() { - return "<Trait.required>"; - }) - } -})); -Object.freeze(Trait.required.toString.prototype); - -exports.Trait = Object.freeze(Trait); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/list.js b/tools/addon-sdk-1.4/packages/api-utils/lib/list.js deleted file mode 100644 index 8643a0a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/list.js +++ /dev/null @@ -1,147 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Trait } = require('./traits'); - -/** - * @see https://jetpack.mozillalabs.com/sdk/latest/docs/#module/api-utils/list - */ -const Iterable = Trait.compose({ - /** - * Hash map of key-values to iterate over. - * Note: That this property can be a getter if you need dynamic behavior. - * @type {Object} - */ - _keyValueMap: Trait.required, - /** - * Custom iterator providing `Iterable`s enumeration behavior. - * @param {Boolean} onKeys - */ - __iterator__: function __iterator__(onKeys, onKeyValue) { - let map = this._keyValueMap; - for (let key in map) - yield onKeyValue ? [key, map[key]] : onKeys ? key : map[key]; - } -}); -exports.Iterable = Iterable; - -/** - * An ordered collection (also known as a sequence) disallowing duplicate - * elements. List is composed out of `Iterable` there for it provides custom - * enumeration behavior that is similar to array (enumerates only on the - * elements of the list). List is a base trait and is meant to be a part of - * composition, since all of it's API is private except length property. - */ -const List = Trait.resolve({ toString: null }).compose({ - _keyValueMap: null, - /** - * List constructor can take any number of element to populate itself. - * @params {Object|String|Number} element - * @example - * List(1,2,3).length == 3 // true - */ - constructor: function List() { - this._keyValueMap = []; - for (let i = 0, ii = arguments.length; i < ii; i++) - this._add(arguments[i]); - }, - /** - * Number of elements in this list. - * @type {Number} - */ - get length() this._keyValueMap.length, - /** - * Returns a string representing this list. - * @returns {String} - */ - toString: function toString() 'List(' + this._keyValueMap + ')', - /** - * Returns `true` if this list contains the specified `element`. - * @param {Object|Number|String} element - * @returns {Boolean} - */ - _has: function _has(element) 0 <= this._keyValueMap.indexOf(element), - /** - * Appends the specified `element` to the end of this list, if it doesn't - * contains it. Ignores the call if `element` is already contained. - * @param {Object|Number|String} element - */ - _add: function _add(element) { - let list = this._keyValueMap, - index = list.indexOf(element); - if (0 > index) - list.push(this._public[list.length] = element); - }, - /** - * Removes specified `element` from this list, if it contains it. - * Ignores the call if `element` is not contained. - * @param {Object|Number|String} element - */ - _remove: function _remove(element) { - let list = this._keyValueMap, - index = list.indexOf(element); - if (0 <= index) { - delete this._public[list.length - 1]; - list.splice(index, 1); - for (let length = list.length; index < length; index++) - this._public[index] = list[index]; - } - }, - /** - * Removes all of the elements from this list. - */ - _clear: function _clear() { - for (let i = 0, ii = this._keyValueMap.length; i < ii; i ++) - delete this._public[i]; - this._keyValueMap.splice(0); - }, - /** - * Custom iterator providing `List`s enumeration behavior. - * We cant reuse `_iterator` that is defined by `Iterable` since it provides - * iteration in an arbitrary order. - * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in - * @param {Boolean} onKeys - */ - __iterator__: function __iterator__(onKeys, onKeyValue) { - let array = this._keyValueMap.slice(0), - i = -1; - for each(let element in array) - yield onKeyValue ? [++i, element] : onKeys ? ++i : element; - } -}); -exports.List = List; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/match-pattern.js b/tools/addon-sdk-1.4/packages/api-utils/lib/match-pattern.js deleted file mode 100644 index 802fe3a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/match-pattern.js +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Nickolay Ponomarev. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Nickolay Ponomarev <asqueella@gmail.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -const { URL } = require("./url"); - -exports.MatchPattern = MatchPattern; - -function MatchPattern(pattern) { - if (typeof pattern.test == "function") { - - // For compatibility with -moz-document rules, we require the RegExp's - // global, ignoreCase, and multiline flags to be set to false. - if (pattern.global) { - throw new Error("A RegExp match pattern cannot be set to `global` " + - "(i.e. //g)."); - } - if (pattern.ignoreCase) { - throw new Error("A RegExp match pattern cannot be set to `ignoreCase` " + - "(i.e. //i)."); - } - if (pattern.multiline) { - throw new Error("A RegExp match pattern cannot be set to `multiline` " + - "(i.e. //m)."); - } - - this.regexp = pattern; - } - else { - let firstWildcardPosition = pattern.indexOf("*"); - let lastWildcardPosition = pattern.lastIndexOf("*"); - if (firstWildcardPosition != lastWildcardPosition) - throw new Error("There can be at most one '*' character in a wildcard."); - - if (firstWildcardPosition == 0) { - if (pattern.length == 1) - this.anyWebPage = true; - else if (pattern[1] != ".") - throw new Error("Expected a *.<domain name> string, got: " + pattern); - else - this.domain = pattern.substr(2); - } - else { - if (pattern.indexOf(":") == -1) { - throw new Error("When not using *.example.org wildcard, the string " + - "supplied is expected to be either an exact URL to " + - "match or a URL prefix. The provided string ('" + - pattern + "') is unlikely to match any pages."); - } - - if (firstWildcardPosition == -1) - this.exactURL = pattern; - else if (firstWildcardPosition == pattern.length - 1) - this.urlPrefix = pattern.substr(0, pattern.length - 1); - else { - throw new Error("The provided wildcard ('" + pattern + "') has a '*' " + - "in an unexpected position. It is expected to be the " + - "first or the last character in the wildcard."); - } - } - } -} - -MatchPattern.prototype = { - - test: function MatchPattern_test(urlStr) { - try { - var url = URL(urlStr); - } - catch (err) { - return false; - } - - // Test the URL against a RegExp pattern. For compatibility with - // -moz-document rules, we require the RegExp to match the entire URL, - // so we not only test for a match, we also make sure the matched string - // is the entire URL string. - // - // Assuming most URLs don't match most match patterns, we call `test` for - // speed when determining whether or not the URL matches, then call `exec` - // for the small subset that match to make sure the entire URL matches. - // - if (this.regexp && this.regexp.test(urlStr) && - this.regexp.exec(urlStr)[0] == urlStr) - return true; - - if (this.anyWebPage && /^(https?|ftp)$/.test(url.scheme)) - return true; - if (this.exactURL && this.exactURL == urlStr) - return true; - if (this.domain && url.host && - url.host.slice(-this.domain.length) == this.domain) - return true; - if (this.urlPrefix && 0 == urlStr.indexOf(this.urlPrefix)) - return true; - - return false; - } - -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/memory.js b/tools/addon-sdk-1.4/packages/api-utils/lib/memory.js deleted file mode 100644 index 2ff0486..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/memory.js +++ /dev/null @@ -1,146 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,Cu,components} = require("chrome"); -var trackedObjects = {}; - -var Compacter = { - INTERVAL: 5000, - notify: function(timer) { - var newTrackedObjects = {}; - for (let name in trackedObjects) { - var oldBin = trackedObjects[name]; - var newBin = []; - var strongRefs = []; - for (var i = 0; i < oldBin.length; i++) { - var strongRef = oldBin[i].weakref.get(); - if (strongRef && strongRefs.indexOf(strongRef) == -1) { - strongRefs.push(strongRef); - newBin.push(oldBin[i]); - } - } - if (newBin.length) - newTrackedObjects[name] = newBin; - } - trackedObjects = newTrackedObjects; - } -}; - -var timer = Cc["@mozilla.org/timer;1"] - .createInstance(Ci.nsITimer); - -timer.initWithCallback(Compacter, - Compacter.INTERVAL, - Ci.nsITimer.TYPE_REPEATING_SLACK); - -var track = exports.track = function track(object, bin, stackFrameNumber) { - var frame = components.stack.caller; - var weakref = Cu.getWeakReference(object); - if (!bin) - bin = object.constructor.name; - if (bin == "Object") - bin = frame.name; - if (!bin) - bin = "generic"; - if (!(bin in trackedObjects)) - trackedObjects[bin] = []; - - if (stackFrameNumber > 0) - for (var i = 0; i < stackFrameNumber; i++) - frame = frame.caller; - - trackedObjects[bin].push({weakref: weakref, - created: new Date(), - filename: frame.filename, - lineNo: frame.lineNumber, - bin: bin}); -}; - -var getBins = exports.getBins = function getBins() { - var names = []; - for (let name in trackedObjects) - names.push(name); - return names; -}; - -var getObjects = exports.getObjects = function getObjects(bin) { - function getLiveObjectsInBin(bin, array) { - for (var i = 0; i < bin.length; i++) { - var object = bin[i].weakref.get(); - if (object) - array.push(bin[i]); - } - } - - var results = []; - if (bin) { - if (bin in trackedObjects) - getLiveObjectsInBin(trackedObjects[bin], results); - } else - for (let name in trackedObjects) - getLiveObjectsInBin(trackedObjects[name], results); - return results; -}; - -var gc = exports.gc = function gc() { - // Components.utils.forceGC() doesn't currently perform - // cycle collection, which means that e.g. DOM elements - // won't be collected by it. Fortunately, there are - // other ways... - - var window = Cc["@mozilla.org/appshell/appShellService;1"] - .getService(Ci.nsIAppShellService) - .hiddenDOMWindow; - var test_utils = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - test_utils.garbageCollect(); - Compacter.notify(); - - // Not sure why, but sometimes it appears that we don't get - // them all with just one CC, so let's do it again. - test_utils.garbageCollect(); -}; - -require("./unload").when( - function() { - trackedObjects = {}; - if (timer) { - timer.cancel(); - timer = null; - } - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/namespace.js b/tools/addon-sdk-1.4/packages/api-utils/lib/namespace.js deleted file mode 100644 index ae50f36..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/namespace.js +++ /dev/null @@ -1,55 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -/** - * Function creates a new namespace. Optionally `prototype` object may be - * passed, in which case namespace objects will inherit from it. Returned value - * is a function that can be used to get access to the namespaced properties - * for the passed object. - * @examples - * const ns = Namespace(); - * ns(myObject).secret = secret; - */ -exports.Namespace = function Namespace(prototype) { - prototype = prototype || Object.prototype; - const map = new WeakMap(); - return function namespace(target) { - return map.get(target) || - map.set(target, Object.create(prototype)), map.get(target); - }; -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/observer-service.js b/tools/addon-sdk-1.4/packages/api-utils/lib/observer-service.js deleted file mode 100644 index f408dd5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/observer-service.js +++ /dev/null @@ -1,212 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Observers. - * - * The Initial Developer of the Original Code is Daniel Aquino. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Daniel Aquino <mr.danielaquino@gmail.com> - * Myk Melez <myk@mozilla.org> - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -var xpcom = require("./xpcom"); - -/** - * A service for adding, removing and notifying observers of notifications. - * Wraps the nsIObserverService interface. - * - * @version 0.2 - */ - -var service = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - -/** - * A cache of observers that have been added. - * - * We use this to remove observers when a caller calls |Observers.remove|. - */ -var cache = []; - -/** - * Topics specifically available to Jetpack-generated extensions. - * - * Using these predefined consts instead of the platform strings is good: - * - allows us to scope topics specifically for Jetpacks - * - addons aren't dependent on strings nor behavior of core platform topics - * - the core platform topics are not clearly named - * - */ -exports.topics = { - /** - * A topic indicating that the application is in a state usable - * by add-ons. - */ - get APPLICATION_READY() packaging.jetpackID + "_APPLICATION_READY" -}; - -/** - * Register the given callback as an observer of the given topic. - * - * @param topic {String} - * the topic to observe - * - * @param callback {Object} - * the callback; an Object that implements nsIObserver or a Function - * that gets called when the notification occurs - * - * @param thisObject {Object} [optional] - * the object to use as |this| when calling a Function callback - * - * @returns the observer - */ -var add = exports.add = function add(topic, callback, thisObject) { - var observer = new Observer(topic, callback, thisObject); - service.addObserver(observer, topic, true); - cache.push(observer); - - return observer; -}; - -/** - * Unregister the given callback as an observer of the given topic. - * - * @param topic {String} - * the topic being observed - * - * @param callback {Object} - * the callback doing the observing - * - * @param thisObject {Object} [optional] - * the object being used as |this| when calling a Function callback - */ -var remove = exports.remove = function remove(topic, callback, thisObject) { - // This seems fairly inefficient, but I'm not sure how much better - // we can make it. We could index by topic, but we can't index by callback - // or thisObject, as far as I know, since the keys to JavaScript hashes - // (a.k.a. objects) can apparently only be primitive values. - let observers = cache.filter(function(v) { - return (v.topic == topic && - v.callback == callback && - v.thisObject == thisObject); - }); - - if (observers.length) { - service.removeObserver(observers[0], topic); - cache.splice(cache.indexOf(observers[0]), 1); - } -}; - -/** - * Notify observers about something. - * - * @param topic {String} - * the topic to notify observers about - * - * @param subject {Object} [optional] - * some information about the topic; can be any JS object or primitive - * - * @param data {String} [optional] [deprecated] - * some more information about the topic; deprecated as the subject - * is sufficient to pass all needed information to the JS observers - * that this module targets; if you have multiple values to pass to - * the observer, wrap them in an object and pass them via the subject - * parameter (i.e.: { foo: 1, bar: "some string", baz: myObject }) - */ -var notify = exports.notify = function notify(topic, subject, data) { - subject = (typeof subject == "undefined") ? null : new Subject(subject); - data = (typeof data == "undefined") ? null : data; - service.notifyObservers(subject, topic, data); -}; - -function Observer(topic, callback, thisObject) { - memory.track(this); - this.topic = topic; - this.callback = callback; - this.thisObject = thisObject; -} - -Observer.prototype = { - QueryInterface: xpcom.utils.generateQI([Ci.nsIObserver, - Ci.nsISupportsWeakReference]), - observe: function(subject, topic, data) { - // Extract the wrapped object for subjects that are one of our - // wrappers around a JS object. This way we support both wrapped - // subjects created using this module and those that are real - // XPCOM components. - if (subject && typeof subject == "object" && - ("wrappedJSObject" in subject) && - ("observersModuleSubjectWrapper" in subject.wrappedJSObject)) - subject = subject.wrappedJSObject.object; - - try { - if (typeof this.callback == "function") { - if (this.thisObject) - this.callback.call(this.thisObject, subject, data); - else - this.callback(subject, data); - } else // typeof this.callback == "object" (nsIObserver) - this.callback.observe(subject, topic, data); - } catch (e) { - console.exception(e); - } - } -}; - -function Subject(object) { - // Double-wrap the object and set a property identifying the - // wrappedJSObject as one of our wrappers to distinguish between - // subjects that are one of our wrappers (which we should unwrap - // when notifying our observers) and those that are real JS XPCOM - // components (which we should pass through unaltered). - this.wrappedJSObject = { - observersModuleSubjectWrapper: true, - object: object - }; -} - -Subject.prototype = { - QueryInterface: xpcom.utils.generateQI([]), - getHelperForLanguage: function() {}, - getInterfaces: function() {} -}; - -require("./unload").when( - function removeAllObservers() { - // Make a copy of cache first, since cache will be changing as we - // iterate through it. - cache.slice().forEach( - function(observer) { - remove(observer.topic, observer.callback, observer.thisObject); - }); - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/passwords/utils.js b/tools/addon-sdk-1.4/packages/api-utils/lib/passwords/utils.js deleted file mode 100644 index 950aac2..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/passwords/utils.js +++ /dev/null @@ -1,134 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack Packages. - * - * The Initial Developer of the Original Code is Red Hat. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Matěj Cepl <mcepl@redhat.com> (Original Author) - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci, components: { Constructor: CConstructor } } = require("chrome"); -const { uri: ADDON_URI } = require("self"); -const loginManager = Cc["@mozilla.org/login-manager;1"]. - getService(Ci.nsILoginManager); -const { URL: parseURL } = require("../url"); -const LoginInfo = CConstructor("@mozilla.org/login-manager/loginInfo;1", - "nsILoginInfo", "init"); - -function filterMatchingLogins(loginInfo) - Object.keys(this).every(function(key) loginInfo[key] === this[key], this); - -/** - * Removes `user`, `password` and `path` fields from the given `url` if it's - * 'http', 'https' or 'ftp'. All other URLs are returned unchanged. - * @example - * http://user:pass@www.site.com/foo/?bar=baz#bang -> http://www.site.com - */ -function normalizeURL(url) { - let { scheme, host, port } = parseURL(url); - // We normalize URL only if it's `http`, `https` or `ftp`. All other types of - // URLs (`resource`, `chrome`, etc..) should not be normalized as they are - // used with add-on associated credentials path. - return scheme === "http" || scheme === "https" || scheme === "ftp" ? - scheme + "://" + (host || "") + (port ? ":" + port : "") : - url -} - -function Login(options) { - let login = Object.create(Login.prototype); - Object.keys(options || {}).forEach(function(key) { - if (key === 'url') - login.hostname = normalizeURL(options.url); - else if (key === 'formSubmitURL') - login.formSubmitURL = options.formSubmitURL ? - normalizeURL(options.formSubmitURL) : null; - else if (key === 'realm') - login.httpRealm = options.realm; - else - login[key] = options[key]; - }); - - return login; -} -Login.prototype.toJSON = function toJSON() { - return { - url: this.hostname || ADDON_URI, - realm: this.httpRealm || null, - formSubmitURL: this.formSubmitURL || null, - username: this.username || null, - password: this.password || null, - usernameField: this.usernameField || '', - passwordField: this.passwordField || '', - } -}; -Login.prototype.toLoginInfo = function toLoginInfo() { - let { url, realm, formSubmitURL, username, password, usernameField, - passwordField } = this.toJSON(); - - return new LoginInfo(url, formSubmitURL, realm, username, password, - usernameField, passwordField); -}; - -function loginToJSON(value) Login(value).toJSON() - -/** - * Returns array of `nsILoginInfo` objects that are stored in the login manager - * and have all the properties with matching values as a given `options` object. - * @param {Object} options - * @returns {nsILoginInfo[]} - */ -exports.search = function search(options) { - return loginManager.getAllLogins() - .filter(filterMatchingLogins, Login(options)) - .map(loginToJSON); -}; - -/** - * Stores login info created from the given `options` to the applications - * built-in login management system. - * @param {Object} options. - */ -exports.store = function store(options) { - loginManager.addLogin(Login(options).toLoginInfo()); -}; - -/** - * Removes login info from the applications built-in login management system. - * _Please note: When removing a login info the specified properties must - * exactly match to the one that is already stored or exception will be thrown._ - * @param {Object} options. - */ -exports.remove = function remove(options) { - loginManager.removeLogin(Login(options).toLoginInfo()); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/plain-text-console.js b/tools/addon-sdk-1.4/packages/api-utils/lib/plain-text-console.js deleted file mode 100644 index f7ea74e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/plain-text-console.js +++ /dev/null @@ -1,114 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); - -function stringify(arg) { - try { - return String(arg); - } - catch(ex) { - return "<toString() error>"; - } -} - -function stringifyArgs(args) { - return Array.map(args, stringify).join(" "); -} - -function message(print, level, args) { - print(level + ": " + stringifyArgs(args) + "\n", level); -} - -var Console = exports.PlainTextConsole = function PlainTextConsole(print) { - if (!print) - print = dump; - if (print === dump) { - // If we're just using dump(), auto-enable preferences so - // that the developer actually sees the console output. - var prefs = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefBranch); - prefs.setBoolPref("browser.dom.window.dump.enabled", true); - } - this.print = print; - - // Binding all the public methods to an instance so that they can be used - // as callback / listener functions straightaway. - this.log = this.log.bind(this); - this.info = this.info.bind(this); - this.warn = this.warn.bind(this); - this.error = this.error.bind(this); - this.debug = this.debug.bind(this); - this.exception = this.exception.bind(this); - this.trace = this.trace.bind(this); -}; - -Console.prototype = { - log: function log() { - message(this.print, "info", arguments); - }, - - info: function info() { - message(this.print, "info", arguments); - }, - - warn: function warn() { - message(this.print, "warning", arguments); - }, - - error: function error() { - message(this.print, "error", arguments); - }, - - debug: function debug() { - message(this.print, "debug", arguments); - }, - - exception: function exception(e) { - var fullString = ("An exception occurred.\n" + - require("./traceback").format(e) + "\n" + e); - this.error(fullString); - }, - - trace: function trace() { - var traceback = require("./traceback"); - var stack = traceback.get(); - stack.splice(-1, 1); - message(this.print, "info", [traceback.format(stack)]); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/preferences-service.js b/tools/addon-sdk-1.4/packages/api-utils/lib/preferences-service.js deleted file mode 100644 index 127a1cf..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/preferences-service.js +++ /dev/null @@ -1,138 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Preferences. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Myk Melez <myk@mozilla.org> - * Daniel Aquino <mr.danielaquino@gmail.com> - * Atul Varma <atul@mozilla.com> - * Erik Vold <erikvvold@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -// The minimum and maximum integers that can be set as preferences. -// The range of valid values is narrower than the range of valid JS values -// because the native preferences code treats integers as NSPR PRInt32s, -// which are 32-bit signed integers on all platforms. -const MAX_INT = 0x7FFFFFFF; -const MIN_INT = -0x80000000; - -const {Cc,Ci,Cr} = require("chrome"); - -var prefSvc = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefService).getBranch(null); - -var get = exports.get = function get(name, defaultValue) { - switch (prefSvc.getPrefType(name)) { - case Ci.nsIPrefBranch.PREF_STRING: - return prefSvc.getComplexValue(name, Ci.nsISupportsString).data; - - case Ci.nsIPrefBranch.PREF_INT: - return prefSvc.getIntPref(name); - - case Ci.nsIPrefBranch.PREF_BOOL: - return prefSvc.getBoolPref(name); - - case Ci.nsIPrefBranch.PREF_INVALID: - return defaultValue; - - default: - // This should never happen. - throw new Error("Error getting pref " + name + - "; its value's type is " + - prefSvc.getPrefType(name) + - ", which I don't know " + - "how to handle."); - } -}; - -var set = exports.set = function set(name, value) { - var prefType; - if (typeof value != "undefined" && value != null) - prefType = value.constructor.name; - - switch (prefType) { - case "String": - { - var string = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - string.data = value; - prefSvc.setComplexValue(name, Ci.nsISupportsString, string); - } - break; - - case "Number": - // We throw if the number is outside the range or not an integer, since - // the result will not be what the consumer wanted to store. - if (value > MAX_INT || value < MIN_INT) - throw new Error("you cannot set the " + name + - " pref to the number " + value + - ", as number pref values must be in the signed " + - "32-bit integer range -(2^31) to 2^31-1. " + - "To store numbers outside that range, store " + - "them as strings."); - if (value % 1 != 0) - throw new Error("cannot store non-integer number: " + value); - prefSvc.setIntPref(name, value); - break; - - case "Boolean": - prefSvc.setBoolPref(name, value); - break; - - default: - throw new Error("can't set pref " + name + " to value '" + value + - "'; it isn't a string, integer, or boolean"); - } -}; - -var has = exports.has = function has(name) { - return (prefSvc.getPrefType(name) != Ci.nsIPrefBranch.PREF_INVALID); -}; - -var isSet = exports.isSet = function isSet(name) { - return (has(name) && prefSvc.prefHasUserValue(name)); -}; - -var reset = exports.reset = function reset(name) { - try { - prefSvc.clearUserPref(name); - } catch (e if e.result == Cr.NS_ERROR_UNEXPECTED) { - // The pref service throws NS_ERROR_UNEXPECTED when the caller tries - // to reset a pref that doesn't exist or is already set to its default - // value. This interface fails silently in those cases, so callers - // can unconditionally reset a pref without having to check if it needs - // resetting first or trap exceptions after the fact. It passes through - // other exceptions, however, so callers know about them, since we don't - // know what other exceptions might be thrown and what they might mean. - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/process.js b/tools/addon-sdk-1.4/packages/api-utils/lib/process.js deleted file mode 100644 index 3f429eb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/process.js +++ /dev/null @@ -1,95 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci } = require("chrome"); -const { createRemoteBrowser } = require("api-utils/window-utils"); -const { channel } = require("./channel"); -const { setTimout } = require('./timer'); -const packaging = require('@packaging'); -const { when } = require('./unload'); - -const addonService = '@mozilla.org/addon/service;1' in Cc ? - Cc['@mozilla.org/addon/service;1'].getService(Ci.nsIAddonService) : null - -const ENABLE_E10S = packaging.enable_e10s; - -function loadScript(target, uri, sync) { - return 'loadScript' in target ? target.loadScript(uri, sync) - : target.loadFrameScript(uri, sync) -} - -function process(target, id, path, scope) { - // Please note that even though `loadScript`, is executed before channel is - // returned, users still are able to subscribe for messages before any message - // will be sent. That's because `loadScript` queues script execution on the - // other process, which means they will execute async (on the next turn of - // event loop), while the channel for messages is returned immediately (in - // the same turn of event loop). - - loadScript(target, packaging.uriPrefix + packaging.loader, false); - loadScript(target, 'data:,let loader = Loader.new(' + - JSON.stringify(packaging) + ');\n' + - 'loader.main("' + id + '", "' + path + '");', false); - - when(function (reason) { - // Please note that it's important to unload remote loader - // synchronously (using synchronous frame script), to make sure that we - // don't stop during unload. - loadScript(target, 'data:,loader.unload("' + reason + '")', true); - }); - - return { channel: channel.bind(null, scope, target) } -} - -exports.spawn = function spawn(id, path) { - return function promise(deliver) { - // If `nsIAddonService` is available we use it to create an add-on process, - // otherwise we fallback to the remote browser's message manager. - if (ENABLE_E10S && addonService) { - console.log('!!!!!!!!!!!!!!!!!!!! Using addon process !!!!!!!!!!!!!!!!!!'); - deliver(process(addonService.createAddon(), id, path)); - } else { - createRemoteBrowser(ENABLE_E10S)(function(browser) { - let messageManager = browser.QueryInterface(Ci.nsIFrameLoaderOwner). - frameLoader.messageManager - let window = browser.ownerDocument.defaultView; - deliver(process(messageManager, id, path, window)); - }); - } - }; -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/runtime.js b/tools/addon-sdk-1.4/packages/api-utils/lib/runtime.js deleted file mode 100644 index 135617e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/runtime.js +++ /dev/null @@ -1,48 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci } = require("chrome"); -const runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime); - -exports.inSafeMode = runtime.inSafeMode; -exports.OS = runtime.OS; -exports.processType = runtime.processType; -exports.widgetToolkit = runtime.widgetToolkit; -exports.XPCOMABI = runtime.XPCOMABI; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/self!.js b/tools/addon-sdk-1.4/packages/api-utils/lib/self!.js deleted file mode 100644 index bd9b6da..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/self!.js +++ /dev/null @@ -1,82 +0,0 @@ -/* vim:st=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brian Warner <warner@mozilla.com> - * Erik Vold <erikvvold@gmail.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { CC } = require('chrome'); -const { jetpackID, name, manifest, metadata, uriPrefix } = require('@packaging'); - -const XMLHttpRequest = CC('@mozilla.org/xmlextras/xmlhttprequest;1', - 'nsIXMLHttpRequest'); - -// Utility function that synchronously reads local resource from the given -// `uri` and returns content string. -function readURI(uri) { - let request = XMLHttpRequest(); - request.open('GET', uri, false); - request.overrideMimeType('text/plain'); - request.send(); - return request.responseText; -} - -// Some XPCOM APIs require valid URIs as an argument for certain operations (see -// `nsILoginManager` for example). This property represents add-on associated -// unique URI string that can be used for that. -const uri = 'addon:' + jetpackID - -function url(root, path) root + (path || "") -function read(root, path) readURI(url(root, path)) - -exports.create = function create(base) { - let moduleData = manifest[base] && manifest[base].requirements['self']; - let root = uriPrefix + moduleData.dataURIPrefix; - return Object.freeze({ - id: 'self', - exports: Object.freeze({ - id: jetpackID, - uri: uri, - name: name, - version: metadata[name].version, - data: { - url: url.bind(null, root), - load: read.bind(null, root) - } - }) - }); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/system.js b/tools/addon-sdk-1.4/packages/api-utils/lib/system.js deleted file mode 100644 index 70896e7..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/system.js +++ /dev/null @@ -1,131 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 expandtab */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -'use strict'; - -const { Cc, Ci, CC } = require('chrome'); -const options = require('@packaging'); -const file = require('./file'); - -const appStartup = Cc['@mozilla.org/toolkit/app-startup;1']. - getService(Ci.nsIAppStartup); -const appInfo = Cc["@mozilla.org/xre/app-info;1"]. - getService(Ci.nsIXULAppInfo); -const runtime = Cc["@mozilla.org/xre/app-info;1"]. - getService(Ci.nsIXULRuntime); - -const { eAttemptQuit: E_ATTEMPT, eForceQuit: E_FORCE } = appStartup; - -/** - * Parsed JSON object that was passed via `cfx --static-args "{ foo: 'bar' }"` - */ -exports.staticArgs = options.staticArgs; - -/** - * Environment variables. Environment variables are non-enumerable properties - * of this object (key is name and value is value). - */ -exports.env = require('./environment').env; - -/** - * Ends the process with the specified `code`. If omitted, exit uses the - * 'success' code 0. To exit with failure use `1`. - * TODO: Improve platform to actually quit with an exit code. - */ -exports.exit = function exit(code) { - // This is used by 'cfx' to find out exit code. - if ('resultFile' in options) { - let stream = file.open(options.resultFile, 'w'); - stream.write(code ? 'FAIL' : 'OK'); - stream.close(); - } - - appStartup.quit(code ? E_ATTEMPT : E_FORCE); -}; - -/** - * What platform you're running on (all lower case string). - * For possible values see: - * https://developer.mozilla.org/en/OS_TARGET - */ -exports.platform = runtime.OS.toLowerCase(); - -/** - * What processor architecture you're running on: - * `'arm', 'ia32', or 'x64'`. - */ -exports.architecture = runtime.XPCOMABI.split('_')[0]; - -/** - * What compiler used for build: - * `'msvc', 'n32', 'gcc2', 'gcc3', 'sunc', 'ibmc'...` - */ -exports.compiler = runtime.XPCOMABI.split('_')[1]; - -/** - * The application's build ID/date, for example "2004051604". - */ -exports.build = appInfo.appBuildID; - -/** - * The XUL application's UUID. - * This has traditionally been in the form - * `{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}` but for some applications it may - * be: "appname@vendor.tld". - */ -exports.id = appInfo.ID; - -/** - * The name of the application. - */ -exports.name = appInfo.name; - -/** - * The XUL application's version, for example "0.8.0+" or "3.7a1pre". - */ -exports.version = appInfo.version; - -/** - * XULRunner version. - */ -exports.platformVersion = runtime.platformVersion; - - -/** - * The name of the application vendor, for example "Mozilla". - */ -exports.vendor = appInfo.vendor; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/tab-browser.js b/tools/addon-sdk-1.4/packages/api-utils/lib/tab-browser.js deleted file mode 100644 index 272a7c6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/tab-browser.js +++ /dev/null @@ -1,761 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Dietrich Ayala <dietrich@mozilla.com> - * Felipe Gomes <felipc@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -const {Cc,Ci,Cu} = require("chrome"); -var NetUtil = {}; -Cu.import("resource://gre/modules/NetUtil.jsm", NetUtil); -NetUtil = NetUtil.NetUtil; -const errors = require("./errors"); -const windowUtils = require("./window-utils"); -const apiUtils = require("./api-utils"); -const collection = require("./collection"); - -// TODO: The hard-coding of app-specific info here isn't very nice; -// ideally such app-specific info should be more decoupled, and the -// module should be extensible, allowing for support of new apps at -// runtime, perhaps by inspecting supported packages (e.g. via -// dynamically-named modules or package-defined extension points). - -if (!require("./xul-app").is("Firefox")) { - throw new Error([ - "The tab-browser module currently supports only Firefox. In the future ", - "it will support other applications. Please see ", - "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information." - ].join("")); -} - -function onBrowserLoad(callback, event) { - if (event.target && event.target.defaultView == this) { - this.removeEventListener("load", onBrowserLoad, true); - try { - require("timer").setTimeout(function () { - callback(event); - }, 10); - } catch (e) { console.exception(e); } - } -} - -// Utility function to open a new browser window. -function openBrowserWindow(callback, url) { - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - let urlString = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - urlString.data = url; - let window = ww.openWindow(null, "chrome://browser/content/browser.xul", - "_blank", "chrome,all,dialog=no", urlString); - if (callback) - window.addEventListener("load", onBrowserLoad.bind(window, callback), true); - - return window; -} - -// Open a URL in a new tab -exports.addTab = function addTab(url, options) { - if (!options) - options = {}; - options.url = url; - - options = apiUtils.validateOptions(options, { - // TODO: take URL object instead of string (bug 564524) - url: { - is: ["string"], - ok: function (v) !!v, - msg: "The url parameter must have be a non-empty string." - }, - inNewWindow: { - is: ["undefined", "null", "boolean"] - }, - inBackground: { - is: ["undefined", "null", "boolean"] - }, - onLoad: { - is: ["undefined", "null", "function"] - }, - isPinned: { - is: ["undefined", "boolean"] - } - }); - - var wm = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator); - var win = wm.getMostRecentWindow("navigator:browser"); - if (!win || options.inNewWindow) { - openBrowserWindow(function(e) { - if(options.isPinned) { - //get the active tab in the recently created window - let mainWindow = e.target.defaultView; - mainWindow.gBrowser.pinTab(mainWindow.gBrowser.selectedTab); - } - require("./errors").catchAndLog(function(e) options.onLoad(e))(e); - }, options.url); - } else { - let tab = win.gBrowser.addTab(options.url); - if (!options.inBackground) - win.gBrowser.selectedTab = tab; - if (options.onLoad) { - let tabBrowser = win.gBrowser.getBrowserForTab(tab); - tabBrowser.addEventListener("load", function onLoad(e) { - if (e.target.defaultView.content.location == "about:blank") - return; - // remove event handler from addTab - don't want notified - // for subsequent loads in same tab. - tabBrowser.removeEventListener("load", onLoad, true); - require("./errors").catchAndLog(function(e) options.onLoad(e))(e); - }, true); - } - } -} - -// Iterate over a window's tabbrowsers -function tabBrowserIterator(window) { - var browsers = window.document.querySelectorAll("tabbrowser"); - for (var i = 0; i < browsers.length; i++) - yield browsers[i]; -} - -// Iterate over a tabbrowser's tabs -function tabIterator(tabbrowser) { - var tabs = tabbrowser.tabContainer; - for (var i = 0; i < tabs.children.length; i++) { - yield tabs.children[i]; - } -} - -// Tracker for all tabbrowsers across all windows, -// or a single tabbrowser if the window is given. -function Tracker(delegate, window) { - this._delegate = delegate; - this._browsers = []; - this._window = window; - this._windowTracker = new windowUtils.WindowTracker(this); - - require("./unload").ensure(this); -} -Tracker.prototype = { - __iterator__: function __iterator__() { - for (var i = 0; i < this._browsers.length; i++) - yield this._browsers[i]; - }, - get: function get(index) { - return this._browsers[index]; - }, - onTrack: function onTrack(window) { - if (this._window && window != this._window) - return; - - for (let browser in tabBrowserIterator(window)) - this._browsers.push(browser); - if (this._delegate) - for (let browser in tabBrowserIterator(window)) - this._delegate.onTrack(browser); - }, - onUntrack: function onUntrack(window) { - if (this._window && window != this._window) - return; - - for (let browser in tabBrowserIterator(window)) { - let index = this._browsers.indexOf(browser); - if (index != -1) - this._browsers.splice(index, 1); - else - console.error("internal error: browser tab not found"); - } - if (this._delegate) - for (let browser in tabBrowserIterator(window)) - this._delegate.onUntrack(browser); - }, - get length() { - return this._browsers.length; - }, - unload: function unload() { - this._windowTracker.unload(); - } -}; -exports.Tracker = apiUtils.publicConstructor(Tracker); - -// Tracker for all tabs across all windows, -// or a single window if it's given. -function TabTracker(delegate, window) { - this._delegate = delegate; - this._tabs = []; - this._tracker = new Tracker(this, window); - require("./unload").ensure(this); -} -TabTracker.prototype = { - _TAB_EVENTS: ["TabOpen", "TabClose"], - _safeTrackTab: function safeTrackTab(tab) { - this._tabs.push(tab); - try { - this._delegate.onTrack(tab); - } catch (e) { - console.exception(e); - } - }, - _safeUntrackTab: function safeUntrackTab(tab) { - var index = this._tabs.indexOf(tab); - if (index == -1) - console.error("internal error: tab not found"); - this._tabs.splice(index, 1); - try { - this._delegate.onUntrack(tab); - } catch (e) { - console.exception(e); - } - }, - handleEvent: function handleEvent(event) { - switch (event.type) { - case "TabOpen": - this._safeTrackTab(event.target); - break; - case "TabClose": - this._safeUntrackTab(event.target); - break; - default: - throw new Error("internal error: unknown event type: " + - event.type); - } - }, - onTrack: function onTrack(tabbrowser) { - for (let tab in tabIterator(tabbrowser)) - this._safeTrackTab(tab); - var self = this; - this._TAB_EVENTS.forEach( - function(eventName) { - tabbrowser.tabContainer.addEventListener(eventName, self, true); - }); - }, - onUntrack: function onUntrack(tabbrowser) { - for (let tab in tabIterator(tabbrowser)) - this._safeUntrackTab(tab); - var self = this; - this._TAB_EVENTS.forEach( - function(eventName) { - tabbrowser.tabContainer.removeEventListener(eventName, self, true); - }); - }, - unload: function unload() { - this._tracker.unload(); - } -}; -exports.TabTracker = apiUtils.publicConstructor(TabTracker); - -exports.whenContentLoaded = function whenContentLoaded(callback) { - var cb = require("./errors").catchAndLog(function eventHandler(event) { - if (event.target && event.target.defaultView) - callback(event.target.defaultView); - }); - - var tracker = new Tracker({ - onTrack: function(tabBrowser) { - tabBrowser.addEventListener("DOMContentLoaded", cb, false); - }, - onUntrack: function(tabBrowser) { - tabBrowser.removeEventListener("DOMContentLoaded", cb, false); - } - }); - - return tracker; -}; - -exports.__defineGetter__("activeTab", function() { - const wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - let mainWindow = wm.getMostRecentWindow("navigator:browser"); - return mainWindow.gBrowser.selectedTab; -}); - -/******************* TabModule *********************/ - -// Supported tab events -const events = [ - "onActivate", - "onDeactivate", - "onOpen", - "onClose", - "onReady", - "onLoad", - "onPaint" -]; -exports.tabEvents = events; - -/** - * TabModule - * - * Constructor for a module that implements the tabs API - */ -let TabModule = exports.TabModule = function TabModule(window) { - let self = this; - /** - * Tab - * - * Safe object representing a tab. - */ - let tabConstructor = apiUtils.publicConstructor(function(element) { - if (!element) - throw new Error("no tab element."); - let win = element.ownerDocument.defaultView; - if (!win) - throw new Error("element has no window."); - if (window && win != window) - throw new Error("module's window and element's window don't match."); - let browser = win.gBrowser.getBrowserForTab(element); - - this.__defineGetter__("title", function() browser.contentDocument.title); - this.__defineGetter__("location", function() browser.contentDocument.location); - this.__defineSetter__("location", function(val) browser.contentDocument.location = val); - this.__defineGetter__("contentWindow", function() browser.contentWindow); - this.__defineGetter__("contentDocument", function() browser.contentDocument); - this.__defineGetter__("favicon", function() { - let pageURI = NetUtil.newURI(browser.contentDocument.location); - let fs = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); - let faviconURL; - try { - let faviconURI = fs.getFaviconForPage(pageURI); - faviconURL = fs.getFaviconDataAsDataURL(faviconURI); - } catch(ex) { - let data = getChromeURLContents("chrome://mozapps/skin/places/defaultFavicon.png"); - let encoded = browser.contentWindow.btoa(data); - faviconURL = "data:image/png;base64," + encoded; - } - return faviconURL; - }); - this.__defineGetter__("style", function() null); // TODO - this.__defineGetter__("index", function() win.gBrowser.getBrowserIndexForDocument(browser.contentDocument)); - this.__defineGetter__("thumbnail", function() getThumbnailCanvasForTab(element, browser.contentWindow)); - - this.close = function() win.gBrowser.removeTab(element); - this.move = function(index) { - win.gBrowser.moveTabTo(element, index); - }; - - this.__defineGetter__("isPinned", function() element.pinned); - this.pin = function() win.gBrowser.pinTab(element); - this.unpin = function() win.gBrowser.unpinTab(element); - - // Set up the event handlers - let tab = this; - events.filter(function(e) e != "onOpen").forEach(function(e) { - // create a collection for each event - collection.addCollectionProperty(tab, e); - // make tabs setter for each event, for adding via property assignment - tab.__defineSetter__(e, function(val) tab[e].add(val)); - }); - - // listen for events, filtered on this tab - eventsTabDelegate.addTabDelegate(this); - }); - - /** - * tabs.activeTab - */ - this.__defineGetter__("activeTab", function() { - try { - return window ? tabConstructor(window.gBrowser.selectedTab) - : tabConstructor(exports.activeTab); - } - catch (e) { } - return null; - }); - this.__defineSetter__("activeTab", function(tab) { - let [tabElement, win] = getElementAndWindowForTab(tab, window); - if (tabElement) { - // set as active tab - win.gBrowser.selectedTab = tabElement; - // focus the window - win.focus(); - } - }); - - this.open = function TM_open(options) { - open(options, tabConstructor, window); - } - - // Set up the event handlers - events.forEach(function(eventHandler) { - // create a collection for each event - collection.addCollectionProperty(self, eventHandler); - // make tabs setter for each event, for adding via property assignment - self.__defineSetter__(eventHandler, function(val) self[eventHandler].add(val)); - }); - - // Tracker that listens for tab events, and proxies - // them to registered event listeners. - let eventsTabDelegate = { - selectedTab: null, - tabs: [], - addTabDelegate: function TETT_addTabDelegate(tabObj) { - this.tabs.push(tabObj); - }, - pushTabEvent: function TETT_pushTabEvent(event, tab) { - for (let callback in self[event]) { - require("./errors").catchAndLog(function(tab) { - callback(new tabConstructor(tab)); - })(tab); - } - - if (event != "onOpen") { - this.tabs.forEach(function(tabObj) { - if (tabObj[event].length) { - let [tabEl,] = getElementAndWindowForTab(tabObj, window); - if (tabEl == tab) { - for (let callback in tabObj[event]) - require("./errors").catchAndLog(function() callback())(); - } - } - // if being closed, remove the tab object from the cache - // of tabs to notify about events. - if (event == "onClose") - this.tabs.splice(this.tabs.indexOf(tabObj), 1); - }, this); - } - }, - unload: function() { - this.selectedTab = null; - this.tabs.splice(0); - } - }; - require("./unload").ensure(eventsTabDelegate); - - let eventsTabTracker = new ModuleTabTracker({ - onTrack: function TETT_onTrack(tab) { - eventsTabDelegate.pushTabEvent("onOpen", tab); - }, - onUntrack: function TETT_onUntrack(tab) { - eventsTabDelegate.pushTabEvent("onClose", tab); - }, - onSelect: function TETT_onSelect(tab) { - if (eventsTabDelegate.selectedTab) - eventsTabDelegate.pushTabEvent("onDeactivate", tab); - - eventsTabDelegate.selectedTab = new tabConstructor(tab); - - eventsTabDelegate.pushTabEvent("onActivate", tab); - }, - onReady: function TETT_onReady(tab) { - eventsTabDelegate.pushTabEvent("onReady", tab); - }, - onLoad: function TETT_onLoad(tab) { - eventsTabDelegate.pushTabEvent("onLoad", tab); - }, - onPaint: function TETT_onPaint(tab) { - eventsTabDelegate.pushTabEvent("onPaint", tab); - } - }, window); - require("./unload").ensure(eventsTabTracker); - - // Iterator for all tabs - this.__iterator__ = function tabsIterator() { - for (let i = 0; i < eventsTabTracker._tabs.length; i++) - yield tabConstructor(eventsTabTracker._tabs[i]); - } - - this.__defineGetter__("length", function() eventsTabTracker._tabs.length); - - // Cleanup when unloaded - this.unload = function TM_unload() { - // Unregister tabs event listeners - events.forEach(function(e) self[e] = []); - } - require("./unload").ensure(this); - -} // End of TabModule constructor - -/** - * tabs.open - open a URL in a new tab - */ -function open(options, tabConstructor, window) { - if (typeof options === "string") - options = { url: options }; - - options = apiUtils.validateOptions(options, { - url: { - is: ["string"] - }, - inNewWindow: { - is: ["undefined", "boolean"] - }, - inBackground: { - is: ["undefined", "boolean"] - }, - isPinned: { - is: ["undefined", "boolean"] - }, - onOpen: { - is: ["undefined", "function"] - } - }); - - if (window) - options.inNewWindow = false; - - let win = window || require("./window-utils").activeBrowserWindow; - - if (!win || options.inNewWindow) - openURLInNewWindow(options, tabConstructor); - else - openURLInNewTab(options, win, tabConstructor); -} - -function openURLInNewWindow(options, tabConstructor) { - let addTabOptions = { - inNewWindow: true - }; - if (options.onOpen) { - addTabOptions.onLoad = function(e) { - let win = e.target.defaultView; - let tabEl = win.gBrowser.tabContainer.childNodes[0]; - let tabBrowser = win.gBrowser.getBrowserForTab(tabEl); - tabBrowser.addEventListener("load", function onLoad(e) { - tabBrowser.removeEventListener("load", onLoad, true); - let tab = tabConstructor(tabEl); - require("./errors").catchAndLog(function(e) options.onOpen(e))(tab); - }, true); - }; - } - if (options.isPinned) { - addTabOptions.isPinned = true; - } - exports.addTab(options.url.toString(), addTabOptions); -} - -function openURLInNewTab(options, window, tabConstructor) { - window.focus(); - let tabEl = window.gBrowser.addTab(options.url.toString()); - if (!options.inBackground) - window.gBrowser.selectedTab = tabEl; - if (options.isPinned) - window.gBrowser.pinTab(tabEl); - if (options.onOpen) { - let tabBrowser = window.gBrowser.getBrowserForTab(tabEl); - tabBrowser.addEventListener("load", function onLoad(e) { - // remove event handler from addTab - don't want to be notified - // for subsequent loads in same tab. - tabBrowser.removeEventListener("load", onLoad, true); - let tab = tabConstructor(tabEl); - require("./timer").setTimeout(function() { - require("./errors").catchAndLog(function(tab) options.onOpen(tab))(tab); - }, 10); - }, true); - } -} - -function getElementAndWindowForTab(tabObj, window) { - // iterate over open windows, or use single window if provided - let windowIterator = window ? function() { yield window; } - : require("./window-utils").windowIterator; - for (let win in windowIterator()) { - if (win.gBrowser) { - // find the tab element at tab.index - let index = win.gBrowser.getBrowserIndexForDocument(tabObj.contentDocument); - if (index > -1) - return [win.gBrowser.tabContainer.getItemAtIndex(index), win]; - } - } - return [null, null]; -} - -// Tracker for all tabs across all windows -// This is tab-browser.TabTracker, but with -// support for additional events added. -function ModuleTabTracker(delegate, window) { - this._delegate = delegate; - this._tabs = []; - this._tracker = new Tracker(this, window); - require("./unload").ensure(this); -} -ModuleTabTracker.prototype = { - _TAB_EVENTS: ["TabOpen", "TabClose", "TabSelect", "DOMContentLoaded", - "load", "MozAfterPaint"], - _safeTrackTab: function safeTrackTab(tab) { - tab.addEventListener("load", this, false); - tab.linkedBrowser.addEventListener("MozAfterPaint", this, false); - this._tabs.push(tab); - try { - this._delegate.onTrack(tab); - } catch (e) { - console.exception(e); - } - }, - _safeUntrackTab: function safeUntrackTab(tab) { - tab.removeEventListener("load", this, false); - tab.linkedBrowser.removeEventListener("MozAfterPaint", this, false); - var index = this._tabs.indexOf(tab); - if (index == -1) - throw new Error("internal error: tab not found"); - this._tabs.splice(index, 1); - try { - this._delegate.onUntrack(tab); - } catch (e) { - console.exception(e); - } - }, - _safeSelectTab: function safeSelectTab(tab) { - var index = this._tabs.indexOf(tab); - if (index == -1) - console.error("internal error: tab not found"); - try { - if (this._delegate.onSelect) - this._delegate.onSelect(tab); - } catch (e) { - console.exception(e); - } - }, - _safeDOMContentLoaded: function safeDOMContentLoaded(event) { - let tabBrowser = event.currentTarget; - let tabBrowserIndex = tabBrowser.getBrowserIndexForDocument(event.target); - // TODO: I'm seeing this when loading data url images - if (tabBrowserIndex == -1) - return; - let tab = tabBrowser.tabContainer.getItemAtIndex(tabBrowserIndex); - let index = this._tabs.indexOf(tab); - if (index == -1) - console.error("internal error: tab not found"); - try { - if (this._delegate.onReady) - this._delegate.onReady(tab); - } catch (e) { - console.exception(e); - } - }, - _safeLoad: function safeLoad(event) { - let tab = event.target; - let index = this._tabs.indexOf(tab); - if (index == -1) - console.error("internal error: tab not found"); - try { - if (this._delegate.onLoad) - this._delegate.onLoad(tab); - } catch (e) { - console.exception(e); - } - }, - _safeMozAfterPaint: function safeMozAfterPaint(event) { - let win = event.currentTarget.ownerDocument.defaultView; - let tabIndex = win.gBrowser.getBrowserIndexForDocument(event.target.document); - if (tabIndex == -1) - return; - let tab = win.gBrowser.tabContainer.getItemAtIndex(tabIndex); - let index = this._tabs.indexOf(tab); - if (index == -1) - console.error("internal error: tab not found"); - try { - if (this._delegate.onPaint) - this._delegate.onPaint(tab); - } catch (e) { - console.exception(e); - } - }, - handleEvent: function handleEvent(event) { - switch (event.type) { - case "TabOpen": - this._safeTrackTab(event.target); - break; - case "TabClose": - this._safeUntrackTab(event.target); - break; - case "TabSelect": - this._safeSelectTab(event.target); - break; - case "DOMContentLoaded": - this._safeDOMContentLoaded(event); - break; - case "load": - this._safeLoad(event); - break; - case "MozAfterPaint": - this._safeMozAfterPaint(event); - break; - default: - throw new Error("internal error: unknown event type: " + - event.type); - } - }, - onTrack: function onTrack(tabbrowser) { - for (let tab in tabIterator(tabbrowser)) - this._safeTrackTab(tab); - tabbrowser.tabContainer.addEventListener("TabOpen", this, false); - tabbrowser.tabContainer.addEventListener("TabClose", this, false); - tabbrowser.tabContainer.addEventListener("TabSelect", this, false); - tabbrowser.ownerDocument.defaultView.gBrowser.addEventListener("DOMContentLoaded", this, false); - }, - onUntrack: function onUntrack(tabbrowser) { - for (let tab in tabIterator(tabbrowser)) - this._safeUntrackTab(tab); - tabbrowser.tabContainer.removeEventListener("TabOpen", this, false); - tabbrowser.tabContainer.removeEventListener("TabClose", this, false); - tabbrowser.tabContainer.removeEventListener("TabSelect", this, false); - tabbrowser.ownerDocument.defaultView.gBrowser.removeEventListener("DOMContentLoaded", this, false); - }, - unload: function unload() { - this._tracker.unload(); - } -}; - -// Utility to get a thumbnail canvas from a tab object -function getThumbnailCanvasForTab(tabEl, window) { - var thumbnail = window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); - thumbnail.mozOpaque = true; - window = tabEl.linkedBrowser.contentWindow; - thumbnail.width = Math.ceil(window.screen.availWidth / 5.75); - var aspectRatio = 0.5625; // 16:9 - thumbnail.height = Math.round(thumbnail.width * aspectRatio); - var ctx = thumbnail.getContext("2d"); - var snippetWidth = window.innerWidth * .6; - var scale = thumbnail.width / snippetWidth; - ctx.scale(scale, scale); - ctx.drawWindow(window, window.scrollX, window.scrollY, snippetWidth, snippetWidth * aspectRatio, "rgb(255,255,255)"); - return thumbnail; -} - -// Utility to return the contents of the target of a chrome URL -function getChromeURLContents(chromeURL) { - let io = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - let channel = io.newChannel(chromeURL, null, null); - let input = channel.open(); - let stream = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - stream.setInputStream(input); - let str = stream.readBytes(input.available()); - stream.close(); - input.close(); - return str; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/events.js b/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/events.js deleted file mode 100644 index 96309bb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/events.js +++ /dev/null @@ -1,56 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const ON_PREFIX = "on"; -const TAB_PREFIX = "Tab"; - -const EVENTS = { - ready: "DOMContentLoaded", - open: "TabOpen", - close: "TabClose", - activate: "TabSelect", - deactivate: null -} -exports.EVENTS = EVENTS; - -Object.keys(EVENTS).forEach(function(name) { - EVENTS[name] = { - name: name, - listener: ON_PREFIX + name.charAt(0).toUpperCase() + name.substr(1), - dom: EVENTS[name] - } -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/observer.js b/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/observer.js deleted file mode 100644 index f679917..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/observer.js +++ /dev/null @@ -1,126 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { EventEmitterTrait: EventEmitter } = require("../events"); -const { DOMEventAssembler } = require("../events/assembler"); -const { Trait } = require("../light-traits"); -const { getActiveTab, getTabs, getTabContainers } = require("./utils"); -const { browserWindowIterator, isBrowser } = require("../window-utils"); -const { observer: windowObserver } = require("../windows/observer"); - -const EVENTS = { - "TabOpen": "open", - "TabClose": "close", - "TabSelect": "select", - "TabMove": "move", - "TabPinned": "pin", - "TabUnpinned": "unpin" -}; - - -// Event emitter objects used to register listeners and emit events on them -// when they occur. -const observer = Trait.compose(DOMEventAssembler, EventEmitter).create({ - /** - * Method is implemented by `EventEmitter` and is used just for emitting - * events on registered listeners. - */ - _emit: Trait.required, - /** - * Events that are supported and emitted by the module. - */ - supportedEventsTypes: Object.keys(EVENTS), - /** - * Function handles all the supported events on all the windows that are - * observed. Method is used to proxy events to the listeners registered on - * this event emitter. - * @param {Event} event - * Keyboard event being emitted. - */ - handleEvent: function handleEvent(event) { - this._emit(EVENTS[event.type], event.target, event); - } -}); - -// Currently gecko does not dispatches any event on the previously selected -// tab before / after "TabSelect" is dispatched. In order to work around this -// limitation we keep track of selected tab and emit "deactivate" event with -// that before emitting "activate" on selected tab. -var selectedTab = null; -function onTabSelect(tab) { - if (selectedTab !== tab) { - if (selectedTab) observer._emit("deactivate", selectedTab); - if (tab) observer._emit("activate", selectedTab = tab); - } -}; -observer.on("select", onTabSelect); - -// We also observe opening / closing windows in order to add / remove it's -// containers to the observed list. -function onWindowOpen(chromeWindow) { - if (!isBrowser(chromeWindow)) return; // Ignore if it's not a browser window. - getTabContainers(chromeWindow).forEach(function (container) { - observer.observe(container); - }); -} -windowObserver.on("open", onWindowOpen); - -function onWindowClose(chromeWindow) { - if (!isBrowser(chromeWindow)) return; // Ignore if it's not a browser window. - getTabContainers(chromeWindow).forEach(function (container) { - observer.ignore(container); - }); -} -windowObserver.on("close", onWindowClose); - - -// Currently gecko does not dispatches "TabSelect" events when different -// window gets activated. To work around this limitation we emulate "select" -// event for this case. -windowObserver.on("activate", function onWindowActivate(chromeWindow) { - if (!isBrowser(chromeWindow)) return; // Ignore if it's not a browser window. - observer._emit("select", getActiveTab(chromeWindow)); -}); - -// We should synchronize state, since probably we already have at least one -// window open. -for each (let window in browserWindowIterator()) onWindowOpen(window); - -exports.observer = observer; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/tab.js b/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/tab.js deleted file mode 100644 index 17e2ff6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/tab.js +++ /dev/null @@ -1,297 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Ci } = require('chrome'); -const { Trait } = require("../traits"); -const { EventEmitter } = require("../events"); -const { validateOptions } = require("../api-utils"); -const { Enqueued } = require("../utils/function"); -const { EVENTS } = require("./events"); -const { getThumbnailURIForWindow } = require("../utils/thumbnail"); -const { getFaviconURIForLocation } = require("../utils/data"); - - - -// Array of the inner instances of all the wrapped tabs. -const TABS = []; - -/** - * Trait used to create tab wrappers. - */ -const TabTrait = Trait.compose(EventEmitter, { - on: Trait.required, - _emit: Trait.required, - /** - * Tab DOM element that is being wrapped. - */ - _tab: null, - /** - * Window wrapper whose tab this object represents. - */ - window: null, - constructor: function Tab(options) { - this._onReady = this._onReady.bind(this); - this._tab = options.tab; - let window = this.window = options.window; - // Setting event listener if was passed. - for each (let type in EVENTS) { - let listener = options[type.listener]; - if (listener) - this.on(type.name, options[type.listener]); - if ('ready' != type.name) // window spreads this event. - window.tabs.on(type.name, this._onEvent.bind(this, type.name)); - } - - this.on(EVENTS.close.name, this.destroy.bind(this)); - this._browser.addEventListener(EVENTS.ready.dom, this._onReady, true); - - if (options.isPinned) - this.pin(); - - // Since we will have to identify tabs by a DOM elements facade function - // is used as constructor that collects all the instances and makes sure - // that they more then one wrapper is not created per tab. - return this; - }, - destroy: function destroy() { - for each (let type in EVENTS) - this._removeAllListeners(type.name); - this._browser.removeEventListener(EVENTS.ready.dom, this._onReady, - true); - }, - - /** - * Internal listener that emits public event 'ready' when the page of this - * tab is loaded. - */ - _onReady: function _onReady(event) { - // IFrames events will bubble so we need to ignore those. - if (event.target == this._contentDocument) - this._emit(EVENTS.ready.name, this._public); - }, - /** - * Internal tab event router. Window will emit tab related events for all it's - * tabs, this listener will propagate all the events for this tab to it's - * listeners. - */ - _onEvent: function _onEvent(type, tab) { - if (tab == this._public) - this._emit(type, tab); - }, - /** - * Browser DOM element where page of this tab is currently loaded. - */ - get _browser() this._window.gBrowser.getBrowserForTab(this._tab), - /** - * Window DOM element containing this tab. - */ - get _window() this._tab.ownerDocument.defaultView, - /** - * Document object of the page that is currently loaded in this tab. - */ - get _contentDocument() this._browser.contentDocument, - /** - * Window object of the page that is currently loaded in this tab. - */ - get _contentWindow() this._browser.contentWindow, - - /** - * The title of the page currently loaded in the tab. - * Changing this property changes an actual title. - * @type {String} - */ - get title() this._contentDocument.title, - set title(value) this._contentDocument.title = String(value), - /** - * Location of the page currently loaded in this tab. - * Changing this property will loads page under under the specified location. - * @type {String} - */ - get url() String(this._browser.currentURI.spec), - set url(value) this._changeLocation(String(value)), - // "TabOpen" event is fired when it's still "about:blank" is loaded in the - // changing `location` property of the `contentDocument` has no effect since - // seems to be either ignored or overridden by internal listener, there for - // location change is enqueued for the next turn of event loop. - _changeLocation: Enqueued(function(url) this._browser.loadURI(url)), - /** - * URI of the favicon for the page currently loaded in this tab. - * @type {String} - */ - get favicon() getFaviconURIForLocation(this.url), - /** - * The CSS style for the tab - */ - get style() null, // TODO - /** - * The index of the tab relative to other tabs in the application window. - * Changing this property will change order of the actual position of the tab. - * @type {Number} - */ - get index() - this._window.gBrowser.getBrowserIndexForDocument(this._contentDocument), - set index(value) this._window.gBrowser.moveTabTo(this._tab, value), - /** - * Thumbnail data URI of the page currently loaded in this tab. - * @type {String} - */ - getThumbnail: function getThumbnail() - getThumbnailURIForWindow(this._contentWindow), - /** - * Whether or not tab is pinned (Is an app-tab). - * @type {Boolean} - */ - get isPinned() this._tab.pinned, - pin: function pin() { - this._window.gBrowser.pinTab(this._tab); - }, - unpin: function unpin() { - this._window.gBrowser.unpinTab(this._tab); - }, - - /** - * Create a worker for this tab, first argument is options given to Worker. - * @type {Worker} - */ - attach: function attach(options) { - let { Worker } = require("../content/worker"); - options.window = this._contentWindow; - let worker = Worker(options); - worker.once("detach", function detach() { - worker.destroy(); - }); - return worker; - }, - - /** - * Make this tab active. - * Please note: That this function is called synchronous since in E10S that - * will be the case. Besides this function is called from a constructor where - * we would like to return instance before firing a 'TabActivated' event. - */ - activate: Enqueued(function activate() { - if (this._window) // Ignore if window is closed by the time this is invoked. - this._window.gBrowser.selectedTab = this._tab; - }), - /** - * Close the tab - */ - close: function close(callback) { - if (callback) - this.once(EVENTS.close.name, callback); - this._window.gBrowser.removeTab(this._tab); - }, - /** - * Reload the tab - */ - reload: function reload() { - this._window.gBrowser.reloadTab(this._tab); - } -}); - -function Tab(options) { - let chromeTab = options.tab; - for each (let tab in TABS) { - if (chromeTab == tab._tab) - return tab._public; - } - let tab = TabTrait(options); - TABS.push(tab); - return tab._public; -} -Tab.prototype = TabTrait.prototype; -exports.Tab = Tab; - -function Options(options) { - if ("string" === typeof options) - options = { url: options }; - - return validateOptions(options, { - url: { is: ["string"] }, - inBackground: { is: ["undefined", "boolean"] }, - isPinned: { is: ["undefined", "boolean"] }, - onOpen: { is: ["undefined", "function"] }, - onClose: { is: ["undefined", "function"] }, - onReady: { is: ["undefined", "function"] }, - onActivate: { is: ["undefined", "function"] }, - onDeactivate: { is: ["undefined", "function"] } - }); -} -exports.Options = Options; - - -exports.getTabForWindow = function (win) { - // Get browser window - let topWindow = win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow); - if (!topWindow.gBrowser) return null; - - // Get top window object, in case we are in a content iframe - let topContentWindow; - try { - topContentWindow = win.top; - } catch(e) { - // It may throw if win is not a valid content window - return null; - } - - function getWindowID(obj) { - return obj.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .currentInnerWindowID; - } - - // Search for related Tab - let topWindowId = getWindowID(topContentWindow); - for (let i = 0; i < topWindow.gBrowser.browsers.length; i++) { - let w = topWindow.gBrowser.browsers[i].contentWindow; - if (getWindowID(w) == topWindowId) { - return Tab({ - // TODO: api-utils should not depend on addon-kit! - window: require("addon-kit/windows").BrowserWindow({ window: topWindow }), - tab: topWindow.gBrowser.tabs[i] - }); - } - } - - // We were unable to find the related tab! - return null; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/utils.js b/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/utils.js deleted file mode 100644 index 030956c..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/tabs/utils.js +++ /dev/null @@ -1,87 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -function getTabContainer(tabBrowser) { - return tabBrowser.tabContainer; -} -exports.getTabContainer = getTabContainer; - -function getTabBrowsers(window) { - return Array.slice(window.document.getElementsByTagName("tabbrowser")); -} -exports.getTabBrowsers = getTabBrowsers; - -function getTabContainers(window) { - return getTabBrowsers(window).map(getTabContainer); -} -exports.getTabContainers = getTabContainers; - -function getTabs(window) { - return getTabContainers(window).reduce(function (tabs, container) { - tabs.push.apply(tabs, container.children); - return tabs; - }, []); -} -exports.getTabs = getTabs; - -function getActiveTab(window) { - return window.gBrowser.selectedTab; -} -exports.getActiveTab = getActiveTab; - -function getOwnerWindow(tab) { - return tab.ownerDocument.defaultView; -} -exports.getOwnerWindow = getOwnerWindow; - -function openTab(window, url) { - return window.gBrowser.addTab(url); -} -exports.openTab = openTab; - -function closeTab(tab) { - return getOwnerWindow(tab).gBrowser.removeTab(tab); -} -exports.closeTab = closeTab; - -function activateTab(tab) { - getOwnerWindow(tab).gBrowser.selectedTab = tab; -} -exports.activateTab = activateTab; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/test.js b/tools/addon-sdk-1.4/packages/api-utils/lib/test.js deleted file mode 100644 index 6490630..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/test.js +++ /dev/null @@ -1,140 +0,0 @@ -/* vim:ts=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const BaseAssert = require("./test/assert").Assert; -const { isFunction, isObject } = require("./type"); - -function extend(target) { - let descriptor = {} - Array.slice(arguments, 1).forEach(function(source) { - Object.getOwnPropertyNames(source).forEach(function onEach(name) { - descriptor[name] = Object.getOwnPropertyDescriptor(source, name); - }); - }); - return Object.create(target, descriptor); -} - -/** - * Function takes test `suite` object in CommonJS format and defines all of the - * tests from that suite and nested suites in a jetpack format on a given - * `target` object. Optionally third argument `prefix` can be passed to prefix - * all the test names. - */ -function defineTestSuite(target, suite, prefix) { - prefix = prefix || ""; - // If suite defines `Assert` that's what `assert` object have to be created - // from and passed to a test function (This allows custom assertion functions) - // See for details: http://wiki.commonjs.org/wiki/Unit_Testing/1.1 - let Assert = suite.Assert || BaseAssert; - // Going through each item in the test suite and wrapping it into a - // Jetpack test format. - Object.keys(suite).forEach(function(key) { - // If name starts with test then it's a test function or suite. - if (key.indexOf("test") === 0) { - let test = suite[key]; - - // For each test function so we create a wrapper test function in a - // jetpack format and copy that to a `target` exports. - if (isFunction(test)) { - - // Since names of the test may match across suites we use full object - // path as a name to avoid overriding same function. - target[prefix + key] = function(options) { - - // Creating `assert` functions for this test. - let assert = Assert(options); - - // If CommonJS test function expects more than one argument - // it means that test is async and second argument is a callback - // to notify that test is finished. - if (1 < test.length) { - - // Letting test runner know that test is executed async and - // creating a callback function that CommonJS tests will call - // once it's done. - options.waitUntilDone(); - test(assert, function() { - options.done(); - }); - } - - // Otherwise CommonJS test is synchronous so we call it only with - // one argument. - else { - test(assert); - } - } - } - - // If it's an object then it's a test suite containing test function - // and / or nested test suites. In that case we just extend prefix used - // and call this function to copy and wrap tests from nested suite. - else if (isObject(test)) { - // We need to clone `tests` instead of modifying it, since it's very - // likely that it is frozen (usually test suites imported modules). - test = extend(Object.prototype, test, { - Assert: test.Assert || Assert - }); - defineTestSuite(target, test, prefix + key + "."); - } - } - }); -} - -/** - * This function is a CommonJS test runner function, but since Jetpack test - * runner and test format is different from CommonJS this function shims given - * `exports` with all its tests into a Jetpack test format so that the built-in - * test runner will be able to run CommonJS test without manual changes. - */ -exports.run = function run(exports) { - - // We can't leave old properties on exports since those are test in a CommonJS - // format that why we move everything to a new `suite` object. - let suite = {}; - Object.keys(exports).forEach(function(key) { - suite[key] = exports[key]; - delete exports[key]; - }); - - // Now we wrap all the CommonJS tests to a Jetpack format and define - // those to a given `exports` object since that where jetpack test runner - // will look for them. - defineTestSuite(exports, suite); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/test/assert.js b/tools/addon-sdk-1.4/packages/api-utils/lib/test/assert.js deleted file mode 100644 index 0c29d62..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/test/assert.js +++ /dev/null @@ -1,360 +0,0 @@ -/* vim:ts=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { isFunction, isNull, isObject, isString, isRegExp, isArray, isDate, - isPrimitive, isUndefined, instanceOf, source } = require("../type"); - -/** - * The `AssertionError` is defined in assert. - * @extends Error - * @example - * new assert.AssertionError({ - * message: message, - * actual: actual, - * expected: expected - * }) - */ -function AssertionError(options) { - let assertionError = Object.create(AssertionError.prototype); - - if (isString(options)) - options = { message: options }; - if ("actual" in options) - assertionError.actual = options.actual; - if ("expected" in options) - assertionError.expected = options.expected; - if ("operator" in options) - assertionError.operator = options.operator; - - assertionError.message = options.message; - assertionError.stack = new Error().stack; - return assertionError; -} -AssertionError.prototype = Object.create(Error.prototype, { - constructor: { value: AssertionError }, - name: { value: "AssertionError", enumerable: true }, - toString: { value: function toString() { - let value; - if (this.message) { - value = this.name + " : " + this.message; - } - else { - value = [ - this.name + " : ", - source(this.expected), - this.operator, - source(this.actual) - ].join(" "); - } - return value; - }} -}); -exports.AssertionError = AssertionError; - -function Assert(logger) { - return Object.create(Assert.prototype, { _log: { value: logger }}); -} -Assert.prototype = { - fail: function fail(e) { - this._log.fail(e.message); - }, - pass: function pass(message) { - this._log.pass(message); - }, - error: function error(e) { - this._log.exception(e); - }, - ok: function ok(value, message) { - if (!!!value) { - this.fail({ - actual: value, - expected: true, - message: message, - operator: "==" - }); - } - else { - this.pass(message); - } - }, - - /** - * The equality assertion tests shallow, coercive equality with `==`. - * @example - * assert.equal(1, 1, "one is one"); - */ - equal: function equal(actual, expected, message) { - if (actual == expected) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "==" - }); - } - }, - - /** - * The non-equality assertion tests for whether two objects are not equal - * with `!=`. - * @example - * assert.notEqual(1, 2, "one is not two"); - */ - notEqual: function notEqual(actual, expected, message) { - if (actual != expected) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "!=", - }); - } - }, - - /** - * The equivalence assertion tests a deep (with `===`) equality relation. - * @example - * assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects") - */ - deepEqual: function deepEqual(actual, expected, message) { - if (isDeepEqual(actual, expected)) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "deepEqual" - }); - } - }, - - /** - * The non-equivalence assertion tests for any deep (with `===`) inequality. - * @example - * assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }), - * "object's inherit from different prototypes"); - */ - notDeepEqual: function notDeepEqual(actual, expected, message) { - if (!isDeepEqual(actual, expected)) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "notDeepEqual" - }); - } - }, - - /** - * The strict equality assertion tests strict equality, as determined by - * `===`. - * @example - * assert.strictEqual(null, null, "`null` is `null`") - */ - strictEqual: function strictEqual(actual, expected, message) { - if (actual === expected) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "===" - }); - } - }, - - /** - * The strict non-equality assertion tests for strict inequality, as - * determined by `!==`. - * @example - * assert.notStrictEqual(null, undefined, "`null` is not `undefined`"); - */ - notStrictEqual: function notStrictEqual(actual, expected, message) { - if (actual !== expected) { - this.pass(message); - } - else { - this.fail({ - actual: actual, - expected: expected, - message: message, - operator: "!==" - }) - } - }, - - /** - * The assertion whether or not given `block` throws an exception. If optional - * `Error` argument is provided and it's type of function thrown error is - * asserted to be an instance of it, if type of `Error` is string then message - * of throw exception is asserted to contain it. - * @param {Function} block - * Function that is expected to throw. - * @param {Error|RegExp} [Error] - * Error constructor that is expected to be thrown or a string that - * must be contained by a message of the thrown exception, or a RegExp - * matching a message of the thrown exception. - * @param {String} message - * Description message - * - * @examples - * - * assert.throws(function block() { - * doSomething(4) - * }, "Object is expected", "Incorrect argument is passed"); - * - * assert.throws(function block() { - * Object.create(5) - * }, TypeError, "TypeError is thrown"); - */ - throws: function throws(block, Error, message) { - let threw = false; - let exception = null; - - // If third argument is not provided and second argument is a string it - // means that optional `Error` argument was not passed, so we shift - // arguments. - if (isString(Error) && isUndefined(message)) { - message = Error; - Error = undefined; - } - - // Executing given `block`. - try { - block(); - } - catch (e) { - threw = true; - exception = e; - } - - // If exception was thrown and `Error` argument was not passed assert is - // passed. - if (threw && (isUndefined(Error) || - // If passed `Error` is RegExp using it's test method to - // assert thrown exception message. - (isRegExp(Error) && Error.test(exception.message)) || - // If passed `Error` is a constructor function testing if - // thrown exception is an instance of it. - (isFunction(Error) && instanceOf(exception, Error)))) - { - this.pass(message); - } - - // Otherwise we report assertion failure. - else { - let failure = { - message: message, - operator: "throws" - }; - - if (exception) - failure.actual = exception; - - if (Error) - failure.expected = Error; - - this.fail(failure); - } - } -}; -exports.Assert = Assert; - -function isDeepEqual(actual, expected) { - - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - } - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - else if (isDate(actual) && isDate(expected)) { - return actual.getTime() === expected.getTime(); - } - - // XXX specification bug: this should be specified - else if (isPrimitive(actual) || isPrimitive(expected)) { - return expected === actual; - } - - // 7.3. Other pairs that do not both pass typeof value == "object", - // equivalence is determined by ==. - else if (!isObject(actual) && !isObject(expected)) { - return actual == expected; - } - - // 7.4. For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical "prototype" property. Note: this - // accounts for both named and indexed properties on Arrays. - else { - return actual.prototype === expected.prototype && - isEquivalent(actual, expected); - } -} - -function isEquivalent(a, b, stack) { - return isArrayEquivalent(Object.keys(a).sort(), - Object.keys(b).sort()) && - Object.keys(a).every(function(key) { - return isDeepEqual(a[key], b[key], stack) - }); -} - -function isArrayEquivalent(a, b, stack) { - return isArray(a) && isArray(b) && - a.every(function(value, index) { - return isDeepEqual(value, b[index]); - }); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/text-streams.js b/tools/addon-sdk-1.4/packages/api-utils/lib/text-streams.js deleted file mode 100644 index 87d375d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/text-streams.js +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,Cu,components} = require("chrome"); -var NetUtil = {}; -Cu.import("resource://gre/modules/NetUtil.jsm", NetUtil); -NetUtil = NetUtil.NetUtil; - -// NetUtil.asyncCopy() uses this buffer length, and since we call it, for best -// performance we use it, too. -const BUFFER_BYTE_LEN = 0x8000; -const PR_UINT32_MAX = 0xffffffff; -const DEFAULT_CHARSET = "UTF-8"; - -exports.TextReader = TextReader; -exports.TextWriter = TextWriter; - -/** - * An input stream that reads text from a backing stream using a given text - * encoding. - * - * @param inputStream - * The stream is backed by this nsIInputStream. It must already be - * opened. - * @param charset - * Text in inputStream is expected to be in this character encoding. If - * not given, "UTF-8" is assumed. See nsICharsetConverterManager.idl for - * documentation on how to determine other valid values for this. - */ -function TextReader(inputStream, charset) { - const self = this; - charset = checkCharset(charset); - - let stream = Cc["@mozilla.org/intl/converter-input-stream;1"]. - createInstance(Ci.nsIConverterInputStream); - stream.init(inputStream, charset, BUFFER_BYTE_LEN, - Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); - - let manager = new StreamManager(this, stream); - - /** - * Reads a string from the stream. If the stream is closed, an exception is - * thrown. - * - * @param numChars - * The number of characters to read. If not given, the remainder of - * the stream is read. - * @return The string read. If the stream is already at EOS, returns the - * empty string. - */ - this.read = function TextReader_read(numChars) { - manager.ensureOpened(); - - let readAll = false; - if (typeof(numChars) === "number") - numChars = Math.max(numChars, 0); - else - readAll = true; - - let str = ""; - let totalRead = 0; - let chunkRead = 1; - - // Read in numChars or until EOS, whichever comes first. Note that the - // units here are characters, not bytes. - while (true) { - let chunk = {}; - let toRead = readAll ? - PR_UINT32_MAX : - Math.min(numChars - totalRead, PR_UINT32_MAX); - if (toRead <= 0 || chunkRead <= 0) - break; - - // The converter stream reads in at most BUFFER_BYTE_LEN bytes in a call - // to readString, enough to fill its byte buffer. chunkRead will be the - // number of characters encoded by the bytes in that buffer. - chunkRead = stream.readString(toRead, chunk); - str += chunk.value; - totalRead += chunkRead; - } - - return str; - }; -} - -/** - * A buffered output stream that writes text to a backing stream using a given - * text encoding. - * - * @param outputStream - * The stream is backed by this nsIOutputStream. It must already be - * opened. - * @param charset - * Text will be written to outputStream using this character encoding. - * If not given, "UTF-8" is assumed. See nsICharsetConverterManager.idl - * for documentation on how to determine other valid values for this. - */ -function TextWriter(outputStream, charset) { - const self = this; - charset = checkCharset(charset); - - let stream = outputStream; - - // Buffer outputStream if it's not already. - let ioUtils = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil); - if (!ioUtils.outputStreamIsBuffered(outputStream)) { - stream = Cc["@mozilla.org/network/buffered-output-stream;1"]. - createInstance(Ci.nsIBufferedOutputStream); - stream.init(outputStream, BUFFER_BYTE_LEN); - } - - // I'd like to use nsIConverterOutputStream. But NetUtil.asyncCopy(), which - // we use below in writeAsync(), naturally expects its sink to be an instance - // of nsIOutputStream, which nsIConverterOutputStream's only implementation is - // not. So we use uconv and manually convert all strings before writing to - // outputStream. - let uconv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. - createInstance(Ci.nsIScriptableUnicodeConverter); - uconv.charset = charset; - - let manager = new StreamManager(this, stream); - - /** - * Flushes the backing stream's buffer. - */ - this.flush = function TextWriter_flush() { - manager.ensureOpened(); - stream.flush(); - }; - - /** - * Writes a string to the stream. If the stream is closed, an exception is - * thrown. - * - * @param str - * The string to write. - */ - this.write = function TextWriter_write(str) { - manager.ensureOpened(); - let istream = uconv.convertToInputStream(str); - let len = istream.available(); - while (len > 0) { - stream.writeFrom(istream, len); - len = istream.available(); - } - istream.close(); - }; - - /** - * Writes a string on a background thread. After the write completes, the - * backing stream's buffer is flushed, and both the stream and the backing - * stream are closed, also on the background thread. If the stream is already - * closed, an exception is thrown immediately. - * - * @param str - * The string to write. - * @param callback - * An optional function. If given, it's called as callback(error) when - * the write completes. error is an Error object or undefined if there - * was no error. Inside callback, |this| is the stream object. - */ - this.writeAsync = function TextWriter_writeAsync(str, callback) { - manager.ensureOpened(); - let istream = uconv.convertToInputStream(str); - NetUtil.asyncCopy(istream, stream, function (result) { - let err = components.isSuccessCode(result) ? undefined : - new Error("An error occured while writing to the stream: " + result); - if (err) - console.error(err); - - // asyncCopy() closes its output (and input) stream. - manager.opened = false; - - if (typeof(callback) === "function") { - try { - callback.call(self, err); - } - catch (exc) { - console.exception(exc); - } - } - }); - }; -} - -// This manages the lifetime of stream, a TextReader or TextWriter. It defines -// closed and close() on stream and registers an unload listener that closes -// rawStream if it's still opened. It also provides ensureOpened(), which -// throws an exception if the stream is closed. -function StreamManager(stream, rawStream) { - const self = this; - this.rawStream = rawStream; - this.opened = true; - - /** - * True iff the stream is closed. - */ - stream.__defineGetter__("closed", function stream_closed() { - return !self.opened; - }); - - /** - * Closes both the stream and its backing stream. If the stream is already - * closed, an exception is thrown. For TextWriters, this first flushes the - * backing stream's buffer. - */ - stream.close = function stream_close() { - self.ensureOpened(); - self.unload(); - }; - - require("./unload").ensure(this); -} - -StreamManager.prototype = { - ensureOpened: function StreamManager_ensureOpened() { - if (!this.opened) - throw new Error("The stream is closed and cannot be used."); - }, - unload: function StreamManager_unload() { - // TextWriter.writeAsync() causes rawStream to close and therefore sets - // opened to false, so check that we're still opened. - if (this.opened) { - // Calling close() on both an nsIUnicharInputStream and - // nsIBufferedOutputStream closes their backing streams. It also forces - // nsIOutputStreams to flush first. - this.rawStream.close(); - this.opened = false; - } - } -}; - -function checkCharset(charset) { - return typeof(charset) === "string" ? charset : DEFAULT_CHARSET; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/timer.js b/tools/addon-sdk-1.4/packages/api-utils/lib/timer.js deleted file mode 100644 index 052f506..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/timer.js +++ /dev/null @@ -1,141 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Drew Willcoxon <adw@mozilla.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * Erik Vold <erikvvold@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); -var xpcom = require("./xpcom"); - -var timerClass = Cc["@mozilla.org/timer;1"]; -var nextID = 1; -var timers = {}; - -function TimerCallback(timerID, callback, params) { - this._callback = callback; - this._params = params; -}; -TimerCallback.prototype = { - QueryInterface : xpcom.utils.generateQI([Ci.nsITimerCallback]) -}; - -function TimeoutCallback(timerID, callback, params) { - memory.track(this); - TimerCallback.apply(this, arguments) - this._timerID = timerID; -}; -TimeoutCallback.prototype = new TimerCallback(); -TimeoutCallback.prototype.notify = function notifyOnTimeout(timer) { - try { - delete timers[this._timerID]; - this._callback.apply(null, this._params); - } catch (e) { - console.exception(e); - } -}; - -function IntervalCallback(timerID, callback, params) { - memory.track(this); - TimerCallback.apply(this, arguments) -}; -IntervalCallback.prototype = new TimerCallback(); -IntervalCallback.prototype.notify = function notifyOnInterval() { - try { - this._callback.apply(null, this._params); - } catch (e) { - console.exception(e); - } -}; - - -var setTimeout = exports.setTimeout = function setTimeout(callback, delay) { - return makeTimer( - Ci.nsITimer.TYPE_ONE_SHOT, - callback, - TimeoutCallback, - delay, - Array.slice(arguments, 2)); -}; - -var clearTimeout = exports.clearTimeout = function clearTimeout(timerID) { - cancelTimer(timerID); -}; - -var setInterval = exports.setInterval = function setInterval(callback, delay) { - return makeTimer( - Ci.nsITimer.TYPE_REPEATING_SLACK, - callback, - IntervalCallback, - delay, - Array.slice(arguments, 2)); -}; - -var clearInterval = exports.clearInterval = function clearInterval(timerID) { - cancelTimer(timerID); -}; - -function makeTimer(type, callback, callbackType, delay, params) { - var timer = timerClass.createInstance(Ci.nsITimer); - - memory.track(timer, "nsITimer"); - - var timerID = nextID++; - timers[timerID] = timer; - - timer.initWithCallback( - new callbackType(timerID, callback, params), - delay || 0, - type - ); - return timerID; -} - -function cancelTimer(timerID) { - var timer = timers[timerID]; - if (timer) { - timer.cancel(); - delete timers[timerID]; - } -} - -require("./unload").when( - function cancelAllPendingTimers() { - var timerIDs = [timerID for (timerID in timers)]; - timerIDs.forEach(function(timerID) { cancelTimer(timerID); }); - }); - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/traceback.js b/tools/addon-sdk-1.4/packages/api-utils/lib/traceback.js deleted file mode 100644 index fdedd99..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/traceback.js +++ /dev/null @@ -1,155 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,components} = require("chrome"); - -// Undo the auto-parentification of URLs done in bug 418356. -function deParentifyURL(url) { - return url ? url.split(" -> ").slice(-1)[0] : url; -} - -// TODO: We might want to move this function to url or some similar -// module. -function getLocalFile(path) { - var ios = Cc['@mozilla.org/network/io-service;1'] - .getService(Ci.nsIIOService); - var channel = ios.newChannel(path, null, null); - var iStream = channel.open(); - var siStream = Cc['@mozilla.org/scriptableinputstream;1'] - .createInstance(Ci.nsIScriptableInputStream); - siStream.init(iStream); - var data = new String(); - data += siStream.read(-1); - siStream.close(); - iStream.close(); - return data; -} - -function safeGetFileLine(path, line) { - try { - var scheme = require("./url").URL(path).scheme; - // TODO: There should be an easier, more accurate way to figure out - // what's the case here. - if (!(scheme == "http" || scheme == "https")) - return getLocalFile(path).split("\n")[line - 1]; - } catch (e) {} - return null; -} - -function errorStackToJSON(stack) { - var lines = stack.split("\n"); - - var frames = []; - lines.forEach( - function(line) { - if (!line) - return; - var atIndex = line.indexOf("@"); - var colonIndex = line.lastIndexOf(":"); - var filename = deParentifyURL(line.slice(atIndex + 1, colonIndex)); - var lineNo = parseInt(line.slice(colonIndex + 1)); - var funcSig = line.slice(0, atIndex); - var funcName = funcSig.slice(0, funcSig.indexOf("(")); - frames.unshift({filename: filename, - funcName: funcName, - lineNo: lineNo}); - }); - - return frames; -}; - -function nsIStackFramesToJSON(frame) { - var stack = []; - - while (frame) { - if (frame.filename) { - var filename = deParentifyURL(frame.filename); - stack.splice(0, 0, {filename: filename, - lineNo: frame.lineNumber, - funcName: frame.name}); - } - frame = frame.caller; - } - - return stack; -}; - -var fromException = exports.fromException = function fromException(e) { - if (e instanceof Ci.nsIException) - return nsIStackFramesToJSON(e.location); - if (e.stack && e.stack.length) - return errorStackToJSON(e.stack); - if (e.fileName && typeof(e.lineNumber == "number")) - return [{filename: deParentifyURL(e.fileName), - lineNo: e.lineNumber, - funcName: null}]; - return []; -}; - -var get = exports.get = function get() { - return nsIStackFramesToJSON(components.stack.caller); -}; - -var format = exports.format = function format(tbOrException) { - if (tbOrException === undefined) { - tbOrException = get(); - tbOrException.splice(-1, 1); - } - - var tb; - if (typeof(tbOrException) == "object" && - tbOrException.constructor.name == "Array") - tb = tbOrException; - else - tb = fromException(tbOrException); - - var lines = ["Traceback (most recent call last):"]; - - tb.forEach( - function(frame) { - if (!(frame.filename || frame.lineNo || frame.funcName)) - return; - lines.push(' File "' + frame.filename + '", line ' + - frame.lineNo + ', in ' + frame.funcName); - var sourceLine = safeGetFileLine(frame.filename, frame.lineNo); - if (sourceLine) - lines.push(' ' + sourceLine.trim()); - }); - - return lines.join("\n"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/traits.js b/tools/addon-sdk-1.4/packages/api-utils/lib/traits.js deleted file mode 100644 index 59193aa..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/traits.js +++ /dev/null @@ -1,215 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { - compose: _compose, - override: _override, - resolve: _resolve, - trait: _trait, - //create: _create, - required, -} = require('./traits/core'); - -const defineProperties = Object.defineProperties, - freeze = Object.freeze, - create = Object.create; - -/** - * Work around bug 608959 by defining the _create function here instead of - * importing it from traits/core. For docs on this function, see the create - * function in that module. - * - * FIXME: remove this workaround in favor of importing the function once that - * bug has been fixed. - */ -function _create(proto, trait) { - let properties = {}, - keys = Object.getOwnPropertyNames(trait); - for each(let key in keys) { - let descriptor = trait[key]; - if (descriptor.required && - !Object.prototype.hasOwnProperty.call(proto, key)) - throw new Error('Missing required property: ' + key); - else if (descriptor.conflict) - throw new Error('Remaining conflicting property: ' + key); - else - properties[key] = descriptor; - } - return Object.create(proto, properties); -} - -/** - * Placeholder for `Trait.prototype` - */ -let TraitProto = Object.prototype; - -function Get(key) this[key] -function Set(key, value) this[key] = value - -/** - * Creates anonymous trait descriptor from the passed argument, unless argument - * is a trait constructor. In later case trait's already existing properties - * descriptor is returned. - * This is module's internal function and is used as a gateway to a trait's - * internal properties descriptor. - * @param {Function} $ - * Composed trait's constructor. - * @returns {Object} - * Private trait property of the composition. - */ -function TraitDescriptor(object) - ( - 'function' == typeof object && - (object.prototype == TraitProto || object.prototype instanceof Trait) - ) ? object._trait(TraitDescriptor) : _trait(object) - -function Public(instance, trait) { - let result = {}, - keys = Object.getOwnPropertyNames(trait); - for each (let key in keys) { - if ('_' === key.charAt(0) && '__iterator__' !== key ) - continue; - let property = trait[key], - descriptor = { - configurable: property.configurable, - enumerable: property.enumerable - }; - if (property.get) - descriptor.get = property.get.bind(instance); - if (property.set) - descriptor.set = property.set.bind(instance); - if ('value' in property) { - let value = property.value; - if ('function' === typeof value) { - descriptor.value = property.value.bind(instance); - descriptor.writable = property.writable; - } else { - descriptor.get = Get.bind(instance, key); - descriptor.set = Set.bind(instance, key); - } - } - result[key] = descriptor; - } - return result; -} - -/** - * This is private function that composes new trait with privates. - */ -function Composition(trait) { - function Trait() { - let self = _create({}, trait); - self._public = create(Trait.prototype, Public(self, trait)); - delete self._public.constructor; - if (Object === self.constructor) - self.constructor = Trait; - else - return self.constructor.apply(self, arguments) || self._public; - return self._public; - } - defineProperties(Trait, { - prototype: { value: freeze(create(TraitProto, { - constructor: { value: constructor, writable: true } - }))}, // writable is `true` to avoid getters in custom ES5 - displayName: { value: (trait.constructor || constructor).name }, - compose: { value: compose, enumerable: true }, - override: { value: override, enumerable: true }, - resolve: { value: resolve, enumerable: true }, - required: { value: required, enumerable: true }, - _trait: { value: function _trait(caller) - caller === TraitDescriptor ? trait : undefined - } - }); - return freeze(Trait); -} - -/** - * Composes new trait out of itself and traits / property maps passed as an - * arguments. If two or more traits / property maps have properties with the - * same name, the new trait will contain a "conflict" property for that name. - * This is a commutative and associative operation, and the order of its - * arguments is not significant. - * @params {Object|Function} - * List of Traits or property maps to create traits from. - * @returns {Function} - * New trait containing the combined properties of all the traits. - */ -function compose() { - let traits = Array.slice(arguments, 0); - traits.push(this); - return Composition(_compose.apply(null, traits.map(TraitDescriptor))); -} - -/** - * Composes a new trait with all of the combined properties of `this` and the - * argument traits. In contrast to `compose`, `override` immediately resolves - * all conflicts resulting from this composition by overriding the properties of - * later traits. Trait priority is from left to right. I.e. the properties of - * the leftmost trait are never overridden. - * @params {Object} trait - * @returns {Object} - */ -function override() { - let traits = Array.slice(arguments, 0); - traits.push(this); - return Composition(_override.apply(null, traits.map(TraitDescriptor))); -} - -/** - * Composes new resolved trait, with all the same properties as this - * trait, except that all properties whose name is an own property of - * `resolutions` will be renamed to `resolutions[name]`. If it is - * `resolutions[name]` is `null` value is changed into a required property - * descriptor. - */ -function resolve(resolutions) - Composition(_resolve(resolutions, TraitDescriptor(this))) - -/** - * Base Trait, that all the traits are composed of. - */ -const Trait = Composition({ - /** - * Internal property holding public API of this instance. - */ - _public: { value: null, configurable: true, writable: true }, - toString: { value: function() '[object ' + this.constructor.name + ']' } -}); -TraitProto = Trait.prototype; -exports.Trait = Trait; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/traits/core.js b/tools/addon-sdk-1.4/packages/api-utils/lib/traits/core.js deleted file mode 100644 index bc8ae14..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/traits/core.js +++ /dev/null @@ -1,349 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -// Design inspired by: http://www.traitsjs.org/ - -// shortcuts -const getOwnPropertyNames = Object.getOwnPropertyNames, - getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, - hasOwn = Object.prototype.hasOwnProperty, - _create = Object.create; - -function doPropertiesMatch(object1, object2, name) { - // If `object1` has property with the given `name` - return name in object1 ? - // then `object2` should have it with the same value. - name in object2 && object1[name] === object2[name] : - // otherwise `object2` should not have property with the given `name`. - !(name in object2); -} - -/** - * Compares two trait custom property descriptors if they are the same. If - * both are `conflict` or all the properties of descriptor are equal returned - * value will be `true`, otherwise it will be `false`. - * @param {Object} desc1 - * @param {Object} desc2 - */ -function areSame(desc1, desc2) { - return ('conflict' in desc1 && desc1.conflict && - 'conflict' in desc2 && desc2.conflict) || - (doPropertiesMatch(desc1, desc2, 'get') && - doPropertiesMatch(desc1, desc2, 'set') && - doPropertiesMatch(desc1, desc2, 'value') && - doPropertiesMatch(desc1, desc2, 'enumerable') && - doPropertiesMatch(desc1, desc2, 'required') && - doPropertiesMatch(desc1, desc2, 'conflict')); -} - -/** - * Converts array to an object whose own property names represent - * values of array. - * @param {String[]} names - * @returns {Object} - * @example - * Map(['foo', ...]) => { foo: true, ...} - */ -function Map(names) { - let map = {}; - for each (let name in names) - map[name] = true; - return map; -} - - -const ERR_CONFLICT = 'Remaining conflicting property: ', - ERR_REQUIRED = 'Missing required property: '; -/** - * Constant singleton, representing placeholder for required properties. - * @type {Object} - */ -const required = { toString: function()'<Trait.required>' }; -exports.required = required; - -/** - * Generates custom **required** property descriptor. Descriptor contains - * non-standard property `required` that is equal to `true`. - * @param {String} name - * property name to generate descriptor for. - * @returns {Object} - * custom property descriptor - */ -function Required(name) { - function required() { throw new Error(ERR_REQUIRED + name) } - return { - get: required, - set: required, - required: true - }; -} - -/** - * Generates custom **conflicting** property descriptor. Descriptor contains - * non-standard property `conflict` that is equal to `true`. - * @param {String} name - * property name to generate descriptor for. - * @returns {Object} - * custom property descriptor - */ -function Conflict(name) { - function conflict() { throw new Error(ERR_CONFLICT + name) } - return { - get: conflict, - set: conflict, - conflict: true - }; -} - -/** - * Function generates custom properties descriptor of the `object`s own - * properties. All the inherited properties are going to be ignored. - * Properties with values matching `required` singleton will be marked as - * 'required' properties. - * @param {Object} object - * Set of properties to generate trait from. - * @returns {Object} - * Properties descriptor of all of the `object`'s own properties. - */ -function trait(properties) { - let result = {}, - keys = getOwnPropertyNames(properties); - for each (let key in keys) { - let descriptor = getOwnPropertyDescriptor(properties, key); - result[key] = (required === descriptor.value) ? Required(key) : descriptor; - } - return result; -} -exports.Trait = exports.trait = trait; - -/** - * Composes new trait. If two or more traits have own properties with the - * same name, the new trait will contain a 'conflict' property for that name. - * 'compose' is a commutative and associative operation, and the order of its - * arguments is not significant. - * - * @params {Object} trait - * Takes traits as an arguments - * @returns {Object} - * New trait containing the combined own properties of all the traits. - * @example - * var newTrait = compose(trait_1, trait_2, ..., trait_N); - */ -function compose(trait1, trait2) { - let traits = Array.slice(arguments, 0), - result = {}; - for each (let trait in traits) { - let keys = getOwnPropertyNames(trait); - for each (let key in keys) { - let descriptor = trait[key]; - // if property already exists and it's not a requirement - if (hasOwn.call(result, key) && !result[key].required) { - if (descriptor.required) - continue; - if (!areSame(descriptor, result[key])) - result[key] = Conflict(key); - } else { - result[key] = descriptor; - } - } - } - return result; -} -exports.compose = compose; - -/** - * Composes new trait with the same own properties as the original trait, - * except that all property names appearing in the first argument are replaced - * by 'required' property descriptors. - * @param {String[]} keys - * Array of strings property names. - * @param {Object} trait - * A trait some properties of which should be excluded. - * @returns {Object} - * @example - * var newTrait = exclude(['name', ...], trait) - */ -function exclude(keys, trait) { - let exclusions = Map(keys), - result = {}; - - keys = getOwnPropertyNames(trait); - - for each (let key in keys) { - if (!hasOwn.call(exclusions, key) || trait[key].required) - result[key] = trait[key]; - else - result[key] = Required(key); - } - return result; -} - -/** - * Composes a new trait with all of the combined properties of the argument - * traits. In contrast to `compose`, `override` immediately resolves all - * conflicts resulting from this composition by overriding the properties of - * later traits. Trait priority is from left to right. I.e. the properties of - * the leftmost trait are never overridden. - * @params {Object} trait - * @returns {Object} - * @examples - * // override is associative: - * override(t1,t2,t3) - * // is equivalent to - * override(t1, override(t2, t3)) - * // or - * to override(override(t1, t2), t3) - * - * // override is not commutative: - * override(t1,t2) - * // is not equivalent to - * override(t2,t1) - */ -function override() { - let traits = Array.slice(arguments, 0), - result = {}; - for each (let trait in traits) { - let keys = getOwnPropertyNames(trait); - for each(let key in keys) { - let descriptor = trait[key]; - if (!hasOwn.call(result, key) || result[key].required) - result[key] = descriptor; - } - } - return result; -} -exports.override = override; - -/** - * Composes a new trait with the same properties as the original trait, except - * that all properties whose name is an own property of map will be renamed to - * map[name], and a 'required' property for name will be added instead. - * @param {Object} map - * An object whose own properties serve as a mapping from old names to new - * names. - * @param {Object} trait - * A trait object - * @returns {Object} - * @example - * var newTrait = rename(map, trait); - */ -function rename(map, trait) { - let result = {}, - keys = getOwnPropertyNames(trait); - for each(let key in keys) { - // must be renamed & it's not requirement - if (hasOwn.call(map, key) && !trait[key].required) { - let alias = map[key]; - if (hasOwn.call(result, alias) && !result[alias].required) - result[alias] = Conflict(alias); - else - result[alias] = trait[key]; - if (!hasOwn.call(result, key)) - result[key] = Required(key); - } else { // must not be renamed or its a requirement - // property is not in result trait yet - if (!hasOwn.call(result, key)) - result[key] = trait[key]; - // property is already in resulted trait & it's not requirement - else if (!trait[key].required) - result[key] = Conflict(key); - } - } - return result; -} - -/** -* Composes new resolved trait, with all the same properties as the original -* trait, except that all properties whose name is an own property of -* resolutions will be renamed to `resolutions[name]`. If it is -* `resolutions[name]` is `null` value is changed into a required property -* descriptor. -* function can be implemented as `rename(map,exclude(exclusions, trait))` -* where map is the subset of mappings from oldName to newName and exclusions -* is an array of all the keys that map to `null`. -* Note: it's important to **first** `exclude`, **then** `rename`, since -* `exclude` and rename are not associative. -* @param {Object} resolutions -* An object whose own properties serve as a mapping from old names to new -* names, or to `null` if the property should be excluded. -* @param {Object} trait -* A trait object -* @returns {Object} -* Resolved trait with the same own properties as the original trait. -*/ -function resolve(resolutions, trait) { - let renames = {}, - exclusions = [], - keys = getOwnPropertyNames(resolutions); - for each (let key in keys) { // pre-process renamed and excluded properties - if (resolutions[key]) // old name -> new name - renames[key] = resolutions[key]; - else // name -> undefined - exclusions.push(key); - } - return rename(renames, exclude(exclusions, trait)); -} -exports.resolve = resolve; - -/** - * `create` is like `Object.create`, except that it ensures that: - * - an exception is thrown if 'trait' still contains required properties - * - an exception is thrown if 'trait' still contains conflicting - * properties - * @param {Object} - * prototype of the completed object - * @param {Object} trait - * trait object to be turned into a complete object - * @returns {Object} - * An object with all of the properties described by the trait. - */ -function create(proto, trait) { - let properties = {}, - keys = getOwnPropertyNames(trait); - for each(let key in keys) { - let descriptor = trait[key]; - if (descriptor.required && !hasOwn.call(proto, key)) - throw new Error(ERR_REQUIRED + key); - else if (descriptor.conflict) - throw new Error(ERR_CONFLICT + key); - else - properties[key] = descriptor; - } - return _create(proto, properties); -} -exports.create = create; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/type.js b/tools/addon-sdk-1.4/packages/api-utils/lib/type.js deleted file mode 100644 index 012d2d1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/type.js +++ /dev/null @@ -1,372 +0,0 @@ -/* vim:ts=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -/** - * Returns `true` if `value` is `undefined`. - * @examples - * var foo; isUndefined(foo); // true - * isUndefined(0); // false - */ -function isUndefined(value) { - return value === undefined; -} -exports.isUndefined = isUndefined; - -/** - * Returns `true` if value is `null`. - * @examples - * isNull(null); // true - * isNull(undefined); // false - */ -function isNull(value) { - return value === null; -} -exports.isNull = isNull; - -/** - * Returns `true` if value is a string. - * @examples - * isString("moe"); // true - */ -function isString(value) { - return typeof value === "string"; -} -exports.isString = isString; - -/** - * Returns `true` if `value` is a number. - * @examples - * isNumber(8.4 * 5); // true - */ -function isNumber(value) { - return typeof value === "number"; -} -exports.isNumber = isNumber; - -/** - * Returns `true` if `value` is a `RegExp`. - * @examples - * isRegExp(/moe/); // true - */ -function isRegExp(value) { - return isObject(value) && instanceOf(value, RegExp); -} -exports.isRegExp = isRegExp; - -/** - * Returns true if `value` is a `Date`. - * @examples - * isDate(new Date()); // true - */ -function isDate(value) { - return isObject(value) && instanceOf(value, Date); -} -exports.isDate = isDate; - -/** - * Returns true if object is a Function. - * @examples - * isFunction(function foo(){}) // true - */ -function isFunction(value) { - return typeof value === "function"; -} -exports.isFunction = isFunction; - -/** - * Returns `true` if `value` is an object (please note that `null` is considered - * to be an atom and not an object). - * @examples - * isObject({}) // true - * isObject(null) // false - */ -function isObject(value) { - return typeof value === "object" && value !== null; -} -exports.isObject = isObject; - -/** - * Returns true if `value` is an Array. - * @examples - * isArray([1, 2, 3]) // true - * isArray({ 0: 'foo', length: 1 }) // false - */ -var isArray = Array.isArray || function isArray(value) { - Object.prototype.toString.call(value) === "[object Array]"; -} -exports.isArray = isArray; - -/** - * Returns `true` if `value` is an Arguments object. - * @examples - * (function(){ return isArguments(arguments); })(1, 2, 3); // true - * isArguments([1,2,3]); // false - */ -function isArguments(value) { - Object.prototype.toString.call(value) === "[object Arguments]"; -} -exports.isArguments = isArguments; - -/** - * Returns true if it is a primitive `value`. (null, undefined, number, - * boolean, string) - * @examples - * isPrimitive(3) // true - * isPrimitive('foo') // true - * isPrimitive({ bar: 3 }) // false - */ -function isPrimitive(value) { - return !isFunction(value) && !isObject(value); -} -exports.isPrimitive = isPrimitive; - -/** - * Returns `true` if given `object` is flat (it is direct decedent of - * `Object.prototype` or `null`). - * @examples - * isFlat({}) // true - * isFlat(new Type()) // false - */ -function isFlat(object) { - return isObject(object) && (isNull(Object.getPrototypeOf(object)) || - isNull(Object.getPrototypeOf( - Object.getPrototypeOf(object)))); -} -exports.isFlat = isFlat; - -/** - * Returns `true` if object contains no values. - */ -function isEmpty(object) { - if (isObject(object)) { - for (var key in object) - return false; - return true; - } - return false; -} -exports.isEmpty = isEmpty; - -/** - * Returns `true` if `value` is an array / flat object containing only atomic - * values and other flat objects. - */ -function isJSON(value, visited) { - // Adding value to array of visited values. - (visited || (visited = [])).push(value); - // If `value` is an atom return `true` cause it's valid JSON. - return isPrimitive(value) || - // If `value` is an array of JSON values that has not been visited - // yet. - (isArray(value) && value.every(function(element) { - return isJSON(element, visited); - })) || - // If `value` is a plain object containing properties with a JSON - // values it's a valid JSON. - (isFlat(value) && Object.keys(value).every(function(key) { - var $ = Object.getOwnPropertyDescriptor(value, key); - // Check every proprety of a plain object to verify that - // it's neither getter nor setter, but a JSON value, that - // has not been visited yet. - return ((!isObject($.value) || !~visited.indexOf($.value)) && - !('get' in $) && !('set' in $) && - isJSON($.value, visited)); - })); -} -exports.isJSON = function (value) { - return isJSON(value); -}; - -/** - * Returns if `value` is an instance of a given `Type`. This is exactly same as - * `value instanceof Type` with a difference that `Type` can be from a scope - * that has a different top level object. (Like in case where `Type` is a - * function from different iframe / jetpack module / sandbox). - */ -function instanceOf(value, Type) { - var isConstructorNameSame; - var isConstructorSourceSame; - - // If `instanceof` returned `true` we know result right away. - var isInstanceOf = value instanceof Type; - - // If `instanceof` returned `false` we do ducktype check since `Type` may be - // from a different sandbox. If a constructor of the `value` or a constructor - // of the value's prototype has same name and source we assume that it's an - // instance of the Type. - if (!isInstanceOf && value) { - isConstructorNameSame = value.constructor.name === Type.name; - isConstructorSourceSame = String(value.constructor) == String(Type); - isInstanceOf = (isConstructorNameSame && isConstructorSourceSame) || - instanceOf(Object.getPrototypeOf(value), Type); - } - return isInstanceOf; -} -exports.instanceOf = instanceOf; - -/** - * Function returns textual representation of a value passed to it. Function - * takes additional `indent` argument that is used for indentation. Also - * optional `limit` argument may be passed to limit amount of detail returned. - * @param {Object} value - * @param {String} [indent=" "] - * @param {Number} [limit] - */ -function source(value, indent, limit, offset, visited) { - var result; - var names; - var nestingIndex; - var isCompact = !isUndefined(limit); - - indent = indent || " "; - offset = (offset || ""); - result = ""; - visited = visited || []; - - if (isUndefined(value)) { - result += "undefined"; - } - else if (isNull(value)) { - result += "null"; - } - else if (isString(value)) { - result += '"' + value + '"'; - } - else if (isFunction(value)) { - value = String(value).split("\n"); - if (isCompact && value.length > 2) { - value = value.splice(0, 2); - value.push("...}"); - } - result += value.join("\n" + offset); - } - else if (isArray(value)) { - if ((nestingIndex = (visited.indexOf(value) + 1))) { - result = "#" + nestingIndex + "#"; - } - else { - visited.push(value); - - if (isCompact) - value = value.slice(0, limit); - - result += "[\n"; - result += value.map(function(value) { - return offset + indent + source(value, indent, limit, offset + indent, - visited); - }).join(",\n"); - result += isCompact && value.length > limit ? - ",\n" + offset + "...]" : "\n" + offset + "]"; - } - } - else if (isObject(value)) { - if ((nestingIndex = (visited.indexOf(value) + 1))) { - result = "#" + nestingIndex + "#" - } - else { - visited.push(value) - - names = Object.keys(value); - - result += "{ // " + value + "\n"; - result += (isCompact ? names.slice(0, limit) : names).map(function(name) { - var _limit = isCompact ? limit - 1 : limit; - var descriptor = Object.getOwnPropertyDescriptor(value, name); - var result = offset + indent + "// "; - var accessor; - if (0 <= name.indexOf(" ")) - name = '"' + name + '"'; - - if (descriptor.writable) - result += "writable "; - if (descriptor.configurable) - result += "configurable "; - if (descriptor.enumerable) - result += "enumerable "; - - result += "\n"; - if ("value" in descriptor) { - result += offset + indent + name + ": "; - result += source(descriptor.value, indent, _limit, indent + offset, - visited); - } - else { - - if (descriptor.get) { - result += offset + indent + "get " + name + " "; - accessor = source(descriptor.get, indent, _limit, indent + offset, - visited); - result += accessor.substr(accessor.indexOf("{")); - } - - if (descriptor.set) { - result += offset + indent + "set " + name + " "; - accessor = source(descriptor.set, indent, _limit, indent + offset, - visited); - result += accessor.substr(accessor.indexOf("{")); - } - } - return result; - }).join(",\n"); - - if (isCompact) { - if (names.length > limit && limit > 0) { - result += ",\n" + offset + indent + "//..."; - } - } - else { - if (names.length) - result += ","; - - result += "\n" + offset + indent + '"__proto__": '; - result += source(Object.getPrototypeOf(value), indent, 0, - offset + indent); - } - - result += "\n" + offset + "}"; - } - } - else { - result += String(value); - } - return result; -} -exports.source = function (value, indentation, limit) { - return source(value, indentation, limit); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test-finder.js b/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test-finder.js deleted file mode 100644 index a8dc14a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test-finder.js +++ /dev/null @@ -1,106 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const file = require("./file"); -const packaging = require('@packaging'); -const suites = packaging.allTestModules; - -const NOT_TESTS = ['setup', 'teardown']; - -var TestFinder = exports.TestFinder = function TestFinder(options) { - memory.track(this); - this.filter = options.filter; - this.testInProcess = options.testInProcess === false ? false : true; - this.testOutOfProcess = options.testOutOfProcess === true ? true : false; -}; - -TestFinder.prototype = { - _makeTest: function _makeTest(suite, name, test) { - function runTest(runner) { - console.info("executing '" + suite + "." + name + "'"); - test(runner); - } - return runTest; - }, - - findTests: function findTests(cb) { - var self = this; - var tests = []; - var filter; - // A filter string is {fileNameRegex}[:{testNameRegex}] - ie, a colon - // optionally separates a regex for the test fileName from a regex for the - // testName. - if (this.filter) { - var colonPos = this.filter.indexOf(':'); - var filterFileRegex, filterNameRegex; - if (colonPos === -1) { - filterFileRegex = new RegExp(self.filter); - } else { - filterFileRegex = new RegExp(self.filter.substr(0, colonPos)); - filterNameRegex = new RegExp(self.filter.substr(colonPos + 1)); - } - // This function will first be called with just the filename; if - // it returns true the module will be loaded then the function - // called again with both the filename and the testname. - filter = function(filename, testname) { - return filterFileRegex.test(filename) && - ((testname && filterNameRegex) ? filterNameRegex.test(testname) - : true); - }; - } else - filter = function() {return true}; - - suites.forEach( - function(suite) { - var module = require(suite); - if (self.testInProcess) - for each (let name in Object.keys(module).sort()) { - if(NOT_TESTS.indexOf(name) === -1 && filter(suite, name)) { - tests.push({ - setup: module.setup, - teardown: module.teardown, - testFunction: self._makeTest(suite, name, module[name]), - name: suite + "." + name - }); - } - } - }); - - cb(tests); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test.js b/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test.js deleted file mode 100644 index 4b3ac89..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/unit-test.js +++ /dev/null @@ -1,466 +0,0 @@ -/* vim:st=2:sts=2:sw=2: - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; -var timer = require("./timer"); - -exports.findAndRunTests = function findAndRunTests(options) { - var TestFinder = require("./unit-test-finder").TestFinder; - var finder = new TestFinder({ - filter: options.filter, - testInProcess: options.testInProcess, - testOutOfProcess: options.testOutOfProcess - }); - var runner = new TestRunner({fs: options.fs}); - finder.findTests( - function (tests) { - runner.startMany({tests: tests, - onDone: options.onDone}); - }); -}; - -var TestRunner = exports.TestRunner = function TestRunner(options) { - if (options) { - this.fs = options.fs; - } - this.console = (options && "console" in options) ? options.console : console; - memory.track(this); - this.passed = 0; - this.failed = 0; - this.testRunSummary = []; - this.expectFailNesting = 0; -}; - -TestRunner.prototype = { - toString: function toString() "[object TestRunner]", - - DEFAULT_PAUSE_TIMEOUT: 10000, - PAUSE_DELAY: 500, - - _logTestFailed: function _logTestFailed(why) { - this.test.errors[why]++; - if (!this.testFailureLogged) { - this.console.error("TEST FAILED: " + this.test.name + " (" + why + ")"); - this.testFailureLogged = true; - } - }, - - pass: function pass(message) { - if(!this.expectFailure) { - this.console.info("pass:", message); - this.passed++; - this.test.passed++; - } - else { - this.expectFailure = false; - this.fail('Failure Expected: ' + message); - } - }, - - fail: function fail(message) { - if(!this.expectFailure) { - this._logTestFailed("failure"); - this.console.error("fail:", message); - this.console.trace(); - this.failed++; - this.test.failed++; - } - else { - this.expectFailure = false; - this.pass(message); - } - }, - - expectFail: function(callback) { - this.expectFailure = true; - callback(); - this.expectFailure = false; - }, - - exception: function exception(e) { - this._logTestFailed("exception"); - this.console.exception(e); - this.failed++; - this.test.failed++; - }, - - assertMatches: function assertMatches(string, regexp, message) { - if (regexp.test(string)) { - if (!message) - message = uneval(string) + " matches " + uneval(regexp); - this.pass(message); - } else { - var no = uneval(string) + " doesn't match " + uneval(regexp); - if (!message) - message = no; - else - message = message + " (" + no + ")"; - this.fail(message); - } - }, - - assertRaises: function assertRaises(func, predicate, message) { - try { - func(); - if (message) - this.fail(message + " (no exception thrown)"); - else - this.fail("function failed to throw exception"); - } catch (e) { - var errorMessage; - if (typeof(e) == "string") - errorMessage = e; - else - errorMessage = e.message; - if (typeof(predicate) == "string") - this.assertEqual(errorMessage, predicate, message); - else - this.assertMatches(errorMessage, predicate, message); - } - }, - - assert: function assert(a, message) { - if (!a) { - if (!message) - message = "assertion failed, value is " + a; - this.fail(message); - } else - this.pass(message || "assertion successful"); - }, - - assertNotEqual: function assertNotEqual(a, b, message) { - if (a != b) { - if (!message) - message = "a != b != " + uneval(a); - this.pass(message); - } else { - var equality = uneval(a) + " == " + uneval(b); - if (!message) - message = equality; - else - message += " (" + equality + ")"; - this.fail(message); - } - }, - - assertEqual: function assertEqual(a, b, message) { - if (a == b) { - if (!message) - message = "a == b == " + uneval(a); - this.pass(message); - } else { - var inequality = uneval(a) + " != " + uneval(b); - if (!message) - message = inequality; - else - message += " (" + inequality + ")"; - this.fail(message); - } - }, - - assertNotStrictEqual: function assertNotStrictEqual(a, b, message) { - if (a !== b) { - if (!message) - message = "a !== b !== " + uneval(a); - this.pass(message); - } else { - var equality = uneval(a) + " === " + uneval(b); - if (!message) - message = equality; - else - message += " (" + equality + ")"; - this.fail(message); - } - }, - - assertStrictEqual: function assertStrictEqual(a, b, message) { - if (a === b) { - if (!message) - message = "a === b === " + uneval(a); - this.pass(message); - } else { - var inequality = uneval(a) + " !== " + uneval(b); - if (!message) - message = inequality; - else - message += " (" + inequality + ")"; - this.fail(message); - } - }, - - assertFunction: function assertFunction(a, message) { - this.assertStrictEqual('function', typeof a, message); - }, - - assertUndefined: function(a, message) { - this.assertStrictEqual('undefined', typeof a, message); - }, - - assertNotUndefined: function(a, message) { - this.assertNotStrictEqual('undefined', typeof a, message); - }, - - assertNull: function(a, message) { - this.assertStrictEqual(null, a, message); - }, - - assertNotNull: function(a, message) { - this.assertNotStrictEqual(null, a, message); - }, - - assertObject: function(a, message) { - this.assertStrictEqual('[object Object]', Object.prototype.toString.apply(a), message); - }, - - assertString: function(a, message) { - this.assertStrictEqual('[object String]', Object.prototype.toString.apply(a), message); - }, - - assertArray: function(a, message) { - this.assertStrictEqual('[object Array]', Object.prototype.toString.apply(a), message); - }, - - assertNumber: function(a, message) { - this.assertStrictEqual('[object Number]', Object.prototype.toString.apply(a), message); - }, - - done: function done() { - if (!this.isDone) { - this.isDone = true; - if(this.test.teardown) { - this.test.teardown(this); - } - if (this.waitTimeout !== null) { - timer.clearTimeout(this.waitTimeout); - this.waitTimeout = null; - } - if (this.test.passed == 0 && this.test.failed == 0) { - this._logTestFailed("empty test"); - this.failed++; - this.test.failed++; - } - - this.testRunSummary.push({ - name: this.test.name, - passed: this.test.passed, - failed: this.test.failed, - errors: [error for (error in this.test.errors)].join(", ") - }); - - if (this.onDone !== null) { - var onDone = this.onDone; - var self = this; - this.onDone = null; - timer.setTimeout(function() { onDone(self); }, 0); - } - } - }, - - // Set of assertion functions to wait for an assertion to become true - // These functions take the same arguments as the TestRunner.assert* methods. - waitUntil: function waitUntil() { - return this._waitUntil(this.assert, arguments); - }, - - waitUntilNotEqual: function waitUntilNotEqual() { - return this._waitUntil(this.assertNotEqual, arguments); - }, - - waitUntilEqual: function waitUntilEqual() { - return this._waitUntil(this.assertEqual, arguments); - }, - - waitUntilMatches: function waitUntilMatches() { - return this._waitUntil(this.assertMatches, arguments); - }, - - /** - * Internal function that waits for an assertion to become true. - * @param {Function} assertionMethod - * Reference to a TestRunner assertion method like test.assert, - * test.assertEqual, ... - * @param {Array} args - * List of arguments to give to the previous assertion method. - * All functions in this list are going to be called to retrieve current - * assertion values. - */ - _waitUntil: function waitUntil(assertionMethod, args) { - let count = 0; - let maxCount = this.DEFAULT_PAUSE_TIMEOUT / this.PAUSE_DELAY; - - // We need to ensure that test is asynchronous - if (!this.waitTimeout) - this.waitUntilDone(this.DEFAULT_PAUSE_TIMEOUT); - - let callback = null; - let finished = false; - - let test = this; - - // capture a traceback before we go async. - let traceback = require("./traceback"); - let stack = traceback.get(); - stack.splice(-2, 2); - let currentWaitStack = traceback.format(stack); - let timeout = null; - - function loop(stopIt) { - timeout = null; - - // Build a mockup object to fake TestRunner API and intercept calls to - // pass and fail methods, in order to retrieve nice error messages - // and assertion result - let mock = { - pass: function (msg) { - test.pass(msg); - test.waitUntilCallback = null; - if (callback && !stopIt) - callback(); - finished = true; - }, - fail: function (msg) { - // If we are called on test timeout, we stop the loop - // and print which test keeps failing: - if (stopIt) { - test.console.error("test assertion never became true:\n", - msg + "\n", - currentWaitStack); - if (timeout) - timer.clearTimeout(timeout); - return; - } - timeout = timer.setTimeout(loop, test.PAUSE_DELAY); - } - }; - - // Automatically call args closures in order to build arguments for - // assertion function - let appliedArgs = []; - for (let i = 0, l = args.length; i < l; i++) { - let a = args[i]; - if (typeof a == "function") { - try { - a = a(); - } - catch(e) { - test.fail("Exception when calling asynchronous assertion: " + e); - finished = true; - return; - } - } - appliedArgs.push(a); - } - - // Finally call assertion function with current assertion values - assertionMethod.apply(mock, appliedArgs); - } - loop(); - this.waitUntilCallback = loop; - - // Return an object with `then` method, to offer a way to execute - // some code when the assertion passed or failed - return { - then: function (c) { - callback = c; - - // In case of immediate positive result, we need to execute callback - // immediately here: - if (finished) - callback(); - } - }; - }, - - waitUntilDone: function waitUntilDone(ms) { - if (ms === undefined) - ms = this.DEFAULT_PAUSE_TIMEOUT; - - var self = this; - - function tiredOfWaiting() { - self._logTestFailed("timed out"); - if (self.waitUntilCallback) { - self.waitUntilCallback(true); - self.waitUntilCallback = null; - } - self.failed++; - self.test.failed++; - self.done(); - } - - // We may already have registered a timeout callback - if (this.waitTimeout) - timer.clearTimeout(this.waitTimeout); - - this.waitTimeout = timer.setTimeout(tiredOfWaiting, ms); - }, - - startMany: function startMany(options) { - function runNextTest(self) { - var test = options.tests.shift(); - if (test) - self.start({test: test, onDone: runNextTest}); - else - options.onDone(self); - } - runNextTest(this); - }, - - start: function start(options) { - this.test = options.test; - this.test.passed = 0; - this.test.failed = 0; - this.test.errors = {}; - - this.isDone = false; - this.onDone = options.onDone; - this.waitTimeout = null; - this.testFailureLogged = false; - - try { - if(this.test.setup) { - this.test.setup(this); - } - this.test.testFunction(this); - } catch (e) { - this.exception(e); - } - if (this.waitTimeout === null) - this.done(); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/unload.js b/tools/addon-sdk-1.4/packages/api-utils/lib/unload.js deleted file mode 100644 index 3bbeb38..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/unload.js +++ /dev/null @@ -1,59 +0,0 @@ -// Parts of this module were taken from narwhal: -// -// http://narwhaljs.org - -var observers = []; -var unloaders = []; - -var when = exports.when = function when(observer) { - if (observers.indexOf(observer) != -1) - return; - observers.unshift(observer); -}; - -var send = exports.send = function send(reason, onError) { - onError = onError || console.exception; - observers.forEach(function (observer) { - try { - observer(reason); - } catch (e) { - onError(e); - } - }); -}; - -var ensure = exports.ensure = function ensure(obj, destructorName) { - if (!destructorName) - destructorName = "unload"; - if (!(destructorName in obj)) - throw new Error("object has no '" + destructorName + "' property"); - - let called = false; - let originalDestructor = obj[destructorName]; - - function unloadWrapper(reason) { - if (!called) { - called = true; - let index = unloaders.indexOf(unloadWrapper); - if (index == -1) - throw new Error("internal error: unloader not found"); - unloaders.splice(index, 1); - originalDestructor.call(obj, reason); - originalDestructor = null; - destructorName = null; - obj = null; - } - }; - - unloaders.push(unloadWrapper); - - obj[destructorName] = unloadWrapper; -}; - -when( - function(reason) { - unloaders.slice().forEach( - function(unloadWrapper) { - unloadWrapper(reason); - }); - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/url.js b/tools/addon-sdk-1.4/packages/api-utils/lib/url.js deleted file mode 100644 index 4502129..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/url.js +++ /dev/null @@ -1,123 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,Cr} = require("chrome"); - -var ios = Cc['@mozilla.org/network/io-service;1'] - .getService(Ci.nsIIOService); - -var resProt = ios.getProtocolHandler("resource") - .QueryInterface(Ci.nsIResProtocolHandler); - -function newURI(uriStr, base) { - try { - let baseURI = base ? ios.newURI(base, null, null) : null; - return ios.newURI(uriStr, null, baseURI); - } - catch (e if e.result == Cr.NS_ERROR_MALFORMED_URI) { - throw new Error("malformed URI: " + uriStr); - } - catch (e if (e.result == Cr.NS_ERROR_FAILURE || - e.result == Cr.NS_ERROR_ILLEGAL_VALUE)) { - throw new Error("invalid URI: " + uriStr); - } -} - -function resolveResourceURI(uri) { - var resolved; - try { - resolved = resProt.resolveURI(uri); - } catch (e if e.result == Cr.NS_ERROR_NOT_AVAILABLE) { - throw new Error("resource does not exist: " + uri.spec); - }; - return resolved; -} - -let fromFilename = exports.fromFilename = function fromFilename(path) { - var file = Cc['@mozilla.org/file/local;1'] - .createInstance(Ci.nsILocalFile); - file.initWithPath(path); - return ios.newFileURI(file).spec; -}; - -let toFilename = exports.toFilename = function toFilename(url) { - var uri = newURI(url); - if (uri.scheme == "resource") - uri = newURI(resolveResourceURI(uri)); - if (uri.scheme == "chrome") { - var channel = ios.newChannelFromURI(uri); - try { - channel = channel.QueryInterface(Ci.nsIFileChannel); - return channel.file.path; - } catch (e if e.result == Cr.NS_NOINTERFACE) { - throw new Error("chrome url isn't on filesystem: " + url); - } - } - if (uri.scheme == "file") { - var file = uri.QueryInterface(Ci.nsIFileURL).file; - return file.path; - } - throw new Error("cannot map to filename: " + url); -}; - -function URL(url, base) { - var uri = newURI(url, base); - - var userPass = null; - try { - userPass = uri.userPass ? uri.userPass : null; - } catch (e if e.result == Cr.NS_ERROR_FAILURE) {} - - var host = null; - try { - host = uri.host; - } catch (e if e.result == Cr.NS_ERROR_FAILURE) {} - - var port = null; - try { - port = uri.port == -1 ? null : uri.port; - } catch (e if e.result == Cr.NS_ERROR_FAILURE) {} - - this.__defineGetter__("scheme", function() uri.scheme); - this.__defineGetter__("userPass", function() userPass); - this.__defineGetter__("host", function() host); - this.__defineGetter__("port", function() port); - this.__defineGetter__("path", function() uri.path); - this.toString = function URL_toString() uri.spec; -}; -exports.URL = require("./api-utils").publicConstructor(URL); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/data.js b/tools/addon-sdk-1.4/packages/api-utils/lib/utils/data.js deleted file mode 100644 index bf621ad..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/data.js +++ /dev/null @@ -1,104 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci, Cu } = require("chrome"); -const IOService = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); -const AppShellService = Cc["@mozilla.org/appshell/appShellService;1"]. - getService(Ci.nsIAppShellService); - -const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm"); -const FaviconService = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); - -const PNG_B64 = "data:image/png;base64,"; -const DEF_FAVICON_URI = "chrome://mozapps/skin/places/defaultFavicon.png"; -let DEF_FAVICON = null; - -/** - * Takes URI of the page and returns associated favicon URI. - * If page under passed uri has no favicon then base64 encoded data URI of - * default faveicon is returned. - * @param {String} uri - * @returns {String} - */ -exports.getFaviconURIForLocation = function getFaviconURIForLocation(uri) { - let pageURI = NetUtil.newURI(uri); - try { - return FaviconService.getFaviconDataAsDataURL( - FaviconService.getFaviconForPage(pageURI)); - } - catch(e) { - if (!DEF_FAVICON) { - DEF_FAVICON = PNG_B64 + - base64Encode(getChromeURIContent(DEF_FAVICON_URI)); - } - return DEF_FAVICON; - } -} - -/** - * Takes chrome URI and returns content under that URI. - * @param {String} chromeURI - * @returns {String} - */ -function getChromeURIContent(chromeURI) { - let channel = IOService.newChannel(chromeURI, null, null); - let input = channel.open(); - let stream = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - stream.setInputStream(input); - let content = stream.readBytes(input.available()); - stream.close(); - input.close(); - return content; -} -exports.getChromeURIContent = getChromeURIContent; - -/** - * Creates a base-64 encoded ASCII string from a string of binary data. - */ -function base64Encode(data) AppShellService.hiddenDOMWindow.btoa(String(data)); -exports.base64Encode = base64Encode; - -/** - * Decodes a string of data which has been encoded using base-64 encoding. - */ -function base64Decode(data) AppShellService.hiddenDOMWindow.atob(String(data)); -exports.base64Decode = base64Decode; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/function.js b/tools/addon-sdk-1.4/packages/api-utils/lib/utils/function.js deleted file mode 100644 index ba43d59..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/function.js +++ /dev/null @@ -1,64 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -var { setTimeout } = require("../timer"); - -/** - * Takes a function and returns a wrapped one instead, calling which will call - * original function in the next turn of event loop. This is basically utility - * to do `setTimeout(function() { ... }, 0)`, with a difference that returned - * function is reused, instead of creating a new one each time. This also allows - * to use this functions as event listeners. - */ -function Enqueued(callee) { - return function enqueued() - setTimeout(invoke, 0, callee, arguments, this); -} -exports.Enqueued = Enqueued; - -/** - * Invokes `callee` by passing `params` as an arguments and `self` as `this` - * pseudo-variable. Returns value that is returned by a callee. - * @param {Function} callee - * Function to invoke. - * @param {Array} params - * Arguments to invoke function with. - * @param {Object} self - * Object to be passed as a `this` pseudo variable. - */ -function invoke(callee, params, self) callee.apply(self, params); -exports.invoke = invoke; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/registry.js b/tools/addon-sdk-1.4/packages/api-utils/lib/utils/registry.js deleted file mode 100644 index 6cd11b2..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/registry.js +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { EventEmitter } = require('../events'); -const unload = require('../unload'); - -const Registry = EventEmitter.compose({ - _registry: null, - _constructor: null, - constructor: function Registry(constructor) { - this._registry = []; - this._constructor = constructor; - this.on('error', this._onError = this._onError.bind(this)); - unload.ensure(this, "_destructor"); - }, - _destructor: function _destructor() { - let _registry = this._registry.slice(0); - for each (let instance in _registry) - this._emit('remove', instance); - this._registry.splice(0); - }, - _onError: function _onError(e) { - if (!this._listeners('error').length) - console.error(e); - }, - has: function has(instance) { - let _registry = this._registry; - return ( - (0 <= _registry.indexOf(instance)) || - (instance && instance._public && 0 <= _registry.indexOf(instance._public)) - ); - }, - add: function add(instance) { - let { _constructor, _registry } = this; - if (!(instance instanceof _constructor)) - instance = new _constructor(instance); - if (0 > _registry.indexOf(instance)) { - _registry.push(instance); - this._emit('add', instance); - } - return instance; - }, - remove: function remove(instance) { - let _registry = this._registry; - let index = _registry.indexOf(instance) - if (0 <= index) { - this._emit('remove', instance); - _registry.splice(index, 1); - } - } -}); -exports.Registry = Registry; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/thumbnail.js b/tools/addon-sdk-1.4/packages/api-utils/lib/utils/thumbnail.js deleted file mode 100644 index d9012e1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/utils/thumbnail.js +++ /dev/null @@ -1,76 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci, Cu } = require("chrome"); -const AppShellService = Cc["@mozilla.org/appshell/appShellService;1"]. - getService(Ci.nsIAppShellService); - -const NS = "http://www.w3.org/1999/xhtml"; -const COLOR = "rgb(255,255,255)"; - -/** - * Creates canvas element with a thumbnail of the passed window. - * @param {Window} window - * @returns {Element} - */ -function getThumbnailCanvasForWindow(window) { - let aspectRatio = 0.5625; // 16:9 - let thumbnail = AppShellService.hiddenDOMWindow.document - .createElementNS(NS, "canvas"); - thumbnail.mozOpaque = true; - thumbnail.width = Math.ceil(window.screen.availWidth / 5.75); - thumbnail.height = Math.round(thumbnail.width * aspectRatio); - let ctx = thumbnail.getContext("2d"); - let snippetWidth = window.innerWidth * .6; - let scale = thumbnail.width / snippetWidth; - ctx.scale(scale, scale); - ctx.drawWindow(window, window.scrollX, window.scrollY, snippetWidth, - snippetWidth * aspectRatio, COLOR); - return thumbnail; -} -exports.getThumbnailCanvasForWindow = getThumbnailCanvasForWindow; - -/** - * Creates Base64 encoded data URI of the thumbnail for the passed window. - * @param {Window} window - * @returns {String} - */ -exports.getThumbnailURIForWindow = function getThumbnailURIForWindow(window) { - return getThumbnailCanvasForWindow(window).toDataURL() -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/window-utils.js b/tools/addon-sdk-1.4/packages/api-utils/lib/window-utils.js deleted file mode 100644 index 2d123a8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/window-utils.js +++ /dev/null @@ -1,270 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc, Ci } = require("chrome"); -const { EventEmitter } = require('./events'), - { Trait } = require('./traits'); -const errors = require("./errors"); - -const gWindowWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); -const appShellService = Cc["@mozilla.org/appshell/appShellService;1"]. - getService(Ci.nsIAppShellService); - -const XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; - -/** - * An iterator for XUL windows currently in the application. - * - * @return A generator that yields XUL windows exposing the - * nsIDOMWindow interface. - */ -var windowIterator = exports.windowIterator = function windowIterator() { - let winEnum = gWindowWatcher.getWindowEnumerator(); - while (winEnum.hasMoreElements()) - yield winEnum.getNext().QueryInterface(Ci.nsIDOMWindow); -}; - -/** - * An iterator for browser windows currently open in the application. - * @returns {Function} - * A generator that yields browser windows exposing the `nsIDOMWindow` - * interface. - */ -function browserWindowIterator() { - for each (let window in windowIterator()) { - if (isBrowser(window)) - yield window; - } -} -exports.browserWindowIterator = browserWindowIterator; - -var WindowTracker = exports.WindowTracker = function WindowTracker(delegate) { - this.delegate = delegate; - this._loadingWindows = []; - for (let window in windowIterator()) - this._regWindow(window); - gWindowWatcher.registerNotification(this); - require("./unload").ensure(this); -}; - -WindowTracker.prototype = { - _regLoadingWindow: function _regLoadingWindow(window) { - this._loadingWindows.push(window); - window.addEventListener("load", this, true); - }, - - _unregLoadingWindow: function _unregLoadingWindow(window) { - var index = this._loadingWindows.indexOf(window); - - if (index != -1) { - this._loadingWindows.splice(index, 1); - window.removeEventListener("load", this, true); - } - }, - - _regWindow: function _regWindow(window) { - if (window.document.readyState == "complete") { - this._unregLoadingWindow(window); - this.delegate.onTrack(window); - } else - this._regLoadingWindow(window); - }, - - _unregWindow: function _unregWindow(window) { - if (window.document.readyState == "complete") { - if (this.delegate.onUntrack) - this.delegate.onUntrack(window); - } else { - this._unregLoadingWindow(window); - } - }, - - unload: function unload() { - gWindowWatcher.unregisterNotification(this); - for (let window in windowIterator()) - this._unregWindow(window); - }, - - handleEvent: function handleEvent(event) { - if (event.type == "load" && event.target) { - var window = event.target.defaultView; - if (window) - this._regWindow(window); - } - }, - - observe: function observe(subject, topic, data) { - var window = subject.QueryInterface(Ci.nsIDOMWindow); - if (topic == "domwindowopened") - this._regWindow(window); - else - this._unregWindow(window); - } -}; - -errors.catchAndLogProps(WindowTracker.prototype, ["handleEvent", "observe"]); - -const WindowTrackerTrait = Trait.compose({ - _onTrack: Trait.required, - _onUntrack: Trait.required, - constructor: function WindowTrackerTrait() { - new WindowTracker({ - onTrack: this._onTrack.bind(this), - onUntrack: this._onUntrack.bind(this) - }); - } -}); -exports.WindowTrackerTrait = WindowTrackerTrait; - -var gDocsToClose = []; - -function onDocUnload(event) { - var index = gDocsToClose.indexOf(event.target); - if (index == -1) - throw new Error("internal error: unloading document not found"); - var document = gDocsToClose.splice(index, 1)[0]; - // Just in case, let's remove the event listener too. - document.defaultView.removeEventListener("unload", onDocUnload, false); -} - -onDocUnload = require("./errors").catchAndLog(onDocUnload); - -exports.closeOnUnload = function closeOnUnload(window) { - window.addEventListener("unload", onDocUnload, false); - gDocsToClose.push(window.document); -}; - -exports.__defineGetter__("activeWindow", function() { - return Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getMostRecentWindow(null); -}); -exports.__defineSetter__("activeWindow", function(window) { - try { - window.focus(); - } - catch (e) { } -}); - -exports.__defineGetter__("activeBrowserWindow", function() { - return Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getMostRecentWindow("navigator:browser"); -}); - -/** - * Returns the ID of the window's current inner window. - */ -exports.getInnerId = function getInnerId(window) { - return window.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; -}; - -/** - * Returns the ID of the window's outer window. - */ -exports.getOuterId = function getOuterId(window) { - return window.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils).outerWindowID; -}; - -function isBrowser(window) { - return window.document.documentElement.getAttribute("windowtype") === - "navigator:browser"; -}; -exports.isBrowser = isBrowser; - -exports.hiddenWindow = appShellService.hiddenDOMWindow; - -function createHiddenXULFrame() { - return function promise(deliver) { - let window = appShellService.hiddenDOMWindow; - let document = window.document; - let isXMLDoc = (document.contentType == "application/xhtml+xml" || - document.contentType == "application/vnd.mozilla.xul+xml") - - if (isXMLDoc) { - deliver(window) - } - else { - let frame = document.createElement('iframe'); - // This is ugly but we need window for XUL document in order to create - // browser elements. - frame.setAttribute('src', 'chrome://browser/content/hiddenWindow.xul'); - frame.addEventListener('DOMContentLoaded', function onLoad(event) { - frame.removeEventListener('DOMContentLoaded', onLoad, false); - deliver(frame.contentWindow); - }, false); - document.documentElement.appendChild(frame); - } - } -}; -exports.createHiddenXULFrame = createHiddenXULFrame; - -exports.createRemoteBrowser = function createRemoteBrowser(remote) { - return function promise(deliver) { - createHiddenXULFrame()(function(hiddenWindow) { - let document = hiddenWindow.document; - let browser = document.createElementNS(XUL, "browser"); - // Remote="true" enable everything here: - // http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsFrameLoader.cpp#1347 - if (remote !== false) - browser.setAttribute("remote","true"); - // Type="content" is mandatory to enable stuff here: - // http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsFrameLoader.cpp#1776 - browser.setAttribute("type","content"); - // We remove XBL binding to avoid execution of code that is not going to work - // because browser has no docShell attribute in remote mode (for example) - browser.setAttribute("style","-moz-binding: none;"); - // Flex it in order to be visible (optional, for debug purpose) - browser.setAttribute("flex", "1"); - document.documentElement.appendChild(browser); - - // Return browser - deliver(browser); - }); - }; -}; - -require("./unload").when( - function() { - gDocsToClose.slice().forEach( - function(doc) { doc.defaultView.close(); }); - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/dom.js b/tools/addon-sdk-1.4/packages/api-utils/lib/windows/dom.js deleted file mode 100644 index d74e314..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/dom.js +++ /dev/null @@ -1,60 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -'use strict'; - -const { Trait } = require('../traits'); - -const WindowDom = Trait.compose({ - _window: Trait.required, - get title() { - let window = this._window; - return window && window.document ? window.document.title : null - }, - close: function close() { - let window = this._window; - if (window) window.close(); - return this._public; - }, - activate: function activate() { - let window = this._window; - if (window) window.focus(); - return this._public; - } -}); -exports.WindowDom = WindowDom; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/loader.js b/tools/addon-sdk-1.4/packages/api-utils/lib/windows/loader.js deleted file mode 100644 index 6b43fb6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/loader.js +++ /dev/null @@ -1,152 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Cc, Ci } = require('chrome'), - { setTimeout } = require("../timer"), - { Trait } = require('../traits'), - - WM = Cc['@mozilla.org/appshell/window-mediator;1']. - getService(Ci.nsIWindowMediator), - - URI_BROWSER = 'chrome://browser/content/browser.xul', - NAME = '_blank', - FEATURES = 'chrome,all,dialog=no', - PARAMS = [ URI_BROWSER, NAME, FEATURES ], - ON_LOAD = 'load', - ON_UNLOAD = 'unload', - STATE_LOADED = 'complete', - BROWSER = 'navigator:browser'; - -/** - * Trait provides private `_window` property and requires `_onLoad` property - * that will be called when `_window` is loaded. If `_window` property value - * is changed with already loaded window `_onLoad` still will be called. - */ -const WindowLoader = Trait.compose({ - /** - * Internal listener that is called when window is loaded. - * Please keep in mind that this trait will not handle exceptions that may - * be thrown by this method so method itself should take care of - * handling them. - * @param {nsIWindow} window - */ - _onLoad: Trait.required, - _tabOptions: Trait.required, - /** - * Internal listener that is called when `_window`'s DOM 'unload' event - * is dispatched. Please note that this trait will not handle exceptions that - * may be thrown by this method so method itself should take care of - * handling them. - */ - _onUnload: Trait.required, - _load: function _load() { - if (this.__window) return; - let params = PARAMS.slice() - params.push(this._tabOptions.map(function(options) options.url).join("|")) - let browser = WM.getMostRecentWindow(BROWSER); - this._window = browser.openDialog.apply(browser, params); - }, - /** - * Private window who's load event is being tracked. Once window is loaded - * `_onLoad` is called. - * @type {nsIWindow} - */ - get _window() this.__window, - set _window(window) { - let _window = this.__window; - if (!window) window = null; - if (window !== _window) { - if (_window) { - _window.removeEventListener(ON_UNLOAD, this.__unloadListener, false); - _window.removeEventListener(ON_LOAD, this.__loadListener, false); - } - if (window) { - window.addEventListener( - ON_UNLOAD, - this.__unloadListener || - (this.__unloadListener = this._unloadListener.bind(this)) - , - false - ); - this.__window = window; - // If window is not loaded yet setting up a listener. - if (STATE_LOADED != window.document.readyState) { - window.addEventListener( - ON_LOAD, - this.__loadListener || - (this.__loadListener = this._loadListener.bind(this)) - , - false - ); - } - else { // If window is loaded calling listener next turn of event loop. - this._onLoad(window) - } - } - } - }, - __window: null, - /** - * Internal method used for listening 'load' event on the `_window`. - * Method takes care of removing itself from 'load' event listeners once - * event is being handled. - */ - _loadListener: function _loadListener(event) { - let window = this._window; - if (!event.target || event.target.defaultView != window) return; - window.removeEventListener(ON_LOAD, this.__loadListener, false); - this._onLoad(window); - }, - __loadListener: null, - /** - * Internal method used for listening 'unload' event on the `_window`. - * Method takes care of removing itself from 'unload' event listeners once - * event is being handled. - */ - _unloadListener: function _unloadListener(event) { - let window = this._window; - if (!event.target - || event.target.defaultView != window - || STATE_LOADED != window.document.readyState - ) return; - window.removeEventListener(ON_UNLOAD, this.__unloadListener, false); - this._onUnload(window); - }, - __unloadListener: null -}); -exports.WindowLoader = WindowLoader; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/observer.js b/tools/addon-sdk-1.4/packages/api-utils/lib/windows/observer.js deleted file mode 100644 index d7b01e6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/observer.js +++ /dev/null @@ -1,86 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { EventEmitterTrait: EventEmitter } = require("../events"); -const { WindowTracker, windowIterator } = require("../window-utils"); -const { DOMEventAssembler } = require("../events/assembler"); -const { Trait } = require("../light-traits"); - -// Event emitter objects used to register listeners and emit events on them -// when they occur. -const observer = Trait.compose(DOMEventAssembler, EventEmitter).create({ - /** - * Method is implemented by `EventEmitter` and is used just for emitting - * events on registered listeners. - */ - _emit: Trait.required, - /** - * Events that are supported and emitted by the module. - */ - supportedEventsTypes: [ "activate", "deactivate" ], - /** - * Function handles all the supported events on all the windows that are - * observed. Method is used to proxy events to the listeners registered on - * this event emitter. - * @param {Event} event - * Keyboard event being emitted. - */ - handleEvent: function handleEvent(event) { - this._emit(event.type, event.target, event); - } -}); - -// Using `WindowTracker` to track window events. -new WindowTracker({ - onTrack: function onTrack(chromeWindow) { - observer._emit("open", chromeWindow); - observer.observe(chromeWindow); - }, - onUntrack: function onUntrack(chromeWindow) { - observer._emit("close", chromeWindow); - observer.ignore(chromeWindow); - } -}); - -// Making observer aware of already opened windows. -for each (let window in windowIterator()) - observer.observe(window); - -exports.observer = observer; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/tabs.js b/tools/addon-sdk-1.4/packages/api-utils/lib/windows/tabs.js deleted file mode 100644 index 551b1ce..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/windows/tabs.js +++ /dev/null @@ -1,207 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { Trait } = require("../traits"); -const { List } = require("../list"); -const { Tab, Options } = require("../tabs/tab"); -const { EventEmitter } = require("../events"); -const { EVENTS } = require("../tabs/events"); -const { getOwnerWindow, getActiveTab, getTabs, - openTab, activateTab } = require("../tabs/utils"); -const { observer: tabsObserver } = require("../tabs/observer"); - -const TAB_BROWSER = "tabbrowser"; - -/** - * This is a trait that is used in composition of window wrapper. Trait tracks - * tab related events of the wrapped window in order to keep track of open - * tabs and maintain their wrappers. Every new tab gets wrapped and jetpack - * type event is emitted. - */ -const WindowTabTracker = Trait.compose({ - /** - * Chrome window whose tabs are tracked. - */ - _window: Trait.required, - /** - * Function used to emit events. - */ - _emit: EventEmitter.required, - _tabOptions: Trait.required, - /** - * Function to add event listeners. - */ - on: EventEmitter.required, - removeListener: EventEmitter.required, - /** - * Initializes tab tracker for a browser window. - */ - _initWindowTabTracker: function _initWindowTabTracker() { - // Ugly hack that we have to remove at some point (see Bug 658059). At this - // point it is necessary to invoke lazy `tabs` getter on the windows object - // which creates a `TabList` instance. - this.tabs; - // Binding all methods used as event listeners to the instance. - this._onTabReady = this._emitEvent.bind(this, "ready"); - this._onTabOpen = this._onTabEvent.bind(this, "open"); - this._onTabClose = this._onTabEvent.bind(this, "close"); - this._onTabActivate = this._onTabEvent.bind(this, "activate"); - this._onTabDeactivate = this._onTabEvent.bind(this, "deactivate"); - - for each (let tab in getTabs(this._window)) { - // We emulate "open" events for all open tabs since gecko does not emits - // them on the tabs that new windows are open with. Also this is - // necessary to synchronize tabs lists with an actual state. - this._onTabOpen(tab); - } - // We also emulate "activate" event so that it's picked up by a tab list. - this._onTabActivate(getActiveTab(this._window)); - - // Setting up event listeners - tabsObserver.on("open", this._onTabOpen); - tabsObserver.on("close", this._onTabClose); - tabsObserver.on("activate", this._onTabActivate); - tabsObserver.on("deactivate", this._onTabDeactivate); - }, - _destroyWindowTabTracker: function _destroyWindowTabTracker() { - // We emulate close events on all tabs, since gecko does not emits such - // events by itself. - for each (let tab in this.tabs) - this._emitEvent("close", tab); - - this._tabs._clear(); - - tabsObserver.removeListener("open", this._onTabOpen); - tabsObserver.removeListener("close", this._onTabClose); - tabsObserver.removeListener("activate", this._onTabActivate); - tabsObserver.removeListener("deactivate", this._onTabDeactivate); - }, - _onTabEvent: function _onTabEvent(type, tab) { - if (this._window === getOwnerWindow(tab)) { - let options = this._tabOptions.shift() || {}; - options.tab = tab; - options.window = this._public; - // creating tab wrapper and adding listener to "ready" events. - let wrappedTab = Tab(options); - - // Setting up an event listener for ready events. - if (type === "open") - wrappedTab.on("ready", this._onTabReady); - - this._emitEvent(type, wrappedTab); - } - }, - _emitEvent: function _emitEvent(type, tab) { - // Notifies combined tab list that tab was added / removed. - tabs._emit(type, tab); - // Notifies contained tab list that window was added / removed. - this._tabs._emit(type, tab); - } -}); -exports.WindowTabTracker = WindowTabTracker; - -/** - * This trait is used to create live representation of open tab lists. Each - * window wrapper's tab list is represented by an object created from this - * trait. It is also used to represent list of all the open windows. Trait is - * composed out of `EventEmitter` in order to emit 'TabOpen', 'TabClose' events. - * **Please note** that objects created by this trait can't be exposed outside - * instead you should expose it's `_public` property, see comments in - * constructor for details. - */ -const TabList = List.resolve({ constructor: "_init" }).compose( - // This is ugly, but necessary. Will be removed by #596248 - EventEmitter.resolve({ toString: null }), - Trait.compose({ - on: Trait.required, - _emit: Trait.required, - constructor: function TabList(options) { - this._window = options.window; - // Add new items to the list - this.on(EVENTS.open.name, this._add.bind(this)); - // Remove closed items from the list - this.on(EVENTS.close.name, this._remove.bind(this)); - - // Set value whenever new tab becomes active. - this.on("activate", function onTabActivate(tab) { - this._activeTab = tab; - }.bind(this)); - // Initialize list. - this._init(); - // This list is not going to emit any events, object holding this list - // will do it instead, to make that possible we return a private API. - return this; - }, - get activeTab() this._activeTab, - _activeTab: null, - - open: function open(options) { - options = Options(options); - this._window._tabOptions.push(options); - let tab = openTab(this._window._window, options.url); - if (!options.inBackground) - activateTab(tab); - } - // This is ugly, but necessary. Will be removed by #596248 - }).resolve({ toString: null }) -); - -/** - * Combined list of all open tabs on all the windows. - * type {TabList} - */ -var tabs = TabList({ window: null }); -exports.tabs = tabs._public; - -/** - * Trait is a part of composition that represents window wrapper. This trait is - * composed out of `WindowTabTracker` that allows it to keep track of open tabs - * on the window being wrapped. - */ -const WindowTabs = Trait.compose( - WindowTabTracker, - Trait.compose({ - _window: Trait.required, - /** - * List of tabs - */ - get tabs() (this._tabs || (this._tabs = TabList({ window: this })))._public, - _tabs: null, - }) -); -exports.WindowTabs = WindowTabs; diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/xhr.js b/tools/addon-sdk-1.4/packages/api-utils/lib/xhr.js deleted file mode 100644 index 10b83db..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/xhr.js +++ /dev/null @@ -1,181 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci} = require("chrome"); - -// ## Implementation Notes ## -// -// Making `XMLHttpRequest` objects available to Jetpack code involves a -// few key principles universal to all low-level module implementations: -// -// * **Unloadability**. A Jetpack-based extension using this module can be -// asked to unload itself at any time, e.g. because the user decides to -// uninstall or disable the extension. This means we need to keep track of -// all in-progress reqests and abort them on unload. -// -// * **Developer-Ergonomic Tracebacks**. Whenever an exception is raised -// by a Jetpack-based extension, we want it to be logged in a -// place that is specific to that extension--so that a developer -// can distinguish it from an error on a web page or in another -// extension, for instance. We also want it to be logged with a -// full stack traceback, which the Mozilla platform doesn't usually -// do. -// -// Because of this, we don't actually want to give the Mozilla -// platform's "real" XHR implementation to clients, but instead provide -// a simple wrapper that trivially delegates to the implementation in -// all cases except where callbacks are involved: whenever Mozilla -// platform code calls into the extension, such as during the XHR's -// `onreadystatechange` callback, we want to wrap the client's callback -// in a try-catch clause that traps any exceptions raised by the -// callback and logs them via console.exception() instead of allowing -// them to propagate back into Mozilla platform code. - -// This is a private list of all active requests, so we know what to -// abort if we're asked to unload. -var requests = []; - -// Events on XHRs that we should listen for, so we know when to remove -// a request from our private list. -const TERMINATE_EVENTS = ["load", "error", "abort"]; - -// Read-only properties of XMLHttpRequest objects that we want to -// directly delegate to. -const READ_ONLY_PROPS = ["readyState", "responseText", "responseXML", - "status", "statusText"]; - -// Methods of XMLHttpRequest that we want to directly delegate to. -const DELEGATED_METHODS = ["abort", "getAllResponseHeaders", - "getResponseHeader", "overrideMimeType", - "send", "sendAsBinary", "setRequestHeader", - "open"]; - -var getRequestCount = exports.getRequestCount = function getRequestCount() { - return requests.length; -}; - -var XMLHttpRequest = exports.XMLHttpRequest = function XMLHttpRequest() { - var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] - .createInstance(Ci.nsIXMLHttpRequest); - // For the sake of simplicity, don't tie this request to any UI. - req.mozBackgroundRequest = true; - - memory.track(req, "XMLHttpRequest"); - - this._req = req; - this._orsc = null; - - requests.push(this); - - var self = this; - - this._boundCleanup = function _boundCleanup() { - self._cleanup(); - }; - - TERMINATE_EVENTS.forEach( - function(name) { - self._req.addEventListener(name, self._boundCleanup, false); - }); -}; - -XMLHttpRequest.prototype = { - _cleanup: function _cleanup() { - this.onreadystatechange = null; - var index = requests.indexOf(this); - if (index != -1) { - var self = this; - TERMINATE_EVENTS.forEach( - function(name) { - self._req.removeEventListener(name, self._boundCleanup, false); - }); - requests.splice(index, 1); - } - }, - _unload: function _unload() { - this._req.abort(); - this._cleanup(); - }, - addEventListener: function addEventListener() { - throw new Error("not implemented"); - }, - removeEventListener: function removeEventListener() { - throw new Error("not implemented"); - }, - set upload(newValue) { - throw new Error("not implemented"); - }, - get onreadystatechange() { - return this._orsc; - }, - set onreadystatechange(cb) { - this._orsc = cb; - if (cb) { - var self = this; - this._req.onreadystatechange = function() { - try { - self._orsc.apply(self, arguments); - } catch (e) { - console.exception(e); - } - }; - } else - this._req.onreadystatechange = null; - } -}; - -READ_ONLY_PROPS.forEach( - function(name) { - XMLHttpRequest.prototype.__defineGetter__( - name, - function() { - return this._req[name]; - }); - }); - -DELEGATED_METHODS.forEach( - function(name) { - XMLHttpRequest.prototype[name] = function() { - return this._req[name].apply(this._req, arguments); - }; - }); - -require("./unload").when( - function() { - requests.slice().forEach(function(request) { request._unload(); }); - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/xpcom.js b/tools/addon-sdk-1.4/packages/api-utils/lib/xpcom.js deleted file mode 100644 index 10f1d6b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/xpcom.js +++ /dev/null @@ -1,152 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc,Ci,Cm,Cr,Cu} = require("chrome"); - -var jsm = {}; -Cu.import("resource://gre/modules/XPCOMUtils.jsm", jsm); -var utils = exports.utils = jsm.XPCOMUtils; - -Cm.QueryInterface(Ci.nsIComponentRegistrar); - -var factories = []; - -function Factory(options) { - memory.track(this); - - this.wrappedJSObject = this; - this.create = options.create; - this.uuid = options.uuid; - this.name = options.name; - this.contractID = options.contractID; - - Cm.registerFactory(this.uuid, - this.name, - this.contractID, - this); - - var self = this; - - factories.push(this); -} - -Factory.prototype = { - createInstance: function(outer, iid) { - try { - if (outer) - throw Cr.NS_ERROR_NO_AGGREGATION; - return (new this.create()).QueryInterface(iid); - } catch (e) { - console.exception(e); - if (e instanceof Ci.nsIException) - throw e; - else - throw Cr.NS_ERROR_FAILURE; - } - }, - unregister: function() { - var index = factories.indexOf(this); - if (index == -1) - throw new Error("factory already unregistered"); - - var self = this; - - factories.splice(index, 1); - Cm.unregisterFactory(this.uuid, this); - }, - QueryInterface: utils.generateQI([Ci.nsIFactory]) -}; - -var makeUuid = exports.makeUuid = function makeUuid() { - var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] - .getService(Ci.nsIUUIDGenerator); - var uuid = uuidGenerator.generateUUID(); - return uuid; -}; - -var autoRegister = exports.autoRegister = function autoRegister(path) { - // TODO: This assumes that the url points to a directory - // that contains subdirectories corresponding to OS/ABI and then - // further subdirectories corresponding to Gecko platform version. - // we should probably either behave intelligently here or allow - // the caller to pass-in more options if e.g. there aren't - // Gecko-specific binaries for a component (which will be the case - // if only frozen interfaces are used). - - var appInfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULAppInfo); - var runtime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); - - var osDirName = runtime.OS + "_" + runtime.XPCOMABI; - var platformVersion = appInfo.platformVersion.substring(0, 5); - - var file = Cc['@mozilla.org/file/local;1'] - .createInstance(Ci.nsILocalFile); - file.initWithPath(path); - file.append(osDirName); - file.append(platformVersion); - - if (!(file.exists() && file.isDirectory())) - throw new Error("component not available for OS/ABI " + - osDirName + " and platform " + platformVersion); - - Cm.QueryInterface(Ci.nsIComponentRegistrar); - Cm.autoRegister(file); -}; - -var register = exports.register = function register(options) { - options = {__proto__: options}; - if (!options.uuid) - options.uuid = makeUuid(); - return new Factory(options); -}; - -var getClass = exports.getClass = function getClass(contractID, iid) { - if (!iid) - iid = Ci.nsISupports; - return Cm.getClassObjectByContractID(contractID, iid); -}; - -require("./unload").when( - function() { - var copy = factories.slice(); - copy.reverse(); - copy.forEach(function(factory) { factory.unregister(); }); - }); diff --git a/tools/addon-sdk-1.4/packages/api-utils/lib/xul-app.js b/tools/addon-sdk-1.4/packages/api-utils/lib/xul-app.js deleted file mode 100644 index c118682..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/lib/xul-app.js +++ /dev/null @@ -1,95 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const {Cc, Ci} = require("chrome"); - -var appInfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULAppInfo); - -var ID = exports.ID = appInfo.ID; -var name = exports.name = appInfo.name; -var version = exports.version = appInfo.version; -var platformVersion = exports.platformVersion = appInfo.platformVersion; - -// The following mapping of application names to GUIDs was taken from: -// -// https://addons.mozilla.org/en-US/firefox/pages/appversions -// -// Using the GUID instead of the app's name is preferable because sometimes -// re-branded versions of a product have different names: for instance, -// Firefox, Minefield, Iceweasel, and Shiretoko all have the same -// GUID. -// This mapping is duplicated in `app-extensions/bootstrap.js`. They should keep -// in sync, so if you change one, change the other too! - -var ids = exports.ids = { - Firefox: "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}", - Mozilla: "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}", - Sunbird: "{718e30fb-e89b-41dd-9da7-e25a45638b28}", - SeaMonkey: "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}", - Fennec: "{a23983c0-fd0e-11dc-95ff-0800200c9a66}", - Thunderbird: "{3550f703-e582-4d05-9a08-453d09bdfdc6}" -}; - -var is = exports.is = function is(name) { - if (!(name in ids)) - throw new Error("Unkown Mozilla Application: " + name); - return ID == ids[name]; -}; - -var isOneOf = exports.isOneOf = function isOneOf(names) { - for (var i = 0; i < names.length; i++) - if (is(names[i])) - return true; - return false; -}; - -/** - * Use this to check whether the given version (e.g. xulApp.platformVersion) - * is in the given range. Versions must be in version comparator-compatible - * format. See MDC for details: - * https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIVersionComparator - */ -var versionInRange = exports.versionInRange = -function versionInRange(version, lowInclusive, highExclusive) { - var vc = Cc["@mozilla.org/xpcom/version-comparator;1"] - .getService(Ci.nsIVersionComparator); - return (vc.compare(version, lowInclusive) >= 0) && - (vc.compare(version, highExclusive) < 0); -} - diff --git a/tools/addon-sdk-1.4/packages/api-utils/package.json b/tools/addon-sdk-1.4/packages/api-utils/package.json deleted file mode 100644 index d734856..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "api-utils", - "description": "Foundational infrastructure and utilities.", - "keywords": ["javascript", "engine", "platform", "xulrunner", - "jetpack-low-level"], - "author": "Atul Varma (http://toolness.com/) <atul@mozilla.com>", - "contributors": [ - "Myk Melez (http://melez.com/) <myk@mozilla.org>", - "Daniel Aquino <mr.danielaquino@gmail.com>" - ], - "license": "MPL 1.1/GPL 2.0/LGPL 2.1", - "dependencies": ["addon-kit"], - "loader": "lib/cuddlefish.js" -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/commonjs-test-adapter/asserts.js b/tools/addon-sdk-1.4/packages/api-utils/tests/commonjs-test-adapter/asserts.js deleted file mode 100644 index 83abd23..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/commonjs-test-adapter/asserts.js +++ /dev/null @@ -1,50 +0,0 @@ -"use strict"; - -const AssertBase = require("test/assert").Assert; - -/** - * Generates custom assertion constructors that may be bundled with a test - * suite. - * @params {String} - * names of assertion function to be added to the generated Assert. - */ -function Assert() { - let assertDescriptor = {}; - Array.forEach(arguments, function(name) { - assertDescriptor[name] = { value: function(message) { - this.pass(message); - }} - }); - - return function Assert() { - return Object.create(AssertBase.apply(null, arguments), assertDescriptor); - }; -} - -exports["test suite"] = { - Assert: Assert("foo"), - "test that custom assertor is passed to test function": function(assert) { - assert.ok("foo" in assert, "custom assertion function `foo` is defined"); - assert.foo("custom assertion function `foo` is called"); - }, - "test sub suite": { - "test that `Assert` is inherited by sub suits": function(assert) { - assert.ok("foo" in assert, "assertion function `foo` is not defined"); - }, - "test sub sub suite": { - Assert: Assert("bar"), - "test that custom assertor is passed to test function": function(assert) { - assert.ok("bar" in assert, - "custom assertion function `bar` is defined"); - assert.bar("custom assertion function `bar` is called"); - }, - "test that `Assert` is not inherited by sub sub suits": function(assert) { - assert.ok(!("foo" in assert), - "assertion function `foo` is not defined"); - } - } - } -}; - -if (module == require.main) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/fixtures/es5.js b/tools/addon-sdk-1.4/packages/api-utils/tests/fixtures/es5.js deleted file mode 100644 index 6e5b1ea..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/fixtures/es5.js +++ /dev/null @@ -1,4 +0,0 @@ -"use strict"; -exports.frozen = Object.freeze({}); -exports.sealed = Object.seal({}); -exports.inextensible = Object.preventExtensions({}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/helpers.js b/tools/addon-sdk-1.4/packages/api-utils/tests/helpers.js deleted file mode 100644 index bbfe911..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/helpers.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -const { Loader } = require("@loader"); - -exports.Loader = function(module, globals) { - var options = JSON.parse(JSON.stringify(require("@packaging"))); - options.globals = globals; - let loader = Loader.new(options); - return Object.create(loader, { - require: { value: Loader.require.bind(loader, module.path) }, - sandbox: { value: function sandbox(id) { - let path = options.manifest[module.path].requirements[id].path; - return loader.sandboxes[path].sandbox; - }}, - unload: { value: function unload(reason, callback) { - loader.unload(reason, callback); - }} - }) -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/loader/fixture.js b/tools/addon-sdk-1.4/packages/api-utils/tests/loader/fixture.js deleted file mode 100644 index d097dea..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/loader/fixture.js +++ /dev/null @@ -1,2 +0,0 @@ -exports.foo = foo; -console.log('testing', 1, [2, 3, 4]); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/add.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/add.js deleted file mode 100644 index 5825e08..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/add.js +++ /dev/null @@ -1,5 +0,0 @@ -define('modules/add', function () { - return function (a, b) { - return a + b; - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async1.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async1.js deleted file mode 100644 index cb51500..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async1.js +++ /dev/null @@ -1,10 +0,0 @@ -define(['./traditional2', './async2'], function () { - var traditional2 = require('./traditional2'); - return { - name: 'async1', - traditional1Name: traditional2.traditional1Name, - traditional2Name: traditional2.name, - async2Name: require('./async2').name, - async2Traditional2Name: require('./async2').traditional2Name - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async2.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async2.js deleted file mode 100644 index c0281e5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/async2.js +++ /dev/null @@ -1,4 +0,0 @@ -define(['./traditional2', 'exports'], function (traditional2, exports) { - exports.name = 'async2'; - exports.traditional2Name = traditional2.name; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badExportAndReturn.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badExportAndReturn.js deleted file mode 100644 index 0844be1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badExportAndReturn.js +++ /dev/null @@ -1,6 +0,0 @@ -// This is a bad module, it asks for exports but also returns a value from -// the define defintion function. -define(['exports'], function (exports) { - return 'badExportAndReturn'; -}); - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badFirst.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badFirst.js deleted file mode 100644 index c3e4c36..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badFirst.js +++ /dev/null @@ -1,5 +0,0 @@ -define(['./badSecond'], function (badSecond) { - return { - name: 'badFirst' - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badSecond.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badSecond.js deleted file mode 100644 index 213c7b8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/badSecond.js +++ /dev/null @@ -1,4 +0,0 @@ -var first = require('./badFirst'); - -exports.name = 'badSecond'; -exports.badFirstName = first.name; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/blue.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/blue.js deleted file mode 100644 index af3a193..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/blue.js +++ /dev/null @@ -1,5 +0,0 @@ -define(function () { - return { - name: 'blue' - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/castor.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/castor.js deleted file mode 100644 index c2d40b7..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/castor.js +++ /dev/null @@ -1,6 +0,0 @@ -define(['exports', './pollux'], function(exports, pollux) { - exports.name = 'castor'; - exports.getPolluxName = function () { - return pollux.name; - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/cheetah.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/cheetah.js deleted file mode 100644 index ad24e3a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/cheetah.js +++ /dev/null @@ -1,5 +0,0 @@ -define(function () { - return function () { - return 'cheetah'; - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/color.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/color.js deleted file mode 100644 index e1fe374..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/color.js +++ /dev/null @@ -1,3 +0,0 @@ -define({ - type: 'color' -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupe.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupe.js deleted file mode 100644 index f5ce8c9..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupe.js +++ /dev/null @@ -1,11 +0,0 @@ -define({ - name: 'dupe' -}); - -// This is wrong and should not be allowed. Only one call to -// define per file. -define([], function () { - return { - name: 'dupe2' - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeNested.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeNested.js deleted file mode 100644 index 85ecb8d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeNested.js +++ /dev/null @@ -1,11 +0,0 @@ - -define(function () { - // This is wrong and should not be allowed. - define('dupeNested2', { - name: 'dupeNested2' - }); - - return { - name: 'dupeNested' - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeSetExports.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeSetExports.js deleted file mode 100644 index 8ad3417..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/dupeSetExports.js +++ /dev/null @@ -1,4 +0,0 @@ -define({name: "dupeSetExports"}); - -// so this should cause a failure -module.setExports("no no no"); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/exportsEquals.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/exportsEquals.js deleted file mode 100644 index a9bbdd8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/exportsEquals.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 4; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/green.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/green.js deleted file mode 100644 index 8bca33c..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/green.js +++ /dev/null @@ -1,6 +0,0 @@ -define('modules/green', ['./color'], function (color) { - return { - name: 'green', - parentType: color.type - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/lion.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/lion.js deleted file mode 100644 index f3962c1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/lion.js +++ /dev/null @@ -1,3 +0,0 @@ -define(function(require) { - return 'lion'; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/orange.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/orange.js deleted file mode 100644 index d983a35..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/orange.js +++ /dev/null @@ -1,6 +0,0 @@ -define(['./color'], function (color) { - return { - name: 'orange', - parentType: color.type - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/pollux.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/pollux.js deleted file mode 100644 index e49370b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/pollux.js +++ /dev/null @@ -1,6 +0,0 @@ -define(['exports', './castor'], function(exports, castor) { - exports.name = 'pollux'; - exports.getCastorName = function () { - return castor.name; - }; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/red.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/red.js deleted file mode 100644 index eb58660..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/red.js +++ /dev/null @@ -1,12 +0,0 @@ -define(function (require) { - // comment fake-outs for require finding. - // require('bad1'); - return { - name: 'red', - parentType: require('./color').type - }; - - /* - require('bad2'); - */ -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/setExports.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/setExports.js deleted file mode 100644 index 290a3cb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/setExports.js +++ /dev/null @@ -1 +0,0 @@ -module.setExports(5); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/subtract.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/subtract.js deleted file mode 100644 index 2743132..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/subtract.js +++ /dev/null @@ -1,5 +0,0 @@ -define(function () { - return function (a, b) { - return a - b; - } -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/tiger.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/tiger.js deleted file mode 100644 index 9a98b76..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/tiger.js +++ /dev/null @@ -1,4 +0,0 @@ -define(function (require, exports) { - exports.name = 'tiger'; - exports.type = require('modules/types/cat').type; -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional1.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional1.js deleted file mode 100644 index d2e720d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional1.js +++ /dev/null @@ -1,8 +0,0 @@ -exports.name = 'traditional1' - -var async1 = require('./async1'); - -exports.traditional2Name = async1.traditional2Name; -exports.traditional1Name = async1.traditional1Name; -exports.async2Name = async1.async2Name; -exports.async2Traditional2Name = async1.async2Traditional2Name; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional2.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional2.js deleted file mode 100644 index 8363404..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/traditional2.js +++ /dev/null @@ -1,2 +0,0 @@ -exports.name = 'traditional2'; -exports.traditional1Name = require('./traditional1').name; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/types/cat.js b/tools/addon-sdk-1.4/packages/api-utils/tests/modules/types/cat.js deleted file mode 100644 index 24a1c59..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/modules/types/cat.js +++ /dev/null @@ -1 +0,0 @@ -exports.type = 'cat'; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-api-utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-api-utils.js deleted file mode 100644 index fc072bb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-api-utils.js +++ /dev/null @@ -1,274 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const apiUtils = require("api-utils/api-utils"); - -exports.testPublicConstructor = function (test) { - function PrivateCtor() {} - PrivateCtor.prototype = {}; - - let PublicCtor = apiUtils.publicConstructor(PrivateCtor); - test.assert( - PrivateCtor.prototype.isPrototypeOf(PublicCtor.prototype), - "PrivateCtor.prototype should be prototype of PublicCtor.prototype" - ); - - function testObj(useNew) { - let obj = useNew ? new PublicCtor() : PublicCtor(); - test.assert(obj instanceof PublicCtor, - "Object should be instance of PublicCtor"); - test.assert(obj instanceof PrivateCtor, - "Object should be instance of PrivateCtor"); - test.assert(PublicCtor.prototype.isPrototypeOf(obj), - "PublicCtor's prototype should be prototype of object"); - test.assertEqual(obj.constructor, PublicCtor, - "Object constructor should be PublicCtor"); - } - testObj(true); - testObj(false); -}; - -exports.testValidateOptionsEmpty = function (test) { - let val = apiUtils.validateOptions(null, {}); - assertObjsEqual(test, val, {}); - - val = apiUtils.validateOptions(null, { foo: {} }); - assertObjsEqual(test, val, {}); - - val = apiUtils.validateOptions({}, {}); - assertObjsEqual(test, val, {}); - - val = apiUtils.validateOptions({}, { foo: {} }); - assertObjsEqual(test, val, {}); -}; - -exports.testValidateOptionsNonempty = function (test) { - let val = apiUtils.validateOptions({ foo: 123 }, {}); - assertObjsEqual(test, val, {}); - - val = apiUtils.validateOptions({ foo: 123, bar: 456 }, - { foo: {}, bar: {}, baz: {} }); - assertObjsEqual(test, val, { foo: 123, bar: 456 }); -}; - -exports.testValidateOptionsMap = function (test) { - let val = apiUtils.validateOptions({ foo: 3, bar: 2 }, { - foo: { map: function (v) v * v }, - bar: { map: function (v) undefined } - }); - assertObjsEqual(test, val, { foo: 9, bar: undefined }); -}; - -exports.testValidateOptionsMapException = function (test) { - let val = apiUtils.validateOptions({ foo: 3 }, { - foo: { map: function () { throw new Error(); }} - }); - assertObjsEqual(test, val, { foo: 3 }); -}; - -exports.testValidateOptionsOk = function (test) { - let val = apiUtils.validateOptions({ foo: 3, bar: 2, baz: 1 }, { - foo: { ok: function (v) v }, - bar: { ok: function (v) v } - }); - assertObjsEqual(test, val, { foo: 3, bar: 2 }); - - test.assertRaises( - function () apiUtils.validateOptions({ foo: 2, bar: 2 }, { - bar: { ok: function (v) v > 2 } - }), - 'The option "bar" is invalid.', - "ok should raise exception on invalid option" - ); - - test.assertRaises( - function () apiUtils.validateOptions(null, { foo: { ok: function (v) v }}), - 'The option "foo" is invalid.', - "ok should raise exception on invalid option" - ); -}; - -exports.testValidateOptionsIs = function (test) { - let opts = { - array: [], - boolean: true, - func: function () {}, - nul: null, - number: 1337, - object: {}, - string: "foo", - undef1: undefined - }; - let requirements = { - array: { is: ["array"] }, - boolean: { is: ["boolean"] }, - func: { is: ["function"] }, - nul: { is: ["null"] }, - number: { is: ["number"] }, - object: { is: ["object"] }, - string: { is: ["string"] }, - undef1: { is: ["undefined"] }, - undef2: { is: ["undefined"] } - }; - let val = apiUtils.validateOptions(opts, requirements); - assertObjsEqual(test, val, opts); - - test.assertRaises( - function () apiUtils.validateOptions(null, { - foo: { is: ["object", "number"] } - }), - 'The option "foo" must be one of the following types: object, number', - "Invalid type should raise exception" - ); -}; - -exports.testValidateOptionsMapIsOk = function (test) { - let [map, is, ok] = [false, false, false]; - let val = apiUtils.validateOptions({ foo: 1337 }, { - foo: { - map: function (v) v.toString(), - is: ["string"], - ok: function (v) v.length > 0 - } - }); - assertObjsEqual(test, val, { foo: "1337" }); - - let requirements = { - foo: { - is: ["object"], - ok: function () test.fail("is should have caused us to throw by now") - } - }; - test.assertRaises( - function () apiUtils.validateOptions(null, requirements), - 'The option "foo" must be one of the following types: object', - "is should be used before ok is called" - ); -}; - -exports.testValidateOptionsErrorMsg = function (test) { - test.assertRaises( - function () apiUtils.validateOptions(null, { - foo: { ok: function (v) v, msg: "foo!" } - }), - "foo!", - "ok should raise exception with customized message" - ); -}; - -exports.testValidateMapWithMissingKey = function (test) { - let val = apiUtils.validateOptions({ }, { - foo: { - map: function (v) v || "bar" - } - }); - assertObjsEqual(test, val, { foo: "bar" }); - - val = apiUtils.validateOptions({ }, { - foo: { - map: function (v) { throw "bar" } - } - }); - assertObjsEqual(test, val, { }); -}; - -exports.testAddIterator = function testAddIterator(test) { - let obj = {}; - let keys = ["foo", "bar", "baz"]; - let vals = [1, 2, 3]; - let keysVals = [["foo", 1], ["bar", 2], ["baz", 3]]; - apiUtils.addIterator( - obj, - function keysValsGen() { - for each (let keyVal in keysVals) - yield keyVal; - } - ); - - let keysItr = []; - for (let key in obj) - keysItr.push(key); - test.assertEqual(keysItr.length, keys.length, - "the keys iterator returns the correct number of items"); - for (let i = 0; i < keys.length; i++) - test.assertEqual(keysItr[i], keys[i], "the key is correct"); - - let valsItr = []; - for each (let val in obj) - valsItr.push(val); - test.assertEqual(valsItr.length, vals.length, - "the vals iterator returns the correct number of items"); - for (let i = 0; i < vals.length; i++) - test.assertEqual(valsItr[i], vals[i], "the val is correct"); - - let keysValsItr = []; - for (let keyVal in Iterator(obj)) - keysValsItr.push(keyVal); - test.assertEqual(keysValsItr.length, keysVals.length, "the keys/vals " + - "iterator returns the correct number of items"); - for (let i = 0; i < keysVals.length; i++) { - test.assertEqual(keysValsItr[i][0], keysVals[i][0], "the key is correct"); - test.assertEqual(keysValsItr[i][1], keysVals[i][1], "the val is correct"); - } - - let keysOnlyItr = []; - for (let key in Iterator(obj, true /* keysonly */)) - keysOnlyItr.push(key); - test.assertEqual(keysOnlyItr.length, keysVals.length, "the keys only " + - "iterator returns the correct number of items"); - for (let i = 0; i < keysVals.length; i++) - test.assertEqual(keysOnlyItr[i], keysVals[i][0], "the key is correct"); -}; - -function assertObjsEqual(test, obj1, obj2) { - var items = 0; - for (let [key, val] in Iterator(obj1)) { - items++; - test.assert(key in obj2, "obj1 key should be present in obj2"); - test.assertEqual(obj2[key], val, "obj1 value should match obj2 value"); - } - for (let [key, val] in Iterator(obj2)) { - items++; - test.assert(key in obj1, "obj2 key should be present in obj1"); - test.assertEqual(obj1[key], val, "obj2 value should match obj1 value"); - } - if (!items) - test.assertEqual(JSON.stringify(obj1), JSON.stringify(obj2), - "obj1 should have same JSON representation as obj2"); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-app-strings.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-app-strings.js deleted file mode 100644 index 3c41929..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-app-strings.js +++ /dev/null @@ -1,58 +0,0 @@ -const { Cc,Ci } = require("chrome"); - -let StringBundle = require("app-strings").StringBundle; -exports.testStringBundle = function(test) { - let url = "chrome://global/locale/security/caps.properties"; - - let strings = StringBundle(url); - - test.assertEqual(strings.url, url, - "'url' property contains correct URL of string bundle"); - - let appLocale = Cc["@mozilla.org/intl/nslocaleservice;1"]. - getService(Ci.nsILocaleService). - getApplicationLocale(); - - let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle(url, appLocale); - - let (name = "Yes") { - test.assertEqual(strings.get(name), stringBundle.GetStringFromName(name), - "getting a string returns the string"); - } - - let (name = "ExtensionCapability", args = ["foo"]) { - test.assertEqual(strings.get(name, args), - stringBundle.formatStringFromName(name, args, args.length), - "getting a formatted string returns the formatted string"); - } - - test.assertRaises(function () strings.get("nonexistentString"), - "String 'nonexistentString' could not be retrieved from " + - "the bundle due to an unknown error (it doesn't exist?).", - "retrieving a nonexistent string throws an exception"); - - let a = [], b = []; - let enumerator = stringBundle.getSimpleEnumeration(); - while (enumerator.hasMoreElements()) { - let elem = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); - a.push([elem.key, elem.value]); - } - for (let keyVal in Iterator(strings)) - b.push(keyVal); - - // Sort the arrays, because we don't assume enumeration has a set order. - // Sort compares [key, val] as string "key,val", which sorts the way we want - // it to, so there is no need to provide a custom compare function. - a.sort(); - b.sort(); - - test.assertEqual(a.length, b.length, - "the iterator returns the correct number of items"); - for (let i = 0; i < a.length; i++) { - test.assertEqual(a[i][0], b[i][0], "the iterated string's name is correct"); - test.assertEqual(a[i][1], b[i][1], - "the iterated string's value is correct"); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-array.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-array.js deleted file mode 100644 index 88aed24..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-array.js +++ /dev/null @@ -1,36 +0,0 @@ -var array = require("array"); - -exports.testHas = function(test) { - var testAry = [1, 2, 3]; - test.assertEqual(array.has([1, 2, 3], 1), true); - test.assertEqual(testAry.length, 3); - test.assertEqual(testAry[0], 1); - test.assertEqual(testAry[1], 2); - test.assertEqual(testAry[2], 3); - test.assertEqual(array.has(testAry, 2), true); - test.assertEqual(array.has(testAry, 3), true); - test.assertEqual(array.has(testAry, 4), false); - test.assertEqual(array.has(testAry, "1"), false); -}; - -exports.testAdd = function(test) { - var testAry = [1]; - test.assertEqual(array.add(testAry, 1), false); - test.assertEqual(testAry.length, 1); - test.assertEqual(testAry[0], 1); - test.assertEqual(array.add(testAry, 2), true); - test.assertEqual(testAry.length, 2); - test.assertEqual(testAry[0], 1); - test.assertEqual(testAry[1], 2); -}; - -exports.testRemove = function(test) { - var testAry = [1, 2]; - test.assertEqual(array.remove(testAry, 3), false); - test.assertEqual(testAry.length, 2); - test.assertEqual(testAry[0], 1); - test.assertEqual(testAry[1], 2); - test.assertEqual(array.remove(testAry, 2), true); - test.assertEqual(testAry.length, 1); - test.assertEqual(testAry[0], 1); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-byte-streams.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-byte-streams.js deleted file mode 100644 index 4eae428..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-byte-streams.js +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const byteStreams = require("byte-streams"); -const file = require("file"); -const url = require("url"); -const { Loader } = require("./helpers"); - -const STREAM_CLOSED_ERROR = "The stream is closed and cannot be used."; - -// This should match the constant of the same name in byte-streams.js. -const BUFFER_BYTE_LEN = 0x8000; - -exports.testWriteRead = function (test) { - let fname = dataFileFilename(); - - // Write a small string less than the stream's buffer size... - let str = "exports.testWriteRead data!"; - let stream = open(test, fname, true); - test.assert(!stream.closed, "stream.closed after open should be false"); - stream.write(str); - stream.close(); - test.assert(stream.closed, "Stream should be closed after stream.close"); - test.assertRaises(function () stream.write("This shouldn't be written!"), - STREAM_CLOSED_ERROR, - "stream.write after close should raise error"); - - // ... and read it. - stream = open(test, fname); - test.assertEqual(stream.read(), str, - "stream.read should return string written"); - test.assertEqual(stream.read(), "", - "stream.read at EOS should return empty string"); - stream.close(); - test.assert(stream.closed, "Stream should be closed after stream.close"); - test.assertRaises(function () stream.read(), - STREAM_CLOSED_ERROR, - "stream.read after close should raise error"); - - file.remove(fname); -}; - -// Write a big string many times the size of the stream's buffer and read it. -exports.testWriteReadBig = function (test) { - let str = ""; - let bufLen = BUFFER_BYTE_LEN; - let fileSize = bufLen * 10; - for (let i = 0; i < fileSize; i++) - str += i % 10; - let fname = dataFileFilename(); - let stream = open(test, fname, true); - stream.write(str); - stream.close(); - stream = open(test, fname); - test.assertEqual(stream.read(), str, - "stream.read should return string written"); - stream.close(); - file.remove(fname); -}; - -// The same, but write and read in chunks. -exports.testWriteReadChunks = function (test) { - let str = ""; - let bufLen = BUFFER_BYTE_LEN; - let fileSize = bufLen * 10; - for (let i = 0; i < fileSize; i++) - str += i % 10; - let fname = dataFileFilename(); - let stream = open(test, fname, true); - let i = 0; - while (i < str.length) { - // Use a chunk length that spans buffers. - let chunk = str.substr(i, bufLen + 1); - stream.write(chunk); - i += bufLen + 1; - } - stream.close(); - stream = open(test, fname); - let readStr = ""; - bufLen = BUFFER_BYTE_LEN; - let readLen = bufLen + 1; - do { - var frag = stream.read(readLen); - readStr += frag; - } while (frag); - stream.close(); - test.assertEqual(readStr, str, - "stream.write and read in chunks should work as expected"); - file.remove(fname); -}; - -exports.testReadLengths = function (test) { - let fname = dataFileFilename(); - let str = "exports.testReadLengths data!"; - let stream = open(test, fname, true); - stream.write(str); - stream.close(); - - stream = open(test, fname); - test.assertEqual(stream.read(str.length * 1000), str, - "stream.read with big byte length should return string " + - "written"); - stream.close(); - - stream = open(test, fname); - test.assertEqual(stream.read(0), "", - "string.read with zero byte length should return empty " + - "string"); - stream.close(); - - stream = open(test, fname); - test.assertEqual(stream.read(-1), "", - "string.read with negative byte length should return " + - "empty string"); - stream.close(); - - file.remove(fname); -}; - -exports.testTruncate = function (test) { - let fname = dataFileFilename(); - let str = "exports.testReadLengths data!"; - let stream = open(test, fname, true); - stream.write(str); - stream.close(); - - stream = open(test, fname); - test.assertEqual(stream.read(), str, - "stream.read should return string written"); - stream.close(); - - stream = open(test, fname, true); - stream.close(); - - stream = open(test, fname); - test.assertEqual(stream.read(), "", - "stream.read after truncate should be empty"); - stream.close(); - - file.remove(fname); -}; - -exports.testUnload = function (test) { - let loader = Loader(module); - let file = loader.require("file"); - - let filename = url.toFilename(module.uri); - let stream = file.open(filename, "b"); - - loader.unload(); - test.assert(stream.closed, "Stream should be closed after module unload"); -}; - -// Returns the name of a file that should be used to test writing and reading. -function dataFileFilename() { - let dir = file.dirname(url.toFilename(module.uri)); - return file.join(dir, "test-byte-streams-data"); -} - -// Opens and returns the given file and ensures it's of the correct class. -function open(test, filename, forWriting) { - let stream = file.open(filename, forWriting ? "wb" : "b"); - let klass = forWriting ? "ByteWriter" : "ByteReader"; - test.assert(stream instanceof byteStreams[klass], - "Opened stream should be a " + klass); - return stream; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-collection.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-collection.js deleted file mode 100644 index 9db638e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-collection.js +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const collection = require("collection"); - -exports.testAddRemove = function (test) { - let coll = new collection.Collection(); - compare(test, coll, []); - addRemove(test, coll, [], false); -}; - -exports.testAddRemoveBackingArray = function (test) { - let items = ["foo"]; - let coll = new collection.Collection(items); - compare(test, coll, items); - addRemove(test, coll, items, true); - - items = ["foo", "bar"]; - coll = new collection.Collection(items); - compare(test, coll, items); - addRemove(test, coll, items, true); -}; - -exports.testProperty = function (test) { - let obj = makeObjWithCollProp(); - compare(test, obj.coll, []); - addRemove(test, obj.coll, [], false); - - // Test single-value set. - let items = ["foo"]; - obj.coll = items[0]; - compare(test, obj.coll, items); - addRemove(test, obj.coll, items, false); - - // Test array set. - items = ["foo", "bar"]; - obj.coll = items; - compare(test, obj.coll, items); - addRemove(test, obj.coll, items, false); -}; - -exports.testPropertyBackingArray = function (test) { - let items = ["foo"]; - let obj = makeObjWithCollProp(items); - compare(test, obj.coll, items); - addRemove(test, obj.coll, items, true); - - items = ["foo", "bar"]; - obj = makeObjWithCollProp(items); - compare(test, obj.coll, items); - addRemove(test, obj.coll, items, true); -}; - -// Adds some values to coll and then removes them. initialItems is an array -// containing coll's initial items. isBacking is true if initialItems is coll's -// backing array; the point is that updates to coll should affect initialItems -// if that's the case. -function addRemove(test, coll, initialItems, isBacking) { - let items = isBacking ? initialItems : initialItems.slice(0); - let numInitialItems = items.length; - - // Test add(val). - let numInsertions = 5; - for (let i = 0; i < numInsertions; i++) { - compare(test, coll, items); - coll.add(i); - if (!isBacking) - items.push(i); - } - compare(test, coll, items); - - // Add the items we just added to make sure duplicates aren't added. - for (let i = 0; i < numInsertions; i++) - coll.add(i); - compare(test, coll, items); - - // Test remove(val). Do a kind of shuffled remove. Remove item 1, then - // item 0, 3, 2, 5, 4, ... - for (let i = 0; i < numInsertions; i++) { - let val = i % 2 ? i - 1 : - i === numInsertions - 1 ? i : i + 1; - coll.remove(val); - if (!isBacking) - items.splice(items.indexOf(val), 1); - compare(test, coll, items); - } - test.assertEqual(coll.length, numInitialItems, - "All inserted items should be removed"); - - // Remove the items we just removed. coll should be unchanged. - for (let i = 0; i < numInsertions; i++) - coll.remove(i); - compare(test, coll, items); - - // Test add and remove([val1, val2]). - let newItems = [0, 1]; - coll.add(newItems); - compare(test, coll, isBacking ? items : items.concat(newItems)); - coll.remove(newItems); - compare(test, coll, items); - test.assertEqual(coll.length, numInitialItems, - "All inserted items should be removed"); -} - -// Asserts that the items in coll are the items of array. -function compare(test, coll, array) { - test.assertEqual(coll.length, array.length, - "Collection length should be correct"); - let numItems = 0; - for (let item in coll) { - test.assertEqual(item, array[numItems], "Items should be equal"); - numItems++; - } - test.assertEqual(numItems, array.length, - "Number of items in iteration should be correct"); -} - -// Returns a new object with a collection property named "coll". backingArray, -// if defined, will create the collection with that backing array. -function makeObjWithCollProp(backingArray) { - let obj = {}; - collection.addCollectionProperty(obj, "coll", backingArray); - return obj; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-commonjs-test-adapter.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-commonjs-test-adapter.js deleted file mode 100644 index 71fc4a0..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-commonjs-test-adapter.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -exports["test custom `Assert`'s"] = require("./commonjs-test-adapter/asserts"); - -// Disabling this check since it is not yet supported by jetpack. -// if (module == require.main) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-loader.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-loader.js deleted file mode 100644 index 0e91ee5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-loader.js +++ /dev/null @@ -1,223 +0,0 @@ -"use strict"; -const { Loader } = require('content/loader'); -const self = require("self"); - -exports['test:contentURL'] = function(test) { - let loader = Loader(), - value, emitted = 0, changes = 0; - - test.assertRaises( - function() loader.contentURL = undefined, - 'The `contentURL` option must be a valid URL.', - 'Must throw an exception if `contentURL` is not URL.' - ); - test.assertRaises( - function() loader.contentURL = null, - 'The `contentURL` option must be a valid URL.', - 'Must throw an exception if `contentURL` is not URL.' - ); - test.assertRaises( - function() loader.contentURL = 4, - 'The `contentURL` option must be a valid URL.', - 'Must throw an exception if `contentURL` is not URL.' - ); - test.assertRaises( - function() loader.contentURL = { toString: function() 'Oops' }, - 'The `contentURL` option must be a valid URL.', - 'Must throw an exception if `contentURL` is not URL.' - ); - - function listener(e) { - emitted ++; - test.assert( - 'contentURL' in e, - 'emitted event must contain "content" property' - ); - test.assert( - value, - '' + e.contentURL, - 'content property of an event must match value' - ); - } - loader.on('propertyChange', listener); - - test.assertEqual( - null, - loader.contentURL, - 'default value is `null`' - ); - loader.contentURL = value = 'data:text/html,<html><body>Hi</body><html>'; - test.assertEqual( - value, - '' + loader.contentURL, - 'data uri is ok' - ); - test.assertEqual( - ++changes, - emitted, - 'had to emit `propertyChange`' - ); - loader.contentURL = value; - test.assertEqual( - changes, - emitted, - 'must not emit `propertyChange` if same value is set' - ); - - loader.contentURL = value = 'http://google.com/'; - test.assertEqual( - value, - '' + loader.contentURL, - 'value must be set' - ); - test.assertEqual( - ++ changes, - emitted, - 'had to emit `propertyChange`' - ); - loader.contentURL = value; - test.assertEqual( - changes, - emitted, - 'must not emit `propertyChange` if same value is set' - ); - - loader.removeListener('propertyChange', listener); - loader.contentURL = value = 'about:blank'; - test.assertEqual( - value, - '' + loader.contentURL, - 'contentURL must be an actual value' - ); - test.assertEqual( - changes, - emitted, - 'listener had to be romeved' - ); -}; - -exports['test:contentScriptWhen'] = function(test) { - let loader = Loader(); - test.assertEqual( - 'end', - loader.contentScriptWhen, - '`contentScriptWhen` defaults to "end"' - ); - loader.contentScriptWhen = "end"; - test.assertEqual( - "end", - loader.contentScriptWhen - ); - try { - loader.contentScriptWhen = 'boom'; - test.fail('must throw when wrong value is set'); - } catch(e) { - test.assertEqual( - 'The `contentScriptWhen` option must be either "start", "ready" or "end".', - e.message - ); - } - loader.contentScriptWhen = null; - test.assertEqual( - 'end', - loader.contentScriptWhen, - '`contentScriptWhen` defaults to "end"' - ); - loader.contentScriptWhen = "ready"; - test.assertEqual( - "ready", - loader.contentScriptWhen - ); - loader.contentScriptWhen = "start"; - test.assertEqual( - 'start', - loader.contentScriptWhen - ); -}; - -exports['test:contentScript'] = function(test) { - let loader = Loader(), value; - test.assertEqual( - null, - loader.contentScript, - '`contentScript` defaults to `null`' - ); - loader.contentScript = value = 'let test = {};'; - test.assertEqual( - value, - loader.contentScript - ); - try { - loader.contentScript = { 1: value } - test.fail('must throw when wrong value is set'); - } catch(e) { - test.assertEqual( - 'The script option must be a string or an array of strings.', - e.message - ); - } - try { - loader.contentScript = ['oue', 2] - test.fail('must throw when wrong value is set'); - } catch(e) { - test.assertEqual( - 'The script option must be a string or an array of strings.', - e.message - ); - } - loader.contentScript = undefined; - test.assertEqual( - null, - loader.contentScript - ); - loader.contentScript = value = ["1;", "2;"]; - test.assertEqual( - value, - loader.contentScript - ); -}; - -exports['test:contentScriptFile'] = function(test) { - let loader = Loader(), value, uri = self.data.url("test-content-loader.js"); - test.assertEqual( - null, - loader.contentScriptFile, - '`contentScriptFile` defaults to `null`' - ); - loader.contentScriptFile = value = uri; - test.assertEqual( - value, - loader.contentScriptFile - ); - try { - loader.contentScriptFile = { 1: uri } - test.fail('must throw when wrong value is set'); - } catch(e) { - test.assertEqual( - 'The `contentScriptFile` option must be a local file URL or an array of' - + 'URLs.', - e.message - ); - } - try { - loader.contentScriptFile = ['oue', uri] - test.fail('must throw when wrong value is set'); - } catch(e) { - test.assertEqual( - 'The `contentScriptFile` option must be a local file URL or an array of' - + 'URLs.', - e.message - ); - } - loader.contentScriptFile = undefined; - test.assertEqual( - null, - loader.contentScriptFile - ); - loader.contentScriptFile = value = [uri]; - test.assertEqual( - value, - loader.contentScriptFile - ); -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-proxy.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-proxy.js deleted file mode 100644 index 1689c81..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-proxy.js +++ /dev/null @@ -1,754 +0,0 @@ -const hiddenFrames = require("hidden-frame"); -const xulApp = require("xul-app"); - -const { Loader } = require('./helpers'); - -/* - * Utility function that allow to easily run a proxy test with a clean - * new HTML document. See first unit test for usage. - */ -function createProxyTest(html, callback) { - return function (test) { - test.waitUntilDone(); - - let url = 'data:text/html,' + encodeURI(html); - - let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({ - onReady: function () { - - function onDOMReady() { - hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady, - false); - - let xrayWindow = hiddenFrame.element.contentWindow; - let rawWindow = xrayWindow.wrappedJSObject; - - let done = false; - let helper = { - xrayWindow: xrayWindow, - rawWindow: rawWindow, - createWorker: function (contentScript) { - return createWorker(test, xrayWindow, contentScript, helper.done); - }, - done: function () { - if (done) - return; - done = true; - hiddenFrames.remove(hiddenFrame); - test.done(); - } - } - callback(helper, test); - } - - hiddenFrame.element.addEventListener("DOMContentLoaded", onDOMReady, false); - hiddenFrame.element.setAttribute("src", url); - - } - })); - }; -} - -function createWorker(test, xrayWindow, contentScript, done) { - // We have to use Sandboxed loader in order to get access to the private - // unlock key `PRIVATE_KEY`. This key should not be used anywhere else. - // See `PRIVATE_KEY` definition in worker.js - let loader = Loader(module); - let Worker = loader.require("api-utils/content/worker").Worker; - let key = loader.sandbox("api-utils/content/worker").PRIVATE_KEY; - let worker = Worker({ - exposeUnlockKey : key, - window: xrayWindow, - contentScript: [ - 'new ' + function () { - assert = function assert(v, msg) { - self.port.emit("assert", {assertion:v, msg:msg}); - } - done = function done() { - self.port.emit("done"); - } - }, - contentScript - ] - }); - - worker.port.on("done", done); - worker.port.on("assert", function (data) { - test.assert(data.assertion, data.msg); - }); - - return worker; -} - -/* Examples for the `createProxyTest` uses */ - -let html = "<script>var documentGlobal = true</script>"; -exports.testCreateProxyTest = createProxyTest(html, function (helper, test) { - // You can get access to regular `test` object in second argument of - // `createProxyTest` method: - test.assert(helper.rawWindow.documentGlobal, - "You have access to a raw window reference via `helper.rawWindow`"); - test.assert(!("documentGlobal" in helper.xrayWindow), - "You have access to an XrayWrapper reference via `helper.xrayWindow`"); - - // If you do not create a Worker, you have to call helper.done(), - // in order to say when your test is finished - helper.done(); -}); - -exports.testCreateProxyTestWithWorker = createProxyTest("", function (helper) { - - helper.createWorker( - "new " + function WorkerScope() { - assert(true, "You can do assertions in your content script"); - // And if you create a worker, you either have to call `done` - // from content script or helper.done() - done(); - } - ); - -}); - -exports.testCreateProxyTestWithEvents = createProxyTest("", function (helper, test) { - - let worker = helper.createWorker( - "new " + function WorkerScope() { - self.port.emit("foo"); - } - ); - - worker.port.on("foo", function () { - test.pass("You can use events"); - // And terminate your test with helper.done: - helper.done(); - }); - -}); - -// Verify that the attribute `exposeUnlockKey`, that allow this test -// to identify proxies, works correctly. -// See `PRIVATE_KEY` definition in worker.js -exports.testKeyAccess = createProxyTest("", function(helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - assert("UNWRAP_ACCESS_KEY" in window, "have access to `UNWRAP_ACCESS_KEY`"); - done(); - } - ); - -}); - - -// Bug 714778: There was some issue around `toString` functions -// that ended up being shared between content scripts -exports.testSharedToStringProxies = createProxyTest("", function(helper) { - - let worker = helper.createWorker( - 'new ' + function ContentScriptScope() { - assert(document.location.toString() == "data:text/html,", - "document.location.toString()"); - self.postMessage("next"); - } - ); - worker.on("message", function () { - helper.createWorker( - 'new ' + function ContentScriptScope2() { - assert(document.location.toString() == "data:text/html,", - "document.location.toString()"); - done(); - } - ); - }); -}); - - -// Ensure that postMessage is working correctly across documents with an iframe -let html = '<iframe id="iframe" name="test" src="data:text/html," />'; -exports.testPostMessage = createProxyTest(html, function (helper, test) { - let ifWindow = helper.xrayWindow.document.getElementById("iframe").contentWindow; - // Listen without proxies, to check that it will work in regular case - // simulate listening from a web document. - ifWindow.addEventListener("message", function listener(event) { - //if (event.source.wrappedJSObject == helper.rawWindow) return; - ifWindow.removeEventListener("message", listener, false); - // As we are in system principal, event is an XrayWrapper - test.assertEqual(event.source, ifWindow, - "event.source is the iframe window"); - test.assertEqual(event.origin, "null", "origin is null"); - - test.assertEqual(event.data, "{\"foo\":\"bar\\n \\\"escaped\\\".\"}", - "message data is correct"); - - helper.done(); - }, false); - - helper.createWorker( - 'new ' + function ContentScriptScope() { - assert(postMessage === postMessage, - "verify that we doesn't generate multiple functions for the same method"); - - var json = JSON.stringify({foo : "bar\n \"escaped\"."}); - - document.getElementById("iframe").contentWindow.postMessage(json, "*"); - } - ); -}); - -let html = '<input id="input2" type="checkbox" />'; -exports.testObjectListener = createProxyTest(html, function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Test objects being given as event listener - let input = document.getElementById("input2"); - let myClickListener = { - called: false, - handleEvent: function(event) { - assert(this === myClickListener, "`this` is the original object"); - assert(!this.called, "called only once"); - this.called = true; - assert(event.valueOf() !== event.valueOf(UNWRAP_ACCESS_KEY), "event is wrapped"); - assert(event.target, input, "event.target is the wrapped window"); - done(); - } - }; - - window.addEventListener("click", myClickListener, true); - input.click(); - window.removeEventListener("click", myClickListener, true); - } - ); - -}); - -exports.testObjectListener2 = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Verify object as DOM event listener - let myMessageListener = { - called: false, - handleEvent: function(event) { - window.removeEventListener("message", myMessageListener, true); - - assert(this == myMessageListener, "`this` is the original object"); - assert(!this.called, "called only once"); - this.called = true; - assert(event.valueOf() !== event.valueOf(UNWRAP_ACCESS_KEY), "event is wrapped"); - assert(event.target == document.defaultView, "event.target is the wrapped window"); - assert(event.source == document.defaultView, "event.source is the wrapped window"); - assert(event.origin == "null", "origin is null"); - assert(event.data == "ok", "message data is correct"); - done(); - } - }; - - window.addEventListener("message", myMessageListener, true); - document.defaultView.postMessage("ok", '*'); - } - ); - -}); - -let html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' + - '<input id="input2" type="checkbox" />'; -exports.testStringOverload = createProxyTest(html, function (helper, test) { - // Proxy - toString error - let originalString = "string"; - let p = Proxy.create({ - get: function(receiver, name) { - if (name == "binded") - return originalString.toString.bind(originalString); - return originalString[name]; - } - }); - test.assertRaises(function () { - p.toString(); - }, - /String.prototype.toString called on incompatible Proxy/, - "toString can't be called with this being the proxy"); - test.assertEqual(p.binded(), "string", "but it works if we bind this to the original string"); - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // RightJS is hacking around String.prototype, and do similar thing: - // Pass `this` from a String prototype method. - // It is funny because typeof this == "object"! - // So that when we pass `this` to a native method, - // our proxy code can fail on another even more crazy thing. - // See following test to see what fails around proxies. - String.prototype.update = function () { - assert(typeof this == "object", "in update, `this` is an object"); - assert(this.toString() == "input", "in update, `this.toString works"); - return document.querySelectorAll(this); - }; - assert("input".update().length == 3, "String.prototype overload works"); - done(); - } - ); -}); - -exports.testMozMatchedSelector = createProxyTest("", function (helper) { - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Check mozMatchesSelector XrayWrappers bug: - // mozMatchesSelector returns bad results when we are not calling it from the node itself - // SEE BUG 658909: mozMatchesSelector returns incorrect results with XrayWrappers - assert(document.createElement( "div" ).mozMatchesSelector("div"), - "mozMatchesSelector works while being called from the node"); - assert(document.documentElement.mozMatchesSelector.call( - document.createElement( "div" ), - "div" - ), - "mozMatchesSelector works while being called from a " + - "function reference to " + - "document.documentElement.mozMatchesSelector.call"); - done(); - } - ); -}); - -exports.testEventsOverload = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // If we add a "____proxy" attribute on XrayWrappers in order to store - // the related proxy to create an unique proxy for each wrapper; - // we end up setting this attribute to prototype objects :x - // And so, instances created with such prototype will be considered - // as equal to the prototype ... - // // Internal method that return the proxy for a given XrayWrapper - // function proxify(obj) { - // if (obj._proxy) return obj._proxy; - // return obj._proxy = Proxy.create(...); - // } - // - // // Get a proxy of an XrayWrapper prototype object - // let proto = proxify(xpcProto); - // - // // Use this proxy as a prototype - // function Constr() {} - // Constr.proto = proto; - // - // // Try to create an instance using this prototype - // let xpcInstance = new Constr(); - // let wrapper = proxify(xpcInstance) - // - // xpcProto._proxy = proto and as xpcInstance.__proto__ = xpcProto, - // xpcInstance._proxy = proto ... and profixy(xpcInstance) = proto :( - // - let proto = window.document.createEvent('HTMLEvents').__proto__; - window.Event.prototype = proto; - let event = document.createEvent('HTMLEvents'); - assert(event !== proto, "Event should not be equal to its prototype"); - event.initEvent('dataavailable', true, true); - assert(event.type === 'dataavailable', "Events are working fine"); - done(); - } - ); - -}); - -exports.testNestedAttributes = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // XrayWrappers has a bug when you set an attribute on it, - // in some cases, it creates an unnecessary wrapper that introduces - // a different object that refers to the same original object - // Check that our wrappers don't reproduce this bug - // SEE BUG 658560: Fix identity problem with CrossOriginWrappers - let o = {sandboxObject:true}; - window.nested = o; - o.foo = true; - assert(o === window.nested, "Nested attribute to sandbox object should not be proxified"); - window.nested = document; - assert(window.nested === document, "Nested attribute to proxy should not be double proxified"); - done(); - } - ); - -}); - -exports.testFormNodeName = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - let body = document.body; - // Check form[nodeName] - let form = document.createElement("form"); - let input = document.createElement("input"); - input.setAttribute("name", "test"); - form.appendChild(input); - body.appendChild(form); - assert(form.test == input, "form[nodeName] is valid"); - body.removeChild(form); - done(); - } - ); - -}); - -exports.testLocalStorage = createProxyTest("", function (helper, test) { - - let worker = helper.createWorker( - 'new ' + function ContentScriptScope() { - // Check localStorage: - assert(window.localStorage, "has access to localStorage"); - window.localStorage.name = 1; - assert(window.localStorage.name == 1, "localStorage appears to work"); - - self.port.on("step2", function () { - window.localStorage.clear(); - assert(window.localStorage.name == undefined, "localStorage really, really works"); - done(); - }); - self.port.emit("step1"); - } - ); - - worker.port.on("step1", function () { - test.assertEqual(helper.rawWindow.localStorage.name, 1, "localStorage really works"); - worker.port.emit("step2"); - }); - -}); - -exports.testAutoUnwrapCustomAttributes = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - let body = document.body; - // Setting a custom object to a proxy attribute is not wrapped when we get it afterward - let object = {custom: true, enumerable: false}; - body.customAttribute = object; - assert(body.customAttribute.valueOf() === body.customAttribute.valueOf(UNWRAP_ACCESS_KEY), "custom JS attributes are not wrapped"); - assert(object === body.customAttribute, "custom JS attributes are not wrapped"); - done(); - } - ); - -}); - -exports.testObjectTag = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // <object>, <embed> and other tags return typeof 'function' - let flash = document.createElement("object"); - assert(typeof flash == "function", "<object> is typeof 'function'"); - assert(flash.toString().match(/\[object HTMLObjectElement.*\]/), "<object> is HTMLObjectElement"); - assert("setAttribute" in flash, "<object> has a setAttribute method"); - done(); - } - ); - -}); - -exports.testHighlightToStringBehavior = createProxyTest("", function (helper, test) { - // We do not have any workaround this particular use of toString - // applied on <object> elements. So disable this test until we found one! - //test.assertEqual(helper.rawWindow.Object.prototype.toString.call(flash), "[object HTMLObjectElement]", "<object> is HTMLObjectElement"); - function f() {}; - test.assertMatches(Object.prototype.toString.call(f), /\[object Function.*\]/, "functions are functions 1"); - // This is how jquery call toString: - test.assertMatches(helper.rawWindow.Object.prototype.toString.call(""), /\[object String.*\]/, "strings are strings"); - test.assertMatches(helper.rawWindow.Object.prototype.toString.call({}), /\[object Object.*\]/, "objects are objects"); - - // Make sure to pass a function from the same compartments - // or toString will return [object Object] on FF8+ - let f2 = helper.rawWindow.eval("(function () {})"); - test.assertMatches(helper.rawWindow.Object.prototype.toString.call(f2), /\[object Function.*\]/, "functions are functions 2"); - - helper.done(); -}); - -exports.testDocumentTagName = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - let body = document.body; - // Check document[tagName] - let div = document.createElement("div"); - div.setAttribute("name", "test"); - body.appendChild(div); - assert(!document.test, "document[divName] is undefined"); - body.removeChild(div); - - let form = document.createElement("form"); - form.setAttribute("name", "test"); - body.appendChild(form); - assert(document.test == form, "document[formName] is valid"); - body.removeChild(form); - - let img = document.createElement("img"); - img.setAttribute("name", "test"); - body.appendChild(img); - assert(document.test == img, "document[imgName] is valid"); - body.removeChild(img); - done(); - } - ); - -}); - -let html = '<iframe id="iframe" name="test" src="data:text/html," />'; -exports.testWindowFrames = createProxyTest(html, function (helper) { - - helper.createWorker( - 'let glob = this; new ' + function ContentScriptScope() { - // Check window[frameName] and window.frames[i] - let iframe = document.getElementById("iframe"); - //assert(window.frames.length == 1, "The iframe is reported in window.frames check1"); - //assert(window.frames[0] == iframe.contentWindow, "The iframe is reported in window.frames check2"); - //console.log(window.test+ "-"+iframe.contentWindow); - //console.log(window); - assert(window.test == iframe.contentWindow, "window[frameName] is valid"); - done(); - } - ); - -}); - -exports.testCollections = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Highlight XPCNativeWrapper bug with HTMLCollection - // tds[0] is only defined on first access :o - let body = document.body; - let div = document.createElement("div"); - body.appendChild(div); - div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; - let tds = div.getElementsByTagName("td"); - assert(tds[0] == tds[0], "We can get array element multiple times"); - body.removeChild(div); - done(); - } - ); - -}); - -let html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' + - '<input id="input2" type="checkbox" />'; -exports.testCollections2 = createProxyTest(html, function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Verify that NodeList/HTMLCollection are working fine - let body = document.body; - let inputs = body.getElementsByTagName("input"); - assert(body.childNodes.length == 3, "body.childNodes length is correct"); - assert(inputs.length == 3, "inputs.length is correct"); - assert(body.childNodes[0] == inputs[0], "body.childNodes[0] is correct"); - assert(body.childNodes[1] == inputs[1], "body.childNodes[1] is correct"); - assert(body.childNodes[2] == inputs[2], "body.childNodes[2] is correct"); - let count = 0; - for(let i in body.childNodes) { - count++; - } - assert(count == 3, "body.childNodes is iterable"); - done(); - } - ); - -}); - -exports.testValueOf = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Check internal use of valueOf() - assert(window.valueOf().toString().match(/\[object Window.*\]/), "proxy.valueOf() returns the wrapped version"); - assert(window.valueOf({}).toString().match(/\[object Window.*\]/), "proxy.valueOf({}) returns the wrapped version"); - assert(window.valueOf(UNWRAP_ACCESS_KEY).toString().match(/\[object XrayWrapper \[object Window.*\].*\]/), "proxy.valueOf(UNWRAP_ACCESS_KEY) returns the unwrapped version"); - done(); - } - ); - -}); - -exports.testXMLHttpRequest = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // XMLHttpRequest doesn't support XMLHttpRequest.apply, - // that may break our proxy code - assert(window.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object"); - done(); - } - ); - -}); - -exports.testXPathResult = createProxyTest("", function (helper, test) { - - // Check XPathResult bug with constants being undefined on - // XPCNativeWrapper - let value = helper.rawWindow.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE; - let xpcXPathResult = helper.xrayWindow.XPathResult; - test.assertEqual(xpcXPathResult.wrappedJSObject. - UNORDERED_NODE_SNAPSHOT_TYPE, - value, - "XPathResult's constants are valid on unwrapped node"); - - if (xulApp.versionInRange(xulApp.platformVersion, "10.0a1", "*")) { - test.assertEqual(xpcXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, 6, - "XPathResult's constants are defined on " + - "XPCNativeWrapper (platform bug #)"); - } - else { - test.assertEqual(xpcXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, - undefined, - "XPathResult's constants are undefined on " + - "XPCNativeWrapper (platform bug #665279)"); - } - - let worker = helper.createWorker( - 'new ' + function ContentScriptScope() { - self.port.on("value", function (value) { - // Check that our work around is working: - assert(window.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE === value, - "XPathResult works correctly on Proxies"); - done(); - }); - } - ); - worker.port.emit("value", value); - -}); - -exports.testPrototypeInheritance = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Verify that inherited prototype function like initEvent - // are handled correctly. (e2.type will return an error if it's not the case) - let event1 = document.createEvent( 'MouseEvents' ); - event1.initEvent( "click", true, true ); - let event2 = document.createEvent( 'MouseEvents' ); - event2.initEvent( "click", true, true ); - assert(event2.type == "click", "We are able to create an event"); - done(); - } - ); - -}); - -exports.testFunctions = createProxyTest("", function (helper) { - - helper.rawWindow.callFunction = function (f) f(); - helper.rawWindow.isEqual = function (a, b) a == b; - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Check basic usage of functions - let closure2 = function () {return "ok";}; - assert(window.wrappedJSObject.callFunction(closure2) == "ok", "Function references work"); - - // Ensure that functions are cached when being wrapped to native code - let closure = function () {}; - assert(window.wrappedJSObject.isEqual(closure, closure), "Function references are cached before being wrapped to native"); - done(); - } - ); - -}); - -let html = '<input id="input2" type="checkbox" />'; -exports.testListeners = createProxyTest(html, function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - // Verify listeners: - let input = document.getElementById("input2"); - assert(input, "proxy.getElementById works"); - - function onclick() {}; - input.onclick = onclick; - assert(input.onclick === onclick, "on* attributes are equal to original function set"); - - let addEventListenerCalled = false; - let expandoCalled = false; - input.addEventListener("click", function onclick(event) { - input.removeEventListener("click", onclick, true); - - assert(!addEventListenerCalled, "closure given to addEventListener is called once"); - if (addEventListenerCalled) - return; - addEventListenerCalled = true; - - assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals"); - assert("__isWrappedProxy" in event.target, "event object is a proxy"); - - let input2 = document.getElementById("input2"); - - input.onclick = function (event) { - input.onclick = null; - assert(!expandoCalled, "closure set to expando is called once"); - if (expandoCalled) return; - expandoCalled = true; - - assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals"); - assert("__isWrappedProxy" in event.target, "event object is a proxy"); - - setTimeout(function () { - input.click(); - done(); - }, 0); - - } - - setTimeout(function () { - input.click(); - }, 0); - - }, true); - - input.click(); - } - ); - -}); - -exports.testMozRequestAnimationFrame = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - window.mozRequestAnimationFrame(function callback() { - assert(callback == this, "callback is equal to `this`"); - done(); - }); - } - ); - -}); - -exports.testGlobalScope = createProxyTest("", function (helper) { - - helper.createWorker( - 'let toplevelScope = true;' + - 'assert(window.toplevelScope, "variables in toplevel scope are set to `window` object");' + - 'assert(this.toplevelScope, "variables in toplevel scope are set to `this` object");' + - 'done();' - ); - -}); - -// Bug 671016: Typed arrays should not be proxified -exports.testTypedArrays = createProxyTest("", function (helper) { - - helper.createWorker( - 'new ' + function ContentScriptScope() { - let canvas = document.createElement("canvas"); - let context = canvas.getContext("2d"); - let imageData = context.getImageData(0,0, 1, 1); - let unwrappedData = imageData.valueOf(UNWRAP_ACCESS_KEY).data; - let data = imageData.data; - assert(unwrappedData === data, "Typed array isn't proxified") - done(); - } - ); - -}); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-symbiont.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-symbiont.js deleted file mode 100644 index 3bd2890..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-symbiont.js +++ /dev/null @@ -1,186 +0,0 @@ -"use strict"; - -const { Cc, Ci } = require('chrome'); -const { Symbiont } = require('content/symbiont'); -const self = require("self"); - -function makeWindow() { - let content = - '<?xml version="1.0"?>' + - '<window ' + - 'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' + - '<iframe id="content" type="content"/>' + - '</window>'; - var url = "data:application/vnd.mozilla.xul+xml," + - encodeURIComponent(content); - var features = ["chrome", "width=10", "height=10"]; - - return Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher). - openWindow(null, url, null, features.join(","), null); -} - -exports['test:constructing symbiont && validating API'] = function(test) { - let window = makeWindow(); - window.addEventListener("load", function onLoad() { - window.removeEventListener("load", onLoad, false); - let frame = window.document.getElementById("content"); - // TODO: support arrays ?? - let contentScripts = ["1;", "2;"]; - let contentSymbiont = Symbiont({ - frame: frame, - contentScriptFile: self.data.url("test-content-symbiont.js"), - contentScript: contentScripts, - contentScriptWhen: "start" - }); - - test.assertEqual( - self.data.url("test-content-symbiont.js"), - contentSymbiont.contentScriptFile, - "There is one contentScriptFile, as specified in options." - ); - test.assertEqual( - contentScripts.length, - contentSymbiont.contentScript.length, - "There are two contentScripts, as specified in options." - ); - test.assertEqual( - contentScripts[0], - contentSymbiont.contentScript[0], - "There are two contentScripts, as specified in options." - ); - test.assertEqual( - contentScripts[1], - contentSymbiont.contentScript[1], - "There are two contentScripts, as specified in options." - ) - test.assertEqual( - contentSymbiont.contentScriptWhen, - "start", - "contentScriptWhen is as specified in options." - ); - - test.done(); - window.close(); - frame.setAttribute("src", "data:text/html,<html><body></body></html>"); - }, false); - test.waitUntilDone(); -}; - -exports["test:communication with worker global scope"] = function(test) { - let window = makeWindow(); - let contentSymbiont; - - function onMessage1(message) { - test.assertEqual(message, 1, "Program gets message via onMessage."); - contentSymbiont.removeListener('message', onMessage1); - contentSymbiont.on('message', onMessage2); - contentSymbiont.postMessage(2); - }; - - function onMessage2(message) { - if (5 == message) { - test.done(); - } else { - test.assertEqual(message, 3, "Program gets message via onMessage2."); - contentSymbiont.postMessage(4) - } - } - - window.addEventListener("load", function onLoad() { - window.removeEventListener("load", onLoad, false); - let frame = window.document.getElementById("content"); - contentSymbiont = Symbiont({ - frame: frame, - contentScript: 'new ' + function() { - self.postMessage(1); - self.on("message", function onMessage(message) { - if (message === 2) - self.postMessage(3); - if (message === 4) - self.postMessage(5); - }); - } + '()', - contentScriptWhen: 'ready', - onMessage: onMessage1 - }); - - frame.setAttribute("src", "data:text/html,<html><body></body></html>"); - }, false); - test.waitUntilDone(); -}; - -exports['test:pageWorker'] = function(test) { - test.waitUntilDone(); - let worker = Symbiont({ - contentURL: 'about:buildconfig', - contentScript: 'new ' + function WorkerScope() { - self.on('message', function(data) { - if (data.valid) - self.postMessage('bye!'); - }) - self.postMessage(window.location.toString()); - }, - onMessage: function(msg) { - if (msg == 'bye!') { - test.done() - } else { - test.assertEqual( - worker.contentURL + '', - msg - ); - worker.postMessage({ valid: true }); - } - } - }); -}; - -exports["test:document element present on 'start'"] = function(test) { - test.waitUntilDone(); - let xulApp = require("xul-app"); - let worker = Symbiont({ - contentURL: "about:buildconfig", - contentScript: "self.postMessage(!!document.documentElement)", - contentScriptWhen: "start", - onMessage: function(message) { - if (xulApp.versionInRange(xulApp.platformVersion, "2.0b6", "*")) - test.assert(message, "document element present on 'start'"); - else - test.pass("document element not necessarily present on 'start'"); - test.done(); - } - }); -}; - -exports["test:direct communication with trusted document"] = function(test) { - test.waitUntilDone(); - - let worker = Symbiont({ - contentURL: require("self").data.url("test-trusted-document.html") - }); - - worker.port.on('document-to-addon', function (arg) { - test.assertEqual(arg, "ok", "Received an event from the document"); - worker.destroy(); - test.done(); - }); - worker.port.emit('addon-to-document', 'ok'); -}; - -exports["test:`addon` is not available when a content script is set"] = function(test) { - test.waitUntilDone(); - - let worker = Symbiont({ - contentURL: require("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) { - test.assertEqual(hasAddon, false, - "`addon` is not available"); - worker.destroy(); - test.done(); - }); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-worker.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-worker.js deleted file mode 100644 index ced0b60..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-content-worker.js +++ /dev/null @@ -1,374 +0,0 @@ -"use stirct"; - -const { Cc, Ci } = require('chrome'); -const timer = require('timer'); - -function makeWindow(contentURL) { - let content = - '<?xml version="1.0"?>' + - '<window ' + - 'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' + - '<iframe id="content" type="content" src="' + - encodeURIComponent(contentURL) + '"/>' + - '<script>var documentValue=true;</script>' + - '</window>'; - var url = "data:application/vnd.mozilla.xul+xml," + - encodeURIComponent(content); - var features = ["chrome", "width=10", "height=10"]; - - return Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher). - openWindow(null, url, null, features.join(","), null); -} - -const { Worker } = require('content/worker'); -exports['test:sample'] = function(test) { - let window = makeWindow(); - test.waitUntilDone(); - - // As window has just being created, its document is still loading, - // and we have about:blank document before the expected one - test.assertEqual(window.document.location.href, "about:blank", - "window starts by loading about:blank"); - - // We need to wait for the load/unload of temporary about:blank - // or our worker is going to be automatically destroyed - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - test.assertNotEqual(window.document.location.href, "about:blank", - "window is now on the right document"); - - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - // window is accessible - let myLocation = window.location.toString(); - self.on('message', function(data) { - if (data == 'hi!') - self.postMessage('bye!'); - }); - }, - contentScriptWhen: 'ready', - onMessage: function(msg) { - test.assertEqual('bye!', msg); - test.assertEqual(worker.url, window.document.location.href, - "worker.url still works"); - test.done(); - } - }); - - test.assertEqual(worker.url, window.document.location.href, - "worker.url works"); - worker.postMessage('hi!'); - - }, true); - -} - -exports['test:emit'] = function(test) { - let window = makeWindow(); - test.waitUntilDone(); - - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - // Validate self.on and self.emit - self.port.on('addon-to-content', function (data) { - self.port.emit('content-to-addon', data); - }); - - // Check for global pollution - //if (typeof on != "undefined") - // self.postMessage("`on` is in globals"); - if (typeof once != "undefined") - self.postMessage("`once` is in globals"); - if (typeof emit != "undefined") - self.postMessage("`emit` is in globals"); - - }, - onMessage: function(msg) { - test.fail("Got an unexpected message : "+msg); - } - }); - - // Validate worker.port - worker.port.on('content-to-addon', function (data) { - test.assertEqual(data, "event data"); - test.done(); - }); - worker.port.emit('addon-to-content', 'event data'); - -} - -exports['test:emit hack message'] = function(test) { - let window = makeWindow(); - test.waitUntilDone(); - - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - // Validate self.port - self.port.on('message', function (data) { - self.port.emit('message', data); - }); - // We should not receive message on self, but only on self.port - self.on('message', function (data) { - self.postMessage('message', data); - }); - }, - onError: function(e) { - test.fail("Got exception: "+e); - } - }); - - worker.port.on('message', function (data) { - test.assertEqual(data, "event data"); - test.done(); - }); - worker.on('message', function (data) { - test.fail("Got an unexpected message : "+msg); - }); - worker.port.emit('message', 'event data'); - -} - -exports['test:n-arguments emit'] = function(test) { - let window = makeWindow(); - test.waitUntilDone(); - - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - // Validate self.on and self.emit - self.port.on('addon-to-content', function (a1, a2, a3) { - self.port.emit('content-to-addon', a1, a2, a3); - }); - } - }); - - // Validate worker.port - worker.port.on('content-to-addon', function (arg1, arg2, arg3) { - test.assertEqual(arg1, "first argument"); - test.assertEqual(arg2, "second"); - test.assertEqual(arg3, "third"); - test.done(); - }); - worker.port.emit('addon-to-content', 'first argument', 'second', 'third'); -} - -exports['test:post-json-values-only'] = function(test) { - let window = makeWindow("data:text/html,"); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let worker = Worker({ - window: window.document.getElementById("content").contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.on('message', function (message) { - self.postMessage([ message.fun === undefined, - typeof message.w, - message.w && "port" in message.w, - message.w.url, - Array.isArray(message.array), - JSON.stringify(message.array)]); - }); - } - }); - - // Validate worker.onMessage - let array = [1, 2, 3]; - worker.on('message', function (message) { - test.assert(message[0], "function becomes undefined"); - test.assertEqual(message[1], "object", "object stays object"); - test.assert(message[2], "object's attributes are enumerable"); - test.assertEqual(message[3], "about:blank", "jsonable attributes are accessible"); - // See bug 714891, Arrays may be broken over compartements: - test.assert(message[4], "Array keeps being an array"); - test.assertEqual(message[5], JSON.stringify(array), - "Array is correctly serialized"); - test.done(); - }); - worker.postMessage({ fun: function () {}, w: worker, array: array }); - - }, true); - -}; - -exports['test:emit-json-values-only'] = function(test) { - let window = makeWindow("data:text/html,"); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let win = window.document.getElementById("content").contentWindow; - let worker = Worker({ - window: win, - contentScript: 'new ' + function WorkerScope() { - // Validate self.on and self.emit - self.port.on('addon-to-content', function (fun, w, obj, array) { - self.port.emit('content-to-addon', [ - fun === null, - typeof w, - "port" in w, - w.url, - "fun" in obj, - Object.keys(obj.dom).length, - Array.isArray(array), - JSON.stringify(array) - ]); - }); - } - }); - - // Validate worker.port - let array = [1, 2, 3]; - worker.port.on('content-to-addon', function (result) { - test.assert(result[0], "functions become null"); - test.assertEqual(result[1], "object", "objects stay objects"); - test.assert(result[2], "object's attributes are enumerable"); - test.assertEqual(result[3], "about:blank", "json attribute is accessible"); - test.assert(!result[4], "function as object attribute is removed"); - test.assertEqual(result[5], 0, "DOM nodes are converted into empty object"); - // See bug 714891, Arrays may be broken over compartements: - test.assert(result[6], "Array keeps being an array"); - test.assertEqual(result[7], JSON.stringify(array), - "Array is correctly serialized"); - test.done(); - }); - let obj = { - fun: function () {}, - dom: win.document.documentElement - }; - worker.port.emit('addon-to-content', function () {}, worker, obj, array); - - }, true); - -} - -exports['test:content is wrapped'] = function(test) { - let contentURL = 'data:text/html,<script>var documentValue=true;</script>'; - let window = makeWindow(contentURL); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let worker = Worker({ - window: window.document.getElementById("content").contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.postMessage(!window.documentValue); - }, - contentScriptWhen: 'ready', - onMessage: function(msg) { - test.assert(msg, - "content script has a wrapped access to content document"); - test.done(); - } - }); - - }, true); - -} - -exports['test:chrome is unwrapped'] = function(test) { - let window = makeWindow(); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - self.postMessage(window.documentValue); - }, - contentScriptWhen: 'ready', - onMessage: function(msg) { - test.assert(msg, - "content script has an unwrapped access to chrome document"); - test.done(); - } - }); - - }, true); - -} - -exports['test:setTimeout can\'t be cancelled by content'] = function(test) { - let contentURL = 'data:text/html,<script>var documentValue=true;</script>'; - let window = makeWindow(contentURL); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let worker = Worker({ - window: window.document.getElementById("content").contentWindow, - contentScript: 'new ' + function WorkerScope() { - let id = setTimeout(function () { - self.postMessage("timeout"); - }, 100); - unsafeWindow.eval("clearTimeout("+id+");"); - }, - contentScriptWhen: 'ready', - onMessage: function(msg) { - test.assert(msg, - "content didn't managed to cancel our setTimeout"); - test.done(); - } - }); - - }, true); - -} - -exports['test:setTimeout are unregistered on content unload'] = function(test) { - let contentURL = 'data:text/html,foo'; - let window = makeWindow(contentURL); - test.waitUntilDone(); - - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - let iframe = window.document.getElementById("content"); - let originalDocument = iframe.contentDocument; - let worker = Worker({ - window: iframe.contentWindow, - contentScript: 'new ' + function WorkerScope() { - document.title = "ok"; - let i = 0; - setInterval(function () { - document.title = i++; - }, 10); - }, - contentScriptWhen: 'ready' - }); - - // Change location so that content script is destroyed, - // and all setTimeout/setInterval should be unregistered. - // Wait some cycles in order to execute some intervals. - timer.setTimeout(function () { - // Bug 689621: Wait for the new document load so that we are sure that - // previous document cancelled its intervals - iframe.addEventListener("load", function onload() { - iframe.removeEventListener("load", onload, true); - let titleAfterLoad = originalDocument.title; - // Wait additional cycles to verify that intervals are really cancelled - timer.setTimeout(function () { - test.assertEqual(iframe.contentDocument.title, "final", - "New document has not been modified"); - test.assertEqual(originalDocument.title, titleAfterLoad, - "Nor previous one"); - test.done(); - }, 100); - }, true); - iframe.setAttribute("src", "data:text/html,<title>final</title>"); - }, 100); - - }, true); - -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-cortex.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-cortex.js deleted file mode 100644 index 11ed397..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-cortex.js +++ /dev/null @@ -1,118 +0,0 @@ -// vim:set ts=2 sw=2 sts=2 - -"use strict"; - -var Cortex = require("cortex").Cortex; - -exports["test property changes propagate"] = function (assert) { - var source = { - _foo: "secret", - get foo() { - return this._foo; - }, - set foo(value) { - this._foo = value; - }, - get getOnly() { - return this._foo; - }, - set setOnly(value) { - this._setOnly = value; - }, - bar: "public", - method: function method(a, b) { - return this._foo + a + b - } - }; - var fixture = Cortex(source); - - assert.ok(!('_foo' in fixture), - "properties that start with `_` are omitted"); - assert.equal(fixture.foo, "secret", "get accessor alias works"); - fixture.foo = "new secret"; - assert.equal(fixture.foo, "new secret", "set accessor alias works"); - assert.equal(source.foo, "new secret", "accessor delegates to the source"); - assert.equal(fixture.bar, "public", "data property alias works"); - fixture.bar = "bar"; - assert.equal(source.bar, "bar", "data property change propagates"); - source.bar = "foo" - assert.equal(fixture.bar, "foo", "data property change probagets back"); - assert.equal(fixture.method("a", "b"), "new secretab", - "public methods are callable"); - assert.equal(fixture.method.call({ _foo: "test" }, " a,", "b"), - "new secret a,b", - "`this` pseudo-variable can not be passed through call."); - assert.equal(fixture.method.apply({ _foo: "test" }, [" a,", "b"]), - "new secret a,b", - "`this` pseudo-variable can not be passed through apply."); - assert.equal(fixture.getOnly, source._foo, - "getter returned property of wrapped object"); - fixture.setOnly = 'bar' - assert.equal(source._setOnly, 'bar', "setter modified wrapped object") -}; - - -exports["test immunity of inheritance"] = function(assert) { - function Type() {} - Type.prototype = { - constructor: Type, - _bar: 2, - bar: 3, - get_Foo: function getFoo() { - return this._foo; - } - } - var source = Object.create(Type.prototype, { - _foo: { value: 'secret' }, - getBar: { value: function get_Bar() { - return this.bar - }}, - get_Bar: { value: function getBar() { - return this._bar - }} - }); - - var fixture = Cortex(source); - - assert.ok(Cortex({}, null, Type.prototype) instanceof Type, - "if custom prototype is providede cortex will inherit from it"); - assert.ok(fixture instanceof Type, - "if no prototype is given cortex inherits from object's prototype"); - - source.bar += 1; - assert.notEqual(fixture.bar, source.bar, - "chages of properties don't propagate to non-aliases"); - assert.equal(fixture.getBar(), source.bar, - "methods accessing public properties are bound to the source"); - - fixture._bar += 1; - assert.notEqual(fixture._bar, source._bar, - "changes of non aliased properties don't propagate"); - assert.equal(fixture.get_Bar(), source._bar, - "methods accessing privates are bound to the source"); - assert.notEqual(fixture.get_Foo(), source._foo, - "prototoype methods are not bound to the source"); -} - -exports["test customized public properties"] = function(assert) { - var source = { - _a: 'a', - b: 'b', - get: function get(name) { - return this[name]; - } - }; - - var fixture = Cortex(source, ['_a', 'get']); - fixture._a += "#change"; - - - assert.ok(!("b" in fixture), "non-public own property is not defined"); - assert.equal(fixture.get("b"), source.b, - "public methods preserve access to the private properties"); - assert.equal(fixture._a, source._a, - "custom public property changes propagate"); -} - -//if (require.main == module) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-dom.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-dom.js deleted file mode 100644 index 57b1afe..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-dom.js +++ /dev/null @@ -1,84 +0,0 @@ -"use strict"; - -const events = require("dom/events"); -const { activeBrowserWindow: { document } } = require("window-utils"); -const window = document.window; - -exports["test on / emit"] = function (assert, done) { - let element = document.createElement("div"); - events.on(element, "click", function listener(event) { - assert.equal(event.target, element, "event has correct target"); - events.removeListener(element, "click", listener); - done(); - }); - - events.emit(element, "click", { - category: "MouseEvents", - settings: [ - true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null - ] - }); -}; - -exports["test remove"] = function (assert, done) { - let element = document.createElement("span"); - let l1 = 0; - let l2 = 0; - let options = { - category: "MouseEvents", - settings: [ - true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null - ] - }; - - events.on(element, "click", function listener1(event) { - l1 ++; - assert.equal(event.target, element, "event has correct target"); - events.removeListener(element, "click", listener1); - }); - - events.on(element, "click", function listener2(event) { - l2 ++; - if (l1 < l2) { - assert.equal(l1, 1, "firs listener was called and then romeved"); - events.removeListener(element, "click", listener2); - done(); - } - events.emit(element, "click", options); - }); - - events.emit(element, "click", options); -}; - -exports["test once"] = function (assert, done) { - let element = document.createElement("h1"); - let l1 = 0; - let l2 = 0; - let options = { - category: "MouseEvents", - settings: [ - true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null - ] - }; - - - events.once(element, "click", function listener(event) { - assert.equal(event.target, element, "event target is a correct element"); - l1 ++; - }); - - events.on(element, "click", function listener(event) { - l2 ++; - if (l2 > 3) { - events.removeListener(element, "click", listener); - assert.equal(event.target, element, "event has correct target"); - assert.equal(l1, 1, "once was called only once"); - done(); - } - events.emit(element, "click", options); - }); - - events.emit(element, "click", options); -} - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-e10s-porting.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-e10s-porting.js deleted file mode 100644 index 3dc4d32..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-e10s-porting.js +++ /dev/null @@ -1,73 +0,0 @@ -// This file just runs all test suites we've white-listed as being -// compatible with E10s. Once we're done with the porting effort, -// we'll just enable cfx's '--e10s' option by default and remove -// this file. - -// This is just to serve as an indicator not to run these tests in -// the addon process. -require("chrome"); - -const E10S_COMPATIBLE_TEST_SUITES = [ - 'test-api-utils.js', - 'test-traits-core.js', - 'test-traits.js', - 'test-list.js', - 'test-self.js' -]; - -exports.runE10SCompatibleTestSuites = function(test) { - var xulApp = require("xul-app"); - if (xulApp.is("Firefox") && - xulApp.versionInRange(xulApp.version, "4.0b7", "4.0b8pre")) { - test.pass("Due to bug 609066, Firefox 4.0b7 will never pass this test, " + - "so we'll skip it."); - return; - } - - // If the "jetpack/service" XPCOM component is not present, then the host - // application does not support e10s, so we can't run any e10s-compatible - // test suites under e10s mode. - if (!require("chrome").Cc["@mozilla.org/jetpack/service;1"]) { - test.pass("This application does not support e10s."); - return; - } - - if (packaging.enableE10s) { - // Don't worry about running these E10S-compatible test - // suites, cfx will find them by default because its - // '--e10s' option is enabled. - test.pass("'cfx --e10s' detected, skipping this test."); - return; - } - - var {TestFinder} = require("unit-test-finder"); - var {TestRunner} = require("unit-test"); - var url = require("url"); - - var thisDir = url.toFilename(url.URL('./', __url__)); - var finder = new TestFinder({ - dirs: [thisDir], - filter: function(name) { - return E10S_COMPATIBLE_TEST_SUITES.indexOf(name) != -1; - }, - testInProcess: false, - testOutOfProcess: true - }); - var runner = new TestRunner(); - finder.findTests(function(tests) { - test.assert(tests.length >= 1, "must find at least one test"); - runner.startMany({ - tests: tests, - onDone: function(runner) { - test.assertEqual(runner.failed, 0, - "No tests in addon process should have failed"); - test.assert(runner.passed > 0, - "Some tests in addon process must have been run"); - test.failed += runner.failed; - test.passed += runner.passed; - test.done(); - } - }); - }); - test.waitUntilDone(); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-environment.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-environment.js deleted file mode 100644 index 24077a6..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-environment.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -const { env } = require('api-utils/environment'); -const { Cc, Ci } = require('chrome'); -const { get, set, exists } = Cc['@mozilla.org/process/environment;1']. - getService(Ci.nsIEnvironment); - -exports['test exists'] = function(assert) { - assert.equal('PATH' in env, exists('PATH'), - 'PATH environment variable is defined'); - assert.equal('FOO1' in env, exists('FOO1'), - 'FOO1 environment variable is not defined'); - set('FOO1', 'foo'); - assert.equal('FOO1' in env, true, - 'FOO1 environment variable was set'); - set('FOO1', null); - assert.equal('FOO1' in env, false, - 'FOO1 environment variable was unset'); -}; - -exports['test get'] = function(assert) { - assert.equal(env.PATH, get('PATH'), 'PATH env variable matches'); - assert.equal(env.BAR2, undefined, 'BAR2 env variable is not defined'); - set('BAR2', 'bar'); - assert.equal(env.BAR2, 'bar', 'BAR2 env variable was set'); - set('BAR2', null); - assert.equal(env.BAR2, undefined, 'BAR2 env variable was unset'); -}; - -exports['test set'] = function(assert) { - assert.equal(get('BAZ3'), '', 'BAZ3 env variable is not set'); - assert.equal(env.BAZ3, undefined, 'BAZ3 is not set'); - env.BAZ3 = 'baz'; - assert.equal(env.BAZ3, get('BAZ3'), 'BAZ3 env variable is set'); - assert.equal(get('BAZ3'), 'baz', 'BAZ3 env variable was set to "baz"'); -}; - -exports['test unset'] = function(assert) { - env.BLA4 = 'bla'; - assert.equal(env.BLA4, 'bla', 'BLA4 env varibale is set'); - delete env.BLA4; - assert.equal(env.BLA4, undefined, 'BLA4 env variable is unset'); - assert.equal('BLA4' in env, false, 'BLA4 env variable no longer exists' ); -}; - -require('test').run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-errors.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-errors.js deleted file mode 100644 index 6db9c87..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-errors.js +++ /dev/null @@ -1,66 +0,0 @@ -var errors = require("errors"); - -exports.testCatchAndLog = function(test) { - var caught = []; - function dummyLog(e) { caught.push(e); } - - var wrapped = errors.catchAndLog(function(x) { - throw Error("blah" + x + this); - }, - "boop", - dummyLog); - test.assertEqual(wrapped.call("hi", 1), "boop", - "exceptions should be trapped, def. resp. returned"); - test.assertEqual(caught.length, 1, - "logging function should be called"); - test.assertEqual(caught[0].message, "blah1hi", - "args and this should be passed to wrapped func"); -}; - -exports.testCatchAndLogProps = function(test) { - var caught = []; - function dummyLog(e) { caught.push(e); } - - var thing = { - foo: function(x) { throw Error("nowai" + x); }, - bar: function() { throw Error("blah"); }, - baz: function() { throw Error("fnarg"); } - }; - - errors.catchAndLogProps(thing, "foo", "ugh", dummyLog); - - test.assertEqual(thing.foo(1), "ugh", - "props should be wrapped"); - test.assertEqual(caught.length, 1, - "logging function should be called"); - test.assertEqual(caught[0].message, "nowai1", - "args should be passed to wrapped func"); - test.assertRaises(function() { thing.bar(); }, - "blah", - "non-wrapped props should be wrapped"); - - errors.catchAndLogProps(thing, ["bar", "baz"], "err", dummyLog); - test.assert((thing.bar() == thing.baz()) && - (thing.bar() == "err"), - "multiple props should be wrapped if array passed in"); -}; - -exports.testCatchAndReturn = function(test) { - var wrapped = errors.catchAndReturn(function(x) { - if (x == 1) - return "one"; - if (x == 2) - throw new Error("two"); - return this + x; - }); - - test.assertEqual(wrapped(1).returnValue, "one", - "arg should be passed; return value should be returned"); - test.assert(wrapped(2).exception, "exception should be returned"); - test.assertEqual(wrapped(2).exception.message, "two", "message is correct"); - test.assert(wrapped(2).exception.fileName.indexOf("test-errors.js") != -1, - "filename is present"); - test.assert(wrapped(2).exception.stack, "stack is available"); - test.assertEqual(wrapped.call("hi", 3).returnValue, "hi3", - "`this` should be set correctly"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-events.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-events.js deleted file mode 100644 index 8bd846b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-events.js +++ /dev/null @@ -1,182 +0,0 @@ -'use strict'; - -// Exposing private methods as public in order to test -const EventEmitter = require('events').EventEmitter.compose({ - listeners: function(type) this._listeners(type), - emit: function() this._emit.apply(this, arguments), - emitOnObject: function() this._emitOnObject.apply(this, arguments), - removeAllListeners: function(type) this._removeAllListeners(type) -}); - -exports['test:add listeners'] = function(test) { - let e = new EventEmitter(); - - let events_new_listener_emited = []; - let times_hello_emited = 0; - - e.on("newListener", function (event, listener) { - events_new_listener_emited.push(event) - }) - - e.on("hello", function (a, b) { - times_hello_emited += 1 - test.assertEqual("a", a) - test.assertEqual("b", b) - test.assertEqual(this, e, '`this` pseudo-variable is bound to instance'); - }) - - e.emit("hello", "a", "b") -}; - -exports['test:remove listeners'] = function(test) { - let count = 0; - - function listener1 () { - count++; - } - function listener2 () { - count++; - } - function listener3 () { - count++; - } - - let e1 = new EventEmitter(); - e1.on("hello", listener1); - test.assertEqual(1, e1.listeners('hello').length); - e1.removeListener("hello", listener1); - test.assertEqual(0, e1.listeners('hello').length); - - let e2 = new EventEmitter(); - e2.on("hello", listener1); - test.assertEqual(1, e2.listeners('hello').length); - e2.removeListener("hello", listener2); - test.assertEqual(1, e2.listeners('hello').length); - test.assertEqual(listener1, e2.listeners('hello')[0]); - - let e3 = new EventEmitter(); - e3.on("hello", listener1); - test.assertEqual(1, e3.listeners('hello').length); - e3.on("hello", listener2); - test.assertEqual(2, e3.listeners('hello').length); - e3.removeListener("hello", listener1); - test.assertEqual(1, e3.listeners('hello').length); - test.assertEqual(listener2, e3.listeners('hello')[0]); -}; - -exports['test: modify in emit'] = function(test) { - let callbacks_called = [ ]; - let e = new EventEmitter(); - - function callback1() { - callbacks_called.push("callback1"); - e.on("foo", callback2); - e.on("foo", callback3); - e.removeListener("foo", callback1); - } - function callback2() { - callbacks_called.push("callback2"); - e.removeListener("foo", callback2); - } - function callback3() { - callbacks_called.push("callback3"); - e.removeListener("foo", callback3); - } - - e.on("foo", callback1); - test.assertEqual(1, e.listeners("foo").length); - - e.emit("foo"); - test.assertEqual(2, e.listeners("foo").length); - test.assertEqual(1, callbacks_called.length); - test.assertEqual('callback1', callbacks_called[0]); - - e.emit("foo"); - test.assertEqual(0, e.listeners("foo").length); - test.assertEqual(3, callbacks_called.length); - test.assertEqual('callback1', callbacks_called[0]); - test.assertEqual('callback2', callbacks_called[1]); - test.assertEqual('callback3', callbacks_called[2]); - - e.emit("foo"); - test.assertEqual(0, e.listeners("foo").length); - test.assertEqual(3, callbacks_called.length); - test.assertEqual('callback1', callbacks_called[0]); - test.assertEqual('callback2', callbacks_called[1]); - test.assertEqual('callback3', callbacks_called[2]); - - e.on("foo", callback1); - e.on("foo", callback2); - test.assertEqual(2, e.listeners("foo").length); - e.removeAllListeners("foo"); - test.assertEqual(0, e.listeners("foo").length); - - // Verify that removing callbacks while in emit allows emits to propagate to - // all listeners - callbacks_called = [ ]; - - e.on("foo", callback2); - e.on("foo", callback3); - test.assertEqual(2, e.listeners("foo").length); - e.emit("foo"); - test.assertEqual(2, callbacks_called.length); - test.assertEqual('callback2', callbacks_called[0]); - test.assertEqual('callback3', callbacks_called[1]); - test.assertEqual(0, e.listeners("foo").length); -}; - -exports['test:adding same listener'] = function(test) { - function foo() {} - let e = new EventEmitter(); - e.on("foo", foo); - e.on("foo", foo); - test.assertEqual( - 1, - e.listeners("foo").length, - "listener reregistration is ignored" - ); -} - -exports['test:errors are reported if listener throws'] = function(test) { - let e = new EventEmitter(), - reported = false; - e.on('error', function(e) reported = true) - e.on('boom', function() { throw new Error('Boom!') }); - e.emit('boom', 3); - test.assert(reported, 'error should be reported through event'); -}; - -exports['test:emitOnObject'] = function(test) { - let e = new EventEmitter(); - - e.on("foo", function() { - test.assertEqual(this, e, "`this` should be emitter"); - }); - e.emitOnObject(e, "foo"); - - e.on("bar", function() { - test.assertEqual(this, obj, "`this` should be other object"); - }); - let obj = {}; - e.emitOnObject(obj, "bar"); -}; - -exports['test:once'] = function(test) { - let e = new EventEmitter(); - let called = false; - - e.once('foo', function(value) { - test.assert(!called, "listener called only once"); - test.assertEqual(value, "bar", "correct argument was passed"); - }); - - e.emit('foo', 'bar'); - e.emit('foo', 'baz'); -}; - -exports["test romeving once"] = function(test) { - let e = require("events").EventEmitterTrait.create(); - e.once("foo", function() { test.pass("listener was called"); }); - e.once("error", function() { test.fail("error event was emitted"); }); - e._emit("foo", "bug-656684"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-file.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-file.js deleted file mode 100644 index 5b1314a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-file.js +++ /dev/null @@ -1,276 +0,0 @@ -var file = require("file"); -var url = require("url"); -var byteStreams = require("byte-streams"); -var textStreams = require("text-streams"); - -const ERRORS = { - FILE_NOT_FOUND: /^path does not exist: .+$/, - NOT_A_DIRECTORY: /^path is not a directory: .+$/, - NOT_A_FILE: /^path is not a file: .+$/, -}; - -var myurl = module.uri; -var mydir = myurl.slice(0, -("test-file.js".length)); -var otherdir = mydir + "modules/"; - -exports.testDirName = function(test) { - var aDir = url.toFilename(otherdir); - test.assertEqual(file.dirname(aDir), - aDir.slice(0, aDir.lastIndexOf("modules")-1), - "file.dirname() of dir should return parent dir"); - - aDir = url.toFilename(myurl); - test.assertEqual(file.dirname(aDir), - aDir.slice(0, aDir.lastIndexOf("test-file")-1), - "file.dirname() of file should return its dir"); - - while (aDir) - aDir = file.dirname(aDir); - test.assertEqual(aDir, "", - "dirname should return empty string when dir has no parent"); -}; - -exports.testBasename = function(test) { - // Get the top-most path -- the path with no basename. E.g., on Unix-like - // systems this will be /. We'll use it below to build up some test paths. - // We have to go to this trouble because file.join() needs a legal path as a - // base case; join("foo", "bar") doesn't work unfortunately. - var topPath = url.toFilename(myurl); - var parentPath = file.dirname(topPath); - while (parentPath) { - topPath = parentPath; - parentPath = file.dirname(topPath); - } - - var path = topPath; - test.assertEqual(file.basename(path), "", - "basename should work on paths with no components"); - - path = file.join(path, "foo"); - test.assertEqual(file.basename(path), "foo", - "basename should work on paths with a single component"); - - path = file.join(path, "bar"); - test.assertEqual(file.basename(path), "bar", - "basename should work on paths with multiple components"); -}; - -exports.testList = function(test) { - var list = file.list(url.toFilename(otherdir)); - var found = [true for each (name in list) - if (name == "add.js")]; - if (found.length > 1) - test.fail("a dir can't contain two files of the same name!"); - test.assertEqual(found[0], true, "file.list() should work"); - - test.assertRaises( - function() { file.list(url.toFilename(module.uri)); }, - ERRORS.NOT_A_DIRECTORY, - "file.list() on non-dir should raise error" - ); - - test.assertRaises( - function() { file.list(url.toFilename(mydir + "foo/")); }, - ERRORS.FILE_NOT_FOUND, - "file.list() on nonexistent dir should raise error" - ); -}; - -exports.testRead = function(test) { - var filename = url.toFilename(module.uri); - var contents = file.read(filename); - test.assertMatches(contents, /file\.read\(\) should work/, - "file.read() should work"); - - test.assertRaises( - function() { file.read(filename + "blah"); }, - ERRORS.FILE_NOT_FOUND, - "file.read() on nonexistent file should raise error" - ); - - test.assertRaises( - function() { file.read(url.toFilename(otherdir)); }, - ERRORS.NOT_A_FILE, - "file.read() on dir should raise error" - ); -}; - -exports.testJoin = function(test) { - var filename = url.toFilename(myurl); - var baseDir = file.dirname(filename); - - test.assertEqual(file.join(baseDir, "test-file.js"), - filename, - "file.join() should work"); -}; - -exports.testOpenNonexistentForRead = function (test) { - var filename = dataFileFilename(test); - test.assertRaises(function () file.open(filename), - ERRORS.FILE_NOT_FOUND, - "file.open() on nonexistent file should raise error"); - test.assertRaises(function () file.open(filename, "r"), - ERRORS.FILE_NOT_FOUND, - "file.open('r') on nonexistent file should raise error"); - test.assertRaises(function () file.open(filename, "zzz"), - ERRORS.FILE_NOT_FOUND, - "file.open('zzz') on nonexistent file should raise error"); -}; - -exports.testOpenNonexistentForWrite = function (test) { - var filename = dataFileFilename(test); - - var stream = file.open(filename, "w"); - stream.close(); - - test.assert(file.exists(filename), - "file.exists() should return true after file.open('w')"); - file.remove(filename); - test.assert(!file.exists(filename), - "file.exists() should return false after file.remove()"); - - stream = file.open(filename, "rw"); - stream.close(); - - test.assert(file.exists(filename), - "file.exists() should return true after file.open('rw')"); - file.remove(filename); - test.assert(!file.exists(filename), - "file.exists() should return false after file.remove()"); -}; - -exports.testOpenDirectory = function (test) { - var dir = file.dirname(url.toFilename(module.uri)); - test.assertRaises(function () file.open(dir), - ERRORS.NOT_A_FILE, - "file.open() on directory should raise error"); - test.assertRaises(function () file.open(dir, "w"), - ERRORS.NOT_A_FILE, - "file.open('w') on directory should raise error"); -}; - -exports.testOpenTypes = function (test) { - var filename = dataFileFilename(test); - - // Do the opens first to create the data file. - var stream = file.open(filename, "w"); - test.assert(stream instanceof textStreams.TextWriter, - "open(w) should return a TextWriter"); - stream.close(); - - stream = file.open(filename, "wb"); - test.assert(stream instanceof byteStreams.ByteWriter, - "open(wb) should return a ByteWriter"); - stream.close(); - - stream = file.open(filename); - test.assert(stream instanceof textStreams.TextReader, - "open() should return a TextReader"); - stream.close(); - - stream = file.open(filename, "r"); - test.assert(stream instanceof textStreams.TextReader, - "open(r) should return a TextReader"); - stream.close(); - - stream = file.open(filename, "b"); - test.assert(stream instanceof byteStreams.ByteReader, - "open(b) should return a ByteReader"); - stream.close(); - - stream = file.open(filename, "rb"); - test.assert(stream instanceof byteStreams.ByteReader, - "open(rb) should return a ByteReader"); - stream.close(); - - file.remove(filename); -}; - -exports.testMkpathRmdir = function (test) { - var basePath = file.dirname(url.toFilename(module.uri)); - var dirs = []; - for (var i = 0; i < 3; i++) - dirs.push("test-file-dir"); - var paths = []; - for (var i = 0; i < dirs.length; i++) { - var args = [basePath].concat(dirs.slice(0, i + 1)); - paths.unshift(file.join.apply(null, args)); - } - for (i = 0; i < paths.length; i++) { - test.assert(!file.exists(paths[i]), - "Sanity check: path should not exist: " + paths[i]); - } - file.mkpath(paths[0]); - test.assert(file.exists(paths[0]), "mkpath should create path: " + paths[0]); - for (i = 0; i < paths.length; i++) { - file.rmdir(paths[i]); - test.assert(!file.exists(paths[i]), - "rmdir should remove path: " + paths[i]); - } -}; - -exports.testMkpathTwice = function (test) { - var dir = file.dirname(url.toFilename(module.uri)); - var path = file.join(dir, "test-file-dir"); - test.assert(!file.exists(path), - "Sanity check: path should not exist: " + path); - file.mkpath(path); - test.assert(file.exists(path), "mkpath should create path: " + path); - file.mkpath(path); - test.assert(file.exists(path), - "After second mkpath, path should still exist: " + path); - file.rmdir(path); - test.assert(!file.exists(path), "rmdir should remove path: " + path); -}; - -exports.testMkpathExistingNondirectory = function (test) { - var fname = dataFileFilename(test); - file.open(fname, "w").close(); - test.assert(file.exists(fname), "File should exist"); - test.assertRaises(function () file.mkpath(fname), - /^The path already exists and is not a directory: .+$/, - "mkpath on file should raise error"); - file.remove(fname); -}; - -exports.testRmdirNondirectory = function (test) { - var fname = dataFileFilename(test); - file.open(fname, "w").close(); - test.assert(file.exists(fname), "File should exist"); - test.assertRaises(function () file.rmdir(fname), - ERRORS.NOT_A_DIRECTORY, - "rmdir on file should raise error"); - file.remove(fname); - test.assert(!file.exists(fname), "File should not exist"); - test.assertRaises(function () file.rmdir(fname), - ERRORS.FILE_NOT_FOUND, - "rmdir on non-existing file should raise error"); -}; - -exports.testRmdirNonempty = function (test) { - var dir = file.dirname(url.toFilename(module.uri)); - var path = file.join(dir, "test-file-dir"); - test.assert(!file.exists(path), - "Sanity check: path should not exist: " + path); - file.mkpath(path); - var filePath = file.join(path, "file"); - file.open(filePath, "w").close(); - test.assert(file.exists(filePath), - "Sanity check: path should exist: " + filePath); - test.assertRaises(function () file.rmdir(path), - /^The directory is not empty: .+$/, - "rmdir on non-empty directory should raise error"); - file.remove(filePath); - file.rmdir(path); - test.assert(!file.exists(path), "Path should not exist"); -}; - -// Returns the name of a file that should be used to test writing and reading. -function dataFileFilename(test) { - var dir = file.dirname(url.toFilename(module.uri)); - var fname = file.join(dir, "test-file-data"); - test.assert(!file.exists(fname), - "Sanity check: the file that this test assumes does not " + - "exist should really not exist!"); - return fname; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-function-utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-function-utils.js deleted file mode 100644 index 292380a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-function-utils.js +++ /dev/null @@ -1,23 +0,0 @@ -const { invoke, Enqueued } = require('utils/function'); - -exports['test forwardApply'] = function(test) { - function sum(b, c) this.a + b + c - test.assertEqual(invoke(sum, [2, 3], { a: 1 }), 6, - 'passed arguments and pseoude-variable are used'); - test.assertEqual(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7, - 'bounded `this` pseoudo variable is used') -} - -exports['test enqueued function'] = function(test) { - test.waitUntilDone(); - let nextTurn = false; - function sum(b, c) { - test.assert(nextTurn, 'enqueued is called in next turn of event loop'); - test.assertEqual(this.a + b + c, 6, - 'passed arguments an pseoude-variable are used'); - test.done(); - } - let fixture = { a: 1, method: Enqueued(sum) } - fixture.method(2, 3); - nextTurn = true; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-globals.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-globals.js deleted file mode 100644 index 97cb774..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-globals.js +++ /dev/null @@ -1,21 +0,0 @@ -Object.defineProperty(this, "global", { value: this }); - -exports.testGlobals = function(test) { - // the only globals in module scope should be: - // module, exports, require, dump, console - test.assertObject(module, "have 'module', good"); - test.assertObject(exports, "have 'exports', good"); - test.assertFunction(require, "have 'require', good"); - test.assertFunction(dump, "have 'dump', good"); - test.assertObject(console, "have 'console', good"); - - // in particular, these old globals should no longer be present - test.assert(!('packaging' in global), "no 'packaging', good"); - // this will be fixed by bug 620559 - test.expectFail(function() { - test.assert(!('memory' in global), "no 'memory', good"); - }); - - test.assertMatches(module.uri, /test-globals\.js$/, - 'should contain filename'); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-hidden-frame.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-hidden-frame.js deleted file mode 100644 index c92046b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-hidden-frame.js +++ /dev/null @@ -1,47 +0,0 @@ -let tests = {}, hiddenFrames, HiddenFrame; - -tests.testFrame = function(test) { - let url = "data:text/html,<!DOCTYPE%20html>"; - test.waitUntilDone(); - let hiddenFrame = hiddenFrames.add(HiddenFrame({ - onReady: function () { - test.assertEqual(this.element.contentWindow.location, "about:blank", - "HiddenFrame loads about:blank by default."); - - function onDOMReady() { - hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady, - false); - test.assertEqual(hiddenFrame.element.contentWindow.location, url, - "HiddenFrame loads the specified content."); - test.done(); - } - this.element.addEventListener("DOMContentLoaded", onDOMReady, false); - this.element.setAttribute("src", url); - } - })); -}; - -let hiddenFrameSupported = true; - -try { - hiddenFrames = require("hidden-frame"); - HiddenFrame = hiddenFrames.HiddenFrame; -} -catch(ex if ex.message == [ - "The hidden-frame module currently supports only Firefox and Thunderbird. ", - "In the future, we would like it to support other applications, however. ", - "Please see https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more ", - "information." - ].join("")) { - hiddenFrameSupported = false; -} - -if (hiddenFrameSupported) { - for (let test in tests) - exports[test] = tests[test]; -} -else { - exports.testHiddenFrameNotSupported = function(test) { - test.pass("The hidden-frame module is not supported on this app."); - } -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-httpd.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-httpd.js deleted file mode 100644 index 42734c1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-httpd.js +++ /dev/null @@ -1,28 +0,0 @@ -exports.testBasicHTTPServer = function(test) { - var port = 8080; - var data = require("self").data; - var testFilePath = require("url").toFilename(data.url("test-httpd.txt")); - var basePath = require("file").dirname(testFilePath); - var {startServerAsync} = require("httpd"); - - var srv = startServerAsync(port, basePath); - - test.waitUntilDone(); - - // Request this very file. - var Request = require('request').Request; - Request({ - url: "http://localhost:" + port + "/test-httpd.txt", - onComplete: function (response) { - test.assertEqual(response.text, "This is the HTTPD test file.\n"); - done(); - } - }).get(); - - - function done() { - srv.stop(function() { - test.done(); - }); - } -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-observer.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-observer.js deleted file mode 100644 index 27d4276..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-observer.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; - -const { keyPress } = require("api-utils/dom/events/keys"); -const { Loader } = require("./helpers"); - -exports["test unload keyboard observer"] = function(assert, done) { - let loader = Loader(module); - let element = loader.require("api-utils/window-utils"). - activeBrowserWindow.document.documentElement; - let observer = loader.require("api-utils/keyboard/observer"). - observer; - let called = 0; - - observer.on("keypress", function () { called++; }); - - // dispatching "keypress" event to trigger observer listeners. - keyPress(element, "accel-%"); - - // Unload the module. - loader.unload(); - - // dispatching "keypress" even once again. - keyPress(element, "accel-%"); - - // Enqueuing asserts to make sure that assertion is not performed early. - require("timer").setTimeout(function () { - assert.equal(called, 1, "observer was called before unload only."); - done(); - }, 0); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-utils.js deleted file mode 100644 index 137e6b1..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-keyboard-utils.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; - -const utils = require("keyboard/utils"); -const runtime = require("runtime"); - -const isMac = runtime.OS === "Darwin"; - -exports["test toString"] = function(assert) { - assert.equal(utils.toString({ - key: "B", - modifiers: [ "Shift", "Ctrl" ] - }), "Shift-Ctrl-B", "toString does not normalizes JSON"); - - assert.equal(utils.toString({ - key: "C", - modifiers: [], - }), "C", "Works with objects with empty array of modifiers"); - - assert.equal(utils.toString(Object.create((function Type() {}).prototype, { - key: { value: "d" }, - modifiers: { value: [ "alt" ] }, - method: { value: function() {} } - })), "alt-d", "Works with non-json objects"); - - assert.equal(utils.toString({ - modifiers: [ "shift", "alt" ] - }), "shift-alt-", "works with only modifiers"); -}; - -exports["test toJSON"] = function(assert) { - assert.deepEqual(utils.toJSON("Shift-Ctrl-B"), { - key: "b", - modifiers: [ "control", "shift" ] - }, "toJSON normalizes input"); - - assert.deepEqual(utils.toJSON("Meta-Alt-option-C"), { - key: "c", - modifiers: [ "alt", "meta" ] - }, "removes dublicates"); - - assert.deepEqual(utils.toJSON("AccEl+sHiFt+Z", "+"), { - key: "z", - modifiers: isMac ? [ "meta", "shift" ] : [ "control", "shift" ] - }, "normalizes OS specific keys and adjustes seperator"); -}; - -exports["test normalize"] = function assert(assert) { - assert.equal(utils.normalize("Shift Ctrl A control ctrl", " "), - "control shift a", "removes reapeted modifiers"); - assert.equal(utils.normalize("shift-ctrl-left"), "control-shift-left", - "normilizes non printed characters"); - - assert.throws(function() { - utils.normalize("shift-alt-b-z"); - }, "throws if contains more then on non-modifier key"); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-light-traits.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-light-traits.js deleted file mode 100644 index 4ad97b5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-light-traits.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -exports["test traits from objects"] = require("./traits/object-tests"); -exports["test traits from descriptors"] = require("./traits/descriptor-tests"); -exports["test inheritance"] = require("./traits/inheritance-tests"); - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-list.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-list.js deleted file mode 100644 index 29abe1a..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-list.js +++ /dev/null @@ -1,203 +0,0 @@ -"use strict"; - -function assertList(test, array, list) { - for (let i = 0, ii = array.length; i < ii; i < ii, i++) { - test.assertEqual( - array.length, - list.length, - 'list must contain same amount of elements as array' - ); - test.assertEqual( - 'List(' + array + ')', - list + '', - 'toString must output array like result' - ); - test.assert( - i in list, - 'must contain element with index: ' + i - ); - test.assertEqual( - array[i], - list[i], - 'element with index: ' + i + ' should match' - ); - } -} - -const { List } = require('api-utils/list'); - -exports['test:test for'] = function(test) { - let fixture = List(3, 2, 1); - - test.assertEqual(3, fixture.length, 'length is 3'); - let i = 0; - for (let key in fixture) { - test.assertEqual(i++, key, 'key should match'); - } -}; - -exports['test:test for each'] = function(test) { - let fixture = new List(3, 2, 1); - - test.assertEqual(3, fixture.length, 'length is 3'); - let i = 3; - for each (let value in fixture) { - test.assertEqual(i--, value, 'value should match'); - } -}; - -exports['test: for each using Iterator'] = function(test) { - let fixture = new List(3, 2, 1); - - test.assertEqual(3, fixture.length, 'length is 3'); - let v = 3, k = 0; - for each (let [key, value] in Iterator(fixture)) { - test.assertEqual(k++, key, 'key should match'); - test.assertEqual(v--, value, 'value should match'); - } -}; - -exports['test:test toString'] = function(test) { - let fixture = List(3, 2, 1); - - test.assertEqual( - 'List(3,2,1)', - fixture + '', - 'toString must output array like result' - ) -}; - -exports['test:test constructor with apply'] = function(test) { - let array = ['a', 'b', 'c']; - let fixture = List.apply(null, array); - - test.assertEqual( - 3, - fixture.length, - 'should have applied arguments' - ); -}; - -exports['test:direct element access'] = function(test) { - let array = [1, 'foo', 2, 'bar', {}, 'bar', function a() {}, test, 1]; - let fixture = List.apply(null, array); - array.splice(5, 1); - array.splice(7, 1); - - test.assertEqual( - array.length, - fixture.length, - 'list should omit duplicate elements' - ); - - test.assertEqual( - 'List(' + array + ')', - fixture.toString(), - 'elements should not be rearranged' - ); - - for (let key in array) { - test.assert(key in fixture,'should contain key for index:' + key); - test.assertEqual( - array[key], - fixture[key], - 'values should match for: ' + key - ); - } -}; - -exports['test:removing adding elements'] = function(test) { - let array = [1, 'foo', 2, 'bar', {}, 'bar', function a() {}, test, 1]; - let fixture = List.compose({ - add: function() this._add.apply(this, arguments), - remove: function() this._remove.apply(this, arguments), - clear: function() this._clear() - }).apply(null, array); - array.splice(5, 1); - array.splice(7, 1); - - assertList(test, array, fixture); - - array.splice(array.indexOf(2), 1); - fixture.remove(2); - assertList(test, array, fixture); - - array.splice(array.indexOf('foo'), 1); - fixture.remove('foo'); - array.splice(array.indexOf(1), 1); - fixture.remove(1); - array.push('foo'); - fixture.add('foo'); - assertList(test, array, fixture); - - array.splice(0); - fixture.clear(0); - assertList(test, array, fixture); - - array.push(1, 'foo', 2, 'bar', 3); - fixture.add(1); - fixture.add('foo'); - fixture.add(2); - fixture.add('bar'); - fixture.add(3); - - assertList(test, array, fixture); -}; - -exports['test: remove does not leave invalid numerical properties'] = function(test) { - let fixture = List.compose({ - remove: function() this._remove.apply(this, arguments), - }).apply(null, [1, 2, 3]); - - fixture.remove(1); - test.assertEqual(fixture[fixture.length], undefined); -} - -exports['test:add list item from Iterator'] = function(test) { - let array = [1, 2, 3, 4], sum = 0, added = false; - - let fixture = List.compose({ - add: function() this._add.apply(this, arguments), - }).apply(null, array); - - for each (let item in fixture) { - sum += item; - - if (!added) { - fixture.add(5); - added = true; - } - } - - test.assertEqual(sum, 1 + 2 + 3 + 4); -}; - -exports['test:remove list item from Iterator'] = function(test) { - let array = [1, 2, 3, 4], sum = 0; - - let fixture = List.compose({ - remove: function() this._remove.apply(this, arguments), - }).apply(null, array); - - for each (let item in fixture) { - sum += item; - fixture.remove(item); - } - - test.assertEqual(sum, 1 + 2 + 3 + 4); -}; - -exports['test:clear list from Iterator'] = function(test) { - let array = [1, 2, 3, 4], sum = 0; - - let fixture = List.compose({ - clear: function() this._clear() - }).apply(null, array); - - for each (let item in fixture) { - sum += item; - fixture.clear(); - } - - test.assertEqual(sum, 1 + 2 + 3 + 4); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-loader.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-loader.js deleted file mode 100644 index 796d1cb..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-loader.js +++ /dev/null @@ -1,31 +0,0 @@ -const { Loader } = require("./helpers"); - -exports.testLoader = function(test) { - var prints = []; - function print(message) { - prints.push(message); - } - - var loader = Loader(module, { dump: print, foo: 1 }); - - var fixture = loader.require('./loader/fixture'); - - test.assertEqual(fixture.foo, 1, "custom globals must work."); - - test.assertEqual(prints[0], "info: testing 1 2,3,4\n", - "global console must work."); - - var unloadsCalled = ''; - - loader.require("unload").when(function() { - unloadsCalled += 'a'; - }); - loader.require("unload.js").when(function() { - unloadsCalled += 'b'; - }); - - loader.unload(); - - test.assertEqual(unloadsCalled, 'ba', - "loader.unload() must call cb's in LIFO order."); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-match-pattern.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-match-pattern.js deleted file mode 100644 index 0352ba9..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-match-pattern.js +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original Author) - * Drew Willcoxon <adw@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const { MatchPattern } = require("match-pattern"); - -exports.testMatchPatternTestTrue = function(test) { - function ok(pattern, url) { - let mp = new MatchPattern(pattern); - test.assert(mp.test(url), pattern + " should match " + url); - } - - ok("*", "http://example.com"); - ok("*", "https://example.com"); - ok("*", "ftp://example.com"); - - ok("*.example.com", "http://example.com"); - ok("*.example.com", "http://hamburger.example.com"); - ok("*.example.com", "http://hotdog.hamburger.example.com"); - - ok("http://example.com*", "http://example.com"); - ok("http://example.com*", "http://example.com/"); - ok("http://example.com/*", "http://example.com/"); - ok("http://example.com/*", "http://example.com/potato-salad"); - ok("http://example.com/pickles/*", "http://example.com/pickles/"); - ok("http://example.com/pickles/*", "http://example.com/pickles/lemonade"); - - ok("http://example.com", "http://example.com"); - ok("http://example.com/ice-cream", "http://example.com/ice-cream"); - - ok(/.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753"); - ok(/https:.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753"); -}; - -exports.testMatchPatternTestFalse = function(test) { - function ok(pattern, url) { - let mp = new MatchPattern(pattern); - test.assert(!mp.test(url), pattern + " should not match " + url); - } - - ok("*", null); - ok("*", ""); - ok("*", "bogus"); - ok("*", "chrome://browser/content/browser.xul"); - ok("*", "nttp://example.com"); - - ok("*.example.com", null); - ok("*.example.com", ""); - ok("*.example.com", "bogus"); - ok("*.example.com", "http://example.net"); - ok("*.example.com", "http://foo.com"); - ok("*.example.com", "http://example.com.foo"); - ok("*.example2.com", "http://example.com"); - - ok("http://example.com/*", null); - ok("http://example.com/*", ""); - ok("http://example.com/*", "bogus"); - ok("http://example.com/*", "http://example.com"); - ok("http://example.com/*", "http://foo.com/"); - - ok("http://example.com", null); - ok("http://example.com", ""); - ok("http://example.com", "bogus"); - ok("http://example.com", "http://example.com/"); - - ok(/zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753"); - ok(/.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753"); - ok(/https:.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753"); -}; - -exports.testMatchPatternErrors = function(test) { - test.assertRaises( - function() new MatchPattern("*.google.com/*"), - /There can be at most one/, - "MatchPattern throws when supplied multiple '*'" - ); - - test.assertRaises( - function() new MatchPattern("google.com"), - /expected to be either an exact URL/, - "MatchPattern throws when the wildcard doesn't use '*' and doesn't " + - "look like a URL" - ); - - test.assertRaises( - function() new MatchPattern("http://google*.com"), - /expected to be the first or the last/, - "MatchPattern throws when a '*' is in the middle of the wildcard" - ); - - test.assertRaises( - function() new MatchPattern(/ /g), - /^A RegExp match pattern cannot be set to `global` \(i\.e\. \/\/g\)\.$/, - "MatchPattern throws on a RegExp set to `global` (i.e. //g)." - ); - - test.assertRaises( - function() new MatchPattern(/ /i), - /^A RegExp match pattern cannot be set to `ignoreCase` \(i\.e\. \/\/i\)\.$/, - "MatchPattern throws on a RegExp set to `ignoreCase` (i.e. //i)." - ); - - test.assertRaises( - function() new MatchPattern( / /m ), - /^A RegExp match pattern cannot be set to `multiline` \(i\.e\. \/\/m\)\.$/, - "MatchPattern throws on a RegExp set to `multiline` (i.e. //m)." - ); -}; - -exports.testMatchPatternInternals = function(test) { - test.assertEqual( - new MatchPattern("http://google.com/test").exactURL, - "http://google.com/test" - ); - - test.assertEqual( - new MatchPattern("http://google.com/test/*").urlPrefix, - "http://google.com/test/" - ); - - test.assertEqual( - new MatchPattern("*.example.com").domain, - "example.com" - ); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-memory.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-memory.js deleted file mode 100644 index 7e172bf..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-memory.js +++ /dev/null @@ -1,15 +0,0 @@ -var memory = require("memory"); - -exports.testMemory = function(test) { - test.pass("Skipping this test until Gecko memory debugging issues " + - "are resolved (see bug 592774)."); - return; - - var obj = {}; - memory.track(obj, "testMemory.testObj"); - var objs = memory.getObjects("testMemory.testObj"); - test.assertEqual(objs[0].weakref.get(), obj); - obj = null; - memory.gc(); - test.assertEqual(objs[0].weakref.get(), null); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-modules.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-modules.js deleted file mode 100644 index 99297bc..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-modules.js +++ /dev/null @@ -1,144 +0,0 @@ -exports.testDefine = function(test) { - let tiger = require('./modules/tiger'); - test.assertEqual(tiger.name, 'tiger', 'name proprety was exported properly'); - test.assertEqual(tiger.type, 'cat', 'property form other module exported'); -}; - -exports.testDefineInoresNonFactory = function(test) { - let mod = require('./modules/async2'); - test.assertEqual(mod.name, 'async2', 'name proprety was exported properly'); - test.assertNotEqual(mod.traditional2Name, 'traditional2', '1st is ignored'); -}; -/* Disable test that require AMD specific functionality: - -// define() that exports a function as the module value, -// specifying a module name. -exports.testDefExport = function(test) { - var add = require('modules/add'); - test.assertEqual(add(1, 1), 2, 'Named define() exporting a function'); -}; - -// define() that exports function as a value, but is anonymous -exports.testAnonDefExport = function (test) { - var subtract = require('modules/subtract'); - test.assertEqual(subtract(4, 2), 2, - 'Anonymous define() exporting a function'); -} - -// using require([], function () {}) to load modules. -exports.testSimpleRequire = function (test) { - require(['modules/blue', 'modules/orange'], function (blue, orange) { - test.assertEqual(blue.name, 'blue', 'Simple require for blue'); - test.assertEqual(orange.name, 'orange', 'Simple require for orange'); - test.assertEqual(orange.parentType, 'color', - 'Simple require dependency check for orange'); - }); -} - -// using nested require([]) calls. -exports.testSimpleRequireNested = function (test) { - require(['modules/blue', 'modules/orange', 'modules/green'], - function (blue, orange, green) { - - require(['modules/orange', 'modules/red'], function (orange, red) { - test.assertEqual(red.name, 'red', 'Simple require for red'); - test.assertEqual(red.parentType, 'color', - 'Simple require dependency check for red'); - test.assertEqual(blue.name, 'blue', 'Simple require for blue'); - test.assertEqual(orange.name, 'orange', 'Simple require for orange'); - test.assertEqual(orange.parentType, 'color', - 'Simple require dependency check for orange'); - test.assertEqual(green.name, 'green', 'Simple require for green'); - test.assertEqual(green.parentType, 'color', - 'Simple require dependency check for green'); - }); - - }); -} - -// requiring a traditional module, that uses async, that use traditional and -// async, with a circular reference -exports.testMixedCircular = function (test) { - var t = require('modules/traditional1'); - test.assertEqual(t.name, 'traditional1', 'Testing name'); - test.assertEqual(t.traditional2Name, 'traditional2', - 'Testing dependent name'); - test.assertEqual(t.traditional1Name, 'traditional1', 'Testing circular name'); - test.assertEqual(t.async2Name, 'async2', 'Testing async2 name'); - test.assertEqual(t.async2Traditional2Name, 'traditional2', - 'Testing nested traditional2 name'); -} - -// Testing define()(function(require) {}) with some that use exports, -// some that use return. -exports.testAnonExportsReturn = function (test) { - var lion = require('modules/lion'); - require(['modules/tiger', 'modules/cheetah'], function (tiger, cheetah) { - test.assertEqual('lion', lion, 'Check lion name'); - test.assertEqual('tiger', tiger.name, 'Check tiger name'); - test.assertEqual('cat', tiger.type, 'Check tiger type'); - test.assertEqual('cheetah', cheetah(), 'Check cheetah name'); - }); -} - -// circular dependency -exports.testCircular = function (test) { - var pollux = require('modules/pollux'), - castor = require('modules/castor'); - - test.assertEqual(pollux.name, 'pollux', 'Pollux\'s name'); - test.assertEqual(pollux.getCastorName(), - 'castor', 'Castor\'s name from Pollux.'); - test.assertEqual(castor.name, 'castor', 'Castor\'s name'); - test.assertEqual(castor.getPolluxName(), 'pollux', - 'Pollux\'s name from Castor.'); -} - -// test a bad module that asks for exports but also does a define() return -exports.testBadExportAndReturn = function (test) { - var passed = false; - try { - var bad = require('modules/badExportAndReturn'); - } catch(e) { - passed = /cannot use exports and also return/.test(e.toString()); - } - test.assertEqual(passed, true, 'Make sure exports and return fail'); -} - -// test a bad circular dependency, where an exported value is needed, but -// the return value happens too late, a module already asked for the exported -// value. -exports.testBadExportAndReturnCircular = function (test) { - var passed = false; - try { - var bad = require('modules/badFirst'); - } catch(e) { - passed = /after another module has referenced its exported value/ - .test(e.toString()); - } - test.assertEqual(passed, true, 'Make sure return after an exported ' + - 'value is grabbed by another module fails.'); -} - -// only allow one define call per file. -exports.testOneDefine = function (test) { - var passed = false; - try { - var dupe = require('modules/dupe'); - } catch(e) { - passed = /Only one call to define/.test(e.toString()); - } - test.assertEqual(passed, true, 'Only allow one define call per module'); -} - -// only allow one define call per file, testing a bad nested define call. -exports.testOneDefineNested = function (test) { - var passed = false; - try { - var dupe = require('modules/dupeNested'); - } catch(e) { - passed = /Only one call to define/.test(e.toString()); - } - test.assertEqual(passed, true, 'Only allow one define call per module'); -} -*/ diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-namespace.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-namespace.js deleted file mode 100644 index 60ba23d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-namespace.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; - -let { Namespace } = require("api-utils/namespace"); - -exports["test namsepace basics"] = function(assert) { - var privates = Namespace(); - var object = { foo: function foo() { return "hello foo"; } }; - - assert.notEqual(privates(object), object, - "namespaced object is not the same"); - assert.ok(!('foo' in privates(object)), - "public properties are not in the namespace"); - - assert.equal(privates(object), privates(object), - "same namespaced object is returned on each call"); -}; - -exports["test namespace overlays"] = function(assert) { - var _ = new Namespace(); - var object = { foo: 'foo' }; - - _(object).foo = 'bar'; - - assert.equal(_(object).foo, "bar", - "namespaced property `foo` changed value"); - - assert.equal(object.foo, "foo", - "public property `foo` has original value"); - - object.foo = "baz"; - assert.equal(_(object).foo, "bar", - "property changes do not affect namespaced properties"); - - object.bar = "foo"; - assert.ok(!("bar" in _(object)), - "new public properties are not reflected in namespace"); -}; - -exports["test shared namespaces"] = function(assert) { - var _ = new Namespace({ hello: 'hello world' }); - - var f1 = { hello: 1 }; - var f2 = { foo: 'foo' }; - - assert.equal(_(f1).hello, _(f2).hello, "namespace can be shared"); - assert.notEqual(f1.hello, _(f1).hello, "shared namespace can overlay"); - assert.notEqual(f2.hello, _(f2).hello, "target is not affected"); - - _(f1).hello = 2; - - assert.notEqual(_(f1).hello, _(f2).hello, - "namespaced property can be overided"); - assert.equal(_(f2).hello, _({}).hello, "namespace does not change"); -}; - -exports["test multi namespace"] = function(assert) { - var n1 = new Namespace(); - var n2 = new Namespace(); - var object = { baz: 1 }; - n1(object).foo = 1; - n2(object).foo = 2; - n1(object).bar = n2(object).bar = 3; - - assert.notEqual(n1(object).foo, n2(object).foo, - "object can have multiple namespaces"); - assert.equal(n1(object).bar, n2(object).bar, - "object can have matching props in diff namespaces"); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-observer-service.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-observer-service.js deleted file mode 100644 index 68cda74..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-observer-service.js +++ /dev/null @@ -1,73 +0,0 @@ -var observers = require("api-utils/observer-service"); -var {Cc,Ci} = require("chrome"); -const { Loader } = require("./helpers"); - -exports.testUnloadAndErrorLogging = function(test) { - var prints = []; - var loader = Loader(module, { dump: function print(message) { - prints.push(message); - }}); - var sbobsvc = loader.require("api-utils/observer-service"); - - var timesCalled = 0; - var cb = function(subject, data) { - timesCalled++; - }; - var badCb = function(subject, data) { - throw new Error("foo"); - }; - sbobsvc.add("blarg", cb); - observers.notify("blarg", "yo yo"); - test.assertEqual(timesCalled, 1); - sbobsvc.add("narg", badCb); - observers.notify("narg", "yo yo"); - var lines = prints[0].split("\n"); - test.assertEqual(lines[0], "error: An exception occurred."); - test.assertEqual(lines[1], "Traceback (most recent call last):"); - test.assertEqual(lines.slice(-2)[0], "Error: foo"); - - loader.unload(); - observers.notify("blarg", "yo yo"); - test.assertEqual(timesCalled, 1); -}; - -exports.testObserverService = function(test) { - var ios = Cc['@mozilla.org/network/io-service;1'] - .getService(Ci.nsIIOService); - var service = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - var uri = ios.newURI("http://www.foo.com", null, null); - var timesCalled = 0; - var lastSubject = null; - var lastData = null; - - var cb = function(subject, data) { - timesCalled++; - lastSubject = subject; - lastData = data; - }; - - observers.add("blarg", cb); - service.notifyObservers(uri, "blarg", "some data"); - test.assertEqual(timesCalled, 1, - "observer-service.add() should call callback"); - test.assertEqual(lastSubject, uri, - "observer-service.add() should pass subject"); - test.assertEqual(lastData, "some data", - "observer-service.add() should pass data"); - - function customSubject() {} - function customData() {} - observers.notify("blarg", customSubject, customData); - test.assertEqual(timesCalled, 2, - "observer-service.notify() should work"); - test.assertEqual(lastSubject, customSubject, - "observer-service.notify() should pass+wrap subject"); - test.assertEqual(lastData, customData, - "observer-service.notify() should pass data"); - - observers.remove("blarg", cb); - service.notifyObservers(null, "blarg", "some data"); - test.assertEqual(timesCalled, 2, - "observer-service.remove() should work"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-passwords-utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-passwords-utils.js deleted file mode 100644 index 651296f..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-passwords-utils.js +++ /dev/null @@ -1,138 +0,0 @@ -"use strict"; - -const { store, search, remove } = require("passwords/utils"); - -exports["test store requires `password` field"] = function(assert) { - assert.throws(function() { - store({ username: "foo", realm: "bar" }); - }, "`password` is required"); -}; - -exports["test store requires `username` field"] = function(assert) { - assert.throws(function() { - store({ password: "foo", realm: "bar" }); - }, "`username` is required"); -}; - -exports["test store requires `realm` field"] = function(assert) { - assert.throws(function() { - store({ username: "foo", password: "bar" }); - }, "`password` is required"); -}; - -exports["test can't store same login twice"] = function(assert) { - let options = { username: "user", password: "pass", realm: "realm" }; - store(options); - assert.throws(function() { - store(options); - }, "can't store same pass twice"); - remove(options); -}; - -exports["test remove throws if no login found"] = function(assert) { - assert.throws(function() { - remove({ username: "foo", password: "bar", realm: "baz" }); - }, "can't remove unstored credentials"); -}; - -exports["test addon associated credentials"] = function(assert) { - let options = { username: "foo", password: "bar", realm: "baz" }; - store(options); - - assert.ok(search().length, "credential was stored"); - assert.ok(search(options).length, "stored credential found"); - assert.ok(search({ username: options.username }).length, "found by username"); - assert.ok(search({ password: options.password }).length, "found by password"); - assert.ok(search({ realm: options.realm }).length, "found by realm"); - - let credential = search(options)[0]; - assert.equal(credential.url.indexOf("addon:"), 0, - "`addon:` uri is used for add-on associated credentials"); - assert.equal(credential.username, options.username, "username matches"); - assert.equal(credential.password, options.password, "password matches"); - assert.equal(credential.realm, options.realm, "realm matches"); - assert.equal(credential.formSubmitURL, null, - "`formSubmitURL` is `null` for add-on associated credentials"); - assert.equal(credential.usernameField, "", "usernameField is empty"); - assert.equal(credential.passwordField, "", "passwordField is empty"); - - remove(search(options)[0]); - assert.ok(!search(options).length, "remove worked"); -}; - -exports["test web page associated credentials"] = function(assert) { - let options = { - url: "http://www.example.com", - formSubmitURL: "http://login.example.com", - username: "user", - password: "pass", - usernameField: "user-f", - passwordField: "pass-f" - }; - store({ - url: "http://www.example.com/login", - formSubmitURL: "http://login.example.com/foo/authenticate.cgi", - username: options.username, - password: options.password, - usernameField: options.usernameField, - passwordField: options.passwordField - }); - - assert.ok(search().length, "credential was stored"); - assert.ok(search(options).length, "stored credential found"); - assert.ok(search({ username: options.username }).length, "found by username"); - assert.ok(search({ password: options.password }).length, "found by password"); - assert.ok(search({ formSubmitURL: options.formSubmitURL }).length, - "found by formSubmitURL"); - assert.ok(search({ usernameField: options.usernameField }).length, - "found by usernameField"); - assert.ok(search({ passwordField: options.passwordField }).length, - "found by passwordField"); - - let credential = search(options)[0]; - assert.equal(credential.url, options.url, "url matches"); - assert.equal(credential.username, options.username, "username matches"); - assert.equal(credential.password, options.password, "password matches"); - assert.equal(credential.realm, null, "realm is "); - assert.equal(credential.formSubmitURL, options.formSubmitURL, - "`formSubmitURL` matches"); - assert.equal(credential.usernameField, options.usernameField, - "usernameField matches"); - assert.equal(credential.passwordField, options.passwordField, - "passwordField matches"); - - remove(search(options)[0]); - assert.ok(!search(options).length, "remove worked"); -}; - -exports["test site authentication credentials"] = function(assert) { - let options = { - url: "http://test.authentication.com", - username: "u", - password: "p", - realm: "r" - }; - - store(options); - assert.ok(search().length, "credential was stored"); - assert.ok(search(options).length, "stored credential found"); - assert.ok(search({ username: options.username }).length, "found by username"); - assert.ok(search({ password: options.password }).length, "found by password"); - assert.ok(search({ realm: options.realm }).length, "found by realm"); - assert.ok(search({ url: options.url }).length, "found by url"); - - let credential = search(options)[0]; - assert.equal(credential.url, options.url, "url matches"); - assert.equal(credential.username, options.username, "username matches"); - assert.equal(credential.password, options.password, "password matches"); - assert.equal(credential.realm, options.realm, "realm matches"); - assert.equal(credential.formSubmitURL, null, - "`formSubmitURL` is `null` for site authentication credentials"); - assert.equal(credential.usernameField, "", "usernameField is empty"); - assert.equal(credential.passwordField, "", "passwordField is empty"); - - remove(search(options)[0]); - assert.ok(!search(options).length, "remove worked"); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-plain-text-console.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-plain-text-console.js deleted file mode 100644 index a0c9dda..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-plain-text-console.js +++ /dev/null @@ -1,64 +0,0 @@ -exports.testPlainTextConsole = function(test) { - var prints = []; - function print(message) { - prints.push(message); - } - function lastPrint() { - var last = prints.slice(-1)[0]; - prints = []; - return last; - } - - var Console = require("plain-text-console").PlainTextConsole; - var con = new Console(print); - - test.pass("PlainTextConsole instantiates"); - - con.log('testing', 1, [2, 3, 4]); - test.assertEqual(lastPrint(), "info: testing 1 2,3,4\n", - "PlainTextConsole.log() must work."); - - con.info('testing', 1, [2, 3, 4]); - test.assertEqual(lastPrint(), "info: testing 1 2,3,4\n", - "PlainTextConsole.info() must work."); - - con.warn('testing', 1, [2, 3, 4]); - test.assertEqual(lastPrint(), "warning: testing 1 2,3,4\n", - "PlainTextConsole.warn() must work."); - - con.error('testing', 1, [2, 3, 4]); - test.assertEqual(lastPrint(), "error: testing 1 2,3,4\n", - "PlainTextConsole.error() must work."); - - con.debug('testing', 1, [2, 3, 4]); - test.assertEqual(lastPrint(), "debug: testing 1 2,3,4\n", - "PlainTextConsole.debug() must work."); - - con.log('testing', undefined); - test.assertEqual(lastPrint(), "info: testing undefined\n", - "PlainTextConsole.log() must stringify undefined."); - - con.log('testing', null); - test.assertEqual(lastPrint(), "info: testing null\n", - "PlainTextConsole.log() must stringify null."); - - con.log("testing", { toString: function() "obj.toString()" }); - test.assertEqual(lastPrint(), "info: testing obj.toString()\n", - "PlainTextConsole.log() must stringify custom toString."); - - con.log("testing", { toString: function() { throw "fail!"; } }); - test.assertEqual(lastPrint(), "info: testing <toString() error>\n", - "PlainTextConsole.log() must stringify custom bad toString."); - - con.exception(new Error("blah")); - var tbLines = prints[0].split("\n"); - test.assertEqual(tbLines[0], "error: An exception occurred."); - test.assertEqual(tbLines[1], "Traceback (most recent call last):"); - test.assertEqual(tbLines.slice(-2)[0], "Error: blah"); - - prints = []; - con.trace(); - tbLines = prints[0].split("\n"); - test.assertEqual(tbLines[0], "info: Traceback (most recent call last):"); - test.assertEqual(tbLines.slice(-2)[0].trim(), "con.trace();"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-preferences-service.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-preferences-service.js deleted file mode 100644 index dd0de38..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-preferences-service.js +++ /dev/null @@ -1,87 +0,0 @@ -var prefs = require("preferences-service"); -var {Cc,Ci} = require("chrome"); - -exports.testReset = function(test) { - prefs.reset("test_reset_pref"); - test.assertEqual(prefs.has("test_reset_pref"), false); - test.assertEqual(prefs.isSet("test_reset_pref"), false); - prefs.set("test_reset_pref", 5); - test.assertEqual(prefs.has("test_reset_pref"), true); - test.assertEqual(prefs.isSet("test_reset_pref"), true); -}; - -exports.testGetAndSet = function(test) { - let svc = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefService). - getBranch(null); - svc.setCharPref("test_get_string_pref", "a normal string"); - test.assertEqual(prefs.get("test_get_string_pref"), "a normal string", - "preferences-service should read from " + - "application-wide preferences service"); - - prefs.set("test_set_get_pref.integer", 1); - test.assertEqual(prefs.get("test_set_get_pref.integer"), 1, - "set/get integer preference should work"); - - prefs.set("test_set_get_number_pref", 42); - test.assertRaises( - function() { prefs.set("test_set_get_number_pref", 3.14159); }, - "cannot store non-integer number: 3.14159", - "setting a float preference should raise an error" - ); - test.assertEqual(prefs.get("test_set_get_number_pref"), 42, - "bad-type write attempt should not overwrite"); - - // 0x80000000 (no), 0x7fffffff (yes), -0x80000000 (yes), -0x80000001 (no) - test.assertRaises( - function() { prefs.set("test_set_get_number_pref", Math.pow(2, 31)); }, - ("you cannot set the test_set_get_number_pref pref to the number " + - "2147483648, as number pref values must be in the signed 32-bit " + - "integer range -(2^31) to 2^31-1. To store numbers outside that " + - "range, store them as strings."), - "setting an int pref outside the range -(2^31) to 2^31-1 shouldn't work" - ); - test.assertEqual(prefs.get("test_set_get_number_pref"), 42, - "out-of-range write attempt should not overwrite 1"); - prefs.set("test_set_get_number_pref", Math.pow(2, 31)-1); - test.assertEqual(prefs.get("test_set_get_number_pref"), 0x7fffffff, - "in-range write attempt should work 1"); - prefs.set("test_set_get_number_pref", -Math.pow(2, 31)); - test.assertEqual(prefs.get("test_set_get_number_pref"), -0x80000000, - "in-range write attempt should work 2"); - test.assertRaises( - function() { prefs.set("test_set_get_number_pref", -0x80000001); }, - ("you cannot set the test_set_get_number_pref pref to the number " + - "-2147483649, as number pref values must be in the signed 32-bit " + - "integer range -(2^31) to 2^31-1. To store numbers outside that " + - "range, store them as strings."), - "setting an int pref outside the range -(2^31) to 2^31-1 shouldn't work" - ); - test.assertEqual(prefs.get("test_set_get_number_pref"), -0x80000000, - "out-of-range write attempt should not overwrite 2"); - - - prefs.set("test_set_get_pref.string", "foo"); - test.assertEqual(prefs.get("test_set_get_pref.string"), "foo", - "set/get string preference should work"); - - prefs.set("test_set_get_pref.boolean", true); - test.assertEqual(prefs.get("test_set_get_pref.boolean"), true, - "set/get boolean preference should work"); - - prefs.set("test_set_get_unicode_pref", String.fromCharCode(960)); - test.assertEqual(prefs.get("test_set_get_unicode_pref"), - String.fromCharCode(960), - "set/get unicode preference should work"); - - var unsupportedValues = [null, [], undefined]; - unsupportedValues.forEach( - function(value) { - test.assertRaises( - function() { prefs.set("test_set_pref", value); }, - ("can't set pref test_set_pref to value '" + value + "'; " + - "it isn't a string, integer, or boolean"), - "Setting a pref to " + uneval(value) + " should raise error" - ); - }); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-registry.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-registry.js deleted file mode 100644 index 8a251f7..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-registry.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -exports['test:add'] = function(test) { - function Class() {} - let fixture = require('utils/registry').Registry(Class); - let isAddEmitted = false; - fixture.on('add', function(item) { - test.assert( - item instanceof Class, - 'if object added is not an instance should construct instance from it' - ); - test.assert( - fixture.has(item), - 'callback is called after instance is added' - ); - test.assert( - !isAddEmitted, - 'callback should be called for the same item only once' - ); - isAddEmitted = true; - }); - - let object = fixture.add({}); - fixture.add(object); -}; - -exports['test:remove'] = function(test) { - function Class() {} - let fixture = require('utils/registry').Registry(Class); - fixture.on('remove', function(item) { - test.assert( - item instanceof Class, - 'if object removed can be only instance of Class' - ); - test.assert( - fixture.has(item), - 'callback is called before instance is removed' - ); - test.assert( - !isRemoveEmitted, - 'callback should be called for the same item only once' - ); - isRemoveEmitted = true; - }); - - fixture.remove({}); - let object = fixture.add({}); - fixture.remove(object); - fixture.remove(object); -}; - -exports['test:items'] = function(test) { - function Class() {} - let fixture = require('utils/registry').Registry(Class), - actual, - times = 0; - - function testItem(item) { - times ++; - test.assertEqual( - actual, - item, - 'item should match actual item being added/removed' - ); - } - - actual = fixture.add({}); - - fixture.on('add', testItem); - fixture.on('remove', testItem); - - fixture.remove(actual); - fixture.remove(fixture.add(actual = new Class())); - test.assertEqual(3, times, 'should notify listeners on each call'); -} - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-require.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-require.js deleted file mode 100644 index 986a53c..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-require.js +++ /dev/null @@ -1,25 +0,0 @@ -const traceback = require("traceback"); - -exports.test_no_args = function(test) { - var passed = false; - try { - var oops = require(); // leave this on line 6! - } catch(e) { - let msg = e.toString(); - test.assertEqual(msg.indexOf("Error: you must provide a module name when calling require() from "), 0); - test.assertNotEqual(msg.indexOf("test-require"), -1, msg); - // we'd also like to assert that the right filename and linenumber is in - // the stack trace, but this currently doesn't work (see bugs 679591 and - // 551604) - if (0) { - let tb = traceback.fromException(e); - let lastFrame = tb[tb.length-1]; - test.assertNotEqual(lastFrame.filename.indexOf("test-require.js"), -1, - lastFrame.filename); - test.assertEqual(lastFrame.lineNo, 6); - test.assertEqual(lastFrame.funcName, "??"); - } - passed = true; - } - test.assert(passed, 'require() with no args should raise helpful error'); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-self.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-self.js deleted file mode 100644 index 3cc6df5..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-self.js +++ /dev/null @@ -1,29 +0,0 @@ -exports.testSelf = function(test) { - var self = require("self"); - // We can't assert anything about the ID inside the unit test right now, - // because the ID we get depends upon how the test was invoked. The idea - // is that it is supposed to come from the main top-level package's - // package.json file, from the "id" key. - test.assertEqual(typeof(self.id), "string", "self.id is a string"); - test.assert(self.id.length > 0); - - var source = self.data.load("test-content-symbiont.js"); - test.assert(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. - var url = self.data.url("test-content-symbiont.js"); - test.assertEqual(typeof(url), "string", "self.data.url('x') returns string"); - test.assertEqual(/\/test-content-symbiont\.js$/.test(url), true); - - // Make sure 'undefined' is not in url when no string is provided. - url = self.data.url(); - test.assertEqual(typeof(url), "string", "self.data.url() returns string"); - test.assertEqual(/\/undefined$/.test(url), false); - - // When tests are run on just the api-utils package, self.name is - // api-utils. When they're run as 'cfx testall', self.name is testpkgs. - test.assert((self.name == "api-utils") || (self.name == "testpkgs"), - "self.name is api-utils or testpkgs"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-set-exports.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-set-exports.js deleted file mode 100644 index be89305..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-set-exports.js +++ /dev/null @@ -1,31 +0,0 @@ -let four = require("./modules/exportsEquals"); -exports.testExportsEquals = function(test) { - test.assertEqual(four, 4); -} - -/* TODO: Discuss idea of dropping support for this feature that was alternative - to `module.exports = ..` that failed. -let five = require("./modules/setExports"); -exports.testSetExports = function(test) { - test.assertEqual(five, 5); -} - -exports.testDupeSetExports = function(test) { - var passed = false; - try { - var dupe = require('./modules/dupeSetExports'); - } catch(e) { - passed = /define\(\) was used, so module\.exports= and module\.setExports\(\) may not be used/.test(e.toString()); - } - test.assertEqual(passed, true, 'define() or setExports(), not both'); -} -*/ - -exports.testModule = function(test) { - // module.id is not cast in stone yet. In the future, it may include the - // package name, or may possibly be a/ URL of some sort. For now, it's a - // URL that starts with resource: and ends with this module name, but the - // part in between varies depending upon how the test is run. - var found = /test-set-exports$/.test(module.id); - test.assertEqual(found, true, module.id+" ends with test-set-exports.js"); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-browser.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-browser.js deleted file mode 100644 index 10d9614..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-browser.js +++ /dev/null @@ -1,525 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -var timer = require("timer"); -var {Cc,Ci} = require("chrome"); - -function onBrowserLoad(callback, event) { - if (event.target && event.target.defaultView == this) { - this.removeEventListener("load", onBrowserLoad, true); - let browsers = this.document.getElementsByTagName("tabbrowser"); - try { - require("timer").setTimeout(function (window) { - callback(window, browsers[0]); - }, 10, this); - } catch (e) { console.exception(e); } - } -} -// Utility function to open a new browser window. -function openBrowserWindow(callback, url) { - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - let urlString = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - urlString.data = url; - let window = ww.openWindow(null, "chrome://browser/content/browser.xul", - "_blank", "chrome,all,dialog=no", urlString); - if (callback) - window.addEventListener("load", onBrowserLoad.bind(window, callback), true); - - return window; -} - -// Helper for calling code at window close -function closeBrowserWindow(window, callback) { - require("timer").setTimeout(function() { - window.addEventListener("unload", function onUnload() { - window.removeEventListener("unload", onUnload, false); - callback(); - }, false); - window.close(); - }, 0); -} - -// Helper for opening two windows at once -function openTwoWindows(callback) { - openBrowserWindow(function (window1) { - openBrowserWindow(function (window2) { - callback(window1, window2); - }); - }); -} - -// Helper for closing two windows at once -function closeTwoWindows(window1, window2, callback) { - closeBrowserWindow(window1, function() { - closeBrowserWindow(window2, callback); - }); -} - -exports.testAddTab = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(window, browser) { - const tabBrowser = require("tab-browser"); - - let cache = []; - let windowUtils = require("window-utils"); - new windowUtils.WindowTracker({ - onTrack: function(win) { - cache.push(win); - }, - onUntrack: function(win) { - cache.splice(cache.indexOf(win), 1) - } - }); - let startWindowCount = cache.length; - - // Test 1: add a tab - let firstUrl = "data:text/html,one"; - tabBrowser.addTab(firstUrl, { - onLoad: function(e) { - let win1 = cache[startWindowCount - 1]; - test.assertEqual(win1.content.location, firstUrl, "URL of new tab in first window matches"); - - // Test 2: add a tab in a new window - let secondUrl = "data:text/html,two"; - tabBrowser.addTab(secondUrl, { - inNewWindow: true, - onLoad: function(e) { - test.assertEqual(cache.length, startWindowCount + 1, "a new window was opened"); - let win2 = cache[startWindowCount]; - let gBrowser = win2.gBrowser; - gBrowser.addEventListener("DOMContentLoaded", function onLoad(e) { - gBrowser.removeEventListener("DOMContentLoaded", onLoad, false); - test.assertEqual(win2.content.location, secondUrl, "URL of new tab in the new window matches"); - - closeBrowserWindow(win2, function() { - closeBrowserWindow(win1, function() { - test.done(); - }); - }); - }, false); - } - }); - } - }); - }); -}; - -exports.testTrackerWithDelegate = function(test) { - test.waitUntilDone(); - const tabBrowser = require("tab-browser"); - - var delegate = { - state: "initializing", - onTrack: function onTrack(browser) { - if (this.state == "initializing") { - this.state = "waiting for browser window to open"; - } - else if (this.state == "waiting for browser window to open") { - this.state = "waiting for browser window to close"; - require("timer").setTimeout(function() { - closeBrowserWindow(browser.ownerDocument.defaultView, function() { - test.assertEqual(delegate.state, "deinitializing"); - tb.unload(); - test.done(); - }); - }, 0); - } - else - test.fail("invalid state"); - }, - onUntrack: function onUntrack(browser) { - if (this.state == "waiting for browser window to close") { - test.pass("proper state in onUntrack"); - this.state = "deinitializing"; - } - else if (this.state != "deinitializing") - test.fail("invalid state"); - } - }; - var tb = new tabBrowser.Tracker(delegate); - - delegate.state = "waiting for browser window to open"; - - openBrowserWindow(); -}; - -exports.testWhenContentLoaded = function(test) { - test.waitUntilDone(); - const tabBrowser = require("tab-browser"); - - var tracker = tabBrowser.whenContentLoaded( - function(window) { - var item = window.document.getElementById("foo"); - test.assertEqual(item.textContent, "bar", - "whenContentLoaded() works."); - tracker.unload(); - closeBrowserWindow(activeWindow(), function() { - test.done(); - }); - }); - - openBrowserWindow(function(browserWindow, browser) { - var html = '<div id="foo">bar</div>'; - browser.addTab("data:text/html," + html); - }); -}; - -exports.testTrackerWithoutDelegate = function(test) { - test.waitUntilDone(); - const tabBrowser = require("tab-browser"); - - openBrowserWindow(function(browserWindow, browser) { - var tb = new tabBrowser.Tracker(); - - if (tb.length == 0) - test.fail("expect at least one tab browser to exist."); - - for (var i = 0; i < tb.length; i++) - test.assertEqual(tb.get(i).nodeName, "tabbrowser", - "get() method and length prop should work"); - for (var b in tb) - test.assertEqual(b.nodeName, "tabbrowser", - "iterator should work"); - - var matches = [b for (b in tb) - if (b == browser)]; - test.assertEqual(matches.length, 1, - "New browser should be in tracker."); - tb.unload(); - - closeBrowserWindow(browserWindow, function() { - test.done(); - }); - }); -}; - -exports.testTabTracker = function(test) { - test.waitUntilDone(); - const tabBrowser = require("tab-browser"); - - openBrowserWindow(function(browserWindow, browser) { - var delegate = { - tracked: 0, - onTrack: function(tab) { - this.tracked++; - }, - onUntrack: function(tab) { - this.tracked--; - } - }; - - let tabTracker = tabBrowser.TabTracker(delegate); - - let tracked = delegate.tracked; - let url1 = "data:text/html,1"; - let url2 = "data:text/html,2"; - let url3 = "data:text/html,3"; - let tabCount = 0; - - function tabLoadListener(e) { - let loadedURL = e.target.defaultView.location; - if (loadedURL == url1) - tabCount++; - else if (loadedURL == url2) - tabCount++; - else if (loadedURL == url3) - tabCount++; - - if (tabCount == 3) { - test.assertEqual(delegate.tracked, tracked + 3, "delegate tracked tabs matched count"); - tabTracker.unload(); - closeBrowserWindow(browserWindow, function() { - require("timer").setTimeout(function() test.done(), 0); - }); - } - } - - tabBrowser.addTab(url1, { - onLoad: tabLoadListener - }); - tabBrowser.addTab(url2, { - onLoad: tabLoadListener - }); - tabBrowser.addTab(url3, { - onLoad: tabLoadListener - }); - }); -}; - -exports.testActiveTab = function(test) { - test.waitUntilDone(); - openBrowserWindow(function(browserWindow, browser) { - const tabBrowser = require("tab-browser"); - const TabModule = require("tab-browser").TabModule; - let tm = new TabModule(browserWindow); - test.assertEqual(tm.length, 1); - let url1 = "data:text/html,foo"; - let url2 = "data:text/html,bar"; - - function tabURL(tab) tab.ownerDocument.defaultView.content.location.toString() - - tabBrowser.addTab(url1, { - onLoad: function(e) { - // make sure we're running in the right window. - test.assertEqual(tabBrowser.activeTab.ownerDocument.defaultView, browserWindow, "active window matches"); - browserWindow.focus(); - - test.assertEqual(tabURL(tabBrowser.activeTab), url1, "url1 matches"); - let tabIndex = browser.getBrowserIndexForDocument(e.target); - let tabAtIndex = browser.tabContainer.getItemAtIndex(tabIndex); - test.assertEqual(tabAtIndex, tabBrowser.activeTab, "activeTab element matches"); - - tabBrowser.addTab(url2, { - inBackground: true, - onLoad: function() { - test.assertEqual(tabURL(tabBrowser.activeTab), url1, "url1 still matches"); - let tabAtIndex = browser.tabContainer.getItemAtIndex(tabIndex); - test.assertEqual(tabAtIndex, tabBrowser.activeTab, "activeTab element matches"); - closeBrowserWindow(browserWindow, function() { - test.done() - }); - } - }); - } - }); - }); -}; - -// TabModule tests -exports.testEventsAndLengthStayInModule = function(test) { - test.waitUntilDone(); - let TabModule = require("tab-browser").TabModule; - - openTwoWindows(function(window1, window2) { - let tm1 = new TabModule(window1); - let tm2 = new TabModule(window2); - - let counter1 = 0, counter2 = 0; - let counterTabs = 0; - - function onOpenListener() { - ++counterTabs; - if (counterTabs < 5) - return; - test.assertEqual(counter1, 2, "Correct number of events fired from window 1"); - test.assertEqual(counter2, 3, "Correct number of events fired from window 2"); - test.assertEqual(counterTabs, 5, "Correct number of events fired from all windows"); - test.assertEqual(tm1.length, 3, "Correct number of tabs in window 1"); - test.assertEqual(tm2.length, 4, "Correct number of tabs in window 2"); - closeTwoWindows(window1, window2, function() test.done()); - } - - tm1.onOpen = function() ++counter1 && onOpenListener(); - tm2.onOpen = function() ++counter2 && onOpenListener(); - - let url = "data:text/html,default"; - tm1.open(url); - tm1.open(url); - - tm2.open(url); - tm2.open(url); - tm2.open(url); - }); -} - -exports.testTabModuleActiveTab_getterAndSetter = function(test) { - test.waitUntilDone(); - let TabModule = require("tab-browser").TabModule; - - openTwoWindows(function(window1, window2) { - let tm1 = new TabModule(window1); - let tm2 = new TabModule(window2); - - let tab1 = null; - tm1.open({ - url: "data:text/html,<title>window1,tab1</title>", - onOpen: function(tab) tab1 = tab, - }); - tm1.open("data:text/html,<title>window1,tab2</title>"); - - tm1.onActivate = function onActivate() { - tm1.onActivate.remove(onActivate); - require("timer").setTimeout(function() { - test.assertEqual(tm1.activeTab.title, "window1,tab1", "activeTab setter works"); - closeTwoWindows(window1, window2, function() test.done()); - }, 1000); - } - - tm2.open("data:text/html,<title>window2,tab1</title>"); - tm2.open({ - url: "data:text/html,<title>window2,tab2</title>", - onOpen: function(tab4) { - test.assertEqual(tm1.activeTab.title, "window1,tab2", "Correct active tab on window 1"); - test.assertEqual(tm2.activeTab.title, "window2,tab2", "Correct active tab on window 2"); - - tm1.activeTab = tab1; - tm1.activeTab = tab4; // Setting activeTab from another window should have no effect - } - }); - }); -} - -// test tabs iterator -exports.testTabModuleTabsIterator = function(test) { - test.waitUntilDone(); - let TabModule = require("tab-browser").TabModule; - - openBrowserWindow(function(window) { - let tm1 = new TabModule(window); - let url = "data:text/html,default"; - tm1.open(url); - tm1.open(url); - tm1.open({ - url: url, - onOpen: function(tab) { - let count = 0; - for each (let t in tm1) count++; - test.assertEqual(count, 4, "iterated tab count matches"); - test.assertEqual(count, tm1.length, "length tab count matches"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// inNewWindow parameter is ignored on single-window modules -exports.testTabModuleCantOpenInNewWindow = function(test) { - test.waitUntilDone(); - let TabModule = require("tab-browser").TabModule; - - openBrowserWindow(function(window) { - let tm = new TabModule(window); - let url = "data:text/html,default"; - tm.open({ - url: url, - inNewWindow: true, - onOpen: function() { - test.assertEqual(tm.length, 2, "Tab was open on same window"); - closeBrowserWindow(window, function() test.done()); - } - }); - }); -}; - -// Test that having two modules attached to the same -// window won't duplicate events fired on each module -exports.testModuleListenersDontInteract = function(test) { - test.waitUntilDone(); - let TabModule = require("tab-browser").TabModule; - - openBrowserWindow(function(window) { - let tm1 = new TabModule(window); - let tm2 = new TabModule(window); - - let url = "data:text/html,foo"; - let eventCount = 0, eventModule1 = 0, eventModule2 = 0; - - - let listener1 = function() { - // this should be called twice: when tab is open and when - // the url location is changed - eventCount++; - eventModule1++; - } - tm1.onReady = listener1; - - tm2.open({ - url: "about:blank", - onOpen: function(tab) { - // add listener via property assignment - let listener2 = function() { - eventCount++; - eventModule2++; - }; - tab.onReady = listener2; - - // add listener via collection add - let listener3 = function() { - eventCount++; - eventModule2++; - }; - tab.onReady.add(listener3); - - tab.location = url; - - test.waitUntilEqual(function () eventCount, 4, - "Correct global number of events") - .then(function () { - test.assertEqual(eventModule1, 2, - "Correct number of events on module 1"); - test.assertEqual(eventModule2, 2, - "Correct number of events on module 2"); - - tm1.onReady.remove(listener1); - tab.onReady.remove(listener2); - tab.onReady.remove(listener3); - closeBrowserWindow(window, function() test.done()); - }); - } - }); - }); -}; - -/******************* helpers *********************/ - -// Helper for getting the active window -function activeWindow() { - return Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator). - getMostRecentWindow("navigator:browser"); -}; - -// 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. -try { - require("tab-browser"); -} -catch (err) { - // This bug should be mentioned in the error message. - let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=560716"; - if (err.message.indexOf(bug) < 0) - throw err; - for (let [prop, val] in Iterator(exports)) { - if (/^test/.test(prop) && typeof(val) === "function") - delete exports[prop]; - } - exports.testAppNotSupported = function (test) { - test.pass("the tab-browser module does not support this application."); - }; -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-observer.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-observer.js deleted file mode 100644 index b56b1aa..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab-observer.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; - -const { openTab, closeTab } = require("api-utils/tabs/utils"); -const { Loader } = require("./helpers"); -const { setTimeout } = require("timer"); - -exports["test unload tab observer"] = function(assert, done) { - let loader = Loader(module); - - let window = loader.require("api-utils/window-utils").activeBrowserWindow; - let observer = loader.require("api-utils/tabs/observer").observer; - let opened = 0; - let closed = 0; - - observer.on("open", function onOpen(window) { opened++; }); - observer.on("close", function onClose(window) { closed++; }); - - // Open and close tab to trigger observers. - closeTab(openTab(window, "data:text/html,tab-1")); - - // Unload the module so that all listeners set by observer are removed. - loader.unload(); - - // Open and close tab once again. - closeTab(openTab(window, "data:text/html,tab-2")); - - // Enqueuing asserts to make sure that assertion is not performed early. - setTimeout(function () { - assert.equal(1, opened, "observer open was called before unload only"); - assert.equal(1, closed, "observer close was called before unload only"); - done(); - }, 0); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab.js deleted file mode 100644 index 4015faa..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-tab.js +++ /dev/null @@ -1,106 +0,0 @@ -const tabAPI = require("tabs/tab"); -const tabs = require("tabs"); // From addon-kit -const windowUtils = require("window-utils"); - -// The primary test tab -var primaryTab; - -// We have an auxiliary tab to test background tabs. -var auxTab; - -// The window for the outer iframe in the primary test page -var iframeWin; - -exports.testGetTabForWindow = function(test) { - test.waitUntilDone(); - - test.assertEqual(tabAPI.getTabForWindow(windowUtils.activeWindow), null, - "getTabForWindow return null on topwindow"); - test.assertEqual(tabAPI.getTabForWindow(windowUtils.activeBrowserWindow), null, - "getTabForWindow return null on topwindow"); - - let subSubDocument = encodeURIComponent( - 'Sub iframe<br/>'+ - '<iframe id="sub-sub-iframe" src="data:text/html,SubSubIframe" />'); - let subDocument = encodeURIComponent( - 'Iframe<br/>'+ - '<iframe id="sub-iframe" src="data:text/html,'+subSubDocument+'" />'); - let url = 'data:text/html,' + encodeURIComponent( - 'Content<br/><iframe id="iframe" src="data:text/html,'+subDocument+'" />'); - - // Open up a new tab in the background. - // - // This lets us test whether GetTabForWindow works even when the tab in - // question is not active. - tabs.open({ - inBackground: true, - url: "about:mozilla", - onReady: function(tab) { auxTab = tab; step2(url, test);}, - onActivate: function(tab) { step3(test); } - }); -} - -function step2(url, test) { - - tabs.open({ - url: url, - onReady: function(tab) { - primaryTab = tab; - let window = windowUtils.activeBrowserWindow.content; - - let matchedTab = tabAPI.getTabForWindow(window); - test.assertEqual(matchedTab, tab, - "We are able to find the tab with his content window object"); - - let timer = require("timer"); - function waitForFrames() { - let iframe = window.document.getElementById("iframe"); - if (!iframe) { - timer.setTimeout(waitForFrames, 100); - return; - } - iframeWin = iframe.contentWindow; - let subIframe = iframeWin.document.getElementById("sub-iframe"); - if (!subIframe) { - timer.setTimeout(waitForFrames, 100); - return; - } - let subIframeWin = subIframe.contentWindow; - let subSubIframe = subIframeWin.document.getElementById("sub-sub-iframe"); - if (!subSubIframe) { - timer.setTimeout(waitForFrames, 100); - return; - } - let subSubIframeWin = subSubIframe.contentWindow; - - matchedTab = tabAPI.getTabForWindow(iframeWin); - test.assertEqual(matchedTab, tab, - "We are able to find the tab with an iframe window object"); - - matchedTab = tabAPI.getTabForWindow(subIframeWin); - test.assertEqual(matchedTab, tab, - "We are able to find the tab with a sub-iframe window object"); - - matchedTab = tabAPI.getTabForWindow(subSubIframeWin); - test.assertEqual(matchedTab, tab, - "We are able to find the tab with a sub-sub-iframe window object"); - - // Put our primary tab in the background and test again. - // The onActivate listener will take us to step3. - auxTab.activate(); - } - waitForFrames(); - } - }); -} - -function step3(test) { - - let matchedTab = tabAPI.getTabForWindow(iframeWin); - test.assertEqual(matchedTab, primaryTab, - "We get the correct tab even when it's in the background"); - - primaryTab.close(function () { - auxTab.close(function () { test.done();}); - }); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-text-streams.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-text-streams.js deleted file mode 100644 index 2c1c80d..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-text-streams.js +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim:set ts=2 sw=2 sts=2 et filetype=javascript - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Drew Willcoxon <adw@mozilla.com> (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const file = require("file"); -const url = require("url"); -const { Loader } = require("./helpers"); - -const STREAM_CLOSED_ERROR = "The stream is closed and cannot be used."; - -// This should match the constant of the same name in text-streams.js. -const BUFFER_BYTE_LEN = 0x8000; - -exports.testWriteRead = function (test) { - let fname = dataFileFilename(); - - // Write a small string less than the stream's buffer size... - let str = "exports.testWriteRead data!"; - let stream = file.open(fname, "w"); - test.assert(!stream.closed, "stream.closed after open should be false"); - stream.write(str); - stream.close(); - test.assert(stream.closed, "stream.closed after close should be true"); - test.assertRaises(function () stream.close(), - STREAM_CLOSED_ERROR, - "stream.close after already closed should raise error"); - test.assertRaises(function () stream.write("This shouldn't be written!"), - STREAM_CLOSED_ERROR, - "stream.write after close should raise error"); - - // ... and read it. - stream = file.open(fname); - test.assert(!stream.closed, "stream.closed after open should be false"); - test.assertEqual(stream.read(), str, - "stream.read should return string written"); - test.assertEqual(stream.read(), "", - "stream.read at EOS should return empty string"); - stream.close(); - test.assert(stream.closed, "stream.closed after close should be true"); - test.assertRaises(function () stream.close(), - STREAM_CLOSED_ERROR, - "stream.close after already closed should raise error"); - test.assertRaises(function () stream.read(), - STREAM_CLOSED_ERROR, - "stream.read after close should raise error"); - - // Write a big string many times the size of the stream's buffer and read it. - // Since it comes after the previous test, this also ensures that the file is - // truncated when it's opened for writing. - str = ""; - let bufLen = BUFFER_BYTE_LEN; - let fileSize = bufLen * 10; - for (let i = 0; i < fileSize; i++) - str += i % 10; - stream = file.open(fname, "w"); - stream.write(str); - stream.close(); - stream = file.open(fname); - test.assertEqual(stream.read(), str, - "stream.read should return string written"); - stream.close(); - - // The same, but write and read in chunks. - stream = file.open(fname, "w"); - let i = 0; - while (i < str.length) { - // Use a chunk length that spans buffers. - let chunk = str.substr(i, bufLen + 1); - stream.write(chunk); - i += bufLen + 1; - } - stream.close(); - stream = file.open(fname); - let readStr = ""; - bufLen = BUFFER_BYTE_LEN; - let readLen = bufLen + 1; - do { - var frag = stream.read(readLen); - readStr += frag; - } while (frag); - stream.close(); - test.assertEqual(readStr, str, - "stream.write and read in chunks should work as expected"); - - // Read the same file, passing in strange numbers of bytes to read. - stream = file.open(fname); - test.assertEqual(stream.read(fileSize * 100), str, - "stream.read with big byte length should return string " + - "written"); - stream.close(); - - stream = file.open(fname); - test.assertEqual(stream.read(0), "", - "string.read with zero byte length should return empty " + - "string"); - stream.close(); - - stream = file.open(fname); - test.assertEqual(stream.read(-1), "", - "string.read with negative byte length should return " + - "empty string"); - stream.close(); - - file.remove(fname); -}; - -exports.testWriteAsync = function (test) { - test.waitUntilDone(); - - let fname = dataFileFilename(); - let str = "exports.testWriteAsync data!"; - let stream = file.open(fname, "w"); - test.assert(!stream.closed, "stream.closed after open should be false"); - - // Write. - stream.writeAsync(str, function (err) { - test.assertEqual(this, stream, "|this| should be the stream object"); - test.assertEqual(err, undefined, - "stream.writeAsync should not cause error"); - test.assert(stream.closed, "stream.closed after write should be true"); - test.assertRaises(function () stream.close(), - STREAM_CLOSED_ERROR, - "stream.close after already closed should raise error"); - test.assertRaises(function () stream.writeAsync("This shouldn't work!"), - STREAM_CLOSED_ERROR, - "stream.writeAsync after close should raise error"); - - // Read. - stream = file.open(fname, "r"); - test.assert(!stream.closed, "stream.closed after open should be false"); - let readStr = stream.read(); - test.assertEqual(readStr, str, - "string.read should yield string written"); - stream.close(); - file.remove(fname); - test.done(); - }); -}; - -exports.testUnload = function (test) { - let loader = Loader(module); - let file = loader.require("file"); - - let filename = url.toFilename(module.uri); - let stream = file.open(filename); - - loader.unload(); - test.assert(stream.closed, "stream should be closed after module unload"); -}; - -// Returns the name of a file that should be used to test writing and reading. -function dataFileFilename() { - let dir = file.dirname(url.toFilename(module.uri)); - return file.join(dir, "test-text-streams-data"); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-timer.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-timer.js deleted file mode 100644 index 7c995e2..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-timer.js +++ /dev/null @@ -1,127 +0,0 @@ -var timer = require("timer"); -const { Loader } = require("./helpers"); - -exports.testSetTimeout = function(test) { - timer.setTimeout(function() { - test.pass("testSetTimeout passed"); - test.done(); - }, 1); - test.waitUntilDone(); -}; - -exports.testParamedSetTimeout = function(test) { - let params = [1, 'foo', { bar: 'test' }, null, undefined]; - timer.setTimeout.apply(null, [function() { - test.assertEqual(arguments.length, params.length); - for (let i = 0, ii = params.length; i < ii; i++) - test.assertEqual(params[i], arguments[i]); - test.done(); - }, 1].concat(params)); - test.waitUntilDone(); -}; - -exports.testClearTimeout = function(test) { - var myFunc = function myFunc() { - test.fail("myFunc() should not be called in testClearTimeout"); - }; - var id = timer.setTimeout(myFunc, 1); - timer.setTimeout(function() { - test.pass("testClearTimeout passed"); - test.done(); - }, 2); - timer.clearTimeout(id); - test.waitUntilDone(); -}; - -exports.testParamedClearTimeout = function(test) { - let params = [1, 'foo', { bar: 'test' }, null, undefined]; - var myFunc = function myFunc() { - test.fail("myFunc() should not be called in testClearTimeout"); - }; - var id = timer.setTimeout(myFunc, 1); - timer.setTimeout.apply(null, [function() { - test.assertEqual(arguments.length, params.length); - for (let i = 0, ii = params.length; i < ii; i++) - test.assertEqual(params[i], arguments[i]); - test.done(); - }, 1].concat(params)); - timer.clearTimeout(id); - test.waitUntilDone(); -}; - -exports.testSetInterval = function (test) { - var count = 0; - var id = timer.setInterval(function () { - count++; - if (count >= 5) { - timer.clearInterval(id); - test.pass("testSetInterval passed"); - test.done(); - } - }, 1); - test.waitUntilDone(); -}; - -exports.testParamedSetInerval = function(test) { - let params = [1, 'foo', { bar: 'test' }, null, undefined]; - let count = 0; - let id = timer.setInterval.apply(null, [function() { - count ++; - if (count < 5) { - test.assertEqual(arguments.length, params.length); - for (let i = 0, ii = params.length; i < ii; i++) - test.assertEqual(params[i], arguments[i]); - } else { - timer.clearInterval(id); - test.done(); - } - }, 1].concat(params)); - test.waitUntilDone(); -}; - -exports.testClearInterval = function (test) { - timer.clearInterval(timer.setInterval(function () { - test.fail("setInterval callback should not be called"); - }, 1)); - var id = timer.setInterval(function () { - timer.clearInterval(id); - test.pass("testClearInterval passed"); - test.done(); - }, 2); - test.waitUntilDone(); -}; - -exports.testParamedClearInterval = function(test) { - timer.clearInterval(timer.setInterval(function () { - test.fail("setInterval callback should not be called"); - }, 1, timer, {}, null)); - - let id = timer.setInterval(function() { - timer.clearInterval(id); - test.assertEqual(3, arguments.length); - test.done(); - }, 2, undefined, 'test', {}); - test.waitUntilDone(); -}; - - -exports.testUnload = function(test) { - var loader = Loader(module); - var sbtimer = loader.require("timer"); - - var myFunc = function myFunc() { - test.fail("myFunc() should not be called in testUnload"); - }; - - sbtimer.setTimeout(myFunc, 1); - sbtimer.setTimeout(myFunc, 1, 'foo', 4, {}, undefined); - sbtimer.setInterval(myFunc, 1); - sbtimer.setInterval(myFunc, 1, {}, null, 'bar', undefined, 87); - loader.unload(); - timer.setTimeout(function() { - test.pass("timer testUnload passed"); - test.done(); - }, 2); - test.waitUntilDone(); -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traceback.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-traceback.js deleted file mode 100644 index 6cf50f0..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traceback.js +++ /dev/null @@ -1,114 +0,0 @@ -var traceback = require("traceback"); -var {Cc,Ci,Cr,Cu} = require("chrome"); - -function throwNsIException() { - var ios = Cc['@mozilla.org/network/io-service;1'] - .getService(Ci.nsIIOService); - ios.newURI("i'm a malformed URI", null, null); -} - -function throwError() { - throw new Error("foob"); -} - -exports.testFormatDoesNotFetchRemoteFiles = function(test) { - var observers = require("observer-service"); - ["http", "https"].forEach( - function(scheme) { - var httpRequests = 0; - function onHttp() { - httpRequests++; - } - - observers.add("http-on-modify-request", onHttp); - - try { - var tb = [{filename: scheme + "://www.mozilla.org/", - lineNo: 1, - funcName: "blah"}]; - traceback.format(tb); - } catch (e) { - test.exception(e); - } - - observers.remove("http-on-modify-request", onHttp); - - test.assertEqual(httpRequests, 0, - "traceback.format() does not make " + - scheme + " request"); - }); -}; - -exports.testFromExceptionWithString = function(test) { - try { - throw "foob"; - test.fail("an exception should've been thrown"); - } catch (e if e == "foob") { - var tb = traceback.fromException(e); - test.assertEqual(tb.length, 0); - } -}; - -exports.testFormatWithString = function(test) { - // This can happen if e.g. a thrown exception was - // a string instead of an Error instance. - test.assertEqual(traceback.format("blah"), - "Traceback (most recent call last):"); -}; - -exports.testFromExceptionWithError = function(test) { - try { - throwError(); - test.fail("an exception should've been thrown"); - } catch (e if e instanceof Error) { - var tb = traceback.fromException(e); - var xulApp = require("xul-app"); - test.assertEqual(tb.slice(-1)[0].funcName, "throwError"); - } -}; - -exports.testFromExceptionWithNsIException = function(test) { - try { - throwNsIException(); - test.fail("an exception should've been thrown"); - } catch (e if e.result == Cr.NS_ERROR_MALFORMED_URI) { - var tb = traceback.fromException(e); - test.assertEqual(tb.slice(-1)[0].funcName, - "throwNsIException"); - } -}; - -exports.testFormat = function(test) { - function getTraceback() { - return traceback.format(); - } - - var formatted = getTraceback(); - test.assertEqual(typeof(formatted), "string"); - var lines = formatted.split("\n"); - test.assertEqual(lines.slice(-2)[0].indexOf("getTraceback") > 0, - true, - "formatted traceback should include function name"); - test.assertEqual(lines.slice(-1)[0].trim(), - "return traceback.format();", - "formatted traceback should include source code"); -}; - -exports.testExceptionsWithEmptyStacksAreLogged = function(test) { - // Ensures that our fix to bug 550368 works. - var sandbox = Cu.Sandbox("http://www.foo.com"); - var excRaised = false; - try { - Cu.evalInSandbox("returns 1 + 2;", sandbox, "1.8", - "blah.js", 25); - } catch (e) { - excRaised = true; - var stack = traceback.fromException(e); - test.assertEqual(stack.length, 1, "stack should have one frame"); - test.assert(stack[0].filename, "blah.js", "frame should have filename"); - test.assert(stack[0].lineNo, 25, "frame should have line no"); - test.assertEqual(stack[0].funcName, null, "frame should have null function name"); - } - if (!excRaised) - test.fail("Exception should have been raised."); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits-core.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits-core.js deleted file mode 100644 index ecc2c51..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits-core.js +++ /dev/null @@ -1,834 +0,0 @@ -"use strict"; - -const ERR_CONFLICT = 'Remaining conflicting property: ', - ERR_REQUIRED = 'Missing required property: '; - -function assertSametrait(test, trait1, trait2) { - let names1 = Object.getOwnPropertyNames(trait1), - names2 = Object.getOwnPropertyNames(trait2); - - test.assertEqual( - names1.length, - names2.length, - 'equal traits must have same amount of properties' - ); - - for (let i = 0; i < names1.length; i++) { - let name = names1[i]; - test.assertNotEqual( - -1, - names2.indexOf(name), - 'equal traits must contain same named properties: ' + name - ); - assertSameDescriptor(test, name, trait1[name], trait2[name]); - } -} - -function assertSameDescriptor(test, name, desc1, desc2) { - if (desc1.conflict || desc2.conflict) { - test.assertEqual( - desc1.conflict, - desc2.conflict, - 'if one of same descriptors has `conflict` another must have it: ' - + name - ); - } else if (desc1.required || desc2.required) { - test.assertEqual( - desc1.required, - desc2.required, - 'if one of same descriptors is has `required` another must have it: ' - + name - ); - } else { - test.assertEqual( - desc1.get, - desc2.get, - 'get must be the same on both descriptors: ' + name - ); - test.assertEqual( - desc1.set, - desc2.set, - 'set must be the same on both descriptors: ' + name - ); - test.assertEqual( - desc1.value, - desc2.value, - 'value must be the same on both descriptors: ' + name - ); - test.assertEqual( - desc1.enumerable, - desc2.enumerable, - 'enumerable must be the same on both descriptors: ' + name - ); - test.assertEqual( - desc1.required, - desc2.required, - 'value must be the same on both descriptors: ' + name - ); - } -} - -function Data(value, enumerable, confligurable, writable) { - return { - value: value, - enumerable: false !== enumerable, - confligurable: false !== confligurable, - writable: false !== writable - }; -} - -function Method(method, enumerable, confligurable, writable) { - return { - value: method, - enumerable: false !== enumerable, - confligurable: false !== confligurable, - writable: false !== writable - }; -} - -function Accessor(get, set, enumerable, confligurable) { - return { - get: get, - set: set, - enumerable: false !== enumerable, - confligurable: false !== confligurable, - }; -} - -function Required(name) { - function required() { throw new Error(ERR_REQUIRED + name) } - return { - get: required, - set: required, - required: true - }; -} - -function Conflict(name) { - function conflict() { throw new Error(ERR_CONFLICT + name) } - return { - get: conflict, - set: conflict, - conflict: true - }; -} - -function testMethod() {}; - -const { trait, compose, resolve, required, override, create } = - require('traits/core'); - - -exports['test:empty trait'] = function(test) { - assertSametrait( - test, - trait({}), - {} - ); -}; - -exports['test:simple trait'] = function(test) { - assertSametrait( - test, - trait({ - a: 0, - b: testMethod - }), - { - a: Data(0, true, true, true), - b: Method(testMethod, true, true, true) - } - ); -}; - -exports['test:simple trait with required prop'] = function(test) { - assertSametrait( - test, - trait({ - a: required, - b: 1 - }), - { - a: Required('a'), - b: Data(1) - } - ); -}; - -exports['test:ordering of trait properties is irrelevant'] = function(test) { - assertSametrait(test, - trait({ a: 0, b: 1, c: required }), - trait({ b: 1, c: required, a: 0 }) - ); -}; - -exports['test:trait with accessor property'] = function(test) { - let record = { get a() {}, set a(v) {} }; - let get = Object.getOwnPropertyDescriptor(record,'a').get; - let set = Object.getOwnPropertyDescriptor(record,'a').set; - assertSametrait(test, - trait(record), - { a: Accessor(get, set ) } - ); -}; - -exports['test:simple composition'] = function(test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1 }), - trait({ c: 2, d: testMethod }) - ), - { - a: Data(0), - b: Data(1), - c: Data(2), - d: Method(testMethod) - } - ); -}; - -exports['test:composition with conflict'] = function(test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1 }), - trait({ a: 2, c: testMethod }) - ), - { - a: Conflict('a'), - b: Data(1), - c: Method(testMethod) - } - ); -}; - -exports['test:composition of identical props does not cause conflict'] = -function(test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1 }), - trait({ a: 0, c: testMethod }) - ), - { - a: Data(0), - b: Data(1), - c: Method(testMethod) } - ) -}; - -exports['test:composition with identical required props'] = -function(test) { - assertSametrait(test, - compose( - trait({ a: required, b: 1 }), - trait({ a: required, c: testMethod }) - ), - { - a: Required(), - b: Data(1), - c: Method(testMethod) - } - ); -}; - -exports['test:composition satisfying a required prop'] = function (test) { - assertSametrait(test, - compose( - trait({ a: required, b: 1 }), - trait({ a: testMethod }) - ), - { - a: Method(testMethod), - b: Data(1) - } - ); -}; - -exports['test:compose is neutral wrt conflicts'] = function (test) { - assertSametrait(test, - compose( - compose( - trait({ a: 1 }), - trait({ a: 2 }) - ), - trait({ b: 0 }) - ), - { - a: Conflict('a'), - b: Data(0) - } - ); -}; - -exports['test:conflicting prop overrides required prop'] = function (test) { - assertSametrait(test, - compose( - compose( - trait({ a: 1 }), - trait({ a: 2 }) - ), - trait({ a: required }) - ), - { - a: Conflict('a') - } - ); -}; - -exports['test:compose is commutative'] = function (test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1 }), - trait({ c: 2, d: testMethod }) - ), - compose( - trait({ c: 2, d: testMethod }), - trait({ a: 0, b: 1 }) - ) - ); -}; - -exports['test:compose is commutative, also for required/conflicting props'] = -function (test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1, c: 3, e: required }), - trait({ c: 2, d: testMethod }) - ), - compose( - trait({ c: 2, d: testMethod }), - trait({ a: 0, b: 1, c: 3, e: required }) - ) - ); -}; -exports['test:compose is associative'] = function (test) { - assertSametrait(test, - compose( - trait({ a: 0, b: 1, c: 3, d: required }), - compose( - trait({ c: 3, d: required }), - trait({ c: 2, d: testMethod, e: 'foo' }) - ) - ), - compose( - compose( - trait({ a: 0, b: 1, c: 3, d: required }), - trait({ c: 3, d: required }) - ), - trait({ c: 2, d: testMethod, e: 'foo' }) - ) - ); -}; - -exports['test:diamond import of same prop does not generate conflict'] = -function (test) { - assertSametrait(test, - compose( - compose( - trait({ b: 2 }), - trait({ a: 1 }) - ), - compose( - trait({ c: 3 }), - trait({ a: 1 }) - ), - trait({ d: 4 }) - ), - { - a: Data(1), - b: Data(2), - c: Data(3), - d: Data(4) - } - ); -}; - -exports['test:resolve with empty resolutions has no effect'] = -function (test) { - assertSametrait(test, resolve({}, trait({ - a: 1, - b: required, - c: testMethod - })), { - a: Data(1), - b: Required(), - c: Method(testMethod) - }); -}; - -exports['test:resolve: renaming'] = function (test) { - assertSametrait(test, - resolve( - { a: 'A', c: 'C' }, - trait({ a: 1, b: required, c: testMethod }) - ), - { - A: Data(1), - b: Required(), - C: Method(testMethod), - a: Required(), - c: Required() - } - ); -}; - -exports['test:resolve: renaming to conflicting name causes conflict, order 1'] -= function (test) { - assertSametrait(test, - resolve( - { a: 'b'}, - trait({ a: 1, b: 2 }) - ), - { - b: Conflict('b'), - a: Required() - } - ); -}; - -exports['test:resolve: renaming to conflicting name causes conflict, order 2'] -= function (test) { - assertSametrait(test, - resolve( - { a: 'b' }, - trait({ b: 2, a: 1 }) - ), - { - b: Conflict('b'), - a: Required() - } - ); -}; - -exports['test:resolve: simple exclusion'] = function (test) { - assertSametrait(test, - resolve( - { a: undefined }, - trait({ a: 1, b: 2 }) - ), - { - a: Required(), - b: Data(2) - } - ); -}; - -exports['test:resolve: exclusion to "empty" trait'] = function (test) { - assertSametrait(test, - resolve( - { a: undefined, b: undefined }, - trait({ a: 1, b: 2 }) - ), - { - a: Required(), - b: Required() - } - ); -}; - -exports['test:resolve: exclusion and renaming of disjoint props'] = -function (test) { - assertSametrait(test, - resolve( - { a: undefined, b: 'c' }, - trait({ a: 1, b: 2 }) - ), - { - a: Required(), - c: Data(2), - b: Required() - } - ); -}; - -exports['test:resolve: exclusion and renaming of overlapping props'] = -function (test) { - assertSametrait(test, - resolve( - { a: undefined, b: 'a' }, - trait({ a: 1, b: 2 }) - ), - { - a: Data(2), - b: Required() - } - ); -}; - -exports['test:resolve: renaming to a common alias causes conflict'] = -function (test) { - assertSametrait(test, - resolve( - { a: 'c', b: 'c' }, - trait({ a: 1, b: 2 }) - ), - { - c: Conflict('c'), - a: Required(), - b: Required() - } - ); -}; - -exports['test:resolve: renaming overrides required target'] = -function (test) { - assertSametrait(test, - resolve( - { b: 'a' }, - trait({ a: required, b: 2 }) - ), - { - a: Data(2), - b: Required() - } - ); -}; - -exports['test:resolve: renaming required properties has no effect'] = -function (test) { - assertSametrait(test, - resolve( - { b: 'a' }, - trait({ a: 2, b: required }) - ), - { - a: Data(2), - b: Required() - } - ); -}; - -exports['test:resolve: renaming of non-existent props has no effect'] = -function (test) { - assertSametrait(test, - resolve( - { a: 'c', d: 'c' }, - trait({ a: 1, b: 2 }) - ), - { - c: Data(1), - b: Data(2), - a: Required() - } - ); -}; - -exports['test:resolve: exclusion of non-existent props has no effect'] = -function (test) { - assertSametrait(test, - resolve( - { b: undefined }, - trait({ a: 1 }) - ), - { - a: Data(1) - } - ); -}; - -exports['test:resolve is neutral w.r.t. required properties'] = -function (test) { - assertSametrait(test, - resolve( - { a: 'c', b: undefined }, - trait({ a: required, b: required, c: 'foo', d: 1 }) - ), - { - a: Required(), - b: Required(), - c: Data('foo'), - d: Data(1) - } - ); -}; - -exports['test:resolve supports swapping of property names, ordering 1'] = -function (test) { - assertSametrait(test, - resolve( - { a: 'b', b: 'a' }, - trait({ a: 1, b: 2 }) - ), - { - a: Data(2), - b: Data(1) - } - ); -}; - -exports['test:resolve supports swapping of property names, ordering 2'] = -function (test) { - assertSametrait(test, - resolve( - { b: 'a', a: 'b' }, - trait({ a: 1, b: 2 }) - ), - { - a: Data(2), - b: Data(1) - } - ); -}; - -exports['test:resolve supports swapping of property names, ordering 3'] = -function (test) { - assertSametrait(test, - resolve( - { b: 'a', a: 'b' }, - trait({ b: 2, a: 1 }) - ), - { - a: Data(2), - b: Data(1) - } - ); -}; - -exports['test:resolve supports swapping of property names, ordering 4'] = -function (test) { - assertSametrait(test, - resolve( - { a: 'b', b: 'a' }, - trait({ b: 2, a: 1 }) - ), - { - a: Data(2), - b: Data(1) - } - ); -}; - -exports['test:override of mutually exclusive traits'] = function (test) { - assertSametrait(test, - override( - trait({ a: 1, b: 2 }), - trait({ c: 3, d: testMethod }) - ), - { - a: Data(1), - b: Data(2), - c: Data(3), - d: Method(testMethod) - } - ); -}; - -exports['test:override of mutually exclusive traits is compose'] = -function (test) { - assertSametrait(test, - override( - trait({ a: 1, b: 2 }), - trait({ c: 3, d: testMethod }) - ), - compose( - trait({ d: testMethod, c: 3 }), - trait({ b: 2, a: 1 }) - ) - ); -}; - -exports['test:override of overlapping traits'] = function (test) { - assertSametrait(test, - override( - trait({ a: 1, b: 2 }), - trait({ a: 3, c: testMethod }) - ), - { - a: Data(1), - b: Data(2), - c: Method(testMethod) - } - ); -}; - -exports['test:three-way override of overlapping traits'] = function (test) { - assertSametrait(test, - override( - trait({ a: 1, b: 2 }), - trait({ b: 4, c: 3 }), - trait({ a: 3, c: testMethod, d: 5 }) - ), - { - a: Data(1), - b: Data(2), - c: Data(3), - d: Data(5) - } - ); -}; - -exports['test:override replaces required properties'] = function (test) { - assertSametrait(test, - override( - trait({ a: required, b: 2 }), - trait({ a: 1, c: testMethod }) - ), - { - a: Data(1), - b: Data(2), - c: Method(testMethod) - } - ); -}; - -exports['test:override is not commutative'] = function (test) { - assertSametrait(test, - override( - trait({ a: 1, b: 2 }), - trait({ a: 3, c: 4 }) - ), - { - a: Data(1), - b: Data(2), - c: Data(4) - } - ); - - assertSametrait(test, - override( - trait({ a: 3, c: 4 }), - trait({ a: 1, b: 2 }) - ), - { - a: Data(3), - b: Data(2), - c: Data(4) - } - ); -}; - -exports['test:override is associative'] = function (test) { - assertSametrait(test, - override( - override( - trait({ a: 1, b: 2 }), - trait({ a: 3, c: 4, d: 5 }) - ), - trait({ a: 6, c: 7, e: 8 }) - ), - override( - trait({ a: 1, b: 2 }), - override( - trait({ a: 3, c: 4, d: 5 }), - trait({ a: 6, c: 7, e: 8 }) - ) - ) - ); -}; - -exports['test:create simple'] = function(test) { - let o1 = create( - Object.prototype, - trait({ a: 1, b: function() { return this.a; } }) - ); - - test.assertEqual( - Object.prototype, - Object.getPrototypeOf(o1), - 'o1 prototype' - ); - test.assertEqual(1, o1.a, 'o1.a'); - test.assertEqual(1, o1.b(), 'o1.b()'); - test.assertEqual( - 2, - Object.getOwnPropertyNames(o1).length, - 'Object.keys(o1).length === 2' - ); -}; - -exports['test:create with Array.prototype'] = function(test) { - let o2 = create(Array.prototype, trait({})); - test.assertEqual( - Array.prototype, - Object.getPrototypeOf(o2), - "o2 prototype" - ); -}; - -exports['test:exception for incomplete required properties'] = -function(test) { - try { - create(Object.prototype, trait({ foo: required })); - test.fail('expected create to complain about missing required props'); - } catch(e) { - test.assertEqual( - 'Error: Missing required property: foo', - e.toString(), - 'required prop error' - ); - } -}; - -exports['test:exception for unresolved conflicts'] = function(test) { - try { - create({}, compose(trait({ a: 0 }), trait({ a: 1 }))); - test.fail('expected create to complain about unresolved conflicts'); - } catch(e) { - test.assertEqual( - 'Error: Remaining conflicting property: a', - e.toString(), - 'conflicting prop error' - ); - } -}; - -exports['test:verify that required properties are present but undefined'] = -function(test) { - try { - let o4 = Object.create(Object.prototype, trait({ foo: required })); - test.assertEqual(true, 'foo' in o4, 'required property present'); - try { - let foo = o4.foo; - test.fail('access to required property must throw'); - } catch(e) { - test.assertEqual( - 'Error: Missing required property: foo', - e.toString(), - 'required prop error' - ) - } - } catch(e) { - test.fail('did not expect create to complain about required props'); - } -}; - -exports['test:verify that conflicting properties are present'] = -function(test) { - try { - let o5 = Object.create( - Object.prototype, - compose(trait({ a: 0 }), trait({ a: 1 })) - ); - test.assertEqual(true, 'a' in o5, 'conflicting property present'); - try { - let a = o5.a; // accessors or data prop - test.fail('expected conflicting prop to cause exception'); - } catch (e) { - test.assertEqual( - 'Error: Remaining conflicting property: a', - e.toString(), - 'conflicting prop access error' - ); - } - } catch(e) { - test.fail('did not expect create to complain about conflicting props'); - } -}; - -exports['test diamond with conflicts'] = function(test) { - function makeT1(x) trait({ m: function() { return x; } }) - function makeT2(x) compose(trait({ t2: 'foo' }), makeT1(x)) - function makeT3(x) compose(trait({ t3: 'bar' }), makeT1(x)) - - let T4 = compose(makeT2(5), makeT3(5)); - try { - let o = create(Object.prototype, T4); - test.fail('expected diamond prop to cause exception'); - } catch(e) { - test.assertEqual( - 'Error: Remaining conflicting property: m', - e.toString(), - 'diamond prop conflict' - ); - } -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits.js deleted file mode 100644 index 6940616..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-traits.js +++ /dev/null @@ -1,394 +0,0 @@ -"use strict"; - -const { Trait } = require('traits'); - -exports['test:simple compose'] = function(test) { - let List = Trait.compose({ - _list: null, - constructor: function List() { - this._list = []; - }, - list: function list() this._list.slice(0), - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - - test.assertNotEqual(undefined, List, 'should not be undefined'); - test.assertEqual('function', typeof List, 'type should be function'); - test.assertEqual( - Trait.compose, - List.compose, - 'should inherit static compose' - ); - test.assertEqual( - Trait.override, - List.override, - 'should inherit static override' - ); - test.assertEqual( - Trait.required, - List.required, - 'should inherit static required' - ); - test.assertEqual( - Trait.resolve, - List.resolve, - 'should inherit static resolve' - ); - - test.assert( - !('_list' in List.prototype), - 'should not expose private API' - ); -} -exports['test: compose trait instance and create instance'] = function(test) { - let List = Trait.compose({ - constructor: function List(options) { - this._list = []; - this._public.publicMember = options.publicMember; - }, - _privateMember: true, - get privateMember() this._privateMember, - get list() this._list.slice(0), - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list - let index = list.indexOf(item) - if (0 <= index) list.slice(index, 1) - } - }); - let list = List({ publicMember: true }); - - test.assertEqual('object', typeof list, 'should return an object') - test.assertEqual( - true, - list instanceof List, - 'should be instance of a List' - ); - - test.assertEqual( - undefined, - list._privateMember, - 'instance should not expose private API' - ); - - test.assertEqual( - true, - list.privateMember, - 'privates are accessible by public API' - ); - - list._privateMember = false; - - test.assertEqual( - true, - list.privateMember, - 'property changes on instance must not affect privates' - ); - - test.assert( - !('_list' in list), - 'instance should not expose private members' - ); - - test.assertEqual( - true, - list.publicMember, - 'public members are exposed' - ) - test.assertEqual( - 'function', - typeof list.add, - 'should be function' - ) - test.assertEqual( - 'function', - typeof list.remove, - 'should be function' - ); - - list.add(1); - test.assertEqual( - 1, - list.list[0], - 'exposed public API should be able of modifying privates' - ) -}; - - -exports['test:instances must not be hackable'] = function(test) { - let SECRET = 'There is no secret!', - secret = null; - - let Class = Trait.compose({ - _secret: null, - protect: function(data) this._secret = data - }); - - let i1 = Class(); - i1.protect(SECRET); - - test.assertEqual( - undefined, - (function() this._secret).call(i1), - 'call / apply can\'t access private state' - ); - - let proto = Object.getPrototypeOf(i1); - try { - proto.reveal = function() this._secret; - secret = i1.reveal(); - } catch(e) {} - test.assertNotEqual( - SECRET, - secret, - 'public __proto__ changes should not affect privates' - ); - secret = null; - - let Class2 = Trait.compose({ - _secret: null, - protect: function(data) this._secret = data - }); - let i2 = Class2(); - i2.protect(SECRET); - try { - Object.prototype.reveal = function() this._secret; - secret = i2.reveal(); - } catch(e) {} - test.assertNotEqual( - SECRET, - secret, - 'Object.prototype changes must not affect instances' - ); -} - -exports['test:instanceof'] = function(test) { - const List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = [] - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - - test.assert(List() instanceof List, 'Must be instance of List'); - test.assert(new List() instanceof List, 'Must be instance of List'); -}; - -exports['test:privates are unaccessible'] = function(test) { - const List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = []; - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - - let list = List(); - test.assert(!('_list' in list), 'no privates on instance'); - test.assert( - !('_list' in List.prototype), - 'no privates on prototype' - ); -}; - -exports['test:public API can access private API'] = function(test) { - const List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = []; - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - let list = List(); - - list.add('test'); - - test.assertEqual( - 1, - list.length, - 'should be able to add element and access it from public getter' - ); -}; - -exports['test:required'] = function(test) { - const Enumerable = Trait.compose({ - list: Trait.required, - forEach: function forEach(consumer) { - return this.list.forEach(consumer); - } - }); - - try { - let i = Enumerable(); - test.fail('should throw when creating instance with required properties'); - } catch(e) { - test.assertEqual( - 'Error: Missing required property: list', - e.toString(), - 'required prop error' - ); - } -}; - -exports['test:compose with required'] = function(test) { - const List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = []; - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - - const Enumerable = Trait.compose({ - list: Trait.required, - forEach: function forEach(consumer) { - return this.list.forEach(consumer); - } - }); - - const EnumerableList = Enumerable.compose({ - get list() this._list.slice(0) - }, List); - - let array = [1,2, 'ab'] - let l = EnumerableList(array); - array.forEach(function(element) l.add(element)); - let number = 0; - l.forEach(function(element, index) { - number ++; - test.assertEqual(array[index], element, 'should mach array element') - }); - test.assertEqual( - array.length, - number, - 'should perform as many asserts as elements in array' - ); -}; - -exports['test:resolve'] = function(test) { - const List = Trait.compose({ - // private API: - _list: null, - // public API - constructor: function List() { - this._list = []; - }, - get length() this._list.length, - add: function add(item) this._list.push(item), - remove: function remove(item) { - let list = this._list; - let index = list.indexOf(item); - if (0 <= index) list.slice(index, 1); - } - }); - - const Range = List.resolve({ - constructor: null, - add: '_add', - }).compose({ - min: null, - max: null, - get list() this._list.slice(0), - constructor: function Range(min, max) { - this.min = min; - this.max = max; - this._list = []; - }, - add: function(item) { - if (item <= this.max && item >= this.min) - this._add(item) - } - }); - - let r = Range(0, 10); - - test.assertEqual( - 0, - r.min, - 'constructor must have set min' - ); - test.assertEqual( - 10, - r.max, - 'constructor must have set max' - ); - - test.assertEqual( - 0, - r.length, - 'should not contain any elements' - ); - - r.add(5); - - test.assertEqual( - 1, - r.length, - 'should add `5` to list' - ); - - r.add(12); - - test.assertEqual( - 1, - r.length, - 'should not add `12` to list' - ); -}; - -exports['test:custom iterator'] = function(test) { - let Sub = Trait.compose({ - foo: "foo", - bar: "bar", - baz: "baz", - __iterator__: function() { - yield 1; - yield 2; - yield 3; - } - }); - - let (i = 0, sub = Sub()) { - for (let item in sub) - test.assertEqual(++i, item, "iterated item has the right value"); - }; -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-type.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-type.js deleted file mode 100644 index 072075c..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-type.js +++ /dev/null @@ -1,88 +0,0 @@ -"use strict" - -var utils = require("type"); - -exports["test function"] = function (assert) { - assert.ok(utils.isFunction(function(){}), "value is function"); - assert.ok(utils.isFunction(Object), "Object is function"); - assert.ok(utils.isFunction(new Function("")), "Genertaed value is function"); - assert.ok(!utils.isFunction({}), "object is not a function"); - assert.ok(!utils.isFunction(4), "number is not a function"); -}; - -exports["test atoms"] = function (assert) { - assert.ok(utils.isPrimitive(2), "number is primitive"); - assert.ok(utils.isPrimitive(NaN), "`NaN` is primitve"); - assert.ok(utils.isPrimitive(undefined), "`undefined` is primitive"); - assert.ok(utils.isPrimitive(null), "`null` is primitive"); - assert.ok(utils.isPrimitive(Infinity), "`Infinity` is primitive"); - assert.ok(utils.isPrimitive("foo"), "strings are primitive"); - assert.ok(utils.isPrimitive(true) && utils.isPrimitive(false), - "booleans are primitive"); -}; - -exports["test object"] = function (assert) { - assert.ok(utils.isObject({}), "`{}` is object"); - assert.ok(!utils.isObject(null), "`null` is not an object"); - assert.ok(!utils.isObject(Object), "functions is not an object"); -}; - -exports["test flat objects"] = function (assert) { - assert.ok(utils.isFlat({}), "`{}` is a flat object"); - assert.ok(!utils.isFlat([]), "`[]` is not a flat object"); - assert.ok(!utils.isFlat(new function() {}), "derived objects are not flat"); - assert.ok(utils.isFlat(Object.prototype), "Object.prototype is flat"); -}; - -exports["test json atoms"] = function (assert) { - assert.ok(utils.isJSON(null), "`null` is JSON"); - assert.ok(utils.isJSON(undefined), "`undefined` is JSON"); - assert.ok(utils.isJSON(NaN), "`NaN` is JSON"); - assert.ok(utils.isJSON(Infinity), "`Infinity` is JSON"); - assert.ok(utils.isJSON(true) && utils.isJSON(false), "booleans are JSON"); - assert.ok(utils.isJSON(4), utils.isJSON(0), "numbers are JSON"); - assert.ok(utils.isJSON("foo bar"), "strings are JSON"); -}; - -exports["test instanceOf"] = function (assert) { - assert.ok(utils.instanceOf(assert, Object), - "assert is object from other sandbox"); - assert.ok(utils.instanceOf(new Date(), Date), "instance of date"); - assert.ok(!utils.instanceOf(null, Object), "null is not an instance"); -}; - -exports["test json"] = function (assert) { - assert.ok(!utils.isJSON(function(){}), "functions are not json"); - assert.ok(utils.isJSON({}), "`{}` is JSON"); - assert.ok(utils.isJSON({ - a: "foo", - b: 3, - c: undefined, - d: null, - e: { - f: { - g: "bar", - p: [{}, "oueou", 56] - }, - q: { nan: NaN, infinity: Infinity }, - "non standard name": "still works" - } - }), "JSON can contain nested objects"); - - var foo = {}; - var bar = { foo: foo }; - foo.bar = bar; - assert.ok(!utils.isJSON(foo), "recursive objects are not json"); - - - assert.ok(!utils.isJSON({ get foo() { return 5 } }), - "json can not have getter"); - - assert.ok(!utils.isJSON({ foo: "bar", baz: function () {} }), - "json can not contain functions"); - - assert.ok(!utils.isJSON(Object.create({})), - "json must be direct descendant of `Object.prototype`"); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-unit-test.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-unit-test.js deleted file mode 100644 index eeef994..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-unit-test.js +++ /dev/null @@ -1,247 +0,0 @@ -const timer = require("timer"); -const { Loader } = require("./helpers"); - -var setupCalled = false, teardownCalled = false; - -exports.setup = function() { - setupCalled = true; -}; - -exports.teardown = function() { - teardownCalled = true; - setupCalled = false; -}; - -// Important note - unit tests are run in alphabetical order. The following -// unit tests for setup/teardown are order dependent, sometimes the result of -// one test is checked in the next test (testing for teardown does this). When -// tests are cohesively a single unit, they are named <test_name> - partN where -// N is their order in the sequence. Secondly, because these tests should be -// run before all others, they start with an A. -exports.testASetupTeardownSyncTestPart1 = function(test) { - test.assertEqual(true, setupCalled, 'setup function was called before this'); - test.assertEqual(false, teardownCalled, 'teardown function was not called before this'); -}; - -exports.testASetupTeardownSyncTestPart2 = function(test) { - test.assertEqual(true, setupCalled, 'setup was re-called before this'); - test.assertEqual(true, teardownCalled, 'teardown was called after first function'); -}; - -exports.testATeardownAsyncTestPart1 = function(test) { - teardownCalled = false; - - timer.setTimeout(function() { - test.assertEqual(false, teardownCalled, "teardown not called until done"); - test.done(); - }, 200); - test.waitUntilDone(); -}; - -exports.testATeardownAsyncTestPart2 = function(test) { - test.assertEqual(true, teardownCalled, "teardown called after done"); -}; - -exports.testWaitUntilInstant = function(test) { - test.waitUntilDone(); - - test.waitUntil(function () true, "waitUntil with instant true pass") - .then(function () test.done()); -} - -exports.testWaitUntil = function(test) { - test.waitUntilDone(); - let succeed = false; - - test.waitUntil(function () succeed, "waitUntil pass") - .then(function () test.done()); - - timer.setTimeout(function () { - succeed = true; - }, 200); -} - -exports.testWaitUntilEqual = function(test) { - test.waitUntilDone(); - let succeed = false; - - test.waitUntilEqual("foo", function () succeed ? "foo" : "bar", - "waitUntilEqual pass") - .then(function () test.done()); - - timer.setTimeout(function () { - succeed = true; - }, 200); -} - -exports.testWaitUntilNotEqual = function(test) { - test.waitUntilDone(); - let succeed = false; - - test.waitUntilNotEqual("foo", function () succeed ? "bar" : "foo", - "waitUntilNotEqual pass") - .then(function () test.done()); - - timer.setTimeout(function () { - succeed = true; - }, 200); -} - -exports.testWaitUntilMatches = function(test) { - test.waitUntilDone(); - let succeed = false; - - test.waitUntilMatches(function () succeed ? "foo" : "bar", - /foo/, "waitUntilEqual pass") - .then(function () test.done()); - - timer.setTimeout(function () { - succeed = true; - }, 200); -} - -exports.testWaitUntilErrorInCallback = function(test) { - test.waitUntilDone(); - - test.expectFail(function() { - test.waitUntil(function () {throw "oops"}, "waitUntil pass") - .then(function () test.done()); - }); -} - -exports.testWaitUntilTimeoutInCallback = function(test) { - test.waitUntilDone(1000); - - let runner = new (require("unit-test").TestRunner)({ - console: { - calls: 0, - error: function(msg) { - this.calls++; - if (this.calls == 1) - test.assertEqual(arguments[0], "TEST FAILED: wait4ever (timed out)"); - else if (this.calls == 2) { - test.assertEqual(arguments[0], "test assertion never became true:\n"); - test.assertEqual(arguments[1], "assertion failed, value is false\n"); - // We could additionally check that arguments[1] contains the correct - // stack, but it would be difficult to do so given that it contains - // resource: URLs with a randomly generated string embedded in them - // (the ID of the test addon created to run the tests). And in any - // case, checking the arguments seems sufficient. - - test.done(); - } - else { - test.fail("We got unexpected console.error() calls from waitUntil" + - " assertion callback: '" + arguments[1] + "'"); - } - }, - trace: function () {} - } - }); - - runner.start({ - test: { - name: "wait4ever", - testFunction: function(test) { - test.waitUntilDone(100); - test.waitUntil(function() false); - } - }, - onDone: function() {} - }); -}; - -exports.testExpectFail = function(test) { - test.expectFail(function() { - test.fail('expectFail masking .fail'); - }); - - test.expectFail(function() { - test.assert(false, 'expectFail masking .assert'); - }); - - test.assert(true, 'assert should pass with no expectFail'); -/* - test.expectFail(function() { - test.expectFail(function() { - test.fail('this should blow up'); - }); - }); -*/ -}; - -exports.testAssertFunction = function(test) { - test.assertFunction(function() {}, 'assertFunction with function'); - test.expectFail(function() { - test.assertFunction(null, 'assertFunction with non-function'); - }); -}; - -exports.testAssertUndefined = function(test) { - test.assertUndefined(undefined, 'assertUndefined with undefined'); - test.expectFail(function() { - test.assertUndefined(null, 'assertUndefined with null'); - }); - test.expectFail(function() { - test.assertUndefined(false, 'assertUndefined with false'); - }); - test.expectFail(function() { - test.assertUndefined(0, 'assertUndefined with 0'); - }); -}; - -exports.testAssertNotUndefined = function(test) { - test.expectFail(function() { - test.assertNotUndefined(undefined, 'assertNotUndefined with undefined'); - }); - test.assertNotUndefined(null, 'assertNotUndefined with null'); - test.assertNotUndefined(false, 'assertNotUndefined with false'); - test.assertNotUndefined(0, 'assertNotUndefined with 0'); -}; - -exports.testAssertNull = function(test) { - test.assertNull(null, 'assertNull with null'); - test.expectFail(function() { - test.assertNull(undefined, 'assertNull with undefined'); - }); - test.expectFail(function() { - test.assertNull(false, 'assertNull with false'); - }); - test.expectFail(function() { - test.assertNull(0, 'assertNull with 0'); - }); -}; - -exports.testAssertNotNull = function(test) { - test.assertNotNull(undefined, 'assertNotNull with undefined'); - test.assertNotNull(false, 'assertNotNull with false'); - test.assertNotNull(0, 'assertNotNull with 0'); - - test.expectFail(function() { - test.assertNotNull(null, 'testAssertNotNull with null'); - }); -}; - -exports.testAssertObject = function(test) { - test.assertObject({}, 'assertObject with {}' ); - test.assertObject(new Object(), 'assertObject with new Object'); - test.expectFail(function() { - test.assertObject('fail', 'assertObject with string'); - }); -}; - -exports.testAssertString = function(test) { - test.assertString('', 'assertString with ""'); - test.assertString(new String(), 'assertString with new String'); -}; - -exports.testAssertArray = function(test) { - test.assertArray([], 'assertArray with []'); - test.assertArray(new Array(), 'assertArray with new Array'); -}; - -exports.testNumber = function(test) { - test.assertNumber(1, 'assertNumber with 1'); - test.assertNumber(new Number('2'), 'assertNumber with new Number("2")' ); -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-unload.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-unload.js deleted file mode 100644 index 33e84d0..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-unload.js +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> (Original Author) - * Drew Willcoxon <adw@mozilla.com> - * Erik Vold <erikvvold@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -var unload = require("unload"); -var { Loader } = require("./helpers"); - -exports.testUnloading = function(test) { - var loader = Loader(module); - var ul = loader.require("unload"); - var unloadCalled = 0; - var errorsReported = 0; - function unload() { - unloadCalled++; - throw new Error("error"); - } - ul.when(unload); - - // This should be ignored, as we already registered it - ul.when(unload); - - function unload2() { unloadCalled++; } - ul.when(unload2); - loader.unload(undefined, function onError() { errorsReported++; }); - test.assertEqual(unloadCalled, 2, - "Unloader functions are called on unload."); - test.assertEqual(errorsReported, 1, - "One unload handler threw exception"); -}; - -exports.testEnsure = function(test) { - test.assertRaises(function() { unload.ensure({}); }, - "object has no 'unload' property", - "passing obj with no unload prop should fail"); - test.assertRaises(function() { unload.ensure({}, "destroy"); }, - "object has no 'destroy' property", - "passing obj with no custom unload prop should fail"); - - var called = 0; - var obj = {unload: function() { called++; }}; - - unload.ensure(obj); - obj.unload(); - test.assertEqual(called, 1, - "unload() should be called"); - obj.unload(); - test.assertEqual(called, 1, - "unload() should be called only once"); -}; - -/** - * Check that destructors are called only once with Traits. - * - check that public API is calling the destructor and unregister it, - * - check that composed traits with multiple ensure calls, leads to only - * one destructor call. - */ -exports.testEnsureWithTraits = function(test) { - - let { Trait } = require("traits"); - let loader = Loader(module); - let ul = loader.require("unload"); - - let called = 0; - let composedCalled = 0; - let composedTrait = Trait.compose({ - constructor: function () { - // We have to give "public interface" of this trait, as we want to - // call public `unload` method and ensure that we call it only once, - // either when we call this public function manually or on add-on unload - ul.ensure(this._public); - }, - unload: function unload() { - composedCalled++; - } - }); - let obj = Trait.compose( - composedTrait.resolve({ - constructor: "_constructor", - unload : "_unload" - }), { - constructor: function constructor() { - // Same thing applies here, we need to pass public interface - ul.ensure(this._public); - this._constructor(); - }, - unload: function unload() { - called++; - this._unload(); - } - })(); - - obj.unload(); - test.assertEqual(called, 1, - "unload() should be called"); - - test.assertEqual(composedCalled, 1, - "composed object unload() should be called"); - - obj.unload(); - test.assertEqual(called, 1, - "unload() should be called only once"); - test.assertEqual(composedCalled, 1, - "composed object unload() should be called only once"); - - loader.unload(); - test.assertEqual(called, 1, - "unload() should be called only once, after addon unload"); - test.assertEqual(composedCalled, 1, - "composed object unload() should be called only once, " + - "after addon unload"); -}; - -exports.testEnsureWithTraitsPrivate = function(test) { - - let { Trait } = require("traits"); - let loader = Loader(module); - let ul = loader.require("unload"); - - let called = 0; - let privateObj = null; - let obj = Trait.compose({ - constructor: function constructor() { - // This time wa don't have to give public interface, - // as we want to call a private method: - ul.ensure(this, "_unload"); - privateObj = this; - }, - _unload: function unload() { - called++; - this._unload(); - } - })(); - - loader.unload(); - test.assertEqual(called, 1, - "unload() should be called"); - - privateObj._unload(); - test.assertEqual(called, 1, - "_unload() should be called only once, after addon unload"); -}; - -exports.testReason = function (test) { - var reason = "Reason doesn't actually have to be anything in particular."; - var loader = Loader(module); - var ul = loader.require("unload"); - ul.when(function (rsn) { - test.assertEqual(rsn, reason, - "when() reason should be reason given to loader"); - }); - var obj = { - unload: function (rsn) { - test.assertEqual(rsn, reason, - "ensure() reason should be reason given to loader"); - } - }; - ul.ensure(obj); - loader.unload(reason); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-url.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-url.js deleted file mode 100644 index 3307769..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-url.js +++ /dev/null @@ -1,157 +0,0 @@ -var url = require("url"); - -exports.testResolve = function(test) { - test.assertEqual(url.URL("bar", "http://www.foo.com/").toString(), - "http://www.foo.com/bar"); - - test.assertEqual(url.URL("bar", "http://www.foo.com"), - "http://www.foo.com/bar"); - - test.assertEqual(url.URL("http://bar.com/", "http://foo.com/"), - "http://bar.com/", - "relative should override base"); - - test.assertRaises(function() { url.URL("blah"); }, - "malformed URI: blah", - "url.resolve() should throw malformed URI on base"); - - test.assertRaises(function() { url.URL("chrome://global"); }, - "invalid URI: chrome://global", - "url.resolve() should throw invalid URI on base"); - - test.assertRaises(function() { url.URL("chrome://foo/bar"); }, - "invalid URI: chrome://foo/bar", - "url.resolve() should throw on bad chrome URI"); - - test.assertEqual(url.URL("", "http://www.foo.com"), - "http://www.foo.com/", - "url.resolve() should add slash to end of domain"); -}; - -exports.testParseHttp = function(test) { - var info = url.URL("http://foo.com/bar"); - test.assertEqual(info.scheme, "http"); - test.assertEqual(info.host, "foo.com"); - test.assertEqual(info.port, null); - test.assertEqual(info.userPass, null); - test.assertEqual(info.path, "/bar"); -}; - -exports.testParseHttpWithPort = function(test) { - var info = url.URL("http://foo.com:5/bar"); - test.assertEqual(info.port, 5); -}; - -exports.testParseChrome = function(test) { - var info = url.URL("chrome://global/content/blah"); - test.assertEqual(info.scheme, "chrome"); - test.assertEqual(info.host, "global"); - test.assertEqual(info.port, null); - test.assertEqual(info.userPass, null); - test.assertEqual(info.path, "/content/blah"); -}; - -exports.testParseAbout = function(test) { - var info = url.URL("about:boop"); - test.assertEqual(info.scheme, "about"); - test.assertEqual(info.host, null); - test.assertEqual(info.port, null); - test.assertEqual(info.userPass, null); - test.assertEqual(info.path, "boop"); -}; - -exports.testParseFTP = function(test) { - var info = url.URL("ftp://1.2.3.4/foo"); - test.assertEqual(info.scheme, "ftp"); - test.assertEqual(info.host, "1.2.3.4"); - test.assertEqual(info.port, null); - test.assertEqual(info.userPass, null); - test.assertEqual(info.path, "/foo"); -}; - -exports.testParseFTPWithUserPass = function(test) { - var info = url.URL("ftp://user:pass@1.2.3.4/foo"); - test.assertEqual(info.userPass, "user:pass"); -}; - -exports.testToFilename = function(test) { - test.assertRaises( - function() { url.toFilename("resource://nonexistent"); }, - "resource does not exist: resource://nonexistent/", - "url.toFilename() on nonexistent resources should throw" - ); - - test.assertMatches(url.toFilename(module.uri), - /.*test-url\.js$/, - "url.toFilename() on resource: URIs should work"); - - test.assertRaises( - function() { url.toFilename("http://foo.com/"); }, - "cannot map to filename: http://foo.com/", - "url.toFilename() on http: URIs should raise error" - ); - - try { - test.assertMatches( - url.toFilename("chrome://global/content/console.xul"), - /.*console\.xul$/, - "url.toFilename() w/ console.xul works when it maps to filesystem" - ); - } catch (e) { - if (/chrome url isn\'t on filesystem/.test(e.message)) - test.pass("accessing console.xul in jar raises exception"); - else - test.fail("accessing console.xul raises " + e); - } - - // TODO: Are there any chrome URLs that we're certain exist on the - // filesystem? - // test.assertMatches(url.toFilename("chrome://myapp/content/main.js"), - // /.*main\.js$/); -}; - -exports.testFromFilename = function(test) { - var fileUrl = url.fromFilename(url.toFilename(module.uri)); - test.assertEqual(url.URL(fileUrl).scheme, 'file', - 'url.toFilename() should return a file: url'); - test.assertEqual(url.fromFilename(url.toFilename(fileUrl)), - fileUrl); -}; - -exports.testURL = function(test) { - let URL = url.URL; - test.assert(URL("h:foo") instanceof URL, "instance is of correct type"); - test.assertRaises(function() URL(), - "malformed URI: undefined", - "url.URL should throw on undefined"); - test.assertRaises(function() URL(""), - "malformed URI: ", - "url.URL should throw on empty string"); - test.assertRaises(function() URL("foo"), - "malformed URI: foo", - "url.URL should throw on invalid URI"); - test.assert(URL("h:foo").scheme, "has scheme"); - test.assertEqual(URL("h:foo").toString(), - "h:foo", - "toString should roundtrip"); - // test relative + base - test.assertEqual(URL("mypath", "http://foo").toString(), - "http://foo/mypath", - "relative URL resolved to base"); - // test relative + no base - test.assertRaises(function() URL("path").toString(), - "malformed URI: path", - "no base for relative URI should throw"); - - let a = URL("h:foo"); - let b = URL(a); - test.assertEqual(b.toString(), - "h:foo", - "a URL can be initialized from another URL"); - test.assertNotStrictEqual(a, b, - "a URL initialized from another URL is not the same object"); - test.assert(a == "h:foo", - "toString is implicit when a URL is compared to a string via =="); - test.assertStrictEqual(a + "", "h:foo", - "toString is implicit when a URL is concatenated to a string"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-loader.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-loader.js deleted file mode 100644 index fc6f144..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-loader.js +++ /dev/null @@ -1,152 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Irakli Gozalishvili <gozala@mozilla.com> (Original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -"use strict"; - -const { WindowLoader } = require('windows/loader'), - { Trait } = require('traits'); - -const Loader = Trait.compose( - WindowLoader, - { - constructor: function Loader(options) { - this._onLoad = options.onLoad; - this._onUnload = options.onUnload; - if ('window' in options) - this._window = options.window; - this._load(); - this.window = this._window; - }, - window: null, - _onLoad: null, - _onUnload: null, - _tabOptions: [] - } -); - -exports['test compositions with missing required properties'] = function(test) { - test.assertRaises( - function() WindowLoader.compose({})(), - 'Missing required property: _onLoad', - 'should throw missing required property exception' - ); - test.assertRaises( - function() WindowLoader.compose({ _onLoad: null, _tabOptions: null })(), - 'Missing required property: _onUnload', - 'should throw missing required property `_onUnload`' - ); - test.assertRaises( - function() WindowLoader.compose({ _onUnload: null, _tabOptions: null })(), - 'Missing required property: _onLoad', - 'should throw missing required property `_onLoad`' - ); - test.assertRaises( - function() WindowLoader.compose({ _onUnload: null, _onLoad: null })(), - 'Missing required property: _tabOptions', - 'should throw missing required property `_tabOptions`' - ); -}; - -exports['test `load` events'] = function(test) { - test.waitUntilDone(); - let onLoadCalled = false; - Loader({ - onLoad: function(window) { - onLoadCalled = true; - test.assertEqual( - window, this._window, 'windows should match' - ); - test.assertEqual( - window.document.readyState, 'complete', 'window must be fully loaded' - ); - window.close(); - }, - onUnload: function(window) { - test.assertEqual( - window, this._window, 'windows should match' - ); - test.assertEqual( - window.document.readyState, 'complete', 'window must be fully loaded' - ); - test.assert(onLoadCalled, 'load callback is supposed to be called'); - test.done(); - } - }); -}; - -exports['test removeing listeners'] = function(test) { - test.waitUntilDone(); - Loader({ - onLoad: function(window) { - test.assertEqual( - window, this._window, 'windows should match' - ); - window.close(); - }, - onUnload: function(window) { - test.done(); - } - }); -}; - -exports['test create loader from opened window'] = function(test) { - test.waitUntilDone(); - let onUnloadCalled = false; - Loader({ - onLoad: function(window) { - test.assertEqual( - window, this._window, 'windows should match' - ); - test.assertEqual( - window.document.readyState, 'complete', 'window must be fully loaded' - ); - Loader({ - window: window, - onLoad: function(win) { - test.assertEqual(win, window, 'windows should match'); - window.close(); - }, - onUnload: function(window) { - test.assert(onUnloadCalled, 'first handler should be called already'); - test.done(); - } - }); - }, - onUnload: function(window) { - onUnloadCalled = true; - } - }); -}; - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-observer.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-observer.js deleted file mode 100644 index 3f3bfc2..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-observer.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; - -const { Loader } = require("./helpers"); - -exports["test unload window observer"] = function(assert, done) { - // Hacky way to be able to create unloadable modules via makeSandboxedLoader. - let loader = Loader(module); - - let utils = loader.require("api-utils/window-utils"); - let { isBrowser, activeBrowserWindow: activeWindow } = utils; - let observer = loader.require("api-utils/windows/observer").observer; - let opened = 0; - let closed = 0; - - observer.on("open", function onOpen(window) { - // Ignoring non-browser windows - if (isBrowser(window)) - opened++; - }); - observer.on("close", function onClose(window) { - // Ignore non-browser windows & already opened `activeWindow` (unload will - // emit close on it even though it is not actually closed). - if (isBrowser(window) && window !== activeWindow) - closed++; - }); - - // Open window and close it to trigger observers. - activeWindow.open().close(); - - // Unload the module so that all listeners set by observer are removed. - loader.unload(); - - // Open and close window once again. - activeWindow.open().close(); - - // Enqueuing asserts to make sure that assertion is not performed early. - require("timer").setTimeout(function () { - assert.equal(1, opened, "observer open was called before unload only"); - assert.equal(1, closed, "observer close was called before unload only"); - done(); - }, 0); -}; - -require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-utils.js deleted file mode 100644 index eff9f2b..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-window-utils.js +++ /dev/null @@ -1,271 +0,0 @@ -var windowUtils = require("window-utils"); -var timer = require("timer"); -var {Cc,Ci} = require("chrome"); -var { Loader } = require("./helpers"); - -function makeEmptyWindow() { - var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - var blankXul = ('<?xml version="1.0"?>' + - '<?xml-stylesheet href="chrome://global/skin/" ' + - ' type="text/css"?>' + - '<window xmlns="' + xulNs + '" windowtype="test:window">' + - '</window>'); - var url = "data:application/vnd.mozilla.xul+xml," + escape(blankXul); - var features = ["chrome", "width=10", "height=10"]; - - var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Ci.nsIWindowWatcher); - return ww.openWindow(null, url, null, features.join(","), null); -} - -exports.testCloseOnUnload = function(test) { - var timesClosed = 0; - var fakeWindow = { - _listeners: [], - addEventListener: function(name, func, bool) { - this._listeners.push(func); - }, - removeEventListener: function(name, func, bool) { - var index = this._listeners.indexOf(func); - if (index == -1) - throw new Error("event listener not found"); - this._listeners.splice(index, 1); - }, - close: function() { - timesClosed++; - this._listeners.forEach( - function(func) { - func({target: fakeWindow.document}); - }); - }, - document: { - get defaultView() { return fakeWindow; } - } - }; - - let loader = Loader(module); - loader.require("window-utils").closeOnUnload(fakeWindow); - test.assertEqual(fakeWindow._listeners.length, 1, - "unload listener added on closeOnUnload()"); - test.assertEqual(timesClosed, 0, - "window not closed when registered."); - loader.require("unload").send(); - test.assertEqual(timesClosed, 1, - "window closed on module unload."); - test.assertEqual(fakeWindow._listeners.length, 0, - "unload event listener removed on module unload"); - - timesClosed = 0; - loader.require("window-utils").closeOnUnload(fakeWindow); - test.assertEqual(timesClosed, 0, - "window not closed when registered."); - fakeWindow.close(); - test.assertEqual(timesClosed, 1, - "window closed when close() called."); - test.assertEqual(fakeWindow._listeners.length, 0, - "unload event listener removed on window close"); - loader.require("unload").send(); - test.assertEqual(timesClosed, 1, - "window not closed again on module unload."); - loader.unload(); -}; - -exports.testWindowWatcher = function(test) { - var myWindow; - var finished = false; - - var delegate = { - onTrack: function(window) { - if (window == myWindow) { - test.pass("onTrack() called with our test window"); - timer.setTimeout(function() { myWindow.close(); }, 1); - } - }, - onUntrack: function(window) { - if (window == myWindow) { - test.pass("onUntrack() called with our test window"); - timer.setTimeout(function() { - if (!finished) { - finished = true; - myWindow = null; - wt.unload(); - test.done(); - } else - test.fail("finishTest() called multiple times."); - }, 1); - } - } - }; - - var wt = new windowUtils.WindowTracker(delegate); - myWindow = makeEmptyWindow(); - test.waitUntilDone(5000); -}; - -// test that _unregWindow calls _unregLoadingWindow -exports.testWindowWatcherUnregs4LoadingWindows = function(test) { - var myWindow; - var finished = false; - let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getMostRecentWindow("navigator:browser"); - var counter = 0; - - var delegate = { - onTrack: function(window) { - var type = window.document.documentElement.getAttribute("windowtype"); - if (type == "test:window") - test.fail("onTrack shouldn't have been executed."); - } - }; - var wt = new windowUtils.WindowTracker(delegate); - - // make a new window - myWindow = makeEmptyWindow(); - - // make sure that the window hasn't loaded yet - test.assertNotEqual( - myWindow.document.readyState, - "complete", - "window hasn't loaded yet."); - - // unload WindowTracker - wt.unload(); - - // make sure that the window still hasn't loaded, which means that the onTrack - // would have been removed successfully assuming that it doesn't execute. - test.assertNotEqual( - myWindow.document.readyState, - "complete", - "window still hasn't loaded yet."); - - // wait for the window to load and then close it. onTrack wouldn't be called - // until the window loads, so we must let it load before closing it to be - // certain that onTrack was removed. - myWindow.addEventListener("load", function() { - // allow all of the load handles to execute before closing - myWindow.setTimeout(function() { - myWindow.addEventListener("unload", function() { - // once the window unloads test is done - test.done(); - }, false); - myWindow.close(); - }, 0); - }, false); - - test.waitUntilDone(5000); -} - -exports.testWindowWatcherWithoutUntracker = function(test) { - var myWindow; - var finished = false; - - var delegate = { - onTrack: function(window) { - if (window == myWindow) { - test.pass("onTrack() called with our test window"); - timer.setTimeout(function() { - myWindow.close(); - - if (!finished) { - finished = true; - myWindow = null; - wt.unload(); - test.done(); - } else { - test.fail("onTrack() called multiple times."); - } - }, 1); - } - } - }; - - var wt = new windowUtils.WindowTracker(delegate); - myWindow = makeEmptyWindow(); - test.waitUntilDone(5000); -}; - -exports.testActiveWindow = function(test) { - test.waitUntilDone(5000); - - let testRunnerWindow = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getMostRecentWindow("test:runner"); - let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getMostRecentWindow("navigator:browser"); - - test.assertEqual(windowUtils.activeBrowserWindow, browserWindow, - "Browser window is the active browser window."); - - - let testSteps = [ - function() { - windowUtils.activeWindow = browserWindow; - continueAfterFocus(browserWindow); - }, - function() { - test.assertEqual(windowUtils.activeWindow, browserWindow, - "Correct active window [1]"); - continueAfterFocus(windowUtils.activeWindow = testRunnerWindow); - }, - function() { - test.assertEqual(windowUtils.activeWindow, testRunnerWindow, - "Correct active window [2]"); - test.assertEqual(windowUtils.activeBrowserWindow, browserWindow, - "Correct active browser window [3]"); - continueAfterFocus(windowUtils.activeWindow = browserWindow); - }, - function() { - test.assertEqual(windowUtils.activeWindow, browserWindow, - "Correct active window [4]"); - continueAfterFocus(windowUtils.activeWindow = testRunnerWindow); - }, - function() { - test.assertEqual(windowUtils.activeWindow, testRunnerWindow, - "Correct active window [5]"); - test.assertEqual(windowUtils.activeBrowserWindow, browserWindow, - "Correct active browser window [6]"); - testRunnerWindow = null; - browserWindow = null; - test.done() - } - ]; - - let nextTest = function() { - let func = testSteps.shift(); - if (func) { - func(); - } - } - - function continueAfterFocus(targetWindow) { - - // Based on SimpleTest.waitForFocus - var fm = Cc["@mozilla.org/focus-manager;1"]. - getService(Ci.nsIFocusManager); - - var childTargetWindow = {}; - fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow); - childTargetWindow = childTargetWindow.value; - - var focusedChildWindow = {}; - if (fm.activeWindow) { - fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow); - focusedChildWindow = focusedChildWindow.value; - } - - var focused = (focusedChildWindow == childTargetWindow); - if (focused) { - nextTest(); - } else { - childTargetWindow.addEventListener("focus", function focusListener() { - childTargetWindow.removeEventListener("focus", focusListener, true); - nextTest(); - }, true); - } - - } - - nextTest(); -} diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xhr.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-xhr.js deleted file mode 100644 index 2912139..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xhr.js +++ /dev/null @@ -1,70 +0,0 @@ -var xhr = require("xhr"); -var timer = require("timer"); -var { Loader } = require("./helpers"); - -/* Test is intentionally disabled until platform bug 707256 is fixed. -exports.testAbortedXhr = function(test) { - var req = new xhr.XMLHttpRequest(); - test.assertEqual(xhr.getRequestCount(), 1); - req.abort(); - test.assertEqual(xhr.getRequestCount(), 0); -}; -*/ - -exports.testLocalXhr = function(test) { - var req = new xhr.XMLHttpRequest(); - req.overrideMimeType("text/plain"); - req.open("GET", module.uri); - req.onreadystatechange = function() { - if (req.readyState == 4 && req.status == 0) { - test.assertMatches(req.responseText, - /onreadystatechange/, - "XMLHttpRequest should get local files"); - timer.setTimeout( - function() { test.assertEqual(xhr.getRequestCount(), 0); - test.done(); }, - 0 - ); - } - }; - req.send(null); - test.assertEqual(xhr.getRequestCount(), 1); - test.waitUntilDone(4000); -}; - -exports.testUnload = function(test) { - var loader = Loader(module); - var sbxhr = loader.require("xhr"); - var req = new sbxhr.XMLHttpRequest(); - req.overrideMimeType("text/plain"); - req.open("GET", module.uri); - req.send(null); - test.assertEqual(sbxhr.getRequestCount(), 1); - loader.unload(); - test.assertEqual(sbxhr.getRequestCount(), 0); -}; - -exports.testDelegatedReturns = function(test) { - var req = new xhr.XMLHttpRequest(); - req.overrideMimeType("text/plain"); - req.open("GET", module.uri); - req.onreadystatechange = function() { - if (req.readyState == 4 && req.status == 0) { - // This response isn't going to have any headers, so the return value - // should be null. Previously it wasn't returning anything, and thus was - // undefined. - - // Depending on whether Bug 608939 has been applied - // to the platform, getAllResponseHeaders() may return - // null or the empty string; accept either. - var headers = req.getAllResponseHeaders(); - test.assert(headers === null || headers === "", - "XHR's delegated methods should return"); - test.done(); - } - }; - req.send(null); - test.assertEqual(xhr.getRequestCount(), 1); - test.waitUntilDone(4000); -} - diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xpcom.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-xpcom.js deleted file mode 100644 index fdcb6e8..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xpcom.js +++ /dev/null @@ -1,107 +0,0 @@ -var traceback = require("traceback"); -var xpcom = require("xpcom"); -var {Cc,Ci,Cm,Cr} = require("chrome"); -var { Loader } = require("./helpers"); - -exports.testRegister = function(test, text) { - if (!text) - text = "hai2u"; - - function Component() {} - - Component.prototype = { - newChannel : function(aURI) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - - var channel = ios.newChannel( - "data:text/plain," + text, - null, - null - ); - - channel.originalURI = aURI; - return channel; - }, - getURIFlags: function(aURI) { - return Ci.nsIAboutModule.ALLOW_SCRIPT; - }, - QueryInterface: xpcom.utils.generateQI([Ci.nsIAboutModule]) - }; - - var contractID = "@mozilla.org/network/protocol/about;1?what=boop"; - - var factory = xpcom.register({name: "test about:boop page", - contractID: contractID, - create: Component}); - - var manager = Cm.QueryInterface(Ci.nsIComponentRegistrar); - test.assertEqual(manager.isCIDRegistered(factory.uuid), true); - - // We don't want to use Cc[contractID] here because it's immutable, - // so it can't accept updated versions of a contractID during the - // same application session. - var aboutFactory = xpcom.getClass(contractID, Ci.nsIFactory); - - test.assertNotEqual(aboutFactory.wrappedJSObject, - undefined, - "Factory wrappedJSObject should exist."); - - var about = aboutFactory.createInstance(null, Ci.nsIAboutModule); - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - test.assertEqual( - about.getURIFlags(ios.newURI("http://foo.com", null, null)), - Ci.nsIAboutModule.ALLOW_SCRIPT - ); - - var aboutURI = ios.newURI("about:boop", null, null); - var channel = ios.newChannelFromURI(aboutURI); - var iStream = channel.open(); - var siStream = Cc['@mozilla.org/scriptableinputstream;1'] - .createInstance(Ci.nsIScriptableInputStream); - siStream.init(iStream); - var data = new String(); - data += siStream.read(-1); - siStream.close(); - iStream.close(); - test.assertEqual(data, text); - - factory.unregister(); - test.assertEqual(manager.isCIDRegistered(factory.uuid), false); -}; - -exports.testReRegister = function(test) { - exports.testRegister(test, "hai2u again"); -}; - -exports.testMakeUuid = function(test) { - var first = xpcom.makeUuid().toString(); - var second = xpcom.makeUuid().toString(); - test.assertMatches(first, /{[0-9a-f\-]+}/); - test.assertMatches(second, /{[0-9a-f\-]+}/); - test.assertNotEqual(first, second); -}; - -exports.testUnload = function(test) { - var loader = Loader(module); - var sbxpcom = loader.require("xpcom"); - - function Component() {} - - Component.prototype = { - QueryInterface: sbxpcom.utils.generateQI([Ci.nsISupports]) - }; - - var contractID = "@mozilla.org/blargle;1"; - var factory = sbxpcom.register({name: "test component", - contractID: contractID, - create: Component}); - - var manager = Cm.QueryInterface(Ci.nsIComponentRegistrar); - test.assertEqual(manager.isCIDRegistered(factory.uuid), true); - - loader.unload(); - - test.assertEqual(manager.isCIDRegistered(factory.uuid), false); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xul-app.js b/tools/addon-sdk-1.4/packages/api-utils/tests/test-xul-app.js deleted file mode 100644 index cda4a2e..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/test-xul-app.js +++ /dev/null @@ -1,41 +0,0 @@ -var xulApp = require("xul-app"); - -exports.testXulApp = function(test) { - test.assertEqual(typeof(xulApp.ID), "string", - "ID is a string"); - test.assertEqual(typeof(xulApp.name), "string", - "name is a string"); - test.assertEqual(typeof(xulApp.version), "string", - "version is a string"); - test.assertEqual(typeof(xulApp.platformVersion), "string", - "platformVersion is a string"); - - test.assertRaises(function() { xulApp.is("blargy"); }, - "Unkown Mozilla Application: blargy", - "is() throws error on bad app name"); - test.assertRaises(function() { xulApp.isOneOf(["blargy"]); }, - "Unkown Mozilla Application: blargy", - "isOneOf() throws error on bad app name"); - - function testSupport(name) { - var item = xulApp.is(name); - test.assert(item === true || item === false, - "is('" + name + "') is true or false."); - } - - var apps = ["Firefox", "Mozilla", "Sunbird", "SeaMonkey", - "Fennec", "Thunderbird"]; - - apps.forEach(function(name) { testSupport(name); }); - - test.assert(xulApp.isOneOf(apps) == true || - xulApp.isOneOf(apps) == false, - "isOneOf() returns true or false."); - - test.assertEqual(xulApp.versionInRange(xulApp.platformVersion, "1.9", "*"), - true, "platformVersion in range [1.9, *)"); - test.assertEqual(xulApp.versionInRange("3.6.4", "3.6.4", "3.6.*"), - true, "3.6.4 in [3.6.4, 3.6.*)"); - test.assertEqual(xulApp.versionInRange("1.9.3", "1.9.2", "1.9.3"), - false, "1.9.3 not in [1.9.2, 1.9.3)"); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/assert.js b/tools/addon-sdk-1.4/packages/api-utils/tests/traits/assert.js deleted file mode 100644 index dd662a4..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/assert.js +++ /dev/null @@ -1,94 +0,0 @@ -"use strict"; - -var BaseAssert = require("test/assert").Assert; - -/** - * Whether or not given property descriptors are equivalent. They are - * equivalent either if both are marked as "conflict" or "required" property - * or if all the properties of descriptors are equal. - * @param {Object} actual - * @param {Object} expected - */ -function equivalentDescriptors(actual, expected) { - return (actual.conflict && expected.conflict) || - (actual.required && expected.required) || - equalDescriptors(actual, expected); -} - -function equalDescriptors(actual, expected) { - return actual.get === expected.get && - actual.set === expected.set && - actual.value === expected.value && - !!actual.enumerable === !!expected.enumerable && - !!actual.configurable === !!expected.configurable && - !!actual.writable === !!expected.writable; -} - -/** - * Whether or not given `target` array contains all the element - * from a given `source` array. - */ -function containsSet(source, target) { - return source.some(function(element) { - return 0 > target.indexOf(element); - }); -} - -/** - * Whether or not given two arrays contain all elements from another. - */ -function equivalentSets(source, target) { - return containsSet(source, target) && containsSet(target, source); -} - -/** - * Finds name of the property from `source` property descriptor map, that - * is not equivalent of the name named property in the `target` property - * descriptor map. If not found `null` is returned instead. - */ -function findNonEquivalentPropertyName(source, target) { - var value = null; - Object.getOwnPropertyNames(source).some(function(key) { - var areEquivalent = false; - if (!equivalentDescriptors(source[key], target[key])) { - value = key; - areEquivalent = true; - } - return areEquivalent; - }); - return value; -} - -var AssertDescriptor = { - equalTraits: { - value: function equivalentTraits(actual, expected, message) { - var difference; - var actualKeys = Object.getOwnPropertyNames(actual); - var expectedKeys = Object.getOwnPropertyNames(expected); - - if (equivalentSets(actualKeys, expectedKeys)) { - this.fail({ - operator: "equalTraits", - message: "Traits define different properties", - actual: actualKeys.sort().join(","), - expected: expectedKeys.sort().join(","), - }); - } - else if ((difference = findNonEquivalentPropertyName(actual, expected))) { - this.fail({ - operator: "equalTraits", - message: "Traits define non-equivalent property `" + difference + "`", - actual: actual[difference], - expected: expected[difference] - }); - } - else { - this.pass(message || "Traits are equivalent."); - } - } - } -}; - -exports.Assert = function Assert() { - return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor); -}; diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/descriptor-tests.js b/tools/addon-sdk-1.4/packages/api-utils/tests/traits/descriptor-tests.js deleted file mode 100644 index 7c27ac4..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/descriptor-tests.js +++ /dev/null @@ -1,331 +0,0 @@ -"use strict"; - -var Trait = require("light-traits").Trait; -var utils = require("./utils"); -var Data = utils.Data; -var Method = utils.Method; -var Accessor = utils.Accessor; -var Required = utils.Required; -var Conflict = utils.Conflict; - -function method() {} - -exports.Assert = require("./assert").Assert -exports["test simple composition"] = function(assert) { - var actual = Trait.compose( - Trait({ a: 0, b: 1 }), - { c: { value: 2 }, d: { value: method, enumerable: true } } - ); - - var expected = { - a: Data(0), - b: Data(1), - c: Data(2, false, false, false), - d: Method(method, true, false, false) - }; - - assert.equalTraits(actual, expected); -}; - -exports["test composition with conflict"] = function(assert) { - var actual = Trait.compose( - Trait({ a: 0, b: 1 }), - { - a: { - value: 2, - writable: true, - configurable: true, - enumerable: true - }, - c: { - value: method, - configurable: true - } - } - ); - - var expected = { - a: Conflict("a"), - b: Data(1), - c: Method(method, false, true, false) - }; - - assert.equalTraits(actual, expected); -}; - -exports["test identical props does not cause conflict"] = function(assert) { - var actual = Trait.compose( - { - a: { - value: 0, - writable: true, - configurable: true, - enumerable: true - }, - b: { - value: 1 - } - }, - Trait({ - a: 0, - c: method - }) - ); - - var expected = { - a: Data(0), - b: Data(1, false, false, false), - c: Method(method) - } - - assert.equalTraits(actual, expected); -}; - -exports["test composition with identical required props"] = function(assert) { - var actual = Trait.compose( - Trait({ a: Trait.required, b: 1 }), - { a: { required: true }, c: { value: method } } - ); - - var expected = { - a: Required(), - b: Data(1), - c: Method(method, false, false, false) - }; - - assert.equalTraits(actual, expected); -}; - -exports["test composition satisfying a required prop"] = function(assert) { - var actual = Trait.compose( - Trait({ a: Trait.required, b: 1 }), - { a: { value: method, enumerable: true } } - ); - - var expected = { - a: Method(method, true, false, false), - b: Data(1) - }; - - assert.equalTraits(actual, expected); -}; - -exports["test compose is neutral wrt conflicts"] = function(assert) { - var actual = Trait.compose( - Trait({ a: { value: 1 } }, Trait({ a: 2 })), - { b: { value: 0, writable: true, configurable: true, enumerable: false } } - ); - - var expected = { a: Conflict("a"), b: Data(0, false) }; - - assert.equalTraits(actual, expected); -}; - -exports["test conflicting prop overrides Trait.required"] = function(assert) { - var actual = Trait.compose( - Trait.compose( - Trait({ a: 1 }), - { a: { value: 2 } } - ), - { a: { value: Trait.required } } - ); - - var expected = { a: Conflict("a") }; - - assert.equalTraits(actual, expected); -}; - -exports["test compose is commutative"] = function(assert) { - var actual = Trait.compose( - Trait({ a: 0, b: 1 }), - { c: { value: 2 }, d: { value: method } } - ); - - var expected = Trait.compose( - { c: { value: 2 }, d: { value: method } }, - Trait({ a: 0, b: 1 }) - ); - - assert.equalTraits(actual, expected); -} - -exports["test compose is commutative, also for required/conflicting props"] = function(assert) { - var actual = Trait.compose( - { - a: { value: 0 }, - b: { value: 1 }, - c: { value: 3 }, - e: { value: Trait.required } - }, - { - c: { value: 2 }, - d: { get: method } - } - ); - - var expected = Trait.compose( - Trait({ c: 3 }), - { - c: { value: 2 }, - d: { get: method }, - a: { value: 0 }, - b: { value: 1 }, - e: { value: Trait.required }, - } - ); - - assert.equalTraits(actual, expected); -}; - -exports["test compose is associative"] = function(assert) { - var actual = Trait.compose( - { - a: { value: 0 }, - b: { value: 1 }, - c: { value: 3 }, - d: { value: Trait.required } - }, - Trait.compose( - { c: { value: 3 }, d: { value: Trait.required } }, - { c: { value: 2 }, d: { value: method }, e: { value: "foo" } } - ) - ); - - var expected = Trait.compose( - Trait.compose( - { - a: { value: 0 }, - b: { value: 1 }, - c: { value: 3 }, - d: { value: Trait.required } - }, - { - c: { value: 3 }, - d: { value: Trait.required } - } - ), - { - c: { value: 2 }, - d: { value: method }, - e: { value: "foo" } - } - ); - - assert.equalTraits(actual, expected); -}; - -exports["test diamond import of same prop do not conflict"] = function(assert) { - var actual = Trait.compose( - Trait.compose( - { b: { value: 2 } }, - { a: { value: 1, enumerable: true, configurable: true, writable: true } } - ), - Trait.compose( - { c: { value: 3 } }, - Trait({ a: 1 }) - ), - Trait({ d: 4 }) - ); - - var expected = { - a: Data(1), - b: Data(2, false, false, false), - c: Data(3, false, false, false), - d: Data(4) - }; - - assert.equalTraits(actual, expected); -}; - -exports["test create simple"] = function(assert) { - var o1 = Trait.compose( - Trait({ a: 1 }), - { - b: { - value: function() { - return this.a; - } - } - } - ).create(Object.prototype); - - assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype"); - assert.equal(1, o1.a, "o1.a"); - assert.equal(1, o1.b(), "o1.b()"); - assert.equal(Object.keys(o1).length, 1, "Object.keys(o1).length === 2"); -}; - -exports["test create with Array.prototype"] = function(assert) { - var o2 = Trait.compose({}, {}).create(Array.prototype); - assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype"); -}; - -exports["test exception for incomplete required properties"] = function(assert) { - assert.throws(function() { - Trait({ foo: Trait.required }).create(Object.prototype) - }, /Missing required property: `foo`/, "required prop error"); -} - -exports["test exception for unresolved conflicts"] = function(assert) { - assert.throws(function() { - Trait(Trait({ a: 0 }), Trait({ a: 1 })).create({}) - }, /Remaining conflicting property: `a`/, "conflicting prop error"); -} - -exports["test conflicting properties are present"] = function(assert) { - var o5 = Object.create(Object.prototype, Trait.compose( - { a: { value: 0 } }, - { a: { value: 1 } } - )); - - assert.ok("a" in o5, "conflicting property present"); - assert.throws(function() { - o5.a - }, /Remaining conflicting property: `a`/, "conflicting prop access error"); -}; - -exports["test diamond with conflicts"] = function(assert) { - function makeT1(x) { - return { - m: { - value: function() { - return x - } - } - }; - }; - - function makeT2(x) { - return Trait.compose( - Trait({ t2: "foo" }), - makeT1(x) - ); - }; - - function makeT3(x) { - return Trait.compose( - { - t3: { value: "bar" } - }, - makeT1(x) - ); - }; - - var T4 = Trait.compose(makeT2(5), makeT3(5)); - - assert.throws(function() { - T4.create(Object.prototype); - }, /Remaining conflicting property: `m`/, "diamond prop conflict"); -}; - -exports["test providing requirements through proto"] = function(assert) { - var t = Trait.compose( - {}, - { required: { required: true } } - ).create({ required: "test" }); - - assert.equal(t.required, "test", "property from proto is inherited"); -}; - -if (module == require.main) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/inheritance-tests.js b/tools/addon-sdk-1.4/packages/api-utils/tests/traits/inheritance-tests.js deleted file mode 100644 index 73a23b7..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/inheritance-tests.js +++ /dev/null @@ -1,100 +0,0 @@ -"use strict"; - -var Trait = require("light-traits").Trait; - -exports["test custom constructor and inherited toString"] = function(assert) { - function Type() { - return Object.create(Type.prototype); - } - Type.prototype = Trait({ - method: function method() { - return 2; - } - }).create(Object.freeze(Type.prototype)); - - var fixture = Type(); - - assert.equal(fixture.constructor, Type, "must override constructor"); - assert.equal(fixture.toString(), "[object Type]", "must inherit toString"); -}; - -exports["test custom toString and inherited constructor"] = function(assert) { - function Type() { - return Object.create(Type.prototype); - } - Type.prototype = Trait({ - toString: function toString() { - return "<toString>"; - } - }).create(); - - var fixture = Type(); - - assert.equal(fixture.constructor, Trait, "must inherit constructor Trait"); - assert.equal(fixture.toString(), "<toString>", "Must override toString"); -}; - -exports["test custom toString and constructor"] = function(assert) { - function Type() { - return TypeTrait.create(Type.prototype); - } - Object.freeze(Type.prototype); - var TypeTrait = Trait({ - toString: function toString() { - return "<toString>"; - } - }); - - var fixture = Type(); - - assert.equal(fixture.constructor, Type, "constructor is provided to create"); - assert.equal(fixture.toString(), "<toString>", "toString was overridden"); -}; - -exports["test resolve constructor"] = function (assert) { - function Type() {} - var T1 = Trait({ constructor: Type }).resolve({ constructor: '_foo' }); - var f1 = T1.create(); - - assert.equal(f1._foo, Type, "constructor was resolved"); - assert.equal(f1.constructor, Trait, "constructor of prototype is inherited"); - assert.equal(f1.toString(), "[object Trait]", "toString is inherited"); -}; - -exports["test compose read-only"] = function (assert) { - function Type() {} - Type.prototype = Trait.compose(Trait({}), { - constructor: { value: Type }, - a: { value: "b", enumerable: true } - }).resolve({ a: "b" }).create({ a: "a" }); - - var f1 = new Type(); - - assert.equal(Object.getPrototypeOf(f1), Type.prototype, "inherits correctly"); - assert.equal(f1.constructor, Type, "constructor was overridden"); - assert.equal(f1.toString(), "[object Type]", "toString was inherited"); - assert.equal(f1.a, "a", "property a was resolved"); - assert.equal(f1.b, "b", "property a was renamed to b"); - assert.ok(!Object.getOwnPropertyDescriptor(Type.prototype, "a"), - "a is not on the prototype of the instance"); - - var proto = Object.getPrototypeOf(Type.prototype); - var dc = Object.getOwnPropertyDescriptor(Type.prototype, "constructor"); - var db = Object.getOwnPropertyDescriptor(Type.prototype, "b"); - var da = Object.getOwnPropertyDescriptor(proto, "a"); - - assert.ok(!dc.writable, "constructor is not writable"); - assert.ok(!dc.enumerable, "constructor is not enumerable"); - assert.ok(dc.configurable, "constructor inherits configurability"); - - assert.ok(!db.writable, "a -> b is not writable"); - assert.ok(db.enumerable, "a -> b is enumerable"); - assert.ok(!db.configurable, "a -> b is not configurable"); - - assert.ok(da.writable, "a is writable"); - assert.ok(da.enumerable, "a is enumerable"); - assert.ok(da.configurable, "a is configurable"); -}; - -if (require.main == module) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/object-tests.js b/tools/addon-sdk-1.4/packages/api-utils/tests/traits/object-tests.js deleted file mode 100644 index afea3ce..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/object-tests.js +++ /dev/null @@ -1,317 +0,0 @@ -"use strict"; - -var Trait = require("light-traits").Trait; -var utils = require("./utils"); -var Data = utils.Data; -var Method = utils.Method; -var Accessor = utils.Accessor; -var Required = utils.Required; -var Conflict = utils.Conflict; - -function method() {} - -exports.Assert = require("./assert").Assert; - -exports["test empty trait"] = function (assert) { - assert.equalTraits(Trait({}), {}); -}; - -exports["test simple trait"] = function (assert) { - var expected = { - a: Data(0, true, true, true), - b: Method(method, true, true, true) - }; - - assert.equalTraits(Trait({ a: 0, b: method }), expected); -}; - -exports["test simple trait with Trait.required property"] = function (assert) { - var actual = Trait({ a: Trait.required, b: 1 }); - var expected = { a: Required("a"), b: Data(1) }; - - assert.equalTraits(actual, expected); -}; - -exports["test ordering of trait properties is irrelevant"] = function (assert) { - var actual = Trait({ a: 0, b: 1, c: Trait.required }); - var expected = Trait({ b: 1, c: Trait.required, a: 0 }); - - assert.equalTraits(actual, expected); -}; - -exports["test trait with accessor property"] = function (assert) { - var record = { get a() {}, set a(v) {} }; - var get = Object.getOwnPropertyDescriptor(record, "a").get; - var set = Object.getOwnPropertyDescriptor(record, "a").set; - - assert.equalTraits(Trait(record), { a: Accessor(get, set) }); -}; - -exports["test simple composition"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method })); - var expected = { a: Data(0), b: Data(1), c: Data(2), d: Method(method) }; - - assert.equalTraits(actual, expected); -}; - -exports["test composition with conflict"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 2, c: method })); - var expected = { a: Conflict("a"), b: Data(1), c: Method(method) }; - - assert.equalTraits(actual, expected); -}; - -exports["test composition of identical props does not cause conflict"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 0, c: method })); - - assert.equalTraits(actual, { a: Data(0), b: Data(1), c: Method(method) }); -}; - -exports["test composition with identical Trait.required props"] = function (assert) { - var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }), - Trait({ a: Trait.required, c: method })); - - assert.equalTraits(actual, { a: Required(), b: Data(1), c: Method(method) }); -}; - -exports["test composition satisfying a Trait.required prop"] = function (assert) { - var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }), - Trait({ a: method })); - - assert.equalTraits(actual, { a: Method(method), b: Data(1) }); -}; - -exports["test compose is neutral wrt conflicts"] = function (assert) { - var actual = Trait.compose(Trait.compose(Trait({ a: 1 }), Trait({ a: 2 })), - Trait({ b: 0 })); - - assert.equalTraits(actual, { a: Conflict("a"), b: Data(0) }); -}; - -exports["test conflicting prop overrides Trait.required prop"] = function (assert) { - var actual = Trait.compose(Trait.compose(Trait({ a: 1 }), - Trait({ a: 2 })), - Trait({ a: Trait.required })); - - assert.equalTraits(actual, { a: Conflict("a") }); -}; - -exports["test compose is commutative"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method })); - var expected = Trait.compose(Trait({ c: 2, d: method }), - Trait({ a: 0, b: 1 })); - - assert.equalTraits(actual, expected); -}; - -exports["test compose is commutative, also for Trait.required/conflicting props"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, e: Trait.required }), - Trait({ c: 2, d: method })); - - var expected = Trait.compose(Trait({ c: 2, d: method }), - Trait({ a: 0, b: 1, c: 3, e: Trait.required })); - - assert.equalTraits(actual, expected); -}; - -exports["test compose is associative"] = function (assert) { - var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }), - Trait.compose(Trait({ c: 3, d: Trait.required }), - Trait({ c: 2, d: method, - e: "foo" }))); - - var expected = Trait.compose( - Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }), - Trait({ c: 3, d: Trait.required })), - Trait({ c: 2, d: method, e: "foo" })); - - assert.equalTraits(actual, expected); -}; - -exports["test diamond import of same prop does not generate conflict"] = function (assert) { - var actual = Trait.compose(Trait.compose(Trait({ b: 2 }), Trait({ a: 1 })), - Trait.compose(Trait({ c: 3 }), Trait({ a: 1 })), - Trait({ d: 4 })); - var expected = { a: Data(1), b: Data(2), c: Data(3), d: Data(4) }; - - assert.equalTraits(actual, expected); -}; - -exports["test resolve with empty resolutions has no effect"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: Trait.required, c: method }).resolve({}), - { a: Data(1), b: Required(), c: Method(method) }); -}; - -exports["test resolve: renaming"] = function (assert) { - var actual = Trait({ a: 1, b: Trait.required, c: method }); - - assert.equalTraits(actual.resolve({ a: "A", c: "C" }), - { A: Data(1), b: Required(), C: Method(method), - a: Required(), c: Required() }); -}; - -exports["test resolve: renaming to conflicting name causes conflict, order 1"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b" }), - { b: Conflict("b"), a: Required() }); -}; - -exports["test resolve: renaming to conflicting name causes conflict, order 2"] = function (assert) { - assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b" }), - { b: Conflict("b"), a: Required() }); -}; - -exports["test resolve: simple exclusion"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined }), - { a: Required(), b: Data(2) }); -}; - -exports["test resolve: exclusion to empty trait"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: null, b: undefined }), - { a: Required(), b: Required() }); -}; - -exports["test resolve: exclusion and renaming of disjoint props"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "c" }), - { a: Required(), c: Data(2), b: Required() }); -}; - -exports["test resolve: exclusion and renaming of overlapping props"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "a" }), - { a: Data(2), b: Required() }); -}; - -exports["test resolve: renaming to a common alias causes conflict"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", b: "c" }), - { c: Conflict("c"), a: Required(), b: Required() }); -}; - -exports["test resolve: renaming overrides Trait.required target"] = function (assert) { - assert.equalTraits(Trait({ a: Trait.required, b: 2 }).resolve({ b: "a" }), - { a: Data(2), b: Required() }); -}; - -exports["test resolve: renaming Trait.required properties has no effect"] = function (assert) { - assert.equalTraits(Trait({ a: 2, b: Trait.required }).resolve({ b: "a" }), - { a: Data(2), b: Required() }); -}; - -exports["test resolve: renaming of non-existent props has no effect"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", d: "c" }), - { c: Data(1), b: Data(2), a: Required() }); -}; - -exports["test resolve: exclusion of non-existent props has no effect"] = function (assert) { - assert.equalTraits(Trait({ a: 1 }).resolve({ b: undefined }), { a: Data(1) }); -}; - -exports["test resolve is neutral w.r.t. Trait.required properties"] = function (assert) { - var actual = Trait({ a: Trait.required, b: Trait.required, c: "foo", d: 1 }); - var expected = { a: Required(), b: Required(), c: Data("foo"), d: Data(1) }; - assert.equalTraits(actual.resolve({ a: "c", b: undefined }), expected); -}; - -exports["test resolve supports swapping of property names, ordering 1"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b", b: "a" }), - { a: Data(2), b: Data(1) }); -}; - -exports["test resolve supports swapping of property names, ordering 2"] = function (assert) { - assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ b: "a", a: "b" }), - { a: Data(2), b: Data(1) }); -}; - -exports["test resolve supports swapping of property names, ordering 3"] = function (assert) { - assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ b: "a", a: "b" }), - { a: Data(2), b: Data(1) }); -}; - -exports["test resolve supports swapping of property names, ordering 4"] = function (assert) { - assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b", b: "a" }), - { a: Data(2), b: Data(1) }); -}; - -exports["test create simple"] = function (assert) { - var o1 = Trait({ - a: 1, - b: function () { - return this.a; - } - }).create(Object.prototype); - - assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype"); - assert.equal(1, o1.a, "o1.a"); - assert.equal(1, o1.b(), "o1.b()"); - assert.equal(Object.keys(o1).length, 2, "Object.keys(o1).length === 2"); -}; - -exports["test create with Array.prototype"] = function (assert) { - var o2 = Trait({}).create(Array.prototype); - assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype"); -}; - -exports["test exception for incomplete required properties"] = function (assert) { - assert.throws(function () { - Trait({ foo: Trait.required }).create(Object.prototype); - }, /Missing required property: `foo`/, "required prop error"); -}; - -exports["test exception for unresolved conflicts"] = function (assert) { - assert.throws(function () { - Trait.compose(Trait({ a: 0 }), Trait({ a: 1 })).create({}); - }, /Remaining conflicting property: `a`/, "conflicting prop error"); -}; - -exports["test verify that required properties are present but undefined"] = function (assert) { - var o4 = Object.create(Object.prototype, Trait({ foo: Trait.required })); - - assert.ok("foo" in o4, "required property present"); - assert.throws(function () { - o4.foo; - }, /Missing required property: `foo`/, "required prop error"); -}; - -exports["test verify that conflicting properties are present"] = function (assert) { - var o5 = Object.create(Object.prototype, Trait.compose(Trait({ a: 0 }), - Trait({ a: 1 }))); - - assert.ok("a" in o5, "conflicting property present"); - assert.throws(function () { - o5.a; - }, /Remaining conflicting property: `a`/, "conflicting prop access error"); -}; - -exports["test diamond with conflicts"] = function (assert) { - function makeT1(x) { - return Trait({ - m: function () { - return x - } - }) - }; - - function makeT2(x) { - return Trait.compose(Trait({ - t2: "foo" - }), makeT1(x)); - }; - - function makeT3(x) { - return Trait.compose(Trait({ - t3: "bar" - }), makeT1(x)); - }; - - var T4 = Trait.compose(makeT2(5), makeT3(5)); - - assert.throws(function () { - T4.create(Object.prototype); - }, /Remaining conflicting property: `m`/, "diamond prop conflict"); -}; - -exports["test providing requirements through proto"] = function (assert) { - var t = Trait({ required: Trait.required }).create({ required: "test" }); - assert.equal(t.required, "test", "property from proto is inherited"); -}; - -if (module == require.main) - require("test").run(exports); diff --git a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/utils.js b/tools/addon-sdk-1.4/packages/api-utils/tests/traits/utils.js deleted file mode 100644 index 5647fb9..0000000 --- a/tools/addon-sdk-1.4/packages/api-utils/tests/traits/utils.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; - -var ERR_CONFLICT = "Remaining conflicting property: "; -var ERR_REQUIRED = "Missing required property: "; - -exports.Data = function Data(value, enumerable, configurable, writable) { - return ({ - value: value, - enumerable: enumerable !== false, - configurable: configurable !== false, - writable: writable !== false - }); -}; - -exports.Method = function Method(method, enumerable, configurable, writable) { - return ({ - value: method, - enumerable: enumerable !== false, - configurable: configurable !== false, - writable: writable !== false - }); -}; - -exports.Accessor = function Accessor(get, set, enumerable, configurable) { - return ({ - get: get, - set: set, - enumerable: enumerable !== false, - configurable: configurable !== false - }); -}; - -exports.Required = function Required(name) { - function required() { throw new Error(ERR_REQUIRED + name) } - - return ({ - get: required, - set: required, - required: true - }); -}; - -exports.Conflict = function Conflict(name) { - function conflict() { throw new Error(ERR_CONFLICT + name) } - - return ({ - get: conflict, - set: conflict, - conflict: true - }); -}; - diff --git a/tools/addon-sdk-1.4/packages/development-mode/README.md b/tools/addon-sdk-1.4/packages/development-mode/README.md deleted file mode 100644 index af674d1..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/README.md +++ /dev/null @@ -1,8 +0,0 @@ -This package contains a program that pings a local server for -information about other programs to run. If the same program -is requested more than once, it is first unloaded before being run -again. This can be very useful for developing add-ons without -having to restart the parent application. - -In the future, functionality will be added that allows developers to -debug and profile their programs' behavior. diff --git a/tools/addon-sdk-1.4/packages/development-mode/docs/bootstrap.md b/tools/addon-sdk-1.4/packages/development-mode/docs/bootstrap.md deleted file mode 100644 index 2e0156a..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/docs/bootstrap.md +++ /dev/null @@ -1,6 +0,0 @@ -This module contains functionality that allows a program to -"bootstrap" other programs: that is, set up a runtime -environment for them and execute them. - -At present, the functions defined by this module are -implementation-specific and subject to change. diff --git a/tools/addon-sdk-1.4/packages/development-mode/docs/main.md b/tools/addon-sdk-1.4/packages/development-mode/docs/main.md deleted file mode 100644 index 1669c49..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/docs/main.md +++ /dev/null @@ -1,5 +0,0 @@ -This program simply pings a local "task queue" server using AJAX long -polling. When a program needs to be run, this program obtains -a JSON blob containing configuration information from the task queue -server and uses it to bootstrap the program. This goes on -indefinitely, until the application exits. diff --git a/tools/addon-sdk-1.4/packages/development-mode/lib/bootstrap.js b/tools/addon-sdk-1.4/packages/development-mode/lib/bootstrap.js deleted file mode 100644 index 6986c60..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/lib/bootstrap.js +++ /dev/null @@ -1,153 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack SDK. - * - * The Initial Developer of the Original Code is - * Atul Varma <atul@mozilla.com>. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -var {Cc,Cm,Ci,components} = require("chrome"); -var file = require("api-utils/file"); - -// A global registry of all Jetpack Programs that we're responsible -// for loading and unloading. Keys are XPCOM contract IDs of -// the harness services of Jetpack Programs, values are the -// wrappedJSObject of the harness services themselves. -var gServices = {}; - -var manager = Cm; -manager.QueryInterface(Ci.nsIComponentRegistrar); - -// Attempts to unload and then unregister the XPCOM component with the -// given contract ID, if it is managed by us. -function maybeUnload(contractID) { - if (contractID in gServices) { - try { - gServices[contractID].unload(); - } catch (e) { - console.exception(e); - } - var classID = gServices[contractID].classID; - delete gServices[contractID]; - maybeUnregister(contractID, classID); - } -} - -// Attempts to unregister the XPCOM component with the given -// contract ID and class ID, if it is managed by us. -function maybeUnregister(contractID, classID) { - try { - var factory = manager.getClassObjectByContractID(contractID, - Ci.nsIFactory); - manager.unregisterFactory(classID, factory); - } catch (e) { - console.exception(e); - } -} - -// A quit callable that is passed to the main() function of any -// Jetpack Program we manage. Whenever said program quits, we will -// automatically take care of unloading and unregistering it. -function makeQuit(contractID) { - return function quit(status) { - maybeUnload(contractID); - }; -} - -function logError(e) { - console.exception(e); -} - -function makeUnloader(contractID) { - return {unload: function unload() { maybeUnload(contractID); }}; -} - -// The main public function of this module; given a JSON harness options -// blob and a root directory of where the Jetpack Program -// is installed, takes care of loading the program, running it, and -// unloading its resources when they're no longer needed. -exports.run = function run(options, rootDirPath, dump) { - var harnessService; - var contractID = options.bootstrap.contractID; - var classID = components.ID(options.bootstrap.classID); - - maybeUnload(contractID); - options.runImmediately = true; - - var rootDir = Cc["@mozilla.org/file/local;1"] - .createInstance(Ci.nsILocalFile); - rootDir.initWithPath(rootDirPath); - - // Note that we're reusing our own bootstrapping code here, rather - // than directly invoking the target Jetpack Program's bootstrapping - // infrastructure. If one works differently than the other, - // we could have problems, but for now we'll assume that this - // bootstrapping infrastructure is stable. - var HarnessService = packaging.buildHarnessService(rootDir, - dump, - logError, - makeQuit(contractID), - options); - var factory = HarnessService.prototype._xpcom_factory; - var proto = HarnessService.prototype; - manager.registerFactory(proto.classID, - proto.classDescription, - proto.contractID, - factory); - - try { - harnessService = factory.createInstance(null, Ci.nsISupports); - harnessService = harnessService.wrappedJSObject; - gServices[contractID] = harnessService; - harnessService.load(); - return makeUnloader(contractID, classID); - } catch (e) { - console.exception(e); - return null; - } -}; - -// When this module is unloaded, shut down all currently-running -// Jetpack Programs we manage and free their resources. -require("unload").when( - function() { - var argLists = []; - for (contractID in gServices) - argLists.push([contractID, gServices[contractID].classID]); - - argLists.forEach( - function(args) { - maybeUnload.apply(undefined, args); - }); - }); diff --git a/tools/addon-sdk-1.4/packages/development-mode/lib/main.js b/tools/addon-sdk-1.4/packages/development-mode/lib/main.js deleted file mode 100644 index 61854c9..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/lib/main.js +++ /dev/null @@ -1,95 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack SDK. - * - * The Initial Developer of the Original Code is - * Atul Varma <atul@mozilla.com>. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -var print; - -var {Cc,Ci} = require("chrome"); -var xhr = require("api-utils/xhr"); - -// TODO: Eventually we should be able to e.g. require("os").environ -// rather than access this XPCOM service directly. -var environ = Cc["@mozilla.org/process/environment;1"] - .getService(Ci.nsIEnvironment); - -function runTask(options) { - require("./bootstrap").run(options, packaging.root.path, print); - processNextTask(); -} - -function processNextTask() { - var req = new xhr.XMLHttpRequest(); - var port = environ.get("JETPACK_DEV_SERVER_PORT"); - var url = "http://localhost:" + port + "/api/task-queue/get"; - req.open("GET", url); - req.onreadystatechange = function() { - if (req.readyState == 4) { - if (req.status == 200) { - if (req.responseText) { - runTask(JSON.parse(req.responseText)); - } else - processNextTask(); - } else { - require("api-utils/timer").setTimeout(processNextTask, 1000); - } - } - }; - req.send(null); -} - -function makeMainWindow(quit) { - var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Ci.nsIWindowWatcher); - var text = "Now in development mode. Close this window to exit."; - var window = ww.openWindow(null, "data:text/plain," + encodeURI(text), - "development-mode", "centerscreen", null); - - window.addEventListener("close", function() quit("OK"), false); -} - -exports.main = function(options, callbacks) { - var appInfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULAppInfo); - - print = callbacks.print; - if (appInfo.ID == "xulapp@toolness.com") - // We're running barebones XULRunner, open a default window. - makeMainWindow(callbacks.quit); - console.log("Starting."); - processNextTask(); -}; diff --git a/tools/addon-sdk-1.4/packages/development-mode/package.json b/tools/addon-sdk-1.4/packages/development-mode/package.json deleted file mode 100644 index 1dc71a3..0000000 --- a/tools/addon-sdk-1.4/packages/development-mode/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "development-mode", - "description": "Adds Add-on SDK development functionality to a program.", - "keywords": ["jetpack-low-level"], - "author": "Atul Varma (http://toolness.com/)", - "license": "MPL 1.1/GPL 2.0/LGPL 2.1", - "main": "main", - "dependencies": ["api-utils", "test-harness"], - "id": "anonid0-development-mode" -} diff --git a/tools/addon-sdk-1.4/packages/test-harness/README.md b/tools/addon-sdk-1.4/packages/test-harness/README.md deleted file mode 100644 index a833d34..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/README.md +++ /dev/null @@ -1,8 +0,0 @@ -<span class="aside"> -For more information on testing in the Add-on SDK, see the -[Reusable Modules](dev-guide/addon-development/implementing-reusable-module.html) -tutorial. -</span> - -This package contains a program that finds and runs tests. It is -automatically used whenever the `cfx test` command is executed. diff --git a/tools/addon-sdk-1.4/packages/test-harness/docs/harness.md b/tools/addon-sdk-1.4/packages/test-harness/docs/harness.md deleted file mode 100644 index 9f6cd7b..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/docs/harness.md +++ /dev/null @@ -1,2 +0,0 @@ -This module contains the bulk of the test harness setup and execution -implementation. diff --git a/tools/addon-sdk-1.4/packages/test-harness/docs/run-tests.md b/tools/addon-sdk-1.4/packages/test-harness/docs/run-tests.md deleted file mode 100644 index 38f4569..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/docs/run-tests.md +++ /dev/null @@ -1,9 +0,0 @@ -<span class="aside"> -For more information on testing in the Add-on SDK, see the -[Reusable Modules](dev-guide/addon-development/implementing-reusable-module.html) -tutorial. -</span> - -This module contains the package's main program, which does a -bit of high-level setup and then delegates test finding and running to -the `harness` module. diff --git a/tools/addon-sdk-1.4/packages/test-harness/lib/harness.js b/tools/addon-sdk-1.4/packages/test-harness/lib/harness.js deleted file mode 100644 index a5a9284..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/lib/harness.js +++ /dev/null @@ -1,352 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * Irakli Gozalishvili <gozala@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -const { Cc,Ci } = require("chrome"); -const { Loader } = require("@loader") - -var cService = Cc['@mozilla.org/consoleservice;1'].getService() - .QueryInterface(Ci.nsIConsoleService); - -// Cuddlefish loader for the sandbox in which we load and -// execute tests. -var sandbox; - -// Function to call when we're done running tests. -var onDone; - -// Function to print text to a console, w/o CR at the end. -var print; - -// How many more times to run all tests. -var iterationsLeft; - -// Only tests in files whose names match this regexp filter will be run. -var filter; - -// Whether to report memory profiling information. -var profileMemory; - -// Combined information from all test runs. -var results = { - passed: 0, - failed: 0, - testRuns: [] -}; - -// JSON serialization of last memory usage stats; we keep it stringified -// so we don't actually change the memory usage stats (in terms of objects) -// of the JSRuntime we're profiling. -var lastMemoryUsage; - -function analyzeRawProfilingData(data) { - var graph = data.graph; - var shapes = {}; - - // Convert keys in the graph from strings to ints. - // TODO: Can we get rid of this ridiculousness? - var newGraph = {}; - for (id in graph) { - newGraph[parseInt(id)] = graph[id]; - } - graph = newGraph; - - var modules = 0; - var moduleIds = []; - var moduleObjs = {UNKNOWN: 0}; - for (let name in data.namedObjects) { - moduleObjs[name] = 0; - moduleIds[data.namedObjects[name]] = name; - modules++; - } - - var count = 0; - for (id in graph) { - var parent = graph[id].parent; - while (parent) { - if (parent in moduleIds) { - var name = moduleIds[parent]; - moduleObjs[name]++; - break; - } - if (!(parent in graph)) { - moduleObjs.UNKNOWN++; - break; - } - parent = graph[parent].parent; - } - count++; - } - - print("\nobject count is " + count + " in " + modules + " modules" + - " (" + data.totalObjectCount + " across entire JS runtime)\n"); - if (lastMemoryUsage) { - var last = JSON.parse(lastMemoryUsage); - var diff = { - moduleObjs: dictDiff(last.moduleObjs, moduleObjs), - totalObjectClasses: dictDiff(last.totalObjectClasses, - data.totalObjectClasses) - }; - - for (let name in diff.moduleObjs) - print(" " + diff.moduleObjs[name] + " in " + name + "\n"); - for (let name in diff.totalObjectClasses) - print(" " + diff.totalObjectClasses[name] + " instances of " + - name + "\n"); - } - lastMemoryUsage = JSON.stringify( - {moduleObjs: moduleObjs, - totalObjectClasses: data.totalObjectClasses} - ); -} - -function dictDiff(last, curr) { - var diff = {}; - - for (let name in last) { - var result = (curr[name] || 0) - last[name]; - if (result) - diff[name] = (result > 0 ? "+" : "") + result; - } - for (let name in curr) { - var result = curr[name] - (last[name] || 0); - if (result) - diff[name] = (result > 0 ? "+" : "") + result; - } - return diff; -} - -function reportMemoryUsage() { - memory.gc(); - sandbox.memory.gc(); - - var mgr = Cc["@mozilla.org/memory-reporter-manager;1"] - .getService(Ci.nsIMemoryReporterManager); - var reporters = mgr.enumerateReporters(); - if (reporters.hasMoreElements()) - print("\n"); - while (reporters.hasMoreElements()) { - var reporter = reporters.getNext(); - reporter.QueryInterface(Ci.nsIMemoryReporter); - print(reporter.description + ": " + reporter.memoryUsed + "\n"); - } - - var weakrefs = [info.weakref.get() - for each (info in sandbox.memory.getObjects())]; - weakrefs = [weakref for each (weakref in weakrefs) if (weakref)]; - print("Tracked memory objects in testing sandbox: " + - weakrefs.length + "\n"); -} - -var gWeakrefInfo; - -function showResults() { - memory.gc(); - - if (gWeakrefInfo) { - gWeakrefInfo.forEach( - function(info) { - var ref = info.weakref.get(); - if (ref !== null) { - var data = ref.__url__ ? ref.__url__ : ref; - var warning = data == "[object Object]" - ? "[object " + data.constructor.name + "(" + - [p for (p in data)].join(", ") + ")]" - : data; - console.warn("LEAK", warning, info.bin); - } - } - ); - } - - print("\n"); - var total = results.passed + results.failed; - print(results.passed + " of " + total + " tests passed.\n"); - onDone(results); -} - -function cleanup() { - try { - for (let name in sandbox.modules) - sandbox.globals.memory.track(sandbox.modules[name], - "module global scope: " + name); - sandbox.globals.memory.track(sandbox, "Cuddlefish Loader"); - - if (profileMemory) { - gWeakrefInfo = [{ weakref: info.weakref, bin: info.bin } - for each (info in sandbox.globals.memory.getObjects())]; - } - - sandbox.unload(); - - if (sandbox.globals.console.errorsLogged && !results.failed) { - results.failed++; - console.error("warnings and/or errors were logged."); - } - - if (consoleListener.errorsLogged && !results.failed) { - console.warn(consoleListener.errorsLogged + " " + - "warnings or errors were logged to the " + - "platform's nsIConsoleService, which could " + - "be of no consequence; however, they could also " + - "be indicative of aberrant behavior."); - } - - consoleListener.errorsLogged = 0; - sandbox = null; - - memory.gc(); - } catch (e) { - results.failed++; - console.error("unload.send() threw an exception."); - console.exception(e); - }; - - require("api-utils/timer").setTimeout(showResults, 1); -} - -function nextIteration(tests) { - if (tests) { - results.passed += tests.passed; - results.failed += tests.failed; - - if (profileMemory) - reportMemoryUsage(); - - let testRun = []; - for each (let test in tests.testRunSummary) { - let testCopy = {}; - for (let info in test) { - testCopy[info] = test[info]; - } - testRun.push(testCopy); - } - - results.testRuns.push(testRun); - iterationsLeft--; - } - - if (iterationsLeft) { - let require = Loader.require.bind(sandbox, module.path); - require("api-utils/unit-test").findAndRunTests({ - testOutOfProcess: require('@packaging').enableE10s, - testInProcess: true, - filter: filter, - onDone: nextIteration - }); - } - else { - require("api-utils/timer").setTimeout(cleanup, 0); - } -} - -var POINTLESS_ERRORS = [ - "Invalid chrome URI:", - "OpenGL LayerManager Initialized Succesfully." -]; - -var consoleListener = { - errorsLogged: 0, - observe: function(object) { - if (!(object instanceof Ci.nsIScriptError)) - return; - this.errorsLogged++; - var message = object.QueryInterface(Ci.nsIConsoleMessage).message; - var pointless = [err for each (err in POINTLESS_ERRORS) - if (message.indexOf(err) == 0)]; - if (pointless.length == 0 && message) - print("console: " + message + "\n"); - } -}; - -function TestRunnerConsole(base, options) { - this.__proto__ = { - errorsLogged: 0, - warn: function warn() { - this.errorsLogged++; - base.warn.apply(base, arguments); - }, - error: function error() { - this.errorsLogged++; - base.error.apply(base, arguments); - }, - info: function info(first) { - if (options.verbose) - base.info.apply(base, arguments); - else - if (first == "pass:") - print("."); - }, - __proto__: base - }; -} - -var runTests = exports.runTests = function runTests(options) { - iterationsLeft = options.iterations; - filter = options.filter; - profileMemory = options.profileMemory; - onDone = options.onDone; - print = options.print; - - try { - cService.registerListener(consoleListener); - - var ptc = require("api-utils/plain-text-console"); - var url = require("api-utils/url"); - var system = require("api-utils/system"); - - print("Running tests on " + system.name + " " + system.version + - "/Gecko " + system.platformVersion + " (" + - system.id + ") under " + - system.platform + "/" + system.architecture + ".\n"); - - sandbox = Loader.new(require("@packaging")); - Object.defineProperty(sandbox.globals, 'console', { - value: new TestRunnerConsole(new ptc.PlainTextConsole(print), options) - }); - - nextIteration(); - } catch (e) { - print(require("api-utils/traceback").format(e) + "\n" + e + "\n"); - onDone({passed: 0, failed: 1}); - } -}; - -require("api-utils/unload").when(function() { - cService.unregisterListener(consoleListener); -}); diff --git a/tools/addon-sdk-1.4/packages/test-harness/lib/run-tests.js b/tools/addon-sdk-1.4/packages/test-harness/lib/run-tests.js deleted file mode 100644 index 4ea6e3f..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/lib/run-tests.js +++ /dev/null @@ -1,133 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Jetpack. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma <atul@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict"; - -var obsvc = require("api-utils/observer-service"); -var system = require("api-utils/system"); -var options = require('@packaging'); -var {Cc,Ci} = require("chrome"); - -function runTests(iterations, filter, profileMemory, verbose, rootPaths, exit, print) { - var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Ci.nsIWindowWatcher); - - let ns = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; - let msg = 'Running tests...'; - let markup = '<?xml version="1.0"?><window xmlns="' + ns + - '" windowtype="test:runner"><label>' + msg + '</label></window>'; - let url = "data:application/vnd.mozilla.xul+xml," + escape(markup); - - - var window = ww.openWindow(null, url, "harness", "centerscreen", null); - - var harness = require("./harness"); - - function onDone(tests) { - window.close(); - if (tests.failed == 0) { - if (tests.passed === 0) - print("No tests were run\n"); - exit(0); - } else { - printFailedTests(tests, verbose, print); - exit(1); - } - }; - - // We have to wait for this window to be fully loaded *and* focused - // in order to avoid it to mess with our various window/focus tests. - // We are first waiting for our window to be fully loaded before ensuring - // that it will take the focus, and then we wait for it to be focused. - window.addEventListener("load", function onload() { - window.removeEventListener("load", onload, true); - - window.addEventListener("focus", function onfocus() { - window.removeEventListener("focus", onfocus, true); - // Finally, we have to run test on next cycle, otherwise XPCOM components - // are not correctly updated. - // For ex: nsIFocusManager.getFocusedElementForWindow may throw - // NS_ERROR_ILLEGAL_VALUE exception. - require("timer").setTimeout(function () { - harness.runTests({iterations: iterations, - filter: filter, - profileMemory: profileMemory, - verbose: verbose, - rootPaths: rootPaths, - print: print, - onDone: onDone}); - }, 0); - }, true); - window.focus(); - }, true); -} - -function printFailedTests(tests, verbose, print) { - if (!verbose) - return; - - let iterationNumber = 0; - let singleIteration = tests.testRuns.length == 1; - let padding = singleIteration ? "" : " "; - - print("\nThe following tests failed:\n"); - - for each (let testRun in tests.testRuns) { - iterationNumber++; - - if (!singleIteration) - print(" Iteration " + iterationNumber + ":\n"); - - for each (let test in testRun) { - if (test.failed > 0) { - print(padding + " " + test.name + ": " + test.errors +"\n"); - } - } - print("\n"); - } -} - -exports.main = function main() { - var testsStarted = false; - - if (!testsStarted) { - testsStarted = true; - runTests(options.iterations, options.filter, - options.profileMemory, options.verbose, - options.rootPaths, system.exit, - dump); - } -}; diff --git a/tools/addon-sdk-1.4/packages/test-harness/package.json b/tools/addon-sdk-1.4/packages/test-harness/package.json deleted file mode 100644 index 1ef10a5..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "test-harness", - "description": "A harness for running Jetpack tests.", - "author": "Atul Varma (http://toolness.com/)", - "keywords": ["jetpack-low-level"], - "license": "MPL 1.1/GPL 2.0/LGPL 2.1", - "dependencies": ["api-utils"] -} diff --git a/tools/addon-sdk-1.4/packages/test-harness/tests/test-packaging.js b/tools/addon-sdk-1.4/packages/test-harness/tests/test-packaging.js deleted file mode 100644 index d030267..0000000 --- a/tools/addon-sdk-1.4/packages/test-harness/tests/test-packaging.js +++ /dev/null @@ -1,14 +0,0 @@ -var url = require("url"); -var file = require("file"); -var {Cm,Ci} = require("chrome"); -var options = require("@packaging"); - -exports.testPackaging = function(test) { - test.assertEqual(options.main, - 'test-harness/run-tests', - "main program should be the test harness"); - - test.assertEqual(options.metadata['test-harness'].author, - 'Atul Varma (http://toolness.com/)', - "packaging metadata should be available"); -}; |