merge mozilla-inbound to mozilla-central. r=merge a=merge

MozReview-Commit-ID: GUc4LEY8qp4
This commit is contained in:
Sebastian Hengst 2017-09-13 11:27:47 +02:00
commit 1fbe7771e8
1140 changed files with 5696 additions and 118007 deletions

View File

@ -7,7 +7,6 @@ obj*/**
# We ignore all these directories by default, until we get them enabled.
# If you are enabling a directory, please add directory specific exclusions
# below.
addon-sdk/**
chrome/**
config/**
docshell/**

View File

@ -809,7 +809,8 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
// Process relocation list.
for (uint32_t idx = 0; idx < mRelocations.Length(); idx++) {
if (mRelocations[idx]->IsInDocument()) {
// owner should be in a document and have na associated DOM node (docs sometimes don't)
if (mRelocations[idx]->IsInDocument() && mRelocations[idx]->HasOwnContent()) {
mDocument->DoARIAOwnsRelocation(mRelocations[idx]);
}
}

View File

@ -77,7 +77,7 @@ Accessible::IsSearchbox() const
return (roleMapEntry && roleMapEntry->Is(nsGkAtoms::searchbox)) ||
(mContent->IsHTMLElement(nsGkAtoms::input) &&
mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::textInputType, eCaseMatters));
nsGkAtoms::search, eCaseMatters));
}
inline bool

View File

@ -147,3 +147,22 @@ addAccessibleTask(`
testChildrenIds(two, ["a", "b"]);
}
);
addAccessibleTask(`<div id="a"></div><div id="b"></div>`,
async function(browser, accDoc) {
testChildrenIds(accDoc, ["a", "b"]);
let waitFor = {
expected: [[ EVENT_REORDER, e => e.accessible == accDoc ]]
};
await contentSpawnMutation(browser, waitFor, function() {
document.documentElement.style.display = "none";
document.documentElement.getBoundingClientRect();
document.body.setAttribute("aria-owns", "b a");
document.documentElement.remove();
});
testChildrenIds(accDoc, []);
}
);

View File

@ -144,7 +144,7 @@ XULTreeAccessible::Value(nsString& aValue)
void
XULTreeAccessible::Shutdown()
{
if (!mDoc->IsDefunct()) {
if (mDoc && !mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}

View File

@ -277,7 +277,7 @@ NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
void
XULTreeGridRowAccessible::Shutdown()
{
if (!mDoc->IsDefunct()) {
if (mDoc && !mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}

View File

@ -1,29 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
TESTADDONS = source/test/addons
ADDONSRC = $(srcdir)/$(TESTADDONS)
include $(topsrcdir)/config/rules.mk
# This can switch to just zipping the files when native jetpacks land
%.xpi: FORCE
$(PYTHON) $(srcdir)/source/bin/cfx xpi --no-strip-xpi --pkgdir=$(ADDONSRC)/$* --output-file=$@
TEST_FILES = \
$(srcdir)/source/app-extension \
$(srcdir)/source/bin \
$(srcdir)/source/python-lib \
$(srcdir)/source/test \
$(srcdir)/source/package.json \
$(srcdir)/source/mapping.json \
$(NULL)
# Remove this once the test harness uses the APIs built into Firefox
TEST_FILES += $(srcdir)/source/lib
PKG_STAGE = $(DIST)/test-stage
stage-tests-package:: $(TEST_FILES)
$(INSTALL) $^ $(PKG_STAGE)/jetpack

View File

@ -1,122 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
# Makefile.in uses a misc target through test_addons_TARGET.
HAS_MISC_RULE = True
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
DIRS += ['source/test/fixtures']
EXTRA_JS_MODULES.sdk += [
'source/app-extension/bootstrap.js',
]
EXTRA_JS_MODULES.sdk.system += [
'source/modules/system/Startup.js',
]
modules = [
'index.js',
'jetpack-id/index.js',
'method/core.js',
'mozilla-toolkit-versioning/index.js',
'mozilla-toolkit-versioning/lib/utils.js',
'node/os.js',
'sdk/addon/installer.js',
'sdk/addon/window.js',
'sdk/base64.js',
'sdk/clipboard.js',
'sdk/console/plain-text.js',
'sdk/console/traceback.js',
'sdk/core/disposable.js',
'sdk/core/heritage.js',
'sdk/core/namespace.js',
'sdk/core/observer.js',
'sdk/core/promise.js',
'sdk/core/reference.js',
'sdk/deprecated/unit-test-finder.js',
'sdk/deprecated/unit-test.js',
'sdk/deprecated/window-utils.js',
'sdk/event/chrome.js',
'sdk/event/core.js',
'sdk/event/dom.js',
'sdk/event/target.js',
'sdk/event/utils.js',
'sdk/frame/utils.js',
'sdk/io/file.js',
'sdk/lang/functional.js',
'sdk/lang/functional/concurrent.js',
'sdk/lang/functional/core.js',
'sdk/lang/functional/helpers.js',
'sdk/lang/type.js',
'sdk/lang/weak-set.js',
'sdk/net/url.js',
'sdk/platform/xpcom.js',
'sdk/preferences/service.js',
'sdk/preferences/utils.js',
'sdk/private-browsing.js',
'sdk/private-browsing/utils.js',
'sdk/querystring.js',
'sdk/self.js',
'sdk/system.js',
'sdk/system/environment.js',
'sdk/system/events.js',
'sdk/system/globals.js',
'sdk/system/process.js',
'sdk/system/runtime.js',
'sdk/system/unload.js',
'sdk/system/xul-app.js',
'sdk/system/xul-app.jsm',
'sdk/test.js',
'sdk/test/assert.js',
'sdk/test/harness.js',
'sdk/test/loader.js',
'sdk/test/options.js',
'sdk/test/utils.js',
'sdk/timers.js',
'sdk/uri/resource.js',
'sdk/url.js',
'sdk/url/utils.js',
'sdk/util/array.js',
'sdk/util/collection.js',
'sdk/util/deprecate.js',
'sdk/util/dispatcher.js',
'sdk/util/list.js',
'sdk/util/object.js',
'sdk/util/sequence.js',
'sdk/util/uuid.js',
'sdk/window/utils.js',
'sdk/zip/utils.js',
'test.js',
'toolkit/loader.js',
'toolkit/require.js',
]
commonjs = EXTRA_JS_MODULES.commonjs
sources = {}
def get_sources(path):
key = '/'.join(path)
if key in sources:
return sources[key]
source_dir = commonjs
for dir_ in path:
source_dir = source_dir[dir_]
sources[key] = source_dir
return source_dir
for module in modules:
path = module.split('/')[:-1]
source_dir = get_sources(path)
source_dir += ['source/lib/%s' % module]
with Files("**"):
BUG_COMPONENT = ("Add-on SDK", "General")

View File

@ -1,5 +0,0 @@
.gitignore export-ignore
.hgignore export-ignore
.hgtags export-ignore
.gitattributes export-ignore
python-lib/cuddlefish/_version.py export-subst

View File

@ -1,36 +0,0 @@
local.json
python-lib/cuddlefish/app-extension/components/jetpack.xpt
testdocs.tgz
jetpack-sdk-docs.tgz
.test_tmp/
doc/dev-guide/
doc/index.html
doc/modules/
doc/status.md5
packages/*
node_modules
cache
# Python
*.pyc
# OSX
*.DS_Store
# Windows
*Thumbs.db
# Ignore subtrees
# git@github.com:jsantell/jetpack-id.git
lib/jetpack-id/*
!lib/jetpack-id/index.js
!lib/jetpack-id/package.json
# git@github.com:jsantell/mozilla-toolkit-versioning.git
lib/mozilla-toolkit-versioning/*
!lib/mozilla-toolkit-versioning/index.js
!lib/mozilla-toolkit-versioning/lib
lib/mozilla-toolkit-versioning/lib/*
!lib/mozilla-toolkit-versioning/lib/*.js
!lib/mozilla-toolkit-versioning/package.json

View File

@ -1,15 +0,0 @@
syntax: glob
local.json
python-lib/cuddlefish/app-extension/components/jetpack.xpt
testdocs.tgz
jetpack-sdk-docs.tgz
.test_tmp
jetpack-sdk-docs
node_modules
# These should really be in a global .hgignore, but such a thing
# seems ridiculously confusing to set up, so we'll include some
# common intermediate files here.
*.pyc
*~
*.DS_Store

View File

@ -1,64 +0,0 @@
39c45211aa250d43f6e54b776a60ef07a7a4cbb6 jep-31-examples
0120642297b217680e75e68c4005a93b16466001 0.1rc1
1fd7993ff2cec39c5948a1b2535b78c2d4c65858 0.1rc2
530e51d02922ad05fd43e8cf113618068216b0cf 0.1
ed11a9e3ae23aefd56ac88042b9816887d10a04f 0.2rc1
f70ab8998abdce809bda93408435f83648909cdd 0.2rc2
f70ab8998abdce809bda93408435f83648909cdd 0.2
436968c6ec833d9c18a15426be26595a44b79283 0.3rc1
a3b091d29607f0bcecf77fe27801ba901142f1c9 0.3
06031b56312ad7f1880a9620b4d26ce253a23b23 0.3rc2
a3b091d29607f0bcecf77fe27801ba901142f1c9 0.3
4b08c8a8c1eef71ac3aa54e004b68e87049ca56b 0.3
6884e54fd6a1cfa9ec63910c46d2cbf51495b584 0.3rc3
4b08c8a8c1eef71ac3aa54e004b68e87049ca56b 0.3
cd70b7140ec20689255f1248512a1e5b9cf90a32 0.3
d9d733666ca8738e9665ba816d5d12f41fc0d216 0.4rc1
8d2871fc10df16740273f53ef05815310da4b210 0.4
201e60065b1aef23259a71756f93207cffa2abd5 0.4rc2
8d2871fc10df16740273f53ef05815310da4b210 0.4
c0e5bbdcafad4572a5de22e533543bf3330a869e 0.4
201e60065b1aef23259a71756f93207cffa2abd5 0.4rc2
a8dceaefd6f3376b7bc1619cccd854591b76ecc0 0.4rc2
c0e5bbdcafad4572a5de22e533543bf3330a869e 0.4
dfa3bdfedb12d743b5e0ac19d0ecf116b567a0b3 0.4
b519a0848585e2a665a14aac2fb6f15c0a839e6c 0.4rc3
dfa3bdfedb12d743b5e0ac19d0ecf116b567a0b3 0.4
05acdf4987c28d8cc1d5a12d87e71b1445fdd6b7 0.4
04b5afe48d1cee819d9f0af72ed16556a075b67d 0.5rc1
1968150561097bcfeeb28a75801ef881d2fcbbf5 0.5
3236e68e6f2e36353e47f01a9b8acfce56686263 0.5rc2
1968150561097bcfeeb28a75801ef881d2fcbbf5 0.5
0097da78aa23be8b7a5a811c4be0e3e35395af43 0.5
be7016807a69c910ac31ff068a6c2bde0a25c9d4 0.5rc3
0097da78aa23be8b7a5a811c4be0e3e35395af43 0.5
83e97107e4a381b898c780b32e30e48b0e4d37f3 0.5
182a405aa393dbd412e671e8516d2decd8e8d80c 0.6rc1
96799a3d96abfdb1408f9b8e30479668f1feed70 0.6
c5f6cdfa36b2ad33d8017e6844992de0b0a6c0e0 0.6rc2
96799a3d96abfdb1408f9b8e30479668f1feed70 0.6
65c393fbc6af7db79a4a2e903d06b17e90d254bf 0.6
3e747e3e307a4e853d468b03357f96b2172bad37 0.7rc1
b0e97e12eb9115f08127cc447d459f871c5046ed 0.7
37288479d249168668abd60a907620fa7f593128 0.7rc2
b0e97e12eb9115f08127cc447d459f871c5046ed 0.7
db0eabc310619d00ce47372ecaafba7d2539b601 0.7
37288479d249168668abd60a907620fa7f593128 0.7rc2
b90bedb83525d8f32ebb4d3833e8d91efa991b6d 0.7rc2
db0eabc310619d00ce47372ecaafba7d2539b601 0.7
e6ea2e5c5274cbbb0278dc976844dbf51818a95e 0.7
b90bedb83525d8f32ebb4d3833e8d91efa991b6d 0.7rc2
9b978d823509de5d52ca222b9907f72591c68c5a 0.7rc2
e6ea2e5c5274cbbb0278dc976844dbf51818a95e 0.7
cd71e1e77c93adf169b9f38184b1f95d423876ba 0.7
67e3fd285fa955898a2641226c86725365d68b95 0.8rc1
b2f9405db6d74c21601ca9c250887411c837396a 0.8
67e3fd285fa955898a2641226c86725365d68b95 0.8rc1
56e8179ff5b467959ddf33978558d7eb5346ee53 0.8rc1
b2f9405db6d74c21601ca9c250887411c837396a 0.8
51a22a186b1c7d8e7292a5ec9670752dad223ca1 0.8
d150cca77cfef60dee2f2fe7c892fd7fc5ce83c4 0.9rc1
1e106beb57f65fabc32682f277de51a8101c919b 0.9
173d56fa8cc1c5622eae70f1ae88ef789de4722b 0.9rc2
1e106beb57f65fabc32682f277de51a8101c919b 0.9
cde12eefd178d7a0ee7d5e9ae77f3089bcbdc6ec 0.9

View File

@ -1,18 +0,0 @@
local.json
mapping.json
CONTRIBUTING.md
@addon-sdk.xpi
.*
app-extension/
bin/
modules/
node_modules/
examples/
cache/
# Python
python-lib/
*.pyc
# Windows
*Thumbs.db

View File

@ -1,26 +0,0 @@
sudo: false
language: node_js
node_js:
- "0.12"
env:
- JPM_FX_DEBUG=0
- JPM_FX_DEBUG=1
notifications:
irc: "irc.mozilla.org#jetpack"
cache:
directories:
- cache
before_install:
- "export DISPLAY=:99.0"
- "/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 fx-download -g
- npm install gulp -g
- bash bin/fx-download.sh
- export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox
- cd $TRAVIS_BUILD_DIR

View File

@ -1,54 +0,0 @@
## Overview
- Changes should follow the [design guidelines], as well as the [coding style guide]
- All changes need tests
- In order to land, changes need a review by one of the Jetpack reviewers
- Changes may need an API review
- Changes may need a review from a Mozilla platform domain-expert
If you have questions, ask in [#jetpack on IRC][jetpack irc channel] or on the [Jetpack mailing list].
## How to Make Code Contributions
Follow the [standard mozilla contribution guidelines](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Introduction). All contributions and patches should be through Bugzilla.
Pull requests on github are not accepted and new pull requests on github will be rejected.
## Good First Bugs
There is a list of [good first bugs here][good first bugs].
## Reviewers
Changes should be reviewed by someone on the [add-on sdk review team](https://bugzilla.mozilla.org/page.cgi?id=review_suggestions.html#Add-on%20SDK) within Bugzilla.
Others who might be able to help include:
- [@mossop]
- [@gozala]
- [@ZER0]
- [@jsantell]
- [@zombie]
For review of Mozilla platform usage and best practices, ask [@autonome],
[@0c0w3], or [@mossop] to find the domain expert.
For API and developer ergonomics review, ask [@gozala].
[design guidelines]:https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines
[jetpack irc channel]:irc://irc.mozilla.org/#jetpack
[Jetpack mailing list]:http://groups.google.com/group/mozilla-labs-jetpack
[open bugs]:https://bugzilla.mozilla.org/buglist.cgi?quicksearch=product%3ASDK
[make bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general
[test intro]:https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing
[test API]:https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert
[coding style guide]:https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
[Add-on SDK repo]:https://github.com/mozilla/addon-sdk
[GitHub]:https://github.com/
[good first bugs]:https://bugzilla.mozilla.org/buglist.cgi?list_id=7345714&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&query_based_on=jetpack-good-1st-bugs&status_whiteboard_type=allwordssubstr&query_format=advanced&status_whiteboard=[good%20first%20bug]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&product=Add-on%20SDK&known_name=jetpack-good-1st-bugs
[@mossop]:https://github.com/mossop/
[@gozala]:https://github.com/Gozala/
[@ZER0]:https://github.com/ZER0/
[@jsantell]:https://github.com/jsantell
[@zombie]:https://github.com/zombie

View File

@ -1,30 +0,0 @@
The files which make up the SDK are developed by Mozilla and licensed
under the MPL 2.0 (http://mozilla.org/MPL/2.0/), with the exception of the
components listed below, which are made available by their authors under
the licenses listed alongside.
syntaxhighlighter
------------------
doc/static-files/syntaxhighlighter
Made available under the MIT license.
jQuery
------
examples/reddit-panel/data/jquery-1.4.4.min.js
examples/annotator/data/jquery-1.4.2.min.js
Made available under the MIT license.
simplejson
----------
python-lib/simplejson
Made available under the MIT license.
Python Markdown
---------------
python-lib/markdown
Made available under the BSD license.
LibraryDetector
---------------
examples/library-detector/data/library-detector.js
Made available under the MIT license.

View File

@ -1,34 +0,0 @@
# Mozilla Add-on SDK [![Build Status](https://travis-ci.org/mozilla/addon-sdk.png)](https://travis-ci.org/mozilla/addon-sdk)
We suggest that developers of new add-ons [should look at using WebExtensions](https://developer.mozilla.org/en-US/Add-ons/WebExtensions).
Using the Add-on SDK you can create Firefox add-ons using standard Web technologies: JavaScript, HTML, and CSS. The SDK includes JavaScript APIs which you can use to create add-ons, and tools for creating, running, testing, and packaging add-ons.
If you find a problem, please [report the bug here](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK).
## Developing Add-ons
These resources offer some help:
* [Add-on SDK Documentation](https://developer.mozilla.org/en-US/Add-ons/SDK)
* [Community Developed Modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules)
* [Jetpack FAQ](https://wiki.mozilla.org/Jetpack/FAQ)
* [StackOverflow Questions](http://stackoverflow.com/questions/tagged/firefox-addon-sdk)
* [Mailing List](https://wiki.mozilla.org/Jetpack#Mailing_list)
* #jetpack on irc.mozilla.org
## Contributing Code
Please read these two guides if you wish to make some patches to the addon-sdk:
* [Contribute Guide](https://github.com/mozilla/addon-sdk/blob/master/CONTRIBUTING.md)
* [Style Guide](https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide)
## Issues
We use [bugzilla](https://bugzilla.mozilla.org/) as our issue tracker, here are some useful links:
* [File a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK)
* [Open bugs](https://bugzilla.mozilla.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&product=Add-on%20SDK&query_format=advanced&order=priority)
* [Good first bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+first+bug]&&resolution=---&product=Add-on+SDK)
* [Good next bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+next+bug]&&resolution=---&product=Add-on+SDK)

View File

@ -1,11 +0,0 @@
[App]
Vendor=Varma
Name=Test App
Version=1.0
BuildID=20060101
Copyright=Copyright (c) 2009 Atul Varma
ID=xulapp@toolness.com
[Gecko]
MinVersion=1.9.2.0
MaxVersion=2.0.*

View File

@ -1,362 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// @see http://dxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp
'use strict';
// IMPORTANT: Avoid adding any initialization tasks here, if you need to do
// something before add-on is loaded consider addon/runner module instead!
const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
results: Cr, manager: Cm } = Components;
const ioService = Cc['@mozilla.org/network/io-service;1'].
getService(Ci.nsIIOService);
const resourceHandler = ioService.getProtocolHandler('resource').
QueryInterface(Ci.nsIResProtocolHandler);
const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
getService(Ci.mozIJSSubScriptLoader);
const prefService = Cc['@mozilla.org/preferences-service;1'].
getService(Ci.nsIPrefService).
QueryInterface(Ci.nsIPrefBranch);
const appInfo = Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULAppInfo);
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
getService(Ci.nsIVersionComparator);
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
'install', 'uninstall', 'upgrade', 'downgrade' ];
const bind = Function.call.bind(Function.bind);
var loader = null;
var unload = null;
var cuddlefishSandbox = null;
var nukeTimer = null;
var resourceDomains = [];
function setResourceSubstitution(domain, uri) {
resourceDomains.push(domain);
resourceHandler.setSubstitution(domain, uri);
}
// Utility function that synchronously reads local resource from the given
// `uri` and returns content string.
function readURI(uri) {
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(uri, 'UTF-8'),
loadUsingSystemPrincipal: true
});
let stream = channel.open2();
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
createInstance(Ci.nsIConverterInputStream);
cstream.init(stream, 'UTF-8', 0, 0);
let str = {};
let data = '';
let read = 0;
do {
read = cstream.readString(0xffffffff, str);
data += str.value;
} while (read != 0);
cstream.close();
return data;
}
// We don't do anything on install & uninstall yet, but in a future
// we should allow add-ons to cleanup after uninstall.
function install(data, reason) {}
function uninstall(data, reason) {}
function startup(data, reasonCode) {
try {
let reason = REASON[reasonCode];
// URI for the root of the XPI file.
// 'jar:' URI if the addon is packed, 'file:' URI otherwise.
// (Used by l10n module in order to fetch `locale` folder)
let rootURI = data.resourceURI.spec;
// TODO: Maybe we should perform read harness-options.json asynchronously,
// since we can't do anything until 'sessionstore-windows-restored' anyway.
let options = JSON.parse(readURI(rootURI + './harness-options.json'));
let id = options.jetpackID;
let name = options.name;
// Clean the metadata
options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {};
// freeze the permissionss
Object.freeze(options.metadata[name]['permissions']);
// freeze the metadata
Object.freeze(options.metadata[name]);
// Register a new resource 'domain' for this addon which is mapping to
// XPI's `resources` folder.
// Generate the domain name by using jetpack ID, which is the extension ID
// by stripping common characters that doesn't work as a domain name:
let uuidRe =
/^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
let domain = id.
toLowerCase().
replace(/@/g, '-at-').
replace(/\./g, '-dot-').
replace(uuidRe, '$1');
let prefixURI = 'resource://' + domain + '/';
let resourcesURI = ioService.newURI(rootURI + '/resources/');
setResourceSubstitution(domain, resourcesURI);
// Create path to URLs mapping supported by loader.
let paths = {
// Relative modules resolve to add-on package lib
'./': prefixURI + name + '/lib/',
'./tests/': prefixURI + name + '/tests/',
'': 'resource://gre/modules/commonjs/'
};
// Maps addon lib and tests ressource folders for each package
paths = Object.keys(options.metadata).reduce(function(result, name) {
result[name + '/'] = prefixURI + name + '/lib/'
result[name + '/tests/'] = prefixURI + name + '/tests/'
return result;
}, paths);
// We need to map tests folder when we run sdk tests whose package name
// is stripped
if (name == 'addon-sdk')
paths['tests/'] = prefixURI + name + '/tests/';
let useBundledSDK = options['force-use-bundled-sdk'];
if (!useBundledSDK) {
try {
useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK");
}
catch (e) {
// Pref doesn't exist, allow using Firefox shipped SDK
}
}
// Starting with Firefox 21.0a1, we start using modules shipped into firefox
// Still allow using modules from the xpi if the manifest tell us to do so.
// And only try to look for sdk modules in xpi if the xpi actually ship them
if (options['is-sdk-bundled'] &&
(vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) {
// Maps sdk module folders to their resource folder
paths[''] = prefixURI + 'addon-sdk/lib/';
// test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
// so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
// until we no longer support SDK modules in XPI:
paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
}
// Retrieve list of module folder overloads based on preferences in order to
// eventually used a local modules instead of files shipped into Firefox.
let branch = prefService.getBranch('extensions.modules.' + id + '.path');
paths = branch.getChildList('', {}).reduce(function (result, name) {
// Allows overloading of any sub folder by replacing . by / in pref name
let path = name.substr(1).split('.').join('/');
// Only accept overloading folder by ensuring always ending with `/`
if (path) path += '/';
let fileURI = branch.getCharPref(name);
// On mobile, file URI has to end with a `/` otherwise, setSubstitution
// takes the parent folder instead.
if (fileURI[fileURI.length-1] !== '/')
fileURI += '/';
// Maps the given file:// URI to a resource:// in order to avoid various
// failure that happens with file:// URI and be close to production env
let resourcesURI = ioService.newURI(fileURI);
let resName = 'extensions.modules.' + domain + '.commonjs.path' + name;
setResourceSubstitution(resName, resourcesURI);
result[path] = 'resource://' + resName + '/';
return result;
}, paths);
// Make version 2 of the manifest
let manifest = options.manifest;
// Import `cuddlefish.js` module using a Sandbox and bootstrap loader.
let cuddlefishPath = 'loader/cuddlefish.js';
let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath;
if (paths['sdk/']) { // sdk folder has been overloaded
// (from pref, or cuddlefish is still in the xpi)
cuddlefishURI = paths['sdk/'] + cuddlefishPath;
}
else if (paths['']) { // root modules folder has been overloaded
cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath;
}
cuddlefishSandbox = loadSandbox(cuddlefishURI);
let cuddlefish = cuddlefishSandbox.exports;
// Normalize `options.mainPath` so that it looks like one that will come
// in a new version of linker.
let main = options.mainPath;
unload = cuddlefish.unload;
loader = cuddlefish.Loader({
paths: paths,
// modules manifest.
manifest: manifest,
// Add-on ID used by different APIs as a unique identifier.
id: id,
// Add-on name.
name: name,
// Add-on version.
version: options.metadata[name].version,
// Add-on package descriptor.
metadata: options.metadata[name],
// Add-on load reason.
loadReason: reason,
prefixURI: prefixURI,
// Add-on URI.
rootURI: rootURI,
// options used by system module.
// File to write 'OK' or 'FAIL' (exit code emulation).
resultFile: options.resultFile,
// Arguments passed as --static-args
staticArgs: options.staticArgs,
// Option to prevent automatic kill of firefox during tests
noQuit: options.no_quit,
// Add-on preferences branch name
preferencesBranch: options.preferencesBranch,
// Arguments related to test runner.
modules: {
'@test/options': {
iterations: options.iterations,
filter: options.filter,
profileMemory: options.profileMemory,
stopOnError: options.stopOnError,
verbose: options.verbose,
parseable: options.parseable,
checkMemory: options.check_memory,
}
}
});
let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI);
let require = cuddlefish.Require(loader, module);
// Init the 'sdk/webextension' module from the bootstrap addon parameter.
require("sdk/webextension").initFromBootstrapAddonParam(data);
require('sdk/addon/runner').startup(reason, {
loader: loader,
main: main,
prefsURI: rootURI + 'defaults/preferences/prefs.js'
});
} catch (error) {
dump('Bootstrap error: ' +
(error.message ? error.message : String(error)) + '\n' +
(error.stack || error.fileName + ': ' + error.lineNumber) + '\n');
throw error;
}
};
function loadSandbox(uri) {
let proto = {
sandboxPrototype: {
loadSandbox: loadSandbox,
ChromeWorker: ChromeWorker
}
};
let sandbox = Cu.Sandbox(systemPrincipal, proto);
// Create a fake commonjs environnement just to enable loading loader.js
// correctly
sandbox.exports = {};
sandbox.module = { uri: uri, exports: sandbox.exports };
sandbox.require = function (id) {
if (id !== "chrome")
throw new Error("Bootstrap sandbox `require` method isn't implemented.");
return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
CC: bind(CC, Components), components: Components,
ChromeWorker: ChromeWorker });
};
scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
return sandbox;
}
function unloadSandbox(sandbox) {
if (Cu.getClassName(sandbox, true) == "Sandbox")
Cu.nukeSandbox(sandbox);
}
function setTimeout(callback, delay) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback({ notify: callback }, delay,
Ci.nsITimer.TYPE_ONE_SHOT);
return timer;
}
function shutdown(data, reasonCode) {
let reason = REASON[reasonCode];
if (loader) {
unload(loader, reason);
unload = null;
// Don't waste time cleaning up if the application is shutting down
if (reason != "shutdown") {
// Avoid leaking all modules when something goes wrong with one particular
// module. Do not clean it up immediatly in order to allow executing some
// actions on addon disabling.
// We need to keep a reference to the timer, otherwise it is collected
// and won't ever fire.
nukeTimer = setTimeout(nukeModules, 1000);
// Bug 944951 - bootstrap.js must remove the added resource: URIs on unload
resourceDomains.forEach(domain => {
resourceHandler.setSubstitution(domain, null);
})
}
}
};
function nukeModules() {
nukeTimer = null;
// module objects store `exports` which comes from sandboxes
// We should avoid keeping link to these object to avoid leaking sandboxes
for (let key in loader.modules) {
delete loader.modules[key];
}
// Direct links to sandboxes should be removed too
for (let key in loader.sandboxes) {
let sandbox = loader.sandboxes[key];
delete loader.sandboxes[key];
// Bug 775067: From FF17 we can kill all CCW from a given sandbox
unloadSandbox(sandbox);
}
unloadSandbox(loader.sharedGlobalSandbox);
loader = null;
// both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
// `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when
// the addon is unload.
unloadSandbox(cuddlefishSandbox.loaderSandbox);
// Bug 764840: We need to unload cuddlefish otherwise it will stay alive
// and keep a reference to this compartment.
unloadSandbox(cuddlefishSandbox);
cuddlefishSandbox = null;
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>xulapp@toolness.com</em:id>
<em:version>1.0</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>26.0</em:minVersion>
<em:maxVersion>30.0</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Test App</em:name>
<em:description>Harness for tests.</em:description>
<em:creator>Mozilla Corporation</em:creator>
<em:homepageURL></em:homepageURL>
<em:optionsType></em:optionsType>
<em:optionsURL></em:optionsURL>
<em:updateURL></em:updateURL>
</Description>
</RDF>

View File

@ -1,84 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r
fi
if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
PYTHONPATH="$_OLD_PYTHONPATH"
export PYTHONPATH
unset _OLD_PYTHONPATH
unset CUDDLEFISH_ROOT
unset VIRTUAL_ENV
if [ ! "$1" = "nondestructive" ] ; then
# Self destruct!
unset deactivate
fi
}
# unset irrelavent variables
deactivate nondestructive
_OLD_PYTHONPATH="$PYTHONPATH"
_OLD_VIRTUAL_PATH="$PATH"
VIRTUAL_ENV="`pwd`"
if [ "x$OSTYPE" = "xmsys" ] ; then
CUDDLEFISH_ROOT="`pwd -W | sed s,/,\\\\\\\\,g`"
PATH="`pwd`/bin:$PATH"
# msys will convert any env vars with PATH in it to use msys
# form and will unconvert before launching
PYTHONPATH="`pwd -W`/python-lib;$PYTHONPATH"
else
CUDDLEFISH_ROOT="$VIRTUAL_ENV"
PYTHONPATH="$VIRTUAL_ENV/python-lib:$PYTHONPATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
fi
VIRTUAL_ENV="`pwd`"
export CUDDLEFISH_ROOT
export PYTHONPATH
export PATH
_OLD_VIRTUAL_PS1="$PS1"
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
export PS1
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r
fi
python -c "from jetpack_sdk_env import welcome; welcome()"

View File

@ -1,134 +0,0 @@
@echo off
rem This Source Code Form is subject to the terms of the Mozilla Public
rem License, v. 2.0. If a copy of the MPL was not distributed with this
rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
set VIRTUAL_ENV=%~dp0
set VIRTUAL_ENV=%VIRTUAL_ENV:~0,-5%
set CUDDLEFISH_ROOT=%VIRTUAL_ENV%
SET PYTHONKEY=SOFTWARE\Python\PythonCore
rem look for 32-bit windows and python, or 64-bit windows and python
SET PYTHONVERSION=2.7
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
SET PYTHONVERSION=2.6
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
SET PYTHONVERSION=2.5
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
if not defined ProgramFiles(x86) goto win32
rem look for 32-bit python on 64-bit windows
SET PYTHONKEY=SOFTWARE\Wow6432Node\Python\PythonCore
SET PYTHONVERSION=2.7
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
SET PYTHONVERSION=2.6
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
SET PYTHONVERSION=2.5
call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
if "%PYTHONINSTALL%" NEQ "" goto FoundPython
:win32
SET PYTHONVERSION=
set PYTHONKEY=
echo Warning: Failed to find Python installation directory
goto :EOF
:FoundPython
if defined _OLD_PYTHONPATH (
set PYTHONPATH=%_OLD_PYTHONPATH%
)
if not defined PYTHONPATH (
set PYTHONPATH=;
)
set _OLD_PYTHONPATH=%PYTHONPATH%
set PYTHONPATH=%VIRTUAL_ENV%\python-lib;%PYTHONPATH%
if not defined PROMPT (
set PROMPT=$P$G
)
if defined _OLD_VIRTUAL_PROMPT (
set PROMPT=%_OLD_VIRTUAL_PROMPT%
)
set _OLD_VIRTUAL_PROMPT=%PROMPT%
set PROMPT=(%VIRTUAL_ENV%) %PROMPT%
if defined _OLD_VIRTUAL_PATH goto OLDPATH
goto SKIPPATH
:OLDPATH
PATH %_OLD_VIRTUAL_PATH%
:SKIPPATH
set _OLD_VIRTUAL_PATH=%PATH%
PATH %VIRTUAL_ENV%\bin;%PYTHONINSTALL%;%PATH%
set PYTHONKEY=
set PYTHONINSTALL=
set PYTHONVERSION=
set key=
set reg=
set _tokens=
python -c "from jetpack_sdk_env import welcome; welcome()"
GOTO :EOF
:CheckPython
::CheckPython(retVal, key)
::Reads the registry at %2% and checks if a Python exists there.
::Checks both HKLM and HKCU, then checks the executable actually exists.
SET key=%2%
SET "%~1="
SET reg=reg
if defined ProgramFiles(x86) (
rem 32-bit cmd on 64-bit windows
if exist %WINDIR%\sysnative\reg.exe SET reg=%WINDIR%\sysnative\reg.exe
)
rem On Vista+, the last line of output is:
rem (default) REG_SZ the_value
rem (but note the word "default" will be localized.
rem On XP, the last line of output is:
rem <NO NAME>\tREG_SZ\tthe_value
rem (not sure if "NO NAME" is localized or not!)
rem SO: we use ")>" as the tokens to split on, then nuke
rem the REG_SZ and any tabs or spaces.
FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKLM\%key% /ve 2^>NUL`) DO SET "%~1=%%A"
rem Remove the REG_SZ
set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=%
rem Remove tabs (note the literal \t in the next line
set PYTHONINSTALL=%PYTHONINSTALL: =%
rem Remove spaces.
set PYTHONINSTALL=%PYTHONINSTALL: =%
if exist %PYTHONINSTALL%\python.exe goto :EOF
rem It may be a 32bit Python directory built from source, in which case the
rem executable is in the PCBuild directory.
if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF)
rem Or maybe a 64bit build directory.
if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF)
rem And try HKCU
FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKCU\%key% /ve 2^>NUL`) DO SET "%~1=%%A"
set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=%
set PYTHONINSTALL=%PYTHONINSTALL: =%
set PYTHONINSTALL=%PYTHONINSTALL: =%
if exist %PYTHONINSTALL%\python.exe goto :EOF
if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF)
if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF)
rem can't find it here, so arrange to try the next key
set PYTHONINSTALL=
GOTO :EOF

View File

@ -1,66 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This file must be used with "source bin/activate.fish" *from fish*
# you cannot run it directly
# Much of this code is based off of the activate.fish file for the
# virtualenv project. http://ur1.ca/ehmd6
function deactivate -d "Exit addon-sdk and return to normal shell environment"
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_PYTHONPATH"
set -gx PYTHONPATH $_OLD_PYTHONPATH
set -e _OLD_PYTHONPATH
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
functions -e fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
. ( begin
printf "function fish_prompt\n\t#"
functions _old_fish_prompt
end | psub )
functions -e _old_fish_prompt
end
set -e CUDDLEFISH_ROOT
set -e VIRTUAL_ENV
if test "$argv[1]" != "nondestructive"
functions -e deactivate
end
end
# unset irrelavent variables
deactivate nondestructive
set -gx _OLD_PYTHONPATH $PYTHONPATH
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx _OLD_FISH_PROMPT_OVERRIDE "true"
set VIRTUAL_ENV (pwd)
set -gx CUDDLEFISH_ROOT $VIRTUAL_ENV
set -gx PYTHONPATH "$VIRTUAL_ENV/python-lib" $PYTHONPATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# save the current fish_prompt function as the function _old_fish_prompt
. ( begin
printf "function _old_fish_prompt\n\t#"
functions fish_prompt
end | psub )
# with the original prompt function renamed, we can override with our own.
function fish_prompt
printf "(%s)%s%s" (basename "$VIRTUAL_ENV") (set_color normal) (_old_fish_prompt)
return
end
python -c "from jetpack_sdk_env import welcome; welcome()"

View File

@ -1,99 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
$Env:VIRTUAL_ENV = (gl);
$Env:CUDDLEFISH_ROOT = $Env:VIRTUAL_ENV;
# http://stackoverflow.com/questions/5648931/powershell-test-if-registry-value-exists/5652674#5652674
Function Test-RegistryValue {
param(
[Alias("PSPath")]
[Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[String]$Path
,
[Parameter(Position = 1, Mandatory = $true)]
[String]$Name
,
[Switch]$PassThru
)
process {
if (Test-Path $Path) {
$Key = Get-Item -LiteralPath $Path
if ($Key.GetValue($Name, $null) -ne $null) {
if ($PassThru) {
Get-ItemProperty $Path $Name
} else {
$true
}
} else {
$false
}
} else {
$false
}
}
}
$WINCURVERKEY = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion';
$WIN64 = (Test-RegistryValue $WINCURVERKEY 'ProgramFilesDir (x86)');
if($WIN64) {
$PYTHONKEY='HKLM:SOFTWARE\Wow6432Node\Python\PythonCore';
}
else {
$PYTHONKEY='HKLM:SOFTWARE\Python\PythonCore';
}
$Env:PYTHONVERSION = '';
$Env:PYTHONINSTALL = '';
foreach ($version in @('2.6', '2.5', '2.4')) {
if (Test-RegistryValue "$PYTHONKEY\$version\InstallPath" '(default)') {
$Env:PYTHONVERSION = $version;
}
}
if ($Env:PYTHONVERSION) {
$Env:PYTHONINSTALL = (Get-Item "$PYTHONKEY\$version\InstallPath)").'(default)';
}
if ($Env:PYTHONINSTALL) {
$Env:Path += ";$Env:PYTHONINSTALL";
}
if (Test-Path Env:_OLD_PYTHONPATH) {
$Env:PYTHONPATH = $Env:_OLD_PYTHONPATH;
}
else {
$Env:PYTHONPATH = '';
}
$Env:_OLD_PYTHONPATH=$Env:PYTHONPATH;
$Env:PYTHONPATH= "$Env:VIRTUAL_ENV\python-lib;$Env:PYTHONPATH";
if (Test-Path Function:_OLD_VIRTUAL_PROMPT) {
Set-Content Function:Prompt (Get-Content Function:_OLD_VIRTUAL_PROMPT);
}
else {
function global:_OLD_VIRTUAL_PROMPT {}
}
Set-Content Function:_OLD_VIRTUAL_PROMPT (Get-Content Function:Prompt);
function global:prompt { "($Env:VIRTUAL_ENV) $(_OLD_VIRTUAL_PROMPT)"; };
if (Test-Path Env:_OLD_VIRTUAL_PATH) {
$Env:PATH = $Env:_OLD_VIRTUAL_PATH;
}
else {
$Env:_OLD_VIRTUAL_PATH = $Env:PATH;
}
$Env:Path="$Env:VIRTUAL_ENV\bin;$Env:Path"
[System.Console]::WriteLine("Note: this PowerShell SDK activation script is experimental.")
python -c "from jetpack_sdk_env import welcome; welcome()"

View File

@ -1,33 +0,0 @@
#! /usr/bin/env python
# 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/.
import os
import sys
# set the cuddlefish "root directory" for this process if it's not already
# set in the environment
cuddlefish_root = os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0])))
if 'CUDDLEFISH_ROOT' not in os.environ:
os.environ['CUDDLEFISH_ROOT'] = cuddlefish_root
# add our own python-lib path to the python module search path.
python_lib_dir = os.path.join(cuddlefish_root, "python-lib")
if python_lib_dir not in sys.path:
sys.path.insert(0, python_lib_dir)
# now export to env so sub-processes get it too
if 'PYTHONPATH' not in os.environ:
os.environ['PYTHONPATH'] = python_lib_dir
elif python_lib_dir not in os.environ['PYTHONPATH'].split(os.pathsep):
paths = os.environ['PYTHONPATH'].split(os.pathsep)
paths.insert(0, python_lib_dir)
os.environ['PYTHONPATH'] = os.pathsep.join(paths)
import cuddlefish
if __name__ == '__main__':
cuddlefish.run()

View File

@ -1,6 +0,0 @@
@echo off
rem This Source Code Form is subject to the terms of the Mozilla Public
rem License, v. 2.0. If a copy of the MPL was not distributed with this
rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
python "%VIRTUAL_ENV%\bin\cfx" %*

View File

@ -1,23 +0,0 @@
@echo off
rem This Source Code Form is subject to the terms of the Mozilla Public
rem License, v. 2.0. If a copy of the MPL was not distributed with this
rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
if defined _OLD_VIRTUAL_PROMPT (
set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
)
set _OLD_VIRTUAL_PROMPT=
if defined _OLD_VIRTUAL_PATH (
set "PATH=%_OLD_VIRTUAL_PATH%"
)
set _OLD_VIRTUAL_PATH=
if defined _OLD_PYTHONPATH (
set "PYTHONPATH=%_OLD_PYTHONPATH%"
)
set _OLD_PYTHONPATH=
set CUDDLEFISH_ROOT=
:END

View File

@ -1,7 +0,0 @@
#!/bin/sh
if [ "$JPM_FX_DEBUG" = "1" ]; then
fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox --debug
else
fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox
fi

View File

@ -1,14 +0,0 @@
#!/bin/bash
# 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/.
source ./bin/activate
if [ type -P xvfb-run ]
then
xvfb-run cfx $*
else
cfx $*
fi
deactivate

View File

@ -1,364 +0,0 @@
#!/usr/bin/env python
# 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/.
import os
import signal
import threading
import urllib2, urllib
import zipfile
import tarfile
import subprocess
import optparse
import sys, re
#import win32api
class SDK:
def __init__(self):
try:
# Take the current working directory
self.default_path = os.getcwd()
if sys.platform == "win32":
self.mswindows = True
else:
self.mswindows = False
# Take the default home path of the user.
home = os.path.expanduser('~')
# The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0
# If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop"
parser = optparse.OptionParser()
parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip')
parser.add_option('-p', '--path', dest = 'path', default = self.default_path)
parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app')
(options, args) = parser.parse_args()
# Get the URL from the parameter
self.link = options.url
# Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory.
if options.path!=self.default_path:
if self.mswindows:
self.base_path = home + str(options.path).strip() + '\\'
else:
self.base_path = home + str(options.path).strip() + '/'
else:
if self.mswindows:
self.base_path = str(options.path).strip() + '\\'
else:
self.base_path = str(options.path).strip() + '/'
assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue."
print('Your Base path is =' + self.base_path)
# This assignment is not used in this program. It will be used in version 2 of this script.
self.bin = options.binary
# if app or bin is empty, dont pass anything
# Search for the .zip file or tarball file in the URL.
i = self.link.rfind('/')
self.fname = self.link[i+1:]
z = re.search('zip',self.fname,re.I)
g = re.search('gz',self.fname,re.I)
if z:
print 'zip file present in the URL.'
self.zip = True
self.gz = False
elif g:
print 'gz file present in the URL'
self.gz = True
self.zip = False
else:
print 'zip/gz file not present. Check the URL.'
return
print("File name is =" + self.fname)
# Join the base path and the zip/tar file name to crate a complete Local file path.
self.fpath = self.base_path + self.fname
print('Your local file path will be=' + self.fpath)
except AssertionError, e:
print e.args[0]
sys.exit(1)
# Download function - to download the SDK from the URL to the local machine.
def download(self,url,fpath,fname):
try:
# Start the download
print("Downloading...Please be patient!")
urllib.urlretrieve(url,filename = fname)
print('Download was successful.')
except ValueError: # Handles broken URL errors.
print 'The URL is ether broken or the file does not exist. Please enter the correct URL.'
raise
except urllib2.URLError: # Handles URL errors
print '\nURL not correct. Check again!'
raise
# Function to extract the downloaded zipfile.
def extract(self, zipfilepath, extfile):
try:
# Timeout is set to 30 seconds.
timeout = 30
# Change the directory to the location of the zip file.
try:
os.chdir(zipfilepath)
except OSError:
# Will reach here if zip file doesnt exist
print 'O/S Error:' + zipfilepath + 'does not exist'
raise
# Get the folder name of Jetpack to get the exact version number.
if self.zip:
try:
f = zipfile.ZipFile(extfile, "r")
except IOError as (errno, strerror): # Handles file errors
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
raise
list = f.namelist()[0]
temp_name = list.split('/')
print('Folder Name= ' +temp_name[0])
self.folder_name = temp_name[0]
elif self.gz:
try:
f = tarfile.open(extfile,'r')
except IOError as (errno, strerror): # Handles file errors
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
raise
list = f.getnames()[0]
temp_name = list.split('/')
print('Folder Name= ' +temp_name[0])
self.folder_name = temp_name[0]
print ('Starting to Extract...')
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
# timeout, the process is killed.
kill_check = threading.Event()
if self.zip:
# Call the command to unzip the file.
if self.mswindows:
zipfile.ZipFile.extractall(f)
else:
p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True)
pid = p.pid
elif self.gz:
# Call the command to untar the file.
if self.mswindows:
tarfile.TarFile.extractall(f)
else:
p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True)
pid = p.pid
#No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix)
if self.mswindows==False:
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows ))
watch.start()
(stdout, stderr) = p.communicate()
watch.cancel() # if it's still waiting to run
success = not kill_check.isSet()
# Abort process if process fails.
if not success:
raise RuntimeError
kill_check.clear()
print('Extraction Successful.')
except RuntimeError:
print "Ending the program"
sys.exit(1)
except:
print "Error during file extraction: ", sys.exc_info()[0]
raise
# Function to run the cfx testall comands and to make sure the SDK is not broken.
def run_testall(self, home_path, folder_name):
try:
timeout = 500
self.new_dir = home_path + folder_name
try:
os.chdir(self.new_dir)
except OSError:
# Will reach here if the jetpack 0.X directory doesnt exist
print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir
raise
print '\nStarting tests...'
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
# timeout, the process is killed.
kill_check = threading.Event()
# Set the path for the logs. They will be in the parent directory of the Jetpack SDK.
log_path = home_path + 'tests.log'
# Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file.
if self.bin != None:
if self.mswindows:
p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
proc_handle = p._handle
(stdout,stderr) = p.communicate()
else:
p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
pid = p.pid
(stdout,stderr) = p.communicate()
elif self.bin == None:
if self.mswindows:
p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
proc_handle = p._handle
(stdout,stderr) = p.communicate()
else:
p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
pid = p.pid
(stdout,stderr) = p.communicate()
#Write the output to log file
f=open(log_path,"w")
f.write(stdout+stderr)
f.close()
#Watchdog for timeout process
if self.mswindows:
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
else:
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
watch.start()
watch.cancel() # if it's still waiting to run
success = not kill_check.isSet()
if not success:
raise RuntimeError
kill_check.clear()
if p.returncode!=0:
print('\nAll tests were not successful. Check the test-logs in the jetpack directory.')
result_sdk(home_path)
#sys.exit(1)
raise RuntimeError
else:
ret_code=result_sdk(home_path)
if ret_code==0:
print('\nAll tests were successful. Yay \o/ . Running a sample package test now...')
else:
print ('\nThere were errors during the tests.Take a look at logs')
raise RuntimeError
except RuntimeError:
print "Ending the program"
sys.exit(1)
except:
print "Error during the testall command execution:", sys.exc_info()[0]
raise
def package(self, example_dir):
try:
timeout = 30
print '\nNow Running packaging tests...'
kill_check = threading.Event()
# Set the path for the example logs. They will be in the parent directory of the Jetpack SDK.
exlog_path = example_dir + 'test-example.log'
# Subprocess call to test the sample example for packaging.
if self.bin!=None:
if self.mswindows:
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
proc_handle = p._handle
(stdout, stderr) = p.communicate()
else:
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
pid = p.pid
(stdout, stderr) = p.communicate()
elif self.bin==None:
if self.mswindows:
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
proc_handle = p._handle
(stdout, stderr) = p.communicate()
else:
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
pid = p.pid
(stdout, stderr) = p.communicate()
#Write the output to log file
f=open(exlog_path,"w")
f.write(stdout+stderr)
f.close()
#Watch dog for timeout process
if self.mswindows:
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
else:
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
watch.start()
watch.cancel() # if it's still waiting to run
success = not kill_check.isSet()
if not success:
raise RuntimeError
kill_check.clear()
if p.returncode != 0:
print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.')
result_example(example_dir)
raise RuntimeError
else:
ret_code=result_example(example_dir)
if ret_code==0:
print('\nAll tests pass. The SDK is working! Yay \o/')
else:
print ('\nTests passed with warning.Take a look at logs')
sys.exit(1)
except RuntimeError:
print "Ending program"
sys.exit(1)
except:
print "Error during running sample tests:", sys.exc_info()[0]
raise
def result_sdk(sdk_dir):
log_path = sdk_dir + 'tests.log'
print 'Results are logged at:' + log_path
try:
f = open(log_path,'r')
# Handles file errors
except IOError :
print 'I/O error - Cannot open test log at ' + log_path
raise
for line in reversed(open(log_path).readlines()):
if line.strip()=='FAIL':
print ('\nOverall result - FAIL. Look at the test log at '+log_path)
return 1
return 0
def result_example(sdk_dir):
exlog_path = sdk_dir + 'test-example.log'
print 'Sample test results are logged at:' + exlog_path
try:
f = open(exlog_path,'r')
# Handles file errors
except IOError :
print 'I/O error - Cannot open sample test log at ' + exlog_path
raise
#Read the file in reverse and check for the keyword 'FAIL'.
for line in reversed(open(exlog_path).readlines()):
if line.strip()=='FAIL':
print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path)
return 1
return 0
def kill_process(process, kill_check, mswindows):
print '\nProcess Timedout. Killing the process. Please Rerun this script.'
if mswindows:
win32api.TerminateProcess(process, -1)
else:
os.kill(process, signal.SIGKILL)
kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process.
return
if __name__ == "__main__":
obj = SDK()
obj.download(obj.link,obj.fpath,obj.fname)
obj.extract(obj.base_path,obj.fname)
obj.run_testall(obj.base_path,obj.folder_name)
obj.package(obj.base_path)

View File

@ -1,34 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var Promise = require("promise");
var Mocha = require("mocha");
var mocha = new Mocha({
ui: "bdd",
reporter: "spec",
timeout: 900000
});
var isDebug = require("./node-scripts/utils").isDebug;
exports.run = function(type) {
return new Promise(function(resolve) {
type = type || "";
[
(!isDebug && /^(firefox-bin)?$/.test(type)) && require.resolve("../bin/node-scripts/test.firefox-bin"),
(!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"),
(!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"),
(/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
(!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
(!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
].forEach(function(filepath) {
filepath && mocha.addFile(filepath);
})
mocha.run(function(failures) {
resolve(failures);
});
});
}

View File

@ -1,64 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var path = require("path");
var cp = require("child_process");
var fs = require("fs");
var Promise = require("promise");
var patcher = require("patch-editor");
var readParam = require("./utils").readParam;
var isKeeper = /\/addon-sdk\/source/;
function apply(options) {
return clean(options).then(function() {
return new Promise(function(resolve) {
var patch = path.resolve(readParam("patch"));
var proc = cp.spawn("git", ["apply", patch]);
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
proc.on("close", resolve);
});
});
}
exports.apply = apply;
function clean(options) {
return new Promise(function(resolve) {
var patch = path.resolve(readParam("patch"));
if (!patch) {
throw new Error("no --patch was provided.");
}
console.log("Cleaning patch " + patch);
patcher.getChunks({ patch: patch }).then(function(chunks) {
var keepers = [];
for (var i = chunks.length - 1; i >= 0; i--) {
var chunk = chunks[i];
var files = chunk.getFilesChanged();
// check if the file changed is related to the addon-sdk/source directory
var keepIt = files.map(function(file) {
return (isKeeper.test(file));
}).reduce(function(prev, curr) {
return prev || curr;
}, false);
if (keepIt) {
keepers.push(chunk);
}
}
var contents = "\n" + keepers.join("\n") + "\n";
contents = contents.replace(/\/addon-sdk\/source/g, "");
fs.writeFileSync(patch, contents, { encoding: "utf8" });
console.log("Done cleaning patch.");
}).then(resolve).catch(console.error);
});
}
exports.clean = clean;

View File

@ -1,57 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var utils = require("./utils");
var path = require("path");
var fs = require("fs");
var jpm = utils.run;
var readParam = utils.readParam;
var isDebug = utils.isDebug;
var addonsPath = path.join(__dirname, "..", "..", "test", "addons");
var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
var filterPattern = readParam("filter");
describe("jpm test sdk addons", function () {
fs.readdirSync(addonsPath)
.filter(fileFilter.bind(null, addonsPath))
.forEach(function (file) {
it(file, function (done) {
var addonPath = path.join(addonsPath, file);
process.chdir(addonPath);
var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }};
if (process.env.DISPLAY) {
options.env.DISPLAY = process.env.DISPLAY;
}
if (/^e10s/.test(file)) {
options.e10s = true;
}
jpm("run", options).then(done).catch(done);
});
});
});
function fileFilter(root, file) {
var matcher = filterPattern && new RegExp(filterPattern);
if (/^(l10n-properties|simple-prefs|page-mod-debugger)/.test(file)) {
return false;
}
// filter additional add-ons when using debug builds
if (isDebug) {
if (/^(chrome|e10s)/.test(file)) {
return false;
}
}
if (matcher && !matcher.test(file)) {
return false;
}
var stat = fs.statSync(path.join(root, file))
return (stat && stat.isDirectory());
}

View File

@ -1,145 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var createHash = require('crypto').createHash;
var fs = require("fs");
var fsExtra = require("fs-extra")
var path = require("path");
var Promise = require("promise");
var chai = require("chai");
var expect = chai.expect;
var teacher = require("teacher");
var rootURI = path.join(__dirname, "..", "..");
// get a list of words that fail spell check but are still acceptable
var NEW_WORDS = fs.readFileSync(path.join(__dirname, "words.txt")).toString().trim().split("\n");
var CACHE_PATH = path.join(__dirname, "..", "..", "cache", "spellchecks.json");
var CACHE = {};
try {
CACHE = JSON.parse(fs.readFileSync(CACHE_PATH).toString());
}
catch (e) {}
function md5(str) {
return createHash("md5").update(str).digest("utf8");
}
function addCacheHash(hash) {
CACHE[hash] = true;
fsExtra.ensureFileSync(CACHE_PATH);
fsExtra.writeJSONSync(CACHE_PATH, CACHE);
}
describe("Spell Checking", function () {
it("Spellcheck CONTRIBUTING.md", function (done) {
var readme = path.join(rootURI, "CONTRIBUTING.md");
fs.readFile(readme, function (err, data) {
if (err) {
throw err;
}
var text = data.toString();
var hash = md5(text);
// skip this test if we know we have done the
// exact same test with positive results before
if (CACHE[hash]) {
expect(CACHE[hash]).to.be.equal(true);
return done();
}
teacher.check(text, function(err, data) {
expect(err).to.be.equal(null);
var results = data || [];
results = results.filter(function(result) {
if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
return false;
}
// ignore anything that starts with a dash
if (result.string[0] == "-") {
return false;
}
if (!(new RegExp(result.string)).test(text)) {
return false;
}
return true;
})
if (results.length > 0) {
console.log(results);
}
else {
addCacheHash(hash);
}
expect(results.length).to.be.equal(0);
setTimeout(done, 500);
});
});
});
it("Spellcheck README.md", function (done) {
var readme = path.join(rootURI, "README.md");
fs.readFile(readme, function (err, data) {
if (err) {
throw err;
}
var text = data.toString();
var hash = md5(text);
// skip this test if we know we have done the
// exact same test with positive results before
if (CACHE[hash]) {
expect(CACHE[hash]).to.be.equal(true);
return done();
}
teacher.check(text, function(err, data) {
expect(err).to.be.equal(null);
var results = data || [];
results = results.filter(function(result) {
if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
return false;
}
// ignore anything that starts with a dash
if (result.string[0] == "-") {
return false;
}
// ignore anything that we don't find in the original text,
// for some reason "bootstrap.js" becomes "bootstrapjs".
if (!(new RegExp(result.string)).test(text)) {
return false;
}
return true;
})
if (results.length > 0) {
console.log(results);
}
else {
addCacheHash(hash);
}
expect(results.length).to.be.equal(0);
done();
});
});
});
});

View File

@ -1,45 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var utils = require("./utils");
var path = require("path");
var fs = require("fs");
var jpm = utils.run;
var readParam = utils.readParam;
var examplesPath = path.join(__dirname, "..", "..", "examples");
var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
var filterPattern = readParam("filter");
describe("jpm test sdk examples", function () {
fs.readdirSync(examplesPath)
.filter(fileFilter.bind(null, examplesPath))
.forEach(function (file) {
it(file, function (done) {
var addonPath = path.join(examplesPath, file);
process.chdir(addonPath);
var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }};
if (process.env.DISPLAY) {
options.env.DISPLAY = process.env.DISPLAY;
}
jpm("test", options).then(done);
});
});
});
function fileFilter(root, file) {
var matcher = filterPattern && new RegExp(filterPattern);
if (/^(reading-data)/.test(file)) {
return false;
}
if (matcher && !matcher.test(file)) {
return false;
}
var stat = fs.statSync(path.join(root, file))
return (stat && stat.isDirectory());
}

View File

@ -1,37 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var fs = require("fs");
var Promise = require("promise");
var chai = require("chai");
var expect = chai.expect;
var normalizeBinary = require("fx-runner/lib/utils").normalizeBinary;
//var firefox_binary = process.env["JPM_FIREFOX_BINARY"] || normalizeBinary("nightly");
describe("Checking Firefox binary", function () {
it("using matching fx-runner version with jpm", function () {
var sdkPackageJSON = require("../../package.json");
var jpmPackageINI = require("jpm/package.json");
expect(sdkPackageJSON.devDependencies["fx-runner"]).to.be.equal(jpmPackageINI.dependencies["fx-runner"]);
});
it("exists", function (done) {
var useEnvVar = new Promise(function(resolve) {
resolve(process.env["JPM_FIREFOX_BINARY"]);
});
var firefox_binary = process.env["JPM_FIREFOX_BINARY"] ? useEnvVar : normalizeBinary("nightly");
firefox_binary.then(function(path) {
expect(path).to.be.ok;
fs.exists(path, function (exists) {
expect(exists).to.be.ok;
done();
});
})
});
});

View File

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var fs = require("fs");
var path = require("path");
var Promise = require("promise");
var chai = require("chai");
var expect = chai.expect;
var ini = require("./update-ini");
var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
var packageINI = path.resolve("./test/jetpack-package.ini");
describe("Checking ini files", function () {
it("Check test/addons/jetpack-addon.ini", function (done) {
fs.readFile(addonINI, function (err, data) {
if (err) {
throw err;
}
// filter comments
var text = data.toString().split("\n").filter(function(line) {
return !/^\s*#/.test(line);
}).join("\n");
var expected = "";
ini.makeAddonIniContent()
.then(function(contents) {
expected = contents;
setTimeout(function end() {
expect(text.trim()).to.be.equal(expected.trim());
done();
});
});
});
});
it("Check test/jetpack-package.ini", function (done) {
fs.readFile(packageINI, function (err, data) {
if (err) {
throw err;
}
// filter comments
var text = data.toString().split("\n").filter(function(line) {
return !/^\s*#/.test(line);
}).join("\n");
var expected = "";
ini.makePackageIniContent()
.then(function(contents) {
expected = contents;
setTimeout(function end() {
expect(text.trim()).to.be.equal(expected.trim());
done();
});
});
});
});
});

View File

@ -1,28 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var utils = require("./utils");
var readParam = utils.readParam;
var path = require("path");
var fs = require("fs");
var jpm = utils.run;
var sdk = path.join(__dirname, "..", "..");
var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
var filterPattern = readParam("filter");
describe("jpm test sdk modules", function () {
it("SDK Modules", function (done) {
process.chdir(sdk);
var options = { cwd: sdk, env: { JPM_FIREFOX_BINARY: binary } };
if (process.env.DISPLAY) {
options.env.DISPLAY = process.env.DISPLAY;
}
options.filter = filterPattern;
jpm("test", options, process).then(done);
});
});

View File

@ -1,141 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var path = require("path");
var cp = require("child_process");
var fs = require("fs");
var Promise = require("promise");
var parser = require("ini-parser");
var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
var addonsDir = path.resolve("./test/addons/");
var packageINI = path.resolve("./test/jetpack-package.ini");
var packageDir = path.resolve("./test/");
var packageIgnorables = [ "addons", "preferences" ];
var packageSupportFiles = [
"fixtures.js",
"test-context-menu.html",
"util.js"
]
function updateAddonINI() {
return new Promise(function(resolve) {
console.log("Start updating " + addonINI);
makeAddonIniContent().
then(function(contents) {
fs.writeFileSync(addonINI, contents, { encoding: "utf8" });
console.log("Done updating " + addonINI);
resolve();
});
})
}
exports.updateAddonINI = updateAddonINI;
function makeAddonIniContent() {
return new Promise(function(resolve) {
var data = parser.parse(fs.readFileSync(addonINI, { encoding: "utf8" }).toString());
var result = {};
fs.readdir(addonsDir, function(err, files) {
// get a list of folders
var folders = files.filter(function(file) {
return fs.statSync(path.resolve(addonsDir, file)).isDirectory();
}).sort();
// copy any related data from the existing ini
folders.forEach(function(folder) {
var oldData = data[folder + ".xpi"];
result[folder] = oldData ? oldData : {};
});
// build a new ini file
var contents = [];
Object.keys(result).sort().forEach(function(key) {
contents.push("[" + key + ".xpi]");
Object.keys(result[key]).forEach(function(dataKey) {
contents.push(dataKey + " = " + result[key][dataKey]);
});
});
contents = contents.join("\n") + "\n";
return resolve(contents);
});
});
}
exports.makeAddonIniContent = makeAddonIniContent;
function makePackageIniContent() {
return new Promise(function(resolve) {
var data = parser.parse(fs.readFileSync(packageINI, { encoding: "utf8" }).toString());
var result = {};
fs.readdir(packageDir, function(err, files) {
// get a list of folders
var folders = files.filter(function(file) {
var ignore = (packageIgnorables.indexOf(file) >= 0);
var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
return (isDir && !ignore);
}).sort();
// get a list of "test-"" files
var files = files.filter(function(file) {
var ignore = !/^test\-.*\.js$/i.test(file);
var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
return (!isDir && !ignore);
}).sort();
// get a list of the support files
var support_files = packageSupportFiles.map(function(file) {
return " " + file;
});
folders.forEach(function(folder) {
support_files.push(" " + folder + "/**");
});
support_files = support_files.sort();
// copy any related data from the existing ini
files.forEach(function(file) {
var oldData = data[file];
result[file] = oldData ? oldData : {};
});
// build a new ini file
var contents = [
"[DEFAULT]",
"support-files ="
];
support_files.forEach(function(support_file) {
contents.push(support_file);
});
contents.push("");
Object.keys(result).sort().forEach(function(key) {
contents.push("[" + key + "]");
Object.keys(result[key]).forEach(function(dataKey) {
contents.push(dataKey + " = " + result[key][dataKey]);
});
});
contents = contents.join("\n") + "\n";
return resolve(contents);
});
});
}
exports.makePackageIniContent = makePackageIniContent;
function updatePackageINI() {
return new Promise(function(resolve) {
console.log("Start updating " + packageINI);
makeAddonIniContent().
then(function(contents) {
fs.writeFileSync(packageINI, contents, { encoding: "utf8" });
console.log("Done updating " + packageINI);
resolve();
});
})
}
exports.updatePackageINI = updatePackageINI;

View File

@ -1,104 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var _ = require("lodash");
var path = require("path");
var child_process = require("child_process");
var jpm = require.resolve("../../node_modules/jpm/bin/jpm");
var Promise = require("promise");
var chai = require("chai");
var expect = chai.expect;
var assert = chai.assert;
var DEFAULT_PROCESS = process;
var sdk = path.join(__dirname, "..", "..");
var prefsPath = path.join(sdk, "test", "preferences", "test-preferences.js");
var e10sPrefsPath = path.join(sdk, "test", "preferences", "test-e10s-preferences.js");
var OUTPUT_FILTERS = [
/[^\n\r]+WARNING\: NS_ENSURE_SUCCESS\(rv, rv\) failed[^\n]+\n\r?/
];
var isDebug = (process.env["JPM_FX_DEBUG"] == "1");
exports.isDebug = isDebug;
function spawn (cmd, options) {
options = options || {};
var env = _.extend({}, options.env, process.env);
if (isDebug) {
env["MOZ_QUIET"] = 1;
}
var e10s = options.e10s || false;
return child_process.spawn("node", [
jpm, cmd, "-v", "--tbpl",
"--prefs", e10s ? e10sPrefsPath : prefsPath,
"-o", sdk,
"-f", options.filter || ""
], {
cwd: options.cwd || tmpOutputDir,
env: env
});
}
exports.spawn = spawn;
function run (cmd, options, p) {
return new Promise(function(resolve) {
var output = [];
var proc = spawn(cmd, options);
proc.stderr.pipe(process.stderr);
proc.stdout.on("data", function (data) {
for (var i = OUTPUT_FILTERS.length - 1; i >= 0; i--) {
if (OUTPUT_FILTERS[i].test(data)) {
return null;
}
}
output.push(data);
return null;
});
if (p) {
proc.stdout.pipe(p.stdout);
}
else if (!isDebug) {
proc.stdout.pipe(DEFAULT_PROCESS.stdout);
}
else {
proc.stdout.on("data", function (data) {
data = (data || "") + "";
if (/TEST-/.test(data)) {
DEFAULT_PROCESS.stdout.write(data.replace(/[\s\n]+$/, "") + "\n");
}
});
}
proc.on("close", function(code) {
var out = output.join("");
var buildDisplayed = /Build \d+/.test(out);
var noTests = /No tests were run/.test(out);
var hasSuccess = /All tests passed!/.test(out);
var hasFailure = /There were test failures\.\.\./.test(out);
if (noTests || hasFailure || !hasSuccess || code != 0) {
DEFAULT_PROCESS.stdout.write(out);
}
expect(code).to.equal(hasFailure ? 1 : 0);
expect(buildDisplayed).to.equal(true);
expect(hasFailure).to.equal(false);
expect(hasSuccess).to.equal(true);
expect(noTests).to.equal(false);
resolve();
});
});
}
exports.run = run;
function readParam(name) {
var index = process.argv.indexOf("--" + name)
return index >= 0 && process.argv[index + 1]
}
exports.readParam = readParam;

View File

@ -1,11 +0,0 @@
addon-sdk
github
stackoverflow
bugzilla
irc
jsantell
mossop
gozala
zer0
autonome
0c0w3

View File

@ -1,3 +0,0 @@
# Actor REPL
Simple REPL for a Firefox debugging protocol.

File diff suppressed because one or more lines are too long

View File

@ -1,264 +0,0 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
.cm-tab { display: inline-block; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
visibility: hidden;
border-right: none;
width: 0;
}
.CodeMirror-focused div.CodeMirror-cursor {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursor {
visibility: hidden;
}
}

View File

@ -1,147 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html>
<head>
<link rel="stylesheet" href="./codemirror.css">
<link rel="stylesheet" href="./main.css">
<script src="./codemirror-compressed.js"></script>
<views>
<section class="task cm-s-default">
<pre class="request "></pre>
<pre class="response"><span class="one"></span><span class="two"></span><span class="three"></span></pre>
</section>
</views>
</head>
<body>
<pre class="input"></pre>
</body>
<script>
function debounce(fn, ms) {
var id;
return function(...args) {
clearTimeout(id);
id = setTimeout(fn, ms, ...args);
};
}
function Try(fn) {
return function(...args) {
try { return fn(...args); }
catch (error) { return null; }
};
}
var parse = Try(JSON.parse);
var CommandHistory = {
init: function() {
this._state = {};
this._state.els = document.querySelectorAll("body > section.task > .request");
this._state.idx = this._state.els.length;
},
get prev() {
if (!!this._state.els && this._state.idx > 0) {
this._state.idx--;
return this._state.els[this._state.idx].textContent;
}
return "";
},
get next() {
if (!!this._state.els && this._state.idx < this._state.els.length-1) {
this._state.idx++;
return this._state.els[this._state.idx].textContent;
}
return "";
}
}
function cmdHistory(fn, editor) {
editor.setValue(fn());
document.querySelector(".input").scrollIntoView();
}
var cmdHistoryNext = cmdHistory.bind(null, () => CommandHistory.next);
var cmdHistoryBack = cmdHistory.bind(null, () => CommandHistory.prev);
function send(editor) {
var input = editor.getWrapperElement().parentNode;
var code = editor.getValue().trim();
var packet = parse(code);
if (packet) {
var task = document.querySelector("views .task").cloneNode(true);
var request = task.querySelector(".request");
var response = task.querySelector(".response");
input.parentNode.insertBefore(task, input);
CodeMirror.runMode(JSON.stringify(packet, 2, 2),
"application/json",
request);
response.classList.add("pending");
editor.setValue("");
document.querySelector(".input").scrollIntoView();
port.postMessage(packet);
}
}
var editor = CodeMirror(document.querySelector(".input"), {
autofocus: true,
mode: "application/json",
matchBrackets: true,
value: '{"to": "root", "type": "requestTypes"}',
extraKeys: {"Cmd-Enter": send,
"Ctrl-Enter": send,
"Cmd-Down": cmdHistoryNext,
"Ctrl-Down": cmdHistoryNext,
"Cmd-Up": cmdHistoryBack,
"Ctrl-Up": cmdHistoryBack}
});
editor.on("change", debounce(function(editor) {
var input = editor.getWrapperElement().parentNode;
if (parse(editor.getValue().trim())) {
input.classList.remove("invalid");
} else {
input.classList.add("invalid");
}
}, 800));
</script>
<script>
window.addEventListener("message", event => {
window.port = event.ports[0];
port.onmessage = onMessage;
});
var onMessage = (event) => {
var packet = event.data;
var code = JSON.stringify(packet, 2, 2);
var input = document.querySelector(".input");
var response = document.querySelector(".task .response.pending");
if (!response) {
message = document.querySelector("views .task").cloneNode(true);
response = message.querySelector(".response");
response.classList.add("message");
input.parentNode.insertBefore(message, input);
}
if (packet.error) {
response.classList.add("error");
}
CodeMirror.runMode(code, "application/json", response);
response.classList.remove("pending");
document.querySelector(".input").scrollIntoView();
CommandHistory.init();
};
</script>
</html>

View File

@ -1,117 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
body
{
position: absolute;
width: 100%;
margin: 0;
padding: 0;
background: white;
}
pre
{
margin: 0;
}
section
{
border-top: 1px solid rgba(150, 150, 150, 0.5);
}
.CodeMirror {
height: auto;
}
.CodeMirror-scroll {
overflow-y: hidden;
overflow-x: auto;
}
.request,
.response,
.input
{
border-left: 5px solid;
padding-left: 10px;
}
.request:not(:empty),
.response.pending
{
padding: 5px;
}
.input
{
padding-left: 6px;
border-color: lightgreen;
}
.input.invalid
{
border-color: orange;
}
.request
{
border-color: lightgrey;
}
.response
{
border-color: grey;
}
.response.error
{
border-color: red;
}
.response.message
{
border-color: lightblue;
}
.response .one,
.response .two,
.response .three
{
width: 0;
height: auto;
}
.response.pending .one,
.response.pending .two,
.response.pending .three
{
width: 10px;
height: 10px;
background-color: rgba(150, 150, 150, 0.5);
border-radius: 100%;
display: inline-block;
animation: bouncedelay 1.4s infinite ease-in-out;
/* Prevent first frame from flickering when animation starts */
animation-fill-mode: both;
}
.response.pending .one
{
animation-delay: -0.32s;
}
.response.pending .two
{
animation-delay: -0.16s;
}
@keyframes bouncedelay {
0%, 80%, 100% {
transform: scale(0.0);
} 40% {
transform: scale(1.0);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1,37 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Panel } = require("dev/panel");
const { Tool } = require("dev/toolbox");
const { Class } = require("sdk/core/heritage");
const REPLPanel = Class({
extends: Panel,
label: "Actor REPL",
tooltip: "Firefox debugging protocol REPL",
icon: "./robot.png",
url: "./index.html",
setup: function({debuggee}) {
this.debuggee = debuggee;
},
dispose: function() {
this.debuggee = null;
},
onReady: function() {
console.log("repl panel document is interactive");
this.debuggee.start();
this.postMessage("RDP", [this.debuggee]);
},
onLoad: function() {
console.log("repl panel document is fully loaded");
}
});
exports.REPLPanel = REPLPanel;
const replTool = new Tool({
panels: { repl: REPLPanel }
});

View File

@ -1,10 +0,0 @@
{
"name": "actor-repl",
"id": "@actor-repl",
"title": "Actor REPL",
"description": "Actor REPL",
"version": "0.0.1",
"author": "Irakli Gozalishvili",
"main": "./index.js",
"license": "MPL-2.0"
}

View File

@ -1,10 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
exports.testMain = function(assert) {
assert.pass("TODO: Write some tests.");
};
require("sdk/test").run(exports);

View File

@ -1,816 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(exports) {
"use strict";
var describe = Object.getOwnPropertyDescriptor;
var Class = fields => {
var constructor = fields.constructor || function() {};
var ancestor = fields.extends || Object;
var descriptor = {};
for (var key of Object.keys(fields))
descriptor[key] = describe(fields, key);
var prototype = Object.create(ancestor.prototype, descriptor);
constructor.prototype = prototype;
prototype.constructor = constructor;
return constructor;
};
var bus = function Bus() {
var parser = new DOMParser();
return parser.parseFromString("<EventTarget/>", "application/xml").documentElement;
}();
var GUID = new WeakMap();
GUID.id = 0;
var guid = x => GUID.get(x);
var setGUID = x => {
GUID.set(x, ++ GUID.id);
};
var Emitter = Class({
extends: EventTarget,
constructor: function() {
this.setupEmitter();
},
setupEmitter: function() {
setGUID(this);
},
addEventListener: function(type, listener, capture) {
bus.addEventListener(type + "@" + guid(this),
listener, capture);
},
removeEventListener: function(type, listener, capture) {
bus.removeEventListener(type + "@" + guid(this),
listener, capture);
}
});
function dispatch(target, type, data) {
var event = new MessageEvent(type + "@" + guid(target), {
bubbles: true,
cancelable: false,
data: data
});
bus.dispatchEvent(event);
}
var supervisedWorkers = new WeakMap();
var supervised = supervisor => {
if (!supervisedWorkers.has(supervisor)) {
supervisedWorkers.set(supervisor, new Map());
supervisor.connection.addActorPool(supervisor);
}
return supervisedWorkers.get(supervisor);
};
var Supervisor = Class({
extends: Emitter,
constructor: function(...params) {
this.setupEmitter(...params);
this.setupSupervisor(...params);
},
Supervisor: function(connection) {
this.connection = connection;
},
/**
* Return the parent pool for this client.
*/
supervisor: function() {
return this.connection.poolFor(this.actorID);
},
/**
* Override this if you want actors returned by this actor
* to belong to a different actor by default.
*/
marshallPool: function() { return this; },
/**
* Add an actor as a child of this pool.
*/
supervise: function(actor) {
if (!actor.actorID)
actor.actorID = this.connection.allocID(actor.actorPrefix ||
actor.typeName);
supervised(this).set(actor.actorID, actor);
return actor;
},
/**
* Remove an actor as a child of this pool.
*/
abandon: function(actor) {
supervised(this).delete(actor.actorID);
},
// true if the given actor ID exists in the pool.
has: function(actorID) {
return supervised(this).has(actorID);
},
// Same as actor, should update debugger connection to use 'actor'
// and then remove this.
get: function(actorID) {
return supervised(this).get(actorID);
},
actor: function(actorID) {
return supervised(this).get(actorID);
},
isEmpty: function() {
return supervised(this).size === 0;
},
/**
* For getting along with the debugger server pools, should be removable
* eventually.
*/
cleanup: function() {
this.destroy();
},
destroy: function() {
var supervisor = this.supervisor();
if (supervisor)
supervisor.abandon(this);
for (var actor of supervised(this).values()) {
if (actor !== this) {
var destroy = actor.destroy;
// Disconnect destroy while we're destroying in case of (misbehaving)
// circular ownership.
if (destroy) {
actor.destroy = null;
destroy.call(actor);
actor.destroy = destroy;
}
}
}
this.connection.removeActorPool(this);
supervised(this).clear();
}
});
var mailbox = new WeakMap();
var clientRequests = new WeakMap();
var inbox = client => mailbox.get(client).inbox;
var outbox = client => mailbox.get(client).outbox;
var requests = client => clientRequests.get(client);
var Receiver = Class({
receive: function(packet) {
if (packet.error)
this.reject(packet.error);
else
this.resolve(this.read(packet));
}
});
var Connection = Class({
constructor: function() {
// Queue of the outgoing messages.
this.outbox = [];
// Map of pending requests.
this.pending = new Map();
this.pools = new Set();
},
isConnected: function() {
return !!this.port
},
connect: function(port) {
this.port = port;
port.addEventListener("message", this);
port.start();
this.flush();
},
addPool: function(pool) {
this.pools.add(pool);
},
removePool: function(pool) {
this.pools.delete(pool);
},
poolFor: function(id) {
for (let pool of this.pools.values()) {
if (pool.has(id))
return pool;
}
},
get: function(id) {
var pool = this.poolFor(id);
return pool && pool.get(id);
},
disconnect: function() {
this.port.stop();
this.port = null;
for (var request of this.pending.values()) {
request.catch(new Error("Connection closed"));
}
this.pending.clear();
var requests = this.outbox.splice(0);
for (var request of request) {
requests.catch(new Error("Connection closed"));
}
},
handleEvent: function(event) {
this.receive(event.data);
},
flush: function() {
if (this.isConnected()) {
for (var request of this.outbox) {
if (!this.pending.has(request.to)) {
this.outbox.splice(this.outbox.indexOf(request), 1);
this.pending.set(request.to, request);
this.send(request.packet);
}
}
}
},
send: function(packet) {
this.port.postMessage(packet);
},
request: function(packet) {
return new Promise(function(resolve, reject) {
this.outbox.push({
to: packet.to,
packet: packet,
receive: resolve,
catch: reject
});
this.flush();
});
},
receive: function(packet) {
var { from, type, why } = packet;
var receiver = this.pending.get(from);
if (!receiver) {
console.warn("Unable to handle received packet", data);
} else {
this.pending.delete(from);
if (packet.error)
receiver.catch(packet.error);
else
receiver.receive(packet);
}
this.flush();
},
});
/**
* Base class for client-side actor fronts.
*/
var Client = Class({
extends: Supervisor,
constructor: function(from=null, detail=null, connection=null) {
this.Client(from, detail, connection);
},
Client: function(form, detail, connection) {
this.Supervisor(connection);
if (form) {
this.actorID = form.actor;
this.from(form, detail);
}
},
connect: function(port) {
this.connection = new Connection(port);
},
actorID: null,
actor: function() {
return this.actorID;
},
/**
* Update the actor from its representation.
* Subclasses should override this.
*/
form: function(form) {
},
/**
* Method is invokeid when packet received constitutes an
* event. By default such packets are demarshalled and
* dispatched on the client instance.
*/
dispatch: function(packet) {
},
/**
* Method is invoked when packet is returned in response to
* a request. By default respond delivers response to a first
* request in a queue.
*/
read: function(input) {
throw new TypeError("Subclass must implement read method");
},
write: function(input) {
throw new TypeError("Subclass must implement write method");
},
respond: function(packet) {
var [resolve, reject] = requests(this).shift();
if (packet.error)
reject(packet.error);
else
resolve(this.read(packet));
},
receive: function(packet) {
if (this.isEventPacket(packet)) {
this.dispatch(packet);
}
else if (requests(this).length) {
this.respond(packet);
}
else {
this.catch(packet);
}
},
send: function(packet) {
Promise.cast(packet.to || this.actor()).then(id => {
packet.to = id;
this.connection.send(packet);
})
},
request: function(packet) {
return this.connection.request(packet);
}
});
var Destructor = method => {
return function(...args) {
return method.apply(this, args).then(result => {
this.destroy();
return result;
});
};
};
var Profiled = (method, id) => {
return function(...args) {
var start = new Date();
return method.apply(this, args).then(result => {
var end = new Date();
this.telemetry.add(id, +end - start);
return result;
});
};
};
var Method = (request, response) => {
return response ? new BidirectionalMethod(request, response) :
new UnidirecationalMethod(request);
};
var UnidirecationalMethod = request => {
return function(...args) {
var packet = request.write(args, this);
this.connection.send(packet);
return Promise.resolve(void(0));
};
};
var BidirectionalMethod = (request, response) => {
return function(...args) {
var packet = request.write(args, this);
return this.connection.request(packet).then(packet => {
return response.read(packet, this);
});
};
};
Client.from = ({category, typeName, methods, events}) => {
var proto = {
constructor: function(...args) {
this.Client(...args);
},
extends: Client,
name: typeName
};
methods.forEach(({telemetry, request, response, name, oneway, release}) => {
var [reader, writer] = oneway ? [, new Request(request)] :
[new Request(request), new Response(response)];
var method = new Method(request, response);
var profiler = telemetry ? new Profiler(method) : method;
var destructor = release ? new Destructor(profiler) : profiler;
proto[name] = destructor;
});
return Class(proto);
};
var defineType = (client, descriptor) => {
var type = void(0)
if (typeof(descriptor) === "string") {
if (name.indexOf(":") > 0)
type = makeCompoundType(descriptor);
else if (name.indexOf("#") > 0)
type = new ActorDetail(descriptor);
else if (client.specification[descriptor])
type = makeCategoryType(client.specification[descriptor]);
} else {
type = makeCategoryType(descriptor);
}
if (type)
client.types.set(type.name, type);
else
throw TypeError("Invalid type: " + descriptor);
};
var makeCompoundType = name => {
var index = name.indexOf(":");
var [baseType, subType] = [name.slice(0, index), parts.slice(1)];
return baseType === "array" ? new ArrayOf(subType) :
baseType === "nullable" ? new Maybe(subType) :
null;
};
var makeCategoryType = (descriptor) => {
var { category } = descriptor;
return category === "dict" ? new Dictionary(descriptor) :
category === "actor" ? new Actor(descriptor) :
null;
};
var typeFor = (client, type="primitive") => {
if (!client.types.has(type))
defineType(client, type);
return client.types.get(type);
};
var Client = Class({
constructor: function() {
},
setupTypes: function(specification) {
this.specification = specification;
this.types = new Map();
},
read: function(input, type) {
return typeFor(this, type).read(input, this);
},
write: function(input, type) {
return typeFor(this, type).write(input, this);
}
});
var Type = Class({
get name() {
return this.category ? this.category + ":" + this.type :
this.type;
},
read: function(input, client) {
throw new TypeError("`Type` subclass must implement `read`");
},
write: function(input, client) {
throw new TypeError("`Type` subclass must implement `write`");
}
});
var Primitve = Class({
extends: Type,
constuctor: function(type) {
this.type = type;
},
read: function(input, client) {
return input;
},
write: function(input, client) {
return input;
}
});
var Maybe = Class({
extends: Type,
category: "nullable",
constructor: function(type) {
this.type = type;
},
read: function(input, client) {
return input === null ? null :
input === void(0) ? void(0) :
client.read(input, this.type);
},
write: function(input, client) {
return input === null ? null :
input === void(0) ? void(0) :
client.write(input, this.type);
}
});
var ArrayOf = Class({
extends: Type,
category: "array",
constructor: function(type) {
this.type = type;
},
read: function(input, client) {
return input.map($ => client.read($, this.type));
},
write: function(input, client) {
return input.map($ => client.write($, this.type));
}
});
var Dictionary = Class({
exteds: Type,
category: "dict",
get name() { return this.type; },
constructor: function({typeName, specializations}) {
this.type = typeName;
this.types = specifications;
},
read: function(input, client) {
var output = {};
for (var key in input) {
output[key] = client.read(input[key], this.types[key]);
}
return output;
},
write: function(input, client) {
var output = {};
for (var key in input) {
output[key] = client.write(value, this.types[key]);
}
return output;
}
});
var Actor = Class({
exteds: Type,
category: "actor",
get name() { return this.type; },
constructor: function({typeName}) {
this.type = typeName;
},
read: function(input, client, detail) {
var id = value.actor;
var actor = void(0);
if (client.connection.has(id)) {
return client.connection.get(id).form(input, detail, client);
} else {
actor = Client.from(detail, client);
actor.actorID = id;
client.supervise(actor);
}
},
write: function(input, client, detail) {
if (input instanceof Actor) {
if (!input.actorID) {
client.supervise(input);
}
return input.from(detail);
}
return input.actorID;
}
});
var Root = Client.from({
"category": "actor",
"typeName": "root",
"methods": [
{"name": "listTabs",
"request": {},
"response": {
}
},
{"name": "listAddons"
},
{"name": "echo",
},
{"name": "protocolDescription",
}
]
});
var ActorDetail = Class({
extends: Actor,
constructor: function(name, actor, detail) {
this.detail = detail;
this.actor = actor;
},
read: function(input, client) {
this.actor.read(input, client, this.detail);
},
write: function(input, client) {
this.actor.write(input, client, this.detail);
}
});
var registeredLifetimes = new Map();
var LifeTime = Class({
extends: Type,
category: "lifetime",
constructor: function(lifetime, type) {
this.name = lifetime + ":" + type.name;
this.field = registeredLifetimes.get(lifetime);
},
read: function(input, client) {
return this.type.read(input, client[this.field]);
},
write: function(input, client) {
return this.type.write(input, client[this.field]);
}
});
var primitive = new Primitve("primitive");
var string = new Primitve("string");
var number = new Primitve("number");
var boolean = new Primitve("boolean");
var json = new Primitve("json");
var array = new Primitve("array");
var TypedValue = Class({
extends: Type,
constructor: function(name, type) {
this.TypedValue(name, type);
},
TypedValue: function(name, type) {
this.name = name;
this.type = type;
},
read: function(input, client) {
return this.client.read(input, this.type);
},
write: function(input, client) {
return this.client.write(input, this.type);
}
});
var Return = Class({
extends: TypedValue,
constructor: function(type) {
this.type = type
}
});
var Argument = Class({
extends: TypedValue,
constructor: function(...args) {
this.Argument(...args);
},
Argument: function(index, type) {
this.index = index;
this.TypedValue("argument[" + index + "]", type);
},
read: function(input, client, target) {
return target[this.index] = client.read(input, this.type);
}
});
var Option = Class({
extends: Argument,
constructor: function(...args) {
return this.Argument(...args);
},
read: function(input, client, target, name) {
var param = target[this.index] || (target[this.index] = {});
param[name] = input === void(0) ? input : client.read(input, this.type);
},
write: function(input, client, name) {
var value = input && input[name];
return value === void(0) ? value : client.write(value, this.type);
}
});
var Request = Class({
extends: Type,
constructor: function(template={}) {
this.type = template.type;
this.template = template;
this.params = findPlaceholders(template, Argument);
},
read: function(packet, client) {
var args = [];
for (var param of this.params) {
var {placeholder, path} = param;
var name = path[path.length - 1];
placeholder.read(getPath(packet, path), client, args, name);
// TODO:
// args[placeholder.index] = placeholder.read(query(packet, path), client);
}
return args;
},
write: function(input, client) {
return JSON.parse(JSON.stringify(this.template, (key, value) => {
return value instanceof Argument ? value.write(input[value.index],
client, key) :
value;
}));
}
});
var Response = Class({
extends: Type,
constructor: function(template={}) {
this.template = template;
var [x] = findPlaceholders(template, Return);
var {placeholder, path} = x;
this.return = placeholder;
this.path = path;
},
read: function(packet, client) {
var value = query(packet, this.path);
return this.return.read(value, client);
},
write: function(input, client) {
return JSON.parse(JSON.stringify(this.template, (key, value) => {
return value instanceof Return ? value.write(input) :
input
}));
}
});
// Returns array of values for the given object.
var values = object => Object.keys(object).map(key => object[key]);
// Returns [key, value] pairs for the given object.
var pairs = object => Object.keys(object).map(key => [key, object[key]]);
// Queries an object for the field nested with in it.
var query = (object, path) => path.reduce((object, entry) => object && object[entry],
object);
var Root = Client.from({
"category": "actor",
"typeName": "root",
"methods": [
{
"name": "echo",
"request": {
"string": { "_arg": 0, "type": "string" }
},
"response": {
"string": { "_retval": "string" }
}
},
{
"name": "listTabs",
"request": {},
"response": { "_retval": "tablist" }
},
{
"name": "actorDescriptions",
"request": {},
"response": { "_retval": "json" }
}
],
"events": {
"tabListChanged": {}
}
});
var Tab = Client.from({
"category": "dict",
"typeName": "tab",
"specifications": {
"title": "string",
"url": "string",
"outerWindowID": "number",
"console": "console",
"inspectorActor": "inspector",
"callWatcherActor": "call-watcher",
"canvasActor": "canvas",
"webglActor": "webgl",
"webaudioActor": "webaudio",
"styleSheetsActor": "stylesheets",
"styleEditorActor": "styleeditor",
"storageActor": "storage",
"gcliActor": "gcli",
"memoryActor": "memory",
"eventLoopLag": "eventLoopLag",
"trace": "trace", // missing
}
});
var tablist = Client.from({
"category": "dict",
"typeName": "tablist",
"specializations": {
"selected": "number",
"tabs": "array:tab"
}
});
})(this);

