1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * Dumping ground for simple services for which the isolation of a full global
7 * is overkill. Be careful about namespace pollution, and be mindful about
8 * importing lots of JSMs in global scope, since this file will almost certainly
9 * be loaded from enough callsites that any such imports will always end up getting
10 * eagerly loaded at startup.
13 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
17 ChromeUtils.defineESModuleGetters(lazy, {
18 NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
21 XPCOMUtils.defineLazyServiceGetter(
24 "@mozilla.org/streamConverters;1",
25 "nsIStreamConverterService"
27 const ArrayBufferInputStream = Components.Constructor(
28 "@mozilla.org/io/arraybuffer-input-stream;1",
29 "nsIArrayBufferInputStream",
34 * This class provides a stream filter for locale messages in CSS files served
35 * by the moz-extension: protocol handler.
37 * See SubstituteChannel in netwerk/protocol/res/ExtensionProtocolHandler.cpp
40 export function AddonLocalizationConverter() {}
42 AddonLocalizationConverter.prototype = {
43 QueryInterface: ChromeUtils.generateQI(["nsIStreamConverter"]),
45 FROM_TYPE: "application/vnd.mozilla.webext.unlocalized",
48 checkTypes(aFromType, aToType) {
49 if (aFromType != this.FROM_TYPE) {
50 throw Components.Exception(
51 "Invalid aFromType value",
52 Cr.NS_ERROR_INVALID_ARG,
53 Components.stack.caller.caller
56 if (aToType != this.TO_TYPE) {
57 throw Components.Exception(
58 "Invalid aToType value",
59 Cr.NS_ERROR_INVALID_ARG,
60 Components.stack.caller.caller
65 // aContext must be a nsIURI object for a valid moz-extension: URL.
67 // In this case, we want the add-on ID even if the URL is web accessible,
68 // so check the root rather than the exact path.
69 let uri = Services.io.newURI("/", null, aContext);
71 let addon = WebExtensionPolicy.getByURI(uri);
73 throw new Components.Exception(
75 Cr.NS_ERROR_INVALID_ARG
81 convertToStream(aAddon, aString) {
82 aString = aAddon.localize(aString);
83 let bytes = new TextEncoder().encode(aString).buffer;
84 return new ArrayBufferInputStream(bytes, 0, bytes.byteLength);
87 convert(aStream, aFromType, aToType, aContext) {
88 this.checkTypes(aFromType, aToType);
89 let addon = this.getAddon(aContext);
91 let count = aStream.available();
93 ? new TextDecoder().decode(lazy.NetUtil.readInputStream(aStream, count))
95 return this.convertToStream(addon, string);
98 asyncConvertData(aFromType, aToType, aListener, aContext) {
99 this.checkTypes(aFromType, aToType);
100 this.addon = this.getAddon(aContext);
101 this.listener = aListener;
106 this.decoder = new TextDecoder();
109 onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
110 let bytes = lazy.NetUtil.readInputStream(aInputStream, aCount);
111 this.parts.push(this.decoder.decode(bytes, { stream: true }));
114 onStopRequest(aRequest, aStatusCode) {
116 this.listener.onStartRequest(aRequest, null);
117 if (Components.isSuccessCode(aStatusCode)) {
118 this.parts.push(this.decoder.decode());
119 let string = this.parts.join("");
120 let stream = this.convertToStream(this.addon, string);
122 this.listener.onDataAvailable(aRequest, stream, 0, stream.available());
125 aStatusCode = e.result || Cr.NS_ERROR_FAILURE;
127 this.listener.onStopRequest(aRequest, aStatusCode);
131 export function HttpIndexViewer() {}
133 HttpIndexViewer.prototype = {
134 QueryInterface: ChromeUtils.generateQI(["nsIDocumentLoaderFactory"]),
145 // Bug 1824325: application/http-index-format is deprecated for almost all
146 // sites, we only allow it for urls with a inner scheme of "file" or
147 // "moz-gio" (specified in network.http_index_format.allowed_schemes).
148 // This also includes jar: and resource:// uris, as jar: uris has a inner
149 // scheme of "file", and resource:// uris have been turned into either a
150 // jar: or file:// uri by the point where we are checking them here.
152 let uri = aChannel.URI;
153 if (uri instanceof Ci.nsINestedURI) {
154 uri = uri.QueryInterface(Ci.nsINestedURI).innermostURI;
157 const allowedSchemes = Services.prefs.getStringPref(
158 "network.http_index_format.allowed_schemes",
162 allowedSchemes === "*" || allowedSchemes.split(",").some(uri.schemeIs);
163 let contentType = isFile ? "text/html" : "text/plain";
165 aChannel.contentType = contentType;
167 // NOTE: This assumes that both text/html and text/plain will continue to be
168 // handled by nsContentDLF. If this ever changes this logic will need to be
171 "@mozilla.org/content/document-loader-factory;1"
172 ].getService(Ci.nsIDocumentLoaderFactory);
175 let res = factory.createInstance(
186 aDocListenerResult.value = lazy.streamConv.asyncConvertData(
187 "application/http-index-format",
193 aDocListenerResult.value = listener.value;
194 aChannel.loadInfo.browsingContext.window.console.warn(
195 "application/http-index-format is deprecated, content will display as plain text"