Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Policies.sys.mjs   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";

import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";

const lazy = {};

XPCOMUtils.defineLazyServiceGetters(lazy, {
  gCertDB: ["@mozilla.org/security/x509certdb;1", "nsIX509CertDB"],
  gExternalProtocolService: [
    "@mozilla.org/uriloader/external-protocol-service;1",
    "nsIExternalProtocolService",
  ],
  gHandlerService: [
    "@mozilla.org/uriloader/handler-service;1",
    "nsIHandlerService",
  ],
  gMIMEService: ["@mozilla.org/mime;1", "nsIMIMEService"],
});

ChromeUtils.defineESModuleGetters(lazy, {
  AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
  BookmarksPolicies: "resource:///modules/policies/BookmarksPolicies.sys.mjs",
  CustomizableUI: "resource:///modules/CustomizableUI.sys.mjs",
  FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
  ProxyPolicies: "resource:///modules/policies/ProxyPolicies.sys.mjs",
  UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
  WebsiteFilter: "resource:///modules/policies/WebsiteFilter.sys.mjs",
});

const PREF_LOGLEVEL = "browser.policies.loglevel";
const BROWSER_DOCUMENT_URL = AppConstants.BROWSER_CHROME_URL;
const ABOUT_CONTRACT = "@mozilla.org/network/protocol/about;1?what=";

const isXpcshell = Services.env.exists("XPCSHELL_TEST_PROFILE_DIR");

ChromeUtils.defineLazyGetter(lazy, "log", () => {
  let { ConsoleAPI } = ChromeUtils.importESModule(
    "resource://gre/modules/Console.sys.mjs"
  );
  return new ConsoleAPI({
    prefix: "Policies",
    // tip: set maxLogLevel to "debug" and use log.debug() to create detailed
    // messages during development. See LOG_LEVELS in Console.sys.mjs for details.
    maxLogLevel: "error",
    maxLogLevelPref: PREF_LOGLEVEL,
  });
});

/*
 * ============================
 * = POLICIES IMPLEMENTATIONS =
 * ============================
 *
 * The Policies object below is where the implementation for each policy
 * happens. An object for each policy should be defined, containing
 * callback functions that will be called by the engine.
 *
 * See the _callbacks object in EnterprisePolicies.js for the list of
 * possible callbacks and an explanation of each.
 *
 * Each callback will be called with two parameters:
 * - manager
 *   This is the EnterprisePoliciesManager singleton object from
 *   EnterprisePolicies.js
 *
 * - param
 *   The parameter defined for this policy in policies-schema.json.
 *   It will be different for each policy. It could be a boolean,
 *   a string, an array or a complex object. All parameters have
 *   been validated according to the schema, and no unknown
 *   properties will be present on them.
 *
 * The callbacks will be bound to their parent policy object.
 */
