tor-browser

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

HtmlPreview.js (3018B)


      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/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  Component,
      9 } = require("resource://devtools/client/shared/vendor/react.mjs");
     10 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     11 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     12 
     13 /*
     14 * Response preview component
     15 * Display HTML content within a sandbox enabled iframe
     16 */
     17 class HTMLPreview extends Component {
     18  static get propTypes() {
     19    return {
     20      responseContent: PropTypes.object.isRequired,
     21      responseHeaders: PropTypes.object,
     22      url: PropTypes.string.isRequired,
     23    };
     24  }
     25 
     26  componentDidMount() {
     27    const { container } = this.refs;
     28    const browser = container.ownerDocument.createXULElement("browser");
     29    this.browser = browser;
     30    browser.setAttribute("type", "content");
     31    browser.setAttribute("remote", "true");
     32    browser.setAttribute("maychangeremoteness", "true");
     33    browser.setAttribute("disableglobalhistory", "true");
     34 
     35    // Bug 1800916 allow interaction with the preview page until
     36    // we find a way to prevent navigation without preventing copy paste from it.
     37    //
     38    // browser.addEventListener("mousedown", e => e.preventDefault(), {
     39    //   capture: true,
     40    // });
     41    container.appendChild(browser);
     42 
     43    // browsingContext attribute is only available after the browser
     44    // is attached to the DOM Tree.
     45    browser.browsingContext.allowJavascript = false;
     46 
     47    this.#updatePreview();
     48  }
     49 
     50  componentDidUpdate() {
     51    this.#updatePreview();
     52  }
     53 
     54  componentWillUnmount() {
     55    this.browser.remove();
     56  }
     57 
     58  #updatePreview() {
     59    const { responseContent, responseHeaders, url } = this.props;
     60    const htmlBody = responseContent ? responseContent.content.text : "";
     61    const uri = Services.io.newURI(
     62      "data:text/html;charset=UTF-8," + encodeURIComponent(htmlBody)
     63    );
     64 
     65    let policyContainer;
     66    const cspHeaders = responseHeaders?.headers.filter(
     67      e => e.name.toLowerCase() === "content-security-policy"
     68    );
     69    if (cspHeaders?.length) {
     70      // Merge multiple CSP headers with a comma.
     71      const merged = cspHeaders.map(e => e.value).join(",");
     72      const csp = ChromeUtils.createCSPFromHeader(
     73        merged,
     74        new URL(url).URI,
     75        Services.scriptSecurityManager.createNullPrincipal({})
     76      );
     77      const PolicyContainer = Components.Constructor(
     78        "@mozilla.org/policycontainer;1",
     79        "nsIPolicyContainer",
     80        "initFromCSP"
     81      );
     82      policyContainer = new PolicyContainer(csp);
     83    }
     84 
     85    const options = {
     86      policyContainer,
     87      triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     88    };
     89    this.browser.loadURI(uri, options);
     90  }
     91 
     92  render() {
     93    return dom.div({ className: "html-preview", ref: "container" });
     94  }
     95 }
     96 
     97 module.exports = HTMLPreview;