tor-browser

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

index.js (6701B)


      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 { BrowserLoader } = ChromeUtils.importESModule(
      8  "resource://devtools/shared/loader/browser-loader.sys.mjs"
      9 );
     10 const { require } = BrowserLoader({
     11  baseURI: "resource://devtools/client/responsive/",
     12  window,
     13 });
     14 const Telemetry = require("resource://devtools/client/shared/telemetry.js");
     15 
     16 const {
     17  createFactory,
     18  createElement,
     19 } = require("resource://devtools/client/shared/vendor/react.mjs");
     20 const ReactDOM = require("resource://devtools/client/shared/vendor/react-dom.mjs");
     21 const {
     22  Provider,
     23 } = require("resource://devtools/client/shared/vendor/react-redux.js");
     24 const {
     25  START_IGNORE_ACTION,
     26 } = require("resource://devtools/client/shared/redux/middleware/ignore.js");
     27 
     28 const message = require("resource://devtools/client/responsive/utils/message.js");
     29 const App = createFactory(
     30  require("resource://devtools/client/responsive/components/App.js")
     31 );
     32 const Store = require("resource://devtools/client/responsive/store.js");
     33 const {
     34  loadDevices,
     35  restoreDeviceState,
     36 } = require("resource://devtools/client/responsive/actions/devices.js");
     37 const {
     38  addViewport,
     39  removeDeviceAssociation,
     40  resizeViewport,
     41  zoomViewport,
     42 } = require("resource://devtools/client/responsive/actions/viewports.js");
     43 const {
     44  changeDisplayPixelRatio,
     45 } = require("resource://devtools/client/responsive/actions/ui.js");
     46 
     47 // Exposed for use by tests
     48 window.require = require;
     49 
     50 // Tell the ResponsiveUIManager that the frame script has begun initializing.
     51 message.post(window, "script-init");
     52 
     53 const bootstrap = {
     54  telemetry: new Telemetry(),
     55 
     56  store: null,
     57 
     58  async init() {
     59    this.telemetry.toolOpened("responsive", this);
     60 
     61    const store = (this.store = Store());
     62    const provider = createElement(Provider, { store }, App());
     63    this._root = document.querySelector("#root");
     64    ReactDOM.render(provider, this._root);
     65    message.post(window, "init:done");
     66 
     67    this.destroy = this.destroy.bind(this);
     68    window.addEventListener("unload", this.destroy, { once: true });
     69  },
     70 
     71  destroy() {
     72    window.removeEventListener("unload", this.destroy, { once: true });
     73 
     74    // Prevents any further action from being dispatched
     75    this.store.dispatch(START_IGNORE_ACTION);
     76 
     77    // unmount to stop async action and renders after destroy
     78    ReactDOM.unmountComponentAtNode(this._root);
     79 
     80    this.store = null;
     81 
     82    this.telemetry.toolClosed("responsive", this);
     83    this.telemetry = null;
     84  },
     85 
     86  /**
     87   * While most actions will be dispatched by React components, some external
     88   * APIs that coordinate with the larger browser UI may also have actions to
     89   * to dispatch.  They can do so here.
     90   */
     91  dispatch(action) {
     92    if (!this.store) {
     93      // If actions are dispatched after store is destroyed, ignore them.  This
     94      // can happen in tests that close the tool quickly while async tasks like
     95      // initDevices() below are still pending.
     96      return Promise.resolve();
     97    }
     98    return this.store.dispatch(action);
     99  },
    100 };
    101 
    102 // manager.js sends a message to signal init
    103 message.wait(window, "init").then(() => bootstrap.init());
    104 
    105 // manager.js sends a message to signal init is done, which can be used for delayed
    106 // startup work that shouldn't block initial load
    107 message.wait(window, "post-init").then(() => {
    108  bootstrap.dispatch(loadDevices()).then(() => {
    109    bootstrap.dispatch(restoreDeviceState());
    110  });
    111 });
    112 
    113 window.destroy = () => bootstrap.destroy();
    114 // Allows quick testing of actions from the console
    115 window.dispatch = action => bootstrap.dispatch(action);
    116 
    117 // Expose the store on window for testing
    118 Object.defineProperty(window, "store", {
    119  get: () => bootstrap.store,
    120  enumerable: true,
    121 });
    122 
    123 // Dispatch a `changeDisplayPixelRatio` action when the browser's pixel ratio is changing.
    124 // This is usually triggered when the user changes the monitor resolution, or when the
    125 // browser's window is dragged to a different display with a different pixel ratio.
    126 // TODO: It would be better to move this watching into the actor, so that it can be
    127 // better synchronized with any overrides that might be applied.  Also, reading a single
    128 // value like this makes less sense with multiple viewports.
    129 function onDevicePixelRatioChange() {
    130  const dpr = window.devicePixelRatio;
    131  const mql = window.matchMedia(`(resolution: ${dpr}dppx)`);
    132 
    133  function listener() {
    134    bootstrap.dispatch(changeDisplayPixelRatio(window.devicePixelRatio));
    135    mql.removeListener(listener);
    136    onDevicePixelRatioChange();
    137  }
    138 
    139  mql.addListener(listener);
    140 }
    141 
    142 /**
    143 * Called by manager.js to add the initial viewport based on the original page.
    144 */
    145 window.addInitialViewport = ({ userContextId }) => {
    146  try {
    147    onDevicePixelRatioChange();
    148    bootstrap.dispatch(changeDisplayPixelRatio(window.devicePixelRatio));
    149    bootstrap.dispatch(addViewport(userContextId));
    150  } catch (e) {
    151    console.error(e);
    152  }
    153 };
    154 
    155 window.getAssociatedDevice = () => {
    156  const { viewports } = bootstrap.store.getState();
    157  if (!viewports.length) {
    158    return null;
    159  }
    160 
    161  return viewports[0].device;
    162 };
    163 
    164 /**
    165 * Called by manager.js when tests want to check the viewport size.
    166 */
    167 window.getViewportSize = () => {
    168  const { viewports } = bootstrap.store.getState();
    169  if (!viewports.length) {
    170    return null;
    171  }
    172 
    173  const { width, height } = viewports[0];
    174  return { width, height };
    175 };
    176 
    177 /**
    178 * Called by manager.js to set viewport size from tests, etc.
    179 */
    180 window.setViewportSize = ({ width, height }) => {
    181  try {
    182    bootstrap.dispatch(resizeViewport(0, width, height));
    183  } catch (e) {
    184    console.error(e);
    185  }
    186 };
    187 
    188 window.clearDeviceAssociation = () => {
    189  try {
    190    bootstrap.dispatch(removeDeviceAssociation(0));
    191  } catch (e) {
    192    console.error(e);
    193  }
    194 };
    195 
    196 /**
    197 * Called by manager.js to access the viewport's browser, either for testing
    198 * purposes or to reload it when touch simulation is enabled.
    199 * A messageManager getter is added on the object to provide an easy access
    200 * to the message manager without pulling the frame loader.
    201 */
    202 window.getViewportBrowser = () => {
    203  const browser = document.querySelector("iframe.browser");
    204  if (browser && !browser.messageManager) {
    205    Object.defineProperty(browser, "messageManager", {
    206      get() {
    207        return this.frameLoader.messageManager;
    208      },
    209      configurable: true,
    210      enumerable: true,
    211    });
    212  }
    213  return browser;
    214 };
    215 
    216 /**
    217 * Called by manager.js to zoom the viewport.
    218 */
    219 window.setViewportZoom = zoom => {
    220  try {
    221    bootstrap.dispatch(zoomViewport(0, zoom));
    222  } catch (e) {
    223    console.error(e);
    224  }
    225 };