Bug 1286712 - Validate runtime.sendMessage parameters r=billm

The main motive for this patch is to remove the use of the GlobalManager
global (which was used to see if an extension ID is valid, which was
specifically added in order to create thebrowser_ext_lastError.js test).
To preserve test coverage I implemented a full validation of the
runtime.sendMessage method.

Now the error for a non-existent extension is identical in both the
content script and background pages. Note that this also fixes a
minor privacy leak: Previously extensions could see whether another
extension is installed by sending a message to the specified extension
and using the different responses to see whether another extension is
installed.

MozReview-Commit-ID: 82R97Ei25Xr
This commit is contained in:
Rob Wu
2016-08-16 21:36:42 -07:00
parent 08d2f6f5b6
commit 47e975c1fb
5 changed files with 99 additions and 12 deletions

View File

@@ -74,20 +74,38 @@ extensions.registerSchemaAPI("runtime", context => {
sendMessage: function(...args) {
let options; // eslint-disable-line no-unused-vars
let extensionId, message, responseCallback;
if (args.length == 1) {
if (typeof args[args.length - 1] == "function") {
responseCallback = args.pop();
}
if (!args.length) {
return Promise.reject({message: "runtime.sendMessage's message argument is missing"});
} else if (args.length == 1) {
message = args[0];
} else if (args.length == 2) {
[message, responseCallback] = args;
if (typeof args[0] == "string" && args[0]) {
[extensionId, message] = args;
} else {
[message, options] = args;
}
} else if (args.length == 3) {
[extensionId, message, options] = args;
} else if (args.length == 4 && !responseCallback) {
return Promise.reject({message: "runtime.sendMessage's last argument is not a function"});
} else {
[extensionId, message, options, responseCallback] = args;
return Promise.reject({message: "runtime.sendMessage received too many arguments"});
}
if (extensionId != null && typeof extensionId != "string") {
return Promise.reject({message: "runtime.sendMessage's extensionId argument is invalid"});
}
if (options != null && typeof options != "object") {
return Promise.reject({message: "runtime.sendMessage's options argument is invalid"});
}
// TODO(robwu): Validate option keys and values when we support it.
extensionId = extensionId || extension.id;
let recipient = {extensionId};
if (!GlobalManager.extensionMap.has(recipient.extensionId)) {
return context.wrapPromise(Promise.reject({message: "Invalid extension ID"}),
responseCallback);
}
return context.messenger.sendMessage(Services.cpmm, message, recipient, responseCallback);
},