View File

@ -1,50 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html>
<head>
<script src="resource://sdk/dev/volcan.js"></script>
<script src="./task.js"></script>
</head>
<body>
</body>
<script>
const wait = (target, type, capture) => new Promise((resolve, reject) => {
const listener = event => {
target.removeEventListener(type, listener, capture);
resolve(event);
};
target.addEventListener(type, listener, capture);
});
const display = message =>
document.body.innerHTML += message + "<br/>";
Task.spawn(function*() {
var event = yield wait(window, "message");
var port = event.ports[0];
display("Port received");
var root = yield volcan.connect(port);
display("Connected to a debugger");
var message = yield root.echo("hello")
display("Received echo for: " + message);
var list = yield root.listTabs();
display("You have " + list.tabs.length + " open tabs");
var activeTab = list.tabs[list.selected];
display("Your active tab url is: " + activeTab.url);
var sheets = yield activeTab.styleSheetsActor.getStyleSheets();
display("Page in active tab has " + sheets.length + " stylesheets");
});
</script>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,28 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(exports) {
"use strict";
const spawn = (task, ...args) => {
return new Promise((resolve, reject) => {
try {
const routine = task(...args);
const raise = error => routine.throw(error);
const step = data => {
const { done, value } = routine.next(data);
if (done)
resolve(value);
else
Promise.resolve(value).then(step, raise);
}
step();
} catch(error) {
reject(error);
}
});
}
exports.spawn = spawn;
})(Task = {});

