Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
"use strict";
6
7
const { XPCOMUtils } = ChromeUtils.import(
9
);
10
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
11
const { AppConstants } = ChromeUtils.import(
13
);
14
15
XPCOMUtils.defineLazyServiceGetters(this, {
16
gCertDB: ["@mozilla.org/security/x509certdb;1", "nsIX509CertDB"],
17
gXulStore: ["@mozilla.org/xul/xulstore;1", "nsIXULStore"],
18
});
19
20
XPCOMUtils.defineLazyModuleGetters(this, {
27
});
28
29
XPCOMUtils.defineLazyGlobalGetters(this, ["File", "FileReader"]);
30
31
const PREF_LOGLEVEL = "browser.policies.loglevel";
32
const BROWSER_DOCUMENT_URL = AppConstants.BROWSER_CHROME_URL;
33
34
XPCOMUtils.defineLazyGetter(this, "log", () => {
35
let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm");
36
return new ConsoleAPI({
37
prefix: "Policies.jsm",
38
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
39
// messages during development. See LOG_LEVELS in Console.jsm for details.
40
maxLogLevel: "error",
41
maxLogLevelPref: PREF_LOGLEVEL,
42
});
43
});
44
45
var EXPORTED_SYMBOLS = ["Policies"];
46
47
/*
48
* ============================
49
* = POLICIES IMPLEMENTATIONS =
50
* ============================
51
*
52
* The Policies object below is where the implementation for each policy
53
* happens. An object for each policy should be defined, containing
54
* callback functions that will be called by the engine.
55
*
56
* See the _callbacks object in EnterprisePolicies.js for the list of
57
* possible callbacks and an explanation of each.
58
*
59
* Each callback will be called with two parameters:
60
* - manager
61
* This is the EnterprisePoliciesManager singleton object from
62
* EnterprisePolicies.js
63
*
64
* - param
65
* The parameter defined for this policy in policies-schema.json.
66
* It will be different for each policy. It could be a boolean,
67
* a string, an array or a complex object. All parameters have
68
* been validated according to the schema, and no unknown
69
* properties will be present on them.
70
*
71
* The callbacks will be bound to their parent policy object.
72
*/
73
var Policies = {
74
"3rdparty": {
75
onBeforeAddons(manager, param) {
76
manager.setExtensionPolicies(param.Extensions);
77
},
78
},
79
80
AppAutoUpdate: {
81
onBeforeUIStartup(manager, param) {
82
// Logic feels a bit reversed here, but it's correct. If AppAutoUpdate is
83
// true, we disallow turning off auto updating, and visa versa.
84
if (param) {
85
manager.disallowFeature("app-auto-updates-off");
86
} else {
87
manager.disallowFeature("app-auto-updates-on");
88
}
89
},
90
},
91
92
AppUpdateURL: {
93
// No implementation needed here. UpdateService.jsm will check for this
94
// policy directly when determining the update URL.
95
},
96
97
Authentication: {
98
onBeforeAddons(manager, param) {
99
let locked = true;
100
if ("Locked" in param) {
101
locked = param.Locked;
102
}
103
104
if ("SPNEGO" in param) {
105
setDefaultPref(
106
"network.negotiate-auth.trusted-uris",
107
param.SPNEGO.join(", "),
108
locked
109
);
110
}
111
if ("Delegated" in param) {
112
setDefaultPref(
113
"network.negotiate-auth.delegation-uris",
114
param.Delegated.join(", "),
115
locked
116
);
117
}
118
if ("NTLM" in param) {
119
setDefaultPref(
120
"network.automatic-ntlm-auth.trusted-uris",
121
param.NTLM.join(", "),
122
locked
123
);
124
}
125
if ("AllowNonFQDN" in param) {
126
if ("NTLM" in param.AllowNonFQDN) {
127
setDefaultPref(
128
"network.automatic-ntlm-auth.allow-non-fqdn",
129
param.AllowNonFQDN.NTLM,
130
locked
131
);
132
}
133
if ("SPNEGO" in param.AllowNonFQDN) {
134
setDefaultPref(
135
"network.negotiate-auth.allow-non-fqdn",
136
param.AllowNonFQDN.SPNEGO,
137
locked
138
);
139
}
140
}
141
if ("AllowProxies" in param) {
142
if ("NTLM" in param.AllowProxies) {
143
setDefaultPref(
144
"network.automatic-ntlm-auth.allow-proxies",
145
param.AllowProxies.NTLM,
146
locked
147
);
148
}
149
if ("SPNEGO" in param.AllowProxies) {
150
setDefaultPref(
151
"network.negotiate-auth.allow-proxies",
152
param.AllowProxies.SPNEGO,
153
locked
154
);
155
}
156
}
157
},
158
},
159
160
BlockAboutAddons: {
161
onBeforeUIStartup(manager, param) {
162
if (param) {
163
blockAboutPage(manager, "about:addons", true);
164
}
165
},
166
},
167
168
BlockAboutConfig: {
169
onBeforeUIStartup(manager, param) {
170
if (param) {
171
blockAboutPage(manager, "about:config");
172
setAndLockPref("devtools.chrome.enabled", false);
173
}
174
},
175
},
176
177
BlockAboutProfiles: {
178
onBeforeUIStartup(manager, param) {
179
if (param) {
180
blockAboutPage(manager, "about:profiles");
181
}
182
},
183
},
184
185
BlockAboutSupport: {
186
onBeforeUIStartup(manager, param) {
187
if (param) {
188
blockAboutPage(manager, "about:support");
189
}
190
},
191
},
192
193
Bookmarks: {
194
onAllWindowsRestored(manager, param) {
195
BookmarksPolicies.processBookmarks(param);
196
},
197
},
198
199
CaptivePortal: {
200
onBeforeAddons(manager, param) {
201
setAndLockPref("network.captive-portal-service.enabled", param);
202
},
203
},
204
205
Certificates: {
206
onBeforeAddons(manager, param) {
207
if ("ImportEnterpriseRoots" in param) {
208
setAndLockPref(
209
"security.enterprise_roots.enabled",
210
param.ImportEnterpriseRoots
211
);
212
}
213
if ("Install" in param) {
214
(async () => {
215
let dirs = [];
216
let platform = AppConstants.platform;
217
if (platform == "win") {
218
dirs = [
219
// Ugly, but there is no official way to get %USERNAME\AppData\Roaming\Mozilla.
220
Services.dirsvc.get("XREUSysExt", Ci.nsIFile).parent,
221
// Even more ugly, but there is no official way to get %USERNAME\AppData\Local\Mozilla.
222
Services.dirsvc.get("DefProfLRt", Ci.nsIFile).parent.parent,
223
];
224
} else if (platform == "macosx" || platform == "linux") {
225
dirs = [
226
// These two keys are named wrong. They return the Mozilla directory.
227
Services.dirsvc.get("XREUserNativeManifests", Ci.nsIFile),
228
Services.dirsvc.get("XRESysNativeManifests", Ci.nsIFile),
229
];
230
}
231
dirs.unshift(Services.dirsvc.get("XREAppDist", Ci.nsIFile));
232
for (let certfilename of param.Install) {
233
let certfile;
234
try {
235
certfile = Cc["@mozilla.org/file/local;1"].createInstance(
236
Ci.nsIFile
237
);
238
certfile.initWithPath(certfilename);
239
} catch (e) {
240
for (let dir of dirs) {
241
certfile = dir.clone();
242
certfile.append(
243
platform == "linux" ? "certificates" : "Certificates"
244
);
245
certfile.append(certfilename);
246
if (certfile.exists()) {
247
break;
248
}
249
}
250
}
251
let file;
252
try {
253
file = await File.createFromNsIFile(certfile);
254
} catch (e) {
255
log.error(`Unable to find certificate - ${certfilename}`);
256
continue;
257
}
258
let reader = new FileReader();
259
reader.onloadend = function() {
260
if (reader.readyState != reader.DONE) {
261
log.error(`Unable to read certificate - ${certfile.path}`);
262
return;
263
}
264
let certFile = reader.result;
265
let certFileArray = [];
266
for (let i = 0; i < certFile.length; i++) {
267
certFileArray.push(certFile.charCodeAt(i));
268
}
269
let cert;
270
try {
271
cert = gCertDB.constructX509(certFileArray);
272
} catch (e) {
273
try {
274
// It might be PEM instead of DER.
275
cert = gCertDB.constructX509FromBase64(pemToBase64(certFile));
276
} catch (ex) {
277
log.error(`Unable to add certificate - ${certfile.path}`);
278
}
279
}
280
if (cert) {
281
if (
282
gCertDB.isCertTrusted(
283
cert,
284
Ci.nsIX509Cert.CA_CERT,
285
Ci.nsIX509CertDB.TRUSTED_SSL
286
)
287
) {
288
// Certificate is already installed.
289
return;
290
}
291
try {
292
gCertDB.addCert(certFile, "CT,CT,");
293
} catch (e) {
294
// It might be PEM instead of DER.
295
gCertDB.addCertFromBase64(pemToBase64(certFile), "CT,CT,");
296
}
297
}
298
};
299
reader.readAsBinaryString(file);
300
}
301
})();
302
}
303
},
304
},
305
306
Cookies: {
307
onBeforeUIStartup(manager, param) {
308
addAllowDenyPermissions("cookie", param.Allow, param.Block);
309
310
if (param.Block) {
311
const hosts = param.Block.map(url => url.hostname)
312
.sort()
313
.join("\n");
314
runOncePerModification("clearCookiesForBlockedHosts", hosts, () => {
315
for (let blocked of param.Block) {
316
Services.cookies.removeCookiesWithOriginAttributes(
317
"{}",
318
blocked.hostname
319
);
320
}
321
});
322
}
323
324
if (
325
param.Default !== undefined ||
326
param.AcceptThirdParty !== undefined ||
327
param.RejectTracker !== undefined ||
328
param.Locked
329
) {
330
const ACCEPT_COOKIES = 0;
331
const REJECT_THIRD_PARTY_COOKIES = 1;
332
const REJECT_ALL_COOKIES = 2;
333
const REJECT_UNVISITED_THIRD_PARTY = 3;
334
const REJECT_TRACKER = 4;
335
336
let newCookieBehavior = ACCEPT_COOKIES;
337
if (param.Default !== undefined && !param.Default) {
338
newCookieBehavior = REJECT_ALL_COOKIES;
339
} else if (param.AcceptThirdParty) {
340
if (param.AcceptThirdParty == "never") {
341
newCookieBehavior = REJECT_THIRD_PARTY_COOKIES;
342
} else if (param.AcceptThirdParty == "from-visited") {
343
newCookieBehavior = REJECT_UNVISITED_THIRD_PARTY;
344
}
345
} else if (param.RejectTracker !== undefined && param.RejectTracker) {
346
newCookieBehavior = REJECT_TRACKER;
347
}
348
349
setDefaultPref(
350
"network.cookie.cookieBehavior",
351
newCookieBehavior,
352
param.Locked
353
);
354
}
355
356
const KEEP_COOKIES_UNTIL_EXPIRATION = 0;
357
const KEEP_COOKIES_UNTIL_END_OF_SESSION = 2;
358
359
if (param.ExpireAtSessionEnd !== undefined || param.Locked) {
360
let newLifetimePolicy = KEEP_COOKIES_UNTIL_EXPIRATION;
361
if (param.ExpireAtSessionEnd) {
362
newLifetimePolicy = KEEP_COOKIES_UNTIL_END_OF_SESSION;
363
}
364
365
setDefaultPref(
366
"network.cookie.lifetimePolicy",
367
newLifetimePolicy,
368
param.Locked
369
);
370
}
371
},
372
},
373
374
DefaultDownloadDirectory: {
375
onBeforeAddons(manager, param) {
376
setDefaultPref("browser.download.dir", replacePathVariables(param));
377
// If a custom download directory is being used, just lock folder list to 2.
378
setAndLockPref("browser.download.folderList", 2);
379
},
380
},
381
382
DisableAppUpdate: {
383
onBeforeAddons(manager, param) {
384
if (param) {
385
manager.disallowFeature("appUpdate");
386
}
387
},
388
},
389
390
DisableBuiltinPDFViewer: {
391
onBeforeAddons(manager, param) {
392
if (param) {
393
setAndLockPref("pdfjs.disabled", true);
394
}
395
},
396
},
397
398
DisabledCiphers: {
399
onBeforeAddons(manager, param) {
400
if ("TLS_DHE_RSA_WITH_AES_128_CBC_SHA" in param) {
401
setAndLockPref("security.ssl3.dhe_rsa_aes_128_sha", false);
402
}
403
if ("TLS_DHE_RSA_WITH_AES_256_CBC_SHA" in param) {
404
setAndLockPref("security.ssl3.dhe_rsa_aes_256_sha", false);
405
}
406
if ("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" in param) {
407
setAndLockPref("security.ssl3.ecdhe_rsa_aes_128_sha", false);
408
}
409
if ("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" in param) {
410
setAndLockPref("security.ssl3.ecdhe_rsa_aes_256_sha", false);
411
}
412
if ("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" in param) {
413
setAndLockPref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", false);
414
}
415
if ("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" in param) {
416
setAndLockPref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", false);
417
}
418
if ("TLS_RSA_WITH_AES_128_CBC_SHA" in param) {
419
setAndLockPref("security.ssl3.rsa_aes_128_sha", false);
420
}
421
if ("TLS_RSA_WITH_AES_256_CBC_SHA" in param) {
422
setAndLockPref("security.ssl3.rsa_aes_256_sha", false);
423
}
424
if ("TLS_RSA_WITH_3DES_EDE_CBC_SHA" in param) {
425
setAndLockPref("security.ssl3.rsa_des_ede3_sha", false);
426
}
427
},
428
},
429
430
DisableDefaultBrowserAgent: {
431
// The implementation of this policy is in the default browser agent itself
432
// (/toolkit/mozapps/defaultagent); we need an entry for it here so that it
433
// shows up in about:policies as a real policy and not as an error.
434
},
435
436
DisableDeveloperTools: {
437
onBeforeAddons(manager, param) {
438
if (param) {
439
setAndLockPref("devtools.policy.disabled", true);
440
setAndLockPref("devtools.chrome.enabled", false);
441
442
manager.disallowFeature("devtools");
443
blockAboutPage(manager, "about:devtools");
444
blockAboutPage(manager, "about:debugging");
445
blockAboutPage(manager, "about:devtools-toolbox");
446
blockAboutPage(manager, "about:profiling");
447
}
448
},
449
},
450
451
DisableFeedbackCommands: {
452
onBeforeUIStartup(manager, param) {
453
if (param) {
454
manager.disallowFeature("feedbackCommands");
455
}
456
},
457
},
458
459
DisableFirefoxAccounts: {
460
onBeforeAddons(manager, param) {
461
if (param) {
462
setAndLockPref("identity.fxaccounts.enabled", false);
463
setAndLockPref("trailhead.firstrun.branches", "nofirstrun");
464
}
465
},
466
},
467
468
DisableFirefoxScreenshots: {
469
onBeforeAddons(manager, param) {
470
if (param) {
471
setAndLockPref("extensions.screenshots.disabled", true);
472
}
473
},
474
},
475
476
DisableFirefoxStudies: {
477
onBeforeAddons(manager, param) {
478
if (param) {
479
manager.disallowFeature("Shield");
480
setAndLockPref(
481
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
482
false
483
);
484
setAndLockPref(
485
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
486
false
487
);
488
}
489
},
490
},
491
492
DisableForgetButton: {
493
onProfileAfterChange(manager, param) {
494
if (param) {
495
setAndLockPref("privacy.panicButton.enabled", false);
496
}
497
},
498
},
499
500
DisableFormHistory: {
501
onBeforeUIStartup(manager, param) {
502
if (param) {
503
setAndLockPref("browser.formfill.enable", false);
504
}
505
},
506
},
507
508
DisableMasterPasswordCreation: {
509
onBeforeUIStartup(manager, param) {
510
if (param) {
511
manager.disallowFeature("createMasterPassword");
512
}
513
},
514
},
515
516
DisablePasswordReveal: {
517
onBeforeUIStartup(manager, param) {
518
if (param) {
519
manager.disallowFeature("passwordReveal");
520
}
521
},
522
},
523
524
DisablePocket: {
525
onBeforeAddons(manager, param) {
526
if (param) {
527
setAndLockPref("extensions.pocket.enabled", false);
528
}
529
},
530
},
531
532
DisablePrivateBrowsing: {
533
onBeforeAddons(manager, param) {
534
if (param) {
535
manager.disallowFeature("privatebrowsing");
536
blockAboutPage(manager, "about:privatebrowsing", true);
537
setAndLockPref("browser.privatebrowsing.autostart", false);
538
}
539
},
540
},
541
542
DisableProfileImport: {
543
onBeforeUIStartup(manager, param) {
544
if (param) {
545
manager.disallowFeature("profileImport");
546
setAndLockPref(
547
"browser.newtabpage.activity-stream.migrationExpired",
548
true
549
);
550
}
551
},
552
},
553
554
DisableProfileRefresh: {
555
onBeforeUIStartup(manager, param) {
556
if (param) {
557
manager.disallowFeature("profileRefresh");
558
setAndLockPref("browser.disableResetPrompt", true);
559
}
560
},
561
},
562
563
DisableSafeMode: {
564
onBeforeUIStartup(manager, param) {
565
if (param) {
566
manager.disallowFeature("safeMode");
567
}
568
},
569
},
570
571
DisableSecurityBypass: {
572
onBeforeUIStartup(manager, param) {
573
if ("InvalidCertificate" in param) {
574
setAndLockPref(
575
"security.certerror.hideAddException",
576
param.InvalidCertificate
577
);
578
}
579
580
if ("SafeBrowsing" in param) {
581
setAndLockPref(
582
"browser.safebrowsing.allowOverride",
583
!param.SafeBrowsing
584
);
585
}
586
},
587
},
588
589
DisableSetDesktopBackground: {
590
onBeforeUIStartup(manager, param) {
591
if (param) {
592
manager.disallowFeature("setDesktopBackground");
593
}
594
},
595
},
596
597
DisableSystemAddonUpdate: {
598
onBeforeAddons(manager, param) {
599
if (param) {
600
manager.disallowFeature("SysAddonUpdate");
601
}
602
},
603
},
604
605
DisableTelemetry: {
606
onBeforeAddons(manager, param) {
607
if (param) {
608
setAndLockPref("datareporting.healthreport.uploadEnabled", false);
609
setAndLockPref("datareporting.policy.dataSubmissionEnabled", false);
610
blockAboutPage(manager, "about:telemetry");
611
}
612
},
613
},
614
615
DisplayBookmarksToolbar: {
616
onBeforeUIStartup(manager, param) {
617
let value = (!param).toString();
618
// This policy is meant to change the default behavior, not to force it.
619
// If this policy was alreay applied and the user chose to re-hide the
620
// bookmarks toolbar, do not show it again.
621
runOncePerModification("displayBookmarksToolbar", value, () => {
622
gXulStore.setValue(
623
BROWSER_DOCUMENT_URL,
624
"PersonalToolbar",
625
"collapsed",
626
value
627
);
628
});
629
},
630
},
631
632
DisplayMenuBar: {
633
onBeforeUIStartup(manager, param) {
634
let value;
635
if (
636
typeof param === "boolean" ||
637
param == "default-on" ||
638
param == "default-off"
639
) {
640
switch (param) {
641
case "default-on":
642
value = "false";
643
break;
644
case "default-off":
645
value = "true";
646
break;
647
default:
648
value = (!param).toString();
649
break;
650
}
651
// This policy is meant to change the default behavior, not to force it.
652
// If this policy was already applied and the user chose to re-hide the
653
// menu bar, do not show it again.
654
runOncePerModification("displayMenuBar", value, () => {
655
gXulStore.setValue(
656
BROWSER_DOCUMENT_URL,
657
"toolbar-menubar",
658
"autohide",
659
value
660
);
661
});
662
} else {
663
switch (param) {
664
case "always":
665
value = "false";
666
break;
667
case "never":
668
// Make sure Alt key doesn't show the menubar
669
setAndLockPref("ui.key.menuAccessKeyFocuses", false);
670
value = "true";
671
break;
672
}
673
gXulStore.setValue(
674
BROWSER_DOCUMENT_URL,
675
"toolbar-menubar",
676
"autohide",
677
value
678
);
679
manager.disallowFeature("hideShowMenuBar");
680
}
681
},
682
},
683
684
DNSOverHTTPS: {
685
onBeforeAddons(manager, param) {
686
let locked = false;
687
if ("Locked" in param) {
688
locked = param.Locked;
689
}
690
if ("Enabled" in param) {
691
let mode = param.Enabled ? 2 : 5;
692
setDefaultPref("network.trr.mode", mode, locked);
693
}
694
if ("ProviderURL" in param) {
695
setDefaultPref("network.trr.uri", param.ProviderURL.href, locked);
696
}
697
if ("ExcludedDomains" in param) {
698
setDefaultPref(
699
"network.trr.excluded-domains",
700
param.ExcludedDomains.join(","),
701
locked
702
);
703
}
704
},
705
},
706
707
DontCheckDefaultBrowser: {
708
onBeforeUIStartup(manager, param) {
709
setAndLockPref("browser.shell.checkDefaultBrowser", !param);
710
},
711
},
712
713
DownloadDirectory: {
714
onBeforeAddons(manager, param) {
715
setAndLockPref("browser.download.dir", replacePathVariables(param));
716
// If a custom download directory is being used, just lock folder list to 2.
717
setAndLockPref("browser.download.folderList", 2);
718
// Per Chrome spec, user can't choose to download every time
719
// if this is set.
720
setAndLockPref("browser.download.useDownloadDir", true);
721
},
722
},
723
724
EnableTrackingProtection: {
725
onBeforeUIStartup(manager, param) {
726
if (param.Value) {
727
setDefaultPref(
728
"privacy.trackingprotection.enabled",
729
true,
730
param.Locked
731
);
732
setDefaultPref(
733
"privacy.trackingprotection.pbmode.enabled",
734
true,
735
param.Locked
736
);
737
} else {
738
setAndLockPref("privacy.trackingprotection.enabled", false);
739
setAndLockPref("privacy.trackingprotection.pbmode.enabled", false);
740
}
741
if ("Cryptomining" in param) {
742
setDefaultPref(
743
"privacy.trackingprotection.cryptomining.enabled",
744
param.Cryptomining,
745
param.Locked
746
);
747
}
748
if ("Fingerprinting" in param) {
749
setDefaultPref(
750
"privacy.trackingprotection.fingerprinting.enabled",
751
param.Fingerprinting,
752
param.Locked
753
);
754
}
755
if ("Exceptions" in param) {
756
addAllowDenyPermissions("trackingprotection", param.Exceptions);
757
}
758
},
759
},
760
761
Extensions: {
762
onBeforeUIStartup(manager, param) {
763
let uninstallingPromise = Promise.resolve();
764
if ("Uninstall" in param) {
765
uninstallingPromise = runOncePerModification(
766
"extensionsUninstall",
767
JSON.stringify(param.Uninstall),
768
async () => {
769
// If we're uninstalling add-ons, re-run the extensionsInstall runOnce even if it hasn't
770
// changed, which will allow add-ons to be updated.
771
Services.prefs.clearUserPref(
772
"browser.policies.runOncePerModification.extensionsInstall"
773
);
774
let addons = await AddonManager.getAddonsByIDs(param.Uninstall);
775
for (let addon of addons) {
776
if (addon) {
777
try {
778
await addon.uninstall();
779
} catch (e) {
780
// This can fail for add-ons that can't be uninstalled.
781
log.debug(`Add-on ID (${addon.id}) couldn't be uninstalled.`);
782
}
783
}
784
}
785
}
786
);
787
}
788
if ("Install" in param) {
789
runOncePerModification(
790
"extensionsInstall",
791
JSON.stringify(param.Install),
792
async () => {
793
await uninstallingPromise;
794
for (let location of param.Install) {
795
let uri;
796
try {
797
// We need to try as a file first because
798
// Windows paths are valid URIs.
799
// This is done for legacy support (old API)
800
let xpiFile = new FileUtils.File(location);
801
uri = Services.io.newFileURI(xpiFile);
802
} catch (e) {
803
uri = Services.io.newURI(location);
804
}
805
installAddonFromURL(uri.spec);
806
}
807
}
808
);
809
}
810
if ("Locked" in param) {
811
for (let ID of param.Locked) {
812
manager.disallowFeature(`uninstall-extension:${ID}`);
813
manager.disallowFeature(`disable-extension:${ID}`);
814
}
815
}
816
},
817
},
818
819
ExtensionSettings: {
820
onBeforeAddons(manager, param) {
821
try {
822
manager.setExtensionSettings(param);
823
} catch (e) {
824
log.error("Invalid ExtensionSettings");
825
}
826
},
827
async onBeforeUIStartup(manager, param) {
828
let extensionSettings = param;
829
let blockAllExtensions = false;
830
if ("*" in extensionSettings) {
831
if (
832
"installation_mode" in extensionSettings["*"] &&
833
extensionSettings["*"].installation_mode == "blocked"
834
) {
835
blockAllExtensions = true;
836
// Turn off discovery pane in about:addons
837
setAndLockPref("extensions.getAddons.showPane", false);
838
// Turn off recommendations
839
setAndLockPref(
840
"extensions.htmlaboutaddons.recommendations.enable",
841
false
842
);
843
// Block about:debugging
844
blockAboutPage(manager, "about:debugging");
845
}
846
}
847
let addons = await AddonManager.getAllAddons();
848
let allowedExtensions = [];
849
for (let extensionID in extensionSettings) {
850
if (extensionID == "*") {
851
// Ignore global settings
852
continue;
853
}
854
if ("installation_mode" in extensionSettings[extensionID]) {
855
if (
856
extensionSettings[extensionID].installation_mode ==
857
"force_installed" ||
858
extensionSettings[extensionID].installation_mode ==
859
"normal_installed"
860
) {
861
if (!extensionSettings[extensionID].install_url) {
862
throw new Error(`Missing install_url for ${extensionID}`);
863
}
864
if (!addons.find(addon => addon.id == extensionID)) {
865
installAddonFromURL(
866
extensionSettings[extensionID].install_url,
867
extensionID
868
);
869
}
870
manager.disallowFeature(`uninstall-extension:${extensionID}`);
871
if (
872
extensionSettings[extensionID].installation_mode ==
873
"force_installed"
874
) {
875
manager.disallowFeature(`disable-extension:${extensionID}`);
876
}
877
allowedExtensions.push(extensionID);
878
} else if (
879
extensionSettings[extensionID].installation_mode == "allowed"
880
) {
881
allowedExtensions.push(extensionID);
882
} else if (
883
extensionSettings[extensionID].installation_mode == "blocked"
884
) {
885
if (addons.find(addon => addon.id == extensionID)) {
886
// Can't use the addon from getActiveAddons since it doesn't have uninstall.
887
let addon = await AddonManager.getAddonByID(extensionID);
888
try {
889
await addon.uninstall();
890
} catch (e) {
891
// This can fail for add-ons that can't be uninstalled.
892
log.debug(`Add-on ID (${addon.id}) couldn't be uninstalled.`);
893
}
894
}
895
}
896
}
897
}
898
if (blockAllExtensions) {
899
for (let addon of addons) {
900
if (
901
addon.isSystem ||
902
addon.isBuiltin ||
903
!(addon.scope & AddonManager.SCOPE_PROFILE)
904
) {
905
continue;
906
}
907
if (!allowedExtensions.includes(addon.id)) {
908
try {
909
// Can't use the addon from getActiveAddons since it doesn't have uninstall.
910
let addonToUninstall = await AddonManager.getAddonByID(addon.id);
911
await addonToUninstall.uninstall();
912
} catch (e) {
913
// This can fail for add-ons that can't be uninstalled.
914
log.debug(`Add-on ID (${addon.id}) couldn't be uninstalled.`);
915
}
916
}
917
}
918
}
919
},
920
},
921
922
ExtensionUpdate: {
923
onBeforeAddons(manager, param) {
924
if (!param) {
925
setAndLockPref("extensions.update.enabled", param);
926
}
927
},
928
},
929
930
FirefoxHome: {
931
onBeforeAddons(manager, param) {
932
let locked = param.Locked || false;
933
if ("Search" in param) {
934
setDefaultPref(
935
"browser.newtabpage.activity-stream.showSearch",
936
param.Search,
937
locked
938
);
939
}
940
if ("TopSites" in param) {
941
setDefaultPref(
942
"browser.newtabpage.activity-stream.feeds.topsites",
943
param.TopSites,
944
locked
945
);
946
}
947
if ("Highlights" in param) {
948
setDefaultPref(
949
"browser.newtabpage.activity-stream.feeds.section.highlights",
950
param.Highlights,
951
locked
952
);
953
}
954
if ("Pocket" in param) {
955
setDefaultPref(
956
"browser.newtabpage.activity-stream.feeds.section.topstories",
957
param.Pocket,
958
locked
959
);
960
}
961
if ("Snippets" in param) {
962
setDefaultPref(
963
"browser.newtabpage.activity-stream.feeds.snippets",
964
param.Snippets,
965
locked
966
);
967
}
968
},
969
},
970
971
FlashPlugin: {
972
onBeforeUIStartup(manager, param) {
973
addAllowDenyPermissions("plugin:flash", param.Allow, param.Block);
974
975
const FLASH_NEVER_ACTIVATE = 0;
976
const FLASH_ASK_TO_ACTIVATE = 1;
977
978
let flashPrefVal;
979
if (param.Default === undefined || param.Default) {
980
flashPrefVal = FLASH_ASK_TO_ACTIVATE;
981
} else {
982
flashPrefVal = FLASH_NEVER_ACTIVATE;
983
}
984
if (param.Locked) {
985
setAndLockPref("plugin.state.flash", flashPrefVal);
986
} else if (param.Default !== undefined) {
987
setDefaultPref("plugin.state.flash", flashPrefVal);
988
}
989
},
990
},
991
992
HardwareAcceleration: {
993
onBeforeAddons(manager, param) {
994
if (!param) {
995
setAndLockPref("layers.acceleration.disabled", true);
996
}
997
},
998
},
999
1000
Homepage: {
1001
onBeforeUIStartup(manager, param) {
1002
// |homepages| will be a string containing a pipe-separated ('|') list of
1003
// URLs because that is what the "Home page" section of about:preferences
1004
// (and therefore what the pref |browser.startup.homepage|) accepts.
1005
if (param.URL) {
1006
let homepages = param.URL.href;
1007
if (param.Additional && param.Additional.length) {
1008
homepages += "|" + param.Additional.map(url => url.href).join("|");
1009
}
1010
setDefaultPref("browser.startup.homepage", homepages, param.Locked);
1011
if (param.Locked) {
1012
setAndLockPref(
1013
"pref.browser.homepage.disable_button.current_page",
1014
true
1015
);
1016
setAndLockPref(
1017
"pref.browser.homepage.disable_button.bookmark_page",
1018
true
1019
);
1020
setAndLockPref(
1021
"pref.browser.homepage.disable_button.restore_default",
1022
true
1023
);
1024
} else {
1025
// Clear out old run once modification that is no longer used.
1026
clearRunOnceModification("setHomepage");
1027
}
1028
}
1029
if (param.StartPage) {
1030
let prefValue;
1031
switch (param.StartPage) {
1032
case "none":
1033
prefValue = 0;
1034
break;
1035
case "homepage":
1036
prefValue = 1;
1037
break;
1038
case "previous-session":
1039
prefValue = 3;
1040
break;
1041
}
1042
setDefaultPref("browser.startup.page", prefValue, param.Locked);
1043
}
1044
},
1045
},
1046
1047
InstallAddonsPermission: {
1048
onBeforeUIStartup(manager, param) {
1049
if ("Allow" in param) {
1050
addAllowDenyPermissions("install", param.Allow, null);
1051
}
1052
if ("Default" in param) {
1053
setAndLockPref("xpinstall.enabled", param.Default);
1054
if (!param.Default) {
1055
blockAboutPage(manager, "about:debugging");
1056
setAndLockPref(
1057
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
1058
false
1059
);
1060
setAndLockPref(
1061
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
1062
false
1063
);
1064
manager.disallowFeature("xpinstall");
1065
}
1066
}
1067
},
1068
},
1069
1070
LegacyProfiles: {
1071
// Handled in nsToolkitProfileService.cpp (Windows only)
1072
},
1073
1074
LocalFileLinks: {
1075
onBeforeAddons(manager, param) {
1076
// If there are existing capabilities, lock them with the policy pref.
1077
let policyNames = Services.prefs
1078
.getCharPref("capability.policy.policynames", "")
1079
.split(" ");
1080
policyNames.push("localfilelinks_policy");
1081
setAndLockPref("capability.policy.policynames", policyNames.join(" "));
1082
setAndLockPref(
1083
"capability.policy.localfilelinks_policy.checkloaduri.enabled",
1084
"allAccess"
1085
);
1086
setAndLockPref(
1087
"capability.policy.localfilelinks_policy.sites",
1088
param.join(" ")
1089
);
1090
},
1091
},
1092
1093
NetworkPrediction: {
1094
onBeforeAddons(manager, param) {
1095
setAndLockPref("network.dns.disablePrefetch", !param);
1096
setAndLockPref("network.dns.disablePrefetchFromHTTPS", !param);
1097
},
1098
},
1099
1100
NewTabPage: {
1101
onBeforeAddons(manager, param) {
1102
setAndLockPref("browser.newtabpage.enabled", param);
1103
},
1104
},
1105
1106
NoDefaultBookmarks: {
1107
onProfileAfterChange(manager, param) {
1108
if (param) {
1109
manager.disallowFeature("defaultBookmarks");
1110
}
1111
},
1112
},
1113
1114
OfferToSaveLogins: {
1115
onBeforeUIStartup(manager, param) {
1116
setAndLockPref("signon.rememberSignons", param);
1117
},
1118
},
1119
1120
OfferToSaveLoginsDefault: {
1121
onBeforeUIStartup(manager, param) {
1122
setDefaultPref("signon.rememberSignons", param);
1123
},
1124
},
1125
1126
OverrideFirstRunPage: {
1127
onProfileAfterChange(manager, param) {
1128
let url = param ? param.href : "";
1129
setAndLockPref("startup.homepage_welcome_url", url);
1130
setAndLockPref("trailhead.firstrun.branches", "nofirstrun");
1131
},
1132
},
1133
1134
OverridePostUpdatePage: {
1135
onProfileAfterChange(manager, param) {
1136
let url = param ? param.href : "";
1137
setAndLockPref("startup.homepage_override_url", url);
1138
// The pref startup.homepage_override_url is only used
1139
// as a fallback when the update.xml file hasn't provided
1140
// a specific post-update URL.
1141
manager.disallowFeature("postUpdateCustomPage");
1142
},
1143
},
1144
1145
PasswordManagerEnabled: {
1146
onBeforeUIStartup(manager, param) {
1147
if (!param) {
1148
blockAboutPage(manager, "about:logins", true);
1149
gBlockedChromePages.push("passwordManager.xhtml");
1150
setAndLockPref("pref.privacy.disable_button.view_passwords", true);
1151
}
1152
setAndLockPref("signon.rememberSignons", param);
1153
},
1154
},
1155
1156
Permissions: {
1157
onBeforeUIStartup(manager, param) {
1158
if (param.Camera) {
1159
addAllowDenyPermissions(
1160
"camera",
1161
param.Camera.Allow,
1162
param.Camera.Block
1163
);
1164
setDefaultPermission("camera", param.Camera);
1165
}
1166
1167
if (param.Microphone) {
1168
addAllowDenyPermissions(
1169
"microphone",
1170
param.Microphone.Allow,
1171
param.Microphone.Block
1172
);
1173
setDefaultPermission("microphone", param.Microphone);
1174
}
1175
1176
if (param.Autoplay) {
1177
addAllowDenyPermissions(
1178
"autoplay-media",
1179
param.Autoplay.Allow,
1180
param.Autoplay.Block
1181
);
1182
if ("Default" in param.Autoplay) {
1183
let prefValue;
1184
switch (param.Autoplay.Default) {
1185
case "allow-audio-video":
1186
prefValue = 0;
1187
break;
1188
case "block-audio":
1189
prefValue = 1;
1190
break;
1191
case "block-audio-video":
1192
prefValue = 5;
1193
break;
1194
}
1195
setDefaultPref(
1196
"media.autoplay.default",
1197
prefValue,
1198
param.Autoplay.Locked
1199
);
1200
}
1201
}
1202
1203
if (param.Location) {
1204
addAllowDenyPermissions(
1205
"geo",
1206
param.Location.Allow,
1207
param.Location.Block
1208
);
1209
setDefaultPermission("geo", param.Location);
1210
}
1211
1212
if (param.Notifications) {
1213
addAllowDenyPermissions(
1214
"desktop-notification",
1215
param.Notifications.Allow,
1216
param.Notifications.Block
1217
);
1218
setDefaultPermission("desktop-notification", param.Notifications);
1219
}
1220
},
1221
},
1222
1223
PopupBlocking: {
1224
onBeforeUIStartup(manager, param) {
1225
addAllowDenyPermissions("popup", param.Allow, null);
1226
1227
if (param.Locked) {
1228
let blockValue = true;
1229
if (param.Default !== undefined && !param.Default) {
1230
blockValue = false;
1231
}
1232
setAndLockPref("dom.disable_open_during_load", blockValue);
1233
} else if (param.Default !== undefined) {
1234
setDefaultPref("dom.disable_open_during_load", !!param.Default);
1235
}
1236
},
1237
},
1238
1239
Preferences: {
1240
onBeforeAddons(manager, param) {
1241
for (let preference in param) {
1242
setAndLockPref(preference, param[preference]);
1243
}
1244
},
1245
},
1246
1247
PromptForDownloadLocation: {
1248
onBeforeAddons(manager, param) {
1249
setAndLockPref("browser.download.useDownloadDir", !param);
1250
},
1251
},
1252
1253
Proxy: {
1254
onBeforeAddons(manager, param) {
1255
if (param.Locked) {
1256
manager.disallowFeature("changeProxySettings");
1257
ProxyPolicies.configureProxySettings(param, setAndLockPref);
1258
} else {
1259
ProxyPolicies.configureProxySettings(param, setDefaultPref);
1260
}
1261
},
1262
},
1263
1264
RequestedLocales: {
1265
onBeforeAddons(manager, param) {
1266
if (Array.isArray(param)) {
1267
Services.locale.requestedLocales = param;
1268
} else if (param) {
1269
Services.locale.requestedLocales = param.split(",");
1270
} else {
1271
Services.locale.requestedLocales = [];
1272
}
1273
},
1274
},
1275
1276
SanitizeOnShutdown: {
1277
onBeforeUIStartup(manager, param) {
1278
if (typeof param === "boolean") {
1279
setAndLockPref("privacy.sanitize.sanitizeOnShutdown", param);
1280
if (param) {
1281
setAndLockPref("privacy.clearOnShutdown.cache", true);
1282
setAndLockPref("privacy.clearOnShutdown.cookies", true);
1283
setAndLockPref("privacy.clearOnShutdown.downloads", true);
1284
setAndLockPref("privacy.clearOnShutdown.formdata", true);
1285
setAndLockPref("privacy.clearOnShutdown.history", true);
1286
setAndLockPref("privacy.clearOnShutdown.sessions", true);
1287
setAndLockPref("privacy.clearOnShutdown.siteSettings", true);
1288
setAndLockPref("privacy.clearOnShutdown.offlineApps", true);
1289
}
1290
} else {
1291
let locked = true;
1292
// Needed to preserve original behavior in perpetuity.
1293
let lockDefaultPrefs = true;
1294
if ("Locked" in param) {
1295
locked = param.Locked;
1296
lockDefaultPrefs = false;
1297
}
1298
setDefaultPref("privacy.sanitize.sanitizeOnShutdown", true, locked);
1299
if ("Cache" in param) {
1300
setDefaultPref("privacy.clearOnShutdown.cache", param.Cache, locked);
1301
} else {
1302
setDefaultPref(
1303
"privacy.clearOnShutdown.cache",
1304
false,
1305
lockDefaultPrefs
1306
);
1307
}
1308
if ("Cookies" in param) {
1309
setDefaultPref(
1310
"privacy.clearOnShutdown.cookies",
1311
param.Cookies,
1312
locked
1313
);
1314
} else {
1315
setDefaultPref(
1316
"privacy.clearOnShutdown.cookies",
1317
false,
1318
lockDefaultPrefs
1319
);
1320
}
1321
if ("Downloads" in param) {
1322
setDefaultPref(
1323
"privacy.clearOnShutdown.downloads",
1324
param.Downloads,
1325
locked
1326
);
1327
} else {
1328
setDefaultPref(
1329
"privacy.clearOnShutdown.downloads",
1330
false,
1331
lockDefaultPrefs
1332
);
1333
}
1334
if ("FormData" in param) {
1335
setDefaultPref(
1336
"privacy.clearOnShutdown.formdata",
1337
param.FormData,
1338
locked
1339
);
1340
} else {
1341
setDefaultPref(
1342
"privacy.clearOnShutdown.formdata",
1343
false,
1344
lockDefaultPrefs
1345
);
1346
}
1347
if ("History" in param) {
1348
setDefaultPref(
1349
"privacy.clearOnShutdown.history",
1350
param.History,
1351
locked
1352
);
1353
} else {
1354
setDefaultPref(
1355
"privacy.clearOnShutdown.history",
1356
false,
1357
lockDefaultPrefs
1358
);
1359
}
1360
if ("Sessions" in param) {
1361
setDefaultPref(
1362
"privacy.clearOnShutdown.sessions",
1363
param.Sessions,
1364
locked
1365
);
1366
} else {
1367
setDefaultPref(
1368
"privacy.clearOnShutdown.sessions",
1369
false,
1370
lockDefaultPrefs
1371
);
1372
}
1373
if ("SiteSettings" in param) {
1374
setDefaultPref(
1375
"privacy.clearOnShutdown.siteSettings",
1376
param.SiteSettings,
1377
locked
1378
);
1379
}
1380
if ("OfflineApps" in param) {
1381
setDefaultPref(
1382
"privacy.clearOnShutdown.offlineApps",
1383
param.OfflineApps,
1384
locked
1385
);
1386
}
1387
}
1388
},
1389
},
1390
1391
SearchBar: {
1392
onAllWindowsRestored(manager, param) {
1393
// This policy is meant to change the default behavior, not to force it.
1394
// If this policy was already applied and the user chose move the search
1395
// bar, don't move it again.
1396
runOncePerModification("searchInNavBar", param, () => {
1397
if (param == "separate") {
1398
CustomizableUI.addWidgetToArea(
1399
"search-container",
1400
CustomizableUI.AREA_NAVBAR,
1401
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1
1402
);
1403
} else if (param == "unified") {
1404
CustomizableUI.removeWidgetFromArea("search-container");
1405
}
1406
});
1407
},
1408
},
1409
1410
SearchEngines: {
1411
onBeforeUIStartup(manager, param) {
1412
if (param.PreventInstalls) {
1413
manager.disallowFeature("installSearchEngine", true);
1414
}
1415
},
1416
onAllWindowsRestored(manager, param) {
1417
Services.search.init().then(async () => {
1418
if (param.Remove) {
1419
// Only rerun if the list of engine names has changed.
1420
await runOncePerModification(
1421
"removeSearchEngines",
1422
JSON.stringify(param.Remove),
1423
async function() {
1424
for (let engineName of param.Remove) {
1425
let engine = Services.search.getEngineByName(engineName);
1426
if (engine) {
1427
try {
1428
await Services.search.removeEngine(engine);
1429
} catch (ex) {
1430
log.error("Unable to remove the search engine", ex);
1431
}
1432
}
1433
}
1434
}
1435
);
1436
}
1437
if (param.Add) {
1438
// Only rerun if the list of engine names has changed.
1439
let engineNameList = param.Add.map(engine => engine.Name);
1440
await runOncePerModification(
1441
"addSearchEngines",
1442
JSON.stringify(engineNameList),
1443
async function() {
1444
for (let newEngine of param.Add) {
1445
let newEngineParameters = {
1446
template: newEngine.URLTemplate,
1447
iconURL: newEngine.IconURL ? newEngine.IconURL.href : null,
1448
alias: newEngine.Alias,
1449
description: newEngine.Description,
1450
method: newEngine.Method,
1451
postData: newEngine.PostData,
1452
suggestURL: newEngine.SuggestURLTemplate,
1453
extensionID: "set-via-policy",
1454
queryCharset: "UTF-8",
1455
};
1456
try {
1457
await Services.search.addEngineWithDetails(
1458
newEngine.Name,
1459
newEngineParameters
1460
);
1461
} catch (ex) {
1462
log.error("Unable to add search engine", ex);
1463
}
1464
}
1465
}
1466
);
1467
}
1468
if (param.Default) {
1469
await runOncePerModification(
1470
"setDefaultSearchEngine",
1471
param.Default,
1472
async () => {
1473
let defaultEngine;
1474
try {
1475
defaultEngine = Services.search.getEngineByName(param.Default);
1476
if (!defaultEngine) {
1477
throw new Error("No engine by that name could be found");
1478
}
1479
} catch (ex) {
1480
log.error(
1481
`Search engine lookup failed when attempting to set ` +
1482
`the default engine. Requested engine was ` +
1483
`"${param.Default}".`,
1484
ex
1485
);
1486
}
1487
if (defaultEngine) {
1488
try {
1489
await Services.search.setDefault(defaultEngine);
1490
} catch (ex) {
1491
log.error("Unable to set the default search engine", ex);
1492
}
1493
}
1494
}
1495
);
1496
}
1497
if (param.DefaultPrivate) {
1498
await runOncePerModification(
1499
"setDefaultPrivateSearchEngine",
1500
param.DefaultPrivate,
1501
async () => {
1502
let defaultPrivateEngine;
1503
try {
1504
defaultPrivateEngine = Services.search.getEngineByName(
1505
param.DefaultPrivate
1506
);
1507
if (!defaultPrivateEngine) {
1508
throw new Error("No engine by that name could be found");
1509
}
1510
} catch (ex) {
1511
log.error(
1512
`Search engine lookup failed when attempting to set ` +
1513
`the default private engine. Requested engine was ` +
1514
`"${param.DefaultPrivate}".`,
1515
ex
1516
);
1517
}
1518
if (defaultPrivateEngine) {
1519
try {
1520
await Services.search.setDefaultPrivate(defaultPrivateEngine);
1521
} catch (ex) {
1522
log.error(
1523
"Unable to set the default private search engine",
1524
ex
1525
);
1526
}
1527
}
1528
}
1529
);
1530
}
1531
});
1532
},
1533
},
1534
1535
SearchSuggestEnabled: {
1536
onBeforeAddons(manager, param) {
1537
setAndLockPref("browser.urlbar.suggest.searches", param);
1538
setAndLockPref("browser.search.suggest.enabled", param);
1539
},
1540
},
1541
1542
SecurityDevices: {
1543
onProfileAfterChange(manager, param) {
1544
let securityDevices = param;
1545
let pkcs11db = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
1546
Ci.nsIPKCS11ModuleDB
1547
);
1548
let moduleList = pkcs11db.listModules();
1549
for (let deviceName in securityDevices) {
1550
let foundModule = false;
1551
for (let module of moduleList) {
1552
if (module && module.libName === securityDevices[deviceName]) {
1553
foundModule = true;
1554
break;
1555
}
1556
}
1557
if (foundModule) {
1558
continue;
1559
}
1560
try {
1561
pkcs11db.addModule(deviceName, securityDevices[deviceName], 0, 0);
1562
} catch (ex) {
1563
log.error(`Unable to add security device ${deviceName}`);
1564
log.debug(ex);
1565
}
1566
}
1567
},
1568
},
1569
1570
SSLVersionMax: {
1571
onBeforeAddons(manager, param) {
1572
let tlsVersion;
1573
switch (param) {
1574
case "tls1":
1575
tlsVersion = 1;
1576
break;
1577
case "tls1.1":
1578
tlsVersion = 2;
1579
break;
1580
case "tls1.2":
1581
tlsVersion = 3;
1582
break;
1583
case "tls1.3":
1584
tlsVersion = 4;
1585
break;
1586
}
1587
setAndLockPref("security.tls.version.max", tlsVersion);
1588
},
1589
},
1590
1591
SSLVersionMin: {
1592
onBeforeAddons(manager, param) {
1593
let tlsVersion;
1594
switch (param) {
1595
case "tls1":
1596
tlsVersion = 1;
1597
break;
1598
case "tls1.1":
1599
tlsVersion = 2;
1600
break;
1601
case "tls1.2":
1602
tlsVersion = 3;
1603
break;
1604
case "tls1.3":
1605
tlsVersion = 4;
1606
break;
1607
}
1608
setAndLockPref("security.tls.version.min", tlsVersion);
1609
},
1610
},
1611
1612
SupportMenu: {
1613
onProfileAfterChange(manager, param) {
1614
manager.setSupportMenu(param);
1615
},
1616
},
1617
1618
UserMessaging: {
1619
onBeforeAddons(manager, param) {
1620
let locked = false;
1621
if ("Locked" in param) {
1622
locked = param.Locked;
1623
}
1624
if ("WhatsNew" in param) {
1625
setDefaultPref(
1626
"browser.messaging-system.whatsNewPanel.enabled",
1627
param.WhatsNew,
1628
locked
1629
);
1630
}
1631
if ("ExtensionRecommendations" in param) {
1632
setDefaultPref(
1633
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
1634
param.ExtensionRecommendations,
1635
locked
1636
);
1637
}
1638
if ("FeatureRecommendations" in param) {
1639
setDefaultPref(
1640
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
1641
param.FeatureRecommendations,
1642
locked
1643
);
1644
}
1645
if ("UrlbarInterventions" in param && !param.UrlbarInterventions) {
1646
manager.disallowFeature("urlbarinterventions");
1647
}
1648
},
1649
},
1650
1651
WebsiteFilter: {
1652
onBeforeUIStartup(manager, param) {
1653
this.filter = new WebsiteFilter(
1654
param.Block || [],
1655
param.Exceptions || []
1656
);
1657
},
1658
},
1659
};
1660
1661
/*
1662
* ====================
1663
* = HELPER FUNCTIONS =
1664
* ====================
1665
*
1666
* The functions below are helpers to be used by several policies.
1667
*/
1668
1669
/**
1670
* setAndLockPref
1671
*
1672
* Sets the _default_ value of a pref, and locks it (meaning that
1673
* the default value will always be returned, independent from what
1674
* is stored as the user value).
1675
* The value is only changed in memory, and not stored to disk.
1676
*
1677
* @param {string} prefName
1678
* The pref to be changed
1679
* @param {boolean,number,string} prefValue
1680
* The value to set and lock
1681
*/
1682
function setAndLockPref(prefName, prefValue) {
1683
setDefaultPref(prefName, prefValue, true);
1684
}
1685
1686
/**
1687
* setDefaultPref
1688
*
1689
* Sets the _default_ value of a pref and optionally locks it.
1690
* The value is only changed in memory, and not stored to disk.
1691
*
1692
* @param {string} prefName
1693
* The pref to be changed
1694
* @param {boolean,number,string} prefValue
1695
* The value to set
1696
* @param {boolean} locked
1697
* Optionally lock the pref
1698
*/
1699
function setDefaultPref(prefName, prefValue, locked = false) {
1700
if (Services.prefs.prefIsLocked(prefName)) {
1701
Services.prefs.unlockPref(prefName);
1702
}
1703
1704
let defaults = Services.prefs.getDefaultBranch("");
1705
1706
switch (typeof prefValue) {
1707
case "boolean":
1708
defaults.setBoolPref(prefName, prefValue);
1709
break;
1710
1711
case "number":
1712
if (!Number.isInteger(prefValue)) {
1713
throw new Error(`Non-integer value for ${prefName}`);
1714
}
1715
1716
defaults.setIntPref(prefName, prefValue);
1717
break;
1718
1719
case "string":
1720
defaults.setStringPref(prefName, prefValue);
1721
break;
1722
}
1723
1724
if (locked) {
1725
Services.prefs.lockPref(prefName);
1726
}
1727
}
1728
1729
/**
1730
* setDefaultPermission
1731
*
1732
* Helper function to set preferences appropriately for the policy
1733
*
1734
* @param {string} policyName
1735
* The name of the policy to set
1736
* @param {object} policyParam
1737
* The object containing param for the policy
1738
*/
1739
function setDefaultPermission(policyName, policyParam) {
1740
if ("BlockNewRequests" in policyParam) {
1741
let prefName = "permissions.default." + policyName;
1742
1743
if (policyParam.BlockNewRequests) {
1744
setDefaultPref(prefName, 2, policyParam.Locked);
1745
} else {
1746
setDefaultPref(prefName, 0, policyParam.Locked);
1747
}
1748
}
1749
}
1750
1751
/**
1752
* addAllowDenyPermissions
1753
*
1754
* Helper function to call the permissions manager (Services.perms.addFromPrincipal)
1755
* for two arrays of URLs.
1756
*
1757
* @param {string} permissionName
1758
* The name of the permission to change
1759
* @param {array} allowList
1760
* The list of URLs to be set as ALLOW_ACTION for the chosen permission.
1761
* @param {array} blockList
1762
* The list of URLs to be set as DENY_ACTION for the chosen permission.
1763
*/
1764
function addAllowDenyPermissions(permissionName, allowList, blockList) {
1765
allowList = allowList || [];
1766
blockList = blockList || [];
1767
1768
for (let origin of allowList) {
1769
try {
1770
Services.perms.addFromPrincipal(
1771
Services.scriptSecurityManager.createContentPrincipalFromOrigin(origin),
1772
permissionName,
1773
Ci.nsIPermissionManager.ALLOW_ACTION,
1774
Ci.nsIPermissionManager.EXPIRE_POLICY
1775
);
1776
} catch (ex) {
1777
log.error(`Added by default for ${permissionName} permission in the permission
1778
manager - ${origin.href}`);
1779
}
1780
}
1781
1782
for (let origin of blockList) {
1783
Services.perms.addFromPrincipal(
1784
Services.scriptSecurityManager.createContentPrincipalFromOrigin(origin),
1785
permissionName,
1786
Ci.nsIPermissionManager.DENY_ACTION,
1787
Ci.nsIPermissionManager.EXPIRE_POLICY
1788
);
1789
}
1790
}
1791
1792
/**
1793
* runOnce
1794
*
1795
* Helper function to run a callback only once per policy.
1796
*
1797
* @param {string} actionName
1798
* A given name which will be used to track if this callback has run.
1799
* @param {Functon} callback
1800
* The callback to run only once.
1801
*/
1802
// eslint-disable-next-line no-unused-vars
1803
function runOnce(actionName, callback) {
1804
let prefName = `browser.policies.runonce.${actionName}`;
1805
if (Services.prefs.getBoolPref(prefName, false)) {
1806
log.debug(
1807
`Not running action ${actionName} again because it has already run.`
1808
);
1809
return;
1810
}
1811
Services.prefs.setBoolPref(prefName, true);
1812
callback();
1813
}
1814
1815
/**
1816
* runOncePerModification
1817
*
1818
* Helper function similar to runOnce. The difference is that runOnce runs the
1819
* callback once when the policy is set, then never again.
1820
* runOncePerModification runs the callback once each time the policy value
1821
* changes from its previous value.
1822
* If the callback that was passed is an async function, you can await on this
1823
* function to await for the callback.
1824
*
1825
* @param {string} actionName
1826
* A given name which will be used to track if this callback has run.
1827
* This string will be part of a pref name.
1828
* @param {string} policyValue
1829
* The current value of the policy. This will be compared to previous
1830
* values given to this function to determine if the policy value has
1831
* changed. Regardless of the data type of the policy, this must be a
1832
* string.
1833
* @param {Function} callback
1834
* The callback to be run when the pref value changes
1835
* @returns Promise
1836
* A promise that will resolve once the callback finishes running.
1837
*
1838
*/
1839
async function runOncePerModification(actionName, policyValue, callback) {
1840
let prefName = `browser.policies.runOncePerModification.${actionName}`;
1841
let oldPolicyValue = Services.prefs.getStringPref(prefName, undefined);
1842
if (policyValue === oldPolicyValue) {
1843
log.debug(
1844
`Not running action ${actionName} again because the policy's value is unchanged`
1845
);
1846
return Promise.resolve();
1847
}
1848
Services.prefs.setStringPref(prefName, policyValue);
1849
return callback();
1850
}
1851
1852
/**
1853
* clearRunOnceModification
1854
*
1855
* Helper function that clears a runOnce policy.
1856
*/
1857
function clearRunOnceModification(actionName) {
1858
let prefName = `browser.policies.runOncePerModification.${actionName}`;
1859
Services.prefs.clearUserPref(prefName);
1860
}
1861
1862
function replacePathVariables(path) {
1863
if (path.includes("${home}")) {
1864
return path.replace("${home}", FileUtils.getFile("Home", []).path);
1865
}
1866
return path;
1867
}
1868
1869
/**
1870
* installAddonFromURL
1871
*
1872
* Helper function that installs an addon from a URL
1873
* and verifies that the addon ID matches.
1874
*/
1875
function installAddonFromURL(url, extensionID) {
1876
AddonManager.getInstallForURL(url, {
1877
telemetryInfo: { source: "enterprise-policy" },
1878
}).then(install => {
1879
if (install.addon && install.addon.appDisabled) {
1880
log.error(`Incompatible add-on - ${location}`);
1881
install.cancel();
1882
return;
1883
}
1884
let listener = {
1885
/* eslint-disable-next-line no-shadow */
1886
onDownloadEnded: install => {
1887
if (extensionID && install.addon.id != extensionID) {
1888
log.error(
1889
`Add-on downloaded from ${url} had unexpected id (got ${install.addon.id} expected ${extensionID})`
1890
);
1891
install.removeListener(listener);
1892
install.cancel();
1893
}
1894
if (install.addon && install.addon.appDisabled) {
1895
log.error(`Incompatible add-on - ${url}`);
1896
install.removeListener(listener);
1897
install.cancel();
1898
}
1899
},
1900
onDownloadFailed: () => {
1901
install.removeListener(listener);
1902
log.error(
1903
`Download failed - ${AddonManager.errorToString(
1904
install.error
1905
)} - ${url}`
1906
);
1907
clearRunOnceModification("extensionsInstall");
1908
},
1909
onInstallFailed: () => {
1910
install.removeListener(listener);
1911
log.error(
1912
`Installation failed - ${AddonManager.errorToString(
1913
install.error
1914
)} - {url}`
1915
);
1916
},
1917
onInstallEnded: () => {
1918
install.removeListener(listener);
1919
log.debug(`Installation succeeded - ${url}`);
1920
},
1921
};
1922
install.addListener(listener);
1923
install.install();
1924
});
1925
}
1926
1927
let gBlockedChromePages = [];
1928
1929
function blockAboutPage(manager, feature, neededOnContentProcess = false) {
1930
if (!gBlockedChromePages.length) {
1931
addChromeURLBlocker();
1932
}
1933
manager.disallowFeature(feature, neededOnContentProcess);
1934
let splitURL = Services.io
1935
.newChannelFromURI(
1936
Services.io.newURI(feature),
1937
null,
1938
Services.scriptSecurityManager.getSystemPrincipal(),
1939
null,
1940
0,
1941
Ci.nsIContentPolicy.TYPE_OTHER
1942
)
1943
.URI.spec.split("/");
1944
// about:debugging uses index.html for a filename, so we need to rely
1945
// on more than just the filename.
1946
let fileName =
1947
splitURL[splitURL.length - 2] + "/" + splitURL[splitURL.length - 1];
1948
gBlockedChromePages.push(fileName);
1949
if (feature == "about:config") {
1950
// Hide old page until it is removed
1951
gBlockedChromePages.push("config.xhtml");
1952
}
1953
}
1954
1955
let ChromeURLBlockPolicy = {
1956
shouldLoad(contentLocation, loadInfo, mimeTypeGuess) {
1957
let contentType = loadInfo.externalContentPolicyType;
1958
if (
1959
contentLocation.scheme == "chrome" &&
1960
contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT &&
1961
loadInfo.loadingContext &&
1962
loadInfo.loadingContext.baseURI == AppConstants.BROWSER_CHROME_URL &&
1963
gBlockedChromePages.some(function(fileName) {
1964
return contentLocation.filePath.endsWith(fileName);
1965
})
1966
) {
1967
return Ci.nsIContentPolicy.REJECT_REQUEST;
1968
}
1969
return Ci.nsIContentPolicy.ACCEPT;
1970
},
1971
shouldProcess(contentLocation, loadInfo, mimeTypeGuess) {
1972
return Ci.nsIContentPolicy.ACCEPT;
1973
},
1974
classDescription: "Policy Engine Content Policy",
1975
contractID: "@mozilla-org/policy-engine-content-policy-service;1",
1976
classID: Components.ID("{ba7b9118-cabc-4845-8b26-4215d2a59ed7}"),
1977
QueryInterface: ChromeUtils.generateQI([Ci.nsIContentPolicy]),
1978
createInstance(outer, iid) {
1979
return this.QueryInterface(iid);
1980
},
1981
};
1982
1983
function addChromeURLBlocker() {
1984
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
1985
registrar.registerFactory(
1986
ChromeURLBlockPolicy.classID,
1987
ChromeURLBlockPolicy.classDescription,
1988
ChromeURLBlockPolicy.contractID,
1989
ChromeURLBlockPolicy
1990
);
1991
1992
Services.catMan.addCategoryEntry(
1993
"content-policy",
1994
ChromeURLBlockPolicy.contractID,
1995
ChromeURLBlockPolicy.contractID,
1996
false,
1997
true
1998
);
1999
}
2000
2001
function pemToBase64(pem) {
2002
return pem
2003
.replace(/-----BEGIN CERTIFICATE-----/, "")
2004
.replace(/-----END CERTIFICATE-----/, "")
2005
.replace(/[\r\n]/g, "");
2006
}