tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

head.js (7245B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { NetUtil } = ChromeUtils.importESModule(
      7  "resource://gre/modules/NetUtil.sys.mjs"
      8 );
      9 const { MockRegistrar } = ChromeUtils.importESModule(
     10  "resource://testing-common/MockRegistrar.sys.mjs"
     11 );
     12 const { MozCachedOHTTPProtocolHandler } = ChromeUtils.importESModule(
     13  "moz-src:///browser/components/mozcachedohttp/MozCachedOHTTPProtocolHandler.sys.mjs"
     14 );
     15 
     16 do_get_profile();
     17 
     18 ChromeUtils.registerProcessActor("MozCachedOHTTP", {
     19  parent: {
     20    esModuleURI:
     21      "moz-src:///browser/components/mozcachedohttp/actors/MozCachedOHTTPParent.sys.mjs",
     22  },
     23  includeParent: true,
     24 });
     25 
     26 /**
     27 * Creates a test URI for the moz-cached-ohttp protocol.
     28 *
     29 * @param {string} resourceURL - The target resource URL to encode
     30 * @returns {string} The moz-cached-ohttp:// URI
     31 */
     32 function createTestOHTTPResourceURI(resourceURL) {
     33  const encodedURL = encodeURIComponent(resourceURL);
     34  return `moz-cached-ohttp://newtab-image/?url=${encodedURL}`;
     35 }
     36 
     37 /**
     38 * Creates a test channel with proper load info for privileged about content.
     39 * Always creates a MozCachedOHTTPChannel with the injected mock service.
     40 *
     41 * @param {string} uri - The URI to create a channel for
     42 * @returns {nsIChannel} The created channel
     43 */
     44 function createTestChannel(uri) {
     45  const testURI = Services.io.newURI(uri);
     46  const principal = Services.scriptSecurityManager.getSystemPrincipal();
     47  const protocolHandler = new MozCachedOHTTPProtocolHandler();
     48  protocolHandler.injectOHTTPService(MockOHTTPService);
     49 
     50  const loadInfo = createLoadInfo(
     51    testURI,
     52    principal,
     53    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT,
     54    Ci.nsIContentPolicy.TYPE_OTHER
     55  );
     56 
     57  return protocolHandler.newChannel(testURI, loadInfo);
     58 }
     59 
     60 /**
     61 * Creates a LoadInfo object for testing using the NetUtil.newChannel pattern.
     62 *
     63 * @param {nsIURI} uri - The URI to use for the temporary channel
     64 * @param {nsIPrincipal} loadingPrincipal - The loading principal
     65 * @param {number} securityFlags - Security flags
     66 * @param {number} contentPolicyType - Content policy type
     67 * @returns {nsILoadInfo} LoadInfo object
     68 */
     69 function createLoadInfo(
     70  uri,
     71  loadingPrincipal,
     72  securityFlags,
     73  contentPolicyType
     74 ) {
     75  return NetUtil.newChannel({
     76    uri,
     77    loadingPrincipal,
     78    securityFlags,
     79    contentPolicyType,
     80  }).loadInfo;
     81 }
     82 
     83 /**
     84 * Creates a reusable data collecting listener for testing channel responses.
     85 *
     86 * @param {Function} onComplete
     87 *   Callback executed on completion with (data, success).
     88 * @returns {nsIStreamListener}
     89 *   Stream listener implementation
     90 */
     91 function createDataCollectingListener(onComplete) {
     92  let receivedData = "";
     93 
     94  return {
     95    onStartRequest() {},
     96 
     97    onDataAvailable(request, inputStream, offset, count) {
     98      const binaryInputStream = Cc[
     99        "@mozilla.org/binaryinputstream;1"
    100      ].createInstance(Ci.nsIBinaryInputStream);
    101      binaryInputStream.setInputStream(inputStream);
    102      receivedData += binaryInputStream.readBytes(count);
    103    },
    104 
    105    onStopRequest(request, status) {
    106      const success = Components.isSuccessCode(status);
    107      onComplete(receivedData, success);
    108    },
    109  };
    110 }
    111 
    112 /**
    113 * Creates a simple completion listener for testing channel success/failure.
    114 *
    115 * @param {Function} onComplete
    116 *   Callback executed on completion with (success).
    117 * @returns {nsIStreamListener}
    118 *   Stream listener implementation
    119 */
    120 function createCompletionListener(onComplete) {
    121  let receivedData = false;
    122 
    123  return {
    124    onStartRequest() {},
    125 
    126    onDataAvailable() {
    127      receivedData = true;
    128    },
    129 
    130    onStopRequest(request, status) {
    131      const success = Components.isSuccessCode(status);
    132      onComplete(success, receivedData);
    133    },
    134  };
    135 }
    136 
    137 /**
    138 * Mock OHTTP service for testing.
    139 * Simulates nsIObliviousHttpService behavior for protocol handler testing.
    140 */
    141 const MockOHTTPService = {
    142  channelCreated: false,
    143  totalChannels: 0,
    144  lastRelayURI: null,
    145  lastTargetURI: null,
    146  lastConfig: null,
    147  shouldSucceed: true,
    148  shouldUseContentTypeHeader: "",
    149 
    150  /**
    151   * Creates a mock channel that simulates OHTTP behavior.
    152   *
    153   * @param {nsIURI} relayURI
    154   *   The OHTTP relay URI.
    155   * @param {nsIURI} targetURI
    156   *   The target resource URI.
    157   * @param {Uint8Array} config
    158   *   OHTTP configuration.
    159   * @returns {nsIChannel}
    160   *   Mock channel implementation.
    161   */
    162  newChannel(relayURI, targetURI, config) {
    163    this.channelCreated = true;
    164    this.lastRelayURI = relayURI;
    165    this.lastTargetURI = targetURI;
    166    this.lastConfig = config;
    167    this.totalChannels++;
    168 
    169    return this._createMockChannel(
    170      targetURI,
    171      this.shouldSucceed,
    172      this.shouldUseContentTypeHeader
    173    );
    174  },
    175 
    176  /**
    177   * Creates a mock channel with configurable success behavior.
    178   *
    179   * @param {nsIURI} targetURI
    180   *   The URI for the channel.
    181   * @param {boolean} shouldSucceed
    182   *   Whether the channel should succeed.
    183   * @param {string} shouldUseContentTypeHeader
    184   *   The Content-Type to have a header value set to, or the empty string
    185   *   for no Content-Type.
    186   * @returns {nsIChannel}
    187   *   Mock channel implementation.
    188   */
    189  _createMockChannel(targetURI, shouldSucceed, shouldUseContentTypeHeader) {
    190    return {
    191      URI: targetURI,
    192      loadInfo: null,
    193      loadFlags: 0,
    194      notificationCallbacks: null,
    195      loadGroup: null,
    196 
    197      asyncOpen(listener) {
    198        Services.tm.dispatchToMainThread(() => {
    199          this._simulateChannelResponse(listener, shouldSucceed);
    200        });
    201      },
    202 
    203      _simulateChannelResponse(listener, success) {
    204        try {
    205          listener.onStartRequest(this);
    206 
    207          if (success) {
    208            const data = new ArrayBuffer(1024);
    209            const inputStream = Cc[
    210              "@mozilla.org/io/arraybuffer-input-stream;1"
    211            ].createInstance(Ci.nsIArrayBufferInputStream);
    212            inputStream.setData(data, 0, data.byteLength);
    213            listener.onDataAvailable(this, inputStream, 0, data.byteLength);
    214          }
    215 
    216          listener.onStopRequest(
    217            this,
    218            success ? Cr.NS_OK : Cr.NS_ERROR_FAILURE
    219          );
    220        } catch (e) {
    221          listener.onStopRequest(this, Cr.NS_ERROR_FAILURE);
    222        }
    223      },
    224 
    225      visitResponseHeaders(visitor) {
    226        if (shouldUseContentTypeHeader) {
    227          visitor.visitHeader("Content-Type", shouldUseContentTypeHeader);
    228        }
    229      },
    230 
    231      QueryInterface: ChromeUtils.generateQI(["nsIChannel", "nsIRequest"]),
    232    };
    233  },
    234 
    235  /**
    236   * Resets the mock service state to initial values.
    237   */
    238  reset() {
    239    this.channelCreated = false;
    240    this.totalChannels = 0;
    241    this.lastRelayURI = null;
    242    this.lastTargetURI = null;
    243    this.lastConfig = null;
    244    this.shouldSucceed = true;
    245    this.shouldUseContentTypeHeader = "";
    246  },
    247 
    248  QueryInterface: ChromeUtils.generateQI(["nsIObliviousHttpService"]),
    249 };
    250 
    251 add_setup(async () => {
    252  registerCleanupFunction(() => {
    253    // Invokes OnHandleClosed on any nsICacheEntry instances that have been
    254    // used, allowing them to be closed out before the nsICacheStorageService
    255    // shuts down (which causes leak assertion failures in debug builds).
    256    Cu.forceGC();
    257  });
    258 });