diff options
Diffstat (limited to 'data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules')
113 files changed, 7423 insertions, 0 deletions
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.npmignore b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.npmignore new file mode 100644 index 0000000..d15926f --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.npmignore @@ -0,0 +1,7 @@ +.DS_Store +*.xpi +.project +.settings +*.zip +node_modules + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.travis.yml b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.travis.yml new file mode 100644 index 0000000..c9fefad --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/.travis.yml @@ -0,0 +1,22 @@ +language: node_js +node_js: +- "0.10" + +before_install: +- "export DISPLAY=:99.0" +- "sh -e /etc/init.d/xvfb start" +- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR" + +before_script: +- npm install jpm -g +- rm -r node_modules/addon-pathfinder/test +- cd .. +- url="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/firefox-36.0a1.en-US.linux-x86_64.tar.bz2" +- wget -O firefox.tar.bz2 "$url" +- bzip2 -cd firefox.tar.bz2 | tar xvf - +- cd $TRAVIS_BUILD_DIR + +script: +- export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox +- jpm test -v + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/README.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/README.md new file mode 100644 index 0000000..140ad26 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/README.md @@ -0,0 +1,28 @@ +# Menuitem + +[](https://travis-ci.org/jetpack-labs/menuitem) + +[](https://nodei.co/npm/menuitem/) +[](https://nodei.co/npm/menuitem) + +The menuitems API is a simple way to create a menuitem, +which can perform an action when clicked, and display state. + +## Example + + // create menuitem for the File menu, + // and insert it before the 'Quit' menuitem + require("menuitem").Menuitem({ + id: "myextprefix-some-mi-id", + menuid: "menu_FilePopup", + insertbefore: "menu_FileQuitItem", + "label": _("label"), + "accesskey": _("label.ak"), + image: self.data.url("icon.png"), + className: 'pizazz', + disabled: false, + checked: false, + onCommand: function() { + // do something + } + }); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/index.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/index.js new file mode 100644 index 0000000..e5f79dc --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/index.js @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const windowUtils = require("sdk/deprecated/window-utils"); +const { Class } = require("sdk/core/heritage"); +const { validateOptions } = require("sdk/deprecated/api-utils"); +const { on, emit, once, off } = require("sdk/event/core"); +const { isBrowser } = require("sdk/window/utils"); +const { EventTarget } = require('sdk/event/target'); +const menuitemNS = require("sdk/core/namespace").ns(); + +const { unload } = require('pathfinder/lib/addon/unload'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function MenuitemOptions(options) { + return validateOptions(options, { + id: { is: ['string'] }, + menuid: { is: ['undefined', 'string'] }, + insertbefore: { is: ['undefined', 'string', 'object', 'number'] }, + label: { is: ["string"] }, + include: { is: ['string', 'undefined'] }, + disabled: { is: ["undefined", "boolean"], map: function(v) !!v}, + accesskey: { is: ["undefined", "string"] }, + key: { is: ["undefined", "string"] }, + checked: { is: ['undefined', 'boolean'] }, + className: { is: ["undefined", "string"] }, + onCommand: { is: ['undefined', 'function'] }, + useChrome: { map: function(v) !!v } + }); +} + +let Menuitem = Class({ + extends: EventTarget, + initialize: function(options) { + options = menuitemNS(this).options = MenuitemOptions(options); + EventTarget.prototype.initialize.call(this, options); + + menuitemNS(this).destroyed = false; + menuitemNS(this).unloaders = []; + menuitemNS(this).menuitems = addMenuitems(this, options).menuitems; + }, + get id() menuitemNS(this).options.id, + get label() menuitemNS(this).options.label, + set label(val) updateProperty(this, 'label', val), + get checked() menuitemNS(this).options.checked, + set checked(val) updateProperty(this, 'checked', !!val), + get disabled() menuitemNS(this).options.disabled, + set disabled(val) updateProperty(this, 'disabled', !!val), + get key() menuitemNS(this).options.key, + set key(val) updateProperty(this, 'key', val), + clone: function (overwrites) { + let opts = Object.clone(menuitemNS(this).options); + for (let key in overwrites) { + opts[key] = overwrites[key]; + } + return Menuitem(opts); + }, + get menuid() menuitemNS(this).options.menuid, + set menuid(val) { + let options = menuitemNS(this).options; + options.menuid = val; + + forEachMI(function(menuitem, i, $) { + updateMenuitemParent(menuitem, options, $); + }); + }, + destroy: function() { + if (!menuitemNS(this).destroyed) { + menuitemNS(this).destroyed = true; + menuitemNS(this).unloaders.forEach(function(u) u()); + menuitemNS(this).unloaders = null; + menuitemNS(this).menuitems = null; + } + return true; + } +}); + +function addMenuitems(self, options) { + let menuitems = []; + + // setup window tracker + windowUtils.WindowTracker({ + onTrack: function (window) { + if (menuitemNS(self).destroyed) return; + if (options.include) { + if (options.include != window.location) return; + } + else if (!isBrowser(window)) { + return; + } + + // add the new menuitem to a menu + var menuitem = updateMenuitemAttributes( + window.document.createElementNS(NS_XUL, "menuitem"), options); + var menuitems_i = menuitems.push(menuitem) - 1; + + // add the menutiem to the ui + let added = updateMenuitemParent(menuitem, options, function(id) window.document.getElementById(id)); + + menuitem.addEventListener("command", function() { + if (!self.disabled) + emit(self, 'command', options.useChrome ? window : null); + }, true); + + // add unloader + let unloader = function unloader() { + menuitem.parentNode && menuitem.parentNode.removeChild(menuitem); + menuitems[menuitems_i] = null; + }; + + menuitemNS(self).unloaders.push(function() { + remover(); + unloader(); + }); + + let remover = unload(unloader, window); + } + + }); + + return { menuitems: menuitems }; +} + +function updateMenuitemParent(menuitem, options, $) { + // add the menutiem to the ui + if (Array.isArray(options.menuid)) { + let ids = options.menuid; + for (var len = ids.length, i = 0; i < len; i++) { + if (tryParent($(ids[i]), menuitem, options.insertbefore)) + return true; + } + } + else { + return tryParent($(options.menuid), menuitem, options.insertbefore); + } + + return false; +} + +function updateMenuitemAttributes(menuitem, options) { + menuitem.setAttribute("id", options.id); + menuitem.setAttribute("label", options.label); + + if (options.accesskey) + menuitem.setAttribute("accesskey", options.accesskey); + + if (options.key) + menuitem.setAttribute("key", options.key); + + menuitem.setAttribute("disabled", !!options.disabled); + + if (options.image) { + menuitem.classList.add("menuitem-iconic"); + menuitem.style.listStyleImage = "url('" + options.image + "')"; + } + + if (options.checked) + menuitem.setAttribute('checked', options.checked); + + if (options.className) + options.className.split(/\s+/).forEach(function(name) menuitem.classList.add(name)); + + return menuitem; +} + +function updateProperty(menuitem, key, val) { + menuitemNS(menuitem).options[key] = val; + + forEachMI(function(menuitem) { + menuitem.setAttribute(key, val); + }, menuitem); + return val; +} + +function forEachMI(callback, menuitem) { + menuitemNS(menuitem).menuitems.forEach(function(mi, i) { + if (!mi) return; + callback(mi, i, function(id) mi.ownerDocument.getElementById(id)); + }); +} + +function tryParent(parent, menuitem, before) { + if (parent) { + if (!before) { + parent.appendChild(menuitem); + return true; + } + + parent.insertBefore(menuitem, insertBefore(parent, before)); + return true; + } + + return false; +} + +function insertBefore(parent, insertBefore) { + if (typeof insertBefore == "number") { + switch (insertBefore) { + case MenuitemExport.FIRST_CHILD: + return parent.firstChild; + } + return null; + } + else if (typeof insertBefore == "string") { + return parent.querySelector("#" + insertBefore); + } + return insertBefore; +} + +function MenuitemExport(options) { + return Menuitem(options); +} +MenuitemExport.FIRST_CHILD = 1; + +exports.Menuitem = MenuitemExport; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/package.json b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/package.json new file mode 100644 index 0000000..b8798a5 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/package.json @@ -0,0 +1,82 @@ +{ + "_args": [ + [ + "menuitem@0.0.5", + "/home/nik/src/librejs" + ] + ], + "_from": "menuitem@0.0.5", + "_id": "menuitem@0.0.5", + "_inCache": true, + "_location": "/menuitem", + "_nodeVersion": "4.0.0", + "_npmUser": { + "email": "accounts.npm@overbythere.co.uk", + "name": "overbythere" + }, + "_npmVersion": "2.14.2", + "_phantomChildren": {}, + "_requested": { + "name": "menuitem", + "raw": "menuitem@0.0.5", + "rawSpec": "0.0.5", + "scope": null, + "spec": "0.0.5", + "type": "version" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/menuitem/-/menuitem-0.0.5.tgz", + "_shasum": "c170347dcc0cc7195af645f300acd8f99522f896", + "_shrinkwrap": null, + "_spec": "menuitem@0.0.5", + "_where": "/home/nik/src/librejs", + "author": { + "name": "Erik Vold" + }, + "bugs": { + "url": "https://github.com/OverByThere/menuitem/issues" + }, + "dependencies": { + "pathfinder": "git+https://github.com/OverByThere/addon-pathfinder.git" + }, + "description": "[](https://travis-ci.org/jetpack-labs/menuitem)", + "devDependencies": {}, + "directories": { + "test": "test" + }, + "dist": { + "shasum": "c170347dcc0cc7195af645f300acd8f99522f896", + "tarball": "http://registry.npmjs.org/menuitem/-/menuitem-0.0.5.tgz" + }, + "gitHead": "bb3f05ea29164bf673a4cdd076fc620266028e53", + "homepage": "https://github.com/OverByThere/menuitem#readme", + "installable": true, + "keywords": [ + "firefox", + "gecko", + "jetpack", + "menu", + "menuitem", + "ui" + ], + "license": "MPL-2.0", + "main": "index.js", + "maintainers": [ + { + "name": "overbythere", + "email": "accounts.npm@overbythere.co.uk" + } + ], + "name": "menuitem", + "optionalDependencies": {}, + "repository": { + "type": "git", + "url": "git+https://github.com/OverByThere/menuitem.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "0.0.5" +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/test/test-menuitems.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/test/test-menuitems.js new file mode 100644 index 0000000..52f911d --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/menuitem/test/test-menuitems.js @@ -0,0 +1,169 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict' + +const windowUtils = require('sdk/deprecated/window-utils'); +const menuitems = require('../index'); + +let window = windowUtils.activeBrowserWindow; +let document = window.document; +function $(id) document.getElementById(id); + +function createMI(options, test) { + test.equal(!$(options.id), true); + var mi = new menuitems.Menuitem(options); + return mi; +} + +exports.testMIDoesNotExist = function(assert) { + var options = { + id: "test-mi-dne", + label: "test" + }; + createMI(options, assert); + assert.equal(!!$(options.id), false, 'menuitem does not exists'); +}; + +exports.testMIDoesExist = function(assert) { + var options = { + id: "test-mi-exists", + label: "test", + menuid: 'menu_FilePopup' + }; + let mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.id, options.id, 'menuitem id is ok'); + assert.equal(menuitem.getAttribute('label'), options.label, 'menuitem label is ok'); + assert.equal(menuitem.parentNode.id, options.menuid, 'in the file menu'); + assert.equal(menuitem.getAttribute('disabled'), 'false', 'menuitem not disabled'); + assert.equal(menuitem.getAttribute('accesskey'), '', 'menuitem accesskey is ok'); + assert.equal(menuitem.getAttribute('class'), '', 'menuitem class is ok'); + assert.equal(menuitem.nextSibling, undefined, 'menuitem is last'); + assert.equal(menuitem.hasAttribute("checked"), false, 'menuitem not checked'); + mi.destroy(); + assert.ok(!$(options.id), 'menuitem is gone'); + assert.equal(menuitem.parentNode, null, 'menuitem has no parent'); +}; + +exports.testMIOnClick = function(assert, done) { + let options = { + id: "test-mi-onclick", + label: "test", + menuid: 'menu_FilePopup', + onCommand: function() { + mi.destroy(); + assert.pass('onCommand worked!'); + done(); + } + }; + + let e = document.createEvent("UIEvents"); + e.initUIEvent("command", true, true, window, 1); + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + menuitem.dispatchEvent(e); +}; + +exports.testMIDisabled = function(assert, done) { + let commandIsOK = false; + let count = 0; + let options = { + id: "test-mi-disabled", + label: "test", + disabled: true, + menuid: 'menu_FilePopup', + onCommand: function() { + count++; + if (!commandIsOK) { + assert.fail('onCommand was called, that is not ok'); + return; + } + + mi.destroy(); + assert.equal(count, 1, 'onCommand was called the correct number of times!'); + done(); + } + }; + + let e = document.createEvent("UIEvents"); + e.initUIEvent("command", true, true, window, 1); + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute('disabled'), 'true', 'menuitem not disabled'); + menuitem.dispatchEvent(e); + mi.disabled = false; + assert.equal(menuitem.getAttribute('disabled'), 'false', 'menuitem not disabled'); + commandIsOK = true; + menuitem.dispatchEvent(e); +}; + +exports.testMIChecked = function(assert) { + let options = { + id: "test-mi-checked", + label: "test", + disabled: true, + menuid: 'menu_FilePopup', + checked: true + }; + + let mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute("checked"), "true", 'menuitem checked'); + mi.checked = false; + assert.equal(menuitem.getAttribute("checked"), "false", 'menuitem checked'); + mi.destroy(); +}; + +exports.testMIClass = function(assert) { + let options = { + id: "test-mi-class", + label: "pizazz", + className: "pizazz", + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute('class'), 'pizazz', 'menuitem not disabled'); + mi.destroy(); +}; + +exports.testInsertBeforeExists = function(assert) { + let options = { + id: 'test-mi-insertbefore', + label: 'insertbefore', + insertbefore:'menu_FileQuitItem', + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.nextSibling, $('menu_FileQuitItem'), 'menuitem not disabled'); + mi.destroy(); +}; + +exports.testInsertBeforeDoesNotExist = function(assert) { + let options = { + id: 'test-mi-insertbefore', + label: 'insertbefore', + insertbefore:'menu_ZZZDNE', + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.nextSibling, null, 'menuitem not disabled'); + mi.destroy(); +}; + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/LICENSE b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/LICENSE new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/README.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/README.md new file mode 100644 index 0000000..b84fde1 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/README.md @@ -0,0 +1,5 @@ +NotificationBox implements some of the notificationbox element functionality in Firefox and Mozilla-based browsers using the Addon SDK. For any question or feedback please email lduros--at--member.fsf.org + +It is released under the MPL 2.0. + +See [doc/main.md](https://github.com/lduros/notificationbox/blob/master/doc/main.md) for more information. diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/data/gnu-icon.png b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/data/gnu-icon.png Binary files differnew file mode 100644 index 0000000..7c603f0 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/data/gnu-icon.png diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/critical-notification.png b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/critical-notification.png Binary files differnew file mode 100644 index 0000000..494fd10 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/critical-notification.png diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/info-low-priority.png b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/info-low-priority.png Binary files differnew file mode 100644 index 0000000..bcb4487 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/images/info-low-priority.png diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/main.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/main.md new file mode 100644 index 0000000..3888af0 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/doc/main.md @@ -0,0 +1,53 @@ +NotificationBox implements some of the notificationbox element functionality in Firefox and Mozilla-based browsers using the Addon SDK. For any question or feedback please email lduros--at--member.fsf.org + +You can create a notification as follows: +```javascript +var self = require("self"); +var notification = require("notification-box").NotificationBox({ + 'value': 'important-message', + 'label': 'This is a very important message!', + 'priority': 'CRITICAL_BLOCK', + // Automatically close notification in 5s + 'timeout': 5000, + // How many page changes the notification will stay active for + 'persistence': 2, + 'image': self.data.url("gnu-icon.png"), + 'buttons': [{'label': "Do something about it!", + 'onClick': function () { console.log("You clicked the important button!"); }}] +}); +``` + +It implements the following options: + + - value: value used to identify the notification + - label: label to appear on the notification + - image: URL of image to appear on the notification. You can also + load a local image from the data folder, like in the example + - timeout: How many milliseconds until the notification will automatically close + - persistence: How many page changes the notification will stay active for + - eventCallback: Function to call when notification closes (arg1: reason) + - priority: notification priority. Use one of the following: + - INFO_LOW + - INFO_MEDIUM + - INFO_HIGH + - WARNING_LOW + - WARNING_MEDIUM + - WARNING_HIGH + - CRITICAL_LOW + - CRITICAL_MEDIUM + - CRITICAL_HIGH + - CRITICAL_BLOCK + - buttons: array of buttons to appear on the notification. + You can use the following options: + - accessKey: the accesskey to appear on the button + - onClick: the callback function to trigger when button is activated. + - label: the text to display on the button + + +Here is an overview of what the example above with the critical notification looks like: + + +When using 'INFO_LOW' for the priority instead, you would see: + + +For more information on notificationbox: https://developer.mozilla.org/en-US/docs/XUL/notificationbox diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/main.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/main.js new file mode 100644 index 0000000..0abfbe8 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/main.js @@ -0,0 +1,16 @@ +/* + * Copyrights Loic J. Duros 2012 + * lduros@member.fsf.org + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var self = require("self"); +var notification = require("notification-box").NotificationBox({ + 'value': 'important-message', + 'label': 'You have been warned...', + 'priority': 'WARNING_HIGH', + 'image': self.data.url("gnu-icon.png"), + 'buttons': [{'label': "Gotcha", + 'onClick': function () { console.log("You clicked the important button!"); }}] +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/notification-box.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/notification-box.js new file mode 100644 index 0000000..32e3ba6 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/lib/notification-box.js @@ -0,0 +1,147 @@ +/* + * Copyright 2014 + * @author Loic J. Duros lduros@member.fsf.org + * @author Joshua Cornutt jcornutt@gmail.com + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { Cc, Ci } = require("chrome"); +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); + +/* I haven't found this sort of validation functions in the SDK, +except for the deprecated api-utils module. */ +let isString = function (str) { + if ( !str ) return false; + return typeof(str) == 'string' || str instanceof String; +}; + +let isArray = function (obj) { + if ( !obj || typeof(obj) === 'undefined' ) return false; + return Object.prototype.toString.call(obj) === '[object Array]'; +}; + +let isObject = function(obj) { + if ( !obj || typeof(obj) === 'undefined' ) return false; + return obj instanceof Object; +} + +let isInteger = function(val) { + if ((undefined === val) || (null === val)) return false; + return !isNaN(val); +} + +let isFunction = function(obj) { + if ( !obj || typeof(obj) === 'undefined' ) return false; + return {}.toString.call(obj) === '[object Function]'; +} + +exports.NotificationBox = function (options) { + options = options || {}; + let mainWindow = getMostRecentBrowserWindow(); + let nbObj = mainWindow.gBrowser.getNotificationBox(); + let priority = nbObj[PRIORITY.INFO_LOW], + label = '', + image = 'chrome://browser/skin/Info.png', + value = '', + persistence = 0, + eventCallback = function(){}, + buttons = []; + + if (options.value && isString(options.value)) + value = options.value; + + // Set how many page changes the notification will remain active for. + if ( options.persistence && isInteger(options.persistence) ) + persistence = options.persistence; + + // Set if the user wants to be notified when the notification closes + if ( options.eventCallback && isFunction(options.eventCallback) ) + eventCallback = options.eventCallback; + + // Add label or create empty notification. + if (options.label && isString(options.label)) + label = options.label; + + // Set priority of the notification (from INFO_LOW to CRITICAL_BLOCK) + if (options.priority && options.priority in PRIORITY) + priority = nbObj[PRIORITY[options.priority]]; + + // Set a custom icon for the notification or use the stock info icon. + if (options.image && isString(options.image)) + image = options.image; + + // Sanitize and format each notification button + if ( isArray(options.buttons) ) + for (let i = 0, length = options.buttons.length; i < length; i++) + buttons.push(NotificationButton(options.buttons[i])); + else if ( isObject(options.buttons) ) + // If it's not an array of buttons, then it should be a single button. + buttons.push(NotificationButton(options.buttons)); + else + buttons = null; + + // Add a new notification to the notificationbox. + var nObj = nbObj.appendNotification(label, value, + image, priority, buttons, eventCallback); + + // Set how many page changes the notification will stay active for + nObj.persistence = persistence; + + // Timeout for closing the notification automatically + if( options.timeout && isInteger(options.timeout) ) { + require('sdk/timers').setTimeout( function() { + if( isFunction(nObj.close) ) + nObj.close(); + }, options.timeout ); + } + + // Expose both the NotificationBox and Notification itself + return {'notificationbox': nbObj, 'notification': nObj}; +}; + + +// Notification button santizing function +var NotificationButton = function (options) { + options = options || {}; + let accessKey = '', + onClick = function(){}, + label = "", + popup = null, // no popup for now... maybe we can use a panel later. + timeout = 0; + + if ( options.accessKey ) + accessKey = options.accessKey; + + if ( isFunction(options.onClick) ) + onClick = options.onClick; + + if ( options.label ) + label = options.label; + + if ( isInteger(options.timeout) ) + timeout = options.timeout; + + return {label: label, + accessKey: accessKey, + callback: onClick, + popup: popup, + timeout: timeout}; +}; + +const PRIORITY = { + 'INFO_LOW': 'PRIORITY_INFO_LOW', + 'INFO_MEDIUM': 'PRIORITY_INFO_MEDIUM', + 'INFO_HIGH': 'PRIORITY_INFO_HIGH', + 'WARNING_LOW': 'PRIORITY_WARNING_LOW', + 'WARNING_MEDIUM': 'PRIORITY_WARNING_MEDIUM', + 'WARNING_HIGH': 'PRIORITY_WARNING_HIGH', + 'CRITICAL_LOW': 'PRIORITY_CRITICAL_LOW', + 'CRITICAL_MEDIUM': 'PRIORITY_CRITICAL_MEDIUM', + 'CRITICAL_HIGH': 'PRIORITY_CRITICAL_HIGH', + 'CRITICAL_BLOCK': 'PRIORITY_CRITICAL_BLOCK' +}; + +exports.PRIORITY = PRIORITY;
\ No newline at end of file diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/package.json b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/package.json new file mode 100644 index 0000000..b4fadcb --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/package.json @@ -0,0 +1,61 @@ +{ + "_args": [ + [ + "notification-box@0.1.1", + "/home/nik/src/librejs" + ] + ], + "_from": "notification-box@0.1.1", + "_id": "notification-box@0.1.1", + "_inCache": true, + "_location": "/notification-box", + "_nodeVersion": "0.10.25", + "_npmUser": { + "email": "nikolas@gnu.org", + "name": "nnyby" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "name": "notification-box", + "raw": "notification-box@0.1.1", + "rawSpec": "0.1.1", + "scope": null, + "spec": "0.1.1", + "type": "version" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/notification-box/-/notification-box-0.1.1.tgz", + "_shasum": "b82020c859001846bef65b33766d9f6915cf0498", + "_shrinkwrap": null, + "_spec": "notification-box@0.1.1", + "_where": "/home/nik/src/librejs", + "author": { + "name": "Loic Duros" + }, + "dependencies": {}, + "description": "a basic add-on", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "b82020c859001846bef65b33766d9f6915cf0498", + "tarball": "http://registry.npmjs.org/notification-box/-/notification-box-0.1.1.tgz" + }, + "fullName": "notification-box", + "gitHead": "28d8d3ca6b766691d99941293e5f3d1fba47f9f7", + "id": "jid1-dyFGGJB0CjoDMA", + "installable": true, + "license": "MPL 2.0", + "maintainers": [ + { + "name": "nnyby", + "email": "nikolas@gnu.org" + } + ], + "name": "notification-box", + "optionalDependencies": {}, + "scripts": {}, + "version": "0.1.1" +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/test/test-main.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/test/test-main.js new file mode 100644 index 0000000..9e7031a --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/notification-box/test/test-main.js @@ -0,0 +1,12 @@ +var main = require("main"); + +exports["test main"] = function(assert) { + assert.pass("Unit test running!"); +}; + +exports["test main async"] = function(assert, done) { + assert.pass("async Unit test running!"); + done(); +}; + +require("test").run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/.npmignore b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/.npmignore new file mode 100644 index 0000000..bc7dd61 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/.npmignore @@ -0,0 +1,6 @@ +.DS_Store +*.xpi +.project +.settings +*.zip + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/README.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/README.md new file mode 100644 index 0000000..635b0cf --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/README.md @@ -0,0 +1,22 @@ +# Add-on Pathfinder + +The Add-on Pathfinder is the collection of Jetpack modules made to be used with the +[Add-on SDK](https://github.com/mozilla/addon-sdk). + +## Highlights + +* Toolbar buttons +* Menuitems +* GCLI +* Downloads +* About/Resource Schemes +* UserStyles +* UserScripts +* XUL Help +* ZIP Utilities +* Content policies +* Content Permissions +* Awesomebar +* Modifying Request Headers +* Redirects +* Much much more!... diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning-mod.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning-mod.js new file mode 100644 index 0000000..8d09cc0 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning-mod.js @@ -0,0 +1,19 @@ +'use strict'; + +let $ = function(id) document.getElementById(id); + +function doAndClose(func) { + func(); + window.close(); +} + +$('cancel-btn').addEventListener('click', doAndClose(function() self.port.emit("cancel")), false); +$('ok-btn').addEventListener('click', doAndClose(function() self.port.emit("accept")), false); + +self.port.on('load', function(data) { + $('errorTitle').innerHTML = data.errorTitle || ''; + $('errorShortDesc').innerHTML = data.errorShortDesc || ''; + $('errorLongDesc').innerHTML = data.errorLongDesc || ''; + $('cancel-btn').setAttribute('value', data.cancelButtonLabel || 'Decline'); + $('ok-btn').setAttribute('value', data.okButtonLabel || 'Accept'); +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.css new file mode 100644 index 0000000..ae6a6cc --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.css @@ -0,0 +1,47 @@ +html, body { + background-color: white; + color: #222; + font-family: helvetica, arial, sans-serif; + height: 100%; + padding: 0; + margin: 0; +} + +#content { + height: 100%; + width: 90%; + margin: auto; +} + +#banner { + background: url("/content/gfx/jetpack.png") no-repeat right center; + height: 138px; + font-size: 22pt; + font-weight: normal; + padding-left: 0; + padding-right: 300px; + padding-top: 20px; + padding-bottom: 20px; +} + +#banner a { + color: black; +} + +#featureName { + font-style: italic; +} + +#featureContentContainer { + height: 100%; +} + +#featureContent { + height: 100%; + min-height: 200px; + width: 100%; +} + +#confirmationShortDesc { + font-size: 14pt; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.html b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.html new file mode 100644 index 0000000..124782c --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html class="blacklist"> + <head> + <title></title> + <script type="application/javascript;version=1.8" src="warning.js"></script> + <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/netError.css"/> + <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/blacklist_favicon.png"/> + </head> + <body> + <div id="errorPageContainer"> + <div> + <h1 id="errorTitle"></h1> + </div> + + <div id="errorLongContent"> + <div id="errorShortDesc"></div> + + <div id="errorLongDesc"></div> + + <div id="buttons"> + <p> + <input id="cancel-btn" type="button" value="#cancelButtonLabel#"/> + <input id="ok-btn" type="button" value="#okButtonLabel#"/> + </p> + </div> + </div> + </div> + </body> +</html> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.js new file mode 100644 index 0000000..429d26d --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/data/warning.js @@ -0,0 +1,3 @@ +'use strict'; + + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon-warning.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon-warning.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon-warning.md diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon.md new file mode 100644 index 0000000..d75edcc --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addon.md @@ -0,0 +1,28 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + + +The `addon` API provides a simple way to create +Add-on wrapper instances for the [Extension Manager](about:addons). + +## Example ## + + exports.main = function(options) { + + }; + +<api name="Addon"> +@class + +Module exports `Addon` constructor allowing users to create a +add-on category provider to the Extension Manager. + +<api name="Addon"> +@constructor +Creates a add-on wrapper instance. + +@param options {Object} +Options for the add-on wrapper, with the following parameters: + +</api> + +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addonprovider.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addonprovider.md new file mode 100644 index 0000000..41ea550 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/addonprovider.md @@ -0,0 +1,50 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + + +The `addonprovider` API provides a simple way to create +new Add-on types for the [Extension Manager](about:addons). + +## Example ## + + exports.main = function(options) { + + }; + +<api name="AddonProvider"> +@class + +Module exports `AddonProvider` constructor allowing users to create a +add-on category provider to the Extension Manager. + +<api name="AddonProvider"> +@constructor +Creates a add-on provider. + +@param options {Object} +Options for the add-on provider, with the following parameters: + +@prop type {String} +A unique string that will identify the type of add-ons that your provider +will provide. This is internal users never see it. + +@prop localeKey {String} +A label to be used in the Extension Manager, which users see. + +@prop uiPriority {Number} +A number to represent the order to display your Add-on type in the Extension +Manager side navigation. + +@prop getAddonByID {Function} +A function that returns the appropriate `Addon`. + +@prop getAddons {Function} +A function that returns the appropriate `Addon`s. + +</api> + +<api name="destroy"> +@method +Removes the add-on provider. +</api> + +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/awesomebar.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/awesomebar.md new file mode 100644 index 0000000..dcfbb1f --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/awesomebar.md @@ -0,0 +1,61 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + + +The `awesomebar` API provides a simple way to create AwesomeBar suggestions. + +## Example ## + + // add github search + AwesomeBarSuggestion({ + icon: self.data.url("github_16.png"), + matches: /^(?:@[\w\d_-]+|github\s)/i, + onSearch: function(query, suggest) { + query = query.trim(); + if (/^github\s/i.test(query)) { + query = query.replace(/^github\s/i, ""); + suggest({ + title: 'Search Github for: ' + query, + favicon: self.data.url("github_16.png"), + url: 'https://github.com/search?q=' + encodeURIComponent(query) + }, true); + } else { + var username = query.match(/^@([\w\d_-]+)/)[1]; + suggest({ + title: 'Github user: ' + username, + label: "View user profile for @" + username, + favicon: self.data.url("github_16.png"), + url: 'https://github.com/' + username + }, true); + } + } + }); + +<api name="AwesomeBarSuggestion"> +@class + A `AwesomeBarSuggestion` constructor is exported, which allows one to create a + AwesomeBar suggestions. + +<api name="AwesomeBarSuggestion"> +@constructor + Creates a AwesomeBar suggestion handler. + +@param options {object} + Options for the AwesomeBar suggester, with the following parameters: + +@prop matches {string} + A regular expression which is tested againsted the location bar input string. + +@prop [icon] {string} + A URL for a 16x16 icon image. + +@prop onSearch {function} + Function that is invoked when the match pattern matches the location bar input + string. If will receive too arguments, `query` which is the input string, and + `suggest` which is a function that can be made to return suggestions. +</api> + +<api name="destroy"> +@method + Removes the AwesomeBar suggester. +</api> +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/content-policy.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/content-policy.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/content-policy.md diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/l10n.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/l10n.md new file mode 100644 index 0000000..2207d16 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/l10n.md @@ -0,0 +1,41 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `l10n` module allows one to localize their Jetpack. + +## Example ## + + var _ = require("l10n").l10n({ + filename: "text.properties", + baseURL: require("self").data.url("locale") + }); + console.log(_("hello.world")); + +<api name="l10n"> +@function + Creates and returns a function which can be used to access translations by + key. + + Translations should be grouped together in a folder which contains a folder + for each locale being supported whose name is the locale being supported + (examples: "en", "en-US", "ja", "ja-JP"). Inside each locale's folder should + be a `.properties` file with a name that is the same for every locale. Here + is a example of how you might organize things: + + - data/ + - locale/ + - en/ + - text.properties + - ja/ + - text.properties + +@param options {object} + + +@prop filename {string} + The name of the file storing the translations. +@prop baseURL {string} + The url to the folder containing the locale folders. +@prop [defaultLocale] {string} + Defines the locale to use when you don't have translations for the user's + locale. The default is `"en"`. +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/listen.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/listen.md new file mode 100644 index 0000000..d19c6c6 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/listen.md @@ -0,0 +1,23 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `listen` module allows modules to register listeners to elements that are +automatically removed when the module unloads. + +<api name="listen"> +@function + Add listeners to run when unloading in a unload queue. Optionally scope the + callback to a container, e.g., window. Provide a way to run all the callbacks. + +@param container {object} + A container for the node, which a "unload" event will be attached to, this is + used to cancel the unload magic that would occur, to avoid memory leaks. +@param node {object} + The node to listen to. +@param event {string} + The event type, for example: "load", "click", ... +@param callback {function} + A function to be called when the event occurs on the node. +@param [capture] {boolean} + Indicates if the event should be captured. [See the `useCapture` + documentation here](https://developer.mozilla.org/en/DOM/element.addEventListener). +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/menuitems.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/menuitems.md new file mode 100644 index 0000000..2017c9c --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/menuitems.md @@ -0,0 +1,66 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + + +The `menuitems` API is a simple way to create +[Menuitems](https://developer.mozilla.org/en/XUL/PopupGuide/MenuItems), which +can perform an action when clicked, and display state. + +## Example ## + + exports.main = function(options) { + // create menuitem for the File menu, + // and insert it before the 'Quit' menuitem + require("menuitems").Menuitem({ + id: "myextprefix-some-mi-id", + menuid: "menu_FilePopup", + insertbefore: "menu_FileQuitItem", + "label": _("label"), + "accesskey": _("label.ak"), + image: self.data.url("icon.png"), + className: 'pizazz', + disabled: false, + checked: false, + onCommand: function() { + // do something + } + }); + }; + +<api name="Menuitem"> +@class + +Module exports `Menuitem` constructor allowing users to create a +[`menuitem`](https://developer.mozilla.org/en/XUL/menuitem). + +<api name="Menuitem"> +@constructor +Creates a `menuitem`. + +@param options {Object} + Options for the `menuitem`, with the following parameters: + +@prop id {String} +A id for the `menuitem`, this should be namespaced. + +@prop menuid {String} +The id of the parent `<menu>` node. + +@prop label {String} +A label for the `menuitem`. + +@prop image {String} +A image url for the `menuitem`. + +@prop className {String} +A default space delimited list of class names for the menuitem. + +@prop disabled {Boolean} +When a menuitem is disabled it cannot be used, but is still displayed. + +@prop checked {Boolean} +Displays a check beside the menuitem. + +@prop [onCommand] {Function} + A option function that is invoked when the `menuitem` is executed. +</api> +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/panic.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/panic.md new file mode 100644 index 0000000..3155341 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/panic.md @@ -0,0 +1,45 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `panic` API provides a simple way to create a panic, which +can be used to anything that is desired in a panic situation, like entering +private browsing mode, closing/replacing/hiding tabs, or anything else you +can imagine. + +## Example ## + + // create a panic that lasts 5 mins + require('panic').panic(5*60*1000); + +<api name="inPanic"> +@property {boolean} + This read-only boolean is true if there is a panic going on. +</api> + +<api name="panic"> +@function + Starts a panic. +@param milliseconds {Number} + Optional number of milliseconds that the panic should last for, this would + be useful if you want ensure that certain things are but on hold until the + panic subsides. +</api> + +<api name="start"> +@event +Emitted immediately after a panic begins + + var panic = require('panic'); + panic.on("start", function() { + // Do something when a panic starts + }); +</api> + +<api name="end"> +@event +Emitted immediately after the panic ends + + var panic = require('panic'); + panic.on("start", function() { + // Do something when a panic ends + }); +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/toolbarbutton.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/toolbarbutton.md new file mode 100644 index 0000000..87f4cf2 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/toolbarbutton.md @@ -0,0 +1,84 @@ +The `toolbarbutton` API provides a simple way to create +[toolbar buttons](https://developer.mozilla.org/en/XUL/toolbarbutton), which +can perform an action when clicked. + +## Example ## + + // create toolbarbutton + var tbb = require("toolbarbutton").ToolbarButton({ + id: "TBB-TEST", + label: "TBB TEST", + onCommand: function () { + tbb.destroy(); // kills the toolbar button + } + }); + + if (require('self').loadReason == "install") { + tbb.moveTo({ + toolbarID: "nav-bar", + forceMove: false // only move from palette + }); + } + +<api name="ToolbarButton"> +@class + +Module exports `ToolbarButton` constructor allowing users to create a +toolbar button. + +<api name="ToolbarButton"> +@constructor +Creates a toolbarbutton. + +@param options {Object} + Options for the toolbarbutton, with the following parameters: + +@prop id {String} +A id for the toolbar button, this should be namespaced. + +@prop label {String} +A label for the toolbar button. + +@prop image {String} +A image url for the toolbar button. + +@prop [onCommand] {Function} + A option function that is invoked when the toolbar button is pressed. + +@prop [panel] {Panel} + A optional panel. +</api> + +<api name="destroy"> +@method +Removes the toolbar button from all open windows and no longer adds the +toolbar button to new windows. +</api> + +<api name="moveTo"> +@method +Moves the toolbar button on all open windows to the desired location. + +@param options {Object} +Options which describe the position to move the toolbar button to, with the +following parameters: + +@prop toolbarID {String} +The id of the toolbar which you want to add the toolbar button to. + +Example toolbar IDs: + +- **toolbar-menubar**: The menu bar. +- **nav-bar**: The navigation bar. +- **TabsToolbar**: The tabs bar. +- **addon-bar**: The addon bar. + +@prop insertbefore {String} +The id of the element which the toolbar button should be inserted before. + +@prop forceMove {Boolean} +If `forceMove` is `false`, then the move will only occur if the toolbar button +is not already being used. If `true`, then the move will happen no matter where +the toolbar button is. +</api> +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/unload+.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/unload+.md new file mode 100644 index 0000000..78693ef --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/unload+.md @@ -0,0 +1,20 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `unload+` module allows modules to register callbacks that are called +when they are unloaded, and associate unload functions to containers to have the +unloader automatically deleted when the container unloads. + +<api name="unload"> +@function + Save callbacks to run when unloading in a unload queue. Optionally scope the + callback to a container, e.g., window. Provide a way to run all the callbacks. + +@param callback {function} + A function to be called when the module unloads. +@param [container] {object} + Optional container object; if the container "unloads" before the module + unloads, then the associated callback is removed from the unload queue. +@returns {function} + Returns a function which will allow one to remove the callback from the unload + queue. +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userscript.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userscript.md new file mode 100644 index 0000000..1bc8d4e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userscript.md @@ -0,0 +1,44 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `userscript` module allows modules to create user scripts which automatically +start running on windows opened after the user script is created. + + +## Example ## + var scripts = ["test.user.js"]; + var self = require("self"); + var {UserScript} = require("userscript"); + exports.main = function() { + scripts.forEach(function(scriptName, index) { + UserScript(self.data.url(scriptName)); + }); + }; + + +<api name="UserScript"> +@class + +The module exports a `UserScript` constructor which allowing one to create a +user script. + +<api name="UserScript"> +@constructor +Creates a user script. + +@param aURL {String} + The url of a user script on the local file system, so this url can be a + `resource:`, `file:`, or `chrome:` for example. +</api> + +<api name="enabled"> +@property {Boolean} +Allows one to get and change the status of the a user script. A disabled user +script will not be injected in to newly opened windows. +</api> + +<api name="destroy"> +@method +The user script will no longer be injected into new windows, you will have to +create a new user script in order to run the script again. +</api> +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userstyles.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userstyles.md new file mode 100644 index 0000000..7debf98 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/userstyles.md @@ -0,0 +1,26 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +The `userstyles` module allows one to load css/userstyles for content or chrome +pages. + +## Example ## + + // loads a user stylesheet + require("userstyles").load(require("self").data.url("style.css")); + +<api name="load"> +@function + Loads css (aka userstyles) to the browser which will be automatically removed + when the add-on unloads. + +@param url {string} + The url of a css file. + +@param options {object} + Some options for the stylesheet. + +@prop type {String} + The type for the stylesheet, there are two types 'agent' and 'user'. + The default should be used when possible, which is 'user'. + +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/xulkeys.md b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/xulkeys.md new file mode 100644 index 0000000..4117827 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/docs/xulkeys.md @@ -0,0 +1,55 @@ +<!-- contributed by Erik Vold [erikvvold@gmail.com] --> + +Some add-ons may wish to define keyboard shortcuts for certain operations. This +module exposes an API to create +[xul based hotkeys](https://developer.mozilla.org/en/XUL/key). + +## Example ## + + var keyID = "ADDON:EXAMPLE-HOTKEY@ERIKVOLD.COM:CMD-ALT-R"; + const { XulKey } = require("xulkeys"); + + XulKey({ + id: keyID, + modifiers: "accel,alt", + key: "R", + onCommand: function() { + console.log("pressed"); + } + }); + +<api name="XulKey"> +@class + +This module exports a `XulKey` constructor which allows one to create xul based +hotkeys. + +<api name="XulKey"> +@constructor +Creates a hotkey whose `onCommand` listener method is invoked when the key +comboination provided is pressed. + +@param options {Object} + Options that define the hotkey, with the following properties: + +@prop [id] {string} + A namespaced unique id for the key element. +@prop key {string} + The key to listen for. +@prop [modifiers] {string} + A list of modifier keys that should be pressed to invoke the hotkey. + Multiple keys may be separated by spaces or commas. + + "accel" + "meta,shift" + "control alt" + + See the [MDN documentation on the modifiers + attribute](https://developer.mozilla.org/en/XUL/Attribute/modifiers) for a + full list of acceptable values. + +@prop onCommand {function} + A function that is invoked when the hotkey is pressed. +</api> + +</api> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/data/test.user.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/data/test.user.js new file mode 100644 index 0000000..5911b8e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/data/test.user.js @@ -0,0 +1,6 @@ +// ==UserScript== +// @name test +// @namespace test +// @include http://erikvold.com/* +// @exclude *google* +// ==/UserScript== diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/lib/main.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/lib/main.js new file mode 100644 index 0000000..b0a92ef --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/lib/main.js @@ -0,0 +1,11 @@ + +var scripts = [ "test.user.js"]; + +var self = require("self"); +var {UserScript} = require("userscript"); + +exports.main = function() { + scripts.forEach(function(scriptName, index) { + var script = UserScript(self.data.url(scriptName)); + }); +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/package.json b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/package.json new file mode 100644 index 0000000..9a5b737 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/examples/test/package.json @@ -0,0 +1,8 @@ +{ + "name": "test", + "fullName": "test", + "author": "Erik Vold <erikvvold@gmail.com>", + "id": "superbgwo@erikvold.com", + "version": "0.0.1", + "dependencies": ["addon-kit", "api-utils", "userscripts", "vold-utils"] +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/folder.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/folder.js new file mode 100644 index 0000000..4b590c5 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/folder.js @@ -0,0 +1,51 @@ +'use strict'; + +const JETPACK_DIR_BASENAME = "jetpack"; +const PATH_TEST = /^[\s\.\\\/]/; + +const { Cc, Ci } = require('chrome'); +const file = require('sdk/io/file'); +const jpSelf = require('sdk/self'); + +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('addon-folder'); + +const ADDON_FOLDER_PATH = storeFile.path + '/'; + +// make the addon-folder container folder +file.mkpath(ADDON_FOLDER_PATH); + +function ioFileWrap(funcName, preMode) { + preMode = preMode || ""; + return function(filepath, mode) { + filepath = filepath || ''; + if (PATH_TEST.test(filepath)) { + throw 'The provided filepath "' + filepath + '"" is not valid'; + } + return file[funcName](ADDON_FOLDER_PATH + filepath, preMode + mode); + } +} +exports.isFile = ioFileWrap('isFile'); +exports.exists = ioFileWrap('exists'); + +exports.remove = function(filepath) { + if (exports.isFile(filepath)) { + file.remove(ADDON_FOLDER_PATH + filepath); + } + else { + file.rmdir(ADDON_FOLDER_PATH + filepath); + } +}; +exports.read = ioFileWrap('read'); +exports.write = ioFileWrap('open', 'w'); +exports.mkpath = ioFileWrap('mkpath'); +exports.list = ioFileWrap('list'); + +exports.destroy = function destroy() { + // remove the addon-folder container folder + file.rmdir(ADDON_FOLDER_PATH); +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/unload.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/unload.js new file mode 100644 index 0000000..78803e7 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/addon/unload.js @@ -0,0 +1,92 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Class } = require("sdk/core/heritage"); +const unloadNS = require("sdk/core/namespace").ns(); +const { when: unload } = require("sdk/system/unload"); + +var Unloader = exports.Unloader = Class({ + initialize: function Unloader() { + unloadNS(this).unloaders = []; + unloadNS(this).unloadersUnload = unloadersUnload.bind(null, unloadNS(this).unloaders); + + // run the unloaders on unload + unload(unloadNS(this).unloadersUnload); + }, + unload: function unload(callback, container) { + // Calling with no arguments runs all the unloader callbacks + if (callback == null) { + unloadNS(this).unloadersUnload(); + return null; + } + + let windowRemover = windowUnloader.bind(null, unloader, unloadNS(this).unloaders); + + // The callback is bound to the lifetime of the container if we have one + if (container != null) { + // Remove the unloader when the container unloads + container.addEventListener("unload", windowRemover, false); + + // Wrap the callback to additionally remove the unload listener + let origCallback = callback; + callback = function() { + container.removeEventListener("unload", windowRemover, false); + origCallback(); + } + } + + // Wrap the callback in a function that ignores failures + function unloader() { + try { + callback(); + } + catch(e) { + console.error(e); + } + } + unloadNS(this).unloaders.push(unloader); + + // Provide a way to remove the unloader + return removeUnloader.bind(null, unloader, unloadNS(this).unloaders); + } +}); + +function sliceUnloader(unloader, unloaders) { + let index = unloaders.indexOf(unloader); + if (index < 0) + return []; + return unloaders.splice(index, 1); +} +// wraps sliceUnloader and doesn't return anything +function removeUnloader(unloader, unloaders) { + sliceUnloader.apply(null, arguments); +} +function windowUnloader(unloader, unloaders) { + sliceUnloader.apply(null, arguments).forEach(function(u) u()); +} +function unloadersUnload(unloaders) { + // run all the pending unloaders + unloaders.slice().forEach(function(u) u()); + // clear the unload array + unloaders.length = 0; +} + +/** + * Save callbacks to run when unloading. Optionally scope the callback to a + * container, e.g., window. Provide a way to run all the callbacks. + * + * @usage unload(): Run all callbacks and release them. + * + * @usage unload(callback): Add a callback to run on unload. + * @param [function] callback: 0-parameter function to call on unload. + * @return [function]: A 0-parameter function that undoes adding the callback. + * + * @usage unload(callback, container) Add a scoped callback to run on unload. + * @param [function] callback: 0-parameter function to call on unload. + * @param [node] container: Remove the callback when this container unloads. + * @return [function]: A 0-parameter function that undoes adding the callback. + */ +const gUnload = Unloader(); +exports.unload = gUnload.unload.bind(gUnload); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/addon.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/addon.js new file mode 100644 index 0000000..815f8ed --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/addon.js @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const {Cc, Ci, Cu} = require("chrome"); +const {AddonManager, AddonAuthor} = require("../utils/addonmanager"); +const DO_NOTHING = function(){}; + +// https://developer.mozilla.org/en/Addons/Add-on_Manager/Addon +function Addon(options) { + + this.appDisabled = !!options.appDisabled || false; + this.blocklistState = (options.blocked) ? 2 : 0; + if (options.creator) { + this.creator = new AddonAuthor(options.creator.name); + } + this.id = options.id; + if (typeof options.isActive != "undefined") this.isActive = !!options.isActive; + if (typeof options.isCompatible != "undefined") this.isCompatible = !!options.isCompatible; + if (typeof options.isPlatformCompatible != "undefined") this.isPlatformCompatible = !!options.isPlatformCompatible; + this.name = options.name || ""; + //this.pendingOperations = + this.description = options.description || ""; + if (options.iconURL) this.iconURL = options.iconURL; + + // METHODS + this.uninstall = function() { + options.uninstall && options.uninstall(); + }; + this.cancelUninstall = function() { + options.cancelUninstall && options.cancelUninstall(); + }; + + if (options.getResourceURI) { + this.getResourceURI = function(aPath) { + return options.getResourceURI(aPath); + }; + this.getXPI = function() { + return options.getResourceURI("").QueryInterface(Ci.nsIFileURL).file; + } + } + + return this; +}; + +Addon.prototype = { + // req'd + appDisabled: false, + blocklistState: 0, + creator: null, + id: null, + isActive: true, + isCompatible: true, + isPlatformCompatible: true, + name: null, + pendingOperations: AddonManager.PENDING_NONE, + permissions: AddonManager.PERM_CAN_UNINSTALL, + providesUpdatesSecurely: false, + scope: AddonManager.SCOPE_PROFILE, + type: null, + userDisabled: false, + version: null, + + //not reqd + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE, + contributors: [], + description: "", + translators: [], + sourceURI: null, + + + // METHODS + uninstall: DO_NOTHING, + findUpdates: DO_NOTHING, + cancelUninstall: DO_NOTHING, + hasResource: DO_NOTHING +}; + +exports.Addon = Addon; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/manager.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/manager.js new file mode 100644 index 0000000..cc9388e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/manager.js @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const {AddonManager, AddonManagerPrivate} = require("../utils/addonmanager"); +const Addon = require("addon").Addon; + +exports.getAddonByID = exports.getAddonById = function(aID, aCallback) { + // get the addon obj + AddonManager.getAddonByID(aID, function (addon) { + // return a wrapped addon + aCallback(new Addon(addon)); + }); +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/provider.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/provider.js new file mode 100644 index 0000000..681dcd9 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/aom/provider.js @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const unload = require("sdk/system/unload").when; + +const {AddonManager, AddonManagerPrivate, AddonType} = require("../utils/addonmanager"); + +var defaultUIPriority = 6001; // this increases when it is used + +exports.AddonProvider = function(options) { + var types = null; + + // AddonManagerPrivate.AddonType DNE in Gecko (FF) < 6 + if (AddonType) { + types = [new AddonType( + options.type, // TODO: RANDOMIZE? + null, + options.localeKey, + AddonManager.VIEW_TYPE_LIST, + options.uiPriority || defaultUIPriority++)]; + } + + var provider = { + getAddonByID: function(aId, aCallback) { + aCallback(options.getAddonByID(aId)); + }, + + getAddonsByTypes: function(aTypes, aCallback) { + if (aTypes && aTypes.indexOf(options.type) < 0) { + // not the right type, return nothing + aCallback([]); + } + else { + // the right type, return all addons + aCallback(options.getAddons()); + } + }, + + getInstallsByTypes: function(aTypes, aCallback) { + aCallback([]); + } + }; + AddonManagerPrivate.registerProvider(provider, types); + + unload(function() { + AddonManagerPrivate.unregisterProvider(provider); + }); + + return this; +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/application/restart.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/application/restart.js new file mode 100644 index 0000000..7d97f37 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/application/restart.js @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci } = require("chrome"); + +exports.restart = function restart() { + let canceled = Cc["@mozilla.org/supports-PRBool;1"] + .createInstance(Ci.nsISupportsPRBool); + + Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService) + .notifyObservers(canceled, "quit-application-requested", "restart"); + + if (canceled.data) return false; // somebody canceled our quit request + + // restart + Cc['@mozilla.org/toolkit/app-startup;1'].getService(Ci.nsIAppStartup) + .quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); + + return true; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/instances.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/instances.js new file mode 100644 index 0000000..da9edb8 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/instances.js @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci, Cu } = require("chrome"); + +var Instances = exports.Instances = { + get bis() Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream), + get ch() Cc["@mozilla.org/security/hash;1"] + .createInstance(Ci.nsICryptoHash), + get dp() Cc["@mozilla.org/xmlextras/domparser;1"] + .createInstance(Ci.nsIDOMParser), + get ds() Cc["@mozilla.org/xmlextras/xmlserializer;1"] + .createInstance(Ci.nsIDOMSerializer), + get fos() Cc["@mozilla.org/network/file-output-stream;1"] + .createInstance(Ci.nsIFileOutputStream), + get sfos() Cc["@mozilla.org/network/safe-file-output-stream;1"] + .createInstance(Ci.nsIFileOutputStream) + .QueryInterface(Ci.nsISafeOutputStream), + get fp() Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker), + get lf() Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile), + get process() Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess), + get se() Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError) + .QueryInterface(Ci.nsIScriptError2), + get ss() Cc["@mozilla.org/supports-string;1"] + .createInstance(Ci.nsISupportsString), + get suc() Cc["@mozilla.org/intl/scriptableunicodeconverter"] + .createInstance(Ci.nsIScriptableUnicodeConverter), + get timer() Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer), + get wbp() Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] + .createInstance(Ci.nsIWebBrowserPersist), + get xhr() Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] + .createInstance(Ci.nsIXMLHttpRequest) +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/net-utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/net-utils.js new file mode 100644 index 0000000..a657d20 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/net-utils.js @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +require("chrome").Cu.import("resource://gre/modules/NetUtil.jsm", this); +exports.NetUtil = NetUtil; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/services.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/services.js new file mode 100644 index 0000000..9df8b59 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/services.js @@ -0,0 +1,57 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci, Cu } = require("chrome"); +Cu.import("resource://gre/modules/Services.jsm", this); + +const global = this; +var Services = exports.Services = {}; +(function(inc, tools){ + inc("resource://gre/modules/XPCOMUtils.jsm", global); + inc("resource://gre/modules/Services.jsm", tools); + Services.__proto__ = tools.Services; +})(Cu.import, {}); + +XPCOMUtils.defineLazyServiceGetter( + Services, "as", "@mozilla.org/alerts-service;1", "nsIAlertsService"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "ass", "@mozilla.org/appshell/appShellService;1", + "nsIAppShellService"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "cb", "@mozilla.org/widget/clipboardhelper;1", + "nsIClipboardHelper"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "cs", "@mozilla.org/consoleservice;1", "nsIConsoleService"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "eps", "@mozilla.org/uriloader/external-protocol-service;1", + "nsIExternalProtocolService"); + +if (Cc["@mozilla.org/privatebrowsing;1"]) { + XPCOMUtils.defineLazyServiceGetter( + Services, "pbs", "@mozilla.org/privatebrowsing;1", + "nsIPrivateBrowsingService"); +} else { + Services.pbs = {privateBrowsingEnabled: false}; +} + +XPCOMUtils.defineLazyServiceGetter( + Services, "sis", "@mozilla.org/scriptableinputstream;1", + "nsIScriptableInputStream"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "suhtml", "@mozilla.org/feed-unescapehtml;1", + "nsIScriptableUnescapeHTML"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "tld", "@mozilla.org/network/effective-tld-service;1", + "nsIEffectiveTLDService"); + +XPCOMUtils.defineLazyServiceGetter( + Services, "uuid", "@mozilla.org/uuid-generator;1", + "nsIUUIDGenerator"); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/xpcom-utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/xpcom-utils.js new file mode 100644 index 0000000..f453b34 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/chrome/xpcom-utils.js @@ -0,0 +1,3 @@ + +require("chrome").Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); +exports.XPCOMUtils = XPCOMUtils; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/events.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/events.js new file mode 100644 index 0000000..7d9071b --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/events.js @@ -0,0 +1,23 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const events = require('sdk/system/events'); +const { on, once, off, emit } = require('sdk/event/core'); + +function onRequest(evt) { + emit(exports, 'modify-request', evt); +} +events.on('http-on-modify-request', onRequest); + +/* +function onResponse(evt) { + emit(exports, 'examine-response', evt); +} +events.on('http-on-examine-response', onResponse); +*/ + +exports.on = on.bind(null, exports); +exports.once = once.bind(null, exports); +exports.off = off.bind(null, exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/request.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/request.js new file mode 100644 index 0000000..bf93ca0 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/request.js @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci } = require('chrome'); +const { List, addListItem, removeListItem } = require('sdk/util/list'); +const { ns } = require('sdk/core/namespace'); +const { Class } = require('sdk/core/heritage'); +const { Disposable } = require('sdk/core/disposable'); + +const events = require('./events'); + +const REQUEST_RULES = List(); +const requestNS = ns(); + +function onRequest(evt) { + for each (let rule in REQUEST_RULES) { + applyRequestHeaders(rule, evt) + } +} +events.on('modify-request', onRequest); + +const RequestRule = Class({ + implements: [ Disposable ], + initialize: function(details) { + requestNS(this).details = details; + addListItem(REQUEST_RULES, this); + }, + dispose: function() { + removeListItem(REQUEST_RULES, this); + } +}); +exports.RequestRule = RequestRule; + +function applyRequestHeaders(rule, evt) { + let channel = evt.subject.QueryInterface(Ci.nsIHttpChannel); + let requestURL = channel.URI.spec + + let details = requestNS(rule).details; + let { headers: rules } = details; + for each (let key in Object.keys(rules)) { + channel.setRequestHeader(key, rules[key] + '', false); + } +}
\ No newline at end of file diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/response.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/response.js new file mode 100644 index 0000000..c0ed791 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connection/response.js @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci } = require('chrome'); +const { List, addListItem, removeListItem } = require('sdk/util/list'); +const { ns } = require('sdk/core/namespace'); +const { Class } = require('sdk/core/heritage'); + +const events = require('./events'); + +const RESPONSE_RULES = List(); + +const requestNS = ns(); + +function onResponse(evt) { + for each (let rule in RESPONSE_RULES) { + applyResponseHeaders(rule, evt) + } +} +events.on('examine-response', onResponse); + +const ResponseRule = Class({ + initialize: function(details) { + requestNS(this).details = details; + addListItem(RESPONSE_RULES, this); + }, + destroy: function() { + removeListItem(RESPONSE_RULES, this); + } +}); +exports.ResponseRule = ResponseRule; + +function applyResponseHeaders(rule, evt) { + let channel = evt.subject.QueryInterface(Ci.nsIHttpChannel); + let requestURL = channel.URI.spec + + let details = requestNS(rule).details; + let { headers: rules } = details; + for each (let key in Object.keys(rules)) { + channel.setResponseHeader(key, rules[key], false); + } +}
\ No newline at end of file diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connections.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connections.js new file mode 100644 index 0000000..b81eba1 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/connections.js @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +exports.RequestRule = require('./connection/request').RequestRule; +//exports.ResponseRule = require('./connection/response').ResponseRule; + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/permissions.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/permissions.js new file mode 100644 index 0000000..49cc955 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/permissions.js @@ -0,0 +1,88 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci, Cu } = require('chrome'); +const { List, addListItem } = require('sdk/util/list'); +const { URL } = require('sdk/url'); + +const { Services } = require('../chrome/services'); + +const { nsIPermissionManager } = Ci; + +const UNKNOWN = nsIPermissionManager.UNKNOWN_ACTION; // 0 +const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1 +const BLOCK = nsIPermissionManager.DENY_ACTION; // 2 +const SESSION = Ci.nsICookiePermission.ACCESS_SESSION; // 8 + +function getKey(obj, val) { + for (let key in obj) + if (obj[key] == val) + return key; + + return undefined; +} + +const PERMISSIONS = { + 'session': SESSION, + 'allow': ALLOW, + 'deny': BLOCK +}; + +const TYPES = { + 'images': 'image', + 'popups': 'popup', + 'desktop-notifications': 'desktop-notification', + 'installs': 'install', + 'location': 'geo', + 'fullscreen': 'fullscreen', + 'pointer-lock': 'pointerLock' +} + +const PM = Cc['@mozilla.org/permissionmanager;1']. + getService(nsIPermissionManager); + +function add(options) { + let uri = Services.io.newURI(options.url, null, null); + if (!/^https?/.test(uri.scheme)) { + throw new Error('invalid content url, only https or http schemes are accepted'); + } + + PM.add(uri, + TYPES[options.type], + PERMISSIONS[options.permission]); +} + +function remove(options) { + PM.remove(URL(options.url).host, TYPES[options.type]); +} + +function removeAll() { + PM.removeAll(); +} + +// TODO: cache entries after first request, and observe new additions with the "perm-changed" event + +exports.permissions = { + add: add, + remove: remove, + removeAll: removeAll, + get permissions() { + let list = List(); + let permissions = PM.enumerator; + while (permissions.hasMoreElements()) { + let permission = permissions.getNext().QueryInterface(Ci.nsIPermission); + + addListItem(list, { + type: getKey(TYPES, permission.type), + host: String(permission.host), + permission: getKey(PERMISSIONS, Number(permission.capability)) + //'expire-time': Number(permission.expireTime), + }); + } + return list; + }, + TYPES: TYPES, + PERMISSIONS: PERMISSIONS +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/policy.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/policy.js new file mode 100644 index 0000000..b764272 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/content/policy.js @@ -0,0 +1,143 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci } = require('chrome'); +const { Class } = require('sdk/core/heritage'); +const CP_NS = require('sdk/core/namespace').ns(); +const { ensure } = require('sdk/system/unload'); +const { validateOptions } = require('sdk/deprecated/api-utils'); +const { id: ADDON_ID } = require('sdk/self'); +const xpcom = require('sdk/platform/xpcom'); + +const CM = Cc["@mozilla.org/categorymanager;1"] + .getService(Ci.nsICategoryManager); + +const ACCEPT = exports.ACCEPT = Ci.nsIContentPolicy.ACCEPT; +const REJECT = exports.REJECT = Ci.nsIContentPolicy.REJECT_REQUEST; + +const accept = function() ACCEPT; + +let ContentPolicy_ID = 0; + +const RULES = { + description: { + map: function(v) { + return v ? v : ''; + }, + is: ['string'] + }, + contract: { + map: function(v) { + if (v === undefined) { + v = '@erikvold.com/content-policy.' + ADDON_ID + ';' + ContentPolicy_ID++; + } + return v; + }, + is: ['string'] + }, + entry: { + is: ['string', 'undefined'] + }, + shouldLoad: { + is: ['function', 'undefined'] + }, + shouldProcess: { + is: ['function', 'undefined'] + }, +}; + +function getType(aType) { + switch (aType) { + case Ci.nsIContentPolicy.TYPE_SCRIPT: + return 'script'; + case Ci.nsIContentPolicy.TYPE_IMAGE: + return 'image'; + case Ci.nsIContentPolicy.TYPE_STYLESHEET: + return 'stylesheet'; + case Ci.nsIContentPolicy.TYPE_OBJECT: + return 'object'; + case Ci.nsIContentPolicy.TYPE_DOCUMENT: + return 'document'; + case Ci.nsIContentPolicy.TYPE_SUBDOCUMENT: + return 'subdocument'; + case Ci.nsIContentPolicy.TYPE_REFRESH: + return 'refresh'; + case Ci.nsIContentPolicy.TYPE_XBL: + return 'xbl'; + case Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST: + return 'xhr'; + case Ci.nsIContentPolicy.TYPE_PING: + return 'ping'; + // TODO: support more types + } + return 'other'; +} +const getTypeMemod = memoize(getType, 12, 1); + +function makeDetails(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess) { + return { + type: getTypeMemod(aContentType), + location: aContentLocation.spec, + origin: aRequestOrigin.spec, + context: null, // TODO: support this in a safe way somehow.. + mimeTypeGuess: String(aMimeTypeGuess) + }; +} + +let ContentPolicy = exports.ContentPolicy = Class({ + initialize: function(options) { + const self = this; + options = CP_NS(self).options = validateOptions(options, RULES); + CP_NS(self).shouldLoad = options.shouldLoad || accept; + CP_NS(self).shouldProcess = options.shouldProcess || accept; + + let factory = CP_NS(this).factory = xpcom.Factory({ + Component: getProvider(self), + description: options.description, + contract: options.contract + }); + + let entry = options.entry || options.contract; + CM.addCategoryEntry('content-policy', entry, factory.contract, false, true); + ensure(this, 'destroy'); + }, + destroy: function() { + // already destroyed? + if (!CP_NS(this).options) + return; + + let options = CP_NS(this).options; + CP_NS(this).options = null; + CP_NS(this).shouldLoad = accept; + CP_NS(this).shouldProcess = accept; + + CM.deleteCategoryEntry('content-policy', options.entry || options.contract, false); + } +}); + +function getProvider(self) { + return Class({ + extends: xpcom.Unknown, + interfaces: ['nsIContentPolicy'], + shouldLoad: function (aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { + let load = CP_NS(self).shouldLoad(makeDetails.apply(null, arguments)); + return (load == REJECT || (!load && load !== undefined)) ? REJECT : ACCEPT; + }, + shouldProcess: function (aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { + let load = CP_NS(self).shouldProcess(makeDetails.apply(null, arguments)); + return (load == REJECT || (!load && load !== undefined)) ? REJECT : ACCEPT; + } + }); +} + +function memoize(func) { + let cache = Object.create(null); + return function(a) { + let key = a.toString(); + if (key in cache) + return cache[key]; + return cache[key] = func.call(null, a); + }; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/devtools/gcli.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/devtools/gcli.js new file mode 100644 index 0000000..e1bb17f --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/devtools/gcli.js @@ -0,0 +1,23 @@ +'use strict'; + +const { Cu } = require('chrome'); +const { when: unload } = require('unload'); + +try { + // Starting with FF 23, gcli.jsm moved to another location + Cu.import("resource://gre/modules/devtools/gcli.jsm"); +} catch(e) { + try { + Cu.import("resource:///modules/devtools/gcli.jsm"); + } catch(e) { + console.error("Unable to load gcli.jsm"); + } +} + +function addCommand(cmd) { + let name = cmd.name; + gcli.addCommand(cmd); + unload(gcli.removeCommand.bind(gcli, name)); +} +exports.addCommand = addCommand; +exports.removeCommand = gcli.removeCommand; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/download.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/download.js new file mode 100644 index 0000000..20fef54 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/download.js @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci, Cc, Cu } = require('chrome'); +const { Class } = require('sdk/core/heritage'); +const { on, off, emit, setListeners } = require('sdk/event/core'); +const { EventTarget } = require("sdk/event/target"); +const { ns } = require("sdk/core/namespace"); +const { validateOptions } = require("sdk/deprecated/api-utils"); +const { isValidURI } = require("sdk/url"); + +const PROGRESS_LISTENER_NS = ns(); + +const { Services } = Cu.import('resource://gre/modules/Services.jsm', {}); + +const rules = { + url: { + // Also converts a URL instance to string, bug 857902 + map: function (url) url.toString(), + ok: isValidURI + }, + destination: { + is: ['string'] + } +}; + +const Download = Class({ + extends: EventTarget, + initialize: function(options) { + // Setup listeners. + setListeners(this, options); + + options = validateOptions(options, rules); + + const wbp = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] + .createInstance(Ci.nsIWebBrowserPersist); + let listener = ProgressListener({ + download: this + }); + + wbp.progressListener = listener; + + let localFile = Cc["@mozilla.org/file/local;1"] + .createInstance(Ci.nsILocalFile); + localFile.initWithPath(options.destination); + localFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0666", 8)); + localFile = localFile.QueryInterface(Ci.nsIFile); + + let uri = Services.io.newURI(options.url, null, null); + wbp.saveURI(uri, null, null, null, null, localFile, null); + } +}); +exports.Download = Download; + +const ProgressListener = Class({ + initialize: function(options) { + const internals = PROGRESS_LISTENER_NS(this); + internals.options = options; + this.onStateChange = this.onStateChange.bind(this); + }, + get options() PROGRESS_LISTENER_NS(this).options, + get download() this.options.download, + onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { + }, + onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { + emit(this.download, 'progress', { + current: aCurTotalProgress, + total: aMaxTotalProgress + }) + }, + onSecurityChange: function(aWebProgress, aRequest, aState) { + }, + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { + if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)) + return; + + try { + var { responseStatus, requestSucceeded } = aRequest.QueryInterface(Ci.nsIHttpChannel); + } + catch (e) { + //console.exception(e); + } + + emit(this.download, 'complete', { + responseStatus: responseStatus, + requestSucceeded: requestSucceeded + }); + + return; + }, + onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/l10n.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/l10n.js new file mode 100644 index 0000000..22ed58c --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/l10n.js @@ -0,0 +1,76 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const global = this; +const {Cc,Ci,Cu} = require("chrome"); +Cu.import("resource://gre/modules/Services.jsm", global); + +exports.locale = Cc["@mozilla.org/chrome/chrome-registry;1"] + .getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global"); + +exports.l10n = (function(global) { + let splitter = /(\w+)-\w+/; + + // get user's locale + let locale = exports.locale; + + function getStr(aStrBundle, aKey) { + if (!aStrBundle) return false; + try { + return aStrBundle.GetStringFromName(aKey); + } catch (e) { + //console.log(e); + } + return ""; + } + + function l10n(options) { + var filename = options.filename; + var baseURL = options.baseURL; + var defaultLocale = options.defaultLocale || "en"; + function filepath(locale) { + var path = baseURL + "/" + locale + "/" + filename; + //console.log(path); + return path; + } + + let defaultBundle = Services.strings.createBundle(filepath(locale)); + + let defaultBasicBundle; + let (locale_base = locale.match(splitter)) { + if (locale_base) { + defaultBasicBundle = Services.strings.createBundle( + filepath(locale_base[1])); + } + } + + let addonsDefaultBundle = + Services.strings.createBundle(filepath(defaultLocale)); + + return _ = function l10n_underscore(aKey, aLocale) { + let localeBundle, localeBasicBundle; + if (aLocale) { + localeBundle = Services.strings.createBundle(filepath(aLocale)); + + let locale_base = aLocale.match(splitter) + if (locale_base) + localeBasicBundle = Services.strings.createBundle( + filepath(locale_base[1])); + } + + var x = getStr(localeBundle, aKey) + || getStr(localeBasicBundle, aKey) + || getStr(defaultBundle, aKey) + || getStr(defaultBasicBundle, aKey) + || getStr(addonsDefaultBundle, aKey); + return x; + } + } + + return l10n; +})(this); + +require("unload").when(Services.strings.flushBundles); + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/panic.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/panic.js new file mode 100644 index 0000000..a478077 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/panic.js @@ -0,0 +1,92 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { setTimeout } = require('sdk/timers'); +const { get, set } = require('sdk/preferences/service'); +const { add, notify } = require('sdk/deprecated/observer-service'); +const { on, once, emit, off } = require('sdk/event/core'); +const { loadReason } = require('sdk/self'); + +const { unload } = require('./addon/unload'); + +const PREF_NAME = 'security.addon.panic'; +function inPanic() get(PREF_NAME, false); +function setPanic(value) set(PREF_NAME, value); + +const PREF_END_NAME = 'security.addon.panic_end'; +function getEndTime() get(PREF_END_NAME, 0) * 1; +function setEndTime(timestamp) set(PREF_END_NAME, timestamp + ""); + +Object.defineProperty(exports, "inPanic", { + get: function() inPanic() +}); + +const panic = function (ms) { + ms = ms || 0; + let endTime = Date.now() + ms; + + // check that the current end timestamp is not greater + if (getEndTime() >= endTime) + return; + + // set the end timestamp (to handle the reboot situation) + setEndTime(endTime); + + // notify system of a panic + notify('panic-start'); + + // end the panic + setTimeout(function() { + // check that the end timestamp was not extended by another panic + // NOTE: another instance of panic module could have caused the old panic + if (getEndTime() != endTime) return; + + notify('panic-end'); + }, ms); +}; +exports.panic = panic; + +// internal object used to emit on, instead of `exports`, so that outside code +// cannot emit on this object. +const panicEmitter = {}; + +// create and expose event listener related methods for this module +exports.on = on.bind(null, panicEmitter); +exports.once = once.bind(null, panicEmitter); +exports.off = off.bind(null, panicEmitter); + +// listen to 'panic-start' events in the observer-service since they may come +// from other instances of this module +add('panic-start', function () { + setPanic(true); + emit(panicEmitter, 'start'); +}); +// listen to 'panic-end' events for the same reason as for 'panic-start' +add('panic-end', function () { + setPanic(false); + emit(panicEmitter, 'end'); +}); + +// cleanup prefs on startup, since the add-on could be installed before or +// during startup +if (loadReason == 'startup') { + // check the end timestamp (for the reboot situation) + if (getEndTime() <= Date.now()) { + setEndTime(0); + + if (inPanic()) { + setPanic(false); + } + } +} + +// clean up prefs on shutdown, don't do cleanup on other reasons because there +// may be other instances of the module running +unload(function(reason) { + if (reason == 'shutdown') { + setPanic(false); + setEndTime(0); + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/redirect.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/redirect.js new file mode 100644 index 0000000..ffd46db --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/redirect.js @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci } = require('chrome'); +const { List, addListItem, removeListItem } = require('sdk/util/list'); +const { ns } = require('sdk/core/namespace'); +const { Class } = require('sdk/core/heritage'); +const { Disposable } = require('sdk/core/disposable'); +const { newURI } = require('sdk/url/utils'); + +const events = require('./connection/events'); + +const REDIRECTS = List(); +const requestNS = ns(); + +function onRequest({ subject }) { + let channel = subject.QueryInterface(Ci.nsIHttpChannel); + for each (let redirect in REDIRECTS) + if (applyRedirect(redirect, channel)) + break; + return; +} +events.on('modify-request', onRequest); + +const Redirect = Class({ + implements: [ Disposable ], + initialize: function(details) { + details.to = newURI(details.to.toString()); + requestNS(this).details = details; + + addListItem(REDIRECTS, this); + }, + dispose: function() { + removeListItem(REDIRECTS, this); + }, + get from() requestNS(this).details.from, + get to() requestNS(this).details.to.spec +}); +exports.Redirect = Redirect; + +function applyRedirect(redirect, channel) { + let { from, to } = requestNS(redirect).details; + + if (channel.URI.spec == from) { + channel.redirectTo(to); + // emit(rule, 'redirect', {}); + return true; + } + return false; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/about.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/about.js new file mode 100644 index 0000000..7d94b78 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/about.js @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cr, Cu, Ci, Cc, Cm } = require('chrome'); +const { when: unload } = require('sdk/system/unload'); +const { validateOptions : validate } = require('sdk/deprecated/api-utils'); +const { uuid } = require('sdk/util/uuid'); +const { URL, isValidURI } = require('sdk/url'); +const tabs = require('sdk/tabs'); + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +const validOptions = { + what: { + is: ['string'], + ok: function(what) { + if (what.match(/^[a-z0-9-]+$/i)) + return true; + return false; + }, + map: function(url) url.toLowerCase() + }, + url: { + map: function(url) url.toString(), + ok: isValidURI + }, + useChrome: { + is: ['undefined', 'null', 'boolean'], + map: function(use) !!use + } +}; + +function add(options) { + let { what, url, useChrome } = validate(options, validOptions); + let classID = uuid(); + + let aboutModule = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]), + newChannel: function (aURI) { + let chan = Services.io.newChannel(url, null, null); + if (useChrome) + chan.owner = Services.scriptSecurityManager.getSystemPrincipal(); + return chan; + }, + getURIFlags: function () Ci.nsIAboutModule.ALLOW_SCRIPT + }; + + let factory = { + createInstance: function(aOuter, aIID) { + if (aOuter) + throw Cr.NS_ERROR_NO_AGGREGATION; + return aboutModule.QueryInterface(aIID); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) + }; + + // register about:what + Cm.QueryInterface(Ci.nsIComponentRegistrar). + registerFactory(classID, '', '@mozilla.org/network/protocol/about;1?what='+what, factory); + + let remover = unloader.bind(null, what, factory, classID); + unload(remover); + + return undefined; +} +exports.add = add; + +function unloader(what, factory, classID) { + // unregister about:what + Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(classID, factory); + let regEx = new RegExp('^' + what, 'i'); + + // AMO policy, see http://maglione-k.users.sourceforge.net/bootstrapped.xhtml + // close about:what tabs + for each (let tab in tabs) { + let url = URL(tab.url); + if (url.scheme === 'about' && url.path.match(regEx)) { + tab.close(); + } + } +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/resource.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/resource.js new file mode 100644 index 0000000..81a4061 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scheme/resource.js @@ -0,0 +1,43 @@ +/*jshint asi:true globalstrict:true*/ +'use strict'; + +const { Cc, Ci } = require('chrome') +const ioService = Cc['@mozilla.org/network/io-service;1']. + getService(Ci.nsIIOService); +const resourceHandler = ioService.getProtocolHandler('resource'). + QueryInterface(Ci.nsIResProtocolHandler) + +function get(root) { + /** + Gets the substitution for the `root` key. + **/ + try { + return resourceHandler.getSubstitution(root).spec; + } + catch (error) {} + return null; +} +exports.get = get; + +function has(root) { + /** + Returns `true` if the substitution exists and `false` otherwise. + **/ + return resourceHandler.hasSubstitution(root); +} +exports.has = has; + +function set(root, uri) { + /** + Sets the substitution for the root key: + + resource://root/path ==> baseURI.resolve(path) + + A `null` `uri` removes substitution. A root key should + always be lowercase. However, this may not be enforced. + **/ + uri = !uri ? null : + uri instanceof Ci.nsIURI ? uri : ioService.newURI(uri, null, null); + resourceHandler.setSubstitution(root, uri); +} +exports.set = set; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/GM_xmlhttpRequester.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/GM_xmlhttpRequester.js new file mode 100644 index 0000000..8ca3f5b --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/GM_xmlhttpRequester.js @@ -0,0 +1,238 @@ +'use strict'; + +function Scriptish_stringBundle(a) a; + +const {Cc, Ci, Cu, Cr} = require("chrome"); +var {Instances} = require("../chrome/instances"); +var {XPCOMUtils} = require("../chrome/xpcom-utils"); +var {NetUtil} = require("../chrome/net-utils"); + +const MIME_JSON = /^(application|text)\/(?:x-)?json/i; + +/** + * Abstract base class for (chained) request notification callback overrides + * + * Use such overrides sparely, as the individual request performance might + * degrade quite a bit. + * + * @param req XMLHttpRequest (chrome) + * @author Nils Maier + */ +function NotificationCallbacks(req) { + throw new Error("trying to initiate an abstract NotificationCallbacks"); +} +NotificationCallbacks.prototype = { + init: function(req) { + // rewrite notification callbacks + this._channel = req.channel; + this._notificationCallbacks = this._channel.notificationCallbacks; + this._channel.notificationCallbacks = this; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor]), + getInterface: function(iid) { + try { + return this.query(iid); + } + catch (ex) { + return this.queryOriginal(iid); + } + }, + queryOriginal: function(iid) { + if (this._notificationCallbacks) { + return this._notificationCallbacks.getInterface(iid); + } + throw Cr.NS_ERROR_NO_INTERFACE; + } +} + +/** + * Ignore (specific) redirects + * @param req XMLHttpRequest (chrome) + * @author Nils Maier + */ +function IgnoreRedirect(req, ignoreFlags) { + this.init(req); + this.ignoreFlags = ignoreFlags; +} +IgnoreRedirect.prototype = { + __proto__: NotificationCallbacks.prototype, + query: XPCOMUtils.generateQI([Ci.nsIChannelEventSink]), + asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) { + if (this.ignoreFlags & flags) { + // must throw here, not call callback.onRedirectVerifyCallback, + // or else it will completely cancel the request + throw Cr.NS_ERROR_UNEXPECTED; + } + + try { + let ces = this.queryOriginal(Ci.nsIChannelEventSink); + if (ces) { + ces.asyncOnChannelRedirect(oldChannel, newChannel, flags, callback); + return; + } + } + catch (ex) {} + + callback.onRedirectVerifyCallback(Cr.NS_OK); + } +}; + + +function GM_xmlhttpRequester(unsafeContentWin, originUrl, aScript) { + this.unsafeContentWin = unsafeContentWin; + this.originUrl = originUrl; + this.script = aScript; +} +exports.GM_xmlhttpRequester = GM_xmlhttpRequester; + +// this function gets called by user scripts in content security scope to +// start a cross-domain xmlhttp request. +// +// details should look like: +// {method,url,onload,onerror,onreadystatechange,headers,data} +// headers should be in the form {name:value,name:value,etc} +// can't support mimetype because i think it's only used for forcing +// text/xml and we can't support that +GM_xmlhttpRequester.prototype.contentStartRequest = function(details) { + try { + // Validate and parse the (possibly relative) given URL. + var uri = NetUtil.newURI(details.url, null, NetUtil.newURI(this.originUrl)); + var url = uri.spec; + } catch (e) { + // A malformed URL won't be parsed properly. + //throw new Error(Scriptish_stringBundle("error.api.reqURL") + ": " + details.url); + console.error(e); + } + + // check if the script is allowed to access the url + if (!this.script.matchesDomain(url)) + throw new Error( + "User script is attempting access to restricted domain '" + uri.host + "'", + this.script.fileURL); + + // This is important - without it, GM_xmlhttpRequest can be used to get + // access to things like files and chrome. Careful. + switch (uri.scheme) { + case "http": + case "https": + case "ftp": + var req = Instances.xhr; + this.chromeStartRequest(url, details, req); + break; + default: + throw new Error(Scriptish_stringBundle("error.api.reqURL.scheme") + ": " + details.url); + } + + return { + abort: function() { + req.abort(); + } + }; +}; + +// this function is intended to be called in chrome's security context, so +// that it can access other domains without security warning +GM_xmlhttpRequester.prototype.chromeStartRequest = + function(safeUrl, details, req) { + this.setupRequestEvent(this.unsafeContentWin, req, "onload", details); + this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details); + this.setupRequestEvent( + this.unsafeContentWin, req, "onreadystatechange", details); + + if (details.mozBackgroundRequest) req.mozBackgroundRequest = true; + + req.open( + details.method || "GET", + safeUrl, + true, + details.user || "", + details.password || "" + ); + + if (details.overrideMimeType) req.overrideMimeType(details.overrideMimeType); + + if (details.ignoreCache) + req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // bypass cache + + if (details.ignoreRedirect) + new IgnoreRedirect(req, + Ci.nsIChannelEventSink.REDIRECT_TEMPORARY | Ci.nsIChannelEventSink.REDIRECT_PERMANENT); + if (details.ignoreTempRedirect) + new IgnoreRedirect(req, Ci.nsIChannelEventSink.REDIRECT_TEMPORARY); + if (details.ignorePermanentRedirect) + new IgnoreRedirect(req, Ci.nsIChannelEventSink.REDIRECT_PERMANENT); + + let redirectionLimit = null; + if (details.failOnRedirect) { + redirectionLimit = 0; + } + if ("redirectionLimit" in details) { + if (details.redirectionLimit < 0 || details.redirectionLimit > 10) { + throw new Error("redirectionLimit must be within (0, 10), but it is " + details.redirectionLimit); + } + redirectionLimit = details.redirectionLimit; + } + if (redirectionLimit !== null && req.channel instanceof Ci.nsIHttpChannel) { + req.channel.redirectionLimit = redirectionLimit; + } + + if (details.headers) { + var headers = details.headers; + + for (var prop in headers) { + if (Object.prototype.hasOwnProperty.call(headers, prop)) + req.setRequestHeader(prop, headers[prop]); + } + } + + var body = details.data ? details.data : null; + if (details.binary) req.sendAsBinary(body); + else req.send(body); +} + +// arranges for the specified 'event' on xmlhttprequest 'req' to call the +// method by the same name which is a property of 'details' in the content +// window's security context. +GM_xmlhttpRequester.prototype.setupRequestEvent = + function(unsafeContentWin, req, event, details) { + var origMimeType = details.overrideMimeType; + var script = this.script; + + if (details[event]) { + req[event] = function() { + var responseState = { + // can't support responseXML because security won't + // let the browser call properties on it + responseText: req.responseText, + readyState: req.readyState, + responseHeaders: null, + status: null, + statusText: null, + finalUrl: null + }; + if (4 == req.readyState && 'onerror' != event) { + responseState.responseHeaders = req.getAllResponseHeaders(); + responseState.status = req.status; + responseState.statusText = req.statusText; + if (MIME_JSON.test(origMimeType) + || MIME_JSON.test(details.overrideMimeType) + || MIME_JSON.test(req.channel.contentType)) { + try { + responseState.responseJSON = JSON.parse(req.responseText); + } catch (e) { + responseState.responseJSON = {}; + } + } + responseState.finalUrl = req.channel.URI.spec; + } + + GM_apiSafeCallback( + unsafeContentWin, script, details, details[event], [responseState]); + } + } +} + +// TODO: replace!! +function GM_apiSafeCallback(aWindow, aScript, aThis, aCb, aArgs) { + aCb.apply(aThis, aArgs); +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/convert-2-regexp.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/convert-2-regexp.js new file mode 100644 index 0000000..9b79f30 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/convert-2-regexp.js @@ -0,0 +1,23 @@ +'use strict'; + +const RE_REGEXP = /^\/(.*)\/(i)?$/; +const RE_ESCAPE = /[{}()\[\]\\^$.?]/g; +const RE_WILD = /\*+/g; +const RE_TLD = /^\^[^\/]*(?:\/\/)?[^\/]*\\\.tld(?:\/.*)?\$$/; + +exports.convert2RegExp = function Scriptish_convert2RegExp(aPattern, aNoTLD, forceString) { + var s = aPattern.toString().trim(), m; + + // Already a regexp? + if (!forceString && (m = s.match(RE_REGEXP))) { + return new RegExp(m[1], m[2]); + } + + var res = "^" + s + .replace(RE_ESCAPE, "\\$&") + .replace(RE_WILD, ".*") + + "$"; + var regExp = new RegExp(res, "i"); + regExp.isTLD = !aNoTLD && RE_TLD.test(res); + return regExp; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/greasemonkey-api.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/greasemonkey-api.js new file mode 100644 index 0000000..e465883 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/greasemonkey-api.js @@ -0,0 +1,76 @@ +'use strict'; + +var { Services } = require("services"); +var prefService = require("preferences-service"); +var tabs = require("tabs"); +var clipboard = require("clipboard"); +var {GM_xmlhttpRequester} = require("GM_xmlhttpRequester"); + +const NS_XHTML = "http://www.w3.org/1999/xhtml"; + +function GM_API(aScript, aURL, aWinID, aSafeWin, aUnsafeContentWin, aChromeWin) { + var document = aSafeWin.document; + var windowID = aWinID; + var xhr = new GM_xmlhttpRequester(aUnsafeContentWin, aURL, aScript); + + this.GM_addStyle = function GM_addStyle(css) { + var head = document.getElementsByTagName("head")[0]; + var style = document.createElement("style"); + if (head) { + style.textContent = css; + style.type = "text/css"; + head.appendChild(style); + } + return style; + }; + + // TODO: use simple storage + this.GM_getValue = function GM_getValue(name, defVal) { + return prefService.get(aScript.prefPrefix + name, defVal); + }; + this.GM_setValue = function GM_setValue(name, val) { + return prefService.set(aScript.prefPrefix + name, val); + }; + + this.GM_safeHTMLParser = function GM_safeHTMLParser(aHTMLStr) { + //if (!GM_apiLeakCheck("GM_safeHTMLParser")) return; + let doc = document.implementation.createDocument(NS_XHTML, "html", null); + let body = document.createElementNS(NS_XHTML, "body"); + doc.documentElement.appendChild(body); + body.appendChild(Services.suhtml.parseFragment(aHTMLStr, false, null, body)); + return doc; + } + + this.GM_xmlhttpRequest = function GM_xmlhttpRequest() { + //if (!GM_apiLeakCheck("GM_xmlhttpRequest")) return; + return xhr.contentStartRequest.apply(xhr, arguments); + }; +}; +exports.GM_API = GM_API; + +GM_API.prototype.GM_openInTab = + function GM_openInTab(aURL, aLoadInBackground, aReuse) { + if (aReuse) { + for each (var tab in tabs) { + if (tab.url == aURL) { + if (!aLoadInBackground) + tab.activate(); + return; + } + } + } + + tabs.open({ + url: aURL, + inBackground: aLoadInBackground + }); +}; + +GM_API.prototype.GM_setClipboard = function GM_setClipboard(aData, aType) { + return clipboard.set(aData, aType); +}; + +GM_API.prototype.GM_generateUUID = function GM_generateUUID() ( + Services.uuid.generateUUID().toString()); + +GM_API.prototype.GM_registerMenuCommand = function() {}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-header-parser.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-header-parser.js new file mode 100644 index 0000000..41f7ffd --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-header-parser.js @@ -0,0 +1,31 @@ +'use strict'; + +exports.parse = function(aSource) { + var headers = {}; + var foundMeta = false; + var line; + + // do not 'optimize' by reusing this reg exp! it should not be reused! + var metaRegExp = /\/\/[ \t]*(?:==(\/?UserScript)==|\@(\S+)(?:[ \t]+([^\r\f\n]+))?)/g; + + // read one line at a time looking for start meta delimiter or EOF + while (line = metaRegExp.exec(aSource)) { + if (line[1]) { + if ("userscript" == line[1].toLowerCase()) { + foundMeta = true; // start + continue; + } else { + break; // done + } + } + if (!foundMeta) continue; + + var header = line[2].toLowerCase(); + var value = line[3]; + + if (!headers[header]) headers[header] = [value]; + else headers[header].push(value); + } + + return headers; +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-manager.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-manager.js new file mode 100644 index 0000000..f1eec70 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-manager.js @@ -0,0 +1,44 @@ +'use strict'; + +var { Services } = require("../chrome/services"); +var obs = require("sdk/deprecated/observer-service"); + +var sandboxFactory = require("./userscript-sandbox"); + +var userscripts = []; + +// TODO: register obs only when there is a userscript +obs.add("content-document-global-created", docReady); +obs.add("chrome-document-global-created", docReady); + +function docReady(safeWin, data) { + let href = (safeWin.location.href + || (safeWin.frameElement && safeWin.frameElement.src)) || ""; + + safeWin.addEventListener("load", function() { + userscripts.forEach(function(script) { + // check that the userscript should be run on this page + if (!script.matchesURL(href)) + return; + + sandboxFactory.evalInSandbox( + script._source, + sandboxFactory.createSandbox(safeWin, script, href), + script.jsversion); + }); + }, true); +} + +exports.register = function(aScript) { + unregister(aScript); + userscripts.push(aScript); +}; + +var unregister = exports.unregister = function unregister(aScript) { + for (var i = userscripts.length - 1; ~i; i--) { + if (userscripts[i] == aScript) { + userscripts.splice(i, 1); + break; + } + } +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-sandbox.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-sandbox.js new file mode 100644 index 0000000..1c92066 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/scriptish/userscript-sandbox.js @@ -0,0 +1,24 @@ +'use strict'; + +var { Cc, Ci, Cu } = require('chrome'); +var {GM_API} = require("./greasemonkey-api"); + +exports.createSandbox = function createSandbox(safeWin, userScript, aURL) { + var script = userScript.source; + var sandbox = new Cu.Sandbox(safeWin); + sandbox.window = safeWin; + sandbox.document = sandbox.window.document; + sandbox.__proto__ = safeWin; + var api = new GM_API(userScript, aURL, null, safeWin, safeWin.wrappedJSObject); + + for (var key in api) { + sandbox[key] = api[key]; + } + + return sandbox; +}; + +exports.evalInSandbox = function(code, sandbox, jsVersion) { + jsVersion = jsVersion || "1.8"; + Cu.evalInSandbox("(function(){"+code+"})();", sandbox, jsVersion); +};
\ No newline at end of file diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/storage.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/storage.js new file mode 100644 index 0000000..3ed13d0 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/storage.js @@ -0,0 +1,126 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci, Cu, components } = require('chrome'); +const { id } = require('sdk/self'); +const unload = require('sdk/system/unload'); +const { defer } = require('sdk/core/promise'); + +const { Instances } = require('./chrome/instances'); +const { Services } = require('./chrome/services'); +const { NetUtil } = require('./chrome/net-utils'); + +const { FileUtils } = Cu.import('resource://gre/modules/FileUtils.jsm', {}); + +const JETPACK_DIR_BASENAME = "jetpack"; + +let saving = false; + +function getStorageFile() { + const file = Services.dirsvc.get('ProfD', Ci.nsIFile); + file.append(JETPACK_DIR_BASENAME); + file.append(id); + file.append('pathfinder'); + file.append('storage'); + + if (!file.exists()) + file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt('0755', 8)); + + file.append('storage.blob'); + return file; +} + +function get(options) { + options = options || {}; + let charset = options.charset || 'UTF-8'; + + const { promise, resolve } = defer(); + const file = getStorageFile(); + const channel = NetUtil.newChannel(file); + + if (!file.exists()) { + resolve({ data: '' }); + } + else { + NetUtil.asyncFetch(channel, function(iStream, aResult) { + if (!components.isSuccessCode(aResult)) { + reject(); + } + else { + let text = NetUtil.readInputStreamToString(iStream, iStream.available()); + + let conv = Instances.suc; + conv.charset = charset; + + text = conv.ConvertToUnicode(text); + + resolve({ + data: text, + charset: charset + }); + } + }); + } + + return promise; +} +exports.get = get; + +function set({ data, charset }) { + charset = charset || 'UTF-8'; + data = data || ''; + const { promise, resolve, reject } = defer(); + const file = getStorageFile(); + + if (data == '') { + if (file.exists()) { + file.remove(false); + } + + resolve({ + data: '', + charset: charset + }); + } + else { + const converter = Instances.suc; + converter.charset = "UTF-8"; + + if (isSaving()) { + throw Error('Storage is currently in the process of saving..'); + } + saving = true; + + let iStream = converter.convertToInputStream(data); + let oStream = FileUtils.openSafeFileOutputStream(file); + + NetUtil.asyncCopy( + iStream, + oStream, + function(aResult) { + FileUtils.closeSafeFileOutputStream(oStream); + saving = false; + + if (!components.isSuccessCode(aResult)) { + reject(); + } + else { + resolve({ + data: data, + charset: charset + }); + } + } + ); + } + + return promise; +} +exports.set = set; + +function isSaving() { + return saving; +} +exports.isSaving = isSaving; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js new file mode 100644 index 0000000..641dc14 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js @@ -0,0 +1,205 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const {Cc, Ci, Cu, Cm, components} = require('chrome'); +Cu.import("resource://gre/modules/AddonManager.jsm", this); +Cu.import("resource://gre/modules/Services.jsm", this); +Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); + +var {unload} = require("../addon/unload"); +var {listen} = require("../xul/listen"); +var {watchWindows} = require("window-watcher"); +var {clearTimeout, setTimeout} = require("timer"); + +let handlers = []; + +// public api for adding a keyword and search handler +// TODO: validate, yo +exports.AwesomeBarSuggestion = function AwesomeBarSuggestion(options) { + var i = handlers.push(options) - 1; + var destroyed = false; + + return { + destroy: function() { + if (destroyed) return; + destroyed = true; + handlers[i] = null; + } + }; +}; + +// Bool check if a given string matches a given handler +function handlerMatch(query, handler) !!(handler && handler.matches.test(query)); + +// Get first registered handler that matches a given string +function getMatchingHandler(query) handlers.filter(function(handler) handlerMatch(query, handler)).shift() + +// Add functionality to search from the location bar and hook up autocomplete +function addAddressBarSearch(window) { + let {change} = makeWindowHelpers(window); + let {BrowserUI, gBrowser, gURLBar} = window; + + // Check the input to see if the add-on icon should be shown + // Called when the location bar fires the input event + function onLocationBarInput() { + if (skipCheck()) + return; + + let icon = ""; + let handler = getMatchingHandler(urlbar.value); + if (handler && handler.icon) + icon = handler.icon; + setIcon(icon); + } + + // Implement these functions depending on the platform + let setIcon, skipCheck, urlbar; + + // mobile + if (gBrowser == null) { + setIcon = function(url) BrowserUI._updateIcon(url); + skipCheck = function() false; + urlbar = BrowserUI._edit; + + // Check the input on various events + listen(window, BrowserUI._edit, "input", onLocationBarInput); + + // Convert inputs to twitter urls + change(window.Browser, "getShortcutOrURI", function(orig) { + return function(uri, data) { + return orig.call(this, uri, data); + }; + }); + } + // desktop + else { + setIcon = function(url) window.PageProxySetIcon(url); + skipCheck = function() gURLBar.getAttribute("pageproxystate") == "valid" && + !gURLBar.hasAttribute("focused"); + urlbar = gURLBar; + + // Check the input on various events + listen(window, gURLBar, "input", onLocationBarInput); + listen(window, gBrowser.tabContainer, "TabSelect", onLocationBarInput); + + // Convert inputs to twitter urls + change(gURLBar, "_canonizeURL", function(orig) { + return function(event) { + return orig.call(this, event); + }; + }); + } + + // Provide a way to set the autocomplete search engines and initialize + function setSearch(engines) { + urlbar.setAttribute("autocompletesearch", engines); + urlbar.mSearchNames = null; + urlbar.initSearchNames(); + }; + + // Add in the twitter search and remove on cleanup + let origSearch = urlbar.getAttribute("autocompletesearch"); + setSearch(require('self').id + " " + origSearch); + unload(function() setSearch(origSearch)); +} + +// Add an autocomplete search engine to provide location bar suggestions +function addAutocomplete() { + const contract = "@mozilla.org/autocomplete/search;1?name=" + require('self').id; + const desc = "Jetpack Autocomplete"; + const uuid = components.ID("504A8466-8D3D-11E0-A57E-D2F94824019B"); + + // Keep a timer to send a delayed no match + let timer; + function clearTimer() { + if (timer != null) + clearTimeout(timer); + timer = null; + } + + // call back in one second + function setTimer(callback) { + timer = setTimeout(callback, 1000); + } + + // Implement the autocomplete search that handles twitter queries + let search = { + createInstance: function(outer, iid) search.QueryInterface(iid), + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteSearch]), + + // Handle searches from the location bar + startSearch: function(query, param, previous, listener) { + + // Always clear the timer on a new search + clearTimer(); + + function suggest(o, done) { + listener.onSearchResult(search, { + getCommentAt: function() o.title, + getImageAt: function() o.favicon, + getLabelAt: function() o.label || o.url, + getValueAt: function() o.url, + getStyleAt: function() "favicon", + get matchCount() 1, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteResult]), + removeValueAt: function() {}, + searchResult: Ci.nsIAutoCompleteResult.RESULT_SUCCESS, + get searchString() query, + }); + } + + // TODO: if no search yet, but matched keyword, show example text + + // if there's a query string and a match + if (query.length) { + let handler = getMatchingHandler(query); + if (handler) { + if (query) { + handler.onSearch(query, suggest); + } + } + } + // Send a delayed NOMATCH so the autocomplete doesn't close early + else { + setTimer(function() { + listener.onSearchResult(search, { + searchResult: Ci.nsIAutoCompleteResult.RESULT_NOMATCH, + }); + }); + } + }, + + // Nothing to cancel other than a delayed search as results are synchronous + stopSearch: function() { + clearTimer(); + }, + }; + + // Register this autocomplete search service and clean up when necessary + const registrar = Ci.nsIComponentRegistrar; + Cm.QueryInterface(registrar).registerFactory(uuid, desc, contract, search); + unload(function() { + Cm.QueryInterface(registrar).unregisterFactory(uuid, search); + }); +} + +// Add support to the browser +watchWindows(addAddressBarSearch); +addAutocomplete(); + +// Take a window and create various helper properties and functions +function makeWindowHelpers(window) { + // Replace a value with another value or a function of the original value + function change(obj, prop, val) { + let orig = obj[prop]; + obj[prop] = typeof val == "function" ? val(orig) : val; + unload(function() obj[prop] = orig, window); + } + + return { + change: change, + }; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js new file mode 100644 index 0000000..efbc665 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const winUtils = require('sdk/deprecated/window-utils'); +const { Class } = require('sdk/core/heritage'); +const { validateOptions } = require('sdk/deprecated/api-utils'); +const { isBrowser } = require('sdk/window/utils'); +const { unload } = require('../../addon/unload'); +const { listen } = require('../../xul/listen'); + +const findsuggestionNS = require('sdk/core/namespace').ns(); +const NS_XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; + +function FindSuggestionOptions(options) { + return validateOptions(options, { + word: { is: ['string'] }, + //onClick: { is: ['undefined', 'function'] } + }); +} + +const FindSuggestion = Class({ + initialize: function(options) { + options = findsuggestionNS(this).options = FindSuggestionOptions(options); + let unloaders = findsuggestionNS(this).unloaders = []; + + winUtils.WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) return; + + let findBar = window.gFindBar; + let findContainer = findBar.getElement('findbar-container'); + + // Show these suggestions in the findbar + let ele = window.document.createElementNS(NS_XUL, 'label'); + ele.setAttribute('value', options.word); + ele.style.margin = '2px'; + ele.style.cursor = 'pointer'; + ele.style.fontWeight = 'bold'; + findContainer.appendChild(ele); + + ele.addEventListener('click', suggestionClick.bind({ + findBar: findBar + }), false); + + // Clear out the suggestions when removing the add-on + function clearSuggestion() { + findContainer.removeChild(ele); + } + + // save a destroyer + unloaders.push( + destroyer.bind(null, unload(clearSuggestion, window), clearSuggestion)); + } + }); + }, + destroy: function() findsuggestionNS(this).unloaders.forEach(function(x) x()) +}); +exports.FindSuggestion = FindSuggestion; + +function suggestionClick(event) { + let suggestion = event.target.value; + let findField = this.findBar._findField; + + if (findField.value === suggestion) { + this.findBar.onFindAgainCommand(false); + } + else { + findField.value = suggestion; + findBar._find(); + } +} +function destroyer(remover, clearSuggestion) { + clearSuggestion(); + remover(); +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js new file mode 100644 index 0000000..5e34106 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const windowUtils = require("sdk/deprecated/window-utils"); +const { Class } = require("sdk/core/heritage"); +const { validateOptions } = require("sdk/deprecated/api-utils"); +const { on, emit, once, off } = require("sdk/event/core"); +const { isBrowser } = require("sdk/window/utils"); +const { EventTarget } = require('sdk/event/target'); +const menuitemNS = require("sdk/core/namespace").ns(); + +const { unload } = require('../addon/unload'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function MenuitemOptions(options) { + return validateOptions(options, { + id: { is: ['string'] }, + menuid: { is: ['undefined', 'string'] }, + insertbefore: { is: ['undefined', 'string', 'object', 'number'] }, + label: { is: ["string"] }, + include: { is: ['string', 'undefined'] }, + disabled: { is: ["undefined", "boolean"], map: function(v) !!v}, + accesskey: { is: ["undefined", "string"] }, + key: { is: ["undefined", "string"] }, + checked: { is: ['undefined', 'boolean'] }, + className: { is: ["undefined", "string"] }, + onCommand: { is: ['undefined', 'function'] }, + useChrome: { map: function(v) !!v } + }); +} + +let Menuitem = Class({ + extends: EventTarget, + initialize: function(options) { + options = menuitemNS(this).options = MenuitemOptions(options); + EventTarget.prototype.initialize.call(this, options); + + menuitemNS(this).destroyed = false; + menuitemNS(this).unloaders = []; + menuitemNS(this).menuitems = addMenuitems(this, options).menuitems; + }, + get id() menuitemNS(this).options.id, + get label() menuitemNS(this).options.label, + set label(val) updateProperty(this, 'label', val), + get checked() menuitemNS(this).options.checked, + set checked(val) updateProperty(this, 'checked', !!val), + get disabled() menuitemNS(this).options.disabled, + set disabled(val) updateProperty(this, 'disabled', !!val), + get key() menuitemNS(this).options.key, + set key(val) updateProperty(this, 'key', val), + clone: function (overwrites) { + let opts = Object.clone(menuitemNS(this).options); + for (let key in overwrites) { + opts[key] = ovrewrites[key]; + } + return Menuitem(opts); + }, + get menuid() menuitemNS(this).options.menuid, + set menuid(val) { + let options = menuitemNS(this).options; + options.menuid = val; + + forEachMI(function(menuitem, i, $) { + updateMenuitemParent(menuitem, options, $); + }); + }, + destroy: function() { + if (!menuitemNS(this).destroyed) { + menuitemNS(this).destroyed = true; + menuitemNS(this).unloaders.forEach(function(u) u()); + menuitemNS(this).unloaders = null; + menuitemNS(this).menuitems = null; + } + return true; + } +}); + +function addMenuitems(self, options) { + let menuitems = []; + + // setup window tracker + windowUtils.WindowTracker({ + onTrack: function (window) { + if (menuitemNS(self).destroyed) return; + if (options.include) { + if (options.include != window.location) return; + } + else if (!isBrowser(window)) { + return; + } + + // add the new menuitem to a menu + var menuitem = updateMenuitemAttributes( + window.document.createElementNS(NS_XUL, "menuitem"), options); + var menuitems_i = menuitems.push(menuitem) - 1; + + // add the menutiem to the ui + let added = updateMenuitemParent(menuitem, options, function(id) window.document.getElementById(id)); + + menuitem.addEventListener("command", function() { + if (!self.disabled) + emit(self, 'command', options.useChrome ? window : null); + }, true); + + // add unloader + let unloader = function unloader() { + menuitem.parentNode && menuitem.parentNode.removeChild(menuitem); + menuitems[menuitems_i] = null; + }; + + menuitemNS(self).unloaders.push(function() { + remover(); + unloader(); + }); + + let remover = unload(unloader, window); + } + + }); + + return { menuitems: menuitems }; +} + +function updateMenuitemParent(menuitem, options, $) { + // add the menutiem to the ui + if (Array.isArray(options.menuid)) { + let ids = options.menuid; + for (var len = ids.length, i = 0; i < len; i++) { + if (tryParent($(ids[i]), menuitem, options.insertbefore)) + return true; + } + } + else { + return tryParent($(options.menuid), menuitem, options.insertbefore); + } + + return false; +} + +function updateMenuitemAttributes(menuitem, options) { + menuitem.setAttribute("id", options.id); + menuitem.setAttribute("label", options.label); + + if (options.accesskey) + menuitem.setAttribute("accesskey", options.accesskey); + + if (options.key) + menuitem.setAttribute("key", options.key); + + menuitem.setAttribute("disabled", !!options.disabled); + + if (options.image) { + menuitem.classList.add("menuitem-iconic"); + menuitem.style.listStyleImage = "url('" + options.image + "')"; + } + + if (options.checked) + menuitem.setAttribute('checked', options.checked); + + if (options.className) + options.className.split(/\s+/).forEach(function(name) menuitem.classList.add(name)); + + return menuitem; +} + +function updateProperty(menuitem, key, val) { + menuitemNS(menuitem).options[key] = val; + + forEachMI(function(menuitem) { + menuitem.setAttribute(key, val); + }, menuitem); + return val; +} + +function forEachMI(callback, menuitem) { + menuitemNS(menuitem).menuitems.forEach(function(mi, i) { + if (!mi) return; + callback(mi, i, function(id) mi.ownerDocument.getElementById(id)); + }); +} + +function tryParent(parent, menuitem, before) { + if (parent) { + if (!before) { + parent.appendChild(menuitem); + return true; + } + + parent.insertBefore(menuitem, insertBefore(parent, before)); + return true; + } + + return false; +} + +function insertBefore(parent, insertBefore) { + if (typeof insertBefore == "number") { + switch (insertBefore) { + case MenuitemExport.FIRST_CHILD: + return parent.firstChild; + } + return null; + } + else if (typeof insertBefore == "string") { + return parent.querySelector("#" + insertBefore); + } + return insertBefore; +} + +function MenuitemExport(options) { + return Menuitem(options); +} +MenuitemExport.FIRST_CHILD = 1; + +exports.Menuitem = MenuitemExport; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js new file mode 100644 index 0000000..12076ca --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const method = require('method/core'); + +exports.show = method('show'); +exports.hide = method('hide'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js new file mode 100644 index 0000000..244e60e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { contract } = require('sdk/util/contract'); +const { isValidURI } = require('sdk/url'); + +let string = { is: ['string'] }; + +exports.contract = contract({ + id: { + is: [ 'string' ], + ok: function (v) /^[a-z0-9-_]+$/i.test(v), + msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' + + 'underscores are allowed).' + }, + title: { + is: [ 'string' ], + ok: function (v) v.length + }, + url: { + is: [ 'string' ], + ok: function(url) { + return isValidURI(url); + }, + map: function(v) v.toString(), + msg: 'The option "url" must be a valid URI.' + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js new file mode 100644 index 0000000..05225da --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const method = require('method/core'); + +exports.isShowing = method('isShowing'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js new file mode 100644 index 0000000..4576c5b --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); + +const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function create(window, details) { + let { document } = window; + + let menuitem = document.createElementNS(XUL_NS, 'menuitem'); + menuitem.setAttribute('id', details.id); + menuitem.setAttribute('label', details.title); + menuitem.setAttribute('checked', 'false'); + menuitem.setAttribute('sidebarurl', details.sidebarurl); + menuitem.setAttribute('type', 'checkbox'); + menuitem.setAttribute('group', 'sidebar'); + menuitem.setAttribute('autoCheck', 'false'); + + document.getElementById('viewSidebarMenu').appendChild(menuitem); + + return menuitem; +} +exports.create = create; + +function dispose(menuitem) { + menuitem.parentNode.removeChild(menuitem); +} +exports.dispose = dispose; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js new file mode 100644 index 0000000..38bfb2e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js @@ -0,0 +1,179 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const winUtils = require("sdk/deprecated/window-utils"); +const { isBrowser } = require('sdk/window/utils'); +const { Class } = require('sdk/core/heritage'); +const TBB_NS = require('sdk/core/namespace').ns(); + +const { validate: validateOptions } = require('./validate'); +const { getToolbarButtons, toolbarbuttonExists } = require('./utils'); +const { unload } = require("../addon/unload"); +const { listen } = require("../xul/listen"); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +exports.ToolbarButton = Class({ + initialize: function(options) { + TBB_NS(this).unloaders = []; + + const self = this; + TBB_NS(this).destroyed = false; + TBB_NS(this).destroyFuncs = []; + let safeOptions = TBB_NS(this).options = validateOptions(options); + + winUtils.WindowTracker({ + onTrack: function (window) { + if (!isBrowser(window) || TBB_NS(self).destroyed) + return; + + let doc = window.document; + let $ = function(id) doc.getElementById(id); + + // create toolbar button + let tbb = doc.createElementNS(NS_XUL, "toolbarbutton"); + tbb.setAttribute("id", safeOptions.id); + tbb.setAttribute("type", "button"); + if (safeOptions.image) + tbb.setAttribute("image", safeOptions.image); + tbb.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional"); + tbb.setAttribute("label", safeOptions.label); + tbb.setAttribute('tooltiptext', safeOptions.tooltiptext); + tbb.addEventListener("command", function() { + if (safeOptions.onCommand) + safeOptions.onCommand({}); // TODO: provide something? + + if (safeOptions.panel) { + safeOptions.panel.show(tbb); + } + }, true); + + // add toolbarbutton to palette + ($("navigator-toolbox") || $("mail-toolbox")).palette.appendChild(tbb); + + // find a toolbar to insert the toolbarbutton into + if (TBB_NS(self).options.toolbarID) { + var tb = $(TBB_NS(self).options.toolbarID); + } + if (!tb) { + var tb = toolbarbuttonExists(doc, safeOptions.id); + } + + // found a toolbar to use? + if (tb) { + let b4; + + // find the toolbarbutton to insert before + if (TBB_NS(self).options.insertbefore) { + b4 = $(TBB_NS(self).options.insertbefore); + } + if (!b4) { + let currentset = tb.getAttribute("currentset").split(","); + let i = currentset.indexOf(safeOptions.id) + 1; + + // was the toolbarbutton id found in the curent set? + if (i > 0) { + let len = currentset.length; + // find a toolbarbutton to the right which actually exists + for (; i < len; i++) { + b4 = $(currentset[i]); + if (b4) break; + } + } + } + + tb.insertItem(safeOptions.id, b4, null, false); + } + + var saveTBNodeInfo = function(e) { + TBB_NS(self).options.toolbarID = tbb.parentNode.getAttribute("id") || ""; + TBB_NS(self).options.insertbefore = (tbb.nextSibling || "") + && tbb.nextSibling.getAttribute("id").replace(/^wrapper-/i, ""); + }; + + window.addEventListener("aftercustomization", saveTBNodeInfo, false); + + // add unloader to unload+'s queue + var unloadFunc = function() { + tbb.parentNode.removeChild(tbb); + window.removeEventListener("aftercustomization", saveTBNodeInfo, false); + }; + var index = TBB_NS(self).destroyFuncs.push(unloadFunc) - 1; + listen(window, window, "unload", function() { + TBB_NS(self).destroyFuncs[index] = null; + }, false); + TBB_NS(self).unloaders.push(unload(unloadFunc, window)); + } + }); + }, + destroy: function() { + if (TBB_NS(this).destroyed) return; + TBB_NS(this).destroyed = true; + + let options = TBB_NS(this).options; + + if (options.panel) + options.panel.destroy(); + + // run unload functions + TBB_NS(this).destroyFuncs.forEach(function(f) f && f()); + TBB_NS(this).destroyFuncs.length = 0; + + // remove unload functions from unload+'s queue + TBB_NS(this).unloaders.forEach(function(f) f()); + TBB_NS(this).unloaders.length = 0; + }, + moveTo: function(pos) { + if (TBB_NS(this).destroyed) return; + + let options = TBB_NS(this).options; + + // record the new position for future windows + TBB_NS(this).options.toolbarID = pos.toolbarID; + TBB_NS(this).options.insertbefore = pos.insertbefore; + + // change the current position for open windows + for each (var window in winUtils.windowIterator()) { + if (!isBrowser(window)) continue; + + let $ = function (id) window.document.getElementById(id); + + // if the move isn't being forced and it is already in the window, abort + if (!pos.forceMove && $(this.id)) continue; + + var tb = $(TBB_NS(this).options.toolbarID); + var b4 = $(TBB_NS(this).options.insertbefore); + + // TODO: if b4 dne, but insertbefore is in currentset, then find toolbar to right + + if (tb) tb.insertItem(this.id, b4, null, false); + }; + }, + get id() TBB_NS(this).options.id, + get label() TBB_NS(this).options.label, + set label(value) { + TBB_NS(this).options.label = value; + getToolbarButtons(function(tbb) { + tbb.label = value; + }, this.id); + return value; + }, + setIcon: function setIcon(options) { + let val = TBB_NS(this).options.image = options.image || options.url; + getToolbarButtons(function(tbb) { + tbb.image = val; + }, this.id); + return val; + }, + get image() TBB_NS(this).options.image, + set image(value) this.setIcon({image: value}), + get tooltiptext() TBB_NS(this).options.tooltiptext, + set tooltiptext(value) { + TBB_NS(this).options.tooltiptext = value; + getToolbarButtons(function(tbb) { + tbb.setAttribute('tooltiptext', value); + }, this.id); + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js new file mode 100644 index 0000000..6ad0304 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js @@ -0,0 +1,28 @@ +'use strict'; + +const winUtils = require("sdk/deprecated/window-utils"); +const { isBrowser } = require('sdk/window/utils'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function getToolbarButtons(callback, id) { + let buttons = []; + for each (var window in winUtils.windowIterator()) { + if (!isBrowser(window)) continue; + let tbb = window.document.getElementById(id); + if (tbb) buttons.push(tbb); + } + if (callback) buttons.forEach(callback); + return buttons; +} +exports.getToolbarButtons = getToolbarButtons; + +function toolbarbuttonExists(doc, id) { + var toolbars = doc.getElementsByTagNameNS(NS_XUL, "toolbar"); + for (var i = toolbars.length - 1; ~i; i--) { + if ((new RegExp("(?:^|,)" + id + "(?:,|$)")).test(toolbars[i].getAttribute("currentset"))) + return toolbars[i]; + } + return false; +} +exports.toolbarbuttonExists = toolbarbuttonExists; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js new file mode 100644 index 0000000..3de6d30 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js @@ -0,0 +1,31 @@ +'use strict'; + +const { validateOptions } = require('sdk/deprecated/api-utils'); +const { Panel } = require('sdk/panel'); + + const RULES = { + image: { is: ["null", "undefined", "string"] }, + tooltiptext: { + is: ["null", "undefined", "string"], + defaultValue: '' + }, + id: { + is: ["string"], + ok: function (v) v.length > 0, + msg: 'BAD ID', + readonly: true + }, + label: { + is: ["string"], + ok: function (v) v.length > 0, + msg: 'BAD Label' + }, + panel: { + is: ["null", "undefined", "object"], + ok: function(v) !v || v instanceof Panel + }, + onCommand: { + is: ["null", "undefined", "function"], + } +}; +exports.validate = function(o) validateOptions(o, RULES); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js new file mode 100644 index 0000000..bf2b449 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const self = require('sdk/self'); +const tabs = require('sdk/tabs'); +const { Class } = require('sdk/core/heritage'); +const { on, emit, once, off } = require('sdk/event/core'); +const { EventTarget } = require('sdk/event/target'); + +const awNS = require('sdk/core/namespace').ns(); + +let AddonWarning = Class({ + extends: EventTarget, + initialize: function initialize(options) { + EventTarget.prototype.initialize.call(this, options); + awNS(this).options = options; + }, + open: function() { + let self = this; + let options = awNS(self).options; + + tabs.open({ + url: module.uri.replace(/lib\/addon-warning\.js/, 'data/warning.html'), + onReady: function(tab) { + let worker = tab.attach({ + contentScriptFile: module.uri.replace(/lib\/addon-warning\.js/, 'data/warning-mod.js') + }); + + worker.port.on('cancel', function(data) { + emit(self, 'cancel'); + }); + worker.port.on('accept', function(data) { + emit(self, 'accept'); + }); + + worker.port.emit('load', options); + } + }); + } +}); +exports.AddonWarning = AddonWarning; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js new file mode 100644 index 0000000..f61c958 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js @@ -0,0 +1,289 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +module.metadata = { + 'stability': 'experimental', + 'engines': { + 'Firefox': '*' + } +}; + +const { Class } = require('sdk/core/heritage'); +const { merge } = require('sdk/util/object'); +const { Disposable } = require('sdk/core/disposable'); +const { off, emit, setListeners } = require('sdk/event/core'); +const { EventTarget } = require('sdk/event/target'); +const { URL } = require('sdk/url'); +const { add, remove, has, clear, iterator } = require('sdk/lang/weak-set'); +const { WindowTracker } = require('sdk/deprecated/window-utils'); +const { isBrowser, getMostRecentBrowserWindow, windows } = require('sdk/window/utils'); +const { ns } = require('sdk/core/namespace'); +const { remove: removeFromArray } = require('sdk/util/array'); +const { Worker: WorkerTrait } = require('sdk/content/worker'); + +const { create, dispose } = require('./sidebar/utils'); +const { show, hide } = require('./sidebar/actions'); +const { isShowing } = require('./sidebar/state'); +const { contract } = require('./sidebar/contract'); + +const Worker = WorkerTrait.resolve({ + _injectInDocument: '__injectInDocument' +}).compose({ + get _injectInDocument() false +}); + +const sidebarNS = ns(); + +const WEB_PANEL_BROWSER_ID = 'web-panels-browser'; + +let sidebars = {}; +let models = new WeakMap(); +let views = new WeakMap(); + +function viewsFor(sidebar) views.get(sidebar); +function modelFor(sidebar) models.get(sidebar); + +const WebPanel = Class({ + implements: [ Disposable ], + extends: EventTarget, + setup: function(options) { + let self = this; + + const windowNS = ns(); + + let model = merge({}, contract(options)); + + models.set(this, model); + + setListeners(this, options); + + let bars = []; + sidebarNS(self).tracker = WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) + return; + + let sidebar = window.document.getElementById('sidebar'); + let sidebarBox = window.document.getElementById('sidebar-box'); + + let bar = create(window, { + id: makeID(model.id), + title: model.title, + sidebarurl: model.url + }); + bars.push(bar); + windowNS(window).bar = bar; + + bar.addEventListener('command', function() { + if (isSidebarShowing(window, self)) { + hideSidebar(window, self); + return; + } + + showSidebar(window, self); + }, false); + + function onSidebarLoad() { + // check if the sidebar is ready + let isReady = sidebar.docShell && sidebar.contentDocument; + if (!isReady) + return; + + // check if it is a web panel + let panelBrowser = sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + if (!panelBrowser) { + bar.removeAttribute('checked'); + return; + } + + let sbTitle = window.document.getElementById('sidebar-title'); + function onWebPanelSidebarLoad() { + if (panelBrowser.contentWindow.location != model.url || + sbTitle.value != model.title) { + return; + } + + let worker = windowNS(window).worker = Worker({ + window: panelBrowser.contentWindow + }); + + function onWebPanelSidebarUnload() { + panelBrowser.removeEventListener('unload', onWebPanelSidebarUnload, true); + + windowNS(window).onWebPanelSidebarLoad = null; + + // uncheck the associated menuitem + bar.setAttribute('checked', 'false'); + + emit(self, 'hide', null); + emit(self, 'detach', worker); + } + windowNS(window).onWebPanelSidebarUnload = onWebPanelSidebarUnload; + panelBrowser.contentWindow.addEventListener('unload', onWebPanelSidebarUnload, false); + + // check the associated menuitem + bar.setAttribute('checked', 'true'); + + emit(self, 'show', null); + emit(self, 'attach', worker); + } + windowNS(window).onWebPanelSidebarLoad = onWebPanelSidebarLoad; + panelBrowser.addEventListener('DOMWindowCreated', onWebPanelSidebarLoad, true); + } + windowNS(window).onSidebarLoad = onSidebarLoad; + sidebar.addEventListener('load', onSidebarLoad, true); + }, + onUntrack: function(window) { + if (!isBrowser(window)) + return; + + let { bar } = windowNS(window); + if (bar) { + removeFromArray(viewsFor(self), bar); + dispose(bar); + } + + let sidebar = window.document.getElementById('sidebar'); + if (!sidebar) + return; + + if (windowNS(window).onSidebarLoad) { + sidebar.removeEventListener('load', windowNS(window).onSidebarLoad, true) + windowNS(window).onSidebarLoad = null; + } + + if (windowNS(window).onWebPanelSidebarLoad) { + let webPanel = sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + webPanel && webPanel.removeEventListener('DOMWindowCreated', windowNS(window).onWebPanelSidebarLoad, true); + windowNS(window).onWebPanelSidebarLoad = null; + } + + if (windowNS(window).onWebPanelSidebarUnload) { + windowNS(window).onWebPanelSidebarUnload(); + } + } + }); + + views.set(this, bars); + + add(sidebars, this); + }, + get id() modelFor(this).id, + get title() modelFor(this).title, + get url() modelFor(this).url, + show: function() show(this), + hide: function() hide(this), + dispose: function() { + off(this); + + let wins = windows('navigator:browser', { includePrivate: true }); + for each (let win in wins) { + hideSidebar(win, this); + } + + remove(sidebars, this); + + // stop tracking windows + sidebarNS(this).tracker.unload(); + sidebarNS(this).tracker = null; + + views.delete(this); + } +}); +exports.WebPanel = WebPanel; + +function showSidebar(window, sidebar) { + let model = modelFor(sidebar); + //let window = window || getMostRecentBrowserWindow(); + + window.openWebPanel(model.title, model.url); + + let menuitem = window.document.getElementById(makeID(model.id)); + menuitem.setAttribute('checked', true); +} +show.define(WebPanel, showSidebar.bind(null, null)); + +function hideSidebar(window, sidebar) { + //window = window || getMostRecentBrowserWindow(); + + if (!isSidebarShowing(window, sidebar)) + return; + + // return window.toggleSidebar(); + + // Below was taken from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#4775 + // the code for window.todggleSideBar().. + let { document } = window; + //let sidebar = document.getElementById('sidebar'); + let sidebarTitle = document.getElementById('sidebar-title'); + let sidebarBox = document.getElementById('sidebar-box'); + let sidebarSplitter = document.getElementById('sidebar-splitter'); + let commandID = sidebarBox.getAttribute('sidebarcommand'); + let sidebarBroadcaster = document.getElementById(commandID); + + sidebarBox.hidden = true; + sidebarSplitter.hidden = true; + + sidebar.setAttribute('src', 'about:blank'); + //sidebar.docShell.createAboutBlankContentViewer(null); + + sidebarBroadcaster.removeAttribute('checked'); + sidebarBox.setAttribute('sidebarcommand', ''); + sidebarTitle.value = ''; + sidebarBox.hidden = true; + sidebarSplitter.hidden = true; + + // TODO: perhaps this isn't necessary if the window is not most recent? + window.gBrowser.selectedBrowser.focus(); +} +hide.define(WebPanel, hideSidebar.bind(null, null)); + +function isSidebarShowing(window, sidebar) { + let win = window || getMostRecentBrowserWindow(); + + // make sure there is a window + if (!win) { + return false; + } + + // make sure there is a sidebar for the window + let sb = win.document.getElementById('sidebar'); + let sidebarTitle = win.document.getElementById('sidebar-title'); + if (!(sb && sidebarTitle)) { + return false; + } + + // checks if the sidebar box is hidden + let sbb = win.document.getElementById('sidebar-box'); + if (!sbb || sbb.hidden) { + return false; + } + + // checks if the sidebar is loading + if (win.gWebPanelURI == modelFor(sidebar).url) { + return false; + } + + if (sidebarTitle.value == modelFor(sidebar).title) { + // checks if the sidebar loaded already + let ele = sb.contentDocument && sb.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + + if (ele.getAttribute('cachedurl') == modelFor(sidebar).url) { + return true; + } + + if (ele && ele.contentWindow && ele.contentWindow.location == modelFor(sidebar).url) { + return true; + } + } + + // default + return false; +} +isShowing.define(WebPanel, isSidebarShowing.bind(null, null)); + +function makeID(id) { + return 'pathfinder-sidebar-' + id; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userscript.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userscript.js new file mode 100644 index 0000000..9890200 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userscript.js @@ -0,0 +1,116 @@ +'use strict'; + +var file = require("sdk/io/file"); +var url = require("sdk/url"); + +var convert2RegExp = require("./scriptish/convert-2-regexp").convert2RegExp; +var userscriptParser = require("./scriptish/userscript-header-parser").parse; +var manager = require("./scriptish/userscript-manager"); + +const JSVersions = ['1.6', '1.7', '1.8'/*, '1.8.1'*/]; + +var UserScript = exports.UserScript = function UserScript(aURL) { + var script = new Script(aURL); + manager.register(script); + + return { + destory: function() { + manager.unregister(script); + }, + get enabled() script.enabled, + set enabled(aVal) script.enabled = !!aVal + }; +} + +function Script(aURL) { + this._url = url.URL(aURL); + this._filepath = url.toFilename(aURL); + this._source = file.read(this._filepath); + var header = userscriptParser(this._source); + + this._name = (header.name && header.name[0]) || Script.parseScriptName(aURL); + this._namespace = (header.namespace && header.namespace[0]) || this.url.host; + this._description = (header.description && header.description[0]) || ""; + this.enabled = true; + this._includes = (header.include || []).map(convert2RegExp); + this._excludes = (header.exclude || []).map(convert2RegExp); + this._requires = (header.require || []); + this._resources = (header.resource || []); + if (header.jsversion) { + for (var i = header.jsversion.length - 1; ~i; i--) { + let val = header.jsversion[i]; + if (~JSVersions.indexOf(val)) { + this.jsversion = val; + break; + } + } + } +} + +Script.prototype = { + get prefPrefix () { + return ["greasemonkey.scriptvals.", + this._namespace, + "/", + this._name, + "."].join(""); + }, + + // TODO: actually implement this! + matchesDomain: function() { + return true; + }, + + matchesURL: function(url) { + var test = function(pattern) { + return pattern.test(url); + } + + return this.enabled + && this._includes.some(test) + && !this._excludes.some(test); + }, + + _changed: function(event, data) { + if(this._config) { + this._config._changed(this, event, data); + } + }, + + get name() { return this._name; }, + get namespace() { return this._namespace; }, + get description() { return this._description; }, + + get enabled() { return this._enabled; }, + set enabled(enabled) { + this._enabled = enabled; + this._changed("edit-enabled", enabled); + }, + + get includes() { return this._includes.concat(); }, + get excludes() { return this._excludes.concat(); }, + addInclude: function(url) { + this._includes.push(url); + this._changed("edit-include-add", url); + }, + removeIncludeAt: function(index) { + this._includes.splice(index, 1); + this._changed("edit-include-remove", index); + }, + addExclude: function(url) { + this._excludes.push(url); + this._changed("edit-exclude-add", url); + }, + removeExcludeAt: function(index) { + this._excludes.splice(index, 1); + this._changed("edit-exclude-remove", index); + }, + + get requires() { return this._requires.concat(); }, + get resources() { return this._resources.concat(); }, + get unwrap() { return this._unwrap; } +}; + + +Script.parseScriptName = function(aURL) (( + /\/([^\/]+)\.user(?:-\d+)?\.js(?:[\?#].*)?$/.test(aURL || "")) ? RegExp.$1 : ""); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userstyles.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userstyles.js new file mode 100644 index 0000000..0cc3414 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/userstyles.js @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci } = require("chrome"); +const { unload } = require('./addon/unload'); + +const sss = Cc["@mozilla.org/content/style-sheet-service;1"] + .getService(Ci.nsIStyleSheetService); + +function getURI(aURL) Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService).newURI(aURL, null, null); + +function setOptions(url, options) { + let newOptions = {}; + options = options || {}; + + newOptions.uri = getURI(url); + newOptions.type = (options.type || 'user').toLowerCase(); + newOptions.type = (newOptions.type == 'agent') ? sss.AGENT_SHEET : sss.USER_SHEET; + + return newOptions; +}; + +// capture the unload callbacks for removing the unload function from +// the queue as they are no longer needed when a URL is unregistered manually +var unloaders = {}; + +function removeUnload(url) { + if (typeof unloaders[url] === "function") { + unloaders[url].call(null); + delete unloaders[url]; + } +} + +/** + * Load various packaged styles for the add-on and undo on unload + * + * @usage load(aURL): Load specified style + * @param [string] aURL: Style file to load + * @param [object] options: + */ +const loadSS = exports.load = function loadSS(url, options) { + let { uri, type } = setOptions(url, options); + + // load the stylesheet + sss.loadAndRegisterSheet(uri, type); + + // remove the unloader for this URL if it exists + removeUnload(url); + + // unload the stylesheet on unload + unloaders[url] = unload(unregisterSS.bind(null, url, options)); +}; + +const registeredSS = exports.registered = function registeredSS(url, options) { + let { uri, type } = setOptions(url, options); + + // check that the stylesheet is registered + return !!sss.sheetRegistered(uri, type); +}; + +const unregisterSS = exports.unload = function unregisterSS(url, options) { + let { uri, type } = setOptions(url, options); + + // remove the unloader our load function setup if it exists + removeUnload(url); + + // unregister the stylesheet + sss.unregisterSheet(uri, type); +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/utils/addonmanager.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/utils/addonmanager.js new file mode 100644 index 0000000..3e301a2 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/utils/addonmanager.js @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const {Cc, Ci, Cu} = require("chrome"); + +Cu.import("resource://gre/modules/AddonManager.jsm", this); + +exports.AddonManager = AddonManager; +exports.AddonManagerPrivate = AddonManagerPrivate; + +exports.AddonType = AddonManagerPrivate.AddonType; +exports.AddonAuthor = + AddonManagerPrivate.AddonAuthor || function AddonAuthor(name, url) { + this.name = name; + this.url = url; + this.toString = function() this.name +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/browser.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/browser.js new file mode 100644 index 0000000..5b1ed47 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/browser.js @@ -0,0 +1,180 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { WindowTracker } = require("sdk/deprecated/window-utils"); +const { isBrowser, windows } = require('sdk/window/utils'); +const { validateOptions } = require("sdk/deprecated/api-utils"); +const { Class } = require("sdk/core/heritage"); +const { ns } = require("sdk/core/namespace"); +const { ensure } = require('sdk/system/unload'); + +const { xulNS } = require('./namespace'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; +const VALID_POSITIONS = ['top']; + +// Converts anything that isn't false, null or undefined into a string +function stringOrNull(val) val ? String(val) : val; + +const XUL_SKELETON = Class({ + setup: function setup(attributes) { + const internals = xulNS(this); + internals.attributes = attributes; + ensure(this, 'destroy'); + }, + appendChild: function appendChild(node) { + const ID = this.getAttribute('id'); + + // keep note to update parent in future windows + xulNS(node).parentID = ID; + xulNS(node).insertBeforeID = null; + + // update parent on current windows + windows().forEach(function(window) { + let parent = window.document.getElementById(ID); + let { element } = xulNS(node).windowsNS(window); + parent.appendChild(element); + }); + }, + insertBefore: function(node, beforeNode) { + const ID = this.getAttribute('id'); + const B4_ID = (typeof beforeNode == 'string') ? beforeNode : beforeNode.getAttribute('id'); + + // keep note to update parent in future windows + xulNS(node).parentID = ID; + xulNS(node).insertBeforeID = B4_ID; + + // update parent on current windows + windows().forEach(function(window) { + let parent = window.document.getElementById(ID); + let before = window.document.getElementById(B4_ID); + let { element } = xulNS(node).windowsNS(window); + + parent.insertBefore(element, before); + }); + }, + addEventListener: function addEventListener(type, listener, useCapture) { + internals.eles.forEach(function(ele) { + ele.addEventListener(type, listener, useCapture); + }); + }, + removeEventListener: function removeEventListener(type, listener, useCapture) { + internals.eles.forEach(function(ele) { + ele.removeEventListener(type, listener, useCapture); + }); + }, + getAttribute: function getAttribute(attr) { + return xulNS(this).attributes[attr]; + }, + setAttribute: function setAttribute(attr, value) { + const internals = xulNS(this); + internals.eles.forEach(function(ele) { + ele.setAttribute(attr, value); + }); + internals.attributes[attr] = value; + }, + destroy: function() { + const internals = xulNS(this); + internals.attributes = null; + } +}); + +const XUL = Class({ + implements: [ XUL_SKELETON ], + initialize: function(nodeName, attributes) { + const self = this; + const internals = xulNS(this); + internals.windowsNS = ns(); + internals.eles = []; + internals.attributes = attributes; + + XUL_SKELETON.prototype.setup.call(this, attributes); + + // Set Window Tracker + internals.windowtracker = WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) return; + let ele = window.document.createElementNS(NS_XUL, nodeName); + + Object.keys(attributes).forEach(function(key) { + ele.setAttribute(key, attributes[key]); + }) + + internals.eles.push(ele); + internals.windowsNS(window).element = ele; + + // update parent? + if (internals.parentID) { + let parent = window.document.getElementById(internals.parentID); + if (internals.insertBeforeID) { + let before = window.document.getElementById(internals.insertBeforeID); + parent.insertBefore(ele, before); + } + else { + parent.appendChild(ele); + } + } + }, + onUntrack: function(window) { + if (!isBrowser(window)) return; + let { element } = internals.windowsNS(window); + element.parentNode.removeChild(element); + internals.windowsNS(window).element = null; + } + }); + }, + destroy: function() { + XUL_SKELETON.prototype.destroy.call(this); + const internals = xulNS(this); + internals.windowtracker.unload(); + internals.windowtracker = null; + internals.windowsNS = null; + } +}); +exports.XUL = XUL; + +const XUL_GETTER = Class({ + implements: [ XUL_SKELETON ], + initialize: function(attributes) { + const self = this; + const internals = xulNS(this); + internals.windowsNS = ns(); + internals.eles = []; + internals.attributes = attributes; + + XUL_SKELETON.prototype.setup.call(this, attributes); + + // Set Window Tracker + internals.windowtracker = WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) return; + let ele = window.document.getElementById(attributes.id); + internals.eles.push(ele); + internals.windowsNS(window).element = ele; + + // update parent? + if (internals.parentID) { + let parent = window.document.getElementById(internals.parentID); + parent.appendChild(ele); + } + } + }); + }, + destroy: function() { + const internals = xulNS(this); + + XUL_SKELETON.prototype.destroy.call(this); + + internals.windowtracker.unload(); + internals.windowtracker = null; + internals.windowsNS = null; + } +}); +exports.XUL_GETTER = XUL_GETTER; + +function getXULById(id) { + return XUL_GETTER({ id: id }); +} +exports.getXULById = getXULById; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/key.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/key.js new file mode 100644 index 0000000..c855fc3 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/key.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +exports.XulKey = function XulKey(options) { + var delegate = { + onTrack: function (window) { + if ("chrome://browser/content/browser.xul" != window.location) return; + + let doc = window.document; + function $(id) doc.getElementById(id); + function xul(type) doc.createElementNS(NS_XUL, type); + + var onCmd = function() { + options.onCommand && options.onCommand(); + }; + + var keyset = xul("keyset"); + + // add hotkey + var key = xul("key"); + key.setAttribute("id", options.id); + key.setAttribute("key", options.key); + if (options.modifiers) + key.setAttribute("modifiers", options.modifiers); + key.setAttribute("oncommand", "void(0);"); + key.addEventListener("command", onCmd, true); + ($("mainKeyset") || $("mailKeys")).parentNode.appendChild(keyset).appendChild(key); + + // add unloader + require("unload+").unload(function() { + key.removeEventListener("command", onCmd, true); // must do for some reason.. + keyset.parentNode.removeChild(keyset); + }, window); + }, + onUntrack: function (window) {} + }; + var winUtils = require("window-utils"); + var tracker = new winUtils.WindowTracker(delegate); +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/listen.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/listen.js new file mode 100644 index 0000000..5536e30 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/listen.js @@ -0,0 +1,29 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { unload } = require('../addon/unload'); + +/** + * Helper that adds event listeners and remembers to remove on unload + */ +function listen(window, node, event, func, capture) { + // Default to use capture + if (capture == null) + capture = true; + + node.addEventListener(event, func, capture); + function undoListen() { + node.removeEventListener(event, func, capture); + } + + // Undo the listener on unload and provide a way to undo everything + let undoUnload = unload(undoListen, window); + return function() { + undoListen(); + undoUnload(); + }; +} +exports.listen = listen; + diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/namespace.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/namespace.js new file mode 100644 index 0000000..1a67716 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/xul/namespace.js @@ -0,0 +1,3 @@ +'use strict'; +const { ns } = require('sdk/core/namespace'); +exports.xulNS = ns(); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/zip/utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/zip/utils.js new file mode 100644 index 0000000..fa5796c --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/zip/utils.js @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Cc, Ci, Cu } = require("chrome"); + +exports.getZipReader = function(aFile) { + var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"] + .createInstance(Ci.nsIZipReader); + zipReader.open(aFile); + return zipReader; +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/package.json b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/package.json new file mode 100644 index 0000000..3f0d03a --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/package.json @@ -0,0 +1,60 @@ +{ + "_args": [ + [ + "pathfinder@git+https://github.com/OverByThere/addon-pathfinder.git", + "/home/nik/src/librejs/node_modules/menuitem" + ] + ], + "_from": "git+https://github.com/OverByThere/addon-pathfinder.git", + "_id": "pathfinder@1.0.1", + "_inCache": true, + "_location": "/pathfinder", + "_phantomChildren": {}, + "_requested": { + "hosted": { + "directUrl": "https://raw.githubusercontent.com/OverByThere/addon-pathfinder/master/package.json", + "gitUrl": "git://github.com/OverByThere/addon-pathfinder.git", + "httpsUrl": "git+https://github.com/OverByThere/addon-pathfinder.git", + "shortcut": "github:OverByThere/addon-pathfinder", + "ssh": "git@github.com:OverByThere/addon-pathfinder.git", + "sshUrl": "git+ssh://git@github.com/OverByThere/addon-pathfinder.git", + "type": "github" + }, + "name": "pathfinder", + "raw": "pathfinder@git+https://github.com/OverByThere/addon-pathfinder.git", + "rawSpec": "git+https://github.com/OverByThere/addon-pathfinder.git", + "scope": null, + "spec": "git+https://github.com/OverByThere/addon-pathfinder.git", + "type": "hosted" + }, + "_requiredBy": [ + "/menuitem" + ], + "_resolved": "git+https://github.com/OverByThere/addon-pathfinder.git#bad1110fc9427bafd6d7fc1a1d4594cf8086ab94", + "_shasum": "e8e99972c3ac7a562fb84e8331b9df88ca2a9098", + "_shrinkwrap": null, + "_spec": "pathfinder@git+https://github.com/OverByThere/addon-pathfinder.git", + "_where": "/home/nik/src/librejs/node_modules/menuitem", + "author": { + "name": "Erik Vold" + }, + "bugs": { + "url": "https://github.com/OverByThere/menuitem/issues" + }, + "dependencies": {}, + "description": "The Add-on Pathfinder is the collection of Jetpack modules made to be used with the [Add-on SDK](https://github.com/mozilla/addon-sdk).", + "devDependencies": {}, + "gitHead": "bad1110fc9427bafd6d7fc1a1d4594cf8086ab94", + "homepage": "https://github.com/OverByThere/menuitem#readme", + "installable": true, + "license": "MPL 2.0", + "name": "pathfinder", + "optionalDependencies": {}, + "readme": "# Add-on Pathfinder\n\nThe Add-on Pathfinder is the collection of Jetpack modules made to be used with the\n[Add-on SDK](https://github.com/mozilla/addon-sdk).\n\n## Highlights\n\n* Toolbar buttons\n* Menuitems\n* GCLI\n* Downloads\n* About/Resource Schemes\n* UserStyles\n* UserScripts\n* XUL Help\n* ZIP Utilities\n* Content policies\n* Content Permissions\n* Awesomebar\n* Modifying Request Headers\n* Redirects\n* Much much more!...\n", + "readmeFilename": "README.md", + "repository": { + "type": "git", + "url": "git+https://github.com/OverByThere/menuitem.git" + }, + "version": "1.0.1" +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/black.png b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/black.png Binary files differnew file mode 100644 index 0000000..ee11b09 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/black.png diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/index.html b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/index.html new file mode 100644 index 0000000..7e49348 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/index.html @@ -0,0 +1,4 @@ +<html> + <title></title> + <body></body> +</html> diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-folder.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-folder.js new file mode 100644 index 0000000..4b98c42 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-folder.js @@ -0,0 +1,90 @@ +'use strict'; + +const JETPACK_DIR_BASENAME = "jetpack"; + +const FOLDER = require('pathfinder/addon/folder'); + +const { Loader } = require('sdk/test/loader'); +const { Cc, Ci } = require('chrome'); +const file = require('sdk/io/file'); +const jpSelf = require('sdk/self'); + +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('addon-folder'); + +const ADDON_FOLDER_PATH = storeFile.path; + +exports.testFolderCreated = function(assert) { + let loader = Loader(module); + assert.ok(file.exists(ADDON_FOLDER_PATH), ADDON_FOLDER_PATH + ' was created'); + FOLDER.destroy(); + assert.ok(!file.exists(ADDON_FOLDER_PATH), ADDON_FOLDER_PATH + ' was destroyed'); + loader.require('pathfinder/addon/folder'); + assert.ok(file.exists(ADDON_FOLDER_PATH), ADDON_FOLDER_PATH + ' was created'); + loader.unload(); + assert.ok(file.exists(ADDON_FOLDER_PATH), ADDON_FOLDER_PATH + 'exists after unload'); +} + +exports.testFileLifecycle = function(assert, done) { + let filename = 'test.json'; + let fileStream = FOLDER.write(filename); + try { + fileStream.writeAsync('{}', function(err) { + assert.equal(FOLDER.exists(filename), true, 'the file was created'); + + if (err) + assert.fail(err); + else + assert.equal(FOLDER.read(filename), '{}', 'the file was written correctly'); + + let entries = FOLDER.list(); + assert.ok(entries.length > 0, 'there is more than one entry'); + for each (let entry in entries) { + assert.equal(entry, filename, filename + ' is the only entry listed'); + } + + let testFile = Cc['@mozilla.org/file/directory_service;1'] + .getService(Ci.nsIProperties) + .get('ProfD', Ci.nsIFile); + testFile.append(JETPACK_DIR_BASENAME); + testFile.append(jpSelf.id); + testFile.append('addon-folder'); + testFile.append(filename); + + assert.ok(testFile.exists(), 'the test file does exist.') + + FOLDER.remove(filename); + + assert.equal(FOLDER.exists(filename), false, 'the file was removed'); + + done(); + }); + } + catch(e) { + assert.fail(e); + fileStream.close(); + done(); + } +} + +exports.testBackPath = function(assert, done) { + let filename = '../../test.json'; + let fileStream = { close: function(){} }; + try { + fileStream = FOLDER.write(filename); + assert.fail(filename + ' should not be useable'); + } + catch(e) { + assert.pass(e); + } + + fileStream.close(); + done(); +} + + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-warning.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-warning.js new file mode 100644 index 0000000..777c279 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-addon-warning.js @@ -0,0 +1,3 @@ +'use strict'; + +const warning = require('pathfinder/ui/warning'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-connection-request.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-connection-request.js new file mode 100644 index 0000000..fcd278d --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-connection-request.js @@ -0,0 +1,57 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci } = require('chrome'); +const tabs = require('sdk/tabs'); +const { data } = require('sdk/self'); +const { Loader } = require('sdk/test/loader'); +const httpd = require('sdk/test/httpd'); + +const { RequestRule } = require('pathfinder/connections'); + +exports.testNewHeader = function(assert, done) { + let rule = RequestRule({ + headers: { + 'X-TEST-HEADER': 'TEST' + } + }); + + let serverPort = 8058; + let url = 'http://localhost:' + serverPort + '/test.txt'; + let server = httpd.startServerAsync(serverPort); + const contents = "testNewHeader"; + let requestCount = 0; + + server.registerPathHandler("/test.txt", function handle(request, response) { + requestCount++; + + if (requestCount == 1) { + try { + assert.equal(request.getHeader('X-TEST-HEADER'), 'TEST', 'the new test header value is correct'); + } + catch (e) { + assert.fail(e); + } + rule.destroy(); + } + response.write(contents); + }); + + tabs.open({ + url: url, + onReady: function(tab) { + if (requestCount == 1) { + tab.reload(); + } + else { + server.stop(function() { + done(); + }); + } + } + }) +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-permissions.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-permissions.js new file mode 100644 index 0000000..c9a6da2 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-permissions.js @@ -0,0 +1,35 @@ +'use strict'; + +const { permissions } = require('pathfinder/content/permissions'); + +exports.testAddRemovePermission = function(assert) { + permissions.add({ + url: 'http://erikvold.com/', + permission: 'deny', + type: 'images' + }); + + let found = false; + for each (let permission in permissions.permissions) { + if (permission.host == 'erikvold.com') { + found = true; + assert.equal(permission.permission, 'deny'); + assert.equal(permission.type, 'images'); + } + } + assert.ok(found, 'erikvold.com permission was found'); + + permissions.remove({ + url: 'http://erikvold.com/', + type: 'images' + }); + + for each (let permission in permissions.permissions) { + if (permission.host == 'erikvold.com') { + assert.fail('there should not be a permission for erikvold.com'); + } + } + assert.pass('permission was removed!'); +}; + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-policy.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-policy.js new file mode 100644 index 0000000..5a811df --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-content-policy.js @@ -0,0 +1,155 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); +const tabs = require('sdk/tabs'); +const timers = require('sdk/timers'); + +const cp = require('pathfinder/content/policy'); + +exports.testConstants = function(assert) { + assert.ok(cp.REJECT != undefined, 'REJECT constant exists'); + assert.ok(cp.ACCEPT != undefined, 'ACCEPT constant exists'); + assert.ok(cp.ContentPolicy != undefined, 'ContentPolicy constant exists'); +}; + +exports.testContentPolicyDestroy = function(assert, done) { + const loader = Loader(module); + const httpd = loader.require('sdk/test/httpd'); + const { ContentPolicy } = loader.require('pathfinder/content/policy') + const { startServerAsync } = httpd; + const { setTimeout } = timers; + + let tabsCount = tabs.length; + let tab1; + + let serverPort = 8056; + let server = httpd.startServerAsync(serverPort); + const contents = '<!DOCTYPE html><html><head></head><body>testContentPolicyDestroy</body></html>'; + // test.html + let testPageRequests = 0; + server.registerPathHandler('/test.html', function handle(request, response) { + testPageRequests++; + response.write(contents); + }); + + let url = 'http://localhost:' + serverPort + '/test.html'; + let policy = ContentPolicy({ + shouldLoad: function({ location }) { + if (location != url) + return true; + + setTimeout(function() { + policy.destroy(); + + tabs.open({ + url: url, + inBackground: true, + onReady: function (tab2) { + assert.equal(tab2.url, url, url); + tab2.close(function() tab1.close()); + } + }); + assert.pass('tab2 opening..'); + }, 0); + return false; + } + }); + assert.pass('Content policy is setup'); + + setTimeout(function() { + tabs.open({ + url: url, + inBackground: true, + onOpen: function (tab) { + tab1 = tab; + assert.equal(tab1.url, 'about:blank', 'tab1 opened - about:blank'); + }, + onReady: function() { + assert.fail('tab1 loaded..'); + }, + onClose: function() { + assert.equal(testPageRequests, 1, 'test page was only requested once'); + //assert.equal(tabsCount, tabs.length, 'all test tabs are closed'); + loader.unload(); + done(); + } + }); + + assert.pass('tab1 opening..'); + }, 500); +}; + +exports.testContentPolicyUnload = function(assert, done) { + const loader = Loader(module); + const { ContentPolicy } = loader.require('pathfinder/content/policy'); + const { setTimeout } = loader.require('sdk/timers'); + + let tabsCount = tabs.length; + let tab1; + let otherTabs = []; + let calls = 0; + let expectedCalls = 1; + let url = 'data:text/html;charset=utf-8,testContentPolicyUnload'; + let policy = ContentPolicy({ + contract: '@erikvold.com/content-policy.TEST;unload', + shouldLoad: function({ location }) { + if (location != url) + return true; + + calls++; + setTimeout(function() { + loader.unload(); + + assert.pass('tab2 opening..'); + tabs.open({ + url: url, + inBackground: true, + onOpen: function(tab) { + otherTabs.push(tab); + }, + onReady: function (tab2) { + assert.equal(tab2.url, url, url); + expectedCalls = otherTabs.length; + + // close tabs + (function ender() { + if (otherTabs.length <= 0) + return tab1.close(); + otherTabs.pop().close(); + ender(otherTabs); + })() + } + }); + assert.pass('tab2 open called.'); + }, 0); + + return false; + } + }); + assert.pass('Content policy is setup'); + + setTimeout(function() { + assert.pass('tab1 opening..'); + tabs.open({ + url: url, + inBackground: true, + onOpen: function (tab) { + tab1 = tab; + assert.equal(tab1.url, 'about:blank', 'tab1 opened - about:blank'); + }, + onReady: function() { + assert.fail('tab1 loaded..'); + }, + onClose: function() { + assert.equal(calls, expectedCalls, 'content policy only rejected expected number of times'); + //assert.equal(tabsCount, tabs.length, 'all test tabs are closed'); + done(); + } + }); + }, 500); +}; + +require('test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-download.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-download.js new file mode 100644 index 0000000..30b4b69 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-download.js @@ -0,0 +1,58 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Ci, Cc, Cu } = require('chrome'); +const { pathFor } = require("sdk/system"); +const { Loader } = require("sdk/test/loader"); +const { Request } = require('sdk/request'); +const options = require("@test/options"); + +const { Download } = require('pathfinder/download'); + +const { Services } = require('pathfinder/chrome/services'); + +exports.testDownload = function(assert, done) { + const loader = Loader(module); + const httpd = loader.require('sdk/test/httpd'); + + let serverPort = 8057; + let server = httpd.startServerAsync(serverPort); + const contents = "testDownload"; + + server.registerPathHandler("/test.txt", function handle(request, response) { + response.write(contents); + }); + + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); + file.append("test.txt"); + + assert.ok(!file.exists(), 'Download does not exist yet'); + + let download = Download({ + url: "http://localhost:" + serverPort + "/test.txt", + destination: file.path, + onComplete: function() { + assert.ok(file.exists(), 'Download was successful'); + + Request({ + url: Services.io.newFileURI(file).spec, + overrideMimeType: "text/plain; charset=latin1", + onComplete: function ({ text }) { + assert.equal(text, contents, 'the file content is correct'); + file.remove(false); + assert.ok(!file.exists(), 'File was removed'); + + server.stop(function() { + loader.unload(); + done(); + }); + } + }).get(); + } + }); + assert.ok(!!download, 'Download started'); +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-find-suggestion.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-find-suggestion.js new file mode 100644 index 0000000..18e3de3 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-find-suggestion.js @@ -0,0 +1,3 @@ +'use strict'; + +require('pathfinder/ui/findbar/suggestion'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-listen.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-listen.js new file mode 100644 index 0000000..0967b4f --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-listen.js @@ -0,0 +1,152 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); +const { open, close, promise: windowPromise } = require('sdk/window/helpers'); +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +const { listen: gListen } = require('pathfinder/xul/listen'); + +// from https://developer.mozilla.org/en-US/docs/Web/API/document.createEvent +function simulateClick(ele) { + let window = ele.ownerDocument.defaultView; + let { document } = window; + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + ele.dispatchEvent(evt); +} + +function makeEle(window) { + window = window || getMostRecentBrowserWindow(); + let ele = window.document.createElementNS(NS_XUL, 'toolbar'); + return { + window: window, + document: window.document, + ele: ele + } +} + +exports.testSuccessiveListenersCaptureTrue = function(assert, done) { + const loader = Loader(module); + const { listen } = loader.require('pathfinder/xul/listen'); + let { window, document, ele } = makeEle(); + let aHappened = false; + + listen(window, ele, 'click', function() { + aHappened = true; + }, true); + listen(window, ele, 'click', function() { + assert.ok(aHappened, 'the first listener attached was the first called.') + loader.unload(); + done(); + }, true); + + simulateClick(ele); +} + +exports.testSuccessiveListeners = function(assert, done) { + const loader = Loader(module); + const { listen } = loader.require('pathfinder/xul/listen'); + let { window, document, ele } = makeEle(); + let aHappened = false; + + listen(window, ele, 'click', function() { + aHappened = true; + }, false); + listen(window, ele, 'click', function() { + assert.ok(aHappened, 'the first listener attached was the first called.') + loader.unload(); + done(); + }, false); + + simulateClick(ele); +} + +exports.testSuccessiveListenersAcrossLoaders = function(assert, done) { + const loader = Loader(module); + const { listen } = loader.require('pathfinder/xul/listen'); + let { window, document, ele } = makeEle(); + let aHappened = false; + + listen(window, ele, 'click', function() { + aHappened = true; + }, false); + let remover = gListen(window, ele, 'click', function() { + assert.ok(aHappened, 'the first listener attached was the first called.'); + remover(); + loader.unload(); + done(); + }, false); + + simulateClick(ele); +} + +exports.testRemover = function(assert, done) { + const loader = Loader(module); + const { listen } = loader.require('pathfinder/xul/listen'); + let { window, document, ele } = makeEle(); + let aHappened = false; + + let remover1 = listen(window, ele, 'click', function() { + aHappened = true; + }, false); + let remover = gListen(window, ele, 'click', function() { + assert.ok(!aHappened, 'the first listener attached was removed'); + remover(); + loader.unload(); + done(); + }, false); + + remover1(); + simulateClick(ele); +} + +exports.testWindowUnloadEvent = function(assert, done) { + let eHappened = false; + let { window, ele: ele1 } = makeEle(); + let remover2, remover1 = gListen(window, ele1, 'click', function() { + assert.ok(!eHappened, 'listeners are removed when parent window unloads'); + remover1(); + remover2(); + done(); + }); + + open().then(function(window) { + let { document, ele: ele2 } = makeEle(window); + + remover2 = gListen(window, ele2, 'click', function() { + eHappened = true; + }); + + windowPromise(window, 'unload').then(function() { + simulateClick(ele2); + simulateClick(ele1); + }); + close(window); + }); +} + +exports.testListenWorksOnUnload = function(assert, done) { + const loader = Loader(module); + const { listen } = loader.require('pathfinder/xul/listen'); + let { window, document, ele } = makeEle(); + + listen(window, ele, 'click', function() { + assert.fail('should not be here'); + }, false); + + let remover = gListen(window, ele, 'click', function() { + remover(); + assert.pass('ending listen unload test'); + done(); + }, false); + + loader.unload(); + simulateClick(ele); +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-menuitems.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-menuitems.js new file mode 100644 index 0000000..db55a36 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-menuitems.js @@ -0,0 +1,169 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict' + +const windowUtils = require('sdk/deprecated/window-utils'); +const menuitems = require('pathfinder/ui/menuitems'); + +let window = windowUtils.activeBrowserWindow; +let document = window.document; +function $(id) document.getElementById(id); + +function createMI(options, test) { + test.equal(!$(options.id), true); + var mi = new menuitems.Menuitem(options); + return mi; +} + +exports.testMIDoesNotExist = function(assert) { + var options = { + id: "test-mi-dne", + label: "test" + }; + createMI(options, assert); + assert.equal(!!$(options.id), false, 'menuitem does not exists'); +}; + +exports.testMIDoesExist = function(assert) { + var options = { + id: "test-mi-exists", + label: "test", + menuid: 'menu_FilePopup' + }; + let mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.id, options.id, 'menuitem id is ok'); + assert.equal(menuitem.getAttribute('label'), options.label, 'menuitem label is ok'); + assert.equal(menuitem.parentNode.id, options.menuid, 'in the file menu'); + assert.equal(menuitem.getAttribute('disabled'), 'false', 'menuitem not disabled'); + assert.equal(menuitem.getAttribute('accesskey'), '', 'menuitem accesskey is ok'); + assert.equal(menuitem.getAttribute('class'), '', 'menuitem class is ok'); + assert.equal(menuitem.nextSibling, undefined, 'menuitem is last'); + assert.equal(menuitem.hasAttribute("checked"), false, 'menuitem not checked'); + mi.destroy(); + assert.ok(!$(options.id), 'menuitem is gone'); + assert.equal(menuitem.parentNode, null, 'menuitem has no parent'); +}; + +exports.testMIOnClick = function(assert, done) { + let options = { + id: "test-mi-onclick", + label: "test", + menuid: 'menu_FilePopup', + onCommand: function() { + mi.destroy(); + assert.pass('onCommand worked!'); + done(); + } + }; + + let e = document.createEvent("UIEvents"); + e.initUIEvent("command", true, true, window, 1); + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + menuitem.dispatchEvent(e); +}; + +exports.testMIDisabled = function(assert, done) { + let commandIsOK = false; + let count = 0; + let options = { + id: "test-mi-disabled", + label: "test", + disabled: true, + menuid: 'menu_FilePopup', + onCommand: function() { + count++; + if (!commandIsOK) { + assert.fail('onCommand was called, that is not ok'); + return; + } + + mi.destroy(); + assert.equal(count, 1, 'onCommand was called the correct number of times!'); + done(); + } + }; + + let e = document.createEvent("UIEvents"); + e.initUIEvent("command", true, true, window, 1); + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute('disabled'), 'true', 'menuitem not disabled'); + menuitem.dispatchEvent(e); + mi.disabled = false; + assert.equal(menuitem.getAttribute('disabled'), 'false', 'menuitem not disabled'); + commandIsOK = true; + menuitem.dispatchEvent(e); +}; + +exports.testMIChecked = function(assert) { + let options = { + id: "test-mi-checked", + label: "test", + disabled: true, + menuid: 'menu_FilePopup', + checked: true + }; + + let mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute("checked"), "true", 'menuitem checked'); + mi.checked = false; + assert.equal(menuitem.getAttribute("checked"), "false", 'menuitem checked'); + mi.destroy(); +}; + +exports.testMIClass = function(assert) { + let options = { + id: "test-mi-class", + label: "pizazz", + className: "pizazz", + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.getAttribute('class'), 'pizazz', 'menuitem not disabled'); + mi.destroy(); +}; + +exports.testInsertBeforeExists = function(assert) { + let options = { + id: 'test-mi-insertbefore', + label: 'insertbefore', + insertbefore:'menu_FileQuitItem', + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.nextSibling, $('menu_FileQuitItem'), 'menuitem not disabled'); + mi.destroy(); +}; + +exports.testInsertBeforeDoesNotExist = function(assert) { + let options = { + id: 'test-mi-insertbefore', + label: 'insertbefore', + insertbefore:'menu_ZZZDNE', + menuid: 'menu_FilePopup', + }; + + var mi = createMI(options, assert); + let menuitem = $(options.id); + assert.equal(!!menuitem, true, 'menuitem exists'); + assert.equal(menuitem.nextSibling, null, 'menuitem not disabled'); + mi.destroy(); +}; + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-panic.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-panic.js new file mode 100644 index 0000000..49d3a76 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-panic.js @@ -0,0 +1,103 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const panic = require('pathfinder/panic'); +const prefs = require('sdk/preferences/service'); +const { Loader } = require('sdk/test/loader'); + +const PREF_END_NAME = 'security.addon.panic_end'; + +// TEST: the inPanic variable and panic events +exports.testPanicInPanic = function(assert, done) { + assert.equal(panic.inPanic, false, "not in a panic"); + panic.once('start', function() { + assert.pass('"start" event was fired'); + assert.equal(panic.inPanic, true, "in a panic"); + + panic.once('end', function() { + assert.pass('"end" event was fired'); + assert.equal(panic.inPanic, false, "not in a panic"); + + done(); + }); + }); + + panic.panic(); +}; + +// TEST: on and off methods +exports.testPanicOnOff = function(assert, done) { + let count = 0; + + panic.on('start', function panicOn() { + panic.off('start', panicOn); + count++; + + panic.once('start', function() { + if (count > 1) { + assert.fail('panic.on was called too many times'); + } + else { + assert.pass('panic.on was only called once'); + } + + panic.once('end', function() { + done(); + }); + }); + + panic.once('end', function() { + panic.panic(50); + }); + }); + + panic.panic(); +}; + +// TEST: panic emits in multiple instances +exports.testPanicFiresInMultipleInstances = function(assert, done) { + let count = 0; + + let loader = Loader(module); + let panic2 = loader.require('panic'); + + let testCounter = function() { + if (++count < 2) return; + assert.pass('panic was fired on multiple instances'); + + panic.once('end', function() { + loader.unload(); + done(); + }); + }; + panic.once('start', testCounter); + panic2.once('start', testCounter); + + panic.panic(); +}; + +exports.testEndTimestamp = function(assert, done) { + let ms = 0; + let min = Date.now() + ms; + let endTimestamp; + + panic.once('end', function() { + let now = Date.now(); + let max = (now + ms); + + assert.ok(min <= endTimestamp, endTimestamp + ' is gte ' + min); + assert.ok(min <= now, now + ' event is gte to ' + min); + assert.ok(max >= endTimestamp, 'timestamp is lte to max'); + assert.ok(max >= now, 'end event is lte to max'); + + done(); + }); + + panic.panic(ms); + + endTimestamp = prefs.get(PREF_END_NAME); +}; + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-redirect.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-redirect.js new file mode 100644 index 0000000..071b09d --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-redirect.js @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const tabs = require('sdk/tabs'); +const { data } = require('sdk/self'); +const { Loader } = require("sdk/test/loader"); + +const { Redirect } = require('pathfinder/redirect'); + +function getData(url) { + return 'data:text/javascript;charset=utf-8,' + encodeURIComponent(url); +} + +exports.testRedirect = function(assert, done) { + const loader = Loader(module); + const httpd = loader.require('sdk/test/httpd'); + const { startServerAsync } = httpd; + + let serverPort = 8058; + let server = httpd.startServerAsync(serverPort); + const contents = "testRedirect"; + + server.registerPathHandler("/test.txt", function handle(request, response) { + response.write(contents); + }); + + let details = { + from: 'http://localhost:' + serverPort + '/test.txt', + to: getData('exptected') + }; + let redirect = Redirect(JSON.parse(JSON.stringify(details))); + + tabs.open({ + url: details.from, + onReady: function(tab) { + assert.equal(tab.url, details.to, 'The final destination is correct!'); + redirect.destroy(); + + server.stop(function() { + loader.unload(); + tab.close(done); + }); + } + }); +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-about.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-about.js new file mode 100644 index 0000000..5d7873f --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-about.js @@ -0,0 +1,43 @@ +'use strict'; + +const { Loader } = require('sdk/test/loader'); +const tabs = require('sdk/tabs') + +function openTabGetContent(url, callback) { + tabs.open({ + url: 'about:test', + inBackground: true, + onReady: function(tab) { + let worker = tab.attach({ + contentScript: 'self.port.emit("body", document.body.innerHTML)' + }) + worker.port.on('body', function(msg) { + tab.close(function() { + callback(msg); + }); + }); + } + }) +} + +exports.testAddAboutWhat = function(assert, done) { + const loader = Loader(module); + const { add } = loader.require('pathfinder/scheme/about'); + + add({ + what: 'test', + url: 'data:text/html;charset=utf-8,<body>test</body>' + }); + + openTabGetContent('about:test', function(msg) { + assert.equal(msg, 'test', 'about:test content is "test"'); + loader.unload(); + openTabGetContent('about:test', function(msg) { + assert.notEqual(msg, 'test', 'about:test content is "test"'); + done(); + }); + }); + +} + +require('test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-resource.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-resource.js new file mode 100644 index 0000000..da6fd3b --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-scheme-resource.js @@ -0,0 +1,3 @@ +'use strict'; + +require('pathfinder/scheme/resource'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-storage.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-storage.js new file mode 100644 index 0000000..14187cd --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-storage.js @@ -0,0 +1,134 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); +const { before, after } = require('sdk/test/utils'); + +const { get, set } = require('pathfinder/storage'); + +exports.testGetNothing = function(assert, done) { + get().then(function({ data }) { + assert.equal(data, '', 'the data is blank!'); + done(); + }); +}; + +exports.testSetThenGet = function(assert, done) { + const randomData = Math.random() + ''; + + // SET TO A RANDOM VALUE + set({ data: randomData }).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, randomData, 'the data returned from set is correct [' + randomData + ']'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, randomData, 'the data returned from get is correct [' + randomData + ']'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }) + // SET AGAIN + .then(function() set({ data: 'test' })).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, 'test', 'the data returned from set is correct [test]'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, 'test', 'the data returned from get is correct [test]'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }). + // SET TO BLANK + then(function() set({ data: '' })).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, '', 'the data returned from set is correct'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, '', 'the data returned from get is correct'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }). + // SET TO BLANK AGAIN + then(function() set({ data: '' })).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, '', 'the data returned from set is correct'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, '', 'the data returned from get is correct'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }).then(done, assert.fail); +}; + +exports.testSettingJSON = function(assert, done) { + const json = JSON.stringify({ + num: 1, + str: 'string', + bool: true, + obj: { x: 'x' }, + ary: [ 1, 2, 3 ] + }); + + set({ data: json }).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, json, 'the data returned from set is correct json'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, json, 'the data returned from get is correct json'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }). + // SET TO BLANK AGAIN + then(function() set({ data: '' })).then(function({ data }) { + assert.pass('setting was successful'); + assert.equal(data, '', 'the data returned from set is correct'); + }, function(e) { + assert.fail('setting was unsuccessful'); + assert.fail(e); + }).then(function() get()).then(function({ data }) { + assert.pass('getting was successful'); + assert.equal(data, '', 'the data returned from get is correct'); + }, function(e) { + assert.fail('getting was unsuccessful'); + assert.fail(e); + }).then(done, assert.fail); +}; + +before(exports, function(name, assert, done) { + let loader = Loader(module); + loader.require('pathfinder/storage'); + let file = loader.sandbox('pathfinder/storage').getStorageFile(); + assert.pass(file.exists(), false, 'the storage file DNE'); + loader.unload(); + done(); +}); +after(exports, function(name, assert, done) { + let loader = Loader(module); + loader.require('pathfinder/storage'); + let file = loader.sandbox('pathfinder/storage').getStorageFile(); + assert.pass(file.exists(), false, 'the storage file DNE'); + loader.unload(); + done(); +}); + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-toolbarbutton.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-toolbarbutton.js new file mode 100644 index 0000000..1cfb269 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-toolbarbutton.js @@ -0,0 +1,165 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const windows = require("sdk/windows").browserWindows; +const toolbarbutton = require("pathfinder/ui/toolbarbutton"); +//const { Loader } = require('sdk/test/loader'); +const winUtils = require('sdk/window/utils'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +const TEST_ICON_URL = module.uri.replace(/[^\.\\\/]*\.js$/, "test.png"); +const TEST_ICON_BLACK_URL = module.uri.replace(/[^\.\\\/]*\.js$/, "black.png"); + +function $(id) winUtils.getMostRecentBrowserWindow().document.getElementById(id); + +function createToolbarButton(options, test) { + test.assertEqual(!$(options.id), true); + + var tbb = toolbarbutton.ToolbarButton(options); + test.assertEqual(!$(options.id), true); + + tbb.moveTo(options); + if (options.toolbarID) + test.assertEqual(!$(options.id), false); + + return tbb; +} + +function buttonExists(button, options, test) { + test.assertEqual(!button, false, 'test button'); + test.assertEqual(button.parentNode, $(options.toolbarID), 'test parent'); + test.assertEqual(button.id, options.id, 'test id'); + if (options.label) + test.assertEqual(button.label, options.label, 'test label'); + if (options.image) + test.assertEqual(button.image, options.image); + else + test.assertEqual(button.image, ""); +} + +exports.testTBBExists = function(test) { + var options = { + id: "test-tbb", + label: "test", + toolbarID: "nav-bar", + forceMove: true + }; + + var tbb = createToolbarButton(options, test); + buttonExists($(options.id), options, test); + tbb.destroy(); + test.assertEqual(!$(options.id), true); + var tbb = createToolbarButton(options, test); + tbb.destroy(); +}; + +exports.testTBBDoesNotExist = function(test) { + var options = { + id: "test-tbb2", + label: "test" + }; + var tbb = createToolbarButton(options, test); + var tbbEle = $(options.id); + test.assertEqual(!tbbEle, true, 'toolbar button dne'); + tbb.destroy(); +}; + +exports.testTBBLabelChange = function(test) { + test.waitUntilDone(); + + var options = { + id: "test-tbb3", + label: "test", + toolbarID: "nav-bar", + forceMove: true + }; + + let tbb = createToolbarButton(options, test); + buttonExists($(options.id), options, test); + tbb.label = 'test change'; + test.assertEqual($(options.id).label, 'test change', 'the label is changed'); + test.assertEqual(tbb.label, 'test change', 'the label is changed'); + + tbb.destroy(); + test.done(); +}; + +exports.testTBBPropertyChange = function(test) { + test.waitUntilDone(); + + var options = { + id: "test-tbb4", + label: "test", + toolbarID: "nav-bar", + forceMove: true, + image: TEST_ICON_URL, + tooltiptext: 'a' + }; + + let tbb = createToolbarButton(options, test); + buttonExists($(options.id), options, test); + test.assertEqual($(options.id).image, TEST_ICON_URL, 'the image is correct'); + test.assertEqual(tbb.image, TEST_ICON_URL, 'the image is correct'); + test.assertEqual(tbb.tooltiptext, 'a', 'the tooltiptext is correct'); + tbb.setIcon({url: TEST_ICON_BLACK_URL}); + test.assertEqual($(options.id).image, TEST_ICON_BLACK_URL, 'the image is changed'); + test.assertEqual(tbb.image, TEST_ICON_BLACK_URL, 'the image is changed'); + tbb.tooltiptext = 'b'; + test.assertEqual($(options.id).getAttribute('tooltiptext'), 'b', 'the tooltiptext is changed'); + test.assertEqual(tbb.tooltiptext, 'b', 'the tooltiptext is changed'); + + tbb.destroy(); + test.done(); +}; + +exports.testTBBIteratorWithNonBrowserWindow = function(test) { + test.waitUntilDone(); + + let scratchpad = winUtils.getMostRecentBrowserWindow().Scratchpad.openScratchpad(); + let options = { + id: "test-tbb5", + label: "TEST", + toolbarID: "nav-bar", + image: TEST_ICON_URL + }; + windows.open({ + onOpen: function(window) { + let tbb = createToolbarButton(options, test); + test.assertEqual(windows.length, 2); + + scratchpad.close(); + tbb.destroy(); + window.close(function() test.done()); + } + }) +}; + +exports.testTBBIterator2 = function(test) { + test.waitUntilDone(); + + let window1 = winUtils.getMostRecentBrowserWindow(); + let options = { + id: "test-tbb6", + label: "TEST", + toolbarID: "nav-bar", + image: TEST_ICON_URL + }; + let button = window1.document.createElementNS(NS_XUL, "toolbarbutton"); + button.setAttribute('id', options.id); + window1.document.getElementById(options.toolbarID).appendChild(button); + test.assert(!!$(options.id)); + + windows.open({ + onOpen: function(window) { + let tbb = createToolbarButton(options, test); + test.assertEqual(windows.length, 2); + + tbb.destroy(); + button.parentNode.removeChild(button); + window.close(function() test.done()); + } + }) +}; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-unload+.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-unload+.js new file mode 100644 index 0000000..edb9dff --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-unload+.js @@ -0,0 +1,150 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var timer = require("sdk/timers"); +var { Cc,Ci } = require("chrome"); +const windowUtils = require("sdk/deprecated/window-utils"); +const { Loader } = require('sdk/test/loader'); + +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 + '">' + + '</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.testUnloading = function(assert) { + var loader = Loader(module); + var {unload} = loader.require("pathfinder/addon/unload"); + var unloadCalled = 0; + + function unloader() { + unloadCalled++; + } + unload(unloader); + + function unloader2() unloadCalled++; + var removeUnloader2 = unload(unloader2); + + function unloader3() unloadCalled++; + unload(unloader3); + + // remove unloader2 + removeUnloader2(); + + loader.unload(); + + assert.equal(unloadCalled, 2, "Unloader functions are called on unload."); +}; + +exports.testUnloadingWindow = function(assert, done) { + var loader = Loader(module); + var {unload} = loader.require("pathfinder/addon/unload"); + var unloadCalled = 0; + var finished = false; + var myWindow; + + var delegate = { + onTrack: function(window) { + if (window == myWindow) { + assert.pass("onTrack() called with our test window"); + + let unloader = function unloader() { + unloadCalled++; + } + unload(unloader, window); + unload(unloader); + + timer.setTimeout(function() { + window.close(); + + assert.equal(unloadCalled, 1, "unloader was still called."); + + if (window.closed) { + assert.pass("window closed"); + } + else { + assert.fail("window is not closed!"); + } + + timer.setTimeout(function() { + assert.equal(unloadCalled, 1, "unloader was called."); + + unload(function() { + assert.equal(unloadCalled, 2, "two unloaders called."); + + if (finished) { + assert.pass("finished"); + done(); + } + else { + assert.fail("not finished!"); + } + }); + + loader.unload(); + }, 1); + }, 1); + } + }, + onUntrack: function(window) { + if (window == myWindow) { + assert.pass("onUntrack() called with our test window"); + + if (!finished) { + finished = true; + myWindow = null; + wt.unload(); + } + else { + assert.fail("finishTest() called multiple times."); + } + } + } + }; + + var wt = new windowUtils.WindowTracker(delegate); + myWindow = makeEmptyWindow(); +}; + +exports.testUnloaderExecutionOnWindowClose = function(assert, done) { + var loader = Loader(module); + var {unload} = loader.require("pathfinder/addon/unload"); + var unloadCalled = 0; + var finished = false; + var myWindow; + var unloaderRan = false; + + var delegate = { + onTrack: function(window) { + if (window != myWindow) return; + + unload(function() unloaderRan = true, window); + window.close(); + }, + onUntrack: function(window) { + if (window != myWindow) return; + + loader.require('sdk/timers').setTimeout(function() { + assert.ok(unloaderRan, 'test complete'); + loader.unload(); + done(); + }, 0); + } + }; + + var wt = new windowUtils.WindowTracker(delegate); + myWindow = makeEmptyWindow(); +}; + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userscripts.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userscripts.js new file mode 100644 index 0000000..e43199c --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userscripts.js @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + + + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.css diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.js new file mode 100644 index 0000000..50b741e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-userstyles.js @@ -0,0 +1,116 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); + +const userstyles = require('userstyles'); + +const TEST_CSS_URL = module.uri.replace(/\.js$/, '.css'); +const TEST_FNF_URL = module.uri.replace(/\.js$/, '.x.css'); + +// TEST: userstyles.load +exports.testLoad = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + + userstyles.load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + userstyles.unload(TEST_CSS_URL); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css was unregistered.'); +}; + +// TEST: userstyles.load file not found +exports.testLoadFNF = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is not registered.'); + + try { + userstyles.load(TEST_FNF_URL); + assert.fail('trying to load a file that does not exist should throw an error'); + } + catch(e) { + assert.pass('trying to load a file that does not exist throws an error'); + } + + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css was not registered.'); +}; + +// TEST: userstyles.load for 'agent' type +exports.testLoadAgent = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is not registered.'); + assert.equal(userstyles.registered(TEST_CSS_URL, {type: 'agent'}), false, 'css is not registered.'); + + userstyles.load(TEST_CSS_URL, {type: 'AgeNt'}); + assert.ok(userstyles.registered(TEST_CSS_URL, {type: 'AGENT'}), 'css was registered.'); + + try { + userstyles.unload(TEST_CSS_URL); + assert.fail('unregister did not throw an error'); + } + catch(e) { + assert.pass('unregister did throw an error'); + } + assert.equal(userstyles.registered(TEST_CSS_URL, {type: 'agent'}), true, 'css was not unregistered.'); + + userstyles.unload(TEST_CSS_URL, {type: 'agent'}); + assert.equal(userstyles.registered(TEST_CSS_URL, {type: 'agent'}), false, 'css was unregistered.'); +}; + +exports.testUnload = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + let loader = Loader(module); + + loader.require('userstyles').load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + loader.unload(); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css was unregistered.'); +} + +exports.testUnloadWithMultipleLoads = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + let loader = Loader(module); + + // first load + loader.require('userstyles').load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + // now unload + loader.require('userstyles').unload(TEST_CSS_URL); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + + // now load again + loader.require('userstyles').load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + // send addon unload message and see if we fail + loader.unload(); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); +} + +exports.testUnloadWithMultipleLoaders = function(assert) { + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + let loader = Loader(module); + + // first load + loader.require('userstyles').load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + // now unload + loader.require('userstyles').unload(TEST_CSS_URL); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css is unregistered.'); + + // now load again + userstyles.load(TEST_CSS_URL); + assert.ok(userstyles.registered(TEST_CSS_URL), 'css was registered.'); + + // send addon unload message and see if we fail + loader.unload(); + assert.equal(userstyles.registered(TEST_CSS_URL), true, 'css is still registered.'); + + userstyles.unload(TEST_CSS_URL); + assert.equal(userstyles.registered(TEST_CSS_URL), false, 'css was unregistered.'); +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-web-panel.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-web-panel.js new file mode 100644 index 0000000..e97779a --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test-web-panel.js @@ -0,0 +1,563 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); +const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers'); +const { setTimeout } = require('sdk/timers'); +const { isPrivate } = require('sdk/private-browsing'); +const { data } = require('sdk/self'); +const { fromIterator } = require('sdk/util/array'); +const { URL } = require('sdk/url'); + +const { WebPanel } = require('pathfinder/ui/web-panel'); +const { show, hide } = require('pathfinder/ui/sidebar/actions'); +const { isShowing } = require('pathfinder/ui/sidebar/state'); + +const BUILTIN_SIDEBAR_MENUITEMS = [ + 'menu_socialSidebar', + 'menu_historySidebar', + 'menu_bookmarksSidebar' +]; + +const WEB_PANEL_BROWSER_ID = 'web-panels-browser'; + +function isSidebarShowing(window) { + window = window || getMostRecentBrowserWindow(); + let sidebar = window.document.getElementById('sidebar-box'); + return !sidebar.hidden; +} + +function getSidebarMenuitems(window) { + window = window || getMostRecentBrowserWindow(); + return fromIterator(window.document.querySelectorAll('#viewSidebarMenu menuitem')); +} + +function getExtraSidebarMenuitems() { + let menuitems = getSidebarMenuitems(); + return menuitems.filter(function(mi) { + return BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) < 0; + }); +} + +function makeID(id) { + return 'pathfinder-sidebar-' + id; +} + +function simulateClick(ele) { + let window = ele.ownerDocument.defaultView; + let { document } = window; + var evt = document.createEvent("XULCommandEvent"); + evt.initCommandEvent("command", true, true, window, + 0, false, false, false, false, null); + ele.dispatchEvent(evt); +} + +exports.testSidebarBasicLifeCycle = function(assert, done) { + let testName = 'testSidebarBasicLifeCycle'; + let window = getMostRecentBrowserWindow(); + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + let sidebarXUL = window.document.getElementById('sidebar'); + assert.ok(sidebarXUL, 'sidebar xul element does exist'); + assert.ok(!getExtraSidebarMenuitems().length, 'there are no extra sidebar menuitems'); + + assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 1'); + let sidebarDetails = { + id: testName, + title: 'test', + url: 'data:text/html;charset=utf-8,'+testName + }; + let sidebar = WebPanel(sidebarDetails); + + // test the sidebar attributes + for each(let key in Object.keys(sidebarDetails)) { + assert.equal(sidebarDetails[key], sidebar[key], 'the attributes match the input'); + } + + assert.pass('The Sidebar constructor worked'); + + let extraMenuitems = getExtraSidebarMenuitems(); + assert.equal(extraMenuitems.length, 1, 'there is one extra sidebar menuitems'); + + let ele = window.document.getElementById(makeID(testName)); + assert.equal(ele, extraMenuitems[0], 'the only extra menuitem is the one for our sidebar.') + assert.ok(ele, 'sidebar element was added'); + assert.ok(ele.getAttribute('checked'), 'false', 'the sidebar is not displayed'); + assert.equal(ele.getAttribute('label'), sidebar.title, 'the sidebar title is the menuitem label') + + assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 2'); + sidebar.on('show', function() { + assert.pass('the show event was fired'); + assert.equal(isSidebarShowing(window), true, 'sidebar is not showing 3'); + assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); + assert.equal(ele.getAttribute('checked'), 'true', 'the sidebar is displayed'); + + sidebar.once('hide', function() { + assert.pass('the hide event was fired'); + assert.equal(ele.getAttribute('checked'), 'false', 'the sidebar menuitem is not checked'); + assert.equal(isShowing(sidebar), false, 'the sidebar is not showing'); + assert.equal(isSidebarShowing(window), false, 'the sidebar elemnt is hidden'); + + sidebar.once('detach', function() { + sidebar.destroy(); + + let sidebarMI = getSidebarMenuitems(); + for each (let mi in sidebarMI) { + assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar') + assert.equal(mi.getAttribute('checked'), "false", 'no sidebar menuitem is checked'); + } + + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.pass('calling destroy worked without error'); + + done(); + }); + }); + + sidebar.hide(); + assert.pass('hiding sidebar..'); + }); + + sidebar.show(); + assert.pass('showing sidebar..'); +} + +exports.testSideBarIsInNewWindows = function(assert, done) { + let testName = 'testSideBarOnNewWindow'; + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+testName + }); + + let startWindow = getMostRecentBrowserWindow(); + let ele = startWindow.document.getElementById(makeID(testName)); + assert.ok(ele, 'sidebar element was added'); + + open().then(function(window) { + let ele = window.document.getElementById(makeID(testName)); + assert.ok(ele, 'sidebar element was added'); + + sidebar.destroy(); + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE'); + + close(window).then(done, assert.fail); + }) +} + +exports.testSideBarIsNotInNewPrivateWindows = function(assert, done) { + let testName = 'testSideBarOnNewWindow'; + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+testName + }); + + let startWindow = getMostRecentBrowserWindow(); + let ele = startWindow.document.getElementById(makeID(testName)); + assert.ok(ele, 'sidebar element was added'); + + open(null, { features: { private: true } }).then(function(window) { + let ele = window.document.getElementById(makeID(testName)); + assert.ok(isPrivate(window), 'the new window is private'); + assert.equal(ele, null, 'sidebar element was not added'); + + sidebar.destroy(); + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE'); + + close(window).then(done, assert.fail); + }) +} + +exports.testSideBarIsShowingInNewWindows = function(assert, done) { + let testName = 'testSideBarIsShowingInNewWindows'; + let sidebar = WebPanel({ + id: testName, + title: testName, + url: URL('data:text/html;charset=utf-8,'+testName) + }); + + let startWindow = getMostRecentBrowserWindow(); + let ele = startWindow.document.getElementById(makeID(testName)); + assert.ok(ele, 'sidebar element was added'); + + let oldEle = ele; + sidebar.once('show', function() { + assert.pass('show event fired'); + + sidebar.once('attach', function() { + assert.pass('attach event fired'); + + sidebar.once('show', function() { + let window = getMostRecentBrowserWindow(); + assert.notEqual(startWindow, window, 'window is new'); + + let sb = window.document.getElementById('sidebar'); + if (sb && sb.docShell && sb.contentDocument && sb.contentDocument.getElementById('web-panels-browser')) { + end(); + } + else { + sb.addEventListener('DOMWindowCreated', end, false); + } + + function end() { + sb.removeEventListener('DOMWindowCreated', end, false); + let webPanelBrowser = sb.contentDocument.getElementById('web-panels-browser'); + + let ele = window.document.getElementById(makeID(testName)); + + assert.ok(ele, 'sidebar element was added 2'); + assert.equal(ele.getAttribute('checked'), 'true', 'the sidebar is checked'); + assert.notEqual(ele, oldEle, 'there are two different sidebars'); + + assert.equal(isShowing(sidebar), true, 'the sidebar is showing in new window'); + + webPanelBrowser.contentWindow.addEventListener('load', function onload() { + webPanelBrowser.contentWindow.addEventListener('load', onload, false); + + sidebar.destroy(); + + assert.equal(isShowing(sidebar), false, 'the sidebar is not showing'); + assert.ok(!isSidebarShowing(window), 'sidebar in most recent window is not showing'); + assert.ok(!isSidebarShowing(startWindow), 'sidebar in most start window is not showing'); + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE'); + + setTimeout(function() { + close(window).then(done, assert.fail); + }); + }, false); + } + }); + + startWindow.OpenBrowserWindow(); + }); + }); + + show(sidebar); + assert.pass('showing the sidebar'); +} + +exports.testShowingOneSidebarAfterAnother = function(assert, done) { + let testName = 'testShowingOneSidebarAfterAnother'; + + let sidebar1 = WebPanel({ + id: testName + '1', + title: testName + '1', + url: 'data:text/html;charset=utf-8,'+ testName + 1 + }); + let sidebar2 = WebPanel({ + id: testName + '2', + title: testName + '2', + url: 'data:text/html;charset=utf-8,'+ testName + 2 + }); + + let window = getMostRecentBrowserWindow(); + let IDs = [ sidebar1.id, sidebar2.id ]; + + let extraMenuitems = getExtraSidebarMenuitems(window); + assert.equal(extraMenuitems.length, 2, 'there are two extra sidebar menuitems'); + + function testShowing(sb1, sb2, sbEle) { + assert.equal(isShowing(sidebar1), sb1); + assert.equal(isShowing(sidebar2), sb2); + assert.equal(isSidebarShowing(window), sbEle); + } + testShowing(false, false, false); + + sidebar1.once('show', function() { + testShowing(true, false, true); + for each (let mi in getExtraSidebarMenuitems(window)) { + let menuitemID = mi.getAttribute('id').replace(/^pathfinder-sidebar-/, ''); + assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars'); + assert.equal(mi.getAttribute('checked'), menuitemID == sidebar1.id ? 'true' : 'false', 'the test sidebar menuitem has the correct checked value'); + } + + sidebar2.once('show', function() { + testShowing(false, true, true); + for each (let mi in getExtraSidebarMenuitems(window)) { + let menuitemID = mi.getAttribute('id').replace(/^pathfinder-sidebar-/, ''); + assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars'); + assert.equal(mi.getAttribute('checked'), menuitemID == sidebar2.id ? 'true' : 'false', 'the test sidebar menuitem has the correct checked value'); + } + + sidebar1.destroy(); + sidebar2.destroy(); + + testShowing(false, false, false); + + done(); + }); + + show(sidebar2); + assert.pass('showing sidebar 2'); + }) + show(sidebar1); + assert.pass('showing sidebar 1'); +} + +exports.testSidebarUnload = function(assert, done) { + let loader = Loader(module); + + let testName = 'testSidebarUnload'; + let window = getMostRecentBrowserWindow(); + + assert.equal(isPrivate(window), false, 'the current window is not private'); + + let sidebar = loader.require('pathfinder/ui/web-panel').WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+ testName, + onShow: function() { + assert.pass('onShow works for Sidebar'); + loader.unload(); + + let sidebarMI = getSidebarMenuitems(); + for each (let mi in sidebarMI) { + assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar') + assert.equal(mi.getAttribute('checked'), 'false', 'no sidebar menuitem is checked'); + } + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing'); + + done(); + } + }) + + sidebar.show(); + assert.pass('showing the sidebar'); +} + +exports.testRemoteContent = function(assert) { + let testName = 'testRemoteContent'; + try { + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'http://dne.xyz.mozilla.org' + }); + assert.ok('the web panel was created!'); + sidebar.destroy(); + } + catch(e) { + assert.fail('sidebar was not created..'); + } +} + +exports.testInvalidURL = function(assert) { + let testName = 'testInvalidURL'; + try { + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'http:mozilla.org' + }); + assert.pass('remote uris are fine'); + sidebar.destroy(); + } + catch(e) { + assert.ok(/The option "url" must be a valid URI./.test(e), 'invalid URIs are not acceptable'); + } +} + +exports.testInvalidURLType = function(assert) { + let testName = 'testInvalidURLType'; + try { + let sidebar = WebPanel({ + id: testName, + title: testName + }); + assert.fail('a bad sidebar was created..'); + sidebar.destroy(); + } + catch(e) { + assert.ok(/The option "url" must be a valid URI./.test(e), 'invalid URIs are not acceptable'); + } +} + +exports.testInvalidTitle = function(assert) { + let testName = 'testInvalidTitle'; + try { + let sidebar = WebPanel({ + id: testName, + title: '', + url: 'data:text/html;charset=utf-8,'+testName + }); + assert.fail('a bad sidebar was created..'); + sidebar.destroy(); + } + catch(e) { + assert.equal('The option "title" must be one of the following types: string', e.message, 'invalid titles are not acceptable'); + } +} + +exports.testInvalidID = function(assert) { + let testName = 'testInvalidTitle'; + try { + let sidebar = WebPanel({ + id: '!', + title: testName, + url: 'data:text/html;charset=utf-8,'+testName + }); + assert.fail('a bad sidebar was created..'); + sidebar.destroy(); + } + catch(e) { + assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable'); + } +} + +exports.testSidebarIsNotOpenInNewPrivateWindow = function(assert, done) { + let testName = 'testSidebarIsNotOpenInNewPrivateWindow'; + let window = getMostRecentBrowserWindow(); + + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+testName + }); + + sidebar.on('show', function() { + assert.equal(isPrivate(window), false, 'the new window is not private'); + assert.equal(isSidebarShowing(window), true, 'the sidebar is showing'); + assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); + + let window2 = window.OpenBrowserWindow({private: true}); + windowPromise(window2, 'load').then(focus).then(function() { + // TODO: find better alt to setTimeout... + setTimeout(function() { + assert.equal(isPrivate(window2), true, 'the new window is private'); + assert.equal(isSidebarShowing(window), true, 'the sidebar is showing in old window still'); + assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing in the new private window'); + assert.equal(isShowing(sidebar), false, 'the sidebar is not showing'); + sidebar.destroy(); + close(window2).then(done); + }, 500) + }) + }); + + sidebar.show(); +} + +// TEST: edge case where web panel is destroyed while loading +exports.testDestroyEdgeCaseBug = function(assert, done) { + let testName = 'testDestroyEdgeCaseBug'; + let window = getMostRecentBrowserWindow(); + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+testName + }); + + // NOTE: purposely not listening to show event b/c the event happens + // between now and then. + sidebar.show(); + + assert.equal(isPrivate(window), false, 'the new window is not private'); + assert.equal(isSidebarShowing(window), true, 'the sidebar is showing'); + + //assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); + + open(null, { features: { private: true } }).then(focus).then(function(window2) { + assert.equal(isPrivate(window2), true, 'the new window is private'); + assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing'); + assert.equal(isShowing(sidebar), false, 'the sidebar is not showing'); + + sidebar.destroy(); + assert.pass('destroying the sidebar'); + + close(window2).then(function() focus(window)).then(function(window) { + let loader = Loader(module); + + assert.equal(window, getMostRecentBrowserWindow(), 'window is current window'); + assert.equal(isPrivate(window), false, 'the current window is not private!'); + + let sidebar = loader.require('pathfinder/ui/web-panel').WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+ testName, + onShow: function() { + assert.pass('onShow works for Sidebar'); + loader.unload(); + + let sidebarMI = getSidebarMenuitems(); + for each (let mi in sidebarMI) { + assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar') + assert.equal(mi.getAttribute('checked'), 'false', 'no sidebar menuitem is checked'); + } + assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); + assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing'); + + done(); + } + }) + + assert.pass('showing the sidebar1'); + sidebar.show(); + assert.pass('showing the sidebar2'); + + }); + }); +} + +exports.testClickingACheckedMenuitem = function(assert, done) { + let testName = 'testClickingACheckedMenuitem'; + let window = getMostRecentBrowserWindow(); + let sidebar = WebPanel({ + id: testName, + title: testName, + url: 'data:text/html;charset=utf-8,'+testName, + onShow: function() { + sidebar.once('hide', function() { + assert.pass('clicking the menuitem after the sidebar has shown hides it.'); + sidebar.destroy(); + done(); + }); + let menuitem = window.document.getElementById(makeID(sidebar.id)); + simulateClick(menuitem); + } + }); + + sidebar.show(); +} + +exports.testAddonGlobalDNE = function(assert, done) { + let testName = 'testAddonGlobal'; + let url = 'data:text/html;charset=utf-8,'+encodeURIComponent('<script>window.addEventListener("message", function() window.postMessage({ addon: !!window.addon }, "*"), false)</script>'); + let sidebar = WebPanel({ + id: testName, + title: testName, + url: url + }); + + sidebar.on('attach', function(worker) { + assert.pass('sidebar was attached'); + assert.ok(!!worker, 'attach event has worker'); + + let sidebarXUL = getMostRecentBrowserWindow().document.getElementById('sidebar'); + let window = sidebarXUL.contentDocument.getElementById(WEB_PANEL_BROWSER_ID).contentWindow; + + window.addEventListener('load', function() { + let count = 0; + window.addEventListener('message', function({ data: msg }) { + if (++count != 2) return; + + assert.equal(msg.addon, false, 'the addon global DNE'); + + sidebar.destroy(); + + done(); + }, false); + window.postMessage('', '*'); + }, false); + + }); + + show(sidebar); +} + +require('sdk/test').run(exports); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test.png b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test.png Binary files differnew file mode 100644 index 0000000..5469a50 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/test/test.png |