Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
});
const MOZ_NEWTAB_REMOTE_RENDERER_SCHEME = "moz-newtab-remote-renderer";
export class MozNewTabRemoteRendererProtocolHandler {
#getActor(loadInfo) {
try {
const browsingContext = loadInfo.browsingContext;
const globalChild = browsingContext.window.windowGlobalChild;
return globalChild.getActor("MozNewTabRemoteRendererProtocol");
} catch (e) {
return null;
}
}
/**
* The protocol scheme handled by this handler.
*/
scheme = MOZ_NEWTAB_REMOTE_RENDERER_SCHEME;
/**
* Determines whether a given port is allowed for this protocol.
*
* @param {number} _port
* The port number to check.
* @param {string} _scheme
* The protocol scheme.
* @returns {boolean}
* Always false as this protocol doesn't use ports.
*/
allowPort(_port, _scheme) {
return false;
}
/**
* Creates a new channel for handling moz-newtab-remote-renderer:// URLs.
*
* @param {nsIURI} uri
* The URI to create a channel for.
* @param {nsILoadInfo} loadInfo
* Load information containing security context.
* @returns {MozCachedOHTTPChannel}
* A new channel instance.
* @throws {Components.Exception}
* If the request is not from a valid context
*/
newChannel(uri, loadInfo) {
// Check if we're in a privileged about content process
if (
Services.appinfo.remoteType === lazy.E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE
) {
const innerChannel = Cc["@mozilla.org/network/input-stream-channel;1"]
.createInstance(Ci.nsIInputStreamChannel)
.QueryInterface(Ci.nsIChannel);
innerChannel.loadInfo = loadInfo;
innerChannel.setURI(uri);
let suspendedChannel =
Services.io.newSuspendableChannelWrapper(innerChannel);
suspendedChannel.suspend();
Promise.resolve()
.then(() => {
const actor = this.#getActor(loadInfo);
if (!actor) {
throw Components.Exception(
`${MOZ_NEWTAB_REMOTE_RENDERER_SCHEME} protocol window actor pair not registered`,
Cr.NS_ERROR_NOT_AVAILABLE
);
}
return actor.sendQuery("GetInputStream", {
uriString: uri.spec,
});
})
.then(result => {
if (result.success) {
innerChannel.contentStream = result.inputStream;
innerChannel.contentType = result.contentType;
suspendedChannel.resume();
} else {
innerChannel.cancel(Cr.NS_ERROR_FAILURE);
suspendedChannel.resume();
}
})
.catch(error => {
console.error("Failed to get input stream:", error);
innerChannel.cancel(Cr.NS_ERROR_FAILURE);
suspendedChannel.resume();
});
return suspendedChannel;
}
throw Components.Exception(
`${MOZ_NEWTAB_REMOTE_RENDERER_SCHEME} protocol only accessible from privileged about content`,
Cr.NS_ERROR_INVALID_ARG
);
}
QueryInterface = ChromeUtils.generateQI(["nsIProtocolHandler"]);
}