tor-browser

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

devices.js (6773B)


      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 asyncStorage = require("resource://devtools/shared/async-storage.js");
      8 
      9 const {
     10  ADD_DEVICE,
     11  ADD_DEVICE_TYPE,
     12  EDIT_DEVICE,
     13  LOAD_DEVICE_LIST_START,
     14  LOAD_DEVICE_LIST_ERROR,
     15  LOAD_DEVICE_LIST_END,
     16  REMOVE_DEVICE,
     17  UPDATE_DEVICE_DISPLAYED,
     18  UPDATE_DEVICE_MODAL,
     19 } = require("resource://devtools/client/responsive/actions/index.js");
     20 const {
     21  post,
     22 } = require("resource://devtools/client/responsive/utils/message.js");
     23 
     24 const {
     25  addDevice,
     26  editDevice,
     27  getDevices,
     28  removeDevice,
     29 } = require("resource://devtools/client/shared/devices.js");
     30 const {
     31  changeUserAgent,
     32  toggleTouchSimulation,
     33 } = require("resource://devtools/client/responsive/actions/ui.js");
     34 const {
     35  changeDevice,
     36  changePixelRatio,
     37  changeViewportAngle,
     38 } = require("resource://devtools/client/responsive/actions/viewports.js");
     39 
     40 const DISPLAYED_DEVICES_PREF = "devtools.responsive.html.displayedDeviceList";
     41 
     42 /**
     43 * Returns an object containing the user preference of displayed devices.
     44 *
     45 * @return {object} containing two Sets:
     46 * - added: Names of the devices that were explicitly enabled by the user
     47 * - removed: Names of the devices that were explicitly removed by the user
     48 */
     49 function loadPreferredDevices() {
     50  const preferredDevices = {
     51    added: new Set(),
     52    removed: new Set(),
     53  };
     54 
     55  if (Services.prefs.prefHasUserValue(DISPLAYED_DEVICES_PREF)) {
     56    try {
     57      let savedData = Services.prefs.getStringPref(DISPLAYED_DEVICES_PREF);
     58      savedData = JSON.parse(savedData);
     59      if (savedData.added && savedData.removed) {
     60        preferredDevices.added = new Set(savedData.added);
     61        preferredDevices.removed = new Set(savedData.removed);
     62      }
     63    } catch (e) {
     64      console.error(e);
     65    }
     66  }
     67 
     68  return preferredDevices;
     69 }
     70 
     71 /**
     72 * Update the displayed device list preference with the given device list.
     73 *
     74 * @param {object} containing two Sets:
     75 * - added: Names of the devices that were explicitly enabled by the user
     76 * - removed: Names of the devices that were explicitly removed by the user
     77 */
     78 function updatePreferredDevices(devices) {
     79  let devicesToSave = {
     80    added: Array.from(devices.added),
     81    removed: Array.from(devices.removed),
     82  };
     83  devicesToSave = JSON.stringify(devicesToSave);
     84  Services.prefs.setStringPref(DISPLAYED_DEVICES_PREF, devicesToSave);
     85 }
     86 
     87 module.exports = {
     88  // This function is only exported for testing purposes
     89  _loadPreferredDevices: loadPreferredDevices,
     90 
     91  updatePreferredDevices,
     92 
     93  addCustomDevice(device) {
     94    return async function ({ dispatch }) {
     95      // Add custom device to device storage
     96      await addDevice(device, "custom");
     97      dispatch({
     98        type: ADD_DEVICE,
     99        device,
    100        deviceType: "custom",
    101      });
    102    };
    103  },
    104 
    105  addDevice(device, deviceType) {
    106    return {
    107      type: ADD_DEVICE,
    108      device,
    109      deviceType,
    110    };
    111  },
    112 
    113  addDeviceType(deviceType) {
    114    return {
    115      type: ADD_DEVICE_TYPE,
    116      deviceType,
    117    };
    118  },
    119 
    120  editCustomDevice(viewport, oldDevice, newDevice) {
    121    return async function ({ dispatch }) {
    122      // Edit custom device in storage
    123      await editDevice(oldDevice, newDevice, "custom");
    124      // Notify the window that the device should be updated in the device selector.
    125      post(window, {
    126        type: "change-device",
    127        device: newDevice,
    128        viewport,
    129      });
    130 
    131      // Update UI if the device is selected.
    132      if (viewport) {
    133        dispatch(changeUserAgent(newDevice.userAgent));
    134        dispatch(toggleTouchSimulation(newDevice.touch));
    135      }
    136 
    137      dispatch({
    138        type: EDIT_DEVICE,
    139        deviceType: "custom",
    140        viewport,
    141        oldDevice,
    142        newDevice,
    143      });
    144    };
    145  },
    146 
    147  removeCustomDevice(device) {
    148    return async function ({ dispatch }) {
    149      // Remove custom device from device storage
    150      await removeDevice(device, "custom");
    151      dispatch({
    152        type: REMOVE_DEVICE,
    153        device,
    154        deviceType: "custom",
    155      });
    156    };
    157  },
    158 
    159  updateDeviceDisplayed(device, deviceType, displayed) {
    160    return {
    161      type: UPDATE_DEVICE_DISPLAYED,
    162      device,
    163      deviceType,
    164      displayed,
    165    };
    166  },
    167 
    168  loadDevices() {
    169    return async function ({ dispatch }) {
    170      dispatch({ type: LOAD_DEVICE_LIST_START });
    171      const preferredDevices = loadPreferredDevices();
    172      let deviceByTypes;
    173 
    174      try {
    175        deviceByTypes = await getDevices();
    176      } catch (e) {
    177        console.error("Could not load device list: " + e);
    178        dispatch({ type: LOAD_DEVICE_LIST_ERROR });
    179        return;
    180      }
    181 
    182      for (const [type, devices] of deviceByTypes.entries()) {
    183        dispatch(module.exports.addDeviceType(type));
    184        for (const device of devices) {
    185          if (device.os == "fxos") {
    186            continue;
    187          }
    188 
    189          const newDevice = Object.assign({}, device, {
    190            displayed:
    191              preferredDevices.added.has(device.name) ||
    192              (device.featured && !preferredDevices.removed.has(device.name)),
    193          });
    194 
    195          dispatch(module.exports.addDevice(newDevice, type));
    196        }
    197      }
    198 
    199      // Add an empty "custom" type if it doesn't exist in device storage
    200      if (!deviceByTypes.has("custom")) {
    201        dispatch(module.exports.addDeviceType("custom"));
    202      }
    203 
    204      dispatch({ type: LOAD_DEVICE_LIST_END });
    205    };
    206  },
    207 
    208  restoreDeviceState() {
    209    return async function ({ dispatch, getState }) {
    210      const deviceState = await asyncStorage.getItem(
    211        "devtools.responsive.deviceState"
    212      );
    213      if (!deviceState) {
    214        return;
    215      }
    216 
    217      const { id, device: deviceName, deviceType } = deviceState;
    218      const devices = getState().devices;
    219 
    220      if (!devices.types.includes(deviceType)) {
    221        // Can't find matching device type.
    222        return;
    223      }
    224 
    225      const device = devices[deviceType].find(d => d.name === deviceName);
    226      if (!device) {
    227        // Can't find device with the same device name.
    228        return;
    229      }
    230 
    231      const viewport = getState().viewports[0];
    232 
    233      post(window, {
    234        type: "change-device",
    235        device,
    236        viewport,
    237      });
    238 
    239      dispatch(changeDevice(id, device.name, deviceType));
    240      dispatch(changeViewportAngle(id, viewport.angle));
    241      dispatch(changePixelRatio(id, device.pixelRatio));
    242      dispatch(changeUserAgent(device.userAgent));
    243      dispatch(toggleTouchSimulation(device.touch));
    244    };
    245  },
    246 
    247  updateDeviceModal(isOpen, modalOpenedFromViewport = null) {
    248    return {
    249      type: UPDATE_DEVICE_MODAL,
    250      isOpen,
    251      modalOpenedFromViewport,
    252    };
    253  },
    254 };