View File

@ -1,33 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Panel } = require("dev/panel");
const { Tool } = require("dev/toolbox");
const { Class } = require("sdk/core/heritage");
const LadybugPanel = Class({
extends: Panel,
label: "Ladybug",
tooltip: "Debug client example",
icon: "./plugin.png",
url: "./index.html",
setup: function({debuggee}) {
this.debuggee = debuggee;
},
dispose: function() {
delete this.debuggee;
},
onReady: function() {
this.debuggee.start();
this.postMessage("RDP", [this.debuggee]);
},
});
exports.LadybugPanel = LadybugPanel;
const ladybug = new Tool({
panels: { ladybug: LadybugPanel }
});

View File

@ -1,10 +0,0 @@
{
"name": "debug-client",
"id": "@debug-client",
"title": "Debug client",
"description": "Example debug client",
"version": "0.0.1",
"author": "Irakli Gozalishvili",
"main": "./index.js",
"license": "MPL-2.0"
}

View File

@ -1,10 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
exports.testMain = function(assert) {
assert.pass("TODO: Write some tests.");
};
require("sdk/test").run(exports);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,7 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html><body>
<h1>Hello World</h1>
</body></html>

View File

@ -1,53 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var self = require("sdk/self");
var { Panel } = require("sdk/panel");
var { ToggleButton } = require("sdk/ui");
function replaceMom(html) {
return html.replace("World", "Mom");
}
exports.replaceMom = replaceMom;
exports.main = function(options, callbacks) {
console.log("My ID is " + self.id);
// Load the sample HTML into a string.
var helloHTML = self.data.load("sample.html");
// Let's now modify it...
helloHTML = replaceMom(helloHTML);
// ... and then create a panel that displays it.
var myPanel = Panel({
contentURL: "data:text/html," + helloHTML,
onHide: handleHide
});
// Create a widget that displays the image. We'll attach the panel to it.
// When you click the widget, the panel will pop up.
var button = ToggleButton({
id: "test-widget",
label: "Mom",
icon: './mom.png',
onChange: handleChange
});
// If you run cfx with --static-args='{"quitWhenDone":true}' this program
// will automatically quit Firefox when it's done.
if (options.staticArgs.quitWhenDone)
callbacks.quit();
}
function handleChange(state) {
if (state.checked) {
myPanel.show({ position: button });
}
}
function handleHide() {
button.state('window', { checked: false });
}

