summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-04-23 15:32:23 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-04-23 15:32:23 -0400
commitabe80cc31d5a40ebed743085011fbcda0c1a9a10 (patch)
treefb3762f06b84745b182af281abb107b95a9fcf01 /mobile/android/modules
parent63295d0087eb58a6eb34cad324c4c53d1b220491 (diff)
downloadUXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.gz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.lz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.xz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.zip
Issue #1053 - Drop support Android and remove Fennec - Part 1a: Remove mobile/android
Diffstat (limited to 'mobile/android/modules')
-rw-r--r--mobile/android/modules/Accounts.jsm79
-rw-r--r--mobile/android/modules/AndroidLog.jsm92
-rw-r--r--mobile/android/modules/DelayedInit.jsm177
-rw-r--r--mobile/android/modules/DownloadNotifications.jsm291
-rw-r--r--mobile/android/modules/HelperApps.jsm229
-rw-r--r--mobile/android/modules/Home.jsm487
-rw-r--r--mobile/android/modules/HomeProvider.jsm407
-rw-r--r--mobile/android/modules/JNI.jsm1167
-rw-r--r--mobile/android/modules/JavaAddonManager.jsm115
-rw-r--r--mobile/android/modules/LightweightThemeConsumer.jsm44
-rw-r--r--mobile/android/modules/MediaPlayerApp.jsm166
-rw-r--r--mobile/android/modules/Messaging.jsm183
-rw-r--r--mobile/android/modules/NetErrorHelper.jsm175
-rw-r--r--mobile/android/modules/Notifications.jsm259
-rw-r--r--mobile/android/modules/PageActions.jsm113
-rw-r--r--mobile/android/modules/Prompt.jsm234
-rw-r--r--mobile/android/modules/RuntimePermissions.jsm41
-rw-r--r--mobile/android/modules/SSLExceptions.jsm118
-rw-r--r--mobile/android/modules/Sanitizer.jsm303
-rw-r--r--mobile/android/modules/SharedPreferences.jsm254
-rw-r--r--mobile/android/modules/Snackbars.jsm72
-rw-r--r--mobile/android/modules/TabMirror.jsm153
-rw-r--r--mobile/android/modules/WebsiteMetadata.jsm475
-rw-r--r--mobile/android/modules/dbg-browser-actors.js77
-rw-r--r--mobile/android/modules/moz.build32
25 files changed, 0 insertions, 5743 deletions
diff --git a/mobile/android/modules/Accounts.jsm b/mobile/android/modules/Accounts.jsm
deleted file mode 100644
index ee0fc0c5b..000000000
--- a/mobile/android/modules/Accounts.jsm
+++ /dev/null
@@ -1,79 +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";
-
-this.EXPORTED_SYMBOLS = ["Accounts"];
-
-const { utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Deprecated.jsm"); /*global Deprecated */
-Cu.import("resource://gre/modules/Messaging.jsm"); /*global Messaging */
-Cu.import("resource://gre/modules/Promise.jsm"); /*global Promise */
-Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
-
-/**
- * A promise-based API for querying the existence of Sync accounts,
- * and accessing the Sync setup wizard.
- *
- * Usage:
- *
- * Cu.import("resource://gre/modules/Accounts.jsm");
- * Accounts.anySyncAccountsExist().then(
- * (exist) => {
- * console.log("Accounts exist? " + exist);
- * if (!exist) {
- * Accounts.launchSetup();
- * }
- * },
- * (err) => {
- * console.log("We failed so hard.");
- * }
- * );
- */
-var Accounts = Object.freeze({
- _accountsExist: function (kind) {
- return Messaging.sendRequestForResult({
- type: "Accounts:Exist",
- kind: kind
- }).then(data => data.exists);
- },
-
- syncAccountsExist: function () {
- Deprecated.warning("The legacy Sync account type has been removed from Firefox for Android.");
- return Promise.resolve(false);
- },
-
- anySyncAccountsExist: function () {
- return this._accountsExist("any");
- },
-
- /**
- * Fire-and-forget: open the Firefox accounts activity, which
- * will be the Getting Started screen if FxA isn't yet set up.
- *
- * Optional extras are passed, as a JSON string, to the Firefox
- * Account Getting Started activity in the extras bundle of the
- * activity launch intent, under the key "extras".
- *
- * There is no return value from this method.
- */
- launchSetup: function (extras) {
- Messaging.sendRequest({
- type: "Accounts:Create",
- extras: extras
- });
- },
-
- _addDefaultEndpoints: function (json) {
- // Empty without FxA
- let newData = Cu.cloneInto(json, {}, { cloneFunctions: false });
- return newData;
- },
-
- showSyncPreferences: function () {
- // Only show Sync preferences of an existing Android Account.
- throw new Error("Can't show Sync preferences without accounts!");
- }
-});
diff --git a/mobile/android/modules/AndroidLog.jsm b/mobile/android/modules/AndroidLog.jsm
deleted file mode 100644
index be6cca4e8..000000000
--- a/mobile/android/modules/AndroidLog.jsm
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
- * 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";
-
-/**
- * Native Android logging for JavaScript. Lets you specify a priority and tag
- * in addition to the message being logged. Resembles the android.util.Log API
- * <http://developer.android.com/reference/android/util/Log.html>.
- *
- * // Import it as a JSM:
- * let Log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog;
- *
- * // Or require it in a chrome worker:
- * importScripts("resource://gre/modules/workers/require.js");
- * let Log = require("resource://gre/modules/AndroidLog.jsm");
- *
- * // Use Log.i, Log.v, Log.d, Log.w, and Log.e to log verbose, debug, info,
- * // warning, and error messages, respectively.
- * Log.v("MyModule", "This is a verbose message.");
- * Log.d("MyModule", "This is a debug message.");
- * Log.i("MyModule", "This is an info message.");
- * Log.w("MyModule", "This is a warning message.");
- * Log.e("MyModule", "This is an error message.");
- *
- * // Bind a function with a tag to replace a bespoke dump/log/debug function:
- * let debug = Log.d.bind(null, "MyModule");
- * debug("This is a debug message.");
- * // Outputs "D/GeckoMyModule(#####): This is a debug message."
- *
- * // Or "bind" the module object to a tag to automatically tag messages:
- * Log = Log.bind("MyModule");
- * Log.d("This is a debug message.");
- * // Outputs "D/GeckoMyModule(#####): This is a debug message."
- *
- * Note: the module automatically prepends "Gecko" to the tag you specify,
- * since all tags used by Fennec code should start with that string; and it
- * truncates tags longer than MAX_TAG_LENGTH characters (not including "Gecko").
- */
-
-if (typeof Components != "undefined") {
- // Specify exported symbols for JSM module loader.
- this.EXPORTED_SYMBOLS = ["AndroidLog"];
- Components.utils.import("resource://gre/modules/ctypes.jsm");
-}
-
-// From <https://android.googlesource.com/platform/system/core/+/master/include/android/log.h>.
-const ANDROID_LOG_VERBOSE = 2;
-const ANDROID_LOG_DEBUG = 3;
-const ANDROID_LOG_INFO = 4;
-const ANDROID_LOG_WARN = 5;
-const ANDROID_LOG_ERROR = 6;
-
-// android.util.Log.isLoggable throws IllegalArgumentException if a tag length
-// exceeds 23 characters, and we prepend five characters ("Gecko") to every tag,
-// so we truncate tags exceeding 18 characters (although __android_log_write
-// itself and other android.util.Log methods don't seem to mind longer tags).
-const MAX_TAG_LENGTH = 18;
-
-var liblog = ctypes.open("liblog.so"); // /system/lib/liblog.so
-var __android_log_write = liblog.declare("__android_log_write",
- ctypes.default_abi,
- ctypes.int, // return value: num bytes logged
- ctypes.int, // priority (ANDROID_LOG_* constant)
- ctypes.char.ptr, // tag
- ctypes.char.ptr); // message
-
-var AndroidLog = {
- MAX_TAG_LENGTH: MAX_TAG_LENGTH,
- v: (tag, msg) => __android_log_write(ANDROID_LOG_VERBOSE, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
- d: (tag, msg) => __android_log_write(ANDROID_LOG_DEBUG, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
- i: (tag, msg) => __android_log_write(ANDROID_LOG_INFO, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
- w: (tag, msg) => __android_log_write(ANDROID_LOG_WARN, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
- e: (tag, msg) => __android_log_write(ANDROID_LOG_ERROR, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
-
- bind: function(tag) {
- return {
- MAX_TAG_LENGTH: MAX_TAG_LENGTH,
- v: AndroidLog.v.bind(null, tag),
- d: AndroidLog.d.bind(null, tag),
- i: AndroidLog.i.bind(null, tag),
- w: AndroidLog.w.bind(null, tag),
- e: AndroidLog.e.bind(null, tag),
- };
- },
-};
-
-if (typeof Components == "undefined") {
- // Specify exported symbols for require.js module loader.
- module.exports = AndroidLog;
-}
diff --git a/mobile/android/modules/DelayedInit.jsm b/mobile/android/modules/DelayedInit.jsm
deleted file mode 100644
index 7c33a3ede..000000000
--- a/mobile/android/modules/DelayedInit.jsm
+++ /dev/null
@@ -1,177 +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"
-
-/*globals MessageLoop */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = ["DelayedInit"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "MessageLoop",
- "@mozilla.org/message-loop;1",
- "nsIMessageLoop");
-
-/**
- * Use DelayedInit to schedule initializers to run some time after startup.
- * Initializers are added to a list of pending inits. Whenever the main thread
- * message loop is idle, DelayedInit will start running initializers from the
- * pending list. To prevent monopolizing the message loop, every idling period
- * has a maximum duration. When that's reached, we give up the message loop and
- * wait for the next idle.
- *
- * DelayedInit is compatible with lazy getters like those from XPCOMUtils. When
- * the lazy getter is first accessed, its corresponding initializer is run
- * automatically if it hasn't been run already. Each initializer also has a
- * maximum wait parameter that specifies a mandatory timeout; when the timeout
- * is reached, the initializer is forced to run.
- *
- * DelayedInit.schedule(() => Foo.init(), null, null, 5000);
- *
- * In the example above, Foo.init will run automatically when the message loop
- * becomes idle, or when 5000ms has elapsed, whichever comes first.
- *
- * DelayedInit.schedule(() => Foo.init(), this, "Foo", 5000);
- *
- * In the example above, Foo.init will run automatically when the message loop
- * becomes idle, when |this.Foo| is accessed, or when 5000ms has elapsed,
- * whichever comes first.
- *
- * It may be simpler to have a wrapper for DelayedInit.schedule. For example,
- *
- * function InitLater(fn, obj, name) {
- * return DelayedInit.schedule(fn, obj, name, 5000); // constant max wait
- * }
- * InitLater(() => Foo.init());
- * InitLater(() => Bar.init(), this, "Bar");
- */
-var DelayedInit = {
- schedule: function (fn, object, name, maxWait) {
- return Impl.scheduleInit(fn, object, name, maxWait);
- },
-};
-
-// Maximum duration for each idling period. Pending inits are run until this
-// duration is exceeded; then we wait for next idling period.
-const MAX_IDLE_RUN_MS = 50;
-
-var Impl = {
- pendingInits: [],
-
- onIdle: function () {
- let startTime = Cu.now();
- let time = startTime;
- let nextDue;
-
- // Go through all the pending inits. Even if we don't run them,
- // we still need to find out when the next timeout should be.
- for (let init of this.pendingInits) {
- if (init.complete) {
- continue;
- }
-
- if (time - startTime < MAX_IDLE_RUN_MS) {
- init.maybeInit();
- time = Cu.now();
- } else {
- // We ran out of time; find when the next closest due time is.
- nextDue = nextDue ? Math.min(nextDue, init.due) : init.due;
- }
- }
-
- // Get rid of completed ones.
- this.pendingInits = this.pendingInits.filter((init) => !init.complete);
-
- if (nextDue !== undefined) {
- // Schedule the next idle, if we still have pending inits.
- MessageLoop.postIdleTask(() => this.onIdle(),
- Math.max(0, nextDue - time));
- }
- },
-
- addPendingInit: function (fn, wait) {
- let init = {
- fn: fn,
- due: Cu.now() + wait,
- complete: false,
- maybeInit: function () {
- if (this.complete) {
- return false;
- }
- this.complete = true;
- this.fn.call();
- this.fn = null;
- return true;
- },
- };
-
- if (!this.pendingInits.length) {
- // Schedule for the first idle.
- MessageLoop.postIdleTask(() => this.onIdle(), wait);
- }
- this.pendingInits.push(init);
- return init;
- },
-
- scheduleInit: function (fn, object, name, wait) {
- let init = this.addPendingInit(fn, wait);
-
- if (!object || !name) {
- // No lazy getter needed.
- return;
- }
-
- // Get any existing information about the property.
- let prop = Object.getOwnPropertyDescriptor(object, name) ||
- { configurable: true, enumerable: true, writable: true };
-
- if (!prop.configurable) {
- // Object.defineProperty won't work, so just perform init here.
- init.maybeInit();
- return;
- }
-
- // Define proxy getter/setter that will call first initializer first,
- // before delegating the get/set to the original target.
- Object.defineProperty(object, name, {
- get: function proxy_getter() {
- init.maybeInit();
-
- // If the initializer actually ran, it may have replaced our proxy
- // property with a real one, so we need to reload he property.
- let newProp = Object.getOwnPropertyDescriptor(object, name);
- if (newProp.get !== proxy_getter) {
- // Set prop if newProp doesn't refer to our proxy property.
- prop = newProp;
- } else {
- // Otherwise, reset to the original property.
- Object.defineProperty(object, name, prop);
- }
-
- if (prop.get) {
- return prop.get.call(object);
- }
- return prop.value;
- },
- set: function (newVal) {
- init.maybeInit();
-
- // Since our initializer already ran,
- // we can get rid of our proxy property.
- if (prop.get || prop.set) {
- Object.defineProperty(object, name, prop);
- return prop.set.call(object);
- }
-
- prop.value = newVal;
- Object.defineProperty(object, name, prop);
- return newVal;
- },
- configurable: true,
- enumerable: true,
- });
- }
-};
diff --git a/mobile/android/modules/DownloadNotifications.jsm b/mobile/android/modules/DownloadNotifications.jsm
deleted file mode 100644
index 39b520979..000000000
--- a/mobile/android/modules/DownloadNotifications.jsm
+++ /dev/null
@@ -1,291 +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";
-
-this.EXPORTED_SYMBOLS = ["DownloadNotifications"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ParentalControls",
- "@mozilla.org/parental-controls-service;1", "nsIParentalControlsService");
-
-var Log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.i.bind(null, "DownloadNotifications");
-
-XPCOMUtils.defineLazyGetter(this, "strings",
- () => Services.strings.createBundle("chrome://browser/locale/browser.properties"));
-
-Object.defineProperty(this, "window",
- { get: () => Services.wm.getMostRecentWindow("navigator:browser") });
-
-const kButtons = {
- PAUSE: new DownloadNotificationButton("pause",
- "drawable://pause",
- "alertDownloadsPause"),
- RESUME: new DownloadNotificationButton("resume",
- "drawable://play",
- "alertDownloadsResume"),
- CANCEL: new DownloadNotificationButton("cancel",
- "drawable://close",
- "alertDownloadsCancel")
-};
-
-var notifications = new Map();
-
-var DownloadNotifications = {
- _notificationKey: "downloads",
-
- init: function () {
- Downloads.getList(Downloads.ALL)
- .then(list => list.addView(this))
- .then(() => this._viewAdded = true, Cu.reportError);
-
- // All click, cancel, and button presses will be handled by this handler as part of the Notifications callback API.
- Notifications.registerHandler(this._notificationKey, this);
- },
-
- onDownloadAdded: function (download) {
- // Don't create notifications for pre-existing succeeded downloads.
- // We still add notifications for canceled downloads in case the
- // user decides to retry the download.
- if (download.succeeded && !this._viewAdded) {
- return;
- }
-
- if (!ParentalControls.isAllowed(ParentalControls.DOWNLOAD)) {
- download.cancel().catch(Cu.reportError);
- download.removePartialData().catch(Cu.reportError);
- Snackbars.show(strings.GetStringFromName("downloads.disabledInGuest"), Snackbars.LENGTH_LONG);
- return;
- }
-
- let notification = new DownloadNotification(download);
- notifications.set(download, notification);
- notification.showOrUpdate();
-
- // If this is a new download, show a snackbar as well.
- if (this._viewAdded) {
- Snackbars.show(strings.GetStringFromName("alertDownloadsToast"), Snackbars.LENGTH_LONG);
- }
- },
-
- onDownloadChanged: function (download) {
- let notification = notifications.get(download);
-
- if (download.succeeded) {
- let file = new FileUtils.File(download.target.path);
-
- Snackbars.show(strings.formatStringFromName("alertDownloadSucceeded", [file.leafName], 1), Snackbars.LENGTH_LONG, {
- action: {
- label: strings.GetStringFromName("helperapps.open"),
- callback: () => {
- UITelemetry.addEvent("launch.1", "toast", null, "downloads");
- try {
- file.launch();
- } catch (ex) {
- this.showInAboutDownloads(download);
- }
- if (notification) {
- notification.hide();
- }
- }
- }});
- }
-
- if (notification) {
- notification.showOrUpdate();
- }
- },
-
- onDownloadRemoved: function (download) {
- let notification = notifications.get(download);
- if (!notification) {
- Cu.reportError("Download doesn't have a notification.");
- return;
- }
-
- notification.hide();
- notifications.delete(download);
- },
-
- _findDownloadForCookie: function(cookie) {
- return Downloads.getList(Downloads.ALL)
- .then(list => list.getAll())
- .then((downloads) => {
- for (let download of downloads) {
- let cookie2 = getCookieFromDownload(download);
- if (cookie2 === cookie) {
- return download;
- }
- }
-
- throw "Couldn't find download for " + cookie;
- });
- },
-
- onCancel: function(cookie) {
- // TODO: I'm not sure what we do here...
- },
-
- showInAboutDownloads: function (download) {
- let hash = "#" + window.encodeURIComponent(download.target.path);
-
- // Force using string equality to find a tab
- window.BrowserApp.selectOrAddTab("about:downloads" + hash, null, { startsWith: true });
- },
-
- onClick: function(cookie) {
- this._findDownloadForCookie(cookie).then((download) => {
- if (download.succeeded) {
- // We don't call Download.launch(), because there's (currently) no way to
- // tell if the file was actually launched or not, and we want to show
- // about:downloads if the launch failed.
- let file = new FileUtils.File(download.target.path);
- try {
- file.launch();
- } catch (ex) {
- this.showInAboutDownloads(download);
- }
- } else {
- ConfirmCancelPrompt.show(download);
- }
- }).catch(Cu.reportError);
- },
-
- onButtonClick: function(button, cookie) {
- this._findDownloadForCookie(cookie).then((download) => {
- if (button === kButtons.PAUSE.buttonId) {
- download.cancel().catch(Cu.reportError);
- } else if (button === kButtons.RESUME.buttonId) {
- download.start().catch(Cu.reportError);
- } else if (button === kButtons.CANCEL.buttonId) {
- download.cancel().catch(Cu.reportError);
- download.removePartialData().catch(Cu.reportError);
- }
- }).catch(Cu.reportError);
- },
-};
-
-function getCookieFromDownload(download) {
- return download.target.path +
- download.source.url +
- download.startTime;
-}
-
-function DownloadNotification(download) {
- this.download = download;
- this._fileName = OS.Path.basename(download.target.path);
-
- this.id = null;
-}
-
-DownloadNotification.prototype = {
- _updateFromDownload: function () {
- this._downloading = !this.download.stopped;
- this._paused = this.download.canceled && this.download.hasPartialData;
- this._succeeded = this.download.succeeded;
-
- this._show = this._downloading || this._paused || this._succeeded;
- },
-
- get options() {
- if (!this._show) {
- return null;
- }
-
- let options = {
- icon: "drawable://alert_download",
- cookie: getCookieFromDownload(this.download),
- handlerKey: DownloadNotifications._notificationKey
- };
-
- if (this._downloading) {
- options.icon = "drawable://alert_download_animation";
- if (this.download.currentBytes == 0) {
- this._updateOptionsForStatic(options, "alertDownloadsStart2");
- } else {
- let buttons = this.download.hasPartialData ? [kButtons.PAUSE, kButtons.CANCEL] :
- [kButtons.CANCEL]
- this._updateOptionsForOngoing(options, buttons);
- }
- } else if (this._paused) {
- this._updateOptionsForOngoing(options, [kButtons.RESUME, kButtons.CANCEL]);
- } else if (this._succeeded) {
- options.persistent = false;
- this._updateOptionsForStatic(options, "alertDownloadsDone2");
- }
-
- return options;
- },
-
- _updateOptionsForStatic : function (options, titleName) {
- options.title = strings.GetStringFromName(titleName);
- options.message = this._fileName;
- },
-
- _updateOptionsForOngoing: function (options, buttons) {
- options.title = this._fileName;
- options.message = this.download.progress + "%";
- options.buttons = buttons;
- options.ongoing = true;
- options.progress = this.download.progress;
- options.persistent = true;
- },
-
- showOrUpdate: function () {
- this._updateFromDownload();
-
- if (this._show) {
- if (!this.id) {
- this.id = Notifications.create(this.options);
- } else if (!this.options.ongoing) {
- // We need to explictly cancel ongoing notifications,
- // since updating them to be non-ongoing doesn't seem
- // to work. See bug 1130834.
- Notifications.cancel(this.id);
- this.id = Notifications.create(this.options);
- } else {
- Notifications.update(this.id, this.options);
- }
- } else {
- this.hide();
- }
- },
-
- hide: function () {
- if (this.id) {
- Notifications.cancel(this.id);
- this.id = null;
- }
- },
-};
-
-var ConfirmCancelPrompt = {
- show: function (download) {
- // Open a prompt that offers a choice to cancel the download
- let title = strings.GetStringFromName("downloadCancelPromptTitle1");
- let message = strings.GetStringFromName("downloadCancelPromptMessage1");
-
- if (Services.prompt.confirm(null, title, message)) {
- download.cancel().catch(Cu.reportError);
- download.removePartialData().catch(Cu.reportError);
- }
- }
-};
-
-function DownloadNotificationButton(buttonId, iconUrl, titleStringName, onClicked) {
- this.buttonId = buttonId;
- this.title = strings.GetStringFromName(titleStringName);
- this.icon = iconUrl;
-}
diff --git a/mobile/android/modules/HelperApps.jsm b/mobile/android/modules/HelperApps.jsm
deleted file mode 100644
index 0ac478da0..000000000
--- a/mobile/android/modules/HelperApps.jsm
+++ /dev/null
@@ -1,229 +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";
-
-/* globals ContentAreaUtils */
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Prompt",
- "resource://gre/modules/Prompt.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Messaging",
- "resource://gre/modules/Messaging.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() {
- let ContentAreaUtils = {};
- Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils);
- return ContentAreaUtils;
-});
-
-this.EXPORTED_SYMBOLS = ["App","HelperApps"];
-
-function App(data) {
- this.name = data.name;
- this.isDefault = data.isDefault;
- this.packageName = data.packageName;
- this.activityName = data.activityName;
- this.iconUri = "-moz-icon://" + data.packageName;
-}
-
-App.prototype = {
- // callback will be null if a result is not requested
- launch: function(uri, callback) {
- HelperApps._launchApp(this, uri, callback);
- return false;
- }
-}
-
-var HelperApps = {
- get defaultBrowsers() {
- delete this.defaultBrowsers;
- this.defaultBrowsers = this._getHandlers("http://www.example.com", {
- filterBrowsers: false,
- filterHtml: false
- });
- return this.defaultBrowsers;
- },
-
- // Finds handlers that have registered for text/html pages or urls ending in html. Some apps, like
- // the Samsung Video player will only appear for these urls, while some Browsers (like Link Bubble)
- // won't register here because of the text/html mime type.
- get defaultHtmlHandlers() {
- delete this.defaultHtmlHandlers;
- return this.defaultHtmlHandlers = this._getHandlers("http://www.example.com/index.html", {
- filterBrowsers: false,
- filterHtml: false
- });
- },
-
- _getHandlers: function(url, options) {
- let values = {};
-
- let handlers = this.getAppsForUri(Services.io.newURI(url, null, null), options);
- handlers.forEach(function(app) {
- values[app.name] = app;
- }, this);
-
- return values;
- },
-
- get protoSvc() {
- delete this.protoSvc;
- return this.protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
- },
-
- get urlHandlerService() {
- delete this.urlHandlerService;
- return this.urlHandlerService = Cc["@mozilla.org/uriloader/external-url-handler-service;1"].getService(Ci.nsIExternalURLHandlerService);
- },
-
- prompt: function showPicker(apps, promptOptions, callback) {
- let p = new Prompt(promptOptions).addIconGrid({ items: apps });
- p.show(callback);
- },
-
- getAppsForProtocol: function getAppsForProtocol(scheme) {
- let protoHandlers = this.protoSvc.getProtocolHandlerInfoFromOS(scheme, {}).possibleApplicationHandlers;
-
- let results = {};
- for (let i = 0; i < protoHandlers.length; i++) {
- try {
- let protoApp = protoHandlers.queryElementAt(i, Ci.nsIHandlerApp);
- results[protoApp.name] = new App({
- name: protoApp.name,
- description: protoApp.detailedDescription,
- });
- } catch(e) {}
- }
-
- return results;
- },
-
- getAppsForUri: function getAppsForUri(uri, flags = { }, callback) {
- // Return early for well-known internal schemes
- if (!uri || uri.schemeIs("about") || uri.schemeIs("chrome")) {
- if (callback) {
- callback([]);
- }
- return [];
- }
-
- flags.filterBrowsers = "filterBrowsers" in flags ? flags.filterBrowsers : true;
- flags.filterHtml = "filterHtml" in flags ? flags.filterHtml : true;
-
- // Query for apps that can/can't handle the mimetype
- let msg = this._getMessage("Intent:GetHandlers", uri, flags);
- let parseData = (d) => {
- let apps = []
- if (!d) {
- return apps;
- }
-
- apps = this._parseApps(d.apps);
-
- if (flags.filterBrowsers) {
- apps = apps.filter((app) => {
- return app.name && !this.defaultBrowsers[app.name];
- });
- }
-
- // Some apps will register for html files (the Samsung Video player) but should be shown
- // for non-HTML files (like videos). This filters them only if the page has an htm of html
- // file extension.
- if (flags.filterHtml) {
- // Matches from the first '.' to the end of the string, '?', or '#'
- let ext = /\.([^\?#]*)/.exec(uri.path);
- if (ext && (ext[1] === "html" || ext[1] === "htm")) {
- apps = apps.filter(function(app) {
- return app.name && !this.defaultHtmlHandlers[app.name];
- }, this);
- }
- }
-
- return apps;
- };
-
- if (!callback) {
- let data = this._sendMessageSync(msg);
- return parseData(data);
- } else {
- Messaging.sendRequestForResult(msg).then(function(data) {
- callback(parseData(data));
- });
- }
- },
-
- launchUri: function launchUri(uri) {
- let msg = this._getMessage("Intent:Open", uri);
- Messaging.sendRequest(msg);
- },
-
- _parseApps: function _parseApps(appInfo) {
- // appInfo -> {apps: [app1Label, app1Default, app1PackageName, app1ActivityName, app2Label, app2Defaut, ...]}
- // see GeckoAppShell.java getHandlersForIntent function for details
- const numAttr = 4; // 4 elements per ResolveInfo: label, default, package name, activity name.
-
- let apps = [];
- for (let i = 0; i < appInfo.length; i += numAttr) {
- apps.push(new App({"name" : appInfo[i],
- "isDefault" : appInfo[i+1],
- "packageName" : appInfo[i+2],
- "activityName" : appInfo[i+3]}));
- }
-
- return apps;
- },
-
- _getMessage: function(type, uri, options = {}) {
- let mimeType = options.mimeType;
- if (uri && mimeType == undefined) {
- mimeType = ContentAreaUtils.getMIMETypeForURI(uri) || "";
- }
-
- return {
- type: type,
- mime: mimeType,
- action: options.action || "", // empty action string defaults to android.intent.action.VIEW
- url: uri ? uri.spec : "",
- packageName: options.packageName || "",
- className: options.className || ""
- };
- },
-
- _launchApp: function launchApp(app, uri, callback) {
- if (callback) {
- let msg = this._getMessage("Intent:OpenForResult", uri, {
- packageName: app.packageName,
- className: app.activityName
- });
-
- Messaging.sendRequestForResult(msg).then(callback);
- } else {
- let msg = this._getMessage("Intent:Open", uri, {
- packageName: app.packageName,
- className: app.activityName
- });
-
- Messaging.sendRequest(msg);
- }
- },
-
- _sendMessageSync: function(msg) {
- let res = null;
- Messaging.sendRequestForResult(msg).then(function(data) {
- res = data;
- });
-
- let thread = Services.tm.currentThread;
- while (res == null) {
- thread.processNextEvent(true);
- }
-
- return res;
- },
-};
diff --git a/mobile/android/modules/Home.jsm b/mobile/android/modules/Home.jsm
deleted file mode 100644
index e77d35dbd..000000000
--- a/mobile/android/modules/Home.jsm
+++ /dev/null
@@ -1,487 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["Home"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/SharedPreferences.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-// Keep this in sync with the constant defined in PanelAuthCache.java
-const PREFS_PANEL_AUTH_PREFIX = "home_panels_auth_";
-
-// Default weight for a banner message.
-const DEFAULT_WEIGHT = 100;
-
-// See bug 915424
-function resolveGeckoURI(aURI) {
- if (!aURI)
- throw "Can't resolve an empty uri";
-
- if (aURI.startsWith("chrome://")) {
- let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci["nsIChromeRegistry"]);
- return registry.convertChromeURL(Services.io.newURI(aURI, null, null)).spec;
- } else if (aURI.startsWith("resource://")) {
- let handler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
- return handler.resolveURI(Services.io.newURI(aURI, null, null));
- }
- return aURI;
-}
-
-function BannerMessage(options) {
- let uuidgen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
- this.id = uuidgen.generateUUID().toString();
-
- if ("text" in options && options.text != null)
- this.text = options.text;
-
- if ("icon" in options && options.icon != null)
- this.iconURI = resolveGeckoURI(options.icon);
-
- if ("onshown" in options && typeof options.onshown === "function")
- this.onshown = options.onshown;
-
- if ("onclick" in options && typeof options.onclick === "function")
- this.onclick = options.onclick;
-
- if ("ondismiss" in options && typeof options.ondismiss === "function")
- this.ondismiss = options.ondismiss;
-
- let weight = parseInt(options.weight, 10);
- this.weight = weight > 0 ? weight : DEFAULT_WEIGHT;
-}
-
-// We need this object to have access to the HomeBanner
-// private members without leaking it outside Home.jsm.
-var HomeBannerMessageHandlers;
-
-var HomeBanner = (function () {
- // Whether there is a "HomeBanner:Get" request we couldn't fulfill.
- let _pendingRequest = false;
-
- // Functions used to handle messages sent from Java.
- HomeBannerMessageHandlers = {
- "HomeBanner:Get": function handleBannerGet(data) {
- if (Object.keys(_messages).length > 0) {
- _sendBannerData();
- } else {
- _pendingRequest = true;
- }
- }
- };
-
- // Holds the messages that will rotate through the banner.
- let _messages = {};
-
- // Choose a random message from the set of messages, biasing towards those with higher weight.
- // Weight logic copied from desktop snippets:
- // https://github.com/mozilla/snippets-service/blob/7d80edb8b1cddaed075275c2fc7cdf69a10f4003/snippets/base/templates/base/includes/snippet_js.html#L119
- let _sendBannerData = function() {
- let totalWeight = 0;
- for (let key in _messages) {
- let message = _messages[key];
- totalWeight += message.weight;
- message.totalWeight = totalWeight;
- }
-
- let threshold = Math.random() * totalWeight;
- for (let key in _messages) {
- let message = _messages[key];
- if (threshold < message.totalWeight) {
- Messaging.sendRequest({
- type: "HomeBanner:Data",
- id: message.id,
- text: message.text,
- iconURI: message.iconURI
- });
- return;
- }
- }
- };
-
- let _handleShown = function(id) {
- let message = _messages[id];
- if (message.onshown)
- message.onshown();
- };
-
- let _handleClick = function(id) {
- let message = _messages[id];
- if (message.onclick)
- message.onclick();
- };
-
- let _handleDismiss = function(id) {
- let message = _messages[id];
- if (message.ondismiss)
- message.ondismiss();
- };
-
- return Object.freeze({
- observe: function(subject, topic, data) {
- switch(topic) {
- case "HomeBanner:Shown":
- _handleShown(data);
- break;
-
- case "HomeBanner:Click":
- _handleClick(data);
- break;
-
- case "HomeBanner:Dismiss":
- _handleDismiss(data);
- break;
- }
- },
-
- /**
- * Adds a new banner message to the rotation.
- *
- * @return id Unique identifer for the message.
- */
- add: function(options) {
- let message = new BannerMessage(options);
- _messages[message.id] = message;
-
- // If this is the first message we're adding, add
- // observers to listen for requests from the Java UI.
- if (Object.keys(_messages).length == 1) {
- Services.obs.addObserver(this, "HomeBanner:Shown", false);
- Services.obs.addObserver(this, "HomeBanner:Click", false);
- Services.obs.addObserver(this, "HomeBanner:Dismiss", false);
-
- // Send a message to Java if there's a pending "HomeBanner:Get" request.
- if (_pendingRequest) {
- _pendingRequest = false;
- _sendBannerData();
- }
- }
-
- return message.id;
- },
-
- /**
- * Removes a banner message from the rotation.
- *
- * @param id The id of the message to remove.
- */
- remove: function(id) {
- if (!(id in _messages)) {
- throw "Home.banner: Can't remove message that doesn't exist: id = " + id;
- }
-
- delete _messages[id];
-
- // If there are no more messages, remove the observers.
- if (Object.keys(_messages).length == 0) {
- Services.obs.removeObserver(this, "HomeBanner:Shown");
- Services.obs.removeObserver(this, "HomeBanner:Click");
- Services.obs.removeObserver(this, "HomeBanner:Dismiss");
- }
- }
- });
-})();
-
-// We need this object to have access to the HomePanels
-// private members without leaking it outside Home.jsm.
-var HomePanelsMessageHandlers;
-
-var HomePanels = (function () {
- // Functions used to handle messages sent from Java.
- HomePanelsMessageHandlers = {
-
- "HomePanels:Get": function handlePanelsGet(data) {
- data = JSON.parse(data);
-
- let requestId = data.requestId;
- let ids = data.ids || null;
-
- let panels = [];
- for (let id in _registeredPanels) {
- // Null ids means we want to fetch all available panels
- if (ids == null || ids.indexOf(id) >= 0) {
- try {
- panels.push(_generatePanel(id));
- } catch(e) {
- Cu.reportError("Home.panels: Invalid options, panel.id = " + id + ": " + e);
- }
- }
- }
-
- Messaging.sendRequest({
- type: "HomePanels:Data",
- panels: panels,
- requestId: requestId
- });
- },
-
- "HomePanels:Authenticate": function handlePanelsAuthenticate(id) {
- // Generate panel options to get auth handler.
- let options = _registeredPanels[id]();
- if (!options.auth) {
- throw "Home.panels: Invalid auth for panel.id = " + id;
- }
- if (!options.auth.authenticate || typeof options.auth.authenticate !== "function") {
- throw "Home.panels: Invalid auth authenticate function: panel.id = " + this.id;
- }
- options.auth.authenticate();
- },
-
- "HomePanels:RefreshView": function handlePanelsRefreshView(data) {
- data = JSON.parse(data);
-
- let options = _registeredPanels[data.panelId]();
- let view = options.views[data.viewIndex];
-
- if (!view) {
- throw "Home.panels: Invalid view for panel.id = " + data.panelId
- + ", view.index = " + data.viewIndex;
- }
-
- if (!view.onrefresh || typeof view.onrefresh !== "function") {
- throw "Home.panels: Invalid onrefresh for panel.id = " + data.panelId
- + ", view.index = " + data.viewIndex;
- }
-
- view.onrefresh();
- },
-
- "HomePanels:Installed": function handlePanelsInstalled(id) {
- _assertPanelExists(id);
-
- let options = _registeredPanels[id]();
- if (!options.oninstall) {
- return;
- }
- if (typeof options.oninstall !== "function") {
- throw "Home.panels: Invalid oninstall function: panel.id = " + this.id;
- }
- options.oninstall();
- },
-
- "HomePanels:Uninstalled": function handlePanelsUninstalled(id) {
- _assertPanelExists(id);
-
- let options = _registeredPanels[id]();
- if (!options.onuninstall) {
- return;
- }
- if (typeof options.onuninstall !== "function") {
- throw "Home.panels: Invalid onuninstall function: panel.id = " + this.id;
- }
- options.onuninstall();
- }
- };
-
- // Holds the current set of registered panels that can be
- // installed, updated, uninstalled, or unregistered. It maps
- // panel ids with the functions that dynamically generate
- // their respective panel options. This is used to retrieve
- // the current list of available panels in the system.
- // See HomePanels:Get handler.
- let _registeredPanels = {};
-
- // Valid layouts for a panel.
- let Layout = Object.freeze({
- FRAME: "frame"
- });
-
- // Valid types of views for a dataset.
- let View = Object.freeze({
- LIST: "list",
- GRID: "grid"
- });
-
- // Valid item types for a panel view.
- let Item = Object.freeze({
- ARTICLE: "article",
- IMAGE: "image",
- ICON: "icon"
- });
-
- // Valid item handlers for a panel view.
- let ItemHandler = Object.freeze({
- BROWSER: "browser",
- INTENT: "intent"
- });
-
- function Panel(id, options) {
- this.id = id;
- this.title = options.title;
- this.layout = options.layout;
- this.views = options.views;
- this.default = !!options.default;
-
- if (!this.id || !this.title) {
- throw "Home.panels: Can't create a home panel without an id and title!";
- }
-
- if (!this.layout) {
- // Use FRAME layout by default
- this.layout = Layout.FRAME;
- } else if (!_valueExists(Layout, this.layout)) {
- throw "Home.panels: Invalid layout for panel: panel.id = " + this.id + ", panel.layout =" + this.layout;
- }
-
- for (let view of this.views) {
- if (!_valueExists(View, view.type)) {
- throw "Home.panels: Invalid view type: panel.id = " + this.id + ", view.type = " + view.type;
- }
-
- if (!view.itemType) {
- if (view.type == View.LIST) {
- // Use ARTICLE item type by default in LIST views
- view.itemType = Item.ARTICLE;
- } else if (view.type == View.GRID) {
- // Use IMAGE item type by default in GRID views
- view.itemType = Item.IMAGE;
- }
- } else if (!_valueExists(Item, view.itemType)) {
- throw "Home.panels: Invalid item type: panel.id = " + this.id + ", view.itemType = " + view.itemType;
- }
-
- if (!view.itemHandler) {
- // Use BROWSER item handler by default
- view.itemHandler = ItemHandler.BROWSER;
- } else if (!_valueExists(ItemHandler, view.itemHandler)) {
- throw "Home.panels: Invalid item handler: panel.id = " + this.id + ", view.itemHandler = " + view.itemHandler;
- }
-
- if (!view.dataset) {
- throw "Home.panels: No dataset provided for view: panel.id = " + this.id + ", view.type = " + view.type;
- }
-
- if (view.onrefresh) {
- view.refreshEnabled = true;
- }
- }
-
- if (options.auth) {
- if (!options.auth.messageText) {
- throw "Home.panels: Invalid auth messageText: panel.id = " + this.id;
- }
- if (!options.auth.buttonText) {
- throw "Home.panels: Invalid auth buttonText: panel.id = " + this.id;
- }
-
- this.authConfig = {
- messageText: options.auth.messageText,
- buttonText: options.auth.buttonText
- };
-
- // Include optional image URL if it is specified.
- if (options.auth.imageUrl) {
- this.authConfig.imageUrl = options.auth.imageUrl;
- }
- }
-
- if (options.position >= 0) {
- this.position = options.position;
- }
- }
-
- let _generatePanel = function(id) {
- let options = _registeredPanels[id]();
- return new Panel(id, options);
- };
-
- // Helper function used to see if a value is in an object.
- let _valueExists = function(obj, value) {
- for (let key in obj) {
- if (obj[key] == value) {
- return true;
- }
- }
- return false;
- };
-
- let _assertPanelExists = function(id) {
- if (!(id in _registeredPanels)) {
- throw "Home.panels: Panel doesn't exist: id = " + id;
- }
- };
-
- return Object.freeze({
- Layout: Layout,
- View: View,
- Item: Item,
- ItemHandler: ItemHandler,
-
- register: function(id, optionsCallback) {
- // Bail if the panel already exists
- if (id in _registeredPanels) {
- throw "Home.panels: Panel already exists: id = " + id;
- }
-
- if (!optionsCallback || typeof optionsCallback !== "function") {
- throw "Home.panels: Panel callback must be a function: id = " + id;
- }
-
- _registeredPanels[id] = optionsCallback;
- },
-
- unregister: function(id) {
- _assertPanelExists(id);
-
- delete _registeredPanels[id];
- },
-
- install: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Install",
- panel: _generatePanel(id)
- });
- },
-
- uninstall: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Uninstall",
- id: id
- });
- },
-
- update: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Update",
- panel: _generatePanel(id)
- });
- },
-
- setAuthenticated: function(id, isAuthenticated) {
- _assertPanelExists(id);
-
- let authKey = PREFS_PANEL_AUTH_PREFIX + id;
- let sharedPrefs = SharedPreferences.forProfile();
- sharedPrefs.setBoolPref(authKey, isAuthenticated);
- }
- });
-})();
-
-// Public API
-this.Home = Object.freeze({
- banner: HomeBanner,
- panels: HomePanels,
-
- // Lazy notification observer registered in browser.js
- observe: function(subject, topic, data) {
- if (topic in HomeBannerMessageHandlers) {
- HomeBannerMessageHandlers[topic](data);
- } else if (topic in HomePanelsMessageHandlers) {
- HomePanelsMessageHandlers[topic](data);
- } else {
- Cu.reportError("Home.observe: message handler not found for topic: " + topic);
- }
- }
-});
diff --git a/mobile/android/modules/HomeProvider.jsm b/mobile/android/modules/HomeProvider.jsm
deleted file mode 100644
index bca8fa526..000000000
--- a/mobile/android/modules/HomeProvider.jsm
+++ /dev/null
@@ -1,407 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = [ "HomeProvider" ];
-
-const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-
-Cu.import("resource://gre/modules/Messaging.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Sqlite.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-/*
- * SCHEMA_VERSION history:
- * 1: Create HomeProvider (bug 942288)
- * 2: Add filter column to items table (bug 942295/975841)
- * 3: Add background_color and background_url columns (bug 1157539)
- */
-const SCHEMA_VERSION = 3;
-
-// The maximum number of items you can attempt to save at once.
-const MAX_SAVE_COUNT = 100;
-
-XPCOMUtils.defineLazyGetter(this, "DB_PATH", function() {
- return OS.Path.join(OS.Constants.Path.profileDir, "home.sqlite");
-});
-
-const PREF_STORAGE_LAST_SYNC_TIME_PREFIX = "home.storage.lastSyncTime.";
-const PREF_SYNC_UPDATE_MODE = "home.sync.updateMode";
-const PREF_SYNC_CHECK_INTERVAL_SECS = "home.sync.checkIntervalSecs";
-
-XPCOMUtils.defineLazyGetter(this, "gSyncCheckIntervalSecs", function() {
- return Services.prefs.getIntPref(PREF_SYNC_CHECK_INTERVAL_SECS);
-});
-
-XPCOMUtils.defineLazyServiceGetter(this,
- "gUpdateTimerManager", "@mozilla.org/updates/timer-manager;1", "nsIUpdateTimerManager");
-
-/**
- * All SQL statements should be defined here.
- */
-const SQL = {
- createItemsTable:
- "CREATE TABLE items (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
- "dataset_id TEXT NOT NULL, " +
- "url TEXT," +
- "title TEXT," +
- "description TEXT," +
- "image_url TEXT," +
- "background_color TEXT," +
- "background_url TEXT," +
- "filter TEXT," +
- "created INTEGER" +
- ")",
-
- dropItemsTable:
- "DROP TABLE items",
-
- insertItem:
- "INSERT INTO items (dataset_id, url, title, description, image_url, background_color, background_url, filter, created) " +
- "VALUES (:dataset_id, :url, :title, :description, :image_url, :background_color, :background_url, :filter, :created)",
-
- deleteFromDataset:
- "DELETE FROM items WHERE dataset_id = :dataset_id",
-
- addColumnBackgroundColor:
- "ALTER TABLE items ADD COLUMN background_color TEXT",
-
- addColumnBackgroundUrl:
- "ALTER TABLE items ADD COLUMN background_url TEXT",
-}
-
-/**
- * Technically this function checks to see if the user is on a local network,
- * but we express this as "wifi" to the user.
- */
-function isUsingWifi() {
- let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService);
- return (network.linkType === Ci.nsINetworkLinkService.LINK_TYPE_WIFI || network.linkType === Ci.nsINetworkLinkService.LINK_TYPE_ETHERNET);
-}
-
-function getNowInSeconds() {
- return Math.round(Date.now() / 1000);
-}
-
-function getLastSyncPrefName(datasetId) {
- return PREF_STORAGE_LAST_SYNC_TIME_PREFIX + datasetId;
-}
-
-// Whether or not we've registered an update timer.
-var gTimerRegistered = false;
-
-// Map of datasetId -> { interval: <integer>, callback: <function> }
-var gSyncCallbacks = {};
-
-/**
- * nsITimerCallback implementation. Checks to see if it's time to sync any registered datasets.
- *
- * @param timer The timer which has expired.
- */
-function syncTimerCallback(timer) {
- for (let datasetId in gSyncCallbacks) {
- let lastSyncTime = 0;
- try {
- lastSyncTime = Services.prefs.getIntPref(getLastSyncPrefName(datasetId));
- } catch(e) { }
-
- let now = getNowInSeconds();
- let { interval: interval, callback: callback } = gSyncCallbacks[datasetId];
-
- if (lastSyncTime < now - interval) {
- let success = HomeProvider.requestSync(datasetId, callback);
- if (success) {
- Services.prefs.setIntPref(getLastSyncPrefName(datasetId), now);
- }
- }
- }
-}
-
-this.HomeStorage = function(datasetId) {
- this.datasetId = datasetId;
-};
-
-this.ValidationError = function(message) {
- this.name = "ValidationError";
- this.message = message;
-};
-ValidationError.prototype = new Error();
-ValidationError.prototype.constructor = ValidationError;
-
-this.HomeProvider = Object.freeze({
- ValidationError: ValidationError,
-
- /**
- * Returns a storage associated with a given dataset identifer.
- *
- * @param datasetId
- * (string) Unique identifier for the dataset.
- *
- * @return HomeStorage
- */
- getStorage: function(datasetId) {
- return new HomeStorage(datasetId);
- },
-
- /**
- * Checks to see if it's an appropriate time to sync.
- *
- * @param datasetId Unique identifier for the dataset to sync.
- * @param callback Function to call when it's time to sync, called with datasetId as a parameter.
- *
- * @return boolean Whether or not we were able to sync.
- */
- requestSync: function(datasetId, callback) {
- // Make sure it's a good time to sync.
- if ((Services.prefs.getIntPref(PREF_SYNC_UPDATE_MODE) === 1) && !isUsingWifi()) {
- Cu.reportError("HomeProvider: Failed to sync because device is not on a local network");
- return false;
- }
-
- callback(datasetId);
- return true;
- },
-
- /**
- * Specifies that a sync should be requested for the given dataset and update interval.
- *
- * @param datasetId Unique identifier for the dataset to sync.
- * @param interval Update interval in seconds. By default, this is throttled to 3600 seconds (1 hour).
- * @param callback Function to call when it's time to sync, called with datasetId as a parameter.
- */
- addPeriodicSync: function(datasetId, interval, callback) {
- // Warn developers if they're expecting more frequent notifications that we allow.
- if (interval < gSyncCheckIntervalSecs) {
- Cu.reportError("HomeProvider: Warning for dataset " + datasetId +
- " : Sync notifications are throttled to " + gSyncCheckIntervalSecs + " seconds");
- }
-
- gSyncCallbacks[datasetId] = {
- interval: interval,
- callback: callback
- };
-
- if (!gTimerRegistered) {
- gUpdateTimerManager.registerTimer("home-provider-sync-timer", syncTimerCallback, gSyncCheckIntervalSecs);
- gTimerRegistered = true;
- }
- },
-
- /**
- * Removes a periodic sync timer.
- *
- * @param datasetId Dataset to sync.
- */
- removePeriodicSync: function(datasetId) {
- delete gSyncCallbacks[datasetId];
- Services.prefs.clearUserPref(getLastSyncPrefName(datasetId));
- // You can't unregister a update timer, so we don't try to do that.
- }
-});
-
-var gDatabaseEnsured = false;
-
-/**
- * Creates the database schema.
- */
-function createDatabase(db) {
- return Task.spawn(function create_database_task() {
- yield db.execute(SQL.createItemsTable);
- });
-}
-
-/**
- * Migrates the database schema to a new version.
- */
-function upgradeDatabase(db, oldVersion, newVersion) {
- return Task.spawn(function upgrade_database_task() {
- switch (oldVersion) {
- case 1:
- // Migration from v1 to latest:
- // Recreate the items table discarding any
- // existing data.
- yield db.execute(SQL.dropItemsTable);
- yield db.execute(SQL.createItemsTable);
- break;
-
- case 2:
- // Migration from v2 to latest:
- // Add new columns: background_color, background_url
- yield db.execute(SQL.addColumnBackgroundColor);
- yield db.execute(SQL.addColumnBackgroundUrl);
- break;
- }
- });
-}
-
-/**
- * Opens a database connection and makes sure that the database schema version
- * is correct, performing migrations if necessary. Consumers should be sure
- * to close any database connections they open.
- *
- * @return Promise
- * @resolves Handle on an opened SQLite database.
- */
-function getDatabaseConnection() {
- return Task.spawn(function get_database_connection_task() {
- let db = yield Sqlite.openConnection({ path: DB_PATH });
- if (gDatabaseEnsured) {
- throw new Task.Result(db);
- }
-
- try {
- // Check to see if we need to perform any migrations.
- let dbVersion = parseInt(yield db.getSchemaVersion());
-
- // getSchemaVersion() returns a 0 int if the schema
- // version is undefined.
- if (dbVersion === 0) {
- yield createDatabase(db);
- } else if (dbVersion < SCHEMA_VERSION) {
- yield upgradeDatabase(db, dbVersion, SCHEMA_VERSION);
- }
-
- yield db.setSchemaVersion(SCHEMA_VERSION);
- } catch(e) {
- // Close the DB connection before passing the exception to the consumer.
- yield db.close();
- throw e;
- }
-
- gDatabaseEnsured = true;
- throw new Task.Result(db);
- });
-}
-
-/**
- * Validates an item to be saved to the DB.
- *
- * @param item
- * (object) item object to be validated.
- */
-function validateItem(datasetId, item) {
- if (!item.url) {
- throw new ValidationError('HomeStorage: All rows must have an URL: datasetId = ' +
- datasetId);
- }
-
- if (!item.image_url && !item.title && !item.description) {
- throw new ValidationError('HomeStorage: All rows must have at least an image URL, ' +
- 'or a title or a description: datasetId = ' + datasetId);
- }
-}
-
-var gRefreshTimers = {};
-
-/**
- * Sends a message to Java to refresh the given dataset. Delays sending
- * messages to avoid successive refreshes, which can result in flashing views.
- */
-function refreshDataset(datasetId) {
- // Bail if there's already a refresh timer waiting to fire
- if (gRefreshTimers[datasetId]) {
- return;
- }
-
- let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- timer.initWithCallback(function(timer) {
- delete gRefreshTimers[datasetId];
-
- Messaging.sendRequest({
- type: "HomePanels:RefreshDataset",
- datasetId: datasetId
- });
- }, 100, Ci.nsITimer.TYPE_ONE_SHOT);
-
- gRefreshTimers[datasetId] = timer;
-}
-
-HomeStorage.prototype = {
- /**
- * Saves data rows to the DB.
- *
- * @param data
- * An array of JS objects represnting row items to save.
- * Each object may have the following properties:
- * - url (string)
- * - title (string)
- * - description (string)
- * - image_url (string)
- * - filter (string)
- * @param options
- * A JS object holding additional cofiguration properties.
- * The following properties are currently supported:
- * - replace (boolean): Whether or not to replace existing items.
- *
- * @return Promise
- * @resolves When the operation has completed.
- */
- save: function(data, options) {
- if (data && data.length > MAX_SAVE_COUNT) {
- throw "save failed for dataset = " + this.datasetId +
- ": you cannot save more than " + MAX_SAVE_COUNT + " items at once";
- }
-
- return Task.spawn(function save_task() {
- let db = yield getDatabaseConnection();
- try {
- yield db.executeTransaction(function save_transaction() {
- if (options && options.replace) {
- yield db.executeCached(SQL.deleteFromDataset, { dataset_id: this.datasetId });
- }
-
- // Insert data into DB.
- for (let item of data) {
- validateItem(this.datasetId, item);
-
- // XXX: Directly pass item as params? More validation for item?
- let params = {
- dataset_id: this.datasetId,
- url: item.url,
- title: item.title,
- description: item.description,
- image_url: item.image_url,
- background_color: item.background_color,
- background_url: item.background_url,
- filter: item.filter,
- created: Date.now()
- };
- yield db.executeCached(SQL.insertItem, params);
- }
- }.bind(this));
- } finally {
- yield db.close();
- }
-
- refreshDataset(this.datasetId);
- }.bind(this));
- },
-
- /**
- * Deletes all rows associated with this storage.
- *
- * @return Promise
- * @resolves When the operation has completed.
- */
- deleteAll: function() {
- return Task.spawn(function delete_all_task() {
- let db = yield getDatabaseConnection();
- try {
- let params = { dataset_id: this.datasetId };
- yield db.executeCached(SQL.deleteFromDataset, params);
- } finally {
- yield db.close();
- }
-
- refreshDataset(this.datasetId);
- }.bind(this));
- }
-};
diff --git a/mobile/android/modules/JNI.jsm b/mobile/android/modules/JNI.jsm
deleted file mode 100644
index 1e10b9cfb..000000000
--- a/mobile/android/modules/JNI.jsm
+++ /dev/null
@@ -1,1167 +0,0 @@
-// JavaScript to Java bridge via the Java Native Interface
-// Allows calling into Android SDK from JavaScript in Firefox Add-On.
-// Released into the public domain.
-// C. Scott Ananian <cscott@laptop.org> (http://cscott.net)
-
-// NOTE: All changes to this file should first be pushed to the repo at:
-// https://github.com/cscott/skeleton-addon-fxandroid/tree/jni
-
-var EXPORTED_SYMBOLS = ["JNI","android_log"];
-
-Components.utils.import("resource://gre/modules/ctypes.jsm")
-
-var liblog = ctypes.open('liblog.so');
-var android_log = liblog.declare("__android_log_write",
- ctypes.default_abi,
- ctypes.int32_t,
- ctypes.int32_t,
- ctypes.char.ptr,
- ctypes.char.ptr);
-
-var libxul = ctypes.open('libxul.so');
-
-var jenvptr = ctypes.voidptr_t;
-var jclass = ctypes.voidptr_t;
-var jobject = ctypes.voidptr_t;
-var jvalue = ctypes.voidptr_t;
-var jmethodid = ctypes.voidptr_t;
-var jfieldid = ctypes.voidptr_t;
-
-var jboolean = ctypes.uint8_t;
-var jbyte = ctypes.int8_t;
-var jchar = ctypes.uint16_t;
-var jshort = ctypes.int16_t;
-var jint = ctypes.int32_t;
-var jlong = ctypes.int64_t;
-var jfloat = ctypes.float32_t;
-var jdouble = ctypes.float64_t;
-
-var jsize = jint;
-var jstring = jobject;
-var jarray = jobject;
-var jthrowable = jobject;
-
-var JNINativeInterface = new ctypes.StructType(
- "JNINativeInterface",
- [{reserved0: ctypes.voidptr_t},
- {reserved1: ctypes.voidptr_t},
- {reserved2: ctypes.voidptr_t},
- {reserved3: ctypes.voidptr_t},
- {GetVersion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.int32_t,
- [ctypes.voidptr_t]).ptr},
- {DefineClass: new ctypes.FunctionType(ctypes.default_abi,
- jclass,
- [jenvptr, ctypes.char.ptr, jobject,
- jbyte.array(), jsize]).ptr},
- {FindClass: new ctypes.FunctionType(ctypes.default_abi,
- jclass,
- [jenvptr,
- ctypes.char.ptr]).ptr},
- {FromReflectedMethod: new ctypes.FunctionType(ctypes.default_abi,
- jmethodid,
- [jenvptr, jobject]).ptr},
- {FromReflectedField: new ctypes.FunctionType(ctypes.default_abi,
- jfieldid,
- [jenvptr, jobject]).ptr},
- {ToReflectedMethod: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jclass,
- jmethodid]).ptr},
- {GetSuperclass: new ctypes.FunctionType(ctypes.default_abi,
- jclass, [jenvptr, jclass]).ptr},
- {IsAssignableFrom: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jclass, jclass]).ptr},
- {ToReflectedField: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {Throw: new ctypes.FunctionType(ctypes.default_abi,
- jint, [jenvptr, jthrowable]).ptr},
- {ThrowNew: new ctypes.FunctionType(ctypes.default_abi,
- jint, [jenvptr, jclass,
- ctypes.char.ptr]).ptr},
- {ExceptionOccurred: new ctypes.FunctionType(ctypes.default_abi,
- jthrowable, [jenvptr]).ptr},
- {ExceptionDescribe: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t, [jenvptr]).ptr},
- {ExceptionClear: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t, [jenvptr]).ptr},
- {FatalError: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr,
- ctypes.char.ptr]).ptr},
- {PushLocalFrame: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr, jint]).ptr},
- {PopLocalFrame: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jobject]).ptr},
- {NewGlobalRef: new ctypes.FunctionType(ctypes.default_abi,
- jobject, [jenvptr, jobject]).ptr},
- {DeleteGlobalRef: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr,
- jobject]).ptr},
- {DeleteLocalRef: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr,
- jobject]).ptr},
- {IsSameObject: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jobject, jobject]).ptr},
- {NewLocalRef: new ctypes.FunctionType(ctypes.default_abi,
- jobject, [jenvptr, jobject]).ptr},
- {EnsureLocalCapacity: new ctypes.FunctionType(ctypes.default_abi,
- jint, [jenvptr, jint]).ptr},
- {AllocObject: new ctypes.FunctionType(ctypes.default_abi,
- jobject, [jenvptr, jclass]).ptr},
- {NewObject: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr,
- jclass,
- jmethodid,
- "..."]).ptr},
- {NewObjectV: ctypes.voidptr_t},
- {NewObjectA: ctypes.voidptr_t},
- {GetObjectClass: new ctypes.FunctionType(ctypes.default_abi,
- jclass,
- [jenvptr, jobject]).ptr},
- {IsInstanceOf: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jobject, jclass]).ptr},
- {GetMethodID: new ctypes.FunctionType(ctypes.default_abi,
- jmethodid,
- [jenvptr,
- jclass,
- ctypes.char.ptr,
- ctypes.char.ptr]).ptr},
- {CallObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jobject, jmethodid,
- "..."]).ptr},
- {CallObjectMethodV: ctypes.voidptr_t},
- {CallObjectMethodA: ctypes.voidptr_t},
- {CallBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallBooleanMethodV: ctypes.voidptr_t},
- {CallBooleanMethodA: ctypes.voidptr_t},
- {CallByteMethod: new ctypes.FunctionType(ctypes.default_abi,
- jbyte,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallByteMethodV: ctypes.voidptr_t},
- {CallByteMethodA: ctypes.voidptr_t},
- {CallCharMethod: new ctypes.FunctionType(ctypes.default_abi,
- jchar,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallCharMethodV: ctypes.voidptr_t},
- {CallCharMethodA: ctypes.voidptr_t},
- {CallShortMethod: new ctypes.FunctionType(ctypes.default_abi,
- jshort,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallShortMethodV: ctypes.voidptr_t},
- {CallShortMethodA: ctypes.voidptr_t},
- {CallIntMethod: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallIntMethodV: ctypes.voidptr_t},
- {CallIntMethodA: ctypes.voidptr_t},
- {CallLongMethod: new ctypes.FunctionType(ctypes.default_abi,
- jlong,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallLongMethodV: ctypes.voidptr_t},
- {CallLongMethodA: ctypes.voidptr_t},
- {CallFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
- jfloat,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallFloatMethodV: ctypes.voidptr_t},
- {CallFloatMethodA: ctypes.voidptr_t},
- {CallDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
- jdouble,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallDoubleMethodV: ctypes.voidptr_t},
- {CallDoubleMethodA: ctypes.voidptr_t},
- {CallVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr,
- jobject,
- jmethodid,
- "..."]).ptr},
- {CallVoidMethodV: ctypes.voidptr_t},
- {CallVoidMethodA: ctypes.voidptr_t},
- {CallNonvirtualObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualObjectMethodV: ctypes.voidptr_t},
- {CallNonvirtualObjectMethodA: ctypes.voidptr_t},
- {CallNonvirtualBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualBooleanMethodV: ctypes.voidptr_t},
- {CallNonvirtualBooleanMethodA: ctypes.voidptr_t},
- {CallNonvirtualByteMethod: new ctypes.FunctionType(ctypes.default_abi,
- jbyte,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualByteMethodV: ctypes.voidptr_t},
- {CallNonvirtualByteMethodA: ctypes.voidptr_t},
- {CallNonvirtualCharMethod: new ctypes.FunctionType(ctypes.default_abi,
- jchar,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualCharMethodV: ctypes.voidptr_t},
- {CallNonvirtualCharMethodA: ctypes.voidptr_t},
- {CallNonvirtualShortMethod: new ctypes.FunctionType(ctypes.default_abi,
- jshort,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualShortMethodV: ctypes.voidptr_t},
- {CallNonvirtualShortMethodA: ctypes.voidptr_t},
- {CallNonvirtualIntMethod: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualIntMethodV: ctypes.voidptr_t},
- {CallNonvirtualIntMethodA: ctypes.voidptr_t},
- {CallNonvirtualLongMethod: new ctypes.FunctionType(ctypes.default_abi,
- jlong,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualLongMethodV: ctypes.voidptr_t},
- {CallNonvirtualLongMethodA: ctypes.voidptr_t},
- {CallNonvirtualFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
- jfloat,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualFloatMethodV: ctypes.voidptr_t},
- {CallNonvirtualFloatMethodA: ctypes.voidptr_t},
- {CallNonvirtualDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
- jdouble,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualDoubleMethodV: ctypes.voidptr_t},
- {CallNonvirtualDoubleMethodA: ctypes.voidptr_t},
- {CallNonvirtualVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jclass, jmethodid,
- "..."]).ptr},
- {CallNonvirtualVoidMethodV: ctypes.voidptr_t},
- {CallNonvirtualVoidMethodA: ctypes.voidptr_t},
- {GetFieldID: new ctypes.FunctionType(ctypes.default_abi,
- jfieldid,
- [jenvptr, jclass,
- ctypes.char.ptr,
- ctypes.char.ptr]).ptr},
- {GetObjectField: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetBooleanField: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetByteField: new ctypes.FunctionType(ctypes.default_abi,
- jbyte,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetCharField: new ctypes.FunctionType(ctypes.default_abi,
- jchar,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetShortField: new ctypes.FunctionType(ctypes.default_abi,
- jshort,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetIntField: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetLongField: new ctypes.FunctionType(ctypes.default_abi,
- jlong,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetFloatField: new ctypes.FunctionType(ctypes.default_abi,
- jfloat,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {GetDoubleField: new ctypes.FunctionType(ctypes.default_abi,
- jdouble,
- [jenvptr, jobject,
- jfieldid]).ptr},
- {SetObjectField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jobject]).ptr},
- {SetBooleanField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jboolean]).ptr},
- {SetByteField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jbyte]).ptr},
- {SetCharField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jchar]).ptr},
- {SetShortField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jshort]).ptr},
- {SetIntField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jint]).ptr},
- {SetLongField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jlong]).ptr},
- {SetFloatField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jfloat]).ptr},
- {SetDoubleField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jobject,
- jfieldid, jdouble]).ptr},
- {GetStaticMethodID: new ctypes.FunctionType(ctypes.default_abi,
- jmethodid,
- [jenvptr,
- jclass,
- ctypes.char.ptr,
- ctypes.char.ptr]).ptr},
- {CallStaticObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticObjectMethodV: ctypes.voidptr_t},
- {CallStaticObjectMethodA: ctypes.voidptr_t},
- {CallStaticBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticBooleanMethodV: ctypes.voidptr_t},
- {CallStaticBooleanMethodA: ctypes.voidptr_t},
- {CallStaticByteMethod: new ctypes.FunctionType(ctypes.default_abi,
- jbyte,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticByteMethodV: ctypes.voidptr_t},
- {CallStaticByteMethodA: ctypes.voidptr_t},
- {CallStaticCharMethod: new ctypes.FunctionType(ctypes.default_abi,
- jchar,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticCharMethodV: ctypes.voidptr_t},
- {CallStaticCharMethodA: ctypes.voidptr_t},
- {CallStaticShortMethod: new ctypes.FunctionType(ctypes.default_abi,
- jshort,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticShortMethodV: ctypes.voidptr_t},
- {CallStaticShortMethodA: ctypes.voidptr_t},
- {CallStaticIntMethod: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticIntMethodV: ctypes.voidptr_t},
- {CallStaticIntMethodA: ctypes.voidptr_t},
- {CallStaticLongMethod: new ctypes.FunctionType(ctypes.default_abi,
- jlong,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticLongMethodV: ctypes.voidptr_t},
- {CallStaticLongMethodA: ctypes.voidptr_t},
- {CallStaticFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
- jfloat,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticFloatMethodV: ctypes.voidptr_t},
- {CallStaticFloatMethodA: ctypes.voidptr_t},
- {CallStaticDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
- jdouble,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticDoubleMethodV: ctypes.voidptr_t},
- {CallStaticDoubleMethodA: ctypes.voidptr_t},
- {CallStaticVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jmethodid,
- "..."]).ptr},
- {CallStaticVoidMethodV: ctypes.voidptr_t},
- {CallStaticVoidMethodA: ctypes.voidptr_t},
- {GetStaticFieldID: new ctypes.FunctionType(ctypes.default_abi,
- jfieldid,
- [jenvptr, jclass,
- ctypes.char.ptr,
- ctypes.char.ptr]).ptr},
- {GetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi,
- jboolean,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticByteField: new ctypes.FunctionType(ctypes.default_abi,
- jbyte,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticCharField: new ctypes.FunctionType(ctypes.default_abi,
- jchar,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticShortField: new ctypes.FunctionType(ctypes.default_abi,
- jshort,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticIntField: new ctypes.FunctionType(ctypes.default_abi,
- jint,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticLongField: new ctypes.FunctionType(ctypes.default_abi,
- jlong,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi,
- jfloat,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {GetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi,
- jdouble,
- [jenvptr, jclass,
- jfieldid]).ptr},
- {SetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jobject]).ptr},
- {SetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jboolean]).ptr},
- {SetStaticByteField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jbyte]).ptr},
- {SetStaticCharField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jchar]).ptr},
- {SetStaticShortField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jshort]).ptr},
- {SetStaticIntField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jint]).ptr},
- {SetStaticLongField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jlong]).ptr},
- {SetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jfloat]).ptr},
- {SetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jclass,
- jfieldid, jdouble]).ptr},
-
- {NewString: new ctypes.FunctionType(ctypes.default_abi,
- jstring,
- [jenvptr, jchar.ptr, jsize]).ptr},
- {GetStringLength: new ctypes.FunctionType(ctypes.default_abi,
- jsize,
- [jenvptr, jstring]).ptr},
- {GetStringChars: new ctypes.FunctionType(ctypes.default_abi,
- jchar.ptr,
- [jenvptr, jstring,
- jboolean.ptr]).ptr},
- {ReleaseStringChars: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jstring,
- jchar.ptr]).ptr},
-
- {NewStringUTF: new ctypes.FunctionType(ctypes.default_abi,
- jstring,
- [jenvptr,
- ctypes.char.ptr]).ptr},
- {GetStringUTFLength: new ctypes.FunctionType(ctypes.default_abi,
- jsize,
- [jenvptr, jstring]).ptr},
- {GetStringUTFChars: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.char.ptr,
- [jenvptr, jstring,
- jboolean.ptr]).ptr},
- {ReleaseStringUTFChars: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jstring,
- ctypes.char.ptr]).ptr},
- {GetArrayLength: new ctypes.FunctionType(ctypes.default_abi,
- jsize,
- [jenvptr, jarray]).ptr},
- {NewObjectArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize,
- jclass, jobject]).ptr},
- {GetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi,
- jobject,
- [jenvptr, jarray,
- jsize]).ptr},
- {SetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jobject]).ptr},
- {NewBooleanArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewByteArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewCharArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewShortArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewIntArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewLongArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewFloatArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {NewDoubleArray: new ctypes.FunctionType(ctypes.default_abi,
- jarray,
- [jenvptr, jsize]).ptr},
- {GetBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jboolean.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetByteArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jbyte.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetCharArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jchar.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetShortArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jshort.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetIntArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jint.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetLongArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jlong.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jfloat.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {GetDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- jdouble.ptr,
- [jenvptr, jarray,
- jboolean.ptr]).ptr},
- {ReleaseBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jboolean.ptr,
- jint]).ptr},
- {ReleaseByteArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jbyte.ptr,
- jint]).ptr},
- {ReleaseCharArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jchar.ptr,
- jint]).ptr},
- {ReleaseShortArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jshort.ptr,
- jint]).ptr},
- {ReleaseIntArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jint.ptr,
- jint]).ptr},
- {ReleaseLongArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jlong.ptr,
- jint]).ptr},
- {ReleaseFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jfloat.ptr,
- jint]).ptr},
- {ReleaseDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jdouble.ptr,
- jint]).ptr},
- {GetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jboolean.array()]).ptr},
- {GetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jbyte.array()]).ptr},
- {GetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jchar.array()]).ptr},
- {GetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jshort.array()]).ptr},
- {GetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jint.array()]).ptr},
- {GetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jlong.array()]).ptr},
- {GetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jfloat.array()]).ptr},
- {GetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jdouble.array()]).ptr},
- {SetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jboolean.array()]).ptr},
- {SetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jbyte.array()]).ptr},
- {SetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jchar.array()]).ptr},
- {SetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jshort.array()]).ptr},
- {SetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jint.array()]).ptr},
- {SetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jlong.array()]).ptr},
- {SetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jfloat.array()]).ptr},
- {SetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jarray,
- jsize, jsize,
- jdouble.array()]).ptr},
- {RegisterNatives: ctypes.voidptr_t},
- {UnregisterNatives: ctypes.voidptr_t},
- {MonitorEnter: new ctypes.FunctionType(ctypes.default_abi,
- jint, [jenvptr, jobject]).ptr},
- {MonitorExit: new ctypes.FunctionType(ctypes.default_abi,
- jint, [jenvptr, jobject]).ptr},
- {GetJavaVM: ctypes.voidptr_t},
- {GetStringRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jstring,
- jsize, jsize,
- jchar.array()]).ptr},
- {GetStringUTFRegion: new ctypes.FunctionType(ctypes.default_abi,
- ctypes.void_t,
- [jenvptr, jstring,
- jsize, jsize,
- ctypes.char.array()]).ptr},
- {GetPrimitiveArrayCritical: ctypes.voidptr_t},
- {ReleasePrimitiveArrayCritical: ctypes.voidptr_t},
- {GetStringCritical: ctypes.voidptr_t},
- {ReleaseStringCritical: ctypes.voidptr_t},
- {NewWeakGlobalRef: ctypes.voidptr_t},
- {DeleteWeakGlobalRef: ctypes.voidptr_t},
- {ExceptionCheck: new ctypes.FunctionType(ctypes.default_abi,
- jboolean, [jenvptr]).ptr},
- {NewDirectByteBuffer: ctypes.voidptr_t},
- {GetDirectBufferAddress: ctypes.voidptr_t},
- {GetDirectBufferCapacity: ctypes.voidptr_t},
- {GetObjectRefType: ctypes.voidptr_t}]
-);
-
-var GetJNIForThread = libxul.declare("GetJNIForThread",
- ctypes.default_abi,
- JNINativeInterface.ptr.ptr);
-
-var registry = Object.create(null);
-var classes = Object.create(null);
-
-function JNIUnloadClasses(jenv) {
- Object.getOwnPropertyNames(registry).forEach(function(classname) {
- var jcls = unwrap(registry[classname]);
- jenv.contents.contents.DeleteGlobalRef(jenv, jcls);
-
- // Purge the registry, so we don't try to reuse stale global references
- // in JNI calls and we garbage-collect the JS global reference objects.
- delete registry[classname];
- });
-
- // The refs also get added to the 'classes' object, so we should purge it too.
- // That object is a hierarchical data structure organized by class path parts,
- // but deleting its own properties should be sufficient to break its refs.
- Object.getOwnPropertyNames(classes).forEach(function(topLevelPart) {
- delete classes[topLevelPart];
- });
-}
-
-var PREFIX = 'js#';
-// this regex matches one component of a type signature:
-// any number of array modifiers, followed by either a
-// primitive type character or L<classname>;
-var sigRegex = () => /\[*([VZBCSIJFD]|L([^.\/;]+(\/[^.\/;]+)*);)/g;
-var ensureSig = function(classname_or_signature) {
- // convert a classname into a signature,
- // leaving unchanged signatures. We assume that
- // anything not a valid signature is a classname.
- var m = sigRegex().exec(classname_or_signature);
- return (m && m[0] === classname_or_signature) ? classname_or_signature :
- 'L' + classname_or_signature.replace(/\./g, '/') + ';';
-};
-var wrap = function(obj, classSig) {
- if (!classSig) { return obj; }
- // don't wrap primitive types.
- if (classSig.charAt(0)!=='L' &&
- classSig.charAt(0)!=='[') { return obj; }
- var proto = registry[classSig][PREFIX+'proto'];
- return new proto(obj);
-};
-var unwrap = function(obj, opt_jenv, opt_ctype) {
- if (obj && typeof(obj)==='object' && (PREFIX+'obj') in obj) {
- return obj[PREFIX+'obj'];
- } else if (opt_jenv && opt_ctype) {
- if (opt_ctype !== jobject)
- return opt_ctype(obj); // cast to given primitive ctype
- if (typeof(obj)==='string')
- return unwrap(JNINewString(opt_jenv, obj)); // create Java String
- }
- return obj;
-};
-var ensureLoaded = function(jenv, classSig) {
- if (!Object.hasOwnProperty.call(registry, classSig)) {
- JNILoadClass(jenv, classSig);
- }
- return registry[classSig];
-};
-
-function JNINewString(jenv, value) {
- var s = jenv.contents.contents.NewStringUTF(jenv, ctypes.char.array()(value));
- ensureLoaded(jenv, "Ljava/lang/String;");
- return wrap(s, "Ljava/lang/String;");
-}
-
-function JNIReadString(jenv, jstring_value) {
- var val = unwrap(jstring_value);
- if ((!val) || val.isNull()) { return null; }
- var chars = jenv.contents.contents.GetStringUTFChars(jenv, val, null);
- var result = chars.readString();
- jenv.contents.contents.ReleaseStringUTFChars(jenv, val, chars);
- return result;
-}
-
-var sigInfo = {
- 'V': { name: 'Void', longName: 'Void', ctype: ctypes.void_t },
- 'Z': { name: 'Boolean', longName: 'Boolean', ctype: jboolean },
- 'B': { name: 'Byte', longName: 'Byte', ctype: jbyte },
- 'C': { name: 'Char', longName: 'Char', ctype: jchar },
- 'S': { name: 'Short', longName: 'Short', ctype: jshort },
- 'I': { name: 'Int', longName: 'Integer', ctype: jint },
- 'J': { name: 'Long', longName: 'Long', ctype: jlong },
- 'F': { name: 'Float', longName: 'Float', ctype: jfloat },
- 'D': { name: 'Double', longName: 'Double', ctype: jdouble },
- 'L': { name: 'Object', longName: 'Object', ctype: jobject },
- '[': { name: 'Object', longName: 'Object', ctype: jarray }
-};
-
-var sig2type = function(sig) { return sigInfo[sig.charAt(0)].name; };
-var sig2ctype = function(sig) { return sigInfo[sig.charAt(0)].ctype; };
-var sig2prim = function(sig) { return sigInfo[sig.charAt(0)].longName; };
-
-// return the class object for a signature string.
-// allocates 1 or 2 local refs
-function JNIClassObj(jenv, classSig) {
- var jenvpp = function() { return jenv.contents.contents; };
- // Deal with funny calling convention of JNI FindClass method.
- // Classes get the leading & trailing chars stripped; primitives
- // have to be looked up via their wrapper type.
- var prim = function(ty) {
- var jcls = jenvpp().FindClass(jenv, "java/lang/"+ty);
- var jfld = jenvpp().GetStaticFieldID(jenv, jcls, "TYPE",
- "Ljava/lang/Class;");
- return jenvpp().GetStaticObjectField(jenv, jcls, jfld);
- };
- switch (classSig.charAt(0)) {
- case '[':
- return jenvpp().FindClass(jenv, classSig);
- case 'L':
- classSig = classSig.substring(1, classSig.indexOf(';'));
- return jenvpp().FindClass(jenv, classSig);
- default:
- return prim(sig2prim(classSig));
- }
-}
-
-// return the signature string for a Class object.
-// allocates 2 local refs
-function JNIClassSig(jenv, jcls) {
- var jenvpp = function() { return jenv.contents.contents; };
- var jclscls = jenvpp().FindClass(jenv, "java/lang/Class");
- var jmtd = jenvpp().GetMethodID(jenv, jclscls,
- "getName", "()Ljava/lang/String;");
- var name = jenvpp().CallObjectMethod(jenv, jcls, jmtd);
- name = JNIReadString(jenv, name);
- // API is weird. Make sure we're using slashes not dots
- name = name.replace(/\./g, '/');
- // special case primitives, arrays
- if (name.charAt(0)==='[') return name;
- switch(name) {
- case 'void': return 'V';
- case 'boolean': return 'Z';
- case 'byte': return 'B';
- case 'char': return 'C';
- case 'short': return 'S';
- case 'int': return 'I';
- case 'long': return 'J';
- case 'float': return 'F';
- case 'double': return 'D';
- default:
- return 'L' + name + ';';
- }
-}
-
-// create dispatch method
-// we resolve overloaded methods only by # of arguments. If you need
-// further resolution, use the 'long form' of the method name, ie:
-// obj['toString()Ljava/lang/String'].call(obj);
-var overloadFunc = function(basename) {
- return function() {
- return this[basename+'('+arguments.length+')'].apply(this, arguments);
- };
-};
-
-// Create appropriate wrapper fields/methods for a Java class.
-function JNILoadClass(jenv, classSig, opt_props) {
- var jenvpp = function() { return jenv.contents.contents; };
- var props = opt_props || {};
-
- // allocate a local reference frame with enough space
- // this class (1 or 2 local refs) plus superclass (3 refs)
- // plus array element class (1 or 2 local refs)
- var numLocals = 7;
- jenvpp().PushLocalFrame(jenv, numLocals);
-
- var jcls;
- if (Object.hasOwnProperty.call(registry, classSig)) {
- jcls = unwrap(registry[classSig]);
- } else {
- jcls = jenvpp().NewGlobalRef(jenv, JNIClassObj(jenv, classSig));
-
- // get name of superclass
- var jsuper = jenvpp().GetSuperclass(jenv, jcls);
- if (jsuper.isNull()) {
- jsuper = null;
- } else {
- jsuper = JNIClassSig(jenv, jsuper);
- }
-
- registry[classSig] = Object.create(jsuper?ensureLoaded(jenv, jsuper):null);
- registry[classSig][PREFIX+'obj'] = jcls; // global ref, persistent.
- registry[classSig][PREFIX+'proto'] =
- function(o) { this[PREFIX+'obj'] = o; };
- registry[classSig][PREFIX+'proto'].prototype =
- Object.create(jsuper ?
- ensureLoaded(jenv, jsuper)[PREFIX+'proto'].prototype :
- null);
- // Add a __cast__ method to the wrapper corresponding to the class
- registry[classSig].__cast__ = function(obj) {
- return wrap(unwrap(obj), classSig);
- };
-
- // make wrapper accessible via the classes object.
- var path = sig2type(classSig).toLowerCase();
- if (classSig.charAt(0)==='L') {
- path = classSig.substring(1, classSig.length-1);
- }
- if (classSig.charAt(0)!=='[') {
- var root = classes, i;
- var parts = path.split('/');
- for (i = 0; i < parts.length-1; i++) {
- if (!Object.hasOwnProperty.call(root, parts[i])) {
- root[parts[i]] = Object.create(null);
- }
- root = root[parts[i]];
- }
- root[parts[parts.length-1]] = registry[classSig];
- }
- }
-
- var r = registry[classSig];
- var rpp = r[PREFIX+'proto'].prototype;
-
- if (classSig.charAt(0)==='[') {
- // add 'length' field for arrays
- Object.defineProperty(rpp, 'length', {
- get: function() {
- return jenvpp().GetArrayLength(jenv, unwrap(this));
- }
- });
- // add 'get' and 'set' methods, 'new' constructor
- var elemSig = classSig.substring(1);
- ensureLoaded(jenv, elemSig);
-
- registry[elemSig].__array__ = r;
- if (!Object.hasOwnProperty.call(registry[elemSig], 'array'))
- registry[elemSig].array = r;
-
- if (elemSig.charAt(0)==='L' || elemSig.charAt(0)==='[') {
- var elemClass = unwrap(registry[elemSig]);
-
- rpp.get = function(idx) {
- return wrap(jenvpp().GetObjectArrayElement(jenv, unwrap(this), idx),
- elemSig);
- };
- rpp.set = function(idx, value) {
- jenvpp().SetObjectArrayElement(jenv, unwrap(this), idx,
- unwrap(value, jenv, jobject));
- };
- rpp.getElements = function(start, len) {
- var i, r=[];
- for (i=0; i<len; i++) { r.push(this.get(start+i)); }
- return r;
- };
- rpp.setElements = function(start, vals) {
- vals.forEach(function(v, i) { this.set(start+i, v); }.bind(this));
- };
- r['new'] = function(length) {
- return wrap(jenvpp().NewObjectArray(jenv, length, elemClass, null),
- classSig);
- };
- } else {
- var ty = sig2type(elemSig), ctype = sig2ctype(elemSig);
- var constructor = "New"+ty+"Array";
- var getter = "Get"+ty+"ArrayRegion";
- var setter = "Set"+ty+"ArrayRegion";
- rpp.get = function(idx) { return this.getElements(idx, 1)[0]; };
- rpp.set = function(idx, val) { this.setElements(idx, [val]); };
- rpp.getElements = function(start, len) {
- var j = jenvpp();
- var buf = new (ctype.array())(len);
- j[getter].call(j, jenv, unwrap(this), start, len, buf);
- return buf;
- };
- rpp.setElements = function(start, vals) {
- var j = jenvpp();
- j[setter].call(j, jenv, unwrap(this), start, vals.length,
- ctype.array()(vals));
- };
- r['new'] = function(length) {
- var j = jenvpp();
- return wrap(j[constructor].call(j, jenv, length), classSig);
- };
- }
- }
-
- (props.static_fields || []).forEach(function(fld) {
- var jfld = jenvpp().GetStaticFieldID(jenv, jcls, fld.name, fld.sig);
- var ty = sig2type(fld.sig), nm = fld.sig;
- var getter = "GetStatic"+ty+"Field", setter = "SetStatic"+ty+"Field";
- ensureLoaded(jenv, nm);
- var props = {
- get: function() {
- var j = jenvpp();
- return wrap(j[getter].call(j, jenv, jcls, jfld), nm);
- },
- set: function(newValue) {
- var j = jenvpp();
- j[setter].call(j, jenv, jcls, jfld, unwrap(newValue));
- }
- };
- Object.defineProperty(r, fld.name, props);
- // add static fields to object instances, too.
- Object.defineProperty(rpp, fld.name, props);
- });
- (props.static_methods || []).forEach(function(mtd) {
- var jmtd = jenvpp().GetStaticMethodID(jenv, jcls, mtd.name, mtd.sig);
- var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
- var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
- var ty = sig2type(returnSig), nm = returnSig;
- var call = "CallStatic"+ty+"Method";
- ensureLoaded(jenv, nm);
- r[mtd.name] = rpp[mtd.name] = overloadFunc(mtd.name);
- r[mtd.name + mtd.sig] = r[mtd.name+'('+(argctypes.length-1)+')'] =
- // add static methods to object instances, too.
- rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() {
- var i, j = jenvpp();
- var args = [jenv, jcls, jmtd];
- for (i=0; i<arguments.length; i++) {
- args.push(unwrap(arguments[i], jenv, argctypes[i]));
- }
- return wrap(j[call].apply(j, args), nm);
- };
- });
- (props.constructors || []).forEach(function(mtd) {
- mtd.name = "<init>";
- var jmtd = jenvpp().GetMethodID(jenv, jcls, mtd.name, mtd.sig);
- var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
- var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
-
- r['new'] = overloadFunc('new');
- r['new'+mtd.sig] = r['new('+(argctypes.length-1)+')'] = function() {
- var i, j = jenvpp();
- var args = [jenv, jcls, jmtd];
- for (i=0; i<arguments.length; i++) {
- args.push(unwrap(arguments[i], jenv, argctypes[i]));
- }
- return wrap(j.NewObject.apply(j, args), classSig);
- };
- });
- (props.fields || []).forEach(function(fld) {
- var jfld = jenvpp().GetFieldID(jenv, jcls, fld.name, fld.sig);
- var ty = sig2type(fld.sig), nm = fld.sig;
- var getter = "Get"+ty+"Field", setter = "Set"+ty+"Field";
- ensureLoaded(jenv, nm);
- Object.defineProperty(rpp, fld.name, {
- get: function() {
- var j = jenvpp();
- return wrap(j[getter].call(j, jenv, unwrap(this), jfld), nm);
- },
- set: function(newValue) {
- var j = jenvpp();
- j[setter].call(j, jenv, unwrap(this), jfld, unwrap(newValue));
- }
- });
- });
- (props.methods || []).forEach(function(mtd) {
- var jmtd = jenvpp().GetMethodID(jenv, jcls, mtd.name, mtd.sig);
- var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
- var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
- var ty = sig2type(returnSig), nm = returnSig;
- var call = "Call"+ty+"Method";
- ensureLoaded(jenv, nm);
- rpp[mtd.name] = overloadFunc(mtd.name);
- rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() {
- var i, j = jenvpp();
- var args = [jenv, unwrap(this), jmtd];
- for (i=0; i<arguments.length; i++) {
- args.push(unwrap(arguments[i], jenv, argctypes[i]));
- }
- return wrap(j[call].apply(j, args), nm);
- };
- });
- jenvpp().PopLocalFrame(jenv, null);
- return r;
-}
-
-// exported object
-var JNI = {
- // primitive types
- jboolean: jboolean,
- jbyte: jbyte,
- jchar: jchar,
- jshort: jshort,
- jint: jint,
- jlong: jlong,
- jfloat: jfloat,
- jdouble: jdouble,
- jsize: jsize,
-
- // class registry
- classes: classes,
-
- // methods
- GetForThread: GetJNIForThread,
- NewString: JNINewString,
- ReadString: JNIReadString,
- LoadClass: function(jenv, classname_or_signature, props) {
- return JNILoadClass(jenv, ensureSig(classname_or_signature), props);
- },
- UnloadClasses: JNIUnloadClasses
-};
diff --git a/mobile/android/modules/JavaAddonManager.jsm b/mobile/android/modules/JavaAddonManager.jsm
deleted file mode 100644
index a24535ede..000000000
--- a/mobile/android/modules/JavaAddonManager.jsm
+++ /dev/null
@@ -1,115 +0,0 @@
-// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["JavaAddonManager"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components; /*global Components */
-
-Cu.import("resource://gre/modules/Messaging.jsm"); /*global Messaging */
-Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
-
-function resolveGeckoURI(uri) {
- if (!uri) {
- throw new Error("Can't resolve an empty uri");
- }
- if (uri.startsWith("chrome://")) {
- let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci["nsIChromeRegistry"]);
- return registry.convertChromeURL(Services.io.newURI(uri, null, null)).spec;
- } else if (uri.startsWith("resource://")) {
- let handler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
- return handler.resolveURI(Services.io.newURI(uri, null, null));
- }
- return uri;
-}
-
-/**
- * A promise-based API
- */
-var JavaAddonManager = Object.freeze({
- classInstanceFromFile: function(classname, filename) {
- if (!classname) {
- throw new Error("classname cannot be null");
- }
- if (!filename) {
- throw new Error("filename cannot be null");
- }
- return Messaging.sendRequestForResult({
- type: "JavaAddonManagerV1:Load",
- classname: classname,
- filename: resolveGeckoURI(filename)
- })
- .then((guid) => {
- if (!guid) {
- throw new Error("Internal error: guid should not be null");
- }
- return new JavaAddonV1({classname: classname, guid: guid});
- });
- }
-});
-
-function JavaAddonV1(options = {}) {
- if (!(this instanceof JavaAddonV1)) {
- return new JavaAddonV1(options);
- }
- if (!options.classname) {
- throw new Error("options.classname cannot be null");
- }
- if (!options.guid) {
- throw new Error("options.guid cannot be null");
- }
- this._classname = options.classname;
- this._guid = options.guid;
- this._loaded = true;
- this._listeners = {};
-}
-
-JavaAddonV1.prototype = Object.freeze({
- unload: function() {
- if (!this._loaded) {
- return;
- }
-
- Messaging.sendRequestForResult({
- type: "JavaAddonManagerV1:Unload",
- guid: this._guid
- })
- .then(() => {
- this._loaded = false;
- for (let listener of this._listeners) {
- // If we use this.removeListener, we prefix twice.
- Messaging.removeListener(listener);
- }
- this._listeners = {};
- });
- },
-
- _prefix: function(message) {
- let newMessage = Cu.cloneInto(message, {}, { cloneFunctions: false });
- newMessage.type = this._guid + ":" + message.type;
- return newMessage;
- },
-
- sendRequest: function(message) {
- return Messaging.sendRequest(this._prefix(message));
- },
-
- sendRequestForResult: function(message) {
- return Messaging.sendRequestForResult(this._prefix(message));
- },
-
- addListener: function(listener, message) {
- let prefixedMessage = this._guid + ":" + message;
- this._listeners[prefixedMessage] = listener;
- return Messaging.addListener(listener, prefixedMessage);
- },
-
- removeListener: function(message) {
- let prefixedMessage = this._guid + ":" + message;
- delete this._listeners[prefixedMessage];
- return Messaging.removeListener(prefixedMessage);
- }
-});
diff --git a/mobile/android/modules/LightweightThemeConsumer.jsm b/mobile/android/modules/LightweightThemeConsumer.jsm
deleted file mode 100644
index 3d3ca4c0b..000000000
--- a/mobile/android/modules/LightweightThemeConsumer.jsm
+++ /dev/null
@@ -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/. */
-
-var EXPORTED_SYMBOLS = ["LightweightThemeConsumer"];
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
-
-function LightweightThemeConsumer(aDocument) {
- this._doc = aDocument;
- Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
- Services.obs.addObserver(this, "lightweight-theme-apply", false);
-
- this._update(LightweightThemeManager.currentThemeForDisplay);
-}
-
-LightweightThemeConsumer.prototype = {
- observe: function (aSubject, aTopic, aData) {
- if (aTopic == "lightweight-theme-styling-update")
- this._update(JSON.parse(aData));
- else if (aTopic == "lightweight-theme-apply")
- this._update(LightweightThemeManager.currentThemeForDisplay);
- },
-
- destroy: function () {
- Services.obs.removeObserver(this, "lightweight-theme-styling-update");
- Services.obs.removeObserver(this, "lightweight-theme-apply");
- this._doc = null;
- },
-
- _update: function (aData) {
- if (!aData)
- aData = { headerURL: "", footerURL: "", textcolor: "", accentcolor: "" };
-
- let active = !!aData.headerURL;
-
- let msg = active ? { type: "LightweightTheme:Update", data: aData } :
- { type: "LightweightTheme:Disable" };
- Services.androidBridge.handleGeckoMessage(msg);
- }
-}
diff --git a/mobile/android/modules/MediaPlayerApp.jsm b/mobile/android/modules/MediaPlayerApp.jsm
deleted file mode 100644
index 949863d1f..000000000
--- a/mobile/android/modules/MediaPlayerApp.jsm
+++ /dev/null
@@ -1,166 +0,0 @@
-// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MediaPlayerApp"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-var log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.d.bind(null, "MediaPlayerApp");
-
-// Helper function for sending commands to Java.
-function send(type, data, callback) {
- let msg = {
- type: type
- };
-
- for (let i in data) {
- msg[i] = data[i];
- }
-
- Messaging.sendRequestForResult(msg)
- .then(result => callback(result, null),
- error => callback(null, error));
-}
-
-/* These apps represent players supported natively by the platform. This class will proxy commands
- * to native controls */
-function MediaPlayerApp(service) {
- this.service = service;
- this.location = service.location;
- this.id = service.uuid;
-}
-
-MediaPlayerApp.prototype = {
- start: function start(callback) {
- send("MediaPlayer:Start", { id: this.id }, (result, err) => {
- if (callback) {
- callback(err == null);
- }
- });
- },
-
- stop: function stop(callback) {
- send("MediaPlayer:Stop", { id: this.id }, (result, err) => {
- if (callback) {
- callback(err == null);
- }
- });
- },
-
- remoteMedia: function remoteMedia(callback, listener) {
- if (callback) {
- callback(new RemoteMedia(this.id, listener));
- }
- },
-
- mirror: function mirror(callback) {
- send("MediaPlayer:Mirror", { id: this.id }, (result, err) => {
- if (callback) {
- callback(err == null);
- }
- });
- }
-}
-
-/* RemoteMedia provides a proxy to a native media player session.
- */
-function RemoteMedia(id, listener) {
- this._id = id;
- this._listener = listener;
-
- if ("onRemoteMediaStart" in this._listener) {
- Services.tm.mainThread.dispatch((function() {
- this._listener.onRemoteMediaStart(this);
- }).bind(this), Ci.nsIThread.DISPATCH_NORMAL);
- }
-}
-
-RemoteMedia.prototype = {
- shutdown: function shutdown() {
- Services.obs.removeObserver(this, "MediaPlayer:Playing");
- Services.obs.removeObserver(this, "MediaPlayer:Paused");
-
- this._send("MediaPlayer:End", {}, (result, err) => {
- this._status = "shutdown";
- if ("onRemoteMediaStop" in this._listener) {
- this._listener.onRemoteMediaStop(this);
- }
- });
- },
-
- play: function play() {
- this._send("MediaPlayer:Play", {}, (result, err) => {
- if (err) {
- Cu.reportError("Can't play " + err);
- this.shutdown();
- return;
- }
-
- this._status = "started";
- });
- },
-
- pause: function pause() {
- this._send("MediaPlayer:Pause", {}, (result, err) => {
- if (err) {
- Cu.reportError("Can't pause " + err);
- this.shutdown();
- return;
- }
-
- this._status = "paused";
- });
- },
-
- load: function load(aData) {
- this._send("MediaPlayer:Load", aData, (result, err) => {
- if (err) {
- Cu.reportError("Can't load " + err);
- this.shutdown();
- return;
- }
-
- Services.obs.addObserver(this, "MediaPlayer:Playing", false);
- Services.obs.addObserver(this, "MediaPlayer:Paused", false);
- this._status = "started";
- })
- },
-
- get status() {
- return this._status;
- },
-
- observe: function (aSubject, aTopic, aData) {
- switch (aTopic) {
- case "MediaPlayer:Playing":
- if (this._status !== "started") {
- this._status = "started";
- if ("onRemoteMediaStatus" in this._listener) {
- this._listener.onRemoteMediaStatus(this);
- }
- }
- break;
- case "MediaPlayer:Paused":
- if (this._status !== "paused") {
- this._status = "paused";
- if ("onRemoteMediaStatus" in this._listener) {
- this._listener.onRemoteMediaStatus(this);
- }
- }
- break;
- default:
- break;
- }
- },
-
- _send: function(msg, data, callback) {
- data.id = this._id;
- send(msg, data, callback);
- }
-}
diff --git a/mobile/android/modules/Messaging.jsm b/mobile/android/modules/Messaging.jsm
deleted file mode 100644
index 30b7f5a96..000000000
--- a/mobile/android/modules/Messaging.jsm
+++ /dev/null
@@ -1,183 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-
-this.EXPORTED_SYMBOLS = ["sendMessageToJava", "Messaging"];
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-function sendMessageToJava(aMessage, aCallback) {
- Cu.reportError("sendMessageToJava is deprecated. Use Messaging API instead.");
-
- if (aCallback) {
- Messaging.sendRequestForResult(aMessage)
- .then(result => aCallback(result, null),
- error => aCallback(null, error));
- } else {
- Messaging.sendRequest(aMessage);
- }
-}
-
-var Messaging = {
- /**
- * Add a listener for the given message.
- *
- * Only one request listener can be registered for a given message.
- *
- * Example usage:
- * // aData is data sent from Java with the request. The return value is
- * // used to respond to the request. The return type *must* be an instance
- * // of Object.
- * let listener = function (aData) {
- * if (aData == "foo") {
- * return { response: "bar" };
- * }
- * return {};
- * };
- * Messaging.addListener(listener, "Demo:Request");
- *
- * The listener may also be a generator function, useful for performing a
- * task asynchronously. For example:
- * let listener = function* (aData) {
- * // Respond with "bar" after 2 seconds.
- * yield new Promise(resolve => setTimeout(resolve, 2000));
- * return { response: "bar" };
- * };
- * Messaging.addListener(listener, "Demo:Request");
- *
- * @param aListener Listener callback taking a single data parameter (see
- * example usage above).
- * @param aMessage Event name that this listener should observe.
- */
- addListener: function (aListener, aMessage) {
- requestHandler.addListener(aListener, aMessage);
- },
-
- /**
- * Removes a listener for a given message.
- *
- * @param aMessage The event to stop listening for.
- */
- removeListener: function (aMessage) {
- requestHandler.removeListener(aMessage);
- },
-
- /**
- * Sends a request to Java.
- *
- * @param aMessage Message to send; must be an object with a "type" property
- */
- sendRequest: function (aMessage) {
- Services.androidBridge.handleGeckoMessage(aMessage);
- },
-
- /**
- * Sends a request to Java, returning a Promise that resolves to the response.
- *
- * @param aMessage Message to send; must be an object with a "type" property
- * @returns A Promise resolving to the response
- */
- sendRequestForResult: function (aMessage) {
- return new Promise((resolve, reject) => {
- let id = uuidgen.generateUUID().toString();
- let obs = {
- observe: function (aSubject, aTopic, aData) {
- let data = JSON.parse(aData);
- if (data.__guid__ != id) {
- return;
- }
-
- Services.obs.removeObserver(obs, aMessage.type + ":Response");
-
- if (data.status === "success") {
- resolve(data.response);
- } else {
- reject(data.response);
- }
- }
- };
-
- aMessage.__guid__ = id;
- Services.obs.addObserver(obs, aMessage.type + ":Response", false);
-
- this.sendRequest(aMessage);
- });
- },
-
- /**
- * Handles a request from Java, using the given listener method.
- * This is mainly an internal method used by the RequestHandler object, but can be
- * used in nsIObserver.observe implmentations that fall outside the normal usage
- * patterns.
- *
- * @param aTopic The string name of the message
- * @param aData The data sent to the observe method from Java
- * @param aListener A function that takes a JSON data argument and returns a
- * response which is sent to Java.
- */
- handleRequest: Task.async(function* (aTopic, aData, aListener) {
- let wrapper = JSON.parse(aData);
-
- try {
- let response = yield aListener(wrapper.data);
- if (typeof response !== "object" || response === null) {
- throw new Error("Gecko request listener did not return an object");
- }
-
- Messaging.sendRequest({
- type: "Gecko:Request" + wrapper.id,
- response: response
- });
- } catch (e) {
- Cu.reportError("Error in Messaging handler for " + aTopic + ": " + e);
-
- Messaging.sendRequest({
- type: "Gecko:Request" + wrapper.id,
- error: {
- message: e.message || (e && e.toString()),
- stack: e.stack || Components.stack.formattedStack,
- }
- });
- }
- })
-};
-
-var requestHandler = {
- _listeners: {},
-
- addListener: function (aListener, aMessage) {
- if (aMessage in this._listeners) {
- throw new Error("Error in addListener: A listener already exists for message " + aMessage);
- }
-
- if (typeof aListener !== "function") {
- throw new Error("Error in addListener: Listener must be a function for message " + aMessage);
- }
-
- this._listeners[aMessage] = aListener;
- Services.obs.addObserver(this, aMessage, false);
- },
-
- removeListener: function (aMessage) {
- if (!(aMessage in this._listeners)) {
- throw new Error("Error in removeListener: There is no listener for message " + aMessage);
- }
-
- delete this._listeners[aMessage];
- Services.obs.removeObserver(this, aMessage);
- },
-
- observe: function(aSubject, aTopic, aData) {
- let listener = this._listeners[aTopic];
- Messaging.handleRequest(aTopic, aData, listener);
- }
-};
diff --git a/mobile/android/modules/NetErrorHelper.jsm b/mobile/android/modules/NetErrorHelper.jsm
deleted file mode 100644
index 9c74df8fe..000000000
--- a/mobile/android/modules/NetErrorHelper.jsm
+++ /dev/null
@@ -1,175 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-Cu.import("resource://gre/modules/UITelemetry.jsm");
-
-this.EXPORTED_SYMBOLS = ["NetErrorHelper"];
-
-const KEY_CODE_ENTER = 13;
-
-/* Handlers is a list of objects that will be notified when an error page is shown
- * or when an event occurs on the page that they are registered to handle. Registration
- * is done by just adding yourself to the dictionary.
- *
- * handlers.myKey = {
- * onPageShown: function(browser) { },
- * handleEvent: function(event) { },
- * }
- *
- * The key that you register yourself with should match the ID of the element you want to
- * watch for click events on.
- */
-
-var handlers = {};
-
-function NetErrorHelper(browser) {
- browser.addEventListener("click", this.handleClick, true);
-
- let listener = () => {
- browser.removeEventListener("click", this.handleClick, true);
- browser.removeEventListener("pagehide", listener, true);
- };
- browser.addEventListener("pagehide", listener, true);
-
- // Handlers may want to customize the page
- for (let id in handlers) {
- if (handlers[id].onPageShown) {
- handlers[id].onPageShown(browser);
- }
- }
-}
-
-NetErrorHelper.attachToBrowser = function(browser) {
- return new NetErrorHelper(browser);
-}
-
-NetErrorHelper.prototype = {
- handleClick: function(event) {
- let node = event.target;
-
- while(node) {
- if (node.id in handlers && handlers[node.id].handleClick) {
- handlers[node.id].handleClick(event);
- return;
- }
-
- node = node.parentNode;
- }
- },
-}
-
-handlers.searchbutton = {
- onPageShown: function(browser) {
- let search = browser.contentDocument.querySelector("#searchbox");
- if (!search) {
- return;
- }
-
- let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
- let tab = browserWin.BrowserApp.getTabForBrowser(browser);
-
- // If there is no stored userRequested, just hide the searchbox
- if (!tab.userRequested) {
- search.style.display = "none";
- } else {
- let text = browser.contentDocument.querySelector("#searchtext");
- text.value = tab.userRequested;
- text.addEventListener("keypress", (event) => {
- if (event.keyCode === KEY_CODE_ENTER) {
- this.doSearch(event.target.value);
- }
- });
- }
- },
-
- handleClick: function(event) {
- let value = event.target.previousElementSibling.value;
- this.doSearch(value);
- },
-
- doSearch: function(value) {
- UITelemetry.addEvent("neterror.1", "button", null, "search");
- let engine = Services.search.defaultEngine;
- let uri = engine.getSubmission(value).uri;
-
- let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
- // Reset the user search to whatever the new search term was
- browserWin.BrowserApp.loadURI(uri.spec, undefined, { isSearch: true, userRequested: value });
- }
-};
-
-handlers.wifi = {
- // This registers itself with the nsIObserverService as a weak ref,
- // so we have to implement GetWeakReference as well.
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference]),
-
- GetWeakReference: function() {
- return Cu.getWeakReference(this);
- },
-
- onPageShown: function(browser) {
- // If we have a connection, don't bother showing the wifi toggle.
- let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService);
- if (network.isLinkUp && network.linkStatusKnown) {
- let nodes = browser.contentDocument.querySelectorAll("#wifi");
- for (let i = 0; i < nodes.length; i++) {
- nodes[i].style.display = "none";
- }
- }
- },
-
- handleClick: function(event) {
- let node = event.target;
- while(node && node.id !== "wifi") {
- node = node.parentNode;
- }
-
- if (!node) {
- return;
- }
-
- UITelemetry.addEvent("neterror.1", "button", null, "wifitoggle");
- // Show indeterminate progress while we wait for the network.
- node.disabled = true;
- node.classList.add("inProgress");
-
- this.node = Cu.getWeakReference(node);
- Services.obs.addObserver(this, "network:link-status-changed", true);
-
- Messaging.sendRequest({
- type: "Wifi:Enable"
- });
- },
-
- observe: function(subject, topic, data) {
- let node = this.node.get();
- if (!node) {
- return;
- }
-
- // Remove the progress bar
- node.disabled = false;
- node.classList.remove("inProgress");
-
- let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService);
- if (network.isLinkUp && network.linkStatusKnown) {
- // If everything worked, reload the page
- UITelemetry.addEvent("neterror.1", "button", null, "wifitoggle.reload");
- Services.obs.removeObserver(this, "network:link-status-changed");
-
- // Even at this point, Android sometimes lies about the real state of the network and this reload request fails.
- // Add a 500ms delay before refreshing the page.
- node.ownerDocument.defaultView.setTimeout(function() {
- node.ownerDocument.location.reload(false);
- }, 500);
- }
- }
-}
-
diff --git a/mobile/android/modules/Notifications.jsm b/mobile/android/modules/Notifications.jsm
deleted file mode 100644
index a035bb2e3..000000000
--- a/mobile/android/modules/Notifications.jsm
+++ /dev/null
@@ -1,259 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-
-this.EXPORTED_SYMBOLS = ["Notifications"];
-
-function log(msg) {
- // Services.console.logStringMessage(msg);
-}
-
-var _notificationsMap = {};
-var _handlersMap = {};
-
-function Notification(aId, aOptions) {
- this._id = aId;
- this._when = (new Date()).getTime();
- this.fillWithOptions(aOptions);
-}
-
-Notification.prototype = {
- fillWithOptions: function(aOptions) {
- if ("icon" in aOptions && aOptions.icon != null)
- this._icon = aOptions.icon;
- else
- throw "Notification icon is mandatory";
-
- if ("title" in aOptions && aOptions.title != null)
- this._title = aOptions.title;
- else
- throw "Notification title is mandatory";
-
- if ("message" in aOptions && aOptions.message != null)
- this._message = aOptions.message;
- else
- this._message = null;
-
- if ("priority" in aOptions && aOptions.priority != null)
- this._priority = aOptions.priority;
-
- if ("buttons" in aOptions && aOptions.buttons != null) {
- if (aOptions.buttons.length > 3)
- throw "Too many buttons provided. The max number is 3";
-
- this._buttons = {};
- for (let i = 0; i < aOptions.buttons.length; i++) {
- let button_id = aOptions.buttons[i].buttonId;
- this._buttons[button_id] = aOptions.buttons[i];
- }
- } else {
- this._buttons = null;
- }
-
- if ("ongoing" in aOptions && aOptions.ongoing != null)
- this._ongoing = aOptions.ongoing;
- else
- this._ongoing = false;
-
- if ("progress" in aOptions && aOptions.progress != null)
- this._progress = aOptions.progress;
- else
- this._progress = null;
-
- if ("onCancel" in aOptions && aOptions.onCancel != null)
- this._onCancel = aOptions.onCancel;
- else
- this._onCancel = null;
-
- if ("onClick" in aOptions && aOptions.onClick != null)
- this._onClick = aOptions.onClick;
- else
- this._onClick = null;
-
- if ("cookie" in aOptions && aOptions.cookie != null)
- this._cookie = aOptions.cookie;
- else
- this._cookie = null;
-
- if ("handlerKey" in aOptions && aOptions.handlerKey != null)
- this._handlerKey = aOptions.handlerKey;
-
- if ("persistent" in aOptions && aOptions.persistent != null)
- this._persistent = aOptions.persistent;
- else
- this._persistent = false;
- },
-
- show: function() {
- let msg = {
- type: "Notification:Show",
- id: this._id,
- title: this._title,
- smallIcon: this._icon,
- ongoing: this._ongoing,
- when: this._when,
- persistent: this._persistent,
- };
-
- if (this._message)
- msg.text = this._message;
-
- if (this._progress) {
- msg.progress_value = this._progress;
- msg.progress_max = 100;
- msg.progress_indeterminate = false;
- } else if (Number.isNaN(this._progress)) {
- msg.progress_value = 0;
- msg.progress_max = 0;
- msg.progress_indeterminate = true;
- }
-
- if (this._cookie)
- msg.cookie = JSON.stringify(this._cookie);
-
- if (this._priority)
- msg.priority = this._priority;
-
- if (this._buttons) {
- msg.actions = [];
- let buttonName;
- for (buttonName in this._buttons) {
- let button = this._buttons[buttonName];
- let obj = {
- buttonId: button.buttonId,
- title : button.title,
- icon : button.icon
- };
- msg.actions.push(obj);
- }
- }
-
- if (this._light)
- msg.light = this._light;
-
- if (this._handlerKey)
- msg.handlerKey = this._handlerKey;
-
- Services.androidBridge.handleGeckoMessage(msg);
- return this;
- },
-
- cancel: function() {
- let msg = {
- type: "Notification:Hide",
- id: this._id,
- handlerKey: this._handlerKey,
- cookie: JSON.stringify(this._cookie),
- };
- Services.androidBridge.handleGeckoMessage(msg);
- }
-}
-
-var Notifications = {
- get idService() {
- delete this.idService;
- return this.idService = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
- },
-
- registerHandler: function(key, handler) {
- if (!_handlersMap[key]) {
- _handlersMap[key] = [];
- }
- _handlersMap[key].push(handler);
- },
-
- unregisterHandler: function(key, handler) {
- let h = _handlersMap[key];
- if (!h) {
- return;
- }
- let i = h.indexOf(handler);
- if (i > -1) {
- h.splice(i, 1);
- }
- },
-
- create: function notif_notify(aOptions) {
- let id = this.idService.generateUUID().toString();
-
- let notification = new Notification(id, aOptions);
- _notificationsMap[id] = notification;
- notification.show();
-
- return id;
- },
-
- update: function notif_update(aId, aOptions) {
- let notification = _notificationsMap[aId];
- if (!notification)
- throw "Unknown notification id";
- notification.fillWithOptions(aOptions);
- notification.show();
- },
-
- cancel: function notif_cancel(aId) {
- let notification = _notificationsMap[aId];
- if (notification)
- notification.cancel();
- },
-
- observe: function notif_observe(aSubject, aTopic, aData) {
- Services.console.logStringMessage(aTopic + " " + aData);
-
- let data = JSON.parse(aData);
- let id = data.id;
- let handlerKey = data.handlerKey;
- let cookie = data.cookie ? JSON.parse(data.cookie) : undefined;
- let notification = _notificationsMap[id];
-
- switch (data.eventType) {
- case "notification-clicked":
- if (notification && notification._onClick)
- notification._onClick(id, notification._cookie);
-
- if (handlerKey) {
- _handlersMap[handlerKey].forEach(function(handler) {
- handler.onClick(cookie);
- });
- }
-
- break;
- case "notification-button-clicked":
- if (handlerKey) {
- _handlersMap[handlerKey].forEach(function(handler) {
- handler.onButtonClick(data.buttonId, cookie);
- });
- }
-
- break;
- case "notification-cleared":
- case "notification-closed":
- if (handlerKey) {
- _handlersMap[handlerKey].forEach(function(handler) {
- handler.onCancel(cookie);
- });
- }
-
- if (notification && notification._onCancel)
- notification._onCancel(id, notification._cookie);
- delete _notificationsMap[id]; // since the notification was dismissed, we no longer need to hold a reference.
- break;
- }
- },
-
- QueryInterface: function (aIID) {
- if (!aIID.equals(Ci.nsISupports) &&
- !aIID.equals(Ci.nsIObserver) &&
- !aIID.equals(Ci.nsISupportsWeakReference))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
-};
-
-Services.obs.addObserver(Notifications, "Notification:Event", false);
diff --git a/mobile/android/modules/PageActions.jsm b/mobile/android/modules/PageActions.jsm
deleted file mode 100644
index a66268f82..000000000
--- a/mobile/android/modules/PageActions.jsm
+++ /dev/null
@@ -1,113 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-this.EXPORTED_SYMBOLS = ["PageActions"];
-
-// Copied from browser.js
-// TODO: We should move this method to a common importable location
-function resolveGeckoURI(aURI) {
- if (!aURI)
- throw "Can't resolve an empty uri";
-
- if (aURI.startsWith("chrome://")) {
- let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci["nsIChromeRegistry"]);
- return registry.convertChromeURL(Services.io.newURI(aURI, null, null)).spec;
- } else if (aURI.startsWith("resource://")) {
- let handler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
- return handler.resolveURI(Services.io.newURI(aURI, null, null));
- }
- return aURI;
-}
-
-var PageActions = {
- _items: { },
-
- _inited: false,
-
- _maybeInit: function() {
- if (!this._inited && Object.keys(this._items).length > 0) {
- this._inited = true;
- Services.obs.addObserver(this, "PageActions:Clicked", false);
- Services.obs.addObserver(this, "PageActions:LongClicked", false);
- }
- },
-
- _maybeUninit: function() {
- if (this._inited && Object.keys(this._items).length == 0) {
- this._inited = false;
- Services.obs.removeObserver(this, "PageActions:Clicked");
- Services.obs.removeObserver(this, "PageActions:LongClicked");
- }
- },
-
- observe: function(aSubject, aTopic, aData) {
- let item = this._items[aData];
- if (aTopic == "PageActions:Clicked") {
- if (item.clickCallback) {
- item.clickCallback();
- }
- } else if (aTopic == "PageActions:LongClicked") {
- if (item.longClickCallback) {
- item.longClickCallback();
- }
- }
- },
-
- isShown: function(id) {
- return !!this._items[id];
- },
-
- synthesizeClick: function(id) {
- let item = this._items[id];
- if (item && item.clickCallback) {
- item.clickCallback();
- }
- },
-
- add: function(aOptions) {
- let id = aOptions.id || uuidgen.generateUUID().toString()
-
- Messaging.sendRequest({
- type: "PageActions:Add",
- id: id,
- title: aOptions.title,
- icon: resolveGeckoURI(aOptions.icon),
- important: "important" in aOptions ? aOptions.important : false
- });
-
- this._items[id] = {};
-
- if (aOptions.clickCallback) {
- this._items[id].clickCallback = aOptions.clickCallback;
- }
-
- if (aOptions.longClickCallback) {
- this._items[id].longClickCallback = aOptions.longClickCallback;
- }
-
- this._maybeInit();
- return id;
- },
-
- remove: function(id) {
- Messaging.sendRequest({
- type: "PageActions:Remove",
- id: id
- });
-
- delete this._items[id];
- this._maybeUninit();
- }
-}
diff --git a/mobile/android/modules/Prompt.jsm b/mobile/android/modules/Prompt.jsm
deleted file mode 100644
index 5bed87650..000000000
--- a/mobile/android/modules/Prompt.jsm
+++ /dev/null
@@ -1,234 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
- * 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 Cc = Components.classes;
-var Ci = Components.interfaces;
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/Messaging.jsm");
-
-this.EXPORTED_SYMBOLS = ["Prompt"];
-
-function log(msg) {
- Services.console.logStringMessage(msg);
-}
-
-function Prompt(aOptions) {
- this.window = "window" in aOptions ? aOptions.window : null;
-
- this.msg = { async: true };
-
- if (this.window) {
- let window = Services.wm.getMostRecentWindow("navigator:browser");
- var tab = window.BrowserApp.getTabForWindow(this.window);
- if (tab) {
- this.msg.tabId = tab.id;
- }
- }
-
- if (aOptions.priority === 1)
- this.msg.type = "Prompt:ShowTop"
- else
- this.msg.type = "Prompt:Show"
-
- if ("title" in aOptions && aOptions.title != null)
- this.msg.title = aOptions.title;
-
- if ("message" in aOptions && aOptions.message != null)
- this.msg.text = aOptions.message;
-
- if ("buttons" in aOptions && aOptions.buttons != null)
- this.msg.buttons = aOptions.buttons;
-
- if ("doubleTapButton" in aOptions && aOptions.doubleTapButton != null)
- this.msg.doubleTapButton = aOptions.doubleTapButton;
-
- if ("hint" in aOptions && aOptions.hint != null)
- this.msg.hint = aOptions.hint;
-}
-
-Prompt.prototype = {
- setHint: function(aHint) {
- if (!aHint)
- delete this.msg.hint;
- else
- this.msg.hint = aHint;
- return this;
- },
-
- addButton: function(aOptions) {
- if (!this.msg.buttons)
- this.msg.buttons = [];
- this.msg.buttons.push(aOptions.label);
- return this;
- },
-
- _addInput: function(aOptions) {
- let obj = aOptions;
- if (this[aOptions.type + "_count"] === undefined)
- this[aOptions.type + "_count"] = 0;
-
- obj.id = aOptions.id || (aOptions.type + this[aOptions.type + "_count"]);
- this[aOptions.type + "_count"]++;
-
- if (!this.msg.inputs)
- this.msg.inputs = [];
- this.msg.inputs.push(obj);
- return this;
- },
-
- addCheckbox: function(aOptions) {
- return this._addInput({
- type: "checkbox",
- label: aOptions.label,
- checked: aOptions.checked,
- id: aOptions.id
- });
- },
-
- addTextbox: function(aOptions) {
- return this._addInput({
- type: "textbox",
- value: aOptions.value,
- hint: aOptions.hint,
- autofocus: aOptions.autofocus,
- id: aOptions.id
- });
- },
-
- addNumber: function(aOptions) {
- return this._addInput({
- type: "number",
- value: aOptions.value,
- hint: aOptions.hint,
- autofocus: aOptions.autofocus,
- id: aOptions.id
- });
- },
-
- addPassword: function(aOptions) {
- return this._addInput({
- type: "password",
- value: aOptions.value,
- hint: aOptions.hint,
- autofocus: aOptions.autofocus,
- id : aOptions.id
- });
- },
-
- addDatePicker: function(aOptions) {
- return this._addInput({
- type: aOptions.type || "date",
- value: aOptions.value,
- id: aOptions.id,
- max: aOptions.max,
- min: aOptions.min
- });
- },
-
- addColorPicker: function(aOptions) {
- return this._addInput({
- type: "color",
- value: aOptions.value,
- id: aOptions.id
- });
- },
-
- addLabel: function(aOptions) {
- return this._addInput({
- type: "label",
- label: aOptions.label,
- id: aOptions.id
- });
- },
-
- addMenulist: function(aOptions) {
- return this._addInput({
- type: "menulist",
- values: aOptions.values,
- id: aOptions.id
- });
- },
-
- addIconGrid: function(aOptions) {
- return this._addInput({
- type: "icongrid",
- items: aOptions.items,
- id: aOptions.id
- });
- },
-
- addTabs: function(aOptions) {
- return this._addInput({
- type: "tabs",
- items: aOptions.items,
- id: aOptions.id
- });
- },
-
- show: function(callback) {
- this.callback = callback;
- log("Sending message");
- this._innerShow();
- },
-
- _innerShow: function() {
- Messaging.sendRequestForResult(this.msg).then((data) => {
- if (this.callback)
- this.callback(data);
- });
- },
-
- _setListItems: function(aItems) {
- let hasSelected = false;
- this.msg.listitems = [];
-
- aItems.forEach(function(item) {
- let obj = { id: item.id };
-
- obj.label = item.label;
-
- if (item.disabled)
- obj.disabled = true;
-
- if (item.selected) {
- if (!this.msg.choiceMode) {
- this.msg.choiceMode = "single";
- }
- obj.selected = item.selected;
- }
-
- if (item.header)
- obj.isGroup = true;
-
- if (item.menu)
- obj.isParent = true;
-
- if (item.child)
- obj.inGroup = true;
-
- if (item.showAsActions)
- obj.showAsActions = item.showAsActions;
-
- if (item.icon)
- obj.icon = item.icon;
-
- this.msg.listitems.push(obj);
-
- }, this);
- return this;
- },
-
- setSingleChoiceItems: function(aItems) {
- return this._setListItems(aItems);
- },
-
- setMultiChoiceItems: function(aItems) {
- this.msg.choiceMode = "multiple";
- return this._setListItems(aItems);
- },
-
-}
diff --git a/mobile/android/modules/RuntimePermissions.jsm b/mobile/android/modules/RuntimePermissions.jsm
deleted file mode 100644
index 42d8024b1..000000000
--- a/mobile/android/modules/RuntimePermissions.jsm
+++ /dev/null
@@ -1,41 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = ["RuntimePermissions"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
-
-// See: http://developer.android.com/reference/android/Manifest.permission.html
-const CAMERA = "android.permission.CAMERA";
-const WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
-const RECORD_AUDIO = "android.permission.RECORD_AUDIO";
-
-var RuntimePermissions = {
- CAMERA: CAMERA,
- RECORD_AUDIO: RECORD_AUDIO,
- WRITE_EXTERNAL_STORAGE: WRITE_EXTERNAL_STORAGE,
-
- /**
- * Check whether the permissions have been granted or not. If needed prompt the user to accept the permissions.
- *
- * @returns A promise resolving to true if all the permissions have been granted or false if any of the
- * permissions have been denied.
- */
- waitForPermissions: function(permission) {
- let permissions = [].concat(permission);
-
- let msg = {
- type: 'RuntimePermissions:Prompt',
- permissions: permissions
- };
-
- return Messaging.sendRequestForResult(msg);
- }
-}; \ No newline at end of file
diff --git a/mobile/android/modules/SSLExceptions.jsm b/mobile/android/modules/SSLExceptions.jsm
deleted file mode 100644
index 48dfe8d92..000000000
--- a/mobile/android/modules/SSLExceptions.jsm
+++ /dev/null
@@ -1,118 +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 Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-this.EXPORTED_SYMBOLS = ["SSLExceptions"];
-
-/**
- A class to add exceptions to override SSL certificate problems. The functionality
- itself is borrowed from exceptionDialog.js.
-*/
-function SSLExceptions() {
- this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
- .getService(Ci.nsICertOverrideService);
-}
-
-
-SSLExceptions.prototype = {
- _overrideService: null,
- _sslStatus: null,
-
- getInterface: function SSLE_getInterface(aIID) {
- return this.QueryInterface(aIID);
- },
- QueryInterface: function SSLE_QueryInterface(aIID) {
- if (aIID.equals(Ci.nsIBadCertListener2) ||
- aIID.equals(Ci.nsISupports))
- return this;
-
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- /**
- To collect the SSL status we intercept the certificate error here
- and store the status for later use.
- */
- notifyCertProblem: function SSLE_notifyCertProblem(socketInfo, sslStatus, targetHost) {
- this._sslStatus = sslStatus.QueryInterface(Ci.nsISSLStatus);
- return true; // suppress error UI
- },
-
- /**
- Attempt to download the certificate for the location specified to get the SSLState
- for the certificate and the errors.
- */
- _checkCert: function SSLE_checkCert(aURI) {
- this._sslStatus = null;
-
- let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
- try {
- if (aURI) {
- req.open("GET", aURI.prePath, false);
- req.channel.notificationCallbacks = this;
- req.send(null);
- }
- } catch (e) {
- // We *expect* exceptions if there are problems with the certificate
- // presented by the site. Log it, just in case, but we can proceed here,
- // with appropriate sanity checks
- Components.utils.reportError("Attempted to connect to a site with a bad certificate in the add exception dialog. " +
- "This results in a (mostly harmless) exception being thrown. " +
- "Logged for information purposes only: " + e);
- }
-
- return this._sslStatus;
- },
-
- /**
- Internal method to create an override.
- */
- _addOverride: function SSLE_addOverride(aURI, aWindow, aTemporary) {
- let SSLStatus = this._checkCert(aURI);
- let certificate = SSLStatus.serverCert;
-
- let flags = 0;
-
- // in private browsing do not store exceptions permanently ever
- if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
- aTemporary = true;
- }
-
- if (SSLStatus.isUntrusted)
- flags |= this._overrideService.ERROR_UNTRUSTED;
- if (SSLStatus.isDomainMismatch)
- flags |= this._overrideService.ERROR_MISMATCH;
- if (SSLStatus.isNotValidAtThisTime)
- flags |= this._overrideService.ERROR_TIME;
-
- this._overrideService.rememberValidityOverride(
- aURI.asciiHost,
- aURI.port,
- certificate,
- flags,
- aTemporary);
- },
-
- /**
- Creates a permanent exception to override all overridable errors for
- the given URL.
- */
- addPermanentException: function SSLE_addPermanentException(aURI, aWindow) {
- this._addOverride(aURI, aWindow, false);
- },
-
- /**
- Creates a temporary exception to override all overridable errors for
- the given URL.
- */
- addTemporaryException: function SSLE_addTemporaryException(aURI, aWindow) {
- this._addOverride(aURI, aWindow, true);
- }
-};
diff --git a/mobile/android/modules/Sanitizer.jsm b/mobile/android/modules/Sanitizer.jsm
deleted file mode 100644
index 014a89688..000000000
--- a/mobile/android/modules/Sanitizer.jsm
+++ /dev/null
@@ -1,303 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 4 -*-
-/* 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/. */
-
-/*globals LoadContextInfo, FormHistory, Accounts */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/LoadContextInfo.jsm");
-Cu.import("resource://gre/modules/FormHistory.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/Downloads.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Accounts.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration",
- "resource://gre/modules/DownloadIntegration.jsm");
-
-function dump(a) {
- Services.console.logStringMessage(a);
-}
-
-this.EXPORTED_SYMBOLS = ["Sanitizer"];
-
-function Sanitizer() {}
-Sanitizer.prototype = {
- clearItem: function (aItemName)
- {
- let item = this.items[aItemName];
- let canClear = item.canClear;
- if (typeof canClear == "function") {
- canClear(function clearCallback(aCanClear) {
- if (aCanClear)
- item.clear();
- });
- } else if (canClear) {
- item.clear();
- }
- },
-
- items: {
- cache: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
- try {
- cache.clear();
- } catch(er) {}
-
- let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
- .getImgCacheForDocument(null);
- try {
- imageCache.clearCache(false); // true=chrome, false=content
- } catch(er) {}
-
- resolve();
- });
- },
-
- get canClear()
- {
- return true;
- }
- },
-
- cookies: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- Services.cookies.removeAll();
- resolve();
- });
- },
-
- get canClear()
- {
- return true;
- }
- },
-
- siteSettings: {
- clear: Task.async(function* () {
- // Clear site-specific permissions like "Allow this site to open popups"
- Services.perms.removeAll();
-
- // Clear site-specific settings like page-zoom level
- Cc["@mozilla.org/content-pref/service;1"]
- .getService(Ci.nsIContentPrefService2)
- .removeAllDomains(null);
-
- // Clear site security settings
- var sss = Cc["@mozilla.org/ssservice;1"]
- .getService(Ci.nsISiteSecurityService);
- sss.clearAll();
-
- // Clear push subscriptions
- yield new Promise((resolve, reject) => {
- let push = Cc["@mozilla.org/push/Service;1"]
- .getService(Ci.nsIPushService);
- push.clearForDomain("*", status => {
- if (Components.isSuccessCode(status)) {
- resolve();
- } else {
- reject(new Error("Error clearing push subscriptions: " +
- status));
- }
- });
- });
- }),
-
- get canClear()
- {
- return true;
- }
- },
-
- offlineApps: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
- var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
- try {
- appCacheStorage.asyncEvictStorage(null);
- } catch(er) {}
-
- resolve();
- });
- },
-
- get canClear()
- {
- return true;
- }
- },
-
- history: {
- clear: function ()
- {
- return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory" })
- .catch(e => Cu.reportError("Java-side history clearing failed: " + e))
- .then(function() {
- try {
- Services.obs.notifyObservers(null, "browser:purge-session-history", "");
- }
- catch (e) { }
-
- try {
- var predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
- predictor.reset();
- } catch (e) { }
- });
- },
-
- get canClear()
- {
- // bug 347231: Always allow clearing history due to dependencies on
- // the browser:purge-session-history notification. (like error console)
- return true;
- }
- },
-
- searchHistory: {
- clear: function ()
- {
- return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory", clearSearchHistory: true })
- .catch(e => Cu.reportError("Java-side search history clearing failed: " + e))
- },
-
- get canClear()
- {
- return true;
- }
- },
-
- formdata: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- FormHistory.update({ op: "remove" });
- resolve();
- });
- },
-
- canClear: function (aCallback)
- {
- let count = 0;
- let countDone = {
- handleResult: function(aResult) { count = aResult; },
- handleError: function(aError) { Cu.reportError(aError); },
- handleCompletion: function(aReason) { aCallback(aReason == 0 && count > 0); }
- };
- FormHistory.count({}, countDone);
- }
- },
-
- downloadFiles: {
- clear: Task.async(function* () {
- let list = yield Downloads.getList(Downloads.ALL);
- let downloads = yield list.getAll();
- var finalizePromises = [];
-
- // Logic copied from DownloadList.removeFinished. Ideally, we would
- // just use that method directly, but we want to be able to remove the
- // downloaded files as well.
- for (let download of downloads) {
- // Remove downloads that have been canceled, even if the cancellation
- // operation hasn't completed yet so we don't check "stopped" here.
- // Failed downloads with partial data are also removed.
- if (download.stopped && (!download.hasPartialData || download.error)) {
- // Remove the download first, so that the views don't get the change
- // notifications that may occur during finalization.
- yield list.remove(download);
- // Ensure that the download is stopped and no partial data is kept.
- // This works even if the download state has changed meanwhile. We
- // don't need to wait for the procedure to be complete before
- // processing the other downloads in the list.
- finalizePromises.push(download.finalize(true).then(() => null, Cu.reportError));
-
- // Delete the downloaded files themselves.
- OS.File.remove(download.target.path).then(() => null, ex => {
- if (!(ex instanceof OS.File.Error && ex.becauseNoSuchFile)) {
- Cu.reportError(ex);
- }
- });
- }
- }
-
- yield Promise.all(finalizePromises);
- yield DownloadIntegration.forceSave();
- }),
-
- get canClear()
- {
- return true;
- }
- },
-
- passwords: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- Services.logins.removeAllLogins();
- resolve();
- });
- },
-
- get canClear()
- {
- let count = Services.logins.countLogins("", "", ""); // count all logins
- return (count > 0);
- }
- },
-
- sessions: {
- clear: function ()
- {
- return new Promise(function(resolve, reject) {
- // clear all auth tokens
- var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
- sdr.logoutAndTeardown();
-
- // clear FTP and plain HTTP auth sessions
- Services.obs.notifyObservers(null, "net:clear-active-logins", null);
-
- resolve();
- });
- },
-
- get canClear()
- {
- return true;
- }
- },
-
- syncedTabs: {
- clear: function ()
- {
- return Messaging.sendRequestForResult({ type: "Sanitize:ClearSyncedTabs" })
- .catch(e => Cu.reportError("Java-side synced tabs clearing failed: " + e));
- },
-
- canClear: function(aCallback)
- {
- Accounts.anySyncAccountsExist().then(aCallback)
- .catch(function(err) {
- Cu.reportError("Java-side synced tabs clearing failed: " + err)
- aCallback(false);
- });
- }
- }
-
- }
-};
-
-this.Sanitizer = new Sanitizer();
diff --git a/mobile/android/modules/SharedPreferences.jsm b/mobile/android/modules/SharedPreferences.jsm
deleted file mode 100644
index 3f32df6ea..000000000
--- a/mobile/android/modules/SharedPreferences.jsm
+++ /dev/null
@@ -1,254 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["SharedPreferences"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-// For adding observers.
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-var Scope = Object.freeze({
- APP: "app",
- PROFILE: "profile",
- GLOBAL: "global"
-});
-
-/**
- * Public API to getting a SharedPreferencesImpl instance. These scopes mirror GeckoSharedPrefs.
- */
-var SharedPreferences = {
- forApp: function() {
- return new SharedPreferencesImpl({ scope: Scope.APP });
- },
-
- forProfile: function() {
- return new SharedPreferencesImpl({ scope: Scope.PROFILE });
- },
-
- /**
- * Get SharedPreferences for the named profile; if the profile name is null,
- * returns the preferences for the current profile (just like |forProfile|).
- */
- forProfileName: function(profileName) {
- return new SharedPreferencesImpl({ scope: Scope.PROFILE, profileName: profileName });
- },
-
- /**
- * Get SharedPreferences for the given Android branch; if the branch is null,
- * returns the default preferences branch for the application, which is the
- * output of |PreferenceManager.getDefaultSharedPreferences|.
- */
- forAndroid: function(branch) {
- return new SharedPreferencesImpl({ scope: Scope.GLOBAL, branch: branch });
- }
-};
-
-/**
- * Create an interface to an Android SharedPreferences branch.
- *
- * options {Object} with the following valid keys:
- * - scope {String} (required) specifies the scope of preferences that should be accessed.
- * - branch {String} (only when using Scope.GLOBAL) should be a string describing a preferences branch,
- * like "UpdateService" or "background.data", or null to access the
- * default preferences branch for the application.
- * - profileName {String} (optional, only valid when using Scope.PROFILE)
- */
-function SharedPreferencesImpl(options = {}) {
- if (!(this instanceof SharedPreferencesImpl)) {
- return new SharedPreferencesImpl(options);
- }
-
- if (options.scope == null || options.scope == undefined) {
- throw "Shared Preferences must specifiy a scope.";
- }
-
- this._scope = options.scope;
- this._profileName = options.profileName;
- this._branch = options.branch;
- this._observers = {};
-}
-
-SharedPreferencesImpl.prototype = Object.freeze({
- _set: function _set(prefs) {
- Messaging.sendRequest({
- type: "SharedPreferences:Set",
- preferences: prefs,
- scope: this._scope,
- profileName: this._profileName,
- branch: this._branch,
- });
- },
-
- _setOne: function _setOne(prefName, value, type) {
- let prefs = [];
- prefs.push({
- name: prefName,
- value: value,
- type: type,
- });
- this._set(prefs);
- },
-
- setBoolPref: function setBoolPref(prefName, value) {
- this._setOne(prefName, value, "bool");
- },
-
- setCharPref: function setCharPref(prefName, value) {
- this._setOne(prefName, value, "string");
- },
-
- setIntPref: function setIntPref(prefName, value) {
- this._setOne(prefName, value, "int");
- },
-
- _get: function _get(prefs, callback) {
- let result = null;
- Messaging.sendRequestForResult({
- type: "SharedPreferences:Get",
- preferences: prefs,
- scope: this._scope,
- profileName: this._profileName,
- branch: this._branch,
- }).then((data) => {
- result = data.values;
- });
-
- let thread = Services.tm.currentThread;
- while (result == null)
- thread.processNextEvent(true);
-
- return result;
- },
-
- _getOne: function _getOne(prefName, type) {
- let prefs = [];
- prefs.push({
- name: prefName,
- type: type,
- });
- let values = this._get(prefs);
- if (values.length != 1) {
- throw new Error("Got too many values: " + values.length);
- }
- return values[0].value;
- },
-
- getBoolPref: function getBoolPref(prefName) {
- return this._getOne(prefName, "bool");
- },
-
- getCharPref: function getCharPref(prefName) {
- return this._getOne(prefName, "string");
- },
-
- getIntPref: function getIntPref(prefName) {
- return this._getOne(prefName, "int");
- },
-
- /**
- * Invoke `observer` after a change to the preference `domain` in
- * the current branch.
- *
- * `observer` should implement the nsIObserver.observe interface.
- */
- addObserver: function addObserver(domain, observer, holdWeak) {
- if (!domain)
- throw new Error("domain must not be null");
- if (!observer)
- throw new Error("observer must not be null");
- if (holdWeak)
- throw new Error("Weak references not yet implemented.");
-
- if (!this._observers.hasOwnProperty(domain))
- this._observers[domain] = [];
- if (this._observers[domain].indexOf(observer) > -1)
- return;
-
- this._observers[domain].push(observer);
-
- this._updateAndroidListener();
- },
-
- /**
- * Do not invoke `observer` after a change to the preference
- * `domain` in the current branch.
- */
- removeObserver: function removeObserver(domain, observer) {
- if (!this._observers.hasOwnProperty(domain))
- return;
- let index = this._observers[domain].indexOf(observer);
- if (index < 0)
- return;
-
- this._observers[domain].splice(index, 1);
- if (this._observers[domain].length < 1)
- delete this._observers[domain];
-
- this._updateAndroidListener();
- },
-
- _updateAndroidListener: function _updateAndroidListener() {
- if (this._listening && Object.keys(this._observers).length < 1)
- this._uninstallAndroidListener();
- if (!this._listening && Object.keys(this._observers).length > 0)
- this._installAndroidListener();
- },
-
- _installAndroidListener: function _installAndroidListener() {
- if (this._listening)
- return;
- this._listening = true;
-
- Services.obs.addObserver(this, "SharedPreferences:Changed", false);
- Messaging.sendRequest({
- type: "SharedPreferences:Observe",
- enable: true,
- scope: this._scope,
- profileName: this._profileName,
- branch: this._branch,
- });
- },
-
- observe: function observe(subject, topic, data) {
- if (topic != "SharedPreferences:Changed") {
- return;
- }
-
- let msg = JSON.parse(data);
- if (msg.scope !== this._scope ||
- ((this._scope === Scope.PROFILE) && (msg.profileName !== this._profileName)) ||
- ((this._scope === Scope.GLOBAL) && (msg.branch !== this._branch))) {
- return;
- }
-
- if (!this._observers.hasOwnProperty(msg.key)) {
- return;
- }
-
- let observers = this._observers[msg.key];
- for (let obs of observers) {
- obs.observe(obs, msg.key, msg.value);
- }
- },
-
- _uninstallAndroidListener: function _uninstallAndroidListener() {
- if (!this._listening)
- return;
- this._listening = false;
-
- Services.obs.removeObserver(this, "SharedPreferences:Changed");
- Messaging.sendRequest({
- type: "SharedPreferences:Observe",
- enable: false,
- scope: this._scope,
- profileName: this._profileName,
- branch: this._branch,
- });
- },
-});
diff --git a/mobile/android/modules/Snackbars.jsm b/mobile/android/modules/Snackbars.jsm
deleted file mode 100644
index 066a28c56..000000000
--- a/mobile/android/modules/Snackbars.jsm
+++ /dev/null
@@ -1,72 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = ["Snackbars"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
-
-const LENGTH_INDEFINITE = -2;
-const LENGTH_LONG = 0;
-const LENGTH_SHORT = -1;
-
-var Snackbars = {
- LENGTH_INDEFINITE: LENGTH_INDEFINITE,
- LENGTH_LONG: LENGTH_LONG,
- LENGTH_SHORT: LENGTH_SHORT,
-
- show: function(aMessage, aDuration, aOptions) {
-
- // Takes care of the deprecated toast calls
- if (typeof aDuration === "string") {
- [aDuration, aOptions] = migrateToastIfNeeded(aDuration, aOptions);
- }
-
- let msg = {
- type: 'Snackbar:Show',
- message: aMessage,
- duration: aDuration,
- };
-
- if (aOptions && aOptions.backgroundColor) {
- msg.backgroundColor = aOptions.backgroundColor;
- }
-
- if (aOptions && aOptions.action) {
- msg.action = {};
-
- if (aOptions.action.label) {
- msg.action.label = aOptions.action.label;
- }
-
- Messaging.sendRequestForResult(msg).then(result => aOptions.action.callback());
- } else {
- Messaging.sendRequest(msg);
- }
- }
-};
-
-function migrateToastIfNeeded(aDuration, aOptions) {
- let duration;
- if (aDuration === "long") {
- duration = LENGTH_LONG;
- }
- else {
- duration = LENGTH_SHORT;
- }
-
- let options = {};
- if (aOptions && aOptions.button) {
- options.action = {
- label: aOptions.button.label,
- callback: () => aOptions.button.callback(),
- };
- }
- return [duration, options];
-} \ No newline at end of file
diff --git a/mobile/android/modules/TabMirror.jsm b/mobile/android/modules/TabMirror.jsm
deleted file mode 100644
index 72a640ec8..000000000
--- a/mobile/android/modules/TabMirror.jsm
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
-/* 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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-const CONFIG = { iceServers: [{ "urls": ["stun:stun.services.mozilla.com"] }] };
-
-var log = Cu.import("resource://gre/modules/AndroidLog.jsm",
- {}).AndroidLog.d.bind(null, "TabMirror");
-
-var failure = function(x) {
- log("ERROR: " + JSON.stringify(x));
-};
-
-var TabMirror = function(deviceId, window) {
-
- this.deviceId = deviceId;
- // Save RTCSessionDescription and RTCIceCandidate for later when the window object is not available.
- this.RTCSessionDescription = window.RTCSessionDescription;
- this.RTCIceCandidate = window.RTCIceCandidate;
-
- Services.obs.addObserver((aSubject, aTopic, aData) => this._processMessage(aData), "MediaPlayer:Response", false);
- this._sendMessage({ start: true });
- this._window = window;
- this._pc = new window.RTCPeerConnection(CONFIG, {});
- if (!this._pc) {
- throw "Failure creating Webrtc object";
- }
-
-};
-
-TabMirror.prototype = {
- _window: null,
- _screenSize: { width: 1280, height: 720 },
- _pc: null,
- _start: function() {
- this._pc.onicecandidate = this._onIceCandidate.bind(this);
-
- let windowId = this._window.BrowserApp.selectedBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
- let constraints = {
- video: {
- mediaSource: "browser",
- browserWindow: windowId,
- scrollWithPage: true,
- advanced: [
- { width: { min: 0, max: this._screenSize.width },
- height: { min: 0, max: this._screenSize.height }
- },
- { aspectRatio: this._screenSize.width / this._screenSize.height }
- ]
- }
- };
-
- this._window.navigator.mozGetUserMedia(constraints, this._onGumSuccess.bind(this), this._onGumFailure.bind(this));
- },
-
- _processMessage: function(data) {
- if (!data) {
- return;
- }
-
- let msg = JSON.parse(data);
-
- if (!msg) {
- return;
- }
-
- if (msg.sdp && msg.type === "answer") {
- this._processAnswer(msg);
- } else if (msg.type == "size") {
- if (msg.height) {
- this._screenSize.height = msg.height;
- }
- if (msg.width) {
- this._screenSize.width = msg.width;
- }
- this._start();
- } else if (msg.candidate) {
- this._processIceCandidate(msg);
- } else {
- log("dropping unrecognized message: " + JSON.stringify(msg));
- }
- },
-
- // Signaling methods
- _processAnswer: function(msg) {
- this._pc.setRemoteDescription(new this.RTCSessionDescription(msg),
- this._setRemoteAnswerSuccess.bind(this), failure);
- },
-
- _processIceCandidate: function(msg) {
- // WebRTC generates a warning if the success and fail callbacks are not passed in.
- this._pc.addIceCandidate(new this.RTCIceCandidate(msg), () => log("Ice Candiated added successfuly"), () => log("Failed to add Ice Candidate"));
- },
-
- _setRemoteAnswerSuccess: function() {
- },
-
- _setLocalSuccessOffer: function(sdp) {
- this._sendMessage(sdp);
- },
-
- _createOfferSuccess: function(sdp) {
- this._pc.setLocalDescription(sdp, () => this._setLocalSuccessOffer(sdp), failure);
- },
-
- _onIceCandidate: function (msg) {
- log("NEW Ice Candidate: " + JSON.stringify(msg.candidate));
- this._sendMessage(msg.candidate);
- },
-
- _ready: function() {
- this._pc.createOffer(this._createOfferSuccess.bind(this), failure);
- },
-
- _onGumSuccess: function(stream){
- this._pc.addStream(stream);
- this._ready();
- },
-
- _onGumFailure: function() {
- log("Could not get video stream");
- this._pc.close();
- },
-
- _sendMessage: function(msg) {
- if (this.deviceId) {
- let obj = {
- type: "MediaPlayer:Message",
- id: this.deviceId,
- data: JSON.stringify(msg)
- };
- Messaging.sendRequest(obj);
- }
- },
-
- stop: function() {
- if (this.deviceId) {
- let obj = {
- type: "MediaPlayer:End",
- id: this.deviceId
- };
- Services.androidBridge.handleGeckoMessage(obj);
- }
- },
-};
-
-
-this.EXPORTED_SYMBOLS = ["TabMirror"];
diff --git a/mobile/android/modules/WebsiteMetadata.jsm b/mobile/android/modules/WebsiteMetadata.jsm
deleted file mode 100644
index 39af9ddeb..000000000
--- a/mobile/android/modules/WebsiteMetadata.jsm
+++ /dev/null
@@ -1,475 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = ["WebsiteMetadata"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
-
-var WebsiteMetadata = {
- /**
- * Asynchronously parse the document extract metadata. A 'Website:Metadata' event with the metadata
- * will be sent.
- */
- parseAsynchronously: function(doc) {
- Task.spawn(function() {
- let metadata = getMetadata(doc, doc.location.href, {
- image_url: metadataRules['image_url']
- });
-
- // No metadata was extracted, so don't bother sending it.
- if (Object.keys(metadata).length === 0) {
- return;
- }
-
- let msg = {
- type: 'Website:Metadata',
- location: doc.location.href,
- metadata: metadata,
- };
-
- Messaging.sendRequest(msg);
- });
- }
-};
-
-// #################################################################################################
-// # Modified version of makeUrlAbsolute() to not import url parser library (and dependencies)
-// #################################################################################################
-
-function makeUrlAbsolute(context, relative) {
- var a = context.doc.createElement('a');
- a.href = relative;
- return a.href;
-}
-
-// #################################################################################################
-// # page-metadata-parser
-// # https://github.com/mozilla/page-metadata-parser/
-// # 61c58cbd0f0bf2153df832a388a79c66b288b98c
-// #################################################################################################
-
-function buildRuleset(name, rules, processors) {
- const reversedRules = Array.from(rules).reverse();
- const builtRuleset = ruleset(...reversedRules.map(([query, handler], order) => rule(
- dom(query),
- node => [{
- score: order,
- flavor: name,
- notes: handler(node),
- }]
- )));
-
- return (doc, context) => {
- const kb = builtRuleset.score(doc);
- const maxNode = kb.max(name);
-
- if (maxNode) {
- let value = maxNode.flavors.get(name);
-
- if (processors) {
- processors.forEach(processor => {
- value = processor(value, context);
- });
- }
-
- if (value) {
- if (value.trim) {
- return value.trim();
- }
- return value;
- }
- }
- };
-}
-
-const metadataRules = {
- description: {
- rules: [
- ['meta[property="og:description"]', node => node.element.getAttribute('content')],
- ['meta[name="description"]', node => node.element.getAttribute('content')],
- ],
- },
-
- icon_url: {
- rules: [
- ['link[rel="apple-touch-icon"]', node => node.element.getAttribute('href')],
- ['link[rel="apple-touch-icon-precomposed"]', node => node.element.getAttribute('href')],
- ['link[rel="icon"]', node => node.element.getAttribute('href')],
- ['link[rel="fluid-icon"]', node => node.element.getAttribute('href')],
- ['link[rel="shortcut icon"]', node => node.element.getAttribute('href')],
- ['link[rel="Shortcut Icon"]', node => node.element.getAttribute('href')],
- ['link[rel="mask-icon"]', node => node.element.getAttribute('href')],
- ],
- processors: [
- (icon_url, context) => makeUrlAbsolute(context, icon_url)
- ]
- },
-
- image_url: {
- rules: [
- ['meta[property="og:image:secure_url"]', node => node.element.getAttribute('content')],
- ['meta[property="og:image:url"]', node => node.element.getAttribute('content')],
- ['meta[property="og:image"]', node => node.element.getAttribute('content')],
- ['meta[property="twitter:image"]', node => node.element.getAttribute('content')],
- ['meta[name="thumbnail"]', node => node.element.getAttribute('content')],
- ],
- processors: [
- (image_url, context) => makeUrlAbsolute(context, image_url)
- ],
- },
-
- keywords: {
- rules: [
- ['meta[name="keywords"]', node => node.element.getAttribute('content')],
- ],
- processors: [
- (keywords) => keywords.split(',').map((keyword) => keyword.trim()),
- ]
- },
-
- title: {
- rules: [
- ['meta[property="og:title"]', node => node.element.getAttribute('content')],
- ['meta[property="twitter:title"]', node => node.element.getAttribute('content')],
- ['meta[name="hdl"]', node => node.element.getAttribute('content')],
- ['title', node => node.element.text],
- ],
- },
-
- type: {
- rules: [
- ['meta[property="og:type"]', node => node.element.getAttribute('content')],
- ],
- },
-
- url: {
- rules: [
- ['meta[property="og:url"]', node => node.element.getAttribute('content')],
- ['link[rel="canonical"]', node => node.element.getAttribute('href')],
- ],
- },
-};
-
-function getMetadata(doc, url, rules) {
- const metadata = {};
- const context = {url,doc};
- const ruleSet = rules || metadataRules;
-
- Object.keys(ruleSet).map(metadataKey => {
- const metadataRule = ruleSet[metadataKey];
-
- if(Array.isArray(metadataRule.rules)) {
- const builtRule = buildRuleset(metadataKey, metadataRule.rules, metadataRule.processors);
- metadata[metadataKey] = builtRule(doc, context);
- } else {
- metadata[metadataKey] = getMetadata(doc, url, metadataRule);
- }
- });
-
- return metadata;
-}
-
-// #################################################################################################
-// # Fathom dependencies resolved
-// #################################################################################################
-
-// const {forEach} = require('wu');
-function forEach(fn, obj) {
- for (let x of obj) {
- fn(x);
- }
-}
-
-function best(iterable, by, isBetter) {
- let bestSoFar, bestKeySoFar;
- let isFirst = true;
- forEach(
- function (item) {
- const key = by(item);
- if (isBetter(key, bestKeySoFar) || isFirst) {
- bestSoFar = item;
- bestKeySoFar = key;
- isFirst = false;
- }
- },
- iterable);
- if (isFirst) {
- throw new Error('Tried to call best() on empty iterable');
- }
- return bestSoFar;
-}
-
-// const {max} = require('./utils');
-function max(iterable, by = identity) {
- return best(iterable, by, (a, b) => a > b);
-}
-
-// #################################################################################################
-// # Fathom
-// # https://github.com/mozilla/fathom
-// # cac59e470816f17fc1efd4a34437b585e3e451cd
-// #################################################################################################
-
-// Get a key of a map, first setting it to a default value if it's missing.
-function getDefault(map, key, defaultMaker) {
- if (map.has(key)) {
- return map.get(key);
- }
- const defaultValue = defaultMaker();
- map.set(key, defaultValue);
- return defaultValue;
-}
-
-
-// Construct a filtration network of rules.
-function ruleset(...rules) {
- const rulesByInputFlavor = new Map(); // [someInputFlavor: [rule, ...]]
-
- // File each rule under its input flavor:
- forEach(rule => getDefault(rulesByInputFlavor, rule.source.inputFlavor, () => []).push(rule),
- rules);
-
- return {
- // Iterate over a DOM tree or subtree, building up a knowledgebase, a
- // data structure holding scores and annotations for interesting
- // elements. Return the knowledgebase.
- //
- // This is the "rank" portion of the rank-and-yank algorithm.
- score: function (tree) {
- const kb = knowledgebase();
-
- // Introduce the whole DOM into the KB as flavor 'dom' to get
- // things started:
- const nonterminals = [[{tree}, 'dom']]; // [[node, flavor], [node, flavor], ...]
-
- // While there are new facts, run the applicable rules over them to
- // generate even newer facts. Repeat until everything's fully
- // digested. Rules run in no particular guaranteed order.
- while (nonterminals.length) {
- const [inNode, inFlavor] = nonterminals.pop();
- for (let rule of getDefault(rulesByInputFlavor, inFlavor, () => [])) {
- const outFacts = resultsOf(rule, inNode, inFlavor, kb);
- for (let fact of outFacts) {
- const outNode = kb.nodeForElement(fact.element);
-
- // No matter whether or not this flavor has been
- // emitted before for this node, we multiply the score.
- // We want to be able to add rules that refine the
- // scoring of a node, without having to rewire the path
- // of flavors that winds through the ruleset.
- //
- // 1 score per Node is plenty. That simplifies our
- // data, our rankers, our flavor system (since we don't
- // need to represent score axes), and our engine. If
- // somebody wants more score axes, they can fake it
- // themselves with notes, thus paying only for what
- // they eat. (We can even provide functions that help
- // with that.) Most rulesets will probably be concerned
- // with scoring only 1 thing at a time anyway. So,
- // rankers return a score multiplier + 0 or more new
- // flavors with optional notes. Facts can never be
- // deleted from the KB by rankers (or order would start
- // to matter); after all, they're *facts*.
- outNode.score *= fact.score;
-
- // Add a new annotation to a node--but only if there
- // wasn't already one of the given flavor already
- // there; otherwise there's no point.
- //
- // You might argue that we might want to modify an
- // existing note here, but that would be a bad
- // idea. Notes of a given flavor should be
- // considered immutable once laid down. Otherwise, the
- // order of execution of same-flavored rules could
- // matter, hurting pluggability. Emit a new flavor and
- // a new note if you want to do that.
- //
- // Also, choosing not to add a new fact to nonterminals
- // when we're not adding a new flavor saves the work of
- // running the rules against it, which would be
- // entirely redundant and perform no new work (unless
- // the rankers were nondeterministic, but don't do
- // that).
- if (!outNode.flavors.has(fact.flavor)) {
- outNode.flavors.set(fact.flavor, fact.notes);
- kb.indexNodeByFlavor(outNode, fact.flavor); // TODO: better encapsulation rather than indexing explicitly
- nonterminals.push([outNode, fact.flavor]);
- }
- }
- }
- }
- return kb;
- }
- };
-}
-
-
-// Construct a container for storing and querying facts, where a fact has a
-// flavor (used to dispatch further rules upon), a corresponding DOM element, a
-// score, and some other arbitrary notes opaque to fathom.
-function knowledgebase() {
- const nodesByFlavor = new Map(); // Map{'texty' -> [NodeA],
- // 'spiffy' -> [NodeA, NodeB]}
- // NodeA = {element: <someElement>,
- //
- // // Global nodewide score. Add
- // // custom ones with notes if
- // // you want.
- // score: 8,
- //
- // // Flavors is a map of flavor names to notes:
- // flavors: Map{'texty' -> {ownText: 'blah',
- // someOtherNote: 'foo',
- // someCustomScore: 10},
- // // This is an empty note:
- // 'fluffy' -> undefined}}
- const nodesByElement = new Map();
-
- return {
- // Return the "node" (our own data structure that we control) that
- // corresponds to a given DOM element, creating one if necessary.
- nodeForElement: function (element) {
- return getDefault(nodesByElement,
- element,
- () => ({element,
- score: 1,
- flavors: new Map()}));
- },
-
- // Return the highest-scored node of the given flavor, undefined if
- // there is none.
- max: function (flavor) {
- const nodes = nodesByFlavor.get(flavor);
- return nodes === undefined ? undefined : max(nodes, node => node.score);
- },
-
- // Let the KB know that a new flavor has been added to an element.
- indexNodeByFlavor: function (node, flavor) {
- getDefault(nodesByFlavor, flavor, () => []).push(node);
- },
-
- nodesOfFlavor: function (flavor) {
- return getDefault(nodesByFlavor, flavor, () => []);
- }
- };
-}
-
-
-// Apply a rule (as returned by a call to rule()) to a fact, and return the
-// new facts that result.
-function resultsOf(rule, node, flavor, kb) {
- // If more types of rule pop up someday, do fancier dispatching here.
- return rule.source.flavor === 'flavor' ? resultsOfFlavorRule(rule, node, flavor) : resultsOfDomRule(rule, node, kb);
-}
-
-
-// Pull the DOM tree off the special property of the root "dom" fact, and query
-// against it.
-function *resultsOfDomRule(rule, specialDomNode, kb) {
- // Use the special "tree" property of the special starting node:
- const matches = specialDomNode.tree.querySelectorAll(rule.source.selector);
-
- for (let i = 0; i < matches.length; i++) { // matches is a NodeList, which doesn't conform to iterator protocol
- const element = matches[i];
- const newFacts = explicitFacts(rule.ranker(kb.nodeForElement(element)));
- for (let fact of newFacts) {
- if (fact.element === undefined) {
- fact.element = element;
- }
- if (fact.flavor === undefined) {
- throw new Error('Rankers of dom() rules must return a flavor in each fact. Otherwise, there is no way for that fact to be used later.');
- }
- yield fact;
- }
- }
-}
-
-
-function *resultsOfFlavorRule(rule, node, flavor) {
- const newFacts = explicitFacts(rule.ranker(node));
-
- for (let fact of newFacts) {
- // If the ranker didn't specify a different element, assume it's
- // talking about the one we passed in:
- if (fact.element === undefined) {
- fact.element = node.element;
- }
- if (fact.flavor === undefined) {
- fact.flavor = flavor;
- }
- yield fact;
- }
-}
-
-
-// Take the possibly abbreviated output of a ranker function, and make it
-// explicitly an iterable with a defined score.
-//
-// Rankers can return undefined, which means "no facts", a single fact, or an
-// array of facts.
-function *explicitFacts(rankerResult) {
- const array = (rankerResult === undefined) ? [] : (Array.isArray(rankerResult) ? rankerResult : [rankerResult]);
- for (let fact of array) {
- if (fact.score === undefined) {
- fact.score = 1;
- }
- yield fact;
- }
-}
-
-
-// TODO: For the moment, a lot of responsibility is on the rankers to return a
-// pretty big data structure of up to 4 properties. This is a bit verbose for
-// an arrow function (as I hope we can use most of the time) and the usual case
-// will probably be returning just a score multiplier. Make that case more
-// concise.
-
-// TODO: It is likely that rankers should receive the notes of their input type
-// as a 2nd arg, for brevity.
-
-
-// Return a condition that uses a DOM selector to find its matches from the
-// original DOM tree.
-//
-// For consistency, Nodes will still be delivered to the transformers, but
-// they'll have empty flavors and score = 1.
-//
-// Condition constructors like dom() and flavor() build stupid, introspectable
-// objects that the query engine can read. They don't actually do the query
-// themselves. That way, the query planner can be smarter than them, figuring
-// out which indices to use based on all of them. (We'll probably keep a heap
-// by each dimension's score and a hash by flavor name, for starters.) Someday,
-// fancy things like this may be possible: rule(and(tag('p'), klass('snork')),
-// ...)
-function dom(selector) {
- return {
- flavor: 'dom',
- inputFlavor: 'dom',
- selector
- };
-}
-
-
-// Return a condition that discriminates on nodes of the knowledgebase by flavor.
-function flavor(inputFlavor) {
- return {
- flavor: 'flavor',
- inputFlavor
- };
-}
-
-
-function rule(source, ranker) {
- return {
- source,
- ranker
- };
-}
diff --git a/mobile/android/modules/dbg-browser-actors.js b/mobile/android/modules/dbg-browser-actors.js
deleted file mode 100644
index f96a39151..000000000
--- a/mobile/android/modules/dbg-browser-actors.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* 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";
-/**
- * Fennec-specific actors.
- */
-
-const { RootActor } = require("devtools/server/actors/root");
-const { DebuggerServer } = require("devtools/server/main");
-const { BrowserTabList, BrowserAddonList, sendShutdownEvent } =
- require("devtools/server/actors/webbrowser");
-
-/**
- * Construct a root actor appropriate for use in a server running in a
- * browser on Android. The returned root actor:
- * - respects the factories registered with DebuggerServer.addGlobalActor,
- * - uses a MobileTabList to supply tab actors,
- * - sends all navigator:browser window documents a Debugger:Shutdown event
- * when it exits.
- *
- * * @param aConnection DebuggerServerConnection
- * The conection to the client.
- */
-function createRootActor(aConnection)
-{
- let parameters = {
- tabList: new MobileTabList(aConnection),
- addonList: new BrowserAddonList(aConnection),
- globalActorFactories: DebuggerServer.globalActorFactories,
- onShutdown: sendShutdownEvent
- };
- return new RootActor(aConnection, parameters);
-}
-
-/**
- * A live list of BrowserTabActors representing the current browser tabs,
- * to be provided to the root actor to answer 'listTabs' requests.
- *
- * This object also takes care of listening for TabClose events and
- * onCloseWindow notifications, and exiting the BrowserTabActors concerned.
- *
- * (See the documentation for RootActor for the definition of the "live
- * list" interface.)
- *
- * @param aConnection DebuggerServerConnection
- * The connection in which this list's tab actors may participate.
- *
- * @see BrowserTabList for more a extensive description of how tab list objects
- * work.
- */
-function MobileTabList(aConnection)
-{
- BrowserTabList.call(this, aConnection);
-}
-
-MobileTabList.prototype = Object.create(BrowserTabList.prototype);
-
-MobileTabList.prototype.constructor = MobileTabList;
-
-MobileTabList.prototype._getSelectedBrowser = function(aWindow) {
- return aWindow.BrowserApp.selectedBrowser;
-};
-
-MobileTabList.prototype._getChildren = function(aWindow) {
- return aWindow.BrowserApp.tabs.map(tab => tab.browser);
-};
-
-exports.register = function(handle) {
- handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
- handle.setRootActor(null);
-};
diff --git a/mobile/android/modules/moz.build b/mobile/android/modules/moz.build
deleted file mode 100644
index dd62e484a..000000000
--- a/mobile/android/modules/moz.build
+++ /dev/null
@@ -1,32 +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/.
-
-EXTRA_JS_MODULES += [
- 'Accounts.jsm',
- 'AndroidLog.jsm',
- 'dbg-browser-actors.js',
- 'DelayedInit.jsm',
- 'DownloadNotifications.jsm',
- 'HelperApps.jsm',
- 'Home.jsm',
- 'HomeProvider.jsm',
- 'JavaAddonManager.jsm',
- 'JNI.jsm',
- 'LightweightThemeConsumer.jsm',
- 'MediaPlayerApp.jsm',
- 'Messaging.jsm',
- 'NetErrorHelper.jsm',
- 'Notifications.jsm',
- 'PageActions.jsm',
- 'Prompt.jsm',
- 'RuntimePermissions.jsm',
- 'Sanitizer.jsm',
- 'SharedPreferences.jsm',
- 'Snackbars.jsm',
- 'SSLExceptions.jsm',
- 'TabMirror.jsm',
- 'WebsiteMetadata.jsm'
-]