gecko-dev/mobile/android/modules/geckoview/Messaging.jsm
Andrew McCreight 5dec0e0beb Bug 1432992, part 1 - Remove definitions of Ci, Cr, Cc, and Cu. r=florian
This patch was autogenerated by my decomponents.py

It covers almost every file with the extension js, jsm, html, py,
xhtml, or xul.

It removes blank lines after removed lines, when the removed lines are
preceded by either blank lines or the start of a new block. The "start
of a new block" is defined fairly hackily: either the line starts with
//, ends with */, ends with {, <![CDATA[, """ or '''. The first two
cover comments, the third one covers JS, the fourth covers JS embedded
in XUL, and the final two cover JS embedded in Python. This also
applies if the removed line was the first line of the file.

It covers the pattern matching cases like "var {classes: Cc,
interfaces: Ci, utils: Cu, results: Cr} = Components;". It'll remove
the entire thing if they are all either Ci, Cr, Cc or Cu, or it will
remove the appropriate ones and leave the residue behind. If there's
only one behind, then it will turn it into a normal, non-pattern
matching variable definition. (For instance, "const { classes: Cc,
Constructor: CC, interfaces: Ci, utils: Cu } = Components" becomes
"const CC = Components.Constructor".)

MozReview-Commit-ID: DeSHcClQ7cG

--HG--
extra : rebase_source : d9c41878036c1ef7766ef5e91a7005025bc1d72b
2018-02-06 09:36:57 -08:00

316 lines
9.9 KiB
JavaScript