export var Policies = {
  // Used for cleaning up policies.
  // Use the same timing that you used for setting up the policy.
  _cleanup: {
    onBeforeAddons() {
      if (Cu.isInAutomation || isXpcshell) {
        console.log("_cleanup from onBeforeAddons");
        clearBlockedAboutPages();
      }
    },
    onProfileAfterChange() {
      if (Cu.isInAutomation || isXpcshell) {
        console.log("_cleanup from onProfileAfterChange");
      }
    },
    onBeforeUIStartup() {
      if (Cu.isInAutomation || isXpcshell) {
        console.log("_cleanup from onBeforeUIStartup");
      }
    },
    onAllWindowsRestored() {
      if (Cu.isInAutomation || isXpcshell) {
        console.log("_cleanup from onAllWindowsRestored");
      }
    },
  },

  "3rdparty": {
    onBeforeAddons(manager, param) {
      manager.setExtensionPolicies(param.Extensions);
    },
  },

  AllowedDomainsForApps: {
    onBeforeAddons(manager, param) {
      Services.obs.addObserver(function (subject) {
        let channel = subject.QueryInterface(Ci.nsIHttpChannel);
        if (channel.URI.host.endsWith(".google.com")) {
          channel.setRequestHeader("X-GoogApps-Allowed-Domains", param, true);
        }
      }, "http-on-modify-request");
    },
  },

  AllowFileSelectionDialogs: {
    onBeforeUIStartup(manager, param) {
      if (!param) {
        setAndLockPref("widget.disable_file_pickers", true);
        setAndLockPref("browser.download.useDownloadDir", true);
        manager.disallowFeature("filepickers");
      }
    },
  },

  AppAutoUpdate: {
    onBeforeUIStartup(manager, param) {
      // Logic feels a bit reversed here, but it's correct. If AppAutoUpdate is
      // true, we disallow turning off auto updating, and visa versa.
      if (param) {
        manager.disallowFeature("app-auto-updates-off");
      } else {
        manager.disallowFeature("app-auto-updates-on");
      }
    },
  },

  AppUpdatePin: {
    validate(param) {
      // This is the version when pinning was introduced. Attempting to set a
      // pin before this will not work, because Balrog's pinning table will
      // never have the necessary entry.
      const earliestPinMajorVersion = 102;
      const earliestPinMinorVersion = 0;

      let pinParts = param.split(".");

      if (pinParts.length < 2) {
        lazy.log.error("AppUpdatePin has too few dots.");
        return false;
      }
      if (pinParts.length > 3) {
        lazy.log.error("AppUpdatePin has too many dots.");
        return false;
      }

      const trailingPinPart = pinParts.pop();
      if (trailingPinPart != "") {
        lazy.log.error("AppUpdatePin does not end with a trailing dot.");
        return false;
      }

      const pinMajorVersionStr = pinParts.shift();
      if (!pinMajorVersionStr.length) {
        lazy.log.error("AppUpdatePin's major version is empty.");
        return false;
      }
      if (!/^\d+$/.test(pinMajorVersionStr)) {
        lazy.log.error(
          "AppUpdatePin's major version contains a non-numeric character."
        );
        return false;
      }
      if (/^0/.test(pinMajorVersionStr)) {
        lazy.log.error("AppUpdatePin's major version contains a leading 0.");
        return false;
      }
      const pinMajorVersionInt = parseInt(pinMajorVersionStr, 10);
      if (isNaN(pinMajorVersionInt)) {
        lazy.log.error(
          "AppUpdatePin's major version could not be parsed to an integer."
        );
        return false;
      }
      if (pinMajorVersionInt < earliestPinMajorVersion) {
        lazy.log.error(
          `AppUpdatePin must not be earlier than '${earliestPinMajorVersion}.${earliestPinMinorVersion}.'.`
        );
        return false;
      }

      if (pinParts.length) {
        const pinMinorVersionStr = pinParts.shift();
        if (!pinMinorVersionStr.length) {
          lazy.log.error("AppUpdatePin's minor version is empty.");
          return false;
        }
        if (!/^\d+$/.test(pinMinorVersionStr)) {
          lazy.log.error(
            "AppUpdatePin's minor version contains a non-numeric character."
          );
          return false;
        }
        if (/^0\d/.test(pinMinorVersionStr)) {
          lazy.log.error("AppUpdatePin's minor version contains a leading 0.");
          return false;
        }
        const pinMinorVersionInt = parseInt(pinMinorVersionStr, 10);
        if (isNaN(pinMinorVersionInt)) {
          lazy.log.error(
            "AppUpdatePin's minor version could not be parsed to an integer."
          );
          return false;
        }
        if (
          pinMajorVersionInt == earliestPinMajorVersion &&
          pinMinorVersionInt < earliestPinMinorVersion
        ) {
          lazy.log.error(
            `AppUpdatePin must not be earlier than '${earliestPinMajorVersion}.${earliestPinMinorVersion}.'.`
          );
          return false;
        }
      }

      return true;
    },
    // No additional implementation needed here. UpdateService.sys.mjs will check
    // for this policy directly when determining the update URL.
  },

  AppUpdateURL: {
    // No implementation needed here. UpdateService.sys.mjs will check for this
    // policy directly when determining the update URL.
  },

  Authentication: {
    onBeforeAddons(manager, param) {
      // When Authentication was originally implemented, it was always
      // locked, so it defaults to locked.
      let locked = true;
      if ("Locked" in param) {
        locked = param.Locked;
      }
      if ("SPNEGO" in param) {
        PoliciesUtils.setDefaultPref(
          "network.negotiate-auth.trusted-uris",
          param.SPNEGO.join(", "),
          locked
        );
      }
      if ("Delegated" in param) {
        PoliciesUtils.setDefaultPref(
          "network.negotiate-auth.delegation-uris",
          param.Delegated.join(", "),
          locked
        );
      }
      if ("NTLM" in param) {
        PoliciesUtils.setDefaultPref(
          "network.automatic-ntlm-auth.trusted-uris",
          param.NTLM.join(", "),
          locked
        );
      }
      if ("AllowNonFQDN" in param) {
        if ("NTLM" in param.AllowNonFQDN) {
          PoliciesUtils.setDefaultPref(
            "network.automatic-ntlm-auth.allow-non-fqdn",
            param.AllowNonFQDN.NTLM,
            locked
          );
        }
        if ("SPNEGO" in param.AllowNonFQDN) {
          PoliciesUtils.setDefaultPref(
            "network.negotiate-auth.allow-non-fqdn",
            param.AllowNonFQDN.SPNEGO,
            locked
          );
        }
      }
      if ("AllowProxies" in param) {
        if ("NTLM" in param.AllowProxies) {
          PoliciesUtils.setDefaultPref(
            "network.automatic-ntlm-auth.allow-proxies",
            param.AllowProxies.NTLM,
            locked
          );
        }
        if ("SPNEGO" in param.AllowProxies) {
          PoliciesUtils.setDefaultPref(
            "network.negotiate-auth.allow-proxies",
            param.AllowProxies.SPNEGO,
            locked
          );
        }
      }
      if ("PrivateBrowsing" in param) {
        PoliciesUtils.setDefaultPref(
          "network.auth.private-browsing-sso",
          param.PrivateBrowsing,
          locked
        );
      }
    },
  },

  AutofillAddressEnabled: {
    onBeforeAddons(manager, param) {
      setAndLockPref("extensions.formautofill.addresses.enabled", param);
    },
  },

  AutofillCreditCardEnabled: {
    onBeforeAddons(manager, param) {
      setAndLockPref("extensions.formautofill.creditCards.enabled", param);
    },
  },

  AutoLaunchProtocolsFromOrigins: {
    onBeforeAddons(manager, param) {
      for (let info of param) {
        addAllowDenyPermissions(
          `open-protocol-handler^${info.protocol}`,
          info.allowed_origins
        );
      }
    },
  },

  BackgroundAppUpdate: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("app-background-update-off");
      } else {
        manager.disallowFeature("app-background-update-on");
      }
    },
  },

  BlockAboutAddons: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        blockAboutPage(manager, "about:addons", true);
      }
    },
  },

  BlockAboutConfig: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        blockAboutPage(manager, "about:config");
        setAndLockPref("devtools.chrome.enabled", false);
      }
    },
  },

  BlockAboutProfiles: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        blockAboutPage(manager, "about:profiles");
      }
    },
  },

  BlockAboutSupport: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        blockAboutPage(manager, "about:support");
        manager.disallowFeature("aboutSupport");
      }
    },
  },

  Bookmarks: {
    onAllWindowsRestored(manager, param) {
      lazy.BookmarksPolicies.processBookmarks(param);
    },
  },

  CaptivePortal: {
    onBeforeAddons(manager, param) {
      setAndLockPref("network.captive-portal-service.enabled", param);
    },
  },

  Certificates: {
    onBeforeAddons(manager, param) {
      if ("ImportEnterpriseRoots" in param) {
        setAndLockPref(
          "security.enterprise_roots.enabled",
          param.ImportEnterpriseRoots
        );
      }
      if ("Install" in param) {
        (async () => {
          let dirs = [];
          let platform = AppConstants.platform;
          if (platform == "win") {
            dirs = [
              // Ugly, but there is no official way to get %USERNAME\AppData\Roaming\Mozilla.
              Services.dirsvc.get("XREUSysExt", Ci.nsIFile).parent,
              // Even more ugly, but there is no official way to get %USERNAME\AppData\Local\Mozilla.
              Services.dirsvc.get("DefProfLRt", Ci.nsIFile).parent.parent,
            ];
          } else if (platform == "macosx" || platform == "linux") {
            dirs = [
              // These two keys are named wrong. They return the Mozilla directory.
              Services.dirsvc.get("XREUserNativeManifests", Ci.nsIFile),
              Services.dirsvc.get("XRESysNativeManifests", Ci.nsIFile),
            ];
          }
          dirs.unshift(Services.dirsvc.get("XREAppDist", Ci.nsIFile));
          for (let certfilename of param.Install) {
            let certfile;
            try {
              certfile = Cc["@mozilla.org/file/local;1"].createInstance(
                Ci.nsIFile
              );
              certfile.initWithPath(certfilename);
            } catch (e) {
              for (let dir of dirs) {
                certfile = dir.clone();
                certfile.append(
                  platform == "linux" ? "certificates" : "Certificates"
                );
                certfile.append(certfilename);
                if (certfile.exists()) {
                  break;
                }
              }
            }
            let file;
            try {
              file = await File.createFromNsIFile(certfile);
            } catch (e) {
              lazy.log.error(`Unable to find certificate - ${certfilename}`);
              continue;
            }
            let reader = new FileReader();
            reader.onloadend = function () {
              if (reader.readyState != reader.DONE) {
                lazy.log.error(`Unable to read certificate - ${certfile.path}`);
                return;
              }
              let certFile = reader.result;
              let certFileArray = [];
              for (let i = 0; i < certFile.length; i++) {
                certFileArray.push(certFile.charCodeAt(i));
              }
              let cert;
              try {
                cert = lazy.gCertDB.constructX509(certFileArray);
              } catch (e) {
                lazy.log.debug(
                  `constructX509 failed with error '${e}' - trying constructX509FromBase64.`
                );
                try {
                  // It might be PEM instead of DER.
                  cert = lazy.gCertDB.constructX509FromBase64(
                    pemToBase64(certFile)
                  );
                } catch (ex) {
                  lazy.log.error(
                    `Unable to add certificate - ${certfile.path}`,
                    ex
                  );
                }
              }
              if (cert) {
                if (
                  lazy.gCertDB.isCertTrusted(
                    cert,
                    Ci.nsIX509Cert.CA_CERT,
                    Ci.nsIX509CertDB.TRUSTED_SSL
                  )
                ) {
                  // Certificate is already installed.
                  return;
                }
                try {
                  lazy.gCertDB.addCert(certFile, "CT,CT,");
                } catch (e) {
                  // It might be PEM instead of DER.
                  lazy.gCertDB.addCertFromBase64(
                    pemToBase64(certFile),
                    "CT,CT,"
                  );
                }
              }
            };
            reader.readAsBinaryString(file);
          }
        })();
      }
    },
  },

  Containers: {
    // Queried directly by ContextualIdentityService.sys.mjs
  },

  ContentAnalysis: {
    onBeforeAddons(manager, param) {
      if ("PipePathName" in param) {
        setAndLockPref(
          "browser.contentanalysis.pipe_path_name",
          param.PipePathName
        );
      }
      if ("AgentTimeout" in param) {
        if (!Number.isInteger(param.AgentTimeout)) {
          lazy.log.error(
            `Non-integer value for AgentTimeout: ${param.AgentTimeout}`
          );
        } else {
          setAndLockPref(
            "browser.contentanalysis.agent_timeout",
            param.AgentTimeout
          );
        }
      }
      if ("AllowUrlRegexList" in param) {
        setAndLockPref(
          "browser.contentanalysis.allow_url_regex_list",
          param.AllowUrlRegexList
        );
      }
      if ("DenyUrlRegexList" in param) {
        setAndLockPref(
          "browser.contentanalysis.deny_url_regex_list",
          param.DenyUrlRegexList
        );
      }
      if ("AgentName" in param) {
        setAndLockPref("browser.contentanalysis.agent_name", param.AgentName);
      }
      if ("ClientSignature" in param) {
        setAndLockPref(
          "browser.contentanalysis.client_signature",
          param.ClientSignature
        );
      }
      if ("DefaultResult" in param) {
        if (
          !Number.isInteger(param.DefaultResult) ||
          param.DefaultResult < 0 ||
          param.DefaultResult > 2
        ) {
          lazy.log.error(
            `Non-integer or out of range value for DefaultResult: ${param.DefaultResult}`
          );
        } else {
          setAndLockPref(
            "browser.contentanalysis.default_result",
            param.DefaultResult
          );
        }
      }
      let boolPrefs = [
        ["IsPerUser", "is_per_user"],
        ["ShowBlockedResult", "show_blocked_result"],
        ["BypassForSameTabOperations", "bypass_for_same_tab_operations"],
      ];
      for (let pref of boolPrefs) {
        if (pref[0] in param) {
          setAndLockPref(
            `browser.contentanalysis.${pref[1]}`,
            !!param[pref[0]]
          );
        }
      }
      let interceptionPointPrefs = [
        ["Clipboard", "clipboard"],
        ["DragAndDrop", "drag_and_drop"],
        ["FileUpload", "file_upload"],
        ["Print", "print"],
      ];
      if ("InterceptionPoints" in param) {
        for (let pref of interceptionPointPrefs) {
          // Need to set and lock this value even if the enterprise
          // policy isn't set so users can't change it
          let value = true;
          if (pref[0] in param.InterceptionPoints) {
            if ("Enabled" in param.InterceptionPoints[pref[0]]) {
              value = !!param.InterceptionPoints[pref[0]].Enabled;
            }
          }
          setAndLockPref(
            `browser.contentanalysis.interception_point.${pref[1]}.enabled`,
            value
          );
        }
      }
      if ("Enabled" in param) {
        let enabled = !!param.Enabled;
        setAndLockPref("browser.contentanalysis.enabled", enabled);
        let ca = Cc["@mozilla.org/contentanalysis;1"].getService(
          Ci.nsIContentAnalysis
        );
        ca.isSetByEnterprisePolicy = true;
      }
    },
  },

  Cookies: {
    onBeforeUIStartup(manager, param) {
      addAllowDenyPermissions("cookie", param.Allow, param.Block);

      if (param.AllowSession) {
        for (let origin of param.AllowSession) {
          try {
            Services.perms.addFromPrincipal(
              Services.scriptSecurityManager.createContentPrincipalFromOrigin(
                origin
              ),
              "cookie",
              Ci.nsICookiePermission.ACCESS_SESSION,
              Ci.nsIPermissionManager.EXPIRE_POLICY
            );
          } catch (ex) {
            lazy.log.error(
              `Unable to add cookie session permission - ${origin.href}`
            );
          }
        }
      }

      if (param.Block) {
        const hosts = param.Block.map(url => url.hostname)
          .sort()
          .join("\n");
        runOncePerModification("clearCookiesForBlockedHosts", hosts, () => {
          for (let blocked of param.Block) {
            Services.cookies.removeCookiesWithOriginAttributes(
              "{}",
              blocked.hostname
            );
          }
        });
      }

      if (param.ExpireAtSessionEnd != undefined) {
        lazy.log.error(
          "'ExpireAtSessionEnd' has been deprecated and it has no effect anymore."
        );
      }

      // New Cookie Behavior option takes precendence
      let defaultPref = Services.prefs.getDefaultBranch("");
      let newCookieBehavior = defaultPref.getIntPref(
        "network.cookie.cookieBehavior"
      );
      let newCookieBehaviorPB = defaultPref.getIntPref(
        "network.cookie.cookieBehavior.pbmode"
      );
      if ("Behavior" in param || "BehaviorPrivateBrowsing" in param) {
        let behaviors = {
          accept: Ci.nsICookieService.BEHAVIOR_ACCEPT,
          "reject-foreign": Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
          reject: Ci.nsICookieService.BEHAVIOR_REJECT,
          "limit-foreign": Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN,
          "reject-tracker": Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
          "reject-tracker-and-partition-foreign":
            Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
        };
        if ("Behavior" in param) {
          newCookieBehavior = behaviors[param.Behavior];
        }
        if ("BehaviorPrivateBrowsing" in param) {
          newCookieBehaviorPB = behaviors[param.BehaviorPrivateBrowsing];
        }
      } else {
        // Default, AcceptThirdParty, and RejectTracker are being
        // deprecated in favor of Behavior. They will continue
        // to be supported, though.
        if (
          param.Default !== undefined ||
          param.AcceptThirdParty !== undefined ||
          param.RejectTracker !== undefined ||
          param.Locked
        ) {
          newCookieBehavior = Ci.nsICookieService.BEHAVIOR_ACCEPT;
          if (param.Default !== undefined && !param.Default) {
            newCookieBehavior = Ci.nsICookieService.BEHAVIOR_REJECT;
          } else if (param.AcceptThirdParty) {
            if (param.AcceptThirdParty == "never") {
              newCookieBehavior = Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN;
            } else if (param.AcceptThirdParty == "from-visited") {
              newCookieBehavior = Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN;
            }
          } else if (param.RejectTracker) {
            newCookieBehavior = Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
          }
        }
        // With the old cookie policy, we made private browsing the same.
        newCookieBehaviorPB = newCookieBehavior;
      }
      // We set the values no matter what just in case the policy was only used to lock.
      PoliciesUtils.setDefaultPref(
        "network.cookie.cookieBehavior",
        newCookieBehavior,
        param.Locked
      );
      PoliciesUtils.setDefaultPref(
        "network.cookie.cookieBehavior.pbmode",
        newCookieBehaviorPB,
        param.Locked
      );
    },
  },

  DefaultDownloadDirectory: {
    onBeforeAddons(manager, param) {
      PoliciesUtils.setDefaultPref(
        "browser.download.dir",
        replacePathVariables(param)
      );
    },
  },

  DisableAccounts: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("identity.fxaccounts.enabled", false);
        setAndLockPref("browser.aboutwelcome.enabled", false);
      }
    },
  },

  DisableAppUpdate: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("appUpdate");
      }
    },
  },

  DisableBuiltinPDFViewer: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("pdfjs.disabled", true);
      }
    },
  },

  DisabledCiphers: {
    onBeforeAddons(manager, param) {
      let cipherPrefs = {
        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
          "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
          "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
          "security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256",
        TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
          "security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256",
        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
          "security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384",
        TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
          "security.ssl3.ecdhe_rsa_aes_256_gcm_sha384",
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
          "security.ssl3.ecdhe_rsa_aes_128_sha",
        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
          "security.ssl3.ecdhe_ecdsa_aes_128_sha",
        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
          "security.ssl3.ecdhe_rsa_aes_256_sha",
        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
          "security.ssl3.ecdhe_ecdsa_aes_256_sha",
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA: "security.ssl3.dhe_rsa_aes_128_sha",
        TLS_DHE_RSA_WITH_AES_256_CBC_SHA: "security.ssl3.dhe_rsa_aes_256_sha",
        TLS_RSA_WITH_AES_128_GCM_SHA256: "security.ssl3.rsa_aes_128_gcm_sha256",
        TLS_RSA_WITH_AES_256_GCM_SHA384: "security.ssl3.rsa_aes_256_gcm_sha384",
        TLS_RSA_WITH_AES_128_CBC_SHA: "security.ssl3.rsa_aes_128_sha",
        TLS_RSA_WITH_AES_256_CBC_SHA: "security.ssl3.rsa_aes_256_sha",
        TLS_RSA_WITH_3DES_EDE_CBC_SHA:
          "security.ssl3.deprecated.rsa_des_ede3_sha",
      };

      for (let cipher in param) {
        setAndLockPref(cipherPrefs[cipher], !param[cipher]);
      }
    },
  },

  DisableDefaultBrowserAgent: {
    // The implementation of this policy is in the default browser agent itself
    // (/toolkit/mozapps/defaultagent); we need an entry for it here so that it
    // shows up in about:policies as a real policy and not as an error.
  },

  DisableDeveloperTools: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("devtools.policy.disabled", true);
        setAndLockPref("devtools.chrome.enabled", false);

        manager.disallowFeature("devtools");
        blockAboutPage(manager, "about:debugging");
        blockAboutPage(manager, "about:devtools-toolbox");
        blockAboutPage(manager, "about:profiling");
      }
    },
  },

  DisableEncryptedClientHello: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("network.dns.echconfig.enabled", false);
        setAndLockPref("network.dns.http3_echconfig.enabled", false);
      }
    },
  },

  DisableFeedbackCommands: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("feedbackCommands");
      }
    },
  },

  DisableFirefoxAccounts: {
    onBeforeAddons(manager, param) {
      // If DisableAccounts is set, let it take precedence.
      if ("DisableAccounts" in manager.getActivePolicies()) {
        return;
      }

      if (param) {
        setAndLockPref("identity.fxaccounts.enabled", false);
        setAndLockPref("browser.aboutwelcome.enabled", false);
      }
    },
  },

  DisableFirefoxScreenshots: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("extensions.screenshots.disabled", true);
      }
    },
  },

  DisableFirefoxStudies: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("Shield");
        setAndLockPref(
          "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
          false
        );
        setAndLockPref(
          "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
          false
        );
      }
    },
  },

  DisableForgetButton: {
    onProfileAfterChange(manager, param) {
      if (param) {
        setAndLockPref("privacy.panicButton.enabled", false);
      }
    },
  },

  DisableFormHistory: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        setAndLockPref("browser.formfill.enable", false);
      }
    },
  },

  DisableMasterPasswordCreation: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("createMasterPassword");
      }
    },
  },

  DisablePasswordReveal: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("passwordReveal");
      }
    },
  },

  DisablePocket: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("extensions.pocket.enabled", false);
      }
    },
  },

  DisablePrivateBrowsing: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("privatebrowsing");
        blockAboutPage(manager, "about:privatebrowsing", true);
        setAndLockPref("browser.privatebrowsing.autostart", false);
      }
    },
  },

  DisableProfileImport: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("profileImport");
        setAndLockPref(
          "browser.newtabpage.activity-stream.migrationExpired",
          true
        );
      }
    },
  },

  DisableProfileRefresh: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("profileRefresh");
        setAndLockPref("browser.disableResetPrompt", true);
      }
    },
  },

  DisableSafeMode: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("safeMode");
      }
    },
  },

  DisableSecurityBypass: {
    onBeforeUIStartup(manager, param) {
      if ("InvalidCertificate" in param) {
        setAndLockPref(
          "security.certerror.hideAddException",
          param.InvalidCertificate
        );
      }

      if ("SafeBrowsing" in param) {
        setAndLockPref(
          "browser.safebrowsing.allowOverride",
          !param.SafeBrowsing
        );
      }
    },
  },

  DisableSetDesktopBackground: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("setDesktopBackground");
      }
    },
  },

  DisableSystemAddonUpdate: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("SysAddonUpdate");
      }
    },
  },

  DisableTelemetry: {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("datareporting.healthreport.uploadEnabled", false);
        setAndLockPref("datareporting.policy.dataSubmissionEnabled", false);
        setAndLockPref("toolkit.telemetry.archive.enabled", false);
        blockAboutPage(manager, "about:telemetry");
      }
    },
  },

  DisableThirdPartyModuleBlocking: {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("thirdPartyModuleBlocking");
      }
    },
  },

  DisplayBookmarksToolbar: {
    onBeforeUIStartup(manager, param) {
      let visibility;
      if (typeof param === "boolean") {
        visibility = param ? "always" : "newtab";
      } else {
        visibility = param;
      }
      // This policy is meant to change the default behavior, not to force it.
      // If this policy was already applied and the user chose to re-hide the
      // bookmarks toolbar, do not show it again.
      runOncePerModification("displayBookmarksToolbar", visibility, () => {
        let visibilityPref = "browser.toolbars.bookmarks.visibility";
        Services.prefs.setCharPref(visibilityPref, visibility);
      });
    },
  },

  DisplayMenuBar: {
    onBeforeUIStartup(manager, param) {
      let value;
      if (
        typeof param === "boolean" ||
        param == "default-on" ||
        param == "default-off"
      ) {
        switch (param) {
          case "default-on":
            value = "false";
            break;
          case "default-off":
            value = "true";
            break;
          default:
            value = (!param).toString();
            break;
        }
        // This policy is meant to change the default behavior, not to force it.
        // If this policy was already applied and the user chose to re-hide the
        // menu bar, do not show it again.
        runOncePerModification("displayMenuBar", value, () => {
          Services.xulStore.setValue(
            BROWSER_DOCUMENT_URL,
            "toolbar-menubar",
            "autohide",
            value
          );
        });
      } else {
        switch (param) {
          case "always":
            value = "false";
            break;
          case "never":
            // Make sure Alt key doesn't show the menubar
            setAndLockPref("ui.key.menuAccessKeyFocuses", false);
            value = "true";
            break;
        }
        Services.xulStore.setValue(
          BROWSER_DOCUMENT_URL,
          "toolbar-menubar",
          "autohide",
          value
        );
        manager.disallowFeature("hideShowMenuBar");
      }
    },
  },

  DNSOverHTTPS: {
    onBeforeAddons(manager, param) {
      if ("Enabled" in param) {
        let mode = param.Enabled ? 2 : 5;
        // Fallback only matters if DOH is enabled.
        if (param.Fallback === false) {
          mode = 3;
        }
        PoliciesUtils.setDefaultPref("network.trr.mode", mode, param.Locked);
      }
      if ("ProviderURL" in param) {
        PoliciesUtils.setDefaultPref(
          "network.trr.uri",
          param.ProviderURL.href,
          param.Locked
        );
      }
      if ("ExcludedDomains" in param) {
        PoliciesUtils.setDefaultPref(
          "network.trr.excluded-domains",
          param.ExcludedDomains.join(","),
          param.Locked
        );
      }
    },
  },

  DontCheckDefaultBrowser: {
    onBeforeUIStartup(manager, param) {
      setAndLockPref("browser.shell.checkDefaultBrowser", !param);
    },
  },

  DownloadDirectory: {
    onBeforeAddons(manager, param) {
      setAndLockPref("browser.download.dir", replacePathVariables(param));
      // If a custom download directory is being used, just lock folder list to 2.
      setAndLockPref("browser.download.folderList", 2);
      // Per Chrome spec, user can't choose to download every time
      // if this is set.
      setAndLockPref("browser.download.useDownloadDir", true);
    },
  },

  EnableTrackingProtection: {
    onBeforeUIStartup(manager, param) {
      if (param.Value) {
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.enabled",
          true,
          param.Locked
        );
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.pbmode.enabled",
          true,
          param.Locked
        );
      } else {
        setAndLockPref("privacy.trackingprotection.enabled", false);
        setAndLockPref("privacy.trackingprotection.pbmode.enabled", false);
      }
      if ("Cryptomining" in param) {
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.cryptomining.enabled",
          param.Cryptomining,
          param.Locked
        );
      }
      if ("Fingerprinting" in param) {
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.fingerprinting.enabled",
          param.Fingerprinting,
          param.Locked
        );
      }
      if ("EmailTracking" in param) {
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.emailtracking.enabled",
          param.EmailTracking,
          param.Locked
        );
        PoliciesUtils.setDefaultPref(
          "privacy.trackingprotection.emailtracking.pbmode.enabled",
          param.EmailTracking,
          param.Locked
        );
      }
      if ("Exceptions" in param) {
        addAllowDenyPermissions("trackingprotection", param.Exceptions);
      }
    },
  },

  EncryptedMediaExtensions: {
    onBeforeAddons(manager, param) {
      if ("Enabled" in param) {
        PoliciesUtils.setDefaultPref(
          "media.eme.enabled",
          param.Enabled,
          param.Locked
        );
      }
    },
  },

  ExemptDomainFileTypePairsFromFileTypeDownloadWarnings: {
    // This policy is handled directly in EnterprisePoliciesParent.sys.mjs
    // and requires no validation (It's done by the schema).
  },

  Extensions: {
    onBeforeUIStartup(manager, param) {
      let uninstallingPromise = Promise.resolve();
      if ("Uninstall" in param) {
        uninstallingPromise = runOncePerModification(
          "extensionsUninstall",
          JSON.stringify(param.Uninstall),
          async () => {
            // If we're uninstalling add-ons, re-run the extensionsInstall runOnce even if it hasn't
            // changed, which will allow add-ons to be updated.
            Services.prefs.clearUserPref(
              "browser.policies.runOncePerModification.extensionsInstall"
            );
            let addons = await lazy.AddonManager.getAddonsByIDs(
              param.Uninstall
            );
            for (let addon of addons) {
              if (addon) {
                try {
                  await addon.uninstall();
                } catch (e) {
                  // This can fail for add-ons that can't be uninstalled.
                  lazy.log.debug(
                    `Add-on ID (${addon.id}) couldn't be uninstalled.`
                  );
                }
              }
            }
          }
        );
      }
      if ("Install" in param) {
        runOncePerModification(
          "extensionsInstall",
          JSON.stringify(param.Install),
          async () => {
            await uninstallingPromise;
            for (let location of param.Install) {
              let uri;
              try {
                // We need to try as a file first because
                // Windows paths are valid URIs.
                // This is done for legacy support (old API)
                let xpiFile = new lazy.FileUtils.File(location);
                uri = Services.io.newFileURI(xpiFile);
              } catch (e) {
                uri = Services.io.newURI(location);
              }
              installAddonFromURL(uri.spec);
            }
          }
        );
      }
      if ("Locked" in param) {
        for (let ID of param.Locked) {
          manager.disallowFeature(`uninstall-extension:${ID}`);
          manager.disallowFeature(`disable-extension:${ID}`);
        }
      }
    },
  },

  ExtensionSettings: {
    onBeforeAddons(manager, param) {
      try {
        manager.setExtensionSettings(param);
      } catch (e) {
        lazy.log.error("Invalid ExtensionSettings");
      }
    },
    async onBeforeUIStartup(manager, param) {
      let extensionSettings = param;
      let blockAllExtensions = false;
      if ("*" in extensionSettings) {
        if (
          "installation_mode" in extensionSettings["*"] &&
          extensionSettings["*"].installation_mode == "blocked"
        ) {
          blockAllExtensions = true;
          // Turn off discovery pane in about:addons
          setAndLockPref("extensions.getAddons.showPane", false);
          // Turn off recommendations
          setAndLockPref(
            "extensions.htmlaboutaddons.recommendations.enable",
            false
          );
          // Block about:debugging
          blockAboutPage(manager, "about:debugging");
        }
        if ("restricted_domains" in extensionSettings["*"]) {
          let restrictedDomains = Services.prefs
            .getCharPref("extensions.webextensions.restrictedDomains")
            .split(",");
          setAndLockPref(
            "extensions.webextensions.restrictedDomains",
            restrictedDomains
              .concat(extensionSettings["*"].restricted_domains)
              .join(",")
          );
        }
      }
      let addons = await lazy.AddonManager.getAllAddons();
      let allowedExtensions = [];
      for (let extensionID in extensionSettings) {
        if (extensionID == "*") {
          // Ignore global settings
          continue;
        }
        if ("installation_mode" in extensionSettings[extensionID]) {
          if (
            extensionSettings[extensionID].installation_mode ==
              "force_installed" ||
            extensionSettings[extensionID].installation_mode ==
              "normal_installed"
          ) {
            if (!extensionSettings[extensionID].install_url) {
              throw new Error(`Missing install_url for ${extensionID}`);
            }
            installAddonFromURL(
              extensionSettings[extensionID].install_url,
              extensionID,
              addons.find(addon => addon.id == extensionID)
            );
            manager.disallowFeature(`uninstall-extension:${extensionID}`);
            if (
              extensionSettings[extensionID].installation_mode ==
              "force_installed"
            ) {
              manager.disallowFeature(`disable-extension:${extensionID}`);
            }
            allowedExtensions.push(extensionID);
          } else if (
            extensionSettings[extensionID].installation_mode == "allowed"
          ) {
            allowedExtensions.push(extensionID);
          } else if (
            extensionSettings[extensionID].installation_mode == "blocked"
          ) {
            if (addons.find(addon => addon.id == extensionID)) {
              // Can't use the addon from getActiveAddons since it doesn't have uninstall.
              let addon = await lazy.AddonManager.getAddonByID(extensionID);
              try {
                await addon.uninstall();
              } catch (e) {
                // This can fail for add-ons that can't be uninstalled.
                lazy.log.debug(
                  `Add-on ID (${addon.id}) couldn't be uninstalled.`
                );
              }
            }
          }
        }
      }
      if (blockAllExtensions) {
        for (let addon of addons) {
          if (
            addon.isSystem ||
            addon.isBuiltin ||
            !(addon.scope & lazy.AddonManager.SCOPE_PROFILE)
          ) {
            continue;
          }
          if (!allowedExtensions.includes(addon.id)) {
            try {
              // Can't use the addon from getActiveAddons since it doesn't have uninstall.
              let addonToUninstall = await lazy.AddonManager.getAddonByID(
                addon.id
              );
              await addonToUninstall.uninstall();
            } catch (e) {
              // This can fail for add-ons that can't be uninstalled.
              lazy.log.debug(
                `Add-on ID (${addon.id}) couldn't be uninstalled.`
              );
            }
          }
        }
      }
    },
  },

  ExtensionUpdate: {
    onBeforeAddons(manager, param) {
      if (!param) {
        setAndLockPref("extensions.update.enabled", param);
      }
    },
  },

  FirefoxHome: {
    onBeforeAddons(manager, param) {
      if ("Search" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.showSearch",
          param.Search,
          param.Locked
        );
      }
      if ("TopSites" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.feeds.topsites",
          param.TopSites,
          param.Locked
        );
      }
      if ("SponsoredTopSites" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.showSponsoredTopSites",
          param.SponsoredTopSites,
          param.Locked
        );
      }
      if ("Highlights" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.feeds.section.highlights",
          param.Highlights,
          param.Locked
        );
      }
      if ("Pocket" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.feeds.system.topstories",
          param.Pocket,
          param.Locked
        );
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.feeds.section.topstories",
          param.Pocket,
          param.Locked
        );
      }
      if ("SponsoredPocket" in param) {
        PoliciesUtils.setDefaultPref(
          "browser.newtabpage.activity-stream.showSponsored",
          param.SponsoredPocket,
          param.Locked
        );
      }
    },
  },

  FirefoxSuggest: {
    onBeforeAddons(manager, param) {
      (async () => {
        await lazy.UrlbarPrefs.firefoxSuggestScenarioStartupPromise;
        if ("WebSuggestions" in param) {
          PoliciesUtils.setDefaultPref(
            "browser.urlbar.suggest.quicksuggest.nonsponsored",
            param.WebSuggestions,
            param.Locked
          );
        }
        if ("SponsoredSuggestions" in param) {
          PoliciesUtils.setDefaultPref(
            "browser.urlbar.suggest.quicksuggest.sponsored",
            param.SponsoredSuggestions,
            param.Locked
          );
        }
        if ("ImproveSuggest" in param) {
          PoliciesUtils.setDefaultPref(
            "browser.urlbar.quicksuggest.dataCollection.enabled",
            param.ImproveSuggest,
            param.Locked
          );
        }
      })();
    },
  },

  GoToIntranetSiteForSingleWordEntryInAddressBar: {
    onBeforeAddons(manager, param) {
      setAndLockPref("browser.fixup.dns_first_for_single_words", param);
    },
  },

  Handlers: {
    onBeforeAddons(manager, param) {
      if ("mimeTypes" in param) {
        for (let mimeType in param.mimeTypes) {
          let mimeInfo = param.mimeTypes[mimeType];
          let realMIMEInfo = lazy.gMIMEService.getFromTypeAndExtension(
            mimeType,
            ""
          );
          processMIMEInfo(mimeInfo, realMIMEInfo);
        }
      }
      if ("extensions" in param) {
        for (let extension in param.extensions) {
          let mimeInfo = param.extensions[extension];
          try {
            let realMIMEInfo = lazy.gMIMEService.getFromTypeAndExtension(
              "",
              extension
            );
            processMIMEInfo(mimeInfo, realMIMEInfo);
          } catch (e) {
            lazy.log.error(`Invalid file extension (${extension})`);
          }
        }
      }
      if ("schemes" in param) {
        for (let scheme in param.schemes) {
          let handlerInfo = param.schemes[scheme];
          let realHandlerInfo =
            lazy.gExternalProtocolService.getProtocolHandlerInfo(scheme);
          processMIMEInfo(handlerInfo, realHandlerInfo);
        }
      }
    },
  },

  HardwareAcceleration: {
    onBeforeAddons(manager, param) {
      if (!param) {
        setAndLockPref("layers.acceleration.disabled", true);
      }
    },
  },

  Homepage: {
    onBeforeUIStartup(manager, param) {
      if ("StartPage" in param && param.StartPage == "none") {
        // For blank startpage, we use about:blank rather
        // than messing with browser.startup.page
        param.URL = new URL("about:blank");
      }
      // |homepages| will be a string containing a pipe-separated ('|') list of
      // URLs because that is what the "Home page" section of about:preferences
      // (and therefore what the pref |browser.startup.homepage|) accepts.
      if ("URL" in param) {
        let homepages = param.URL.href;
        if (param.Additional && param.Additional.length) {
          homepages += "|" + param.Additional.map(url => url.href).join("|");
        }
        PoliciesUtils.setDefaultPref(
          "browser.startup.homepage",
          homepages,
          param.Locked
        );
        if (param.Locked) {
          setAndLockPref(
            "pref.browser.homepage.disable_button.current_page",
            true
          );
          setAndLockPref(
            "pref.browser.homepage.disable_button.bookmark_page",
            true
          );
          setAndLockPref(
            "pref.browser.homepage.disable_button.restore_default",
            true
          );
        } else {
          // Clear out old run once modification that is no longer used.
          clearRunOnceModification("setHomepage");
        }
        // If a homepage has been set via policy, show the home button
        if (param.URL != "about:blank") {
          manager.disallowFeature("removeHomeButtonByDefault");
        }
      }
      if (param.StartPage) {
        let prefValue;
        switch (param.StartPage) {
          case "homepage":
          case "homepage-locked":
          case "none":
            prefValue = 1;
            break;
          case "previous-session":
            prefValue = 3;
            break;
        }
        PoliciesUtils.setDefaultPref(
          "browser.startup.page",
          prefValue,
          param.StartPage == "homepage-locked"
        );
      }
    },
  },

  HttpAllowlist: {
    onBeforeAddons(manager, param) {
      addAllowDenyPermissions("https-only-load-insecure", param);
    },
  },

  HttpsOnlyMode: {
    onBeforeAddons(manager, param) {
      switch (param) {
        case "disallowed":
          setAndLockPref("dom.security.https_only_mode", false);
          break;
        case "enabled":
          PoliciesUtils.setDefaultPref("dom.security.https_only_mode", true);
          break;
        case "force_enabled":
          setAndLockPref("dom.security.https_only_mode", true);
          break;
        case "allowed":
          // The default case.
          break;
      }
    },
  },

  InstallAddonsPermission: {
    onBeforeUIStartup(manager, param) {
      if ("Allow" in param) {
        addAllowDenyPermissions("install", param.Allow, null);
      }
      if ("Default" in param) {
        setAndLockPref("xpinstall.enabled", param.Default);
        if (!param.Default) {
          blockAboutPage(manager, "about:debugging");
          setAndLockPref(
            "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
            false
          );
          setAndLockPref(
            "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
            false
          );
          manager.disallowFeature("xpinstall");
        }
      }
    },
  },

  LegacyProfiles: {
    // Handled in nsToolkitProfileService.cpp (Windows only)
  },

  LegacySameSiteCookieBehaviorEnabled: {
    onBeforeAddons(manager, param) {
      PoliciesUtils.setDefaultPref(
        "network.cookie.sameSite.laxByDefault",
        !param
      );
    },
  },

  LegacySameSiteCookieBehaviorEnabledForDomainList: {
    onBeforeAddons(manager, param) {
      PoliciesUtils.setDefaultPref(
        "network.cookie.sameSite.laxByDefault.disabledHosts",
        param.join(",")
      );
    },
  },

  LocalFileLinks: {
    onBeforeAddons(manager, param) {
      // If there are existing capabilities, lock them with the policy pref.
      let policyNames = Services.prefs
        .getCharPref("capability.policy.policynames", "")
        .split(" ");
      policyNames.push("localfilelinks_policy");
      setAndLockPref("capability.policy.policynames", policyNames.join(" "));
      setAndLockPref(
        "capability.policy.localfilelinks_policy.checkloaduri.enabled",
        "allAccess"
      );
      setAndLockPref(
        "capability.policy.localfilelinks_policy.sites",
        param.join(" ")
      );
    },
  },

  ManagedBookmarks: {},

  ManualAppUpdateOnly: {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("autoAppUpdateChecking");
      }
    },
  },

  MicrosoftEntraSSO: {
    onBeforeAddons(manager, param) {
      setAndLockPref("network.http.microsoft-entra-sso.enabled", param);
    },
  },

  NetworkPrediction: {
    onBeforeAddons(manager, param) {
      setAndLockPref("network.dns.disablePrefetch", !param);
      setAndLockPref("network.dns.disablePrefetchFromHTTPS", !param);
    },
  },

  NewTabPage: {
    onBeforeAddons(manager, param) {
      setAndLockPref("browser.newtabpage.enabled", param);
    },
  },

  NoDefaultBookmarks: {
    onProfileAfterChange(manager, param) {
      if (param) {
        manager.disallowFeature("defaultBookmarks");
      }
    },
  },

  OfferToSaveLogins: {
    onBeforeUIStartup(manager, param) {
      setAndLockPref("signon.rememberSignons", param);
      setAndLockPref("services.passwordSavingEnabled", param);
    },
  },

  OfferToSaveLoginsDefault: {
    onBeforeUIStartup(manager, param) {
      let policies = Services.policies.getActivePolicies();
      if ("OfferToSaveLogins" in policies) {
        lazy.log.error(
          `OfferToSaveLoginsDefault ignored because OfferToSaveLogins is present.`
        );
      } else {
        PoliciesUtils.setDefaultPref("signon.rememberSignons", param);
      }
    },
  },

  OverrideFirstRunPage: {
    onProfileAfterChange(manager, param) {
      let url = param ? param : "";
      setAndLockPref("startup.homepage_welcome_url", url);
      setAndLockPref("browser.aboutwelcome.enabled", false);
    },
  },

  OverridePostUpdatePage: {
    onProfileAfterChange(manager, param) {
      let url = param ? param.href : "";
      setAndLockPref("startup.homepage_override_url", url);
      // The pref startup.homepage_override_url is only used
      // as a fallback when the update.xml file hasn't provided
      // a specific post-update URL.
      manager.disallowFeature("postUpdateCustomPage");
    },
  },

  PasswordManagerEnabled: {
    onBeforeUIStartup(manager, param) {
      if (!param) {
        blockAboutPage(manager, "about:logins", true);
        setAndLockPref("pref.privacy.disable_button.view_passwords", true);
      }
      setAndLockPref("signon.rememberSignons", param);
    },
  },

  PasswordManagerExceptions: {
    onBeforeUIStartup(manager, param) {
      addAllowDenyPermissions("login-saving", null, param);
    },
  },

  PDFjs: {
    onBeforeAddons(manager, param) {
      if ("Enabled" in param) {
        setAndLockPref("pdfjs.disabled", !param.Enabled);
      }
      if ("EnablePermissions" in param) {
        setAndLockPref("pdfjs.enablePermissions", param.EnablePermissions);
      }
    },
  },

  Permissions: {
    onBeforeUIStartup(manager, param) {
      if (param.Camera) {
        addAllowDenyPermissions(
          "camera",
          param.Camera.Allow,
          param.Camera.Block
        );
        setDefaultPermission("camera", param.Camera);
      }

      if (param.Microphone) {
        addAllowDenyPermissions(
          "microphone",
          param.Microphone.Allow,
          param.Microphone.Block
        );
        setDefaultPermission("microphone", param.Microphone);
      }

      if (param.Autoplay) {
        addAllowDenyPermissions(
          "autoplay-media",
          param.Autoplay.Allow,
          param.Autoplay.Block
        );
        if ("Default" in param.Autoplay) {
          let prefValue;
          switch (param.Autoplay.Default) {
            case "allow-audio-video":
              prefValue = 0;
              break;
            case "block-audio":
              prefValue = 1;
              break;
            case "block-audio-video":
              prefValue = 5;
              break;
          }
          PoliciesUtils.setDefaultPref(
            "media.autoplay.default",
            prefValue,
            param.Autoplay.Locked
          );
        }
      }

      if (param.Location) {
        addAllowDenyPermissions(
          "geo",
          param.Location.Allow,
          param.Location.Block
        );
        setDefaultPermission("geo", param.Location);
      }

      if (param.Notifications) {
        addAllowDenyPermissions(
          "desktop-notification",
          param.Notifications.Allow,
          param.Notifications.Block
        );
        setDefaultPermission("desktop-notification", param.Notifications);
      }

      if ("VirtualReality" in param) {
        addAllowDenyPermissions(
          "xr",
          param.VirtualReality.Allow,
          param.VirtualReality.Block
        );
        setDefaultPermission("xr", param.VirtualReality);
      }
    },
  },

  PictureInPicture: {
    onBeforeAddons(manager, param) {
      if ("Enabled" in param) {
        PoliciesUtils.setDefaultPref(
          "media.videocontrols.picture-in-picture.video-toggle.enabled",
          param.Enabled
        );
      }
      if (param.Locked) {
        Services.prefs.lockPref(
          "media.videocontrols.picture-in-picture.video-toggle.enabled"
        );
      }
    },
  },

  PopupBlocking: {
    onBeforeUIStartup(manager, param) {
      addAllowDenyPermissions("popup", param.Allow, null);

      if (param.Locked) {
        let blockValue = true;
        if (param.Default !== undefined && !param.Default) {
          blockValue = false;
        }
        setAndLockPref("dom.disable_open_during_load", blockValue);
      } else if (param.Default !== undefined) {
        PoliciesUtils.setDefaultPref(
          "dom.disable_open_during_load",
          !!param.Default
        );
      }
    },
  },

  PostQuantumKeyAgreementEnabled: {
    onBeforeAddons(manager, param) {
      setAndLockPref("network.http.http3.enable_kyber", param);
      setAndLockPref("security.tls.enable_kyber", param);
      setAndLockPref("media.webrtc.enable_pq_dtls", param);
    },
  },

  Preferences: {
    onBeforeAddons(manager, param) {
      let allowedPrefixes = [
        "accessibility.",
        "alerts.",
        "app.update.",
        "browser.",
        "datareporting.policy.",
        "dom.",
        "extensions.",
        "general.autoScroll",
        "general.smoothScroll",
        "geo.",
        "gfx.",
        "identity.fxaccounts.toolbar.",
        "intl.",
        "keyword.enabled",
        "layers.",
        "layout.",
        "media.",
        "network.",
        "pdfjs.",
        "places.",
        "pref.",
        "print.",
        "privacy.globalprivacycontrol.enabled",
        "privacy.userContext.enabled",
        "privacy.userContext.ui.enabled",
        "signon.",
        "spellchecker.",
        "toolkit.legacyUserProfileCustomizations.stylesheets",
        "ui.",
        "widget.",
        "xpinstall.whitelist.required",
      ];
      if (!AppConstants.MOZ_REQUIRE_SIGNING) {
        allowedPrefixes.push("xpinstall.signatures.required");
      }
      const allowedSecurityPrefs = [
        "security.block_fileuri_script_with_wrong_mime",
        "security.default_personal_cert",
        "security.disable_button.openCertManager",
        "security.disable_button.openDeviceManager",
        "security.insecure_connection_text.enabled",
        "security.insecure_connection_text.pbmode.enabled",
        "security.mixed_content.block_active_content",
        "security.mixed_content.block_display_content",
        "security.mixed_content.upgrade_display_content",
        "security.osclientcerts.assume_rsa_pss_support",
        "security.osclientcerts.autoload",
        "security.OCSP.enabled",
        "security.OCSP.require",
        "security.pki.certificate_transparency.disable_for_hosts",
        "security.pki.certificate_transparency.disable_for_spki_hashes",
        "security.pki.certificate_transparency.mode",
        "security.ssl.enable_ocsp_stapling",
        "security.ssl.errorReporting.enabled",
        "security.ssl.require_safe_negotiation",
        "security.tls.enable_0rtt_data",
        "security.tls.hello_downgrade_check",
        "security.tls.version.enable-deprecated",
        "security.warn_submit_secure_to_insecure",
      ];
      const blockedPrefs = [
        "app.update.channel",
        "app.update.lastUpdateTime",
        "app.update.migrated",
        "browser.vpn_promo.disallowed_regions",
      ];

      for (let preference in param) {
        if (blockedPrefs.includes(preference)) {
          lazy.log.error(
            `Unable to set preference ${preference}. Preference not allowed for security reasons.`
          );
          continue;
        }
        if (preference.startsWith("security.")) {
          if (!allowedSecurityPrefs.includes(preference)) {
            lazy.log.error(
              `Unable to set preference ${preference}. Preference not allowed for security reasons.`
            );
            continue;
          }
        } else if (
          !allowedPrefixes.some(prefix => preference.startsWith(prefix))
        ) {
          lazy.log.error(
            `Unable to set preference ${preference}. Preference not allowed for stability reasons.`
          );
          continue;
        }
        if (typeof param[preference] != "object") {
          // Legacy policy preferences
          setAndLockPref(preference, param[preference]);
        } else {
          if (param[preference].Status == "clear") {
            Services.prefs.clearUserPref(preference);
            continue;
          }

          let prefBranch;
          if (param[preference].Status == "user") {
            prefBranch = Services.prefs;
          } else {
            prefBranch = Services.prefs.getDefaultBranch("");
          }

          // Prefs that were previously locked should stay locked,
          // but policy can update the value.
          let prefWasLocked = Services.prefs.prefIsLocked(preference);
          if (prefWasLocked) {
            Services.prefs.unlockPref(preference);
          }
          try {
            let prefType =
              param[preference].Type || typeof param[preference].Value;
            switch (prefType) {
              case "boolean":
                prefBranch.setBoolPref(preference, param[preference].Value);
                break;

              case "number":
                if (!Number.isInteger(param[preference].Value)) {
                  throw new Error(`Non-integer value for ${preference}`);
                }

                // This is ugly, but necessary. On Windows GPO and macOS
                // configs, booleans are converted to 0/1. In the previous
                // Preferences implementation, the schema took care of
                // automatically converting these values to booleans.
                // Since we allow arbitrary prefs now, we have to do
                // something different. See bug 1666836, 1668374, and 1872267.

                // We only set something as int if it was explicit in policy,
                // the same type as the default pref, or NOT 0/1. Otherwise
                // we set it as bool.
                if (
                  param[preference].Type == "number" ||
                  prefBranch.getPrefType(preference) == prefBranch.PREF_INT ||
                  ![0, 1].includes(param[preference].Value)
                ) {
                  prefBranch.setIntPref(preference, param[preference].Value);
                } else {
                  prefBranch.setBoolPref(preference, !!param[preference].Value);
                }
                break;

              case "string":
                prefBranch.setStringPref(preference, param[preference].Value);
                break;
            }
          } catch (e) {
            lazy.log.error(
              `Unable to set preference ${preference}. Probable type mismatch.`
            );
          }

          if (param[preference].Status == "locked" || prefWasLocked) {
            Services.prefs.lockPref(preference);
          }
        }
      }
    },
  },

  PrimaryPassword: {
    onAllWindowsRestored(manager, param) {
      if (param) {
        manager.disallowFeature("removeMasterPassword");
      } else {
        manager.disallowFeature("createMasterPassword");
      }
    },
  },

  PrintingEnabled: {
    onBeforeUIStartup(manager, param) {
      setAndLockPref("print.enabled", param);
    },
  },

  PrivateBrowsingModeAvailability: {
    onBeforeAddons(manager, param) {
      switch (param) {
        // Private Browsing mode disabled
        case 1:
          manager.disallowFeature("privatebrowsing");
          blockAboutPage(manager, "about:privatebrowsing", true);
          setAndLockPref("browser.privatebrowsing.autostart", false);
          break;
        // Private Browsing mode forced
        case 2:
          setAndLockPref("browser.privatebrowsing.autostart", true);
          break;
        // Private Browsing mode available
        case 0:
          break;
      }
    },
  },

  PromptForDownloadLocation: {
    onBeforeAddons(manager, param) {
      setAndLockPref("browser.download.useDownloadDir", !param);
    },
  },

  Proxy: {
    onBeforeAddons(manager, param) {
      if (param.Locked) {
        manager.disallowFeature("changeProxySettings");
      }
      lazy.ProxyPolicies.configureProxySettings(
        param,
        PoliciesUtils.setDefaultPref
      );
    },
  },

  RequestedLocales: {
    onBeforeAddons(manager, param) {
      let requestedLocales;
      if (Array.isArray(param)) {
        requestedLocales = param;
      } else if (param) {
        requestedLocales = param.split(",");
      } else {
        requestedLocales = [];
      }
      runOncePerModification(
        "requestedLocales",
        JSON.stringify(requestedLocales),
        () => {
          Services.locale.requestedLocales = requestedLocales;
        }
      );
    },
  },

  SanitizeOnShutdown: {
    onBeforeUIStartup(manager, param) {
      if (typeof param === "boolean") {
        setAndLockPref("privacy.sanitize.sanitizeOnShutdown", param);
        setAndLockPref("privacy.clearOnShutdown.cache", param);
        setAndLockPref("privacy.clearOnShutdown.cookies", param);
        setAndLockPref("privacy.clearOnShutdown.downloads", param);
--> --------------------

--> maximum size reached

--> --------------------

[ zur Elbe Produktseite wechseln0.52Quellennavigators  Analyse erneut starten  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge