tor-browser

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

HTTPResponse.ts (3986B)


      1 /**
      2 * @license
      3 * Copyright 2020 Google Inc.
      4 * SPDX-License-Identifier: Apache-2.0
      5 */
      6 import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
      7 import type {Protocol} from 'devtools-protocol';
      8 
      9 import type {Frame} from '../api/Frame.js';
     10 import {HTTPResponse, type RemoteAddress} from '../api/HTTPResponse.js';
     11 import {PageEvent} from '../api/Page.js';
     12 import {UnsupportedOperation} from '../common/Errors.js';
     13 import {SecurityDetails} from '../common/SecurityDetails.js';
     14 import {invokeAtMostOnceForArguments} from '../util/decorators.js';
     15 
     16 import type {BidiHTTPRequest} from './HTTPRequest.js';
     17 
     18 /**
     19 * @internal
     20 */
     21 export class BidiHTTPResponse extends HTTPResponse {
     22  static from(
     23    data: Bidi.Network.ResponseData,
     24    request: BidiHTTPRequest,
     25    cdpSupported: boolean,
     26  ): BidiHTTPResponse {
     27    const response = new BidiHTTPResponse(data, request, cdpSupported);
     28    response.#initialize();
     29    return response;
     30  }
     31 
     32  #data: Bidi.Network.ResponseData;
     33  #request: BidiHTTPRequest;
     34  #securityDetails?: SecurityDetails;
     35  #cdpSupported = false;
     36 
     37  private constructor(
     38    data: Bidi.Network.ResponseData,
     39    request: BidiHTTPRequest,
     40    cdpSupported: boolean,
     41  ) {
     42    super();
     43    this.#data = data;
     44    this.#request = request;
     45    this.#cdpSupported = cdpSupported;
     46 
     47    // @ts-expect-error non-standard property.
     48    const securityDetails = data['goog:securityDetails'];
     49    if (cdpSupported && securityDetails) {
     50      this.#securityDetails = new SecurityDetails(
     51        securityDetails as Protocol.Network.SecurityDetails,
     52      );
     53    }
     54  }
     55 
     56  #initialize() {
     57    if (this.#data.fromCache) {
     58      this.#request._fromMemoryCache = true;
     59      this.#request
     60        .frame()
     61        ?.page()
     62        .trustedEmitter.emit(PageEvent.RequestServedFromCache, this.#request);
     63    }
     64    this.#request.frame()?.page().trustedEmitter.emit(PageEvent.Response, this);
     65  }
     66 
     67  @invokeAtMostOnceForArguments
     68  override remoteAddress(): RemoteAddress {
     69    return {
     70      ip: '',
     71      port: -1,
     72    };
     73  }
     74 
     75  override url(): string {
     76    return this.#data.url;
     77  }
     78 
     79  override status(): number {
     80    return this.#data.status;
     81  }
     82 
     83  override statusText(): string {
     84    return this.#data.statusText;
     85  }
     86 
     87  override headers(): Record<string, string> {
     88    const headers: Record<string, string> = {};
     89    for (const header of this.#data.headers) {
     90      // TODO: How to handle Binary Headers
     91      // https://w3c.github.io/webdriver-bidi/#type-network-Header
     92      if (header.value.type === 'string') {
     93        headers[header.name.toLowerCase()] = header.value.value;
     94      }
     95    }
     96    return headers;
     97  }
     98 
     99  override request(): BidiHTTPRequest {
    100    return this.#request;
    101  }
    102 
    103  override fromCache(): boolean {
    104    return this.#data.fromCache;
    105  }
    106 
    107  override timing(): Protocol.Network.ResourceTiming | null {
    108    const bidiTiming = this.#request.timing();
    109    return {
    110      requestTime: bidiTiming.requestTime,
    111      proxyStart: -1,
    112      proxyEnd: -1,
    113      dnsStart: bidiTiming.dnsStart,
    114      dnsEnd: bidiTiming.dnsEnd,
    115      connectStart: bidiTiming.connectStart,
    116      connectEnd: bidiTiming.connectEnd,
    117      sslStart: bidiTiming.tlsStart,
    118      sslEnd: -1,
    119      workerStart: -1,
    120      workerReady: -1,
    121      workerFetchStart: -1,
    122      workerRespondWithSettled: -1,
    123      workerRouterEvaluationStart: -1,
    124      workerCacheLookupStart: -1,
    125      sendStart: bidiTiming.requestStart,
    126      sendEnd: -1,
    127      pushStart: -1,
    128      pushEnd: -1,
    129      receiveHeadersStart: bidiTiming.responseStart,
    130      receiveHeadersEnd: bidiTiming.responseEnd,
    131    };
    132  }
    133 
    134  override frame(): Frame | null {
    135    return this.#request.frame();
    136  }
    137 
    138  override fromServiceWorker(): boolean {
    139    return false;
    140  }
    141 
    142  override securityDetails(): SecurityDetails | null {
    143    if (!this.#cdpSupported) {
    144      throw new UnsupportedOperation();
    145    }
    146    return this.#securityDetails ?? null;
    147  }
    148 
    149  override content(): never {
    150    throw new UnsupportedOperation();
    151  }
    152 }