зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1419102 - Implement the Enterprise Policies feature to provide enterprise users with easier control and setup of deployments of Firefox. r=Mossop
This feature is currently disabled behind a pref, but this pref will be removed when we're green to release it. MozReview-Commit-ID: 3ZH2UJVdtC0 --HG-- rename : browser/components/newtab/tests/browser/.eslintrc.js => browser/components/enterprisepolicies/tests/browser/.eslintrc.js
This commit is contained in:
Родитель
89c4589def
Коммит
fcb1b42e8d
|
@ -77,6 +77,10 @@ browser/base/content/newtab/**
|
|||
# Test files that are really json not js, and don't need to be linted.
|
||||
browser/components/sessionstore/test/unit/data/sessionstore_valid.js
|
||||
browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
|
||||
# This file is split into two in order to keep it as a valid json file
|
||||
# for documentation purposes (policies.json) but to be accessed by the
|
||||
# code as a .jsm (schema.jsm)
|
||||
browser/components/enterprisepolicies/schemas/schema.jsm
|
||||
# generated & special files in cld2
|
||||
browser/components/translation/cld2/**
|
||||
# Screenshots and Follow-on search are imported as a system add-on and have
|
||||
|
|
|
@ -0,0 +1,358 @@
|
|||
/* 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/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
NetUtil: "resource://gre/modules/NetUtil.jsm",
|
||||
Policies: "resource:///modules/policies/Policies.jsm",
|
||||
PoliciesValidator: "resource:///modules/policies/PoliciesValidator.jsm",
|
||||
});
|
||||
|
||||
// This is the file that will be searched for in the
|
||||
// ${InstallDir}/distribution folder.
|
||||
const POLICIES_FILENAME = "policies.json";
|
||||
|
||||
// For easy testing, modify the helpers/sample.json file,
|
||||
// and set PREF_ALTERNATE_PATH in firefox.js as:
|
||||
// /your/repo/browser/components/enterprisepolicies/helpers/sample.json
|
||||
const PREF_ALTERNATE_PATH = "browser.policies.alternatePath";
|
||||
|
||||
// This pref is meant to be temporary: it will only be used while we're
|
||||
// testing this feature without rolling it out officially. When the
|
||||
// policy engine is released, this pref should be removed.
|
||||
const PREF_ENABLED = "browser.policies.enabled";
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "Enterprise Policies",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
// ==== Start XPCOM Boilerplate ==== \\
|
||||
|
||||
// Factory object
|
||||
const EnterprisePoliciesFactory = {
|
||||
_instance: null,
|
||||
createInstance: function BGSF_createInstance(outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return this._instance == null ?
|
||||
this._instance = new EnterprisePoliciesManager() : this._instance;
|
||||
}
|
||||
};
|
||||
|
||||
// ==== End XPCOM Boilerplate ==== //
|
||||
|
||||
// Constructor
|
||||
function EnterprisePoliciesManager() {
|
||||
Services.obs.addObserver(this, "profile-after-change", true);
|
||||
Services.obs.addObserver(this, "final-ui-startup", true);
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||
Services.obs.addObserver(this, "EnterprisePolicies:Restart", true);
|
||||
}
|
||||
|
||||
EnterprisePoliciesManager.prototype = {
|
||||
// for XPCOM
|
||||
classID: Components.ID("{ea4e1414-779b-458b-9d1f-d18e8efbc145}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIEnterprisePolicies]),
|
||||
|
||||
// redefine the default factory for XPCOMUtils
|
||||
_xpcom_factory: EnterprisePoliciesFactory,
|
||||
|
||||
_initialize() {
|
||||
if (!Services.prefs.getBoolPref(PREF_ENABLED, false)) {
|
||||
this.status = Ci.nsIEnterprisePolicies.INACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
this._file = new JSONFileReader(getConfigurationFile());
|
||||
this._file.readData();
|
||||
|
||||
if (!this._file.exists) {
|
||||
this.status = Ci.nsIEnterprisePolicies.INACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._file.failed) {
|
||||
this.status = Ci.nsIEnterprisePolicies.FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
this.status = Ci.nsIEnterprisePolicies.ACTIVE;
|
||||
this._activatePolicies();
|
||||
},
|
||||
|
||||
_activatePolicies() {
|
||||
let { schema } = Cu.import("resource:///modules/policies/schema.jsm", {});
|
||||
let json = this._file.json;
|
||||
|
||||
for (let policyName of Object.keys(json.policies)) {
|
||||
let policySchema = schema.properties[policyName];
|
||||
let policyParameters = json.policies[policyName];
|
||||
|
||||
if (!policySchema) {
|
||||
log.error(`Unknown policy: ${policyName}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let [parametersAreValid, parsedParameters] =
|
||||
PoliciesValidator.validateAndParseParameters(policyParameters,
|
||||
policySchema);
|
||||
|
||||
if (!parametersAreValid) {
|
||||
log.error(`Invalid parameters specified for ${policyName}.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let policyImpl = Policies[policyName];
|
||||
|
||||
for (let timing of Object.keys(this._callbacks)) {
|
||||
let policyCallback = policyImpl["on" + timing];
|
||||
if (policyCallback) {
|
||||
this._schedulePolicyCallback(
|
||||
timing,
|
||||
policyCallback.bind(null,
|
||||
this, /* the EnterprisePoliciesManager */
|
||||
parsedParameters));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_callbacks: {
|
||||
BeforeAddons: [],
|
||||
ProfileAfterChange: [],
|
||||
BeforeUIStartup: [],
|
||||
AllWindowsRestored: [],
|
||||
},
|
||||
|
||||
_schedulePolicyCallback(timing, callback) {
|
||||
this._callbacks[timing].push(callback);
|
||||
},
|
||||
|
||||
_runPoliciesCallbacks(timing) {
|
||||
let callbacks = this._callbacks[timing];
|
||||
while (callbacks.length > 0) {
|
||||
let callback = callbacks.shift();
|
||||
try {
|
||||
callback();
|
||||
} catch (ex) {
|
||||
log.error("Error running ", callback, `for ${timing}:`, ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async _restart() {
|
||||
if (!Cu.isInAutomation) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisallowedFeatures = {};
|
||||
|
||||
this._status = Ci.nsIEnterprisePolicies.UNINITIALIZED;
|
||||
for (let timing of Object.keys(this._callbacks)) {
|
||||
this._callbacks[timing] = [];
|
||||
}
|
||||
delete Services.ppmm.initialProcessData.policies;
|
||||
Services.ppmm.broadcastAsyncMessage("EnterprisePolicies:Restart", null);
|
||||
|
||||
let { PromiseUtils } = Cu.import("resource://gre/modules/PromiseUtils.jsm",
|
||||
{});
|
||||
|
||||
// Simulate the startup process. This step-by-step is a bit ugly but it
|
||||
// tries to emulate the same behavior as of a normal startup.
|
||||
|
||||
await PromiseUtils.idleDispatch(() => {
|
||||
this.observe(null, "policies-startup", null);
|
||||
});
|
||||
|
||||
await PromiseUtils.idleDispatch(() => {
|
||||
this.observe(null, "profile-after-change", null);
|
||||
});
|
||||
|
||||
await PromiseUtils.idleDispatch(() => {
|
||||
this.observe(null, "final-ui-startup", null);
|
||||
});
|
||||
|
||||
await PromiseUtils.idleDispatch(() => {
|
||||
this.observe(null, "sessionstore-windows-restored", null);
|
||||
});
|
||||
},
|
||||
|
||||
// nsIObserver implementation
|
||||
observe: function BG_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "policies-startup":
|
||||
this._initialize();
|
||||
this._runPoliciesCallbacks("BeforeAddons");
|
||||
break;
|
||||
|
||||
case "profile-after-change":
|
||||
// Before the first set of policy callbacks runs, we must
|
||||
// initialize the service.
|
||||
this._runPoliciesCallbacks("ProfileAfterChange");
|
||||
break;
|
||||
|
||||
case "final-ui-startup":
|
||||
this._runPoliciesCallbacks("BeforeUIStartup");
|
||||
break;
|
||||
|
||||
case "sessionstore-windows-restored":
|
||||
this._runPoliciesCallbacks("AllWindowsRestored");
|
||||
|
||||
// After the last set of policy callbacks ran, notify the test observer.
|
||||
Services.obs.notifyObservers(null,
|
||||
"EnterprisePolicies:AllPoliciesApplied");
|
||||
break;
|
||||
|
||||
case "EnterprisePolicies:Restart":
|
||||
this._restart().then(null, Cu.reportError);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
disallowFeature(feature, neededOnContentProcess = false) {
|
||||
DisallowedFeatures[feature] = true;
|
||||
|
||||
// NOTE: For optimization purposes, only features marked as needed
|
||||
// on content process will be passed onto the child processes.
|
||||
if (neededOnContentProcess) {
|
||||
Services.ppmm.initialProcessData.policies
|
||||
.disallowedFeatures.push(feature);
|
||||
|
||||
if (Services.ppmm.childCount > 1) {
|
||||
// If there has been a content process already initialized, let's
|
||||
// broadcast the newly disallowed feature.
|
||||
Services.ppmm.broadcastAsyncMessage(
|
||||
"EnterprisePolicies:DisallowFeature", {feature}
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ------------------------------
|
||||
// public nsIEnterprisePolicies members
|
||||
// ------------------------------
|
||||
|
||||
_status: Ci.nsIEnterprisePolicies.UNINITIALIZED,
|
||||
|
||||
set status(val) {
|
||||
this._status = val;
|
||||
if (val != Ci.nsIEnterprisePolicies.INACTIVE) {
|
||||
Services.ppmm.initialProcessData.policies = {
|
||||
status: val,
|
||||
disallowedFeatures: [],
|
||||
};
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
get status() {
|
||||
return this._status;
|
||||
},
|
||||
|
||||
isAllowed: function BG_sanitize(feature) {
|
||||
return !(feature in DisallowedFeatures);
|
||||
},
|
||||
};
|
||||
|
||||
let DisallowedFeatures = {};
|
||||
|
||||
function JSONFileReader(file) {
|
||||
this._file = file;
|
||||
this._data = {
|
||||
exists: null,
|
||||
failed: false,
|
||||
json: null,
|
||||
};
|
||||
}
|
||||
|
||||
JSONFileReader.prototype = {
|
||||
get exists() {
|
||||
if (this._data.exists === null) {
|
||||
this.readData();
|
||||
}
|
||||
|
||||
return this._data.exists;
|
||||
},
|
||||
|
||||
get failed() {
|
||||
return this._data.failed;
|
||||
},
|
||||
|
||||
get json() {
|
||||
if (this._data.failed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._data.json === null) {
|
||||
this.readData();
|
||||
}
|
||||
|
||||
return this._data.json;
|
||||
},
|
||||
|
||||
readData() {
|
||||
try {
|
||||
let data = Cu.readUTF8File(this._file);
|
||||
if (data) {
|
||||
this._data.exists = true;
|
||||
this._data.json = JSON.parse(data);
|
||||
} else {
|
||||
this._data.exists = false;
|
||||
}
|
||||
} catch (ex) {
|
||||
if (ex instanceof Components.Exception &&
|
||||
ex.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||
this._data.exists = false;
|
||||
} else if (ex instanceof SyntaxError) {
|
||||
log.error("Error parsing JSON file");
|
||||
this._data.failed = true;
|
||||
} else {
|
||||
log.error("Error reading file");
|
||||
this._data.failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getConfigurationFile() {
|
||||
let configFile = Services.dirsvc.get("XREAppDist", Ci.nsIFile);
|
||||
configFile.append(POLICIES_FILENAME);
|
||||
|
||||
let prefType = Services.prefs.getPrefType(PREF_ALTERNATE_PATH);
|
||||
|
||||
if ((prefType == Services.prefs.PREF_STRING) && !configFile.exists()) {
|
||||
// We only want to use the alternate file path if the file on the install
|
||||
// folder doesn't exist. Otherwise it'd be possible for a user to override
|
||||
// the admin-provided policies by changing the user-controlled prefs.
|
||||
// This pref is only meant for tests, so it's fine to use this extra
|
||||
// synchronous configFile.exists() above.
|
||||
configFile = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsIFile);
|
||||
let alternatePath = Services.prefs.getStringPref(PREF_ALTERNATE_PATH);
|
||||
configFile.initWithPath(alternatePath);
|
||||
}
|
||||
|
||||
return configFile;
|
||||
}
|
||||
|
||||
var components = [EnterprisePoliciesManager];
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
|
@ -0,0 +1,5 @@
|
|||
component {ea4e1414-779b-458b-9d1f-d18e8efbc145} EnterprisePolicies.js process=main
|
||||
contract @mozilla.org/browser/enterprisepolicies;1 {ea4e1414-779b-458b-9d1f-d18e8efbc145} process=main
|
||||
|
||||
component {dc6358f8-d167-4566-bf5b-4350b5e6a7a2} EnterprisePoliciesContent.js process=content
|
||||
contract @mozilla.org/browser/enterprisepolicies;1 {dc6358f8-d167-4566-bf5b-4350b5e6a7a2} process=content
|
|
@ -0,0 +1,91 @@
|
|||
/* 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/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "Enterprise Policies Child",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ==== Start XPCOM Boilerplate ==== \\
|
||||
|
||||
// Factory object
|
||||
const EnterprisePoliciesFactory = {
|
||||
_instance: null,
|
||||
createInstance: function BGSF_createInstance(outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return this._instance == null ?
|
||||
this._instance = new EnterprisePoliciesManagerContent() : this._instance;
|
||||
}
|
||||
};
|
||||
|
||||
// ==== End XPCOM Boilerplate ==== //
|
||||
|
||||
|
||||
function EnterprisePoliciesManagerContent() {
|
||||
let policies = Services.cpmm.initialProcessData.policies;
|
||||
if (policies) {
|
||||
this._status = policies.status;
|
||||
// make a copy of the array so that we can keep adding to it
|
||||
// in a way that is not confusing.
|
||||
this._disallowedFeatures = policies.disallowedFeatures.slice();
|
||||
}
|
||||
|
||||
Services.cpmm.addMessageListener("EnterprisePolicies:DisallowFeature", this);
|
||||
Services.cpmm.addMessageListener("EnterprisePolicies:Restart", this);
|
||||
}
|
||||
|
||||
EnterprisePoliciesManagerContent.prototype = {
|
||||
// for XPCOM
|
||||
classID: Components.ID("{dc6358f8-d167-4566-bf5b-4350b5e6a7a2}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
|
||||
Ci.nsIEnterprisePolicies]),
|
||||
|
||||
// redefine the default factory for XPCOMUtils
|
||||
_xpcom_factory: EnterprisePoliciesFactory,
|
||||
|
||||
_status: Ci.nsIEnterprisePolicies.INACTIVE,
|
||||
|
||||
_disallowedFeatures: [],
|
||||
|
||||
receiveMessage({name, data}) {
|
||||
switch (name) {
|
||||
case "EnterprisePolicies:DisallowFeature":
|
||||
this._disallowedFeatures.push(data.feature);
|
||||
break;
|
||||
|
||||
case "EnterprisePolicies:Restart":
|
||||
this._disallowedFeatures = [];
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
get status() {
|
||||
return this._status;
|
||||
},
|
||||
|
||||
isAllowed(feature) {
|
||||
return !this._disallowedFeatures.includes(feature);
|
||||
}
|
||||
};
|
||||
|
||||
var components = [EnterprisePoliciesManagerContent];
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
|
@ -0,0 +1,38 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "Policies.jsm",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Policies"];
|
||||
|
||||
this.Policies = {
|
||||
"block_about_config": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
if (param == true) {
|
||||
manager.disallowFeature("about:config", true);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
|
@ -0,0 +1,148 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "PoliciesValidator.jsm",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PoliciesValidator"];
|
||||
|
||||
this.PoliciesValidator = {
|
||||
validateAndParseParameters(param, properties) {
|
||||
return validateAndParseParamRecursive(param, properties);
|
||||
}
|
||||
};
|
||||
|
||||
function validateAndParseParamRecursive(param, properties) {
|
||||
if (properties.enum) {
|
||||
if (properties.enum.includes(param)) {
|
||||
return [true, param];
|
||||
}
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
log.debug(`checking @${param}@ for type ${properties.type}`);
|
||||
switch (properties.type) {
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "integer":
|
||||
case "string":
|
||||
case "URL":
|
||||
case "origin":
|
||||
return validateAndParseSimpleParam(param, properties.type);
|
||||
|
||||
case "array":
|
||||
if (!Array.isArray(param)) {
|
||||
log.error("Array expected but not received");
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
let parsedArray = [];
|
||||
for (let item of param) {
|
||||
log.debug(`in array, checking @${item}@ for type ${properties.items.type}`);
|
||||
let [valid, parsedValue] = validateAndParseParamRecursive(item, properties.items);
|
||||
if (!valid) {
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
parsedArray.push(parsedValue);
|
||||
}
|
||||
|
||||
return [true, parsedArray];
|
||||
|
||||
case "object": {
|
||||
if (typeof(param) != "object") {
|
||||
log.error("Object expected but not received");
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
let parsedObj = {};
|
||||
for (let property of Object.keys(properties.properties)) {
|
||||
log.debug(`in object, for property ${property} checking @${param[property]}@ for type ${properties.properties[property].type}`);
|
||||
let [valid, parsedValue] = validateAndParseParamRecursive(param[property], properties.properties[property]);
|
||||
if (!valid) {
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
parsedObj[property] = parsedValue;
|
||||
}
|
||||
|
||||
return [true, parsedObj];
|
||||
}
|
||||
}
|
||||
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
function validateAndParseSimpleParam(param, type) {
|
||||
let valid = false;
|
||||
let parsedParam = param;
|
||||
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "string":
|
||||
valid = (typeof(param) == type);
|
||||
break;
|
||||
|
||||
// integer is an alias to "number" that some JSON schema tools use
|
||||
case "integer":
|
||||
valid = (typeof(param) == "number");
|
||||
break;
|
||||
|
||||
case "origin":
|
||||
if (typeof(param) != "string") {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
parsedParam = Services.io.newURI(param);
|
||||
|
||||
let pathQueryRef = parsedParam.pathQueryRef;
|
||||
// Make sure that "origin" types won't accept full URLs.
|
||||
if (pathQueryRef != "/" && pathQueryRef != "") {
|
||||
valid = false;
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
} catch (ex) {
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case "URL":
|
||||
if (typeof(param) != "string") {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
parsedParam = Services.io.newURI(param);
|
||||
valid = true;
|
||||
} catch (ex) {
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return [valid, parsedParam];
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Enterprise Policies")
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"policies": {
|
||||
"block_about_config": true,
|
||||
"dont_check_default_browser": true,
|
||||
|
||||
"flash_plugin": {
|
||||
"allow": [
|
||||
"https://www.example.com"
|
||||
],
|
||||
|
||||
"block": [
|
||||
"https://www.example.org"
|
||||
]
|
||||
},
|
||||
|
||||
"block_about_profiles": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Enterprise Policies")
|
||||
|
||||
DIRS += [
|
||||
'helpers',
|
||||
'schemas',
|
||||
]
|
||||
|
||||
TEST_DIRS += [
|
||||
'tests'
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'EnterprisePolicies.js',
|
||||
'EnterprisePolicies.manifest',
|
||||
'EnterprisePoliciesContent.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.policies += [
|
||||
'Policies.jsm',
|
||||
'PoliciesValidator.jsm',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'browsercomps'
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"policies": {
|
||||
"$ref": "policies.json"
|
||||
}
|
||||
},
|
||||
"required": ["policies"]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Enterprise Policies")
|
||||
|
||||
EXTRA_PP_JS_MODULES.policies += [
|
||||
'schema.jsm',
|
||||
]
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"block_about_config": {
|
||||
"description": "Blocks access to the about:config page.",
|
||||
"first_available": "60.0",
|
||||
|
||||
"type": "boolean",
|
||||
"enum": [true]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["schema"];
|
||||
|
||||
this.schema =
|
||||
#include policies-schema.json
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/browser-test"
|
||||
]
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
[DEFAULT]
|
||||
prefs =
|
||||
browser.policies.enabled=true
|
||||
support-files =
|
||||
head.js
|
||||
config_simple_policies.json
|
||||
config_broken_json.json
|
||||
|
||||
[browser_policies_broken_json.js]
|
||||
[browser_policies_simple_policies.js]
|
||||
[browser_policies_validate_and_parse_API.js]
|
|
@ -0,0 +1,15 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_clean_slate() {
|
||||
await startWithCleanSlate();
|
||||
});
|
||||
|
||||
add_task(async function test_broken_json() {
|
||||
await setupPolicyEngineWithJson("config_broken_json.json");
|
||||
|
||||
is(Services.policies.status, Ci.nsIEnterprisePolicies.FAILED, "Engine was correctly set to the error state");
|
||||
});
|
|
@ -0,0 +1,101 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_clean_slate() {
|
||||
await startWithCleanSlate();
|
||||
});
|
||||
|
||||
add_task(async function test_simple_policies() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
|
||||
// Initialize the service in the content process, in case it hasn't
|
||||
// already started.
|
||||
Services.policies;
|
||||
});
|
||||
|
||||
let { Policies } = Cu.import("resource:///modules/policies/Policies.jsm", {});
|
||||
|
||||
let policy0Ran = false, policy1Ran = false, policy2Ran = false, policy3Ran = false;
|
||||
|
||||
// Implement functions to handle the four simple policies that will be added
|
||||
// to the schema.
|
||||
Policies.simple_policy0 = {
|
||||
onProfileAfterChange(manager, param) {
|
||||
is(param, true, "Param matches what was passed in config file");
|
||||
policy0Ran = true;
|
||||
}
|
||||
};
|
||||
|
||||
Policies.simple_policy1 = {
|
||||
onProfileAfterChange(manager, param) {
|
||||
is(param, true, "Param matches what was passed in config file");
|
||||
manager.disallowFeature("feature1", /* needed in content process */ true);
|
||||
policy1Ran = true;
|
||||
}
|
||||
};
|
||||
|
||||
Policies.simple_policy2 = {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
is(param, true, "Param matches what was passed in config file");
|
||||
manager.disallowFeature("feature2", /* needed in content process */ false);
|
||||
policy2Ran = true;
|
||||
}
|
||||
};
|
||||
|
||||
Policies.simple_policy3 = {
|
||||
onAllWindowsRestored(manager, param) {
|
||||
is(param, false, "Param matches what was passed in config file");
|
||||
policy3Ran = true;
|
||||
}
|
||||
};
|
||||
|
||||
await setupPolicyEngineWithJson(
|
||||
"config_simple_policies.json",
|
||||
/* custom schema */
|
||||
{
|
||||
properties: {
|
||||
"simple_policy0": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"simple_policy1": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"simple_policy2": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"simple_policy3": {
|
||||
"type": "boolean"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
is(Services.policies.status, Ci.nsIEnterprisePolicies.ACTIVE, "Engine is active");
|
||||
is(Services.policies.isAllowed("feature1"), false, "Dummy feature was disallowed");
|
||||
is(Services.policies.isAllowed("feature2"), false, "Dummy feature was disallowed");
|
||||
|
||||
ok(policy0Ran, "Policy 0 ran correctly through BeforeAddons");
|
||||
ok(policy1Ran, "Policy 1 ran correctly through onProfileAfterChange");
|
||||
ok(policy2Ran, "Policy 2 ran correctly through onBeforeUIStartup");
|
||||
ok(policy3Ran, "Policy 3 ran correctly through onAllWindowsRestored");
|
||||
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
is(Services.policies.isAllowed("feature1"), false, "Correctly disallowed in the content process");
|
||||
// Feature 2 wasn't explictly marked as needed in the content process, so it is not marked
|
||||
// as disallowed there.
|
||||
is(Services.policies.isAllowed("feature2"), true, "Correctly missing in the content process");
|
||||
}
|
||||
});
|
||||
|
||||
delete Policies.simple_policy0;
|
||||
delete Policies.simple_policy1;
|
||||
delete Policies.simple_policy2;
|
||||
delete Policies.simple_policy3;
|
||||
});
|
|
@ -0,0 +1,231 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* This file will test the parameters parsing and validation directly through
|
||||
the PoliciesValidator API.
|
||||
*/
|
||||
|
||||
const { PoliciesValidator } = Cu.import("resource:///modules/policies/PoliciesValidator.jsm", {});
|
||||
|
||||
add_task(async function test_boolean_values() {
|
||||
let schema = {
|
||||
type: "boolean"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(true, schema);
|
||||
ok(valid && parsed === true, "Parsed boolean value correctly");
|
||||
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(false, schema);
|
||||
ok(valid && parsed === false, "Parsed boolean value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("0", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("true", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_number_values() {
|
||||
let schema = {
|
||||
type: "number"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === 1, "Parsed number value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_integer_values() {
|
||||
// Integer is an alias for number
|
||||
let schema = {
|
||||
type: "integer"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed == 1, "Parsed integer value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_string_values() {
|
||||
let schema = {
|
||||
type: "string"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("foobar", schema);
|
||||
ok(valid && parsed == "foobar", "Parsed string value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters(1, schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_URL_values() {
|
||||
let schema = {
|
||||
type: "URL"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("https://www.example.com/foo#bar", schema);
|
||||
ok(valid, "URL is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/foo#bar", "pathQueryRef is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("www.example.com", schema)[0], "Scheme is required for URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_origin_values() {
|
||||
// Origin is a URL that doesn't contain a path/query string (i.e., it's only scheme + host + port)
|
||||
let schema = {
|
||||
type: "origin"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("https://www.example.com", schema);
|
||||
ok(valid, "Origin is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/", "pathQueryRef is corect");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://www.example.com/foobar", schema)[0], "Origin cannot contain a path part");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid origin");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_array_values() {
|
||||
// The types inside an array object must all be the same
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "number"
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters([1, 2, 3], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 3, "array is correct");
|
||||
|
||||
// An empty array is also valid
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters([], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 0, "array is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters([1, true, 3], schema)[0], "Mixed types");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(2, schema)[0], "Type is correct but not in an array");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Object is not an array");
|
||||
});
|
||||
|
||||
add_task(async function test_object_values() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL"
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: "Foo",
|
||||
alias: "Bar"
|
||||
},
|
||||
schema);
|
||||
|
||||
ok(valid, "Object is valid");
|
||||
ok(typeof(parsed) == "object", "parsed in an object");
|
||||
ok(parsed.url instanceof Ci.nsIURI, "types inside the object are also parsed");
|
||||
is(parsed.url.spec, "https://www.example.com/foo#bar", "URL was correctly parsed");
|
||||
is(parsed.title, "Foo", "title was correctly parsed");
|
||||
is(parsed.alias, undefined, "property not described in the schema is not present in the parsed object");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Mismatched type for title");
|
||||
|
||||
ok(!PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "www.example.com",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Invalid URL inside the object");
|
||||
});
|
||||
|
||||
add_task(async function test_array_of_objects() {
|
||||
// This schema is used, for example, for bookmarks
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL",
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(
|
||||
[{
|
||||
url: "https://www.example.com/bookmark1",
|
||||
title: "Foo",
|
||||
},
|
||||
{
|
||||
url: "https://www.example.com/bookmark2",
|
||||
title: "Bar",
|
||||
}],
|
||||
schema);
|
||||
|
||||
ok(valid, "Array is valid");
|
||||
is(parsed.length, 2, "Correct number of items");
|
||||
|
||||
ok(typeof(parsed[0]) == "object" && typeof(parsed[1]) == "object", "Correct objects inside array");
|
||||
|
||||
is(parsed[0].url.spec, "https://www.example.com/bookmark1", "Correct URL for bookmark 1");
|
||||
is(parsed[1].url.spec, "https://www.example.com/bookmark2", "Correct URL for bookmark 2");
|
||||
|
||||
is(parsed[0].title, "Foo", "Correct title for bookmark 1");
|
||||
is(parsed[1].title, "Bar", "Correct title for bookmark 2");
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"policies
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"policies": {
|
||||
"simple_policy0": true,
|
||||
"simple_policy1": true,
|
||||
"simple_policy2": true,
|
||||
"simple_policy3": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
async function setupPolicyEngineWithJson(jsonName, customSchema) {
|
||||
let filePath = getTestFilePath(jsonName ? jsonName : "non-existing-file.json");
|
||||
Services.prefs.setStringPref("browser.policies.alternatePath", filePath);
|
||||
|
||||
let resolve = null;
|
||||
let promise = new Promise((r) => resolve = r);
|
||||
|
||||
Services.obs.addObserver(function observer() {
|
||||
Services.obs.removeObserver(observer, "EnterprisePolicies:AllPoliciesApplied");
|
||||
resolve();
|
||||
}, "EnterprisePolicies:AllPoliciesApplied");
|
||||
|
||||
// Clear any previously used custom schema
|
||||
Cu.unload("resource:///modules/policies/schema.jsm");
|
||||
|
||||
if (customSchema) {
|
||||
let schemaModule = Cu.import("resource:///modules/policies/schema.jsm", {});
|
||||
schemaModule.schema = customSchema;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "EnterprisePolicies:Restart");
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function startWithCleanSlate() {
|
||||
await setupPolicyEngineWithJson("");
|
||||
is(Services.policies.status, Ci.nsIEnterprisePolicies.INACTIVE, "Engine is inactive");
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "General")
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'browser/browser.ini'
|
||||
]
|
|
@ -38,6 +38,7 @@ DIRS += [
|
|||
'customizableui',
|
||||
'dirprovider',
|
||||
'downloads',
|
||||
'enterprisepolicies',
|
||||
'extensions',
|
||||
'feeds',
|
||||
'migration',
|
||||
|
|
|
@ -229,6 +229,7 @@
|
|||
@RESPATH@/components/dom_presentation.xpt
|
||||
@RESPATH@/components/downloads.xpt
|
||||
@RESPATH@/components/editor.xpt
|
||||
@RESPATH@/components/enterprisepolicies.xpt
|
||||
@RESPATH@/components/extensions.xpt
|
||||
@RESPATH@/components/exthandler.xpt
|
||||
@RESPATH@/components/fastfind.xpt
|
||||
|
@ -379,6 +380,9 @@
|
|||
@RESPATH@/browser/components/browser-newtab.xpt
|
||||
@RESPATH@/browser/components/aboutNewTabService.js
|
||||
@RESPATH@/browser/components/NewTabComponents.manifest
|
||||
@RESPATH@/browser/components/EnterprisePolicies.js
|
||||
@RESPATH@/browser/components/EnterprisePoliciesContent.js
|
||||
@RESPATH@/browser/components/EnterprisePolicies.manifest
|
||||
@RESPATH@/components/Downloads.manifest
|
||||
@RESPATH@/components/DownloadLegacy.js
|
||||
@RESPATH@/components/thumbnails.xpt
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Enterprise Policies")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIEnterprisePolicies.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'enterprisepolicies'
|
|
@ -0,0 +1,18 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(6a568972-cc91-4bf5-963e-3768f3319b8a)]
|
||||
interface nsIEnterprisePolicies : nsISupports
|
||||
{
|
||||
const unsigned short UNINITIALIZED = 0;
|
||||
const unsigned short INACTIVE = 1;
|
||||
const unsigned short ACTIVE = 2;
|
||||
const unsigned short FAILED = 3;
|
||||
|
||||
readonly attribute short status;
|
||||
|
||||
bool isAllowed(in ACString feature);
|
||||
};
|
|
@ -30,6 +30,7 @@ DIRS += [
|
|||
'crashmonitor',
|
||||
'diskspacewatcher',
|
||||
'downloads',
|
||||
'enterprisepolicies',
|
||||
'extensions',
|
||||
'filewatcher',
|
||||
'finalizationwitness',
|
||||
|
|
|
@ -122,6 +122,9 @@ if (AppConstants.MOZ_GECKO_PROFILER) {
|
|||
if (AppConstants.MOZ_TOOLKIT_SEARCH) {
|
||||
initTable.search = ["@mozilla.org/browser/search-service;1", "nsIBrowserSearchService"];
|
||||
}
|
||||
if (AppConstants.MOZ_BUILD_APP == "browser") {
|
||||
initTable.policies = ["@mozilla.org/browser/enterprisepolicies;1", "nsIEnterprisePolicies"];
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetters(Services, initTable);
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ function run_test() {
|
|||
if ("nsIAndroidBridge" in Ci) {
|
||||
checkService("androidBridge", Ci.nsIAndroidBridge);
|
||||
}
|
||||
if ("@mozilla.org/browser/enterprisepolicies;1" in Cc) {
|
||||
checkService("policies", Ci.nsIEnterprisePolicies);
|
||||
}
|
||||
|
||||
|
||||
// In xpcshell tests, the "@mozilla.org/xre/app-info;1" component implements
|
||||
// only the nsIXULRuntime interface, but not nsIXULAppInfo. To test the
|
||||
|
|
|
@ -1009,6 +1009,12 @@ nsXREDirProvider::DoStartup()
|
|||
static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
|
||||
obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
|
||||
|
||||
// Initialize the Enterprise Policies service
|
||||
nsCOMPtr<nsIObserver> policies(do_GetService("@mozilla.org/browser/enterprisepolicies;1"));
|
||||
if (policies) {
|
||||
policies->Observe(nullptr, "policies-startup", nullptr);
|
||||
}
|
||||
|
||||
// Init the Extension Manager
|
||||
nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
|
||||
if (em) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче