tor-browser

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

permissions.js (7335B)


      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 /* import-globals-from pageInfo.js */
      6 
      7 const { SitePermissions } = ChromeUtils.importESModule(
      8  "resource:///modules/SitePermissions.sys.mjs"
      9 );
     10 
     11 var gPermPrincipal;
     12 
     13 // List of ids of permissions to hide.
     14 const EXCLUDE_PERMS = ["open-protocol-handler"];
     15 
     16 // Array of permissionIDs sorted alphabetically by label.
     17 let gPermissions = SitePermissions.listPermissions()
     18  .filter(permissionID => {
     19    if (!SitePermissions.getPermissionLabel(permissionID)) {
     20      return false;
     21    }
     22    return !EXCLUDE_PERMS.includes(permissionID);
     23  })
     24  .sort((a, b) => {
     25    let firstLabel = SitePermissions.getPermissionLabel(a);
     26    let secondLabel = SitePermissions.getPermissionLabel(b);
     27    return firstLabel.localeCompare(secondLabel);
     28  });
     29 
     30 var permissionObserver = {
     31  observe(aSubject, aTopic) {
     32    if (aTopic == "perm-changed") {
     33      var permission = aSubject.QueryInterface(Ci.nsIPermission);
     34      if (
     35        permission.matches(gPermPrincipal, true) &&
     36        gPermissions.includes(permission.type)
     37      ) {
     38        initRow(permission.type);
     39      }
     40    }
     41  },
     42 };
     43 
     44 function getExcludedPermissions() {
     45  return EXCLUDE_PERMS;
     46 }
     47 
     48 function onLoadPermission(uri, principal) {
     49  var permTab = document.getElementById("permTab");
     50  if (SitePermissions.isSupportedPrincipal(principal)) {
     51    gPermPrincipal = principal;
     52    var hostText = document.getElementById("hostText");
     53    hostText.value = uri.displayPrePath;
     54 
     55    for (var i of gPermissions) {
     56      initRow(i);
     57    }
     58    Services.obs.addObserver(permissionObserver, "perm-changed");
     59    window.addEventListener("unload", onUnloadPermission);
     60    permTab.hidden = false;
     61  } else {
     62    permTab.hidden = true;
     63  }
     64 }
     65 
     66 function onUnloadPermission() {
     67  Services.obs.removeObserver(permissionObserver, "perm-changed");
     68 }
     69 
     70 function initRow(aPartId) {
     71  createRow(aPartId);
     72 
     73  var checkbox = document.getElementById(aPartId + "Def");
     74  var command = document.getElementById("cmd_" + aPartId + "Toggle");
     75  var { state, scope } = SitePermissions.getForPrincipal(
     76    gPermPrincipal,
     77    aPartId
     78  );
     79  let defaultState = SitePermissions.getDefault(aPartId);
     80 
     81  // Since cookies preferences have many different possible configuration states
     82  // we don't consider any permission except "no permission" to be default.
     83  if (aPartId == "cookie") {
     84    state = Services.perms.testPermissionFromPrincipal(
     85      gPermPrincipal,
     86      "cookie"
     87    );
     88 
     89    if (state == SitePermissions.UNKNOWN) {
     90      checkbox.checked = true;
     91      command.setAttribute("disabled", "true");
     92      // Don't select any item in the radio group, as we can't
     93      // confidently say that all cookies on the site will be allowed.
     94      let radioGroup = document.getElementById("cookieRadioGroup");
     95      radioGroup.selectedItem = null;
     96    } else {
     97      checkbox.checked = false;
     98      command.removeAttribute("disabled");
     99    }
    100 
    101    setRadioState(aPartId, state);
    102 
    103    checkbox.disabled = Services.prefs.prefIsLocked(
    104      "network.cookie.cookieBehavior"
    105    );
    106 
    107    return;
    108  }
    109 
    110  if (state != defaultState) {
    111    checkbox.checked = false;
    112    command.removeAttribute("disabled");
    113  } else {
    114    checkbox.checked = true;
    115    command.setAttribute("disabled", "true");
    116  }
    117 
    118  if (
    119    [SitePermissions.SCOPE_POLICY, SitePermissions.SCOPE_GLOBAL].includes(scope)
    120  ) {
    121    checkbox.setAttribute("disabled", "true");
    122    command.setAttribute("disabled", "true");
    123  }
    124 
    125  setRadioState(aPartId, state);
    126 
    127  switch (aPartId) {
    128    case "install":
    129      checkbox.disabled = !Services.policies.isAllowed("xpinstall");
    130      break;
    131    case "popup":
    132      checkbox.disabled = Services.prefs.prefIsLocked(
    133        "dom.disable_open_during_load"
    134      );
    135      break;
    136    case "autoplay-media":
    137      checkbox.disabled = Services.prefs.prefIsLocked("media.autoplay.default");
    138      break;
    139    case "geo":
    140    case "desktop-notification":
    141    case "camera":
    142    case "microphone":
    143    case "xr":
    144    case "screen":
    145      checkbox.disabled = Services.prefs.prefIsLocked(
    146        "permissions.default." + aPartId
    147      );
    148      break;
    149  }
    150 }
    151 
    152 function createRow(aPartId) {
    153  let rowId = "perm-" + aPartId + "-row";
    154  if (document.getElementById(rowId)) {
    155    return;
    156  }
    157 
    158  let commandId = "cmd_" + aPartId + "Toggle";
    159  let labelId = "perm-" + aPartId + "-label";
    160  let radiogroupId = aPartId + "RadioGroup";
    161 
    162  let command = document.createXULElement("command");
    163  command.setAttribute("id", commandId);
    164  command.addEventListener("command", () => onRadioClick(aPartId));
    165  document.getElementById("pageInfoCommandSet").appendChild(command);
    166 
    167  let row = document.createXULElement("vbox");
    168  row.setAttribute("id", rowId);
    169  row.setAttribute("class", "permission");
    170 
    171  let label = document.createXULElement("label");
    172  label.setAttribute("id", labelId);
    173  label.setAttribute("control", radiogroupId);
    174  label.setAttribute("value", SitePermissions.getPermissionLabel(aPartId));
    175  label.setAttribute("class", "permissionLabel");
    176  row.appendChild(label);
    177 
    178  let controls = document.createXULElement("hbox");
    179  controls.setAttribute("role", "group");
    180  controls.setAttribute("aria-labelledby", labelId);
    181 
    182  let checkbox = document.createXULElement("checkbox");
    183  checkbox.setAttribute("id", aPartId + "Def");
    184  checkbox.setAttribute("native", true);
    185  document.l10n.setAttributes(checkbox, "permissions-use-default");
    186  checkbox.addEventListener("command", () => onCheckboxClick(aPartId));
    187  controls.appendChild(checkbox);
    188 
    189  let spacer = document.createXULElement("spacer");
    190  spacer.setAttribute("flex", "1");
    191  controls.appendChild(spacer);
    192 
    193  let radiogroup = document.createXULElement("radiogroup");
    194  radiogroup.setAttribute("id", radiogroupId);
    195  radiogroup.setAttribute("orient", "horizontal");
    196  for (let state of SitePermissions.getAvailableStates(aPartId)) {
    197    let radio = document.createXULElement("radio");
    198    radio.setAttribute("id", aPartId + "#" + state);
    199    radio.setAttribute(
    200      "label",
    201      SitePermissions.getMultichoiceStateLabel(aPartId, state)
    202    );
    203    radio.setAttribute("command", commandId);
    204    radiogroup.appendChild(radio);
    205  }
    206  controls.appendChild(radiogroup);
    207 
    208  row.appendChild(controls);
    209 
    210  document.getElementById("permList").appendChild(row);
    211 }
    212 
    213 function onCheckboxClick(aPartId) {
    214  var command = document.getElementById("cmd_" + aPartId + "Toggle");
    215  var checkbox = document.getElementById(aPartId + "Def");
    216  if (checkbox.checked) {
    217    SitePermissions.removeFromPrincipal(gPermPrincipal, aPartId);
    218    command.setAttribute("disabled", "true");
    219  } else {
    220    onRadioClick(aPartId);
    221    command.removeAttribute("disabled");
    222  }
    223 }
    224 
    225 function onRadioClick(aPartId) {
    226  var radioGroup = document.getElementById(aPartId + "RadioGroup");
    227  let permission;
    228  if (radioGroup.selectedItem) {
    229    permission = parseInt(radioGroup.selectedItem.id.split("#")[1]);
    230  } else {
    231    permission = SitePermissions.getDefault(aPartId);
    232  }
    233  SitePermissions.setForPrincipal(gPermPrincipal, aPartId, permission);
    234 }
    235 
    236 function setRadioState(aPartId, aValue) {
    237  var radio = document.getElementById(aPartId + "#" + aValue);
    238  if (radio) {
    239    radio.radioGroup.selectedItem = radio;
    240  }
    241 }