Policies.jsm 8.92 KB
Newer Older
1
2
3
4
5
6
/* 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";

7
8
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
9
10
11
XPCOMUtils.defineLazyServiceGetter(this, "gXulStore",
                                   "@mozilla.org/xul/xulstore;1",
                                   "nsIXULStore");
12

13
14
15
16
XPCOMUtils.defineLazyModuleGetters(this, {
  BookmarksPolicies: "resource:///modules/policies/BookmarksPolicies.jsm",
});

17
const PREF_LOGLEVEL           = "browser.policies.loglevel";
18
const BROWSER_DOCUMENT_URL    = "chrome://browser/content/browser.xul";
19
20

XPCOMUtils.defineLazyGetter(this, "log", () => {
21
  let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
22
23
24
25
26
27
28
29
30
  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,
  });
});

31
var EXPORTED_SYMBOLS = ["Policies"];
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * ============================
 * = POLICIES IMPLEMENTATIONS =
 * ============================
 *
 * The Policies object below is where the implementation for each policy
 * happens. An object for each policy should be defined, containing
 * callback functions that will be called by the engine.
 *
 * See the _callbacks object in EnterprisePolicies.js for the list of
 * possible callbacks and an explanation of each.
 *
 * Each callback will be called with two parameters:
 * - manager
 *   This is the EnterprisePoliciesManager singleton object from
 *   EnterprisePolicies.js
 *
 * - param
 *   The parameter defined for this policy in policies-schema.json.
 *   It will be different for each policy. It could be a boolean,
 *   a string, an array or a complex object. All parameters have
 *   been validated according to the schema, and no unknown
 *   properties will be present on them.
 *
 * The callbacks will be bound to their parent policy object.
 */
59
var Policies = {
60
61
62
63
64
65
66
67
  "BlockAboutAddons": {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("about:addons", true);
      }
    }
  },

68
  "BlockAboutConfig": {
69
    onBeforeUIStartup(manager, param) {
70
      if (param) {
71
        manager.disallowFeature("about:config", true);
72
        setAndLockPref("devtools.chrome.enabled", false);
73
74
75
      }
    }
  },
76

77
78
79
80
81
82
83
84
  "BlockAboutProfiles": {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("about:profiles", true);
      }
    }
  },

85
86
87
88
89
90
91
92
  "BlockAboutSupport": {
    onBeforeUIStartup(manager, param) {
      if (param) {
        manager.disallowFeature("about:support", true);
      }
    }
  },

93
  "BlockSetDesktopBackground": {
94
    onBeforeUIStartup(manager, param) {
95
      if (param) {
96
        manager.disallowFeature("setDesktopBackground", true);
97
98
99
100
      }
    }
  },

101
102
103
104
105
106
  "Bookmarks": {
    onAllWindowsRestored(manager, param) {
      BookmarksPolicies.processBookmarks(param);
    }
  },

107
  "Cookies": {
108
    onBeforeUIStartup(manager, param) {
109
      addAllowDenyPermissions("cookie", param.Allow, param.Block);
110
111
112
    }
  },

113
  "CreateMasterPassword": {
114
    onBeforeUIStartup(manager, param) {
115
116
      if (!param) {
        manager.disallowFeature("createMasterPassword");
117
118
119
120
      }
    }
  },

121
122
123
124
  "DisableAppUpdate": {
    onBeforeAddons(manager, param) {
      if (param) {
        manager.disallowFeature("appUpdate");
125
126
127
128
      }
    }
  },

129
130
131
132
133
134
135
136
137
138
139
140
141
142
  "DisableDeveloperTools": {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("devtools.policy.disabled", true);
        setAndLockPref("devtools.chrome.enabled", false);

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

143
144
  "DisableFirefoxScreenshots": {
    onBeforeAddons(manager, param) {
145
      if (param) {
146
147
148
149
150
        setAndLockPref("extensions.screenshots.disabled", true);
      }
    }
  },

151
152
  "DisableFirefoxStudies": {
    onBeforeAddons(manager, param) {
153
      if (param) {
154
155
156
157
158
        manager.disallowFeature("Shield");
      }
    }
  },

159
160
  "DisableFormHistory": {
    onBeforeUIStartup(manager, param) {
161
      if (param) {
162
163
164
165
166
        setAndLockPref("browser.formfill.enable", false);
      }
    }
  },

167
168
169
170
171
172
173
174
  "DisablePocket": {
    onBeforeAddons(manager, param) {
      if (param) {
        setAndLockPref("extensions.pocket.enabled", false);
      }
    }
  },

175
  "DisplayBookmarksToolbar": {
176
    onBeforeUIStartup(manager, param) {
177
178
179
180
      if (param) {
        // This policy is meant to change the default behavior, not to force it.
        // If this policy was alreay applied and the user chose to re-hide the
        // bookmarks toolbar, do not show it again.
181
        runOnce("displayBookmarksToolbar", () => {
182
          gXulStore.setValue(BROWSER_DOCUMENT_URL, "PersonalToolbar", "collapsed", "false");
183
        });
184
      }
185
    }
186
187
  },

188
  "DisplayMenuBar": {
189
    onBeforeUIStartup(manager, param) {
190
191
192
193
      if (param) {
        // This policy is meant to change the default behavior, not to force it.
        // If this policy was alreay applied and the user chose to re-hide the
        // menu bar, do not show it again.
194
        runOnce("displayMenuBar", () => {
195
          gXulStore.setValue(BROWSER_DOCUMENT_URL, "toolbar-menubar", "autohide", "false");
196
        });
197
      }
198
199
200
    }
  },

201
  "DontCheckDefaultBrowser": {
202
    onBeforeUIStartup(manager, param) {
203
      setAndLockPref("browser.shell.checkDefaultBrowser", false);
204
205
206
    }
  },

207
  "FlashPlugin": {
208
    onBeforeUIStartup(manager, param) {
209
      addAllowDenyPermissions("plugin:flash", param.Allow, param.Block);
210
211
212
    }
  },

213
  "InstallAddons": {
214
    onBeforeUIStartup(manager, param) {
215
      addAllowDenyPermissions("install", param.Allow, null);
216
217
218
    }
  },

219
  "Popups": {
220
    onBeforeUIStartup(manager, param) {
221
      addAllowDenyPermissions("popup", param.Allow, null);
222
223
224
225
226
227
    }
  },

  "RememberPasswords": {
    onBeforeUIStartup(manager, param) {
      setAndLockPref("signon.rememberSignons", param);
228
229
    }
  },
230
};
231
232
233
234
235
236
237
238
239

/*
 * ====================
 * = HELPER FUNCTIONS =
 * ====================
 *
 * The functions below are helpers to be used by several policies.
 */

240
241
242
243
244
245
246
247
248
249
250
251
252
/**
 * setAndLockPref
 *
 * Sets the _default_ value of a pref, and locks it (meaning that
 * the default value will always be returned, independent from what
 * is stored as the user value).
 * The value is only changed in memory, and not stored to disk.
 *
 * @param {string} prefName
 *        The pref to be changed
 * @param {boolean,number,string} prefValue
 *        The value to set and lock
 */
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
function setAndLockPref(prefName, prefValue) {
  if (Services.prefs.prefIsLocked(prefName)) {
    Services.prefs.unlockPref(prefName);
  }

  let defaults = Services.prefs.getDefaultBranch("");

  switch (typeof(prefValue)) {
    case "boolean":
      defaults.setBoolPref(prefName, prefValue);
      break;

    case "number":
      if (!Number.isInteger(prefValue)) {
        throw new Error(`Non-integer value for ${prefName}`);
      }

      defaults.setIntPref(prefName, prefValue);
      break;

    case "string":
      defaults.setStringPref(prefName, prefValue);
      break;
  }

  Services.prefs.lockPref(prefName);
}
280

281
282
283
284
285
286
287
288
289
290
291
292
293
/**
 * addAllowDenyPermissions
 *
 * Helper function to call the permissions manager (Services.perms.add)
 * for two arrays of URLs.
 *
 * @param {string} permissionName
 *        The name of the permission to change
 * @param {array} allowList
 *        The list of URLs to be set as ALLOW_ACTION for the chosen permission.
 * @param {array} blockList
 *        The list of URLs to be set as DENY_ACTION for the chosen permission.
 */
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
function addAllowDenyPermissions(permissionName, allowList, blockList) {
  allowList = allowList || [];
  blockList = blockList || [];

  for (let origin of allowList) {
    Services.perms.add(origin,
                       permissionName,
                       Ci.nsIPermissionManager.ALLOW_ACTION,
                       Ci.nsIPermissionManager.EXPIRE_POLICY);
  }

  for (let origin of blockList) {
    Services.perms.add(origin,
                       permissionName,
                       Ci.nsIPermissionManager.DENY_ACTION,
                       Ci.nsIPermissionManager.EXPIRE_POLICY);
  }
}
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

/**
 * runOnce
 *
 * Helper function to run a callback only once per policy.
 *
 * @param {string} actionName
 *        A given name which will be used to track if this callback has run.
 * @param {Functon} callback
 *        The callback to run only once.
 */
function runOnce(actionName, callback) {
  let prefName = `browser.policies.runonce.${actionName}`;
  if (Services.prefs.getBoolPref(prefName, false)) {
    log.debug(`Not running action ${actionName} again because it has already run.`);
    return;
  }
  callback();
  Services.prefs.setBoolPref(prefName, true);
}