View File

@ -1,9 +0,0 @@
{
"name": "reading-data",
"description": "A demonstration of reading bundled data.",
"keywords": [],
"author": "Brian Warner",
"contributors": [],
"license": "MPL-2.0",
"id": "reading-data-example@jetpack.mozillalabs.com"
}

View File

@ -1,25 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var m = require("main");
var self = require("sdk/self");
exports.testReplace = function(test) {
var input = "Hello World";
var output = m.replaceMom(input);
test.assertEqual(output, "Hello Mom");
var callbacks = { quit: function() {} };
// Make sure it doesn't crash...
m.main({ staticArgs: {} }, callbacks);
};
exports.testID = function(test) {
// The ID is randomly generated during tests, so we cannot compare it against
// anything in particular. Just assert that it is not empty.
test.assert(self.id.length > 0);
test.assertEqual(self.data.url("sample.html"),
"resource://reading-data-example-at-jetpack-dot-mozillalabs-dot-com/reading-data/data/sample.html");
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,9 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html>
<head>
</head>
<body>
</body>
</html>

View File

@ -1,7 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#devtools-theme-box {
background-color: red !important;
}

View File

@ -1,37 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Tool } = require("dev/toolbox");
const { Class } = require("sdk/core/heritage");
const { onEnable, onDisable } = require("dev/theme/hooks");
const { Theme, LightTheme } = require("dev/theme");
/**
* This object represents a new theme registered within the Toolbox.
* You can activate it by clicking on "My Light Theme" theme option
* in the Options panel.
* Note that the new theme derives styles from built-in Light theme.
*/
const MyTheme = Theme({
name: "mytheme",
label: "My Light Theme",
styles: [LightTheme, "./theme.css"],
onEnable: function(window, oldTheme) {
console.log("myTheme.onEnable; method override " +
window.location.href);
},
onDisable: function(window, newTheme) {
console.log("myTheme.onDisable; method override " +
window.location.href);
},
});
// Registration
const mytheme = new Tool({
name: "My Tool",
themes: { mytheme: MyTheme }
});

