Bug 1238128 - Ensure that the details passed to WebChannelMessageToChrome is a string, with a whitelist for messages from existing users r=Margaret,markh,MattN
MozReview-Commit-ID: DpdJ5bUcBdQ
This commit is contained in:
@@ -814,17 +814,56 @@ var FindBar = {
|
||||
};
|
||||
FindBar.init();
|
||||
|
||||
// An event listener for custom "WebChannelMessageToChrome" events on pages.
|
||||
addEventListener("WebChannelMessageToChrome", function (e) {
|
||||
// If target is window then we want the document principal, otherwise fallback to target itself.
|
||||
let principal = e.target.nodePrincipal ? e.target.nodePrincipal : e.target.document.nodePrincipal;
|
||||
let WebChannelMessageToChromeListener = {
|
||||
// Preference containing the list (space separated) of origins that are
|
||||
// allowed to send non-string values through a WebChannel, mainly for
|
||||
// backwards compatability. See bug 1238128 for more information.
|
||||
URL_WHITELIST_PREF: "webchannel.allowObject.urlWhitelist",
|
||||
|
||||
if (e.detail) {
|
||||
sendAsyncMessage("WebChannelMessageToChrome", e.detail, { eventTarget: e.target }, principal);
|
||||
} else {
|
||||
Cu.reportError("WebChannel message failed. No message detail.");
|
||||
// Cached list of whitelisted principals, we avoid constructing this if the
|
||||
// value in `_lastWhitelistValue` hasn't changed since we constructed it last.
|
||||
_cachedWhitelist: [],
|
||||
_lastWhitelistValue: "",
|
||||
|
||||
init() {
|
||||
addEventListener("WebChannelMessageToChrome", e => {
|
||||
this._onMessageToChrome(e);
|
||||
}, true, true);
|
||||
},
|
||||
|
||||
_getWhitelistedPrincipals() {
|
||||
let whitelist = Services.prefs.getCharPref(this.URL_WHITELIST_PREF);
|
||||
if (whitelist != this._lastWhitelistValue) {
|
||||
let urls = whitelist.split(/\s+/);
|
||||
this._cachedWhitelist = urls.map(origin =>
|
||||
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin));
|
||||
}
|
||||
return this._cachedWhitelist;
|
||||
},
|
||||
|
||||
_onMessageToChrome(e) {
|
||||
// If target is window then we want the document principal, otherwise fallback to target itself.
|
||||
let principal = e.target.nodePrincipal ? e.target.nodePrincipal : e.target.document.nodePrincipal;
|
||||
|
||||
if (e.detail) {
|
||||
if (typeof e.detail != 'string') {
|
||||
// Check if the principal is one of the ones that's allowed to send
|
||||
// non-string values for e.detail.
|
||||
let objectsAllowed = this._getWhitelistedPrincipals().some(whitelisted =>
|
||||
principal.originNoSuffix == whitelisted.originNoSuffix);
|
||||
if (!objectsAllowed) {
|
||||
Cu.reportError("WebChannelMessageToChrome sent with an object from a non-whitelisted principal");
|
||||
return;
|
||||
}
|
||||
}
|
||||
sendAsyncMessage("WebChannelMessageToChrome", e.detail, { eventTarget: e.target }, principal);
|
||||
} else {
|
||||
Cu.reportError("WebChannel message failed. No message detail.");
|
||||
}
|
||||
}
|
||||
}, true, true);
|
||||
};
|
||||
|
||||
WebChannelMessageToChromeListener.init();
|
||||
|
||||
// This should be kept in sync with /browser/base/content.js.
|
||||
// Add message listener for "WebChannelMessageToContent" messages from chrome scripts.
|
||||
|
||||
Reference in New Issue
Block a user