tor-browser

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

App.js (12420B)


      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  createFactory,
      9  PureComponent,
     10 } = require("resource://devtools/client/shared/vendor/react.mjs");
     11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     12 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     13 const {
     14  connect,
     15 } = require("resource://devtools/client/shared/vendor/react-redux.js");
     16 
     17 const Toolbar = createFactory(
     18  require("resource://devtools/client/responsive/components/Toolbar.js")
     19 );
     20 
     21 loader.lazyGetter(this, "DeviceModal", () =>
     22  createFactory(
     23    require("resource://devtools/client/responsive/components/DeviceModal.js")
     24  )
     25 );
     26 
     27 const {
     28  changeNetworkThrottling,
     29 } = require("resource://devtools/client/shared/components/throttling/actions.js");
     30 const {
     31  addCustomDevice,
     32  editCustomDevice,
     33  removeCustomDevice,
     34  updateDeviceDisplayed,
     35  updateDeviceModal,
     36  updatePreferredDevices,
     37 } = require("resource://devtools/client/responsive/actions/devices.js");
     38 const {
     39  takeScreenshot,
     40 } = require("resource://devtools/client/responsive/actions/screenshot.js");
     41 const {
     42  changeUserAgent,
     43  toggleLeftAlignment,
     44  toggleReloadOnTouchSimulation,
     45  toggleReloadOnUserAgent,
     46  toggleTouchSimulation,
     47  toggleUserAgentInput,
     48 } = require("resource://devtools/client/responsive/actions/ui.js");
     49 const {
     50  changeDevice,
     51  changePixelRatio,
     52  changeViewportAngle,
     53  removeDeviceAssociation,
     54  resizeViewport,
     55  rotateViewport,
     56 } = require("resource://devtools/client/responsive/actions/viewports.js");
     57 const {
     58  getOrientation,
     59 } = require("resource://devtools/client/responsive/utils/orientation.js");
     60 
     61 const Types = require("resource://devtools/client/responsive/types.js");
     62 
     63 class App extends PureComponent {
     64  static get propTypes() {
     65    return {
     66      devices: PropTypes.shape(Types.devices).isRequired,
     67      dispatch: PropTypes.func.isRequired,
     68      leftAlignmentEnabled: PropTypes.bool.isRequired,
     69      networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
     70      screenshot: PropTypes.shape(Types.screenshot).isRequired,
     71      viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
     72    };
     73  }
     74 
     75  constructor(props) {
     76    super(props);
     77 
     78    this.onAddCustomDevice = this.onAddCustomDevice.bind(this);
     79    this.onChangeDevice = this.onChangeDevice.bind(this);
     80    this.onChangeNetworkThrottling = this.onChangeNetworkThrottling.bind(this);
     81    this.onChangePixelRatio = this.onChangePixelRatio.bind(this);
     82    this.onChangeTouchSimulation = this.onChangeTouchSimulation.bind(this);
     83    this.onChangeUserAgent = this.onChangeUserAgent.bind(this);
     84    this.onChangeViewportOrientation =
     85      this.onChangeViewportOrientation.bind(this);
     86    this.onDeviceListUpdate = this.onDeviceListUpdate.bind(this);
     87    this.onEditCustomDevice = this.onEditCustomDevice.bind(this);
     88    this.onExit = this.onExit.bind(this);
     89    this.onRemoveCustomDevice = this.onRemoveCustomDevice.bind(this);
     90    this.onRemoveDeviceAssociation = this.onRemoveDeviceAssociation.bind(this);
     91    this.doResizeViewport = this.doResizeViewport.bind(this);
     92    this.onRotateViewport = this.onRotateViewport.bind(this);
     93    this.onScreenshot = this.onScreenshot.bind(this);
     94    this.onToggleLeftAlignment = this.onToggleLeftAlignment.bind(this);
     95    this.onToggleReloadOnTouchSimulation =
     96      this.onToggleReloadOnTouchSimulation.bind(this);
     97    this.onToggleReloadOnUserAgent = this.onToggleReloadOnUserAgent.bind(this);
     98    this.onToggleUserAgentInput = this.onToggleUserAgentInput.bind(this);
     99    this.onUpdateDeviceDisplayed = this.onUpdateDeviceDisplayed.bind(this);
    100    this.onUpdateDeviceModal = this.onUpdateDeviceModal.bind(this);
    101  }
    102 
    103  onAddCustomDevice(device) {
    104    this.props.dispatch(addCustomDevice(device));
    105  }
    106 
    107  onChangeDevice(id, device, deviceType) {
    108    // Resize the viewport first.
    109    this.doResizeViewport(id, device.width, device.height);
    110 
    111    // TODO: Bug 1332754: Move messaging and logic into the action creator so that the
    112    // message is sent from the action creator and device property changes are sent from
    113    // there instead of this function.
    114    window.postMessage(
    115      {
    116        type: "change-device",
    117        device,
    118        viewport: device,
    119      },
    120      "*"
    121    );
    122 
    123    const orientation = getOrientation(device, device);
    124 
    125    this.props.dispatch(changeViewportAngle(0, orientation.angle));
    126    this.props.dispatch(changeDevice(id, device.name, deviceType));
    127    this.props.dispatch(changePixelRatio(id, device.pixelRatio));
    128    this.props.dispatch(changeUserAgent(device.userAgent));
    129    this.props.dispatch(toggleTouchSimulation(device.touch));
    130  }
    131 
    132  onChangeNetworkThrottling(enabled, profile) {
    133    window.postMessage(
    134      {
    135        type: "change-network-throttling",
    136        enabled,
    137        profile,
    138      },
    139      "*"
    140    );
    141    this.props.dispatch(changeNetworkThrottling(enabled, profile));
    142  }
    143 
    144  onChangePixelRatio(pixelRatio) {
    145    window.postMessage(
    146      {
    147        type: "change-pixel-ratio",
    148        pixelRatio,
    149      },
    150      "*"
    151    );
    152    this.props.dispatch(changePixelRatio(0, pixelRatio));
    153  }
    154 
    155  onChangeTouchSimulation(enabled) {
    156    window.postMessage(
    157      {
    158        type: "change-touch-simulation",
    159        enabled,
    160      },
    161      "*"
    162    );
    163    this.props.dispatch(toggleTouchSimulation(enabled));
    164  }
    165 
    166  onChangeUserAgent(userAgent) {
    167    window.postMessage(
    168      {
    169        type: "change-user-agent",
    170        userAgent,
    171      },
    172      "*"
    173    );
    174    this.props.dispatch(changeUserAgent(userAgent));
    175  }
    176 
    177  onChangeViewportOrientation(id, type, angle) {
    178    window.postMessage(
    179      {
    180        type: "viewport-orientation-change",
    181        orientationType: type,
    182        angle,
    183      },
    184      "*"
    185    );
    186 
    187    this.props.dispatch(changeViewportAngle(id, angle));
    188  }
    189 
    190  onDeviceListUpdate(devices) {
    191    updatePreferredDevices(devices);
    192  }
    193 
    194  onEditCustomDevice(oldDevice, newDevice) {
    195    // If the edited device is currently selected, then update its original association
    196    // and reset UI state.
    197    let viewport = this.props.viewports.find(
    198      ({ device }) => device === oldDevice.name
    199    );
    200 
    201    if (viewport) {
    202      viewport = {
    203        ...viewport,
    204        device: newDevice.name,
    205        deviceType: "custom",
    206        height: newDevice.height,
    207        width: newDevice.width,
    208        pixelRatio: newDevice.pixelRatio,
    209        touch: newDevice.touch,
    210        userAgent: newDevice.userAgent,
    211      };
    212    }
    213 
    214    this.props.dispatch(editCustomDevice(viewport, oldDevice, newDevice));
    215  }
    216 
    217  onExit() {
    218    window.postMessage({ type: "exit" }, "*");
    219  }
    220 
    221  onRemoveCustomDevice(device) {
    222    // If the custom device is currently selected on any of the viewports,
    223    // remove the device association and reset all the ui state.
    224    for (const viewport of this.props.viewports) {
    225      if (viewport.device === device.name) {
    226        this.onRemoveDeviceAssociation(viewport.id, { resetProfile: true });
    227      }
    228    }
    229 
    230    this.props.dispatch(removeCustomDevice(device));
    231  }
    232 
    233  onRemoveDeviceAssociation(id, { resetProfile }) {
    234    // TODO: Bug 1332754: Move messaging and logic into the action creator so that device
    235    // property changes are sent from there instead of this function.
    236    this.props.dispatch(removeDeviceAssociation(id, { resetProfile }));
    237    if (resetProfile) {
    238      this.props.dispatch(toggleTouchSimulation(false));
    239      this.props.dispatch(changePixelRatio(id, 0));
    240      this.props.dispatch(changeUserAgent(""));
    241    }
    242  }
    243 
    244  doResizeViewport(id, width, height) {
    245    // This is the setter function that we pass to Toolbar and Viewports
    246    // so they can modify the viewport.
    247    window.postMessage(
    248      {
    249        type: "viewport-resize",
    250        width,
    251        height,
    252      },
    253      "*"
    254    );
    255    this.props.dispatch(resizeViewport(id, width, height));
    256  }
    257 
    258  /**
    259   * Dispatches the rotateViewport action creator. This utilized by the RDM toolbar as
    260   * a prop.
    261   *
    262   * @param {number} id
    263   *        The viewport ID.
    264   */
    265  onRotateViewport(id) {
    266    let currentDevice;
    267    const viewport = this.props.viewports[id];
    268 
    269    for (const type of this.props.devices.types) {
    270      for (const device of this.props.devices[type]) {
    271        if (viewport.device === device.name) {
    272          currentDevice = device;
    273        }
    274      }
    275    }
    276 
    277    // If no device is selected, then assume the selected device's primary orientation is
    278    // opposite of the viewport orientation.
    279    if (!currentDevice) {
    280      currentDevice = {
    281        height: viewport.width,
    282        width: viewport.height,
    283      };
    284    }
    285 
    286    const currentAngle = Services.prefs.getIntPref(
    287      "devtools.responsive.viewport.angle"
    288    );
    289    const angleToRotateTo = currentAngle === 90 ? 0 : 90;
    290    const { type, angle } = getOrientation(
    291      currentDevice,
    292      viewport,
    293      angleToRotateTo
    294    );
    295 
    296    this.onChangeViewportOrientation(id, type, angle, true);
    297    this.props.dispatch(rotateViewport(id));
    298 
    299    window.postMessage(
    300      {
    301        type: "viewport-resize",
    302        height: viewport.width,
    303        width: viewport.height,
    304      },
    305      "*"
    306    );
    307  }
    308 
    309  onScreenshot() {
    310    this.props.dispatch(takeScreenshot());
    311  }
    312 
    313  onToggleLeftAlignment() {
    314    this.props.dispatch(toggleLeftAlignment());
    315 
    316    window.postMessage(
    317      {
    318        type: "toggle-left-alignment",
    319        leftAlignmentEnabled: this.props.leftAlignmentEnabled,
    320      },
    321      "*"
    322    );
    323  }
    324 
    325  onToggleReloadOnTouchSimulation() {
    326    this.props.dispatch(toggleReloadOnTouchSimulation());
    327  }
    328 
    329  onToggleReloadOnUserAgent() {
    330    this.props.dispatch(toggleReloadOnUserAgent());
    331  }
    332 
    333  onToggleUserAgentInput() {
    334    this.props.dispatch(toggleUserAgentInput());
    335  }
    336 
    337  onUpdateDeviceDisplayed(device, deviceType, displayed) {
    338    this.props.dispatch(updateDeviceDisplayed(device, deviceType, displayed));
    339  }
    340 
    341  onUpdateDeviceModal(isOpen, modalOpenedFromViewport) {
    342    this.props.dispatch(updateDeviceModal(isOpen, modalOpenedFromViewport));
    343    window.postMessage({ type: "update-device-modal", isOpen }, "*");
    344  }
    345 
    346  render() {
    347    const { devices, networkThrottling, screenshot, viewports } = this.props;
    348 
    349    const {
    350      onAddCustomDevice,
    351      onChangeDevice,
    352      onChangeNetworkThrottling,
    353      onChangePixelRatio,
    354      onChangeTouchSimulation,
    355      onChangeUserAgent,
    356      onDeviceListUpdate,
    357      onEditCustomDevice,
    358      onExit,
    359      onRemoveCustomDevice,
    360      onRemoveDeviceAssociation,
    361      doResizeViewport,
    362      onRotateViewport,
    363      onScreenshot,
    364      onToggleLeftAlignment,
    365      onToggleReloadOnTouchSimulation,
    366      onToggleReloadOnUserAgent,
    367      onToggleUserAgentInput,
    368      onUpdateDeviceDisplayed,
    369      onUpdateDeviceModal,
    370    } = this;
    371 
    372    if (!viewports.length) {
    373      return null;
    374    }
    375 
    376    const selectedDevice = viewports[0].device;
    377    const selectedPixelRatio = viewports[0].pixelRatio;
    378 
    379    let deviceAdderViewportTemplate = {};
    380    if (devices.modalOpenedFromViewport !== null) {
    381      deviceAdderViewportTemplate = viewports[devices.modalOpenedFromViewport];
    382    }
    383 
    384    return dom.div(
    385      { id: "app" },
    386      Toolbar({
    387        devices,
    388        networkThrottling,
    389        screenshot,
    390        selectedDevice,
    391        selectedPixelRatio,
    392        viewport: viewports[0],
    393        onChangeDevice,
    394        onChangeNetworkThrottling,
    395        onChangePixelRatio,
    396        onChangeTouchSimulation,
    397        onChangeUserAgent,
    398        onExit,
    399        onRemoveDeviceAssociation,
    400        doResizeViewport,
    401        onRotateViewport,
    402        onScreenshot,
    403        onToggleLeftAlignment,
    404        onToggleReloadOnTouchSimulation,
    405        onToggleReloadOnUserAgent,
    406        onToggleUserAgentInput,
    407        onUpdateDeviceModal,
    408      }),
    409      devices.isModalOpen
    410        ? DeviceModal({
    411            deviceAdderViewportTemplate,
    412            devices,
    413            onAddCustomDevice,
    414            onDeviceListUpdate,
    415            onEditCustomDevice,
    416            onRemoveCustomDevice,
    417            onUpdateDeviceDisplayed,
    418            onUpdateDeviceModal,
    419          })
    420        : null
    421    );
    422  }
    423 }
    424 
    425 const mapStateToProps = state => {
    426  return {
    427    ...state,
    428    leftAlignmentEnabled: state.ui.leftAlignmentEnabled,
    429  };
    430 };
    431 
    432 module.exports = connect(mapStateToProps)(App);