View File

@ -1,10 +0,0 @@
{
"name": "theme",
"title": "theme",
"id": "theme@jetpack",
"description": "How to create new theme for devtools",
"author": "Jan Odvarko",
"license": "MPL-2.0",
"version": "0.1.0",
"main": "lib/main"
}

View File

@ -1,10 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
exports.testMain = function(assert) {
assert.pass("TODO: Write some tests.");
};
require("sdk/test").run(exports);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,21 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html>
<body>
<button id=post>post!</button>
</body>
<script>
window.addEventListener("message", event => {
console.log("Document message", event, event.data, event.source !== window && event.source === window.parent);
});
window.addEventListener("click", event => {
if (event.target.id === "post") {
console.log("click!")
window.parent.postMessage("ping!", "*");
}
});
console.log(window.parent === window)
</script>
</html>

View File

@ -1,48 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Toolbar } = require("sdk/ui/toolbar");
const { Frame } = require("sdk/ui/frame");
const { ActionButton } = require("sdk/ui/button/action");
var button = new ActionButton({
id: "button",
label: "send!",
icon: "./favicon.ico",
onClick: () => {
frame.postMessage({
hello: "content"
});
}
});
var frame = new Frame({
url: "./index.html",
onAttach: () => {
console.log("frame was attached");
},
onReady: () => {
console.log("frame document was loaded");
},
onLoad: () => {
console.log("frame load complete");
},
onMessage: (event) => {
console.log("got message from frame content", event);
if (event.data === "ping!")
event.source.postMessage("pong!", event.source.origin);
}
});
var toolbar = new Toolbar({
items: [frame],
title: "Addon Demo",
hidden: false,
onShow: () => {
console.log("toolbar was shown");
},
onHide: () => {
console.log("toolbar was hidden");
}
});