/* 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";
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
this.EXPORTED_SYMBOLS = ["sendMessageToJava", "Messaging", "EventDispatcher"];
ChromeUtils.defineModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "UUIDGen",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
const IS_PARENT_PROCESS = (Services.appinfo.processType ==
Services.appinfo.PROCESS_TYPE_DEFAULT);
function sendMessageToJava(aMessage, aCallback) {
Cu.reportError("sendMessageToJava is deprecated. Use EventDispatcher instead.");
if (aCallback) {
EventDispatcher.instance.sendRequestForResult(aMessage)
.then(result => aCallback(result, null),
error => aCallback(null, error));
} else {
EventDispatcher.instance.sendRequest(aMessage);
}
}
function DispatcherDelegate(aDispatcher, aMessageManager) {
this._dispatcher = aDispatcher;
this._messageManager = aMessageManager;
}
DispatcherDelegate.prototype = {
/**
* Register a listener to be notified of event(s).
*
* @param listener Target listener implementing nsIAndroidEventListener.
* @param events String or array of strings of events to listen to.
*/
registerListener: function(listener, events) {
if (!this._dispatcher) {
throw new Error("Can only listen in parent process");
}
this._dispatcher.registerListener(listener, events);
},
/**
* Unregister a previously-registered listener.
*
* @param listener Registered listener implementing nsIAndroidEventListener.
* @param events String or array of strings of events to stop listening to.
*/
unregisterListener: function(listener, events) {
if (!this._dispatcher) {
throw new Error("Can only listen in parent process");
}
this._dispatcher.unregisterListener(listener, events);
},
/**
* Dispatch an event to registered listeners for that event, and pass an
* optional data object and/or a optional callback interface to the
* listeners.
*
* @param event Name of event to dispatch.
* @param data Optional object containing data for the event.
* @param callback Optional callback implementing nsIAndroidEventCallback.
*/
dispatch: function(event, data, callback) {
if (this._dispatcher) {
this._dispatcher.dispatch(event, data, callback);
return;
}
let mm = this._messageManager || Services.cpmm;
let forwardData = {
global: !this._messageManager,
event: event,
data: data,
};
if (callback) {
forwardData.uuid = UUIDGen.generateUUID().toString();
mm.addMessageListener("GeckoView:MessagingReply", function listener(msg) {
if (msg.data.uuid === forwardData.uuid) {
mm.removeMessageListener(msg.name, listener);
if (msg.data.type === "success") {
callback.onSuccess(msg.data.response);
} else if (msg.data.type === "error") {
callback.onError(msg.data.response);
} else {
throw new Error("invalid reply type");
}
}
});
}
mm.sendAsyncMessage("GeckoView:Messaging", forwardData);
},
/**
* Implementations of Messaging APIs for backwards compatibility.
*/
/**
* Sends a request to Java.
*
* @param msg Message to send; must be an object with a "type" property
*/
sendRequest: function(msg, callback) {
let type = msg.type;
msg.type = undefined;
this.dispatch(type, msg, callback);
},
/**
* Sends a request to Java, returning a Promise that resolves to the response.
*
* @param msg Message to send; must be an object with a "type" property
* @returns A Promise resolving to the response
*/
sendRequestForResult: function(msg) {
return new Promise((resolve, reject) => {
let type = msg.type;
msg.type = undefined;
this.dispatch(type, msg, {
onSuccess: resolve,
onError: reject,
});
});
},
/**
* Add a listener for the given event.
*
* Only one request listener can be registered for a given event.
*
* 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 {};
* };
* EventDispatcher.instance.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" };
* };
* EventDispatcher.instance.addListener(listener, "Demo:Request");
*
* @param listener Listener callback taking a single data parameter
* (see example usage above).
* @param event Event name that this listener should observe.
*/
addListener: function(listener, event) {
if (this._requestHandler.listeners[event]) {
throw new Error("Error in addListener: A listener already exists for event " + event);
}
if (typeof listener !== "function") {
throw new Error("Error in addListener: Listener must be a function for event " + event);
}
this._requestHandler.listeners[event] = listener;
this.registerListener(this._requestHandler, event);
},
/**
* Removes a listener for a given event.
*
* @param event The event to stop listening for.
*/
removeListener: function(event) {
if (!this._requestHandler.listeners[event]) {
throw new Error("Error in removeListener: There is no listener for event " + event);
}
this._requestHandler.listeners[event] = undefined;
this.unregisterListener(this._requestHandler, event);
},
_requestHandler: {
listeners: {},
onEvent: function(event, data, callback) {
let self = this;
Task.spawn(function* () {
return yield self.listeners[event](data.data);
}).then(response => {
callback.onSuccess(response);
}, e => {
Cu.reportError("Error in Messaging handler for " + event + ": " + e);
callback.onError({
message: e.message || (e && e.toString()),
stack: e.stack || Components.stack.formattedStack,
});
});
},
},
};
var EventDispatcher = {
instance: new DispatcherDelegate(IS_PARENT_PROCESS ? Services.androidBridge : undefined),
/**
* Return an EventDispatcher instance for a chrome DOM window. In a content
* process, return a proxy through the message manager that automatically
* forwards events to the main process.
*
* To force using a message manager proxy (for example in a frame script
* environment), call forMessageManager.
*
* @param aWindow a chrome DOM window.
*/
for: function(aWindow) {
let view = aWindow && aWindow.arguments && aWindow.arguments[0] &&
aWindow.arguments[0].QueryInterface(Ci.nsIAndroidView);
if (!view) {
let mm = !IS_PARENT_PROCESS && aWindow && aWindow.messageManager;
if (!mm) {
throw new Error("window is not a GeckoView-connected window and does" +
" not have a message manager");
}
return this.forMessageManager(mm);
}
return new DispatcherDelegate(view);
},
/**
* Return an EventDispatcher instance for a message manager associated with a
* window.
*
* @param aWindow a message manager.
*/
forMessageManager: function(aMessageManager) {
return new DispatcherDelegate(null, aMessageManager);
},
receiveMessage: function(aMsg) {
// aMsg.data includes keys: global, event, data, uuid
let callback;
if (aMsg.data.uuid) {
let reply = (type, response) => {
let mm = aMsg.data.global ? aMsg.target : aMsg.target.messageManager;
mm.sendAsyncMessage("GeckoView:MessagingReply", {
type: type,
response: response,
uuid: aMsg.data.uuid,
});
};
callback = {
onSuccess: response => reply("success", response),
onError: error => reply("error", error),
};
}
if (aMsg.data.global) {
this.instance.dispatch(aMsg.data.event, aMsg.data.data.callback);
return;
}
let win = aMsg.target.ownerGlobal;
let dispatcher = win.WindowEventDispatcher || this.for(win);
dispatcher.dispatch(aMsg.data.event, aMsg.data.data, callback);
},
};
if (IS_PARENT_PROCESS) {
Services.mm.addMessageListener("GeckoView:Messaging", EventDispatcher);
Services.ppmm.addMessageListener("GeckoView:Messaging", EventDispatcher);
}
// For backwards compatibility.
var Messaging = {};
function _addMessagingGetter(name) {
Messaging[name] = function() {
Cu.reportError("Messaging." + name + " is deprecated. " +
"Use EventDispatcher object instead.");
// Try global dispatcher first.
let ret = EventDispatcher.instance[name].apply(EventDispatcher.instance, arguments);
if (ret) {
// For sendRequestForResult, return the global dispatcher promise.
return ret;
}
// Now try the window dispatcher.
let window = Services.wm.getMostRecentWindow("navigator:browser");
let dispatcher = window && window.WindowEventDispatcher;
let func = dispatcher && dispatcher[name];
if (typeof func === "function") {
return func.apply(dispatcher, arguments);
}
};
}
_addMessagingGetter("sendRequest");
_addMessagingGetter("sendRequestForResult");
_addMessagingGetter("addListener");
_addMessagingGetter("removeListener");