Bug 1419102 - Make initialization of the Policies manager its own step with a well-defined timing, running before the add-ons manager initializes. r=Mossop
MozReview-Commit-ID: 5zH0kB9WGpW
--- a/browser/components/enterprisepolicies/EnterprisePolicies.js
+++ b/browser/components/enterprisepolicies/EnterprisePolicies.js
@@ -132,16 +132,17 @@ EnterprisePoliciesManager.prototype = {
this, /* the EnterprisePoliciesManager */
parsedParameters));
}
}
}
},
_callbacks: {
+ BeforeAddons: [],
ProfileAfterChange: [],
BeforeUIStartup: [],
AllWindowsRestored: [],
},
_schedulePolicyCallback(timing, callback) {
this._callbacks[timing].push(callback);
},
@@ -153,70 +154,81 @@ EnterprisePoliciesManager.prototype = {
try {
callback();
} catch (ex) {
log.error("Error running ", callback, `for ${timing}:`, ex);
}
}
},
- _restart() {
+ 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);
- // Simulate the startup process. This is ugly but it tries to ensure
- // the same behavior as of a normal startup.
- Services.tm.idleDispatchToMainThread(() => {
- this.observe(null, "profile-after-change", 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);
+ });
- Services.tm.idleDispatchToMainThread(() => {
- this.observe(null, "final-ui-startup", null);
+ await PromiseUtils.idleDispatch(() => {
+ this.observe(null, "profile-after-change", null);
+ });
- Services.tm.idleDispatchToMainThread(() => {
- this.observe(null, "sessionstore-windows-restored", 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._initialize();
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();
+ this._restart().then(null, Cu.reportError);
break;
}
},
disallowFeature(feature, neededOnContentProcess = false) {
DisallowedFeatures[feature] = true;
// NOTE: For optimization purposes, only features marked as needed
--- a/browser/components/enterprisepolicies/EnterprisePolicies.manifest
+++ b/browser/components/enterprisepolicies/EnterprisePolicies.manifest
@@ -1,6 +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
-category app-startup EnterprisePoliciesManager service,@mozilla.org/browser/enterprisepolicies;1 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
--- a/browser/components/enterprisepolicies/tests/browser/browser_policies_simple_policies.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policies_simple_policies.js
@@ -12,20 +12,27 @@ add_task(async function test_simple_poli
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 policy1Ran = false, policy2Ran = false, policy3Ran = false;
+ let policy0Ran = false, policy1Ran = false, policy2Ran = false, policy3Ran = false;
- // Implement functions to handle the three simple policies that will be added
+ // 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;
}
};
@@ -44,16 +51,20 @@ add_task(async function test_simple_poli
}
};
await setupPolicyEngineWithJson(
"config_simple_policies.json",
/* custom schema */
{
properties: {
+ "simple_policy0": {
+ "type": "boolean"
+ },
+
"simple_policy1": {
"type": "boolean"
},
"simple_policy2": {
"type": "boolean"
},
@@ -64,25 +75,27 @@ add_task(async function test_simple_poli
}
}
);
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;
});
--- a/browser/components/enterprisepolicies/tests/browser/config_simple_policies.json
+++ b/browser/components/enterprisepolicies/tests/browser/config_simple_policies.json
@@ -1,7 +1,8 @@
{
"policies": {
+ "simple_policy0": true,
"simple_policy1": true,
"simple_policy2": true,
"simple_policy3": false
}
}
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -1004,16 +1004,21 @@ nsXREDirProvider::DoStartup()
appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
return NS_OK;
}
}
static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
+ 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) {
em->Observe(nullptr, "addons-startup", nullptr);
} else {
NS_WARNING("Failed to create Addons Manager.");
}