View File

@ -1,12 +0,0 @@
{
"name": "toolbar-api",
"title": "Toolbar API",
"main": "./lib/main.js",
"description": "a toolbar api example",
"author": "",
"license": "MPL-2.0",
"version": "0.1.1",
"engines": {
"firefox": ">=27.0 <=30.0"
}
}

View File

@ -1,10 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
exports.testMain = function(assert) {
assert.pass("TODO: Write some tests.");
};
require("sdk/test").run(exports);

View File

@ -1,39 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var data = require('sdk/self').data;
var tabs = require('sdk/tabs');
var { notify } = require('sdk/notifications');
var { ActionButton, ToggleButton } = require('sdk/ui');
var icon = 'chrome://mozapps/skin/extensions/extensionGeneric.svg';
exports.icon = icon;
// your basic action button
var action = ActionButton({
id: 'test-action-button',
label: 'Action Button',
icon: icon,
onClick: function (state) {
notify({
title: "Action!",
text: "This notification was triggered from an action button!",
});
}
});
exports.actionButton = action;
var toggle = ToggleButton({
id: 'test-toggle-button',
label: 'Toggle Button',
icon: icon,
onClick: function (state) {
notify({
title: "Toggled!",
text: "The current state of the button is " + state.checked,
});
}
});
exports.toggleButton = toggle;

View File

@ -1,10 +0,0 @@
{
"name": "ui-button-apis",
"title": "Australis Button API Examples",
"id": "ui-button-apis@mozilla.org",
"description": "A Button API example",
"author": "jeff@canuckistani.ca (Jeff Griffiths | @canuckistani)",
"license": "MPL-2.0",
"version": "0.1.1",
"main": "./lib/main.js"
}

View File

@ -1,29 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
try {
// CFX use case..
var { actionButton, toggleButton, icon } = require("main");
}
catch (e) {
// JPM use case..
let mainURI = "../lib/main";
var { actionButton, toggleButton, icon } = require(mainURI);
}
var self = require("sdk/self");
exports.testActionButton = function(assert) {
assert.equal(actionButton.id, "test-action-button", "action button id is correct");
assert.equal(actionButton.label, "Action Button", "action button label is correct");
assert.equal(actionButton.icon, icon, "action button icon is correct");
}
exports.testToggleButton = function(assert) {
assert.equal(toggleButton.id, "test-toggle-button", "toggle button id is correct");
assert.equal(toggleButton.label, "Toggle Button", "toggle button label is correct");
assert.equal(toggleButton.icon, icon, "toggle button icon is correct");
}
require("sdk/test").run(exports);

View File

@ -1,44 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var gulp = require('gulp');
var patch = require("./bin/node-scripts/apply-patch");
var ini = require("./bin/node-scripts/update-ini");
gulp.task('test', function(done) {
require("./bin/jpm-test").run().then(done);
});
gulp.task('test:addons', function(done) {
require("./bin/jpm-test").run("addons").catch(console.error).then(done);
});
gulp.task('test:docs', function(done) {
require("./bin/jpm-test").run("docs").catch(console.error).then(done);
});
gulp.task('test:examples', function(done) {
require("./bin/jpm-test").run("examples").catch(console.error).then(done);
});
gulp.task('test:modules', function(done) {
require("./bin/jpm-test").run("modules").catch(console.error).then(done);
});
gulp.task('test:ini', function(done) {
require("./bin/jpm-test").run("ini").catch(console.error).then(done);
});
gulp.task('test:firefox-bin', function(done) {
require("./bin/jpm-test").run("firefox-bin").catch(console.error).then(done);
});
gulp.task('patch:clean', function(done) {
patch.clean().catch(console.error).then(done);
});
gulp.task('patch:apply', function(done) {
patch.apply().catch(console.error).then(done);
});

View File

@ -1,5 +0,0 @@
language: node_js
node_js:
- 0.4
- 0.5
- 0.6

View File

@ -1,14 +0,0 @@
# Changes
## 1.0.1 / 2013-05-01
- Update method library version.
## 1.0.0 / 2012-11-09
- Test integration for browsers.
- New method library.
## 0.0.1 / 2012-10-22
- Initial release

View File

@ -1,18 +0,0 @@
Copyright 2012 Irakli Gozalishvili. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@ -1,70 +0,0 @@
# diffpatcher
[![Build Status](https://secure.travis-ci.org/Gozala/diffpatcher.png)](http://travis-ci.org/Gozala/diffpatcher)
[![Browser support](https://ci.testling.com/Gozala/diffpatcher.png)](http://ci.testling.com/Gozala/diffpatcher)
Diffpatcher is a small library that lets you treat hashes as if they were
git repositories.
## diff
Diff function that takes two hashes and returns delta hash.
```js
var diff = require("diffpatcher/diff")
diff({ a: { b: 1 }, c: { d: 2 } }, // hash#1
{ a: { e: 3 }, c: { d: 4 } }) // hash#2
// => { // delta
// a: {
// b: null, // -
// e: 3 // +
// },
// c: {
// d: 4 // ±
// }
// }
```
As you can see from the example above `delta` makes no real distinction between
proprety upadate and property addition. Try to think of additions as an update
from `undefined` to whatever it's being updated to.
## patch
Patch fuction takes a `hash` and a `delta` and returns a new `hash` which is
just like orginial but with delta applied to it. Let's apply delta from the
previous example to the first hash from the same example
```js
var patch = require("diffpatcher/patch")
patch({ a: { b: 1 }, c: { d: 2 } }, // hash#1
{ // delta
a: {
b: null, // -
e: 3 // +
},
c: {
d: 4 // ±
}
})
// => { a: { e: 3 }, c: { d: 4 } } // hash#2
```
That's about it really, just diffing hashes and applying thes diffs on them.
### rebase
And as Linus mentioned everything in git can be expressed with `rebase`, that
also pretty much the case for `diffpatcher`. `rebase` takes `target` hash,
and rebases `parent` onto it with `diff` applied.
## Install
npm install diffpatcher

View File

@ -1,54 +0,0 @@
{
"name": "diffpatcher",
"id": "diffpatcher",
"version": "1.2.0",
"description": "Utilities for diff-ing & patch-ing hashes",
"keywords": [
"diff", "patch", "rebase", "hash", "changes", "versions"
],
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
"homepage": "https://github.com/Gozala/diffpatcher",
"repository": {
"type": "git",
"url": "https://github.com/Gozala/diffpatcher.git",
"web": "https://github.com/Gozala/diffpatcher"
},
"bugs": {
"url": "http://github.com/Gozala/diffpatcher/issues/"
},
"dependencies": {
"method": "~2.0.0"
},
"devDependencies": {
"test": "~0.x.0",
"phantomify": "~0.x.0",
"retape": "~0.x.0",
"tape": "~0.1.5"
},
"main": "./index.js",
"scripts": {
"test": "npm run test-node && npm run test-browser",
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/common.js",
"test-node": "node ./test/common.js",
"test-tap": "node ./test/tap.js"
},
"testling": {
"files": "test/tap.js",
"browsers": [
"ie/9..latest",
"chrome/25..latest",
"firefox/20..latest",
"safari/6..latest",
"opera/11.0..latest",
"iphone/6..latest",
"ipad/6..latest",
"android-browser/4.2..latest"
]
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/Gozala/diffpatcher/License.md"
}
]
}

View File

@ -1,3 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

View File

@ -1,53 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Takes parsed `package.json` manifest and returns
* valid add-on id for it.
*/
function getID(manifest) {
manifest = manifest || {};
if (manifest.id) {
if (typeof manifest.id !== "string") {
return null;
}
// If manifest.id is already valid (as domain or GUID), use it
if (isValidAOMName(manifest.id)) {
return manifest.id;
}
// Otherwise, this ID is invalid so return `null`
return null;
}
// If no `id` defined, turn `name` into a domain ID,
// as we transition to `name` being an id, similar to node/npm, but
// append a '@' to make it compatible with Firefox requirements
if (manifest.name) {
if (typeof manifest.name !== "string") {
return null;
}
var modifiedName = "@" + manifest.name;
return isValidAOMName(modifiedName) ? modifiedName : null;
}
// If no `id` or `name` property, return null as this manifest
// is invalid
return null;
}
module.exports = getID;
/**
* Regex taken from XPIProvider.jsm in the Addon Manager to validate proper
* IDs that are able to be used.
* http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#209
*/
function isValidAOMName (s) {
return /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i.test(s || "");
}

View File

@ -1,28 +0,0 @@
{
"name": "jetpack-id",
"version": "1.0.0",
"description": "Creates an ID from a Firefox Jetpack manifest",
"main": "index.js",
"repository": {
"type": "git",
"url": "http://github.com/jsantell/jetpack-id"
},
"author": {
"name": "Jordan Santell",
"url": "http://github.com/jsantell"
},
"license": "MPL-2.0",
"scripts": {
"test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
},
"keywords": [
"jetpack",
"addon",
"mozilla",
"firefox"
],
"devDependencies": {
"mocha": "*",
"chai": "*"
}
}

View File

@ -1,5 +0,0 @@
language: node_js
node_js:
- 0.4
- 0.5
- 0.6

View File

@ -1,55 +0,0 @@
# Changes
## 1.0.2 / 2012-12-26
- Delegate to polymorphic methods from `.define` and `.implement` so, they
can be overidden.
## 1.0.1 / 2012-11-11
- Fix issues with different `Error` types as they all inherit from
`Error`.
## 1.0.0 / 2012-11-09
- Add browser test integration.
- Fix cross-browser incompatibilities & test failures.
- Add support for host objects.
- Add optional `hint` argument for method to ease debugging.
- Remove default implementation at definition time.
## 0.1.1 / 2012-10-15
- Fix regression causing custom type implementation to be stored on objects.
## 0.1.0 / 2012-10-15
- Remove dependency on name module.
- Implement fallback for engines that do not support ES5.
- Add support for built-in type extensions without extending their prototypes.
- Make API for default definitions more intuitive.
Skipping type argument now defines default:
isFoo.define(function(value) {
return false
})
- Make exposed `define` and `implement` polymorphic.
- Removed dev dependency on swank-js.
- Primitive types `string, number, boolean` no longer inherit method
implementations from `Object`.
## 0.0.3 / 2012-07-17
- Remove module boilerplate
## 0.0.2 / 2012-06-26
- Name changes to make it less conflicting with other library conventions.
- Expose function version of `define` & `implement` methods.
- Expose `Null` and `Undefined` object holding implementations for an
associated types.
## 0.0.1 / 2012-06-25
- Initial release

View File

@ -1,18 +0,0 @@
Copyright 2012 Irakli Gozalishvili. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@ -1,117 +0,0 @@
# method
[![Build Status](https://secure.travis-ci.org/Gozala/method.png)](http://travis-ci.org/Gozala/method)
Library provides an API for defining polymorphic methods that dispatch on the
first argument type. This provides a powerful way for decouple abstraction
interface definition from an actual implementation per type, without risks
of interference with other libraries.
### Motivation
- Provide a high-performance, dynamic polymorphism construct as an
alternative to existing object methods that does not provides any
mechanics for guarding against name conflicts.
- Allow independent extension of types, and implementations of methods
on types, by different parties.
## Install
npm install method
## Use
```js
var method = require("method")
// Define `isWatchable` method that can be implemented for any type.
var isWatchable = method("isWatchable")
// If you call it on any object it will
// throw as nothing implements that method yet.
//isWatchable({}) // => Exception: method is not implemented
// If you define private method on `Object.prototype`
// all objects will inherit it.
Object.prototype[isWatchable] = function() {
return false;
}
isWatchable({}) // => false
// Although `isWatchable` property above will be enumerable and there for
// may damage some assumbtions made by other libraries. There for it"s
// recomended to use built-in helpers methods that will define extension
// without breaking assumbtions made by other libraries:
isWatchable.define(Object, function() { return false })
// There are primitive types in JS that won"t inherit methods from Object:
isWatchable(null) // => Exception: method is not implemented
// One could either implement methods for such types:
isWatchable.define(null, function() { return false })
isWatchable.define(undefined, function() { return false })
// Or simply define default implementation:
isWatchable.define(function() { return false })
// Alternatively default implementation may be provided at creation:
isWatchable = method(function() { return false })
// Method dispatches on an first argument type. That allows us to create
// new types with an alternative implementations:
function Watchable() {}
isWatchable.define(Watchable, function() { return true })
// This will make all `Watchable` instances watchable!
isWatchable(new Watchable()) // => true
// Arbitrary objects can also be extended to implement given method. For example
// any object can simply made watchable:
function watchable(object) {
return isWatchable.implement(objct, function() { return true })
}
isWatchable(watchable({})) // => true
// Full protocols can be defined with such methods:
var observers = "observers@" + module.filename
var watchers = method("watchers")
var watch = method("watch")
var unwatch = method("unwatch")
watchers.define(Watchable, function(target) {
return target[observers] || (target[observers] = [])
})
watch.define(Watchable, function(target, watcher) {
var observers = watchers(target)
if (observers.indexOf(watcher) < 0) observers.push(watcher)
return target
})
unwatch.define(Watchable, function(target, watcher) {
var observers = watchers(target)
var index = observers.indexOf(watcher)
if (observers.indexOf(watcher) >= 0) observers.unshift(watcher)
return target
})
// Define type Port that inherits form Watchable
function Port() {}
Port.prototype = Object.create(Watchable.prototype)
var emit = method("emit")
emit.define(Port, function(port, message) {
watchers(port).slice().forEach(function(watcher) {
watcher(message)
})
})
var p = new Port()
watch(p, console.log)
emit(p, "hello world") // => info: "hello world"
```

View File

@ -1,225 +0,0 @@
"use strict";
var defineProperty = Object.defineProperty || function(object, name, property) {
object[name] = property.value
return object
}
// Shortcut for `Object.prototype.toString` for faster access.
var typefy = Object.prototype.toString
// Map to for jumping from typeof(value) to associated type prefix used
// as a hash in the map of builtin implementations.
var types = { "function": "Object", "object": "Object" }
// Array is used to save method implementations for the host objects in order
// to avoid extending them with non-primitive values that could cause leaks.
var host = []
// Hash map is used to save method implementations for builtin types in order
// to avoid extending their prototypes. This also allows to share method
// implementations for types across diff contexts / frames / compartments.
var builtin = {}
function Primitive() {}
function ObjectType() {}
ObjectType.prototype = new Primitive()
function ErrorType() {}
ErrorType.prototype = new ObjectType()
var Default = builtin.Default = Primitive.prototype
var Null = builtin.Null = new Primitive()
var Void = builtin.Void = new Primitive()
builtin.String = new Primitive()
builtin.Number = new Primitive()
builtin.Boolean = new Primitive()
builtin.Object = ObjectType.prototype
builtin.Error = ErrorType.prototype
builtin.EvalError = new ErrorType()
builtin.InternalError = new ErrorType()
builtin.RangeError = new ErrorType()
builtin.ReferenceError = new ErrorType()
builtin.StopIteration = new ErrorType()
builtin.SyntaxError = new ErrorType()
builtin.TypeError = new ErrorType()
builtin.URIError = new ErrorType()
function Method(hint) {
/**
Private Method is a callable private name that dispatches on the first
arguments same named Method:
method(object, ...rest) => object[method](...rest)
Optionally hint string may be provided that will be used in generated names
to ease debugging.
## Example
var foo = Method()
// Implementation for any types
foo.define(function(value, arg1, arg2) {
// ...
})
// Implementation for a specific type
foo.define(BarType, function(bar, arg1, arg2) {
// ...
})
**/
// Create an internal unique name if `hint` is provided it is used to
// prefix name to ease debugging.
var name = (hint || "") + "#" + Math.random().toString(32).substr(2)
function dispatch(value) {
// Method dispatches on type of the first argument.
// If first argument is `null` or `void` associated implementation is
// looked up in the `builtin` hash where implementations for built-ins
// are stored.
var type = null
var method = value === null ? Null[name] :
value === void(0) ? Void[name] :
// Otherwise attempt to use method with a generated private
// `name` that is supposedly in the prototype chain of the
// `target`.
value[name] ||
// Otherwise assume it's one of the built-in type instances,
// in which case implementation is stored in a `builtin` hash.
// Attempt to find a implementation for the given built-in
// via constructor name and method name.
((type = builtin[(value.constructor || "").name]) &&
type[name]) ||
// Otherwise assume it's a host object. For host objects
// actual method implementations are stored in the `host`
// array and only index for the implementation is stored
// in the host object's prototype chain. This avoids memory
// leaks that otherwise could happen when saving JS objects
// on host object.
host[value["!" + name] || void(0)] ||
// Otherwise attempt to lookup implementation for builtins by
// a type of the value. This basically makes sure that all
// non primitive values will delegate to an `Object`.
((type = builtin[types[typeof(value)]]) && type[name])
// If method implementation for the type is still not found then
// just fallback for default implementation.
method = method || Default[name]
// If implementation is still not found (which also means there is no
// default) just throw an error with a descriptive message.
if (!method) throw TypeError("Type does not implements method: " + name)
// If implementation was found then just delegate.
return method.apply(method, arguments)
}
// Make `toString` of the dispatch return a private name, this enables
// method definition without sugar:
//
// var method = Method()
// object[method] = function() { /***/ }
dispatch.toString = function toString() { return name }
// Copy utility methods for convenient API.
dispatch.implement = implementMethod
dispatch.define = defineMethod
return dispatch
}
// Create method shortcuts form functions.
var defineMethod = function defineMethod(Type, lambda) {
return define(this, Type, lambda)
}
var implementMethod = function implementMethod(object, lambda) {
return implement(this, object, lambda)
}
// Define `implement` and `define` polymorphic methods to allow definitions
// and implementations through them.
var implement = Method("implement")
var define = Method("define")
function _implement(method, object, lambda) {
/**
Implements `Method` for the given `object` with a provided `implementation`.
Calling `Method` with `object` as a first argument will dispatch on provided
implementation.
**/
return defineProperty(object, method.toString(), {
enumerable: false,
configurable: false,
writable: false,
value: lambda
})
}
function _define(method, Type, lambda) {
/**
Defines `Method` for the given `Type` with a provided `implementation`.
Calling `Method` with a first argument of this `Type` will dispatch on
provided `implementation`. If `Type` is a `Method` default implementation
is defined. If `Type` is a `null` or `undefined` `Method` is implemented
for that value type.
**/
// Attempt to guess a type via `Object.prototype.toString.call` hack.
var type = Type && typefy.call(Type.prototype)
// If only two arguments are passed then `Type` is actually an implementation
// for a default type.
if (!lambda) Default[method] = Type
// If `Type` is `null` or `void` store implementation accordingly.
else if (Type === null) Null[method] = lambda
else if (Type === void(0)) Void[method] = lambda
// If `type` hack indicates built-in type and type has a name us it to
// store a implementation into associated hash. If hash for this type does
// not exists yet create one.
else if (type !== "[object Object]" && Type.name) {
var Bulitin = builtin[Type.name] || (builtin[Type.name] = new ObjectType())
Bulitin[method] = lambda
}
// If `type` hack indicates an object, that may be either object or any
// JS defined "Class". If name of the constructor is `Object`, assume it's
// built-in `Object` and store implementation accordingly.
else if (Type.name === "Object")
builtin.Object[method] = lambda
// Host objects are pain!!! Every browser does some crazy stuff for them
// So far all browser seem to not implement `call` method for host object
// constructors. If that is a case here, assume it's a host object and
// store implementation in a `host` array and store `index` in the array
// in a `Type.prototype` itself. This avoids memory leaks that could be
// caused by storing JS objects on a host objects.
else if (Type.call === void(0)) {
var index = host.indexOf(lambda)
if (index < 0) index = host.push(lambda) - 1
// Prefix private name with `!` so it can be dispatched from the method
// without type checks.
implement("!" + method, Type.prototype, index)
}
// If Got that far `Type` is user defined JS `Class`. Define private name
// as hidden property on it's prototype.
else
implement(method, Type.prototype, lambda)
}
// And provided implementations for a polymorphic equivalents.
_define(define, _define)
_define(implement, _implement)
// Define exports on `Method` as it's only thing being exported.
Method.implement = implement
Method.define = define
Method.Method = Method
Method.method = Method
Method.builtin = builtin
Method.host = host
module.exports = Method

View File

@ -1,41 +0,0 @@
{
"name": "method",
"id": "method",
"version": "1.0.2",
"description": "Functional polymorphic method dispatch",
"keywords": [
"method",
"dispatch",
"protocol",
"polymorphism",
"type dispatch"
],
"author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
"homepage": "https://github.com/Gozala/method",
"main": "./core.js",
"repository": {
"type": "git",
"url": "https://github.com/Gozala/method.git",
"web": "https://github.com/Gozala/method"
},
"bugs": {
"url": "http://github.com/Gozala/method/issues/"
},
"devDependencies": {
"test": "~0.x.0",
"repl-utils": "~2.0.1",
"phantomify": "~0.1.0"
},
"scripts": {
"test": "npm run test-node && npm run test-browser",
"test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/browser.js",
"test-node": "node ./test/common.js",
"repl": "node node_modules/repl-utils"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/Gozala/method/License.md"
}
]
}

View File

@ -1,112 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var versionParse = require('./lib/utils').versionParse;
var COMPARATORS = ['>=', '<=', '>', '<', '=', '~', '^'];
exports.parse = function (input) {
input = input || '';
input = input.trim();
if (!input)
throw new Error('`parse` argument must be a populated string.');
// Handle the "*" case
if (input === "*") {
return { min: undefined, max: undefined };
}
var inputs = input.split(' ');
var min;
var max;
// 1.2.3 - 2.3.4
if (inputs.length === 3 && inputs[1] === '-') {
return { min: inputs[0], max: inputs[2] };
}
inputs.forEach(function (input) {
var parsed = parseExpression(input);
var version = parsed.version;
var comparator = parsed.comparator;
// 1.2.3
if (inputs.length === 1 && !comparator)
min = max = version;
// Parse min
if (~comparator.indexOf('>')) {
if (~comparator.indexOf('='))
min = version; // >=1.2.3
else
min = increment(version); // >1.2.3
}
else if (~comparator.indexOf('<')) {
if (~comparator.indexOf('='))
max = version; // <=1.2.3
else
max = decrement(version); // <1.2.3
}
});
return {
min: min,
max : max
};
};
function parseExpression (input) {
for (var i = 0; i < COMPARATORS.length; i++)
if (~input.indexOf(COMPARATORS[i]))
return {
comparator: COMPARATORS[i],
version: input.substr(COMPARATORS[i].length)
};
return { version: input, comparator: '' };
}
/**
* Takes a version string ('1.2.3') and returns a version string
* that'll parse as one less than the input string ('1.2.3.-1').
*
* @param {String} vString
* @return {String}
*/
function decrement (vString) {
return vString + (vString.charAt(vString.length - 1) === '.' ? '' : '.') + '-1';
}
exports.decrement = decrement;
/**
* Takes a version string ('1.2.3') and returns a version string
* that'll parse as greater than the input string by the smallest margin
* possible ('1.2.3.1').
* listed as number-A, string-B, number-C, string-D in
* Mozilla's Toolkit Format.
* https://developer.mozilla.org/en-US/docs/Toolkit_version_format
*
* @param {String} vString
* @return {String}
*/
function increment (vString) {
var match = versionParse(vString);
var a = match[1];
var b = match[2];
var c = match[3];
var d = match[4];
var lastPos = vString.length - 1;
var lastChar = vString.charAt(lastPos);
if (!b) {
return vString + (lastChar === '.' ? '' : '.') + '1';
}
if (!c) {
return vString + '1';
}
if (!d) {
return vString.substr(0, lastPos) + (++lastChar);
}
return vString.substr(0, lastPos) + String.fromCharCode(lastChar.charCodeAt(0) + 1);
}
exports.increment = increment;

View File

@ -1,15 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Breaks up a version string into the 4 components
* defined in:
* https://developer.mozilla.org/en-US/docs/Toolkit_version_format
* @params {String} val
* @return {String}
*/
function versionParse (val) {
return val.match(/^([0-9\.]*)([a-zA-Z]*)([0-9\.]*)([a-zA-Z]*)$/);
}
exports.versionParse = versionParse;

View File

@ -1,21 +0,0 @@
{
"name": "mozilla-toolkit-versioning",
"version": "0.0.2",
"description": "Parser for Mozilla's toolkit version format",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
},
"repository": {
"type": "git",
"url": "git://github.com/jsantell/mozilla-toolkit-versioning.git"
},
"author": "Jordan Santell",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"mocha": "^1.21.4",
"chai": "^1.9.1",
"mozilla-version-comparator": "^1.0.2"
}
}

View File

@ -1,90 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
module.metadata = {
"stability": "unstable"
};
const { Cc, Ci } = require('chrome');
const system = require('../sdk/system');
const runtime = require('../sdk/system/runtime');
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
const isWindows = system.platform === 'win32';
const endianness = ((new Uint32Array((new Uint8Array([1,2,3,4])).buffer))[0] === 0x04030201) ? 'LE' : 'BE';
XPCOMUtils.defineLazyGetter(this, "oscpu", () => {
try {
return Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).oscpu;
} catch (e) {
return "";
}
});
XPCOMUtils.defineLazyGetter(this, "hostname", () => {
try {
// On some platforms (Linux according to try), this service does not exist and fails.
return Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService).myHostName;
} catch (e) {
return "";
}
});
/**
* Returns a path to a temp directory
*/
exports.tmpdir = () => system.pathFor('TmpD');
/**
* Returns the endianness of the architecture: either 'LE' or 'BE'
*/
exports.endianness = () => endianness;
/**
* Returns hostname of the machine
*/
exports.hostname = () => hostname;
/**
* Name of the OS type
* Possible values:
* https://developer.mozilla.org/en/OS_TARGET
*/
exports.type = () => runtime.OS;
/**
* Name of the OS Platform in lower case string.
* Possible values:
* https://developer.mozilla.org/en/OS_TARGET
*/
exports.platform = () => system.platform;
/**
* Type of processor architecture running:
* 'arm', 'ia32', 'x86', 'x64'
*/
exports.arch = () => system.architecture;
/**
* Returns the operating system release.
*/
exports.release = () => {
let match = oscpu.match(/(\d[\.\d]*)/);
return match && match.length > 1 ? match[1] : oscpu;
};
/**
* Returns EOL character for the OS
*/
exports.EOL = isWindows ? '\r\n' : '\n';
/**
* Returns [0, 0, 0], as this is not implemented.
*/
exports.loadavg = () => [0, 0, 0];
['uptime', 'totalmem', 'freemem', 'cpus'].forEach(method => {
exports[method] = () => { throw new Error('os.' + method + ' is not supported.'); };
});

View File

@ -1,121 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.metadata = {
"stability": "experimental"
};
const { Cc, Ci, Cu } = require("chrome");
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
const { defer } = require("../core/promise");
const { setTimeout } = require("../timers");
/**
* `install` method error codes:
*
* https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors
*/
exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE;
exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH;
exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE;
exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS;
/**
* Immediatly install an addon.
*
* @param {String} xpiPath
* file path to an xpi file to install
* @return {Promise}
* A promise resolved when the addon is finally installed.
* Resolved with addon id as value or rejected with an error code.
*/
exports.install = function install(xpiPath) {
let { promise, resolve, reject } = defer();
// Create nsIFile for the xpi file
let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
try {
file.initWithPath(xpiPath);
}
catch(e) {
reject(exports.ERROR_FILE_ACCESS);
return promise;
}
// Listen for installation end
let listener = {
onInstallEnded: function(aInstall, aAddon) {
aInstall.removeListener(listener);
// Bug 749745: on FF14+, onInstallEnded is called just before `startup()`
// is called, but we expect to resolve the promise only after it.
// As startup is called synchronously just after onInstallEnded,
// a simple setTimeout(0) is enough
setTimeout(resolve, 0, aAddon.id);
},
onInstallFailed: function (aInstall) {
aInstall.removeListener(listener);
reject(aInstall.error);
},
onDownloadFailed: function(aInstall) {
this.onInstallFailed(aInstall);
}
};
// Order AddonManager to install the addon
AddonManager.getInstallForFile(file, function(install) {
if (install.error == 0) {
install.addListener(listener);
install.install();
} else {
reject(install.error);
}
});
return promise;
};
exports.uninstall = function uninstall(addonId) {
let { promise, resolve, reject } = defer();
// Listen for uninstallation end
let listener = {
onUninstalled: function onUninstalled(aAddon) {
if (aAddon.id != addonId)
return;
AddonManager.removeAddonListener(listener);
resolve();
}
};
AddonManager.addAddonListener(listener);
// Order Addonmanager to uninstall the addon
getAddon(addonId).then(addon => addon.uninstall(), reject);
return promise;
};
exports.disable = function disable(addonId) {
return getAddon(addonId).then(addon => {
addon.userDisabled = true;
return addonId;
});
};
exports.enable = function enabled(addonId) {
return getAddon(addonId).then(addon => {
addon.userDisabled = false;
return addonId;
});
};
exports.isActive = function isActive(addonId) {
return getAddon(addonId).then(addon => addon.isActive && !addon.appDisabled);
};
const getAddon = function getAddon (id) {
let { promise, resolve, reject } = defer();
AddonManager.getAddonByID(id, addon => addon ? resolve(addon) : reject());
return promise;
}
exports.getAddon = getAddon;

View File

@ -1,81 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "experimental"
};
const { Ci, Cc, Cu } = require("chrome");
const { when: unload } = require("../system/unload");
const prefs = require("../preferences/service");
if (!prefs.get("extensions.usehiddenwindow", false)) {
const {HiddenFrame} = require("resource://gre/modules/HiddenFrame.jsm", {});
let hiddenFrame = new HiddenFrame();
exports.window = hiddenFrame.getWindow();
exports.ready = hiddenFrame.get();
// Still destroy frame on unload to claim memory back early.
// NOTE: this doesn't seem to work and just doesn't get called. :-\
unload(function() {
hiddenFrame.destroy();
hiddenFrame = null;
});
} else {
const { make: makeWindow, getHiddenWindow } = require("../window/utils");
const { create: makeFrame, getDocShell } = require("../frame/utils");
const { defer } = require("../core/promise");
const cfxArgs = require("../test/options");
var addonPrincipal = Cc["@mozilla.org/systemprincipal;1"].
createInstance(Ci.nsIPrincipal);
var hiddenWindow = getHiddenWindow();
if (cfxArgs.parseable) {
console.info("hiddenWindow document.documentURI:" +
hiddenWindow.document.documentURI);
console.info("hiddenWindow document.readyState:" +
hiddenWindow.document.readyState);
}
// Once Bug 565388 is fixed and shipped we'll be able to make invisible,
// permanent docShells. Meanwhile we create hidden top level window and
// use it's docShell.
var frame = makeFrame(hiddenWindow.document, {
nodeName: "iframe",
namespaceURI: "http://www.w3.org/1999/xhtml",
allowJavascript: true,
allowPlugins: true
})
var docShell = getDocShell(frame);
var eventTarget = docShell.chromeEventHandler;
// We need to grant docShell system principals in order to load XUL document
// from data URI into it.
docShell.createAboutBlankContentViewer(addonPrincipal);
// Get a reference to the DOM window of the given docShell and load
// such document into that would allow us to create XUL iframes, that
// are necessary for hidden frames etc..
var window = docShell.contentViewer.DOMDocument.defaultView;
window.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
// Create a promise that is delivered once add-on window is interactive,
// used by add-on runner to defer add-on loading until window is ready.
var { promise, resolve } = defer();
eventTarget.addEventListener("DOMContentLoaded", function(event) {
resolve();
}, {once: true});
exports.ready = promise;
exports.window = window;
// Still close window on unload to claim memory back early.
unload(function() {
window.close()
frame.remove();
});
}

View File

@ -1,44 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "unstable"
};
const { Cu } = require("chrome");
Cu.importGlobalProperties(["atob", "btoa"]);
function isUTF8(charset) {
let type = typeof charset;
if (type === "undefined")
return false;
if (type === "string" && charset.toLowerCase() === "utf-8")
return true;
throw new Error("The charset argument can be only 'utf-8'");
}
function toOctetChar(c) {
return String.fromCharCode(c.charCodeAt(0) & 0xFF);
}
exports.decode = function (data, charset) {
if (isUTF8(charset))
return decodeURIComponent(escape(atob(data)))
return atob(data);
}
exports.encode = function (data, charset) {
if (isUTF8(charset))
return btoa(unescape(encodeURIComponent(data)))
data = data.replace(/[^\x00-\xFF]/g, toOctetChar);
return btoa(data);
}

View File

@ -1,321 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "stable",
"engines": {
// TODO Fennec Support 789757
"Firefox": "*",
"SeaMonkey": "*",
"Thunderbird": "*"
}
};
const { Cc, Ci } = require("chrome");
const { DataURL } = require("./url");
/*
While these data flavors resemble Internet media types, they do
no directly map to them.
*/
const kAllowableFlavors = [
"text/unicode",
"text/html",
"image/png"
/* CURRENTLY UNSUPPORTED FLAVORS
"text/plain",
"image/jpg",
"image/jpeg",
"image/gif",
"text/x-moz-text-internal",
"AOLMAIL",
"application/x-moz-file",
"text/x-moz-url",
"text/x-moz-url-data",
"text/x-moz-url-desc",
"text/x-moz-url-priv",
"application/x-moz-nativeimage",
"application/x-moz-nativehtml",
"application/x-moz-file-promise-url",
"application/x-moz-file-promise-dest-filename",
"application/x-moz-file-promise",
"application/x-moz-file-promise-dir"
*/
];
/*
Aliases for common flavors. Not all flavors will
get an alias. New aliases must be approved by a
Jetpack API druid.
*/
const kFlavorMap = [
{ short: "text", long: "text/unicode" },
{ short: "html", long: "text/html" },
{ short: "image", long: "image/png" }
];
var clipboardService = Cc["@mozilla.org/widget/clipboard;1"].
getService(Ci.nsIClipboard);
var clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
getService(Ci.nsIClipboardHelper);
var imageTools = Cc["@mozilla.org/image/tools;1"].
getService(Ci.imgITools);
exports.set = function(aData, aDataType) {
let options = {
data: aData,
datatype: aDataType || "text"
};
// If `aDataType` is not given or if it's "image", the data is parsed as
// data URL to detect a better datatype
if (aData && (!aDataType || aDataType === "image")) {
try {
let dataURL = new DataURL(aData);
options.datatype = dataURL.mimeType;
options.data = dataURL.data;
}
catch (e) {
// Ignore invalid URIs
if (e.name !== "URIError") {
throw e;
}
}
}
let flavor = fromJetpackFlavor(options.datatype);
if (!flavor)
throw new Error("Invalid flavor for " + options.datatype);
// Additional checks for using the simple case
if (flavor == "text/unicode") {
clipboardHelper.copyString(options.data);
return true;
}
// Below are the more complex cases where we actually have to work with a
// nsITransferable object
var xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
if (!xferable)
throw new Error("Couldn't set the clipboard due to an internal error " +
"(couldn't create a Transferable object).");
// Bug 769440: Starting with FF16, transferable have to be inited
if ("init" in xferable)
xferable.init(null);
switch (flavor) {
case "text/html":
// add text/html flavor
let str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = options.data;
xferable.addDataFlavor(flavor);
xferable.setTransferData(flavor, str, str.data.length * 2);
// add a text/unicode flavor (html converted to plain text)
str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let converter = Cc["@mozilla.org/feed-textconstruct;1"].
createInstance(Ci.nsIFeedTextConstruct);
converter.type = "html";
converter.text = options.data;
str.data = converter.plainText();
xferable.addDataFlavor("text/unicode");
xferable.setTransferData("text/unicode", str, str.data.length * 2);
break;
// Set images to the clipboard is not straightforward, to have an idea how
// it works on platform side, see:
// http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsCopySupport.cpp?rev=7857c5bff017#530
case "image/png":
let image = options.data;
let container;
try {
let input = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
input.setData(image, image.length);
container = imageTools.decodeImage(input, flavor);
}
catch (e) {
throw new Error("Unable to decode data given in a valid image.");
}
// Store directly the input stream makes the cliboard's data available
// for Firefox but not to the others application or to the OS. Therefore,
// a `nsISupportsInterfacePointer` object that reference an `imgIContainer`
// with the image is needed.
var imgPtr = Cc["@mozilla.org/supports-interface-pointer;1"].
createInstance(Ci.nsISupportsInterfacePointer);
imgPtr.data = container;
xferable.addDataFlavor(flavor);
xferable.setTransferData(flavor, imgPtr, -1);
break;
default:
throw new Error("Unable to handle the flavor " + flavor + ".");
}
// TODO: Not sure if this will ever actually throw. -zpao
try {
clipboardService.setData(
xferable,
null,
clipboardService.kGlobalClipboard
);
} catch (e) {
throw new Error("Couldn't set clipboard data due to an internal error: " + e);
}
return true;
};
exports.get = function(aDataType) {
let options = {
datatype: aDataType
};
// Figure out the best data type for the clipboard's data, if omitted
if (!aDataType) {
if (~currentFlavors().indexOf("image"))
options.datatype = "image";
else
options.datatype = "text";
}
var xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
if (!xferable)
throw new Error("Couldn't set the clipboard due to an internal error " +
"(couldn't create a Transferable object).");
// Bug 769440: Starting with FF16, transferable have to be inited
if ("init" in xferable)
xferable.init(null);
var flavor = fromJetpackFlavor(options.datatype);
// Ensure that the user hasn't requested a flavor that we don't support.
if (!flavor)
throw new Error("Getting the clipboard with the flavor '" + flavor +
"' is not supported.");
// TODO: Check for matching flavor first? Probably not worth it.
xferable.addDataFlavor(flavor);
// Get the data into our transferable.
clipboardService.getData(
xferable,
clipboardService.kGlobalClipboard
);
var data = {};
var dataLen = {};
try {
xferable.getTransferData(flavor, data, dataLen);
} catch (e) {
// Clipboard doesn't contain data in flavor, return null.
return null;
}
// There's no data available, return.
if (data.value === null)
return null;
// TODO: Add flavors here as we support more in kAllowableFlavors.
switch (flavor) {
case "text/unicode":
case "text/html":
data = data.value.QueryInterface(Ci.nsISupportsString).data;
break;
case "image/png":
let dataURL = new DataURL();
dataURL.mimeType = flavor;
dataURL.base64 = true;
let image = data.value;
// Due to the differences in how images could be stored in the clipboard
// the checks below are needed. The clipboard could already provide the
// image as byte streams, but also as pointer, or as image container.
// If it's not possible obtain a byte stream, the function returns `null`.
if (image instanceof Ci.nsISupportsInterfacePointer)
image = image.data;
if (image instanceof Ci.imgIContainer)
image = imageTools.encodeImage(image, flavor);
if (image instanceof Ci.nsIInputStream) {
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
binaryStream.setInputStream(image);
dataURL.data = binaryStream.readBytes(binaryStream.available());
data = dataURL.toString();
}
else
data = null;
break;
default:
data = null;
}
return data;
};
function currentFlavors() {
// Loop over kAllowableFlavors, calling hasDataMatchingFlavors for each.
// This doesn't seem like the most efficient way, but we can't get
// confirmation for specific flavors any other way. This is supposed to be
// an inexpensive call, so performance shouldn't be impacted (much).
var currentFlavors = [];
for (var flavor of kAllowableFlavors) {
var matches = clipboardService.hasDataMatchingFlavors(
[flavor],
1,
clipboardService.kGlobalClipboard
);
if (matches)
currentFlavors.push(toJetpackFlavor(flavor));
}
return currentFlavors;
};
Object.defineProperty(exports, "currentFlavors", { get : currentFlavors });
// SUPPORT FUNCTIONS ////////////////////////////////////////////////////////
function toJetpackFlavor(aFlavor) {
for (let flavorMap of kFlavorMap)
if (flavorMap.long == aFlavor)
return flavorMap.short;
// Return null in the case where we don't match
return null;
}
function fromJetpackFlavor(aJetpackFlavor) {
// TODO: Handle proper flavors better
for (let flavorMap of kFlavorMap)
if (flavorMap.short == aJetpackFlavor || flavorMap.long == aJetpackFlavor)
return flavorMap.long;
// Return null in the case where we don't match.
return null;
}

View File

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "unstable"
};
const { Cc, Ci, Cu, Cr } = require("chrome");
const self = require("../self");
const prefs = require("../preferences/service");
const { merge } = require("../util/object");
const { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
const DEFAULT_LOG_LEVEL = "error";
const ADDON_LOG_LEVEL_PREF = "extensions." + self.id + ".sdk.console.logLevel";
const SDK_LOG_LEVEL_PREF = "extensions.sdk.console.logLevel";
var logLevel = DEFAULT_LOG_LEVEL;
function setLogLevel() {
logLevel = prefs.get(ADDON_LOG_LEVEL_PREF,
prefs.get(SDK_LOG_LEVEL_PREF,
DEFAULT_LOG_LEVEL));
}
setLogLevel();
var logLevelObserver = {
QueryInterface: function(iid) {
if (!iid.equals(Ci.nsIObserver) &&
!iid.equals(Ci.nsISupportsWeakReference) &&
!iid.equals(Ci.nsISupports))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
observe: function(subject, topic, data) {
setLogLevel();
}
};
var branch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService).
getBranch(null);
branch.addObserver(ADDON_LOG_LEVEL_PREF, logLevelObserver, true);
branch.addObserver(SDK_LOG_LEVEL_PREF, logLevelObserver, true);
function PlainTextConsole(print, innerID) {
let consoleOptions = {
prefix: self.name,
maxLogLevel: logLevel,
dump: print,
innerID: innerID,
consoleID: "addon/" + self.id
};
let console = new ConsoleAPI(consoleOptions);
// As we freeze the console object, we can't modify this property afterward
Object.defineProperty(console, "maxLogLevel", {
get: function() {
return logLevel;
}
});
Object.freeze(console);
return console;
};
exports.PlainTextConsole = PlainTextConsole;

Some files were not shown because too many files have changed in this diff Show More