Browse Source
What is CCK2? Answer here: https://mike.kaply.com/cck2/
Updated configuration
Add new old reseed certificate
Update addressbook
Now time to think about one problem - user agent. In FF 60+ removed ability to change it without addons.
Former-commit-id: 6e9eeba209
pull/43/head
R4SAS
6 years ago
70 changed files with 11921 additions and 2035 deletions
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
[XRE] |
||||
EnableProfileMigrator=0 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
resource cck2 modules/ |
@ -0,0 +1,154 @@
@@ -0,0 +1,154 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gForceExternalHandler = false; |
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "extProtocolSvc", |
||||
"@mozilla.org/uriloader/external-protocol-service;1", "nsIExternalProtocolService"); |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
// If the parent document is a local file, don't do anything
|
||||
// Links will just work
|
||||
if (doc.location.href.indexOf("file://") == 0) { |
||||
return; |
||||
} |
||||
var links = event.target.getElementsByTagName("a"); |
||||
for (var i=0; i < links.length; i++) { |
||||
var link = links[i]; |
||||
if (link.href.indexOf("file://") != 0) { |
||||
continue; |
||||
} |
||||
link.addEventListener("click", function(link) { |
||||
return function(event) { |
||||
event.preventDefault(); |
||||
if (gForceExternalHandler) { |
||||
extProtocolSvc.loadUrl(Services.io.newURI(link.href, null, null)); |
||||
} else { |
||||
var target = "_self"; |
||||
if (link.hasAttribute("target")) { |
||||
target = link.getAttribute("target"); |
||||
} |
||||
// If we were told somewhere other than current (based on modifier keys), use it
|
||||
var where = whereToOpenLink(event); |
||||
if (where != "current" || target == "_blank") { |
||||
sendAsyncMessage("cck2:open-url", { |
||||
"url": link.href, |
||||
"where": (target == "_blank") ? "tab" : where |
||||
}); |
||||
return; |
||||
} |
||||
switch (target) { |
||||
case "_self": |
||||
link.ownerDocument.location = link.href; |
||||
break; |
||||
case "_parent": |
||||
link.ownerDocument.defaultView.parent.document.location = link.href; |
||||
break; |
||||
case "_top": |
||||
link.ownerDocument.defaultView.top.document.location = link.href; |
||||
break; |
||||
default: |
||||
// Attempt to find the iframe that this goes into
|
||||
var iframes = doc.defaultView.parent.document.getElementsByName(target); |
||||
if (iframes.length > 0) { |
||||
iframes[0].contentDocument.location = link.href; |
||||
} else { |
||||
link.ownerDocument.location = link.href; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}(link), false); |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.checkloaduri.enabled") == "allAccess") { |
||||
gForceExternalHandler = !extProtocolSvc.isExposedProtocol('file'); |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} catch (e) {} |
||||
} |
||||
|
||||
|
||||
/* Copied from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/utilityOverlay.js?raw=1 */ |
||||
|
||||
function getBoolPref(prefname, def) |
||||
{ |
||||
try { |
||||
return Services.prefs.getBoolPref(prefname); |
||||
} |
||||
catch(er) { |
||||
return def; |
||||
} |
||||
} |
||||
|
||||
/* whereToOpenLink() looks at an event to decide where to open a link. |
||||
* |
||||
* The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). |
||||
* |
||||
* On Windows, the modifiers are: |
||||
* Ctrl new tab, selected |
||||
* Shift new window |
||||
* Ctrl+Shift new tab, in background |
||||
* Alt save |
||||
* |
||||
* Middle-clicking is the same as Ctrl+clicking (it opens a new tab). |
||||
* |
||||
* Exceptions: |
||||
* - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. |
||||
* (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) |
||||
* - Alt is hard to use in context menus, because pressing Alt closes the menu. |
||||
* - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". |
||||
* - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. |
||||
*/ |
||||
function whereToOpenLink( e, ignoreButton, ignoreAlt ) |
||||
{ |
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm"); |
||||
|
||||
// This method must treat a null event like a left click without modifier keys (i.e.
|
||||
// e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 })
|
||||
// for compatibility purposes.
|
||||
if (!e) |
||||
return "current"; |
||||
|
||||
var shift = e.shiftKey; |
||||
var ctrl = e.ctrlKey; |
||||
var meta = e.metaKey; |
||||
var alt = e.altKey && !ignoreAlt; |
||||
|
||||
// ignoreButton allows "middle-click paste" to use function without always opening in a new window.
|
||||
var middle = !ignoreButton && e.button == 1; |
||||
var middleUsesTabs = true; |
||||
|
||||
// Don't do anything special with right-mouse clicks. They're probably clicks on context menu items.
|
||||
|
||||
var metaKey = AppConstants.platform == "macosx" ? meta : ctrl; |
||||
if (metaKey || (middle && middleUsesTabs)) |
||||
return shift ? "tabshifted" : "tab"; |
||||
|
||||
if (alt && getBoolPref("browser.altClickSave", false)) |
||||
return "save"; |
||||
|
||||
if (shift || (middle && !middleUsesTabs)) |
||||
return "window"; |
||||
|
||||
return "current"; |
||||
} |
@ -0,0 +1,183 @@
@@ -0,0 +1,183 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gAllowedPasteSites = []; |
||||
var gAllowedCutCopySites = []; |
||||
var gDeniedPasteSites = []; |
||||
var gDeniedCutCopySites = []; |
||||
var gDefaultPastePolicy = false; |
||||
var gDefaultCutCopyPolicy = false; |
||||
|
||||
function allowCutCopy(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultCutCopyPolicy == true) { |
||||
for (var i=0; i < gDeniedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedCutCopySites[i]) == 0) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedCutCopySites[i]) == 0) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function allowPaste(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultPastePolicy == true) { |
||||
for (var i=0; i < gDeniedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedPasteSites[i]) == 0) { |
||||
return false; |
||||
break; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedPasteSites[i]) == 0) { |
||||
return true; |
||||
break; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function myExecCommand(doc, originalExecCommand) { |
||||
return function(aCommandName, aShowDefaultUI, aValueArgument) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalExecCommand.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
function myQueryCommandSupported(doc, originalQueryCommandSupported) { |
||||
return function(aCommandName) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalQueryCommandSupported.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
var cutCopyAllowed = allowCutCopy(doc); |
||||
var pasteAllowed = allowPaste(doc); |
||||
if (!cutCopyAllowed && !pasteAllowed) { |
||||
return; |
||||
} |
||||
var originalExecCommand = Cu.waiveXrays(doc).execCommand; |
||||
Cu.exportFunction(myExecCommand(doc, originalExecCommand), doc, {defineAs: "execCommand"}); |
||||
var originalQueryCommandSupported = Cu.waiveXrays(doc).queryCommandSupported; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandSupported), doc, {defineAs: "queryCommandSupported"}); |
||||
var originalQueryCommandEnabled = Cu.waiveXrays(doc).queryCommandEnabled; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandEnabled), doc, {defineAs: "queryCommandEnabled"}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.cutcopy") == "allAccess") { |
||||
gDefaultCutCopyPolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.paste") == "allAccess") { |
||||
gDefaultPastePolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
var policies = []; |
||||
policies = Services.prefs.getCharPref("capability.policy.policynames").split(', '); |
||||
for (var i=0; i < policies.length; i++ ) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "allAccess") { |
||||
var allowedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedCutCopySites.length; j++) { |
||||
gAllowedCutCopySites.push(allowedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "noAccess") { |
||||
var deniedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedCutCopySites.length; j++) { |
||||
gDeniedCutCopySites.push(deniedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "allAccess") { |
||||
var allowedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedPasteSites.length; j++) { |
||||
gAllowedPasteSites.push(allowedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "noAccess") { |
||||
var deniedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedPasteSites.length; j++) { |
||||
gDeniedPasteSites.push(deniedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
} |
||||
} catch (e) {} |
||||
if (gDefaultCutCopyPolicy || gDefaultPastePolicy || |
||||
gAllowedCutCopySites.length > 0 || gAllowedPasteSites> 0) { |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,111 @@
@@ -0,0 +1,111 @@
|
||||
/* This file overlays about:addons. It does the following: */ |
||||
/* Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1132971 */ |
||||
/* Hide the "Install Add-on From File" menu if xpinstall.enabled is false */ |
||||
/* Hides the discover pane if xpinstall.enabled is false */ |
||||
/* Hides the add-on entry if specified in the CCK2 config */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var addonId = "cck2wizard@kaply.com"; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:addons": |
||||
case "chrome://mozapps/content/extensions/extensions.xul": |
||||
var configs = CCK2.getConfigs(); |
||||
var hiddenAddons = []; |
||||
var requiredAddons = []; |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config && "extension" in config && config.extension.hide) { |
||||
hiddenAddons.push(config.extension.id); |
||||
} |
||||
if (config.requiredAddons) { |
||||
requiredAddons.push.apply(requiredAddons, config.requiredAddons.split(",")); |
||||
} |
||||
} |
||||
if (hiddenAddons.length > 0 || requiredAddons.length > 0) { |
||||
var ss; |
||||
for (var i = 0; i < doc.styleSheets.length; i++) { |
||||
if (doc.styleSheets[i].href == "chrome://mozapps/skin/extensions/extensions.css") { |
||||
ss = doc.styleSheets[i]; |
||||
break; |
||||
} |
||||
} |
||||
for (var i=0; i < hiddenAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + hiddenAddons[i] + "'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
for (var i=0; i < requiredAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='disable-btn'] { display: none;}", ss.cssRules.length); |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='remove-btn'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
if (requiredAddons.length > 0) { |
||||
win.gViewController.commands.cmd_disableItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_disableItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
win.gViewController.commands.cmd_uninstallItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_uninstallItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
} |
||||
} |
||||
var showDiscoverPane = true; |
||||
var xpinstallEnabled = true; |
||||
try { |
||||
xpinstallEnabled = Services.prefs.getBoolPref("xpinstall.enabled"); |
||||
} catch (e) {} |
||||
try { |
||||
showDiscoverPane = Services.prefs.getBoolPref("extensions.getAddons.showPane"); |
||||
} catch (e) {} |
||||
if (!xpinstallEnabled || !showDiscoverPane) { |
||||
// Work around Mozilla bug 1132971
|
||||
// Hide the discover pane if it is the selected pane
|
||||
if (E("view-port", doc) && E("view-port", doc).selectedIndex == 0) { |
||||
try { |
||||
win.gViewController.loadView("addons://list/extension"); |
||||
} catch (ex) { |
||||
// This fails with Webconverger installed. Ignore it.
|
||||
} |
||||
} |
||||
} |
||||
if (!xpinstallEnabled) { |
||||
// Hide the "Install Add-on From File" separator
|
||||
hide(E("utils-installFromFile-separator", doc)); |
||||
// Hide the "Install Add-on From File" menuitem
|
||||
hide(E("utils-installFromFile", doc)); |
||||
win.gDragDrop.onDragOver = function(event) { |
||||
event.dataTransfer.dropEffect = "none"; |
||||
event.stopPropagation(); |
||||
event.preventDefault(); |
||||
}; |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
/* This file is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1139509 */ |
||||
/* It bolds the Firefox version in the about dialog and unbolds the distribution information */ |
||||
/* It can be removed once Firefox 38 ESR is out of support */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/aboutDialog.xul": |
||||
doc.querySelector("#version").style.fontWeight = "bold"; |
||||
doc.querySelector("#distribution").style.fontWeight = "normal"; |
||||
doc.querySelector("#distributionId").style.fontWeight = "normal"; |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/* This file overrides about:home. It does the following: |
||||
* Remove the sync button if Sync is disabled |
||||
* Remove the Addons button if Sync is disabled |
||||
* Remove the snippets if snippets are disabled |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "content-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:home": |
||||
case "chrome://browser/content/abouthome/aboutHome.xhtml": |
||||
if (!configs) { |
||||
// TODO - Make this Async
|
||||
configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
remove(E("sync", doc)); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
remove(E("addons", doc)); |
||||
} |
||||
if (config.disableWebApps) { |
||||
remove(E("apps", doc)); |
||||
} |
||||
if (config.removeSnippets) { |
||||
var snippets = E("snippets", doc); |
||||
if (snippets) { |
||||
snippets.style.display = "none"; |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(config.hiddenUI[i]); |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
uiElement.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "content-document-global-created", false); |
||||
|
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(observer, "content-document-global-created", false); |
||||
}) |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* This file overrides about:support It does the following: |
||||
* Remove the reset Firefox button if disableResetFirefox is set |
||||
* Remove the safe mode Button if disableSafeMode is set |
||||
* Remove the box if both are set |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:support": |
||||
case "chrome://global/content/aboutSupport.xhtml": |
||||
if (!configs) { |
||||
configs = CCK2.getConfigs(); |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableResetFirefox) { |
||||
remove(E("reset-box", doc)); |
||||
} |
||||
if (config.disableSafeMode) { |
||||
remove(E("safe-mode-box", doc)); |
||||
} |
||||
if (config.disableResetFirefox && |
||||
config.disableSafeMode) { |
||||
remove(E("action-box", doc)); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,373 @@
@@ -0,0 +1,373 @@
|
||||
/* This file modifies the main browser window. It does the following: |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource:///modules/CustomizableUI.jsm"); |
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/browser.xul": |
||||
// Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1149617
|
||||
var origSetReportPhishingMenu = win.gSafeBrowsing.setReportPhishingMenu; |
||||
win.gSafeBrowsing.setReportPhishingMenu = function() { |
||||
try { |
||||
origSetReportPhishingMenu(); |
||||
} catch (e) {} |
||||
} |
||||
|
||||
win.addEventListener("unload", function onUnload(event) { |
||||
win.removeEventListener("unload", onUnload, false); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).removeEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
}); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).addEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
var appMenuPopup = doc.getElementById("appMenu-popup"); |
||||
if (appMenuPopup) { |
||||
E("appMenu-popup", doc).addEventListener("popupshowing", onAppMenuShowing, false); |
||||
} |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
config = configs[id]; |
||||
if (config.disablePrivateBrowsing && |
||||
PrivateBrowsingUtils.isWindowPrivate(win)) { |
||||
win.setTimeout(function() { |
||||
Services.prompt.alert(win, "Private Browsing", "Private Browsing has been disabled by your administrator"); |
||||
win.close(); |
||||
}, 0, false); |
||||
} |
||||
if (config.disablePrivateBrowsing) { |
||||
disablePrivateBrowsing(doc); |
||||
} |
||||
if (config.disableSync) { |
||||
disableSync(doc); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
disableAddonsManager(doc); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
Services.tm.mainThread.dispatch(function() { |
||||
removeDeveloperTools(doc); |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.disableErrorConsole) { |
||||
disableErrorConsole(doc); |
||||
} |
||||
if (config.disableFirefoxHealthReport) { |
||||
var healthReportMenu = doc.getElementById("healthReport"); |
||||
if (healthReportMenu) { |
||||
healthReportMenu.parentNode.removeChild(healthReportMenu); |
||||
} |
||||
} |
||||
if (config.removeSafeModeMenu) { |
||||
hide(E("helpSafeMode", doc)); |
||||
} |
||||
if (config.titlemodifier) { |
||||
doc.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier); |
||||
} |
||||
if (config.removeSetDesktopBackground) { |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-setDesktopBackground", doc)) { |
||||
E("context-setDesktopBackground", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableWebApps) { |
||||
CustomizableUI.destroyWidget("web-apps-button"); |
||||
hide(E("menu_openApps", doc)); |
||||
} |
||||
if (config.disableHello) { |
||||
CustomizableUI.destroyWidget("loop-button"); |
||||
hide(E("menu_openLoop", doc)); |
||||
} |
||||
if (config.disablePocket) { |
||||
CustomizableUI.destroyWidget("pocket-button"); |
||||
} |
||||
if (config.disableSharePage) { |
||||
CustomizableUI.destroyWidget("social-share-button"); |
||||
// Because these are on a context menu, we can't use "hidden"
|
||||
if (E("context-sharelink", doc)) { |
||||
E("context-sharelink", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareselect", doc)) { |
||||
E("context-shareselect", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareimage", doc)) { |
||||
E("context-shareimage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharevideo", doc)) { |
||||
E("context-sharevideo", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharepage", doc)) { |
||||
E("context-sharepage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableSocialAPI) { |
||||
win.SocialActivationListener = {}; |
||||
} |
||||
if (config.disableForget) { |
||||
CustomizableUI.destroyWidget("panic-button"); |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
if (config.helpMenu) { |
||||
// We need to run this function on a delay, because we won't know
|
||||
// if the about menu is hidden for mac until after it is run.
|
||||
Services.tm.mainThread.dispatch(function() { |
||||
var helpMenuPopup = doc.getElementById("menu_HelpPopup"); |
||||
var menuitem = doc.createElement("menuitem"); |
||||
menuitem.setAttribute("label", config.helpMenu.label); |
||||
if ("accesskey" in config.helpMenu) { |
||||
menuitem.setAttribute("accesskey", config.helpMenu.accesskey); |
||||
} |
||||
menuitem.setAttribute("oncommand", "openUILink('" + config.helpMenu.url + "');"); |
||||
menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);"); |
||||
if (!E("aboutName", doc) || E("aboutName", doc).hidden) { |
||||
// Mac
|
||||
helpMenuPopup.appendChild(menuitem); |
||||
} else { |
||||
helpMenuPopup.insertBefore(menuitem, E("aboutName", doc)); |
||||
helpMenuPopup.insertBefore(doc.createElement("menuseparator"), |
||||
E("aboutName", doc)); |
||||
} |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.firstrun || config.upgrade) { |
||||
if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) { |
||||
CustomizableUI.setToolbarVisibility("PersonalToolbar", "true"); |
||||
} |
||||
if (config.displayMenuBar) { |
||||
CustomizableUI.setToolbarVisibility("toolbar-menubar", "true"); |
||||
} |
||||
if (config.showSearchBar) { |
||||
CustomizableUI.addWidgetToArea("search-container", CustomizableUI.AREA_NAVBAR, |
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1); |
||||
} |
||||
config.firstrun = false; |
||||
config.upgrade = false; |
||||
} |
||||
} |
||||
break; |
||||
case "chrome://browser/content/places/places.xul": |
||||
case "chrome://browser/content/bookmarks/bookmarksPanel.xul": |
||||
case "chrome://browser/content/history/history-panel.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
if (E("placesContext_open:newprivatewindow", doc)) { |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function disableSync(doc) { |
||||
var win = doc.defaultView; |
||||
if (win.gSyncUI) { |
||||
var mySyncUI = { |
||||
init: function() { |
||||
return; |
||||
}, |
||||
initUI: function() { |
||||
return; |
||||
}, |
||||
updateUI: function() { |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
} |
||||
win.gSyncUI = mySyncUI; |
||||
} |
||||
CustomizableUI.destroyWidget("sync-button"); |
||||
CustomizableUI.removeWidgetFromArea("sync-button"); |
||||
var toolbox = doc.getElementById("navigator-toolbox"); |
||||
if (toolbox && toolbox.palette) { |
||||
let element = toolbox.palette.querySelector("#sync-button"); |
||||
if (element) { |
||||
element.parentNode.removeChild(element); |
||||
} |
||||
} |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
|
||||
function disablePrivateBrowsing(doc) { |
||||
disable(E("Tools:PrivateBrowsing", doc)); |
||||
hide(E("menu_newPrivateWindow", doc)); |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-openlinkprivate", doc)) |
||||
E("context-openlinkprivate", doc).setAttribute("style", "display: none;"); |
||||
if (E("placesContext_open:newprivatewindow", doc)) |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
CustomizableUI.destroyWidget("privatebrowsing-button") |
||||
} |
||||
|
||||
function disableAddonsManager(doc) { |
||||
hide(E("menu_openAddons", doc)); |
||||
disable(E("Tools:Addons", doc)); // Ctrl+Shift+A
|
||||
CustomizableUI.destroyWidget("add-ons-button") |
||||
} |
||||
|
||||
function removeDeveloperTools(doc) { |
||||
var win = doc.defaultView; |
||||
// Need to delay this because devtools is created dynamically
|
||||
win.setTimeout(function() { |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
hide(E("webDeveloperMenu", doc)); |
||||
var devtoolsKeyset = doc.getElementById("devtoolsKeyset"); |
||||
if (devtoolsKeyset) { |
||||
for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) { |
||||
devtoolsKeyset.childNodes[i].removeAttribute("oncommand"); |
||||
devtoolsKeyset.childNodes[i].removeAttribute("command"); |
||||
} |
||||
} |
||||
}, 0); |
||||
try { |
||||
doc.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:Scratchpad").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserConsole").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbar").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
} |
||||
|
||||
function disableErrorConsole(doc) { |
||||
doc.getElementById("Tools:ErrorConsole").removeAttribute("oncommand"); |
||||
} |
||||
|
||||
function onPanelShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("PanelUI-fxa-status", event.target.ownerDocument)); |
||||
hide(E("PanelUI-footer-fxa", event.target.ownerDocument)); // Firefox 42+
|
||||
} |
||||
} |
||||
} |
||||
|
||||
function onAppMenuShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("appMenu-fxa-container", event.target.ownerDocument)); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
hide(E("appMenu-developer-button", event.target.ownerDocument)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
element.setAttribute("disabled", "true"); |
||||
} |
||||
} |
||||
|
||||
function hideUIElements(doc, hiddenUI) { |
||||
for (var i=0; i < hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(hiddenUI[i]); |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + hiddenUI[i] + "{display: none !important;}"; |
||||
if (!uiElements || uiElements.length == 0) { |
||||
continue; |
||||
} |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
if (uiElement.nodeName == "menuitem") { |
||||
uiElement.removeAttribute("key"); |
||||
uiElement.removeAttribute("oncommand"); |
||||
if (uiElement.hasAttribute("command")) { |
||||
var commandId = uiElement.getAttribute("command"); |
||||
uiElement.removeAttribute("command"); |
||||
var command = doc.getElementById(commandId); |
||||
command.removeAttribute("oncommand"); |
||||
var keys = doc.querySelectorAll("key[command='" + commandId + "']") |
||||
for (var k=0; k < keys.length; k++) { |
||||
keys[k].removeAttribute("command"); |
||||
} |
||||
} |
||||
} |
||||
// Horrible hack to work around the crappy Australis help menu
|
||||
// Items on the menu always show up in the Australis menu, so we have to remove them.
|
||||
if (uiElements[j].parentNode.id == "menu_HelpPopup") { |
||||
uiElements[j].parentNode.removeChild(uiElements[j]); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = []; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
let CCK2FileBlock = { |
||||
chromeBlacklist: ["browser", "mozapps", "marionette", "specialpowers", |
||||
"branding", "alerts"], |
||||
shouldLoad: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
// Prevent the loading of chrome URLs into the main browser window
|
||||
if (aContentLocation.scheme == "chrome") { |
||||
if (aRequestOrigin && |
||||
(aRequestOrigin.spec == "chrome://browser/content/browser.xul" || |
||||
aRequestOrigin.scheme == "moz-nullprincipal")) { |
||||
for (var i=0; i < this.chromeBlacklist.length; i++) { |
||||
if (aContentLocation.host == this.chromeBlacklist[i]) { |
||||
if (aContentLocation.spec.includes(".xul")) { |
||||
return Ci.nsIContentPolicy.REJECT_REQUEST; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
shouldProcess: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
classDescription: "CCK2 FileBlock Service", |
||||
contractID: "@kaply.com/cck2-fileblock-service;1", |
||||
classID: Components.ID('{26e7afc9-e22d-4d12-bb57-c184fe24b828}'), |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]), |
||||
createInstance: function(outer, iid) { |
||||
return this.QueryInterface(iid); |
||||
}, |
||||
}; |
||||
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
||||
registrar.registerFactory(CCK2FileBlock.classID, |
||||
CCK2FileBlock.classDescription, |
||||
CCK2FileBlock.contractID, |
||||
CCK2FileBlock); |
||||
|
||||
var cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); |
||||
cm.addCategoryEntry("content-policy", CCK2FileBlock.contractID, |
||||
CCK2FileBlock.contractID, false, true); |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var disableSearchEngineInstall = false; |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
if (disableSearchEngineInstall) { |
||||
subject.wrappedJSObject.external.AddSearchProvider = function() {}; |
||||
} |
||||
if (!doc.documentURI.startsWith("about:")) { |
||||
return; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
var configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSearchEngineInstall) { |
||||
disableSearchEngineInstall = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/* This file modifies the preferences dialogs. It does the following: |
||||
* Removes private browsing from the pref UI if it is disabled |
||||
* Removes Sync from the pref UI if it is diabled |
||||
* Disables the crash reporter button if crash reporter is disabled |
||||
* Removed the master password UI if it is disabled |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/preferences/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
win.addEventListener("paneload", function(event) { |
||||
updatePrefUI(event.target.ownerDocument); |
||||
}, false); |
||||
updatePrefUI(doc); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (!config.disableSync) { |
||||
continue; |
||||
} |
||||
var prefWindow = E("BrowserPreferences", doc); |
||||
var paneSyncRadio = doc.getAnonymousElementByAttribute(prefWindow, "pane", "paneSync"); |
||||
hide(paneSyncRadio); |
||||
var paneDeck = doc.getAnonymousElementByAttribute(prefWindow, "anonid", "paneDeck"); |
||||
var paneSync = E("paneSync", doc); |
||||
paneSync.removeAttribute("helpTopic"); |
||||
var weavePrefsDeck = E("weavePrefsDeck", doc); |
||||
if (weavePrefsDeck) |
||||
weavePrefsDeck.parentNode.removeChild(weavePrefsDeck); |
||||
if (prefWindow.currentPane == E("paneSync", doc)) |
||||
prefWindow.showPane(E("paneMain", doc)); |
||||
} |
||||
break; |
||||
case "about:preferences": |
||||
case "chrome://browser/content/preferences/in-content/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("category-sync", doc)); |
||||
} |
||||
} |
||||
updatePrefUI(doc); |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
// The IDs are the same, so I can reuse this for regular and in-content prefs
|
||||
function updatePrefUI(doc) { |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
hide(E("privateBrowsingAutoStart", doc)); |
||||
var privateBrowsingMenu = doc.querySelector("menuitem[value='dontremember']"); |
||||
hide(privateBrowsingMenu, doc); |
||||
} |
||||
if (config.disableCrashReporter) { |
||||
disable(E("submitCrashesBox", doc)); |
||||
} |
||||
if (config.disableSync) { |
||||
hide(E("noFxaAccount", doc)); |
||||
hide(E("hasFxaAccount", doc)); |
||||
} |
||||
if (config.noMasterPassword == true) { |
||||
hide(E("useMasterPassword", doc)); |
||||
hide(E("changeMasterPassword", doc)); |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
} |
||||
} |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/** |
||||
* Copied from https://github.com/jvillalobos/CTP-Manager/blob/master/extension/modules/permissions.js
|
||||
**/ |
||||
|
||||
/** |
||||
* Copyright 2013 Jorge Villalobos |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
**/ |
||||
|
||||
var EXPORTED_SYMBOLS = ["CTP"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var CTP = { |
||||
/** |
||||
* Cleans up the plugin name to a more readable form. |
||||
* Taken from /browser/base/content/pageinfo/permissions.js (Firefox 20) |
||||
* @param aPluginName the name to clean up. |
||||
* @return cleaned up plugin name. |
||||
*/ |
||||
makeNicePluginName : function(aPluginName) { |
||||
let newName = |
||||
aPluginName.replace(/[\s\d\.\-\_\(\)]+$/, ""). |
||||
replace(/\bplug-?in\b/i, "").trim(); |
||||
|
||||
return newName; |
||||
}, |
||||
|
||||
/** |
||||
* Gets the plugin permission string from the tag object. In Firefox 20, this |
||||
* is the plugin filename. In 21 an above, the file extension is removed and |
||||
* Flash and Java are special-cased. |
||||
* @param aTag the tag object with the plugin information. |
||||
* @return permission string that corresponds to the plugin in the tag. |
||||
*/ |
||||
getPluginPermissionFromTag : function(aTag) { |
||||
let permission = null; |
||||
let majorVersion = Services.appinfo.platformVersion.split(".")[0]; |
||||
|
||||
if (21 <= majorVersion) { |
||||
let mimeTypes = aTag.getMimeTypes(); |
||||
|
||||
if (CTP.isFlashPlugin(mimeTypes)) { |
||||
permission = "flash"; |
||||
} else if (CTP.isJavaPlugin(mimeTypes)) { |
||||
permission = "java"; |
||||
} else { |
||||
let lastPeriod = aTag.filename.lastIndexOf("."); |
||||
|
||||
permission = |
||||
((0 < lastPeriod) ? aTag.filename.substring(0, lastPeriod) : |
||||
aTag.filename); |
||||
// Remove digits at the end
|
||||
permission = permission.replace(/[0-9]+$/, ""); |
||||
permission = permission.toLowerCase(); |
||||
} |
||||
} else { |
||||
permission = aTag.filename; |
||||
} |
||||
|
||||
return permission; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Java plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Java plugin. |
||||
*/ |
||||
isJavaPlugin : function(aMimeTypes) { |
||||
let isJava = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if ((0 == mimeType.indexOf("application/x-java-vm")) || |
||||
(0 == mimeType.indexOf("application/x-java-applet")) || |
||||
(0 == mimeType.indexOf("application/x-java-bean"))) { |
||||
isJava = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isJava; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Flash plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Flash plugin. |
||||
*/ |
||||
isFlashPlugin : function(aMimeTypes) { |
||||
let isFlash = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if (0 == mimeType.indexOf("application/x-shockwave-flash")) { |
||||
isFlash = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isFlash; |
||||
} |
||||
}; |
@ -0,0 +1,629 @@
@@ -0,0 +1,629 @@
|
||||
/* ***** BEGIN LICENSE BLOCK ***** |
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
||||
* |
||||
* The contents of this file are subject to the Mozilla Public License Version |
||||
* 1.1 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* http://www.mozilla.org/MPL/
|
||||
* |
||||
* Software distributed under the License is distributed on an "AS IS" basis, |
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
||||
* for the specific language governing rights and limitations under the |
||||
* License. |
||||
* |
||||
* The Original Code is Preferences. |
||||
* |
||||
* The Initial Developer of the Original Code is Mozilla. |
||||
* Portions created by the Initial Developer are Copyright (C) 2008 |
||||
* the Initial Developer. All Rights Reserved. |
||||
* |
||||
* Contributor(s): |
||||
* Myk Melez <myk@mozilla.org> |
||||
* Daniel Aquino <mr.danielaquino@gmail.com> |
||||
* |
||||
* Alternatively, the contents of this file may be used under the terms of |
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or |
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
||||
* in which case the provisions of the GPL or the LGPL are applicable instead |
||||
* of those above. If you wish to allow use of your version of this file only |
||||
* under the terms of either the GPL or the LGPL, and not to allow others to |
||||
* use your version of this file under the terms of the MPL, indicate your |
||||
* decision by deleting the provisions above and replace them with the notice |
||||
* and other provisions required by the GPL or the LGPL. If you do not delete |
||||
* the provisions above, a recipient may use your version of this file under |
||||
* the terms of any one of the MPL, the GPL or the LGPL. |
||||
* |
||||
* ***** END LICENSE BLOCK ***** */ |
||||
|
||||
let EXPORTED_SYMBOLS = ["Preferences"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cr = Components.results; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// The minimum and maximum integers that can be set as preferences.
|
||||
// The range of valid values is narrower than the range of valid JS values
|
||||
// because the native preferences code treats integers as NSPR PRInt32s,
|
||||
// which are 32-bit signed integers on all platforms.
|
||||
const MAX_INT = Math.pow(2, 31) - 1; |
||||
const MIN_INT = -MAX_INT; |
||||
|
||||
function Preferences(args) { |
||||
if (isObject(args)) { |
||||
if (args.branch) |
||||
this._prefBranch = args.branch; |
||||
} |
||||
else if (args) |
||||
this._prefBranch = args; |
||||
this.isDefaultBranch = false; |
||||
} |
||||
|
||||
Preferences.prototype = { |
||||
/** |
||||
* Get the value of a pref, if any; otherwise return the default value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to get, or an array of prefs to get |
||||
* |
||||
* @param defaultValue |
||||
* the default value, if any, for prefs that don't have one |
||||
* |
||||
* @returns the value of the pref, if any; otherwise the default value |
||||
*/ |
||||
get: function(prefName, defaultValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(v => this.get(v, defaultValue)); |
||||
|
||||
return this._get(prefName, defaultValue); |
||||
}, |
||||
|
||||
// In all cases below, the preference might exist as a user pref, but not
|
||||
// have a default value. In those cases, get* throws. Return the default value.
|
||||
_get: function(prefName, defaultValue) { |
||||
switch (this._prefSvc.getPrefType(prefName)) { |
||||
case Ci.nsIPrefBranch.PREF_STRING: |
||||
try { |
||||
return this._prefSvc.getComplexValue(prefName, Ci.nsISupportsString).data; |
||||
} catch (ex) { |
||||
if (this.isDefaultBranch) |
||||
return defaultValue; |
||||
else |
||||
return this._prefSvc.getCharPref(prefName); |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INT: |
||||
try { |
||||
return this._prefSvc.getIntPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_BOOL: |
||||
try { |
||||
return this._prefSvc.getBoolPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INVALID: |
||||
return defaultValue; |
||||
|
||||
default: |
||||
// This should never happen.
|
||||
throw "Error getting pref " + prefName + "; its value's type is " + |
||||
this._prefSvc.getPrefType(prefName) + ", which I don't know " + |
||||
"how to handle."; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Set a preference to a value. |
||||
* |
||||
* You can set multiple prefs by passing an object as the only parameter. |
||||
* In that case, this method will treat the properties of the object |
||||
* as preferences to set, where each property name is the name of a pref |
||||
* and its corresponding property value is the value of the pref. |
||||
* |
||||
* @param prefName {String|Object} |
||||
* the name of the pref to set; or an object containing a set |
||||
* of prefs to set |
||||
* |
||||
* @param prefValue {String|Number|Boolean} |
||||
* the value to which to set the pref |
||||
* |
||||
* Note: Preferences cannot store non-integer numbers or numbers outside |
||||
* the signed 32-bit range -(2^31-1) to 2^31-1, If you have such a number, |
||||
* store it as a string by calling toString() on the number before passing |
||||
* it to this method, i.e.: |
||||
* Preferences.set("pi", 3.14159.toString()) |
||||
* Preferences.set("big", Math.pow(2, 31).toString()). |
||||
*/ |
||||
set: function(prefName, prefValue) { |
||||
if (isObject(prefName)) { |
||||
for (let [name, value] in Iterator(prefName)) |
||||
this.set(name, value); |
||||
return; |
||||
} |
||||
|
||||
this._set(prefName, prefValue); |
||||
}, |
||||
|
||||
_set: function(prefName, prefValue) { |
||||
let prefType; |
||||
if (typeof prefValue != "undefined" && prefValue != null) |
||||
prefType = prefValue.constructor.name; |
||||
|
||||
var existingPrefType = this._prefSvc.getPrefType(prefName); |
||||
if (existingPrefType != Ci.nsIPrefBranch.PREF_INVALID) |
||||
{ |
||||
// convert
|
||||
if (existingPrefType == Ci.nsIPrefBranch.PREF_INT && prefType == "String") |
||||
{ |
||||
prefValue = parseInt(prefValue); |
||||
if (isNaN(prefValue)) |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Number"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "String") |
||||
{ |
||||
if (prefValue == "true") |
||||
prefValue = true; |
||||
else if (prefValue == "false") |
||||
prefValue = false; |
||||
else |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Boolean"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "Number") |
||||
{ |
||||
prefValue = prefValue != 0; |
||||
prefType = "Boolean"; |
||||
} |
||||
} |
||||
|
||||
switch (prefType) { |
||||
case "String": |
||||
{ |
||||
try { |
||||
this._prefSvc.setStringPref(prefName, prefValue); |
||||
} catch (e) { |
||||
try { |
||||
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); |
||||
string.data = prefValue; |
||||
this._prefSvc.setComplexValue(prefName, Ci.nsISupportsString, string); |
||||
} catch (e2) { |
||||
Components.utils.reportError(e2); |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case "Number": |
||||
// We throw if the number is outside the range, since the result
|
||||
// will never be what the consumer wanted to store, but we only warn
|
||||
// if the number is non-integer, since the consumer might not mind
|
||||
// the loss of precision.
|
||||
if (prefValue > MAX_INT || prefValue < MIN_INT) |
||||
throw("you cannot set the " + prefName + " pref to the number " + |
||||
prefValue + ", as number pref values must be in the signed " + |
||||
"32-bit integer range -(2^31-1) to 2^31-1. To store numbers " + |
||||
"outside that range, store them as strings."); |
||||
try { |
||||
this._prefSvc.setIntPref(prefName, prefValue); |
||||
} catch (e) { |
||||
throw new Error(e.toString() + " - " + prefName); |
||||
} |
||||
if (prefValue % 1 != 0) |
||||
Cu.reportError("Warning: setting the " + prefName + " pref to the " + |
||||
"non-integer number " + prefValue + " converted it " + |
||||
"to the integer number " + this.get(prefName) + |
||||
"; to retain fractional precision, store non-integer " + |
||||
"numbers as strings."); |
||||
break; |
||||
|
||||
case "Boolean": |
||||
this._prefSvc.setBoolPref(prefName, prefValue); |
||||
break; |
||||
|
||||
default: |
||||
throw "can't set pref " + prefName + " to value '" + prefValue + |
||||
"'; it isn't a String, Number, or Boolean"; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a value. This is different from isSet |
||||
* because it returns true whether the value of the pref is a default value |
||||
* or a user-set value, while isSet only returns true if the value |
||||
* is a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a value; or, if the caller provided |
||||
* an array of pref names, an array of booleans indicating whether |
||||
* or not the prefs have values |
||||
*/ |
||||
has: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.has, this); |
||||
|
||||
return this._has(prefName); |
||||
}, |
||||
|
||||
_has: function(prefName) { |
||||
return (this._prefSvc.getPrefType(prefName) != Ci.nsIPrefBranch.PREF_INVALID); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. This is different |
||||
* from |has| because it returns true only if the value of the pref is a user- |
||||
* set value, while |has| returns true if the value of the pref is a default |
||||
* value or a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a user-set value; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs have user-set values |
||||
*/ |
||||
isSet: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.isSet, this); |
||||
|
||||
return (this.has(prefName) && this._prefSvc.prefHasUserValue(prefName)); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. Use isSet instead, |
||||
* which is equivalent. |
||||
* @deprecated |
||||
*/ |
||||
modified: function(prefName) { return this.isSet(prefName) }, |
||||
|
||||
reset: function(prefName) { |
||||
if (isArray(prefName)) { |
||||
prefName.map(v => this.reset(v)); |
||||
return; |
||||
} |
||||
|
||||
this._reset(prefName); |
||||
}, |
||||
|
||||
_reset: function(prefName) { |
||||
try { |
||||
this._prefSvc.clearUserPref(prefName); |
||||
} |
||||
catch(ex) { |
||||
// The pref service throws NS_ERROR_UNEXPECTED when the caller tries
|
||||
// to reset a pref that doesn't exist or is already set to its default
|
||||
// value. This interface fails silently in those cases, so callers
|
||||
// can unconditionally reset a pref without having to check if it needs
|
||||
// resetting first or trap exceptions after the fact. It passes through
|
||||
// other exceptions, however, so callers know about them, since we don't
|
||||
// know what other exceptions might be thrown and what they might mean.
|
||||
if (ex.result != Cr.NS_ERROR_UNEXPECTED) |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* If you need to know the default values, without resetting the actual |
||||
* user prefs, you can use this. |
||||
* @returns {Preferences} a new Preferences object, which accesses |
||||
* the defaults rather than the user prefs. |
||||
* *Only* call get() on this. |
||||
* If you call set(), you will modify the defaults, so don't do that! |
||||
*/ |
||||
get defaults() { |
||||
// nsIPrefService
|
||||
let defaultBranch = Services.prefs. |
||||
getDefaultBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
let prefs = new Preferences(this._prefBranch); |
||||
// override. nasty, but this is internal, so OK.
|
||||
Object.defineProperty(prefs, "_prefSvc", { |
||||
get: function() { |
||||
return defaultBranch; |
||||
} |
||||
}); |
||||
prefs.isDefaultBranch = true; |
||||
return prefs; |
||||
}, |
||||
|
||||
/** |
||||
* Lock a pref so it can't be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
* @param prefValue {String} (optional) |
||||
* default value of pref to lock only works if prefName isn't an array |
||||
*/ |
||||
lock: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.lock, this); |
||||
else if (typeof prefValue != "undefined") |
||||
this.defaults.set(prefName, prefValue); |
||||
|
||||
this._prefSvc.lockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Unlock a pref so it can be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
*/ |
||||
unlock: function(prefName) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.unlock, this); |
||||
|
||||
this._prefSvc.unlockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref is locked against changes and |
||||
* if it is set to the passedi n value |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* @param prefValue {String|Number|Boolean}} |
||||
* the pref value to compare against |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref is locked; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs are locked |
||||
* If a pref value was specified returns whether or not the pref |
||||
* was locked and equal to the passed in value. |
||||
*/ |
||||
locked: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.locked, this); |
||||
|
||||
if (prefValue) |
||||
return this._prefSvc.prefIsLocked(prefName) && (this.get(prefName) == prefValue); |
||||
else |
||||
return this._prefSvc.prefIsLocked(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Start observing a pref. |
||||
* |
||||
* The callback can be a function or any object that implements nsIObserver. |
||||
* When the callback is a function and thisObject is provided, it gets called |
||||
* as a method of thisObject. |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref to observe |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code to notify when the pref changes; |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object to use as |this| when calling a Function callback; |
||||
* |
||||
* @returns the wrapped observer |
||||
*/ |
||||
observe: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
let observer = new PrefObserver(fullPrefName, callback, thisObject); |
||||
Preferences._prefSvc.addObserver(fullPrefName, observer, true); |
||||
observers.push(observer); |
||||
|
||||
return observer; |
||||
}, |
||||
|
||||
/** |
||||
* Stop observing a pref. |
||||
* |
||||
* You must call this method with the same prefName, callback, and thisObject |
||||
* with which you originally registered the observer. However, you don't have |
||||
* to call this method on the same exact instance of Preferences; you can call |
||||
* it on any instance. For example, the following code first starts and then |
||||
* stops observing the "foo.bar.baz" preference: |
||||
* |
||||
* let observer = function() {...}; |
||||
* Preferences.observe("foo.bar.baz", observer); |
||||
* new Preferences("foo.bar.").ignore("baz", observer); |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref being observed |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code being notified when the pref changes |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object being used as |this| when calling a Function callback |
||||
*/ |
||||
ignore: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
// This seems fairly inefficient, but I'm not sure how much better we can
|
||||
// make it. We could index by fullBranch, but we can't index by callback
|
||||
// or thisObject, as far as I know, since the keys to JavaScript hashes
|
||||
// (a.k.a. objects) can apparently only be primitive values.
|
||||
let [observer] = observers.filter(v => v.prefName == fullPrefName && |
||||
v.callback == callback && |
||||
v.thisObject == thisObject); |
||||
|
||||
if (observer) { |
||||
Preferences._prefSvc.removeObserver(fullPrefName, observer); |
||||
observers.splice(observers.indexOf(observer), 1); |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Same as observe(), but automatically unregisters itself when |
||||
* the window closes, saving you from writing an unload handler and |
||||
* calling ignore(). |
||||
* @param win {nsIDOMWindow} your |window| |
||||
*/ |
||||
observeAuto: function(win, prefName, callback, thisObject) { |
||||
if (!win instanceof Ci.nsIDOMWindow) |
||||
throw "Need your |window| as first parameter"; |
||||
this.observe(prefName, callback, thisObject); |
||||
var self = this; |
||||
win.addEventListener("unload", function() |
||||
{ |
||||
self.ignore(prefName, callback, thisObject); |
||||
}, false); |
||||
win = null; // don't let closure hold on to window unnecessarily
|
||||
}, |
||||
|
||||
resetBranch: function(prefBranch) { |
||||
try { |
||||
this._prefSvc.resetBranch(prefBranch); |
||||
} |
||||
catch(ex) { |
||||
// The current implementation of nsIPrefBranch in Mozilla
|
||||
// doesn't implement resetBranch, so we do it ourselves.
|
||||
if (ex.result == Cr.NS_ERROR_NOT_IMPLEMENTED) |
||||
this.reset(this._prefSvc.getChildList(prefBranch, [])); |
||||
else |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Returns all child prefs of this pref branch. |
||||
* This equals nsIPrefBranch.getChildList(). |
||||
* This allows you to do e.g. |
||||
* var myPrefs = new Preferences("extensions.cooler."); |
||||
* var contents = myPrefs.branch("contents."); |
||||
* for each (let prefname in contents.childPrefNames()) |
||||
* dump("have " + contents.get(prefname) + " " + prefname + "\n"); |
||||
* |
||||
* @returns {Array of String} The names of the children, |
||||
* without the base pref branch, but with subbranch. |
||||
*/ |
||||
childPrefNames : function() { |
||||
return this._prefSvc.getChildList("", []); |
||||
}, |
||||
|
||||
/** |
||||
* Returns an nsIPrefBranch for the pref branch that this object stands for. |
||||
* You can use this to use functions that are not supported here. |
||||
* @returns {nsIPrefBranch} |
||||
*/ |
||||
get mozillaPrefBranch() { |
||||
return this._prefSvc; |
||||
}, |
||||
|
||||
/** |
||||
* Returns the base pref name that this object stands for. |
||||
* E.g. "extensions.yourcooler."; |
||||
* @returns {String} |
||||
*/ |
||||
get prefBranchName() { |
||||
return this._prefBranch; |
||||
}, |
||||
|
||||
/** |
||||
* Returns an Preferences object for an sub pref branch |
||||
* underneath the current pref branch. |
||||
* @param subbranch {String} Will be appended to the |
||||
* current pref branch. Don't forget the trailing dot, |
||||
* where necessary. |
||||
* E.g. "contents." |
||||
* @returns {Preferences} |
||||
*/ |
||||
branch : function(subbranch) { |
||||
return new Preferences(this._prefBranch + subbranch); |
||||
}, |
||||
|
||||
/** |
||||
* The branch of the preferences tree to which this instance provides access. |
||||
* @private |
||||
*/ |
||||
_prefBranch: "", |
||||
|
||||
/** |
||||
* Preferences Service |
||||
* @private |
||||
*/ |
||||
get _prefSvc() { |
||||
// nsIPrefService
|
||||
let prefSvc = Services.prefs. |
||||
getBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
Object.defineProperty(this, "_prefSvc", { |
||||
get: function() { |
||||
return prefSvc; |
||||
} |
||||
}); |
||||
return this._prefSvc; |
||||
} |
||||
|
||||
}; |
||||
|
||||
// Give the constructor the same prototype as its instances, so users can access
|
||||
// preferences directly via the constructor without having to create an instance
|
||||
// first.
|
||||
Preferences.__proto__ = Preferences.prototype; |
||||
|
||||
/** |
||||
* A cache of pref observers. |
||||
* |
||||
* We use this to remove observers when a caller calls Preferences::ignore. |
||||
* |
||||
* All Preferences instances share this object, because we want callers to be |
||||
* able to remove an observer using a different Preferences object than the one |
||||
* with which they added it. That means we have to identify the observers |
||||
* in this object by their complete pref name, not just their name relative to |
||||
* the root branch of the Preferences object with which they were created. |
||||
*/ |
||||
let observers = []; |
||||
|
||||
function PrefObserver(prefName, callback, thisObject) { |
||||
this.prefName = prefName; |
||||
this.callback = callback; |
||||
this.thisObject = thisObject; |
||||
} |
||||
|
||||
PrefObserver.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), |
||||
|
||||
observe: function(subject, topic, data) { |
||||
// The pref service only observes whole branches, but we only observe
|
||||
// individual preferences, so we check here that the pref that changed
|
||||
// is the exact one we're observing (and not some sub-pref on the branch).
|
||||
if (data != this.prefName) |
||||
return; |
||||
|
||||
if (typeof this.callback == "function") { |
||||
let prefValue = Preferences.get(this.prefName); |
||||
|
||||
if (this.thisObject) |
||||
this.callback.call(this.thisObject, prefValue); |
||||
else |
||||
this.callback(prefValue); |
||||
} |
||||
else // typeof this.callback == "object" (nsIObserver)
|
||||
this.callback.observe(subject, topic, data); |
||||
} |
||||
}; |
||||
|
||||
function isArray(val) { |
||||
// We can't check for |val.constructor == Array| here, since the value
|
||||
// might be from a different context whose Array constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Array"); |
||||
} |
||||
|
||||
function isObject(val) { |
||||
// We can't check for |val.constructor == Object| here, since the value
|
||||
// might be from a different context whose Object constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Object"); |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* 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"; |
||||
|
||||
/** |
||||
* JS module implementation of nsIDOMJSWindow.setTimeout and clearTimeout. |
||||
*/ |
||||
|
||||
this.EXPORTED_SYMBOLS = ["setTimeout", "clearTimeout"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
|
||||
let gNextTimeoutId = 1; // setTimeout must return a positive integer
|
||||
|
||||
let gTimeoutTable = new Map(); // int -> nsITimer
|
||||
|
||||
this.setTimeout = function setTimeout(aCallback, aMilliseconds) { |
||||
let id = gNextTimeoutId++; |
||||
let args = Array.slice(arguments, 2); |
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
||||
timer.initWithCallback(function setTimeout_timer() { |
||||
gTimeoutTable.delete(id); |
||||
aCallback.apply(null, args); |
||||
}, aMilliseconds, timer.TYPE_ONE_SHOT); |
||||
|
||||
gTimeoutTable.set(id, timer); |
||||
return id; |
||||
} |
||||
|
||||
this.clearTimeout = function clearTimeout(aId) { |
||||
if (gTimeoutTable.has(aId)) { |
||||
gTimeoutTable.get(aId).cancel(); |
||||
gTimeoutTable.delete(aId); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = ["errorCritical"]; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
function errorCritical(e) |
||||
{ |
||||
Services.prompt.alert(null, "", e); |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIID7DCCAtSgAwIBAgIJAKXaTovgoTIUMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD |
||||
VQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdvcmsxEjAQBgNVBAoMCVB1cnBsZUky |
||||
UDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR0w |
||||
GwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmkycDAeFw0xODA4MjQyMTQ3NTJaFw0y |
||||
MzA4MjMyMTQ3NTJaMIGCMQswCQYDVQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdv |
||||
cmsxEjAQBgNVBAoMCVB1cnBsZUkyUDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRp |
||||
ZmljYXRpb24gQXV0aG9yaXR5MR0wGwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmky |
||||
cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAZnN/U5bgkmiBqp/Np |
||||
yiMOkUPjr2tLhV78Oba46xDLA6AiQ7yTPg+/ZYPIfbF2dPBTpfgGdly2M1xymRKc |
||||
3Pa+IUXkLw6oCA+lFzOFW0Swtekk9HRAgGyHgj6/Hvagva5Wer4HJIO1qRsFPew+ |
||||
XcM3uhhiXoiO8o+YGpJ/7kz0gED3p2b9OVsLPd8G/GfdR3miD+Au+kUx/27z/WdJ |
||||
ISfFILFnYeYZGffrpRcFtoGwuZUCugwnbLtpQpNKuGq8jDidm1v6Rb85JmkoH3Sg |
||||
lRaX1MK0aPhM4WfCf7aWCNe669FAWPNB3Ya2lue7ewPLI84ZUEqcoJwmWn2ci2SU |
||||
EXUCAwEAAaNjMGEwHQYDVR0OBBYEFG3hwzikpXqMasw678OHM8uLyjEoMB8GA1Ud |
||||
IwQYMBaAFG3hwzikpXqMasw678OHM8uLyjEoMA8GA1UdEwQIMAYBAf8CAQAwDgYD |
||||
VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQA07URxJMI/Ta9y1wIg+k7o |
||||
1aHXsl6YOXmd2ymhKZhZHrZlutE2U19IQSoEV0SBddP9D05xD6Ovsrwo7caeYzNt |
||||
+2DJnlJ2IY61NqYUIDEoJyNPL/S7WleH+xO+bcSqWvbntTNYAD6WQVfHCAimVE6P |
||||
RnSZGqG089i84DRCyrh/6F1OxnBd6j14z+2ctQD+h6NlQXiCAUIwzVirYoE7oGpH |
||||
Xta7Ei+RDvBXLXLAQRdXpzSP/Ddf7MCJzmH3VYAy+0sVuHr09hpFMtC59hTrdLVD |
||||
/qma0eKrBr1DGH6QrZMZDqpNfv4wUPyVQBsRbbn2/1fL9IqK43CIj8RUllCOsmyU |
||||
-----END CERTIFICATE----- |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIFxzCCA6+gAwIBAgIQZfqn0yiJL3dGgCjeOeWS6DANBgkqhkiG9w0BAQsFADBw |
||||
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK |
||||
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ |
||||
aG90dHVuYUBtYWlsLmkycDAeFw0xNjExMDkwMzE1MzJaFw0yNjExMDkwMzE1MzJa |
||||
MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV |
||||
BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD |
||||
DBBob3R0dW5hQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC |
||||
AgEA21Bfgcc9VVH4l2u1YvYlTw2OPUyQb16X2IOW0PzdsUO5W78Loueu974BkiKi |
||||
84lQZanLr0OwEopdfutGc6gegSLmwaWx5YCG5uwpLOPkDiObfX+nptH6As/B1cn+ |
||||
mzejYdVKRnWd7EtHW0iseSsILBK1YbGw4AGpXJ8k18DJSzUt2+spOkpBW6XqectN |
||||
8y2JDSTns8yiNxietVeRN/clolDXT9ZwWHkd+QMHTKhgl3Uz1knOffU0L9l4ij4E |
||||
oFgPfQo8NL63kLM24hF1hM/At7XvE4iOlObFwPXE+H5EGZpT5+A7Oezepvd/VMzM |
||||
tCJ49hM0OlR393tKFONye5GCYeSDJGdPEB6+rBptpRrlch63tG9ktpCRrg2wQWgC |
||||
e3aOE1xVRrmwiTZ+jpfsOCbZrrSA/C4Bmp6AfGchyHuDGGkRU/FJwa1YLJe0dkWG |
||||
ITLWeh4zeVuAS5mctdv9NQ5wflSGz9S8HjsPBS5+CDOFHh4cexXRG3ITfk6aLhuY |
||||
KTMlkIO4SHKmnwAvy1sFlsqj6PbfVjpHPLg625fdNxBpe57TLxtIdBB3C7ccQSRW |
||||
+UG6Cmbcmh80PbsSR132NLMlzLhbaOjxeCWWJRo6cLuHBptAFMNwqsXt8xVf9M0N |
||||
NdJoKUmblyvjnq0N8aMEqtQ1uGMTaCB39cutHQq+reD/uzsCAwEAAaNdMFswDgYD |
||||
VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV |
||||
HRMBAf8EBTADAQH/MBkGA1UdDgQSBBBob3R0dW5hQG1haWwuaTJwMA0GCSqGSIb3 |
||||
DQEBCwUAA4ICAQCibFV8t4pajP176u3jx31x1kgqX6Nd+0YFARPZQjq99kUyoZer |
||||
GyHGsMWgM281RxiZkveHxR7Hm7pEd1nkhG3rm+d7GdJ2p2hujr9xUvl0zEqAAqtm |
||||
lkYI6uJ13WBjFc9/QuRIdeIeSUN+eazSXNg2nJhoV4pF9n2Q2xDc9dH4GWO93cMX |
||||
JPKVGujT3s0b7LWsEguZBPdaPW7wwZd902Cg/M5fE1hZQ8/SIAGUtylb/ZilVeTS |
||||
spxWP1gX3NT1SSvv0s6oL7eADCgtggWaMxEjZhi6WMnPUeeFY8X+6trkTlnF9+r/ |
||||
HiVvvzQKrPPtB3j1xfQCAF6gUKN4iY+2AOExv4rl/l+JJbPhpd/FuvD8AVkLMZ8X |
||||
uPe0Ew2xv30cc8JjGDzQvoSpBmVTra4f+xqH+w8UEmxnx97Ye2aUCtnPykACnFte |
||||
oT97K5052B1zq+4fu4xaHZnEzPYVK5POzOufNLPgciJsWrR5GDWtHd+ht/ZD37+b |
||||
+j1BXpeBWUBQgluFv+lNMVNPJxc2OMELR1EtEwXD7mTuuUEtF5Pi63IerQ5LzD3G |
||||
KBvXhMB0XhpE6WG6pBwAvkGf5zVv/CxClJH4BQbdZwj9HYddfEQlPl0z/XFR2M0+ |
||||
9/8nBfGSPYIt6KeHBCeyQWTdE9gqSzMwTMFsennXmaT8gyc7eKqKF6adqw== |
||||
-----END CERTIFICATE----- |
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
[XRE] |
||||
EnableProfileMigrator=0 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
resource cck2 modules/ |
@ -0,0 +1,154 @@
@@ -0,0 +1,154 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gForceExternalHandler = false; |
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "extProtocolSvc", |
||||
"@mozilla.org/uriloader/external-protocol-service;1", "nsIExternalProtocolService"); |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
// If the parent document is a local file, don't do anything
|
||||
// Links will just work
|
||||
if (doc.location.href.indexOf("file://") == 0) { |
||||
return; |
||||
} |
||||
var links = event.target.getElementsByTagName("a"); |
||||
for (var i=0; i < links.length; i++) { |
||||
var link = links[i]; |
||||
if (link.href.indexOf("file://") != 0) { |
||||
continue; |
||||
} |
||||
link.addEventListener("click", function(link) { |
||||
return function(event) { |
||||
event.preventDefault(); |
||||
if (gForceExternalHandler) { |
||||
extProtocolSvc.loadUrl(Services.io.newURI(link.href, null, null)); |
||||
} else { |
||||
var target = "_self"; |
||||
if (link.hasAttribute("target")) { |
||||
target = link.getAttribute("target"); |
||||
} |
||||
// If we were told somewhere other than current (based on modifier keys), use it
|
||||
var where = whereToOpenLink(event); |
||||
if (where != "current" || target == "_blank") { |
||||
sendAsyncMessage("cck2:open-url", { |
||||
"url": link.href, |
||||
"where": (target == "_blank") ? "tab" : where |
||||
}); |
||||
return; |
||||
} |
||||
switch (target) { |
||||
case "_self": |
||||
link.ownerDocument.location = link.href; |
||||
break; |
||||
case "_parent": |
||||
link.ownerDocument.defaultView.parent.document.location = link.href; |
||||
break; |
||||
case "_top": |
||||
link.ownerDocument.defaultView.top.document.location = link.href; |
||||
break; |
||||
default: |
||||
// Attempt to find the iframe that this goes into
|
||||
var iframes = doc.defaultView.parent.document.getElementsByName(target); |
||||
if (iframes.length > 0) { |
||||
iframes[0].contentDocument.location = link.href; |
||||
} else { |
||||
link.ownerDocument.location = link.href; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}(link), false); |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.checkloaduri.enabled") == "allAccess") { |
||||
gForceExternalHandler = !extProtocolSvc.isExposedProtocol('file'); |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} catch (e) {} |
||||
} |
||||
|
||||
|
||||
/* Copied from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/utilityOverlay.js?raw=1 */ |
||||
|
||||
function getBoolPref(prefname, def) |
||||
{ |
||||
try { |
||||
return Services.prefs.getBoolPref(prefname); |
||||
} |
||||
catch(er) { |
||||
return def; |
||||
} |
||||
} |
||||
|
||||
/* whereToOpenLink() looks at an event to decide where to open a link. |
||||
* |
||||
* The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). |
||||
* |
||||
* On Windows, the modifiers are: |
||||
* Ctrl new tab, selected |
||||
* Shift new window |
||||
* Ctrl+Shift new tab, in background |
||||
* Alt save |
||||
* |
||||
* Middle-clicking is the same as Ctrl+clicking (it opens a new tab). |
||||
* |
||||
* Exceptions: |
||||
* - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. |
||||
* (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) |
||||
* - Alt is hard to use in context menus, because pressing Alt closes the menu. |
||||
* - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". |
||||
* - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. |
||||
*/ |
||||
function whereToOpenLink( e, ignoreButton, ignoreAlt ) |
||||
{ |
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm"); |
||||
|
||||
// This method must treat a null event like a left click without modifier keys (i.e.
|
||||
// e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 })
|
||||
// for compatibility purposes.
|
||||
if (!e) |
||||
return "current"; |
||||
|
||||
var shift = e.shiftKey; |
||||
var ctrl = e.ctrlKey; |
||||
var meta = e.metaKey; |
||||
var alt = e.altKey && !ignoreAlt; |
||||
|
||||
// ignoreButton allows "middle-click paste" to use function without always opening in a new window.
|
||||
var middle = !ignoreButton && e.button == 1; |
||||
var middleUsesTabs = true; |
||||
|
||||
// Don't do anything special with right-mouse clicks. They're probably clicks on context menu items.
|
||||
|
||||
var metaKey = AppConstants.platform == "macosx" ? meta : ctrl; |
||||
if (metaKey || (middle && middleUsesTabs)) |
||||
return shift ? "tabshifted" : "tab"; |
||||
|
||||
if (alt && getBoolPref("browser.altClickSave", false)) |
||||
return "save"; |
||||
|
||||
if (shift || (middle && !middleUsesTabs)) |
||||
return "window"; |
||||
|
||||
return "current"; |
||||
} |
@ -0,0 +1,183 @@
@@ -0,0 +1,183 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gAllowedPasteSites = []; |
||||
var gAllowedCutCopySites = []; |
||||
var gDeniedPasteSites = []; |
||||
var gDeniedCutCopySites = []; |
||||
var gDefaultPastePolicy = false; |
||||
var gDefaultCutCopyPolicy = false; |
||||
|
||||
function allowCutCopy(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultCutCopyPolicy == true) { |
||||
for (var i=0; i < gDeniedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedCutCopySites[i]) == 0) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedCutCopySites[i]) == 0) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function allowPaste(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultPastePolicy == true) { |
||||
for (var i=0; i < gDeniedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedPasteSites[i]) == 0) { |
||||
return false; |
||||
break; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedPasteSites[i]) == 0) { |
||||
return true; |
||||
break; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function myExecCommand(doc, originalExecCommand) { |
||||
return function(aCommandName, aShowDefaultUI, aValueArgument) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalExecCommand.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
function myQueryCommandSupported(doc, originalQueryCommandSupported) { |
||||
return function(aCommandName) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalQueryCommandSupported.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
var cutCopyAllowed = allowCutCopy(doc); |
||||
var pasteAllowed = allowPaste(doc); |
||||
if (!cutCopyAllowed && !pasteAllowed) { |
||||
return; |
||||
} |
||||
var originalExecCommand = Cu.waiveXrays(doc).execCommand; |
||||
Cu.exportFunction(myExecCommand(doc, originalExecCommand), doc, {defineAs: "execCommand"}); |
||||
var originalQueryCommandSupported = Cu.waiveXrays(doc).queryCommandSupported; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandSupported), doc, {defineAs: "queryCommandSupported"}); |
||||
var originalQueryCommandEnabled = Cu.waiveXrays(doc).queryCommandEnabled; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandEnabled), doc, {defineAs: "queryCommandEnabled"}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.cutcopy") == "allAccess") { |
||||
gDefaultCutCopyPolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.paste") == "allAccess") { |
||||
gDefaultPastePolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
var policies = []; |
||||
policies = Services.prefs.getCharPref("capability.policy.policynames").split(', '); |
||||
for (var i=0; i < policies.length; i++ ) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "allAccess") { |
||||
var allowedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedCutCopySites.length; j++) { |
||||
gAllowedCutCopySites.push(allowedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "noAccess") { |
||||
var deniedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedCutCopySites.length; j++) { |
||||
gDeniedCutCopySites.push(deniedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "allAccess") { |
||||
var allowedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedPasteSites.length; j++) { |
||||
gAllowedPasteSites.push(allowedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "noAccess") { |
||||
var deniedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedPasteSites.length; j++) { |
||||
gDeniedPasteSites.push(deniedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
} |
||||
} catch (e) {} |
||||
if (gDefaultCutCopyPolicy || gDefaultPastePolicy || |
||||
gAllowedCutCopySites.length > 0 || gAllowedPasteSites> 0) { |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,111 @@
@@ -0,0 +1,111 @@
|
||||
/* This file overlays about:addons. It does the following: */ |
||||
/* Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1132971 */ |
||||
/* Hide the "Install Add-on From File" menu if xpinstall.enabled is false */ |
||||
/* Hides the discover pane if xpinstall.enabled is false */ |
||||
/* Hides the add-on entry if specified in the CCK2 config */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var addonId = "cck2wizard@kaply.com"; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:addons": |
||||
case "chrome://mozapps/content/extensions/extensions.xul": |
||||
var configs = CCK2.getConfigs(); |
||||
var hiddenAddons = []; |
||||
var requiredAddons = []; |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config && "extension" in config && config.extension.hide) { |
||||
hiddenAddons.push(config.extension.id); |
||||
} |
||||
if (config.requiredAddons) { |
||||
requiredAddons.push.apply(requiredAddons, config.requiredAddons.split(",")); |
||||
} |
||||
} |
||||
if (hiddenAddons.length > 0 || requiredAddons.length > 0) { |
||||
var ss; |
||||
for (var i = 0; i < doc.styleSheets.length; i++) { |
||||
if (doc.styleSheets[i].href == "chrome://mozapps/skin/extensions/extensions.css") { |
||||
ss = doc.styleSheets[i]; |
||||
break; |
||||
} |
||||
} |
||||
for (var i=0; i < hiddenAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + hiddenAddons[i] + "'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
for (var i=0; i < requiredAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='disable-btn'] { display: none;}", ss.cssRules.length); |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='remove-btn'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
if (requiredAddons.length > 0) { |
||||
win.gViewController.commands.cmd_disableItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_disableItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
win.gViewController.commands.cmd_uninstallItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_uninstallItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
} |
||||
} |
||||
var showDiscoverPane = true; |
||||
var xpinstallEnabled = true; |
||||
try { |
||||
xpinstallEnabled = Services.prefs.getBoolPref("xpinstall.enabled"); |
||||
} catch (e) {} |
||||
try { |
||||
showDiscoverPane = Services.prefs.getBoolPref("extensions.getAddons.showPane"); |
||||
} catch (e) {} |
||||
if (!xpinstallEnabled || !showDiscoverPane) { |
||||
// Work around Mozilla bug 1132971
|
||||
// Hide the discover pane if it is the selected pane
|
||||
if (E("view-port", doc) && E("view-port", doc).selectedIndex == 0) { |
||||
try { |
||||
win.gViewController.loadView("addons://list/extension"); |
||||
} catch (ex) { |
||||
// This fails with Webconverger installed. Ignore it.
|
||||
} |
||||
} |
||||
} |
||||
if (!xpinstallEnabled) { |
||||
// Hide the "Install Add-on From File" separator
|
||||
hide(E("utils-installFromFile-separator", doc)); |
||||
// Hide the "Install Add-on From File" menuitem
|
||||
hide(E("utils-installFromFile", doc)); |
||||
win.gDragDrop.onDragOver = function(event) { |
||||
event.dataTransfer.dropEffect = "none"; |
||||
event.stopPropagation(); |
||||
event.preventDefault(); |
||||
}; |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
/* This file is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1139509 */ |
||||
/* It bolds the Firefox version in the about dialog and unbolds the distribution information */ |
||||
/* It can be removed once Firefox 38 ESR is out of support */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/aboutDialog.xul": |
||||
doc.querySelector("#version").style.fontWeight = "bold"; |
||||
doc.querySelector("#distribution").style.fontWeight = "normal"; |
||||
doc.querySelector("#distributionId").style.fontWeight = "normal"; |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/* This file overrides about:home. It does the following: |
||||
* Remove the sync button if Sync is disabled |
||||
* Remove the Addons button if Sync is disabled |
||||
* Remove the snippets if snippets are disabled |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "content-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:home": |
||||
case "chrome://browser/content/abouthome/aboutHome.xhtml": |
||||
if (!configs) { |
||||
// TODO - Make this Async
|
||||
configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
remove(E("sync", doc)); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
remove(E("addons", doc)); |
||||
} |
||||
if (config.disableWebApps) { |
||||
remove(E("apps", doc)); |
||||
} |
||||
if (config.removeSnippets) { |
||||
var snippets = E("snippets", doc); |
||||
if (snippets) { |
||||
snippets.style.display = "none"; |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(config.hiddenUI[i]); |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
uiElement.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "content-document-global-created", false); |
||||
|
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(observer, "content-document-global-created", false); |
||||
}) |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* This file overrides about:support It does the following: |
||||
* Remove the reset Firefox button if disableResetFirefox is set |
||||
* Remove the safe mode Button if disableSafeMode is set |
||||
* Remove the box if both are set |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:support": |
||||
case "chrome://global/content/aboutSupport.xhtml": |
||||
if (!configs) { |
||||
configs = CCK2.getConfigs(); |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableResetFirefox) { |
||||
remove(E("reset-box", doc)); |
||||
} |
||||
if (config.disableSafeMode) { |
||||
remove(E("safe-mode-box", doc)); |
||||
} |
||||
if (config.disableResetFirefox && |
||||
config.disableSafeMode) { |
||||
remove(E("action-box", doc)); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,373 @@
@@ -0,0 +1,373 @@
|
||||
/* This file modifies the main browser window. It does the following: |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource:///modules/CustomizableUI.jsm"); |
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/browser.xul": |
||||
// Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1149617
|
||||
var origSetReportPhishingMenu = win.gSafeBrowsing.setReportPhishingMenu; |
||||
win.gSafeBrowsing.setReportPhishingMenu = function() { |
||||
try { |
||||
origSetReportPhishingMenu(); |
||||
} catch (e) {} |
||||
} |
||||
|
||||
win.addEventListener("unload", function onUnload(event) { |
||||
win.removeEventListener("unload", onUnload, false); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).removeEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
}); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).addEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
var appMenuPopup = doc.getElementById("appMenu-popup"); |
||||
if (appMenuPopup) { |
||||
E("appMenu-popup", doc).addEventListener("popupshowing", onAppMenuShowing, false); |
||||
} |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
config = configs[id]; |
||||
if (config.disablePrivateBrowsing && |
||||
PrivateBrowsingUtils.isWindowPrivate(win)) { |
||||
win.setTimeout(function() { |
||||
Services.prompt.alert(win, "Private Browsing", "Private Browsing has been disabled by your administrator"); |
||||
win.close(); |
||||
}, 0, false); |
||||
} |
||||
if (config.disablePrivateBrowsing) { |
||||
disablePrivateBrowsing(doc); |
||||
} |
||||
if (config.disableSync) { |
||||
disableSync(doc); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
disableAddonsManager(doc); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
Services.tm.mainThread.dispatch(function() { |
||||
removeDeveloperTools(doc); |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.disableErrorConsole) { |
||||
disableErrorConsole(doc); |
||||
} |
||||
if (config.disableFirefoxHealthReport) { |
||||
var healthReportMenu = doc.getElementById("healthReport"); |
||||
if (healthReportMenu) { |
||||
healthReportMenu.parentNode.removeChild(healthReportMenu); |
||||
} |
||||
} |
||||
if (config.removeSafeModeMenu) { |
||||
hide(E("helpSafeMode", doc)); |
||||
} |
||||
if (config.titlemodifier) { |
||||
doc.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier); |
||||
} |
||||
if (config.removeSetDesktopBackground) { |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-setDesktopBackground", doc)) { |
||||
E("context-setDesktopBackground", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableWebApps) { |
||||
CustomizableUI.destroyWidget("web-apps-button"); |
||||
hide(E("menu_openApps", doc)); |
||||
} |
||||
if (config.disableHello) { |
||||
CustomizableUI.destroyWidget("loop-button"); |
||||
hide(E("menu_openLoop", doc)); |
||||
} |
||||
if (config.disablePocket) { |
||||
CustomizableUI.destroyWidget("pocket-button"); |
||||
} |
||||
if (config.disableSharePage) { |
||||
CustomizableUI.destroyWidget("social-share-button"); |
||||
// Because these are on a context menu, we can't use "hidden"
|
||||
if (E("context-sharelink", doc)) { |
||||
E("context-sharelink", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareselect", doc)) { |
||||
E("context-shareselect", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareimage", doc)) { |
||||
E("context-shareimage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharevideo", doc)) { |
||||
E("context-sharevideo", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharepage", doc)) { |
||||
E("context-sharepage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableSocialAPI) { |
||||
win.SocialActivationListener = {}; |
||||
} |
||||
if (config.disableForget) { |
||||
CustomizableUI.destroyWidget("panic-button"); |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
if (config.helpMenu) { |
||||
// We need to run this function on a delay, because we won't know
|
||||
// if the about menu is hidden for mac until after it is run.
|
||||
Services.tm.mainThread.dispatch(function() { |
||||
var helpMenuPopup = doc.getElementById("menu_HelpPopup"); |
||||
var menuitem = doc.createElement("menuitem"); |
||||
menuitem.setAttribute("label", config.helpMenu.label); |
||||
if ("accesskey" in config.helpMenu) { |
||||
menuitem.setAttribute("accesskey", config.helpMenu.accesskey); |
||||
} |
||||
menuitem.setAttribute("oncommand", "openUILink('" + config.helpMenu.url + "');"); |
||||
menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);"); |
||||
if (!E("aboutName", doc) || E("aboutName", doc).hidden) { |
||||
// Mac
|
||||
helpMenuPopup.appendChild(menuitem); |
||||
} else { |
||||
helpMenuPopup.insertBefore(menuitem, E("aboutName", doc)); |
||||
helpMenuPopup.insertBefore(doc.createElement("menuseparator"), |
||||
E("aboutName", doc)); |
||||
} |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.firstrun || config.upgrade) { |
||||
if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) { |
||||
CustomizableUI.setToolbarVisibility("PersonalToolbar", "true"); |
||||
} |
||||
if (config.displayMenuBar) { |
||||
CustomizableUI.setToolbarVisibility("toolbar-menubar", "true"); |
||||
} |
||||
if (config.showSearchBar) { |
||||
CustomizableUI.addWidgetToArea("search-container", CustomizableUI.AREA_NAVBAR, |
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1); |
||||
} |
||||
config.firstrun = false; |
||||
config.upgrade = false; |
||||
} |
||||
} |
||||
break; |
||||
case "chrome://browser/content/places/places.xul": |
||||
case "chrome://browser/content/bookmarks/bookmarksPanel.xul": |
||||
case "chrome://browser/content/history/history-panel.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
if (E("placesContext_open:newprivatewindow", doc)) { |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function disableSync(doc) { |
||||
var win = doc.defaultView; |
||||
if (win.gSyncUI) { |
||||
var mySyncUI = { |
||||
init: function() { |
||||
return; |
||||
}, |
||||
initUI: function() { |
||||
return; |
||||
}, |
||||
updateUI: function() { |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
} |
||||
win.gSyncUI = mySyncUI; |
||||
} |
||||
CustomizableUI.destroyWidget("sync-button"); |
||||
CustomizableUI.removeWidgetFromArea("sync-button"); |
||||
var toolbox = doc.getElementById("navigator-toolbox"); |
||||
if (toolbox && toolbox.palette) { |
||||
let element = toolbox.palette.querySelector("#sync-button"); |
||||
if (element) { |
||||
element.parentNode.removeChild(element); |
||||
} |
||||
} |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
|
||||
function disablePrivateBrowsing(doc) { |
||||
disable(E("Tools:PrivateBrowsing", doc)); |
||||
hide(E("menu_newPrivateWindow", doc)); |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-openlinkprivate", doc)) |
||||
E("context-openlinkprivate", doc).setAttribute("style", "display: none;"); |
||||
if (E("placesContext_open:newprivatewindow", doc)) |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
CustomizableUI.destroyWidget("privatebrowsing-button") |
||||
} |
||||
|
||||
function disableAddonsManager(doc) { |
||||
hide(E("menu_openAddons", doc)); |
||||
disable(E("Tools:Addons", doc)); // Ctrl+Shift+A
|
||||
CustomizableUI.destroyWidget("add-ons-button") |
||||
} |
||||
|
||||
function removeDeveloperTools(doc) { |
||||
var win = doc.defaultView; |
||||
// Need to delay this because devtools is created dynamically
|
||||
win.setTimeout(function() { |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
hide(E("webDeveloperMenu", doc)); |
||||
var devtoolsKeyset = doc.getElementById("devtoolsKeyset"); |
||||
if (devtoolsKeyset) { |
||||
for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) { |
||||
devtoolsKeyset.childNodes[i].removeAttribute("oncommand"); |
||||
devtoolsKeyset.childNodes[i].removeAttribute("command"); |
||||
} |
||||
} |
||||
}, 0); |
||||
try { |
||||
doc.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:Scratchpad").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserConsole").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbar").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
} |
||||
|
||||
function disableErrorConsole(doc) { |
||||
doc.getElementById("Tools:ErrorConsole").removeAttribute("oncommand"); |
||||
} |
||||
|
||||
function onPanelShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("PanelUI-fxa-status", event.target.ownerDocument)); |
||||
hide(E("PanelUI-footer-fxa", event.target.ownerDocument)); // Firefox 42+
|
||||
} |
||||
} |
||||
} |
||||
|
||||
function onAppMenuShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("appMenu-fxa-container", event.target.ownerDocument)); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
hide(E("appMenu-developer-button", event.target.ownerDocument)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
element.setAttribute("disabled", "true"); |
||||
} |
||||
} |
||||
|
||||
function hideUIElements(doc, hiddenUI) { |
||||
for (var i=0; i < hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(hiddenUI[i]); |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + hiddenUI[i] + "{display: none !important;}"; |
||||
if (!uiElements || uiElements.length == 0) { |
||||
continue; |
||||
} |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
if (uiElement.nodeName == "menuitem") { |
||||
uiElement.removeAttribute("key"); |
||||
uiElement.removeAttribute("oncommand"); |
||||
if (uiElement.hasAttribute("command")) { |
||||
var commandId = uiElement.getAttribute("command"); |
||||
uiElement.removeAttribute("command"); |
||||
var command = doc.getElementById(commandId); |
||||
command.removeAttribute("oncommand"); |
||||
var keys = doc.querySelectorAll("key[command='" + commandId + "']") |
||||
for (var k=0; k < keys.length; k++) { |
||||
keys[k].removeAttribute("command"); |
||||
} |
||||
} |
||||
} |
||||
// Horrible hack to work around the crappy Australis help menu
|
||||
// Items on the menu always show up in the Australis menu, so we have to remove them.
|
||||
if (uiElements[j].parentNode.id == "menu_HelpPopup") { |
||||
uiElements[j].parentNode.removeChild(uiElements[j]); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = []; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
let CCK2FileBlock = { |
||||
chromeBlacklist: ["browser", "mozapps", "marionette", "specialpowers", |
||||
"branding", "alerts"], |
||||
shouldLoad: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
// Prevent the loading of chrome URLs into the main browser window
|
||||
if (aContentLocation.scheme == "chrome") { |
||||
if (aRequestOrigin && |
||||
(aRequestOrigin.spec == "chrome://browser/content/browser.xul" || |
||||
aRequestOrigin.scheme == "moz-nullprincipal")) { |
||||
for (var i=0; i < this.chromeBlacklist.length; i++) { |
||||
if (aContentLocation.host == this.chromeBlacklist[i]) { |
||||
if (aContentLocation.spec.includes(".xul")) { |
||||
return Ci.nsIContentPolicy.REJECT_REQUEST; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
shouldProcess: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
classDescription: "CCK2 FileBlock Service", |
||||
contractID: "@kaply.com/cck2-fileblock-service;1", |
||||
classID: Components.ID('{26e7afc9-e22d-4d12-bb57-c184fe24b828}'), |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]), |
||||
createInstance: function(outer, iid) { |
||||
return this.QueryInterface(iid); |
||||
}, |
||||
}; |
||||
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
||||
registrar.registerFactory(CCK2FileBlock.classID, |
||||
CCK2FileBlock.classDescription, |
||||
CCK2FileBlock.contractID, |
||||
CCK2FileBlock); |
||||
|
||||
var cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); |
||||
cm.addCategoryEntry("content-policy", CCK2FileBlock.contractID, |
||||
CCK2FileBlock.contractID, false, true); |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var disableSearchEngineInstall = false; |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
if (disableSearchEngineInstall) { |
||||
subject.wrappedJSObject.external.AddSearchProvider = function() {}; |
||||
} |
||||
if (!doc.documentURI.startsWith("about:")) { |
||||
return; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
var configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSearchEngineInstall) { |
||||
disableSearchEngineInstall = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/* This file modifies the preferences dialogs. It does the following: |
||||
* Removes private browsing from the pref UI if it is disabled |
||||
* Removes Sync from the pref UI if it is diabled |
||||
* Disables the crash reporter button if crash reporter is disabled |
||||
* Removed the master password UI if it is disabled |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/preferences/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
win.addEventListener("paneload", function(event) { |
||||
updatePrefUI(event.target.ownerDocument); |
||||
}, false); |
||||
updatePrefUI(doc); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (!config.disableSync) { |
||||
continue; |
||||
} |
||||
var prefWindow = E("BrowserPreferences", doc); |
||||
var paneSyncRadio = doc.getAnonymousElementByAttribute(prefWindow, "pane", "paneSync"); |
||||
hide(paneSyncRadio); |
||||
var paneDeck = doc.getAnonymousElementByAttribute(prefWindow, "anonid", "paneDeck"); |
||||
var paneSync = E("paneSync", doc); |
||||
paneSync.removeAttribute("helpTopic"); |
||||
var weavePrefsDeck = E("weavePrefsDeck", doc); |
||||
if (weavePrefsDeck) |
||||
weavePrefsDeck.parentNode.removeChild(weavePrefsDeck); |
||||
if (prefWindow.currentPane == E("paneSync", doc)) |
||||
prefWindow.showPane(E("paneMain", doc)); |
||||
} |
||||
break; |
||||
case "about:preferences": |
||||
case "chrome://browser/content/preferences/in-content/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("category-sync", doc)); |
||||
} |
||||
} |
||||
updatePrefUI(doc); |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
// The IDs are the same, so I can reuse this for regular and in-content prefs
|
||||
function updatePrefUI(doc) { |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
hide(E("privateBrowsingAutoStart", doc)); |
||||
var privateBrowsingMenu = doc.querySelector("menuitem[value='dontremember']"); |
||||
hide(privateBrowsingMenu, doc); |
||||
} |
||||
if (config.disableCrashReporter) { |
||||
disable(E("submitCrashesBox", doc)); |
||||
} |
||||
if (config.disableSync) { |
||||
hide(E("noFxaAccount", doc)); |
||||
hide(E("hasFxaAccount", doc)); |
||||
} |
||||
if (config.noMasterPassword == true) { |
||||
hide(E("useMasterPassword", doc)); |
||||
hide(E("changeMasterPassword", doc)); |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
} |
||||
} |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/** |
||||
* Copied from https://github.com/jvillalobos/CTP-Manager/blob/master/extension/modules/permissions.js
|
||||
**/ |
||||
|
||||
/** |
||||
* Copyright 2013 Jorge Villalobos |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
**/ |
||||
|
||||
var EXPORTED_SYMBOLS = ["CTP"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var CTP = { |
||||
/** |
||||
* Cleans up the plugin name to a more readable form. |
||||
* Taken from /browser/base/content/pageinfo/permissions.js (Firefox 20) |
||||
* @param aPluginName the name to clean up. |
||||
* @return cleaned up plugin name. |
||||
*/ |
||||
makeNicePluginName : function(aPluginName) { |
||||
let newName = |
||||
aPluginName.replace(/[\s\d\.\-\_\(\)]+$/, ""). |
||||
replace(/\bplug-?in\b/i, "").trim(); |
||||
|
||||
return newName; |
||||
}, |
||||
|
||||
/** |
||||
* Gets the plugin permission string from the tag object. In Firefox 20, this |
||||
* is the plugin filename. In 21 an above, the file extension is removed and |
||||
* Flash and Java are special-cased. |
||||
* @param aTag the tag object with the plugin information. |
||||
* @return permission string that corresponds to the plugin in the tag. |
||||
*/ |
||||
getPluginPermissionFromTag : function(aTag) { |
||||
let permission = null; |
||||
let majorVersion = Services.appinfo.platformVersion.split(".")[0]; |
||||
|
||||
if (21 <= majorVersion) { |
||||
let mimeTypes = aTag.getMimeTypes(); |
||||
|
||||
if (CTP.isFlashPlugin(mimeTypes)) { |
||||
permission = "flash"; |
||||
} else if (CTP.isJavaPlugin(mimeTypes)) { |
||||
permission = "java"; |
||||
} else { |
||||
let lastPeriod = aTag.filename.lastIndexOf("."); |
||||
|
||||
permission = |
||||
((0 < lastPeriod) ? aTag.filename.substring(0, lastPeriod) : |
||||
aTag.filename); |
||||
// Remove digits at the end
|
||||
permission = permission.replace(/[0-9]+$/, ""); |
||||
permission = permission.toLowerCase(); |
||||
} |
||||
} else { |
||||
permission = aTag.filename; |
||||
} |
||||
|
||||
return permission; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Java plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Java plugin. |
||||
*/ |
||||
isJavaPlugin : function(aMimeTypes) { |
||||
let isJava = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if ((0 == mimeType.indexOf("application/x-java-vm")) || |
||||
(0 == mimeType.indexOf("application/x-java-applet")) || |
||||
(0 == mimeType.indexOf("application/x-java-bean"))) { |
||||
isJava = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isJava; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Flash plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Flash plugin. |
||||
*/ |
||||
isFlashPlugin : function(aMimeTypes) { |
||||
let isFlash = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if (0 == mimeType.indexOf("application/x-shockwave-flash")) { |
||||
isFlash = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isFlash; |
||||
} |
||||
}; |
@ -0,0 +1,629 @@
@@ -0,0 +1,629 @@
|
||||
/* ***** BEGIN LICENSE BLOCK ***** |
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
||||
* |
||||
* The contents of this file are subject to the Mozilla Public License Version |
||||
* 1.1 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* http://www.mozilla.org/MPL/
|
||||
* |
||||
* Software distributed under the License is distributed on an "AS IS" basis, |
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
||||
* for the specific language governing rights and limitations under the |
||||
* License. |
||||
* |
||||
* The Original Code is Preferences. |
||||
* |
||||
* The Initial Developer of the Original Code is Mozilla. |
||||
* Portions created by the Initial Developer are Copyright (C) 2008 |
||||
* the Initial Developer. All Rights Reserved. |
||||
* |
||||
* Contributor(s): |
||||
* Myk Melez <myk@mozilla.org> |
||||
* Daniel Aquino <mr.danielaquino@gmail.com> |
||||
* |
||||
* Alternatively, the contents of this file may be used under the terms of |
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or |
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
||||
* in which case the provisions of the GPL or the LGPL are applicable instead |
||||
* of those above. If you wish to allow use of your version of this file only |
||||
* under the terms of either the GPL or the LGPL, and not to allow others to |
||||
* use your version of this file under the terms of the MPL, indicate your |
||||
* decision by deleting the provisions above and replace them with the notice |
||||
* and other provisions required by the GPL or the LGPL. If you do not delete |
||||
* the provisions above, a recipient may use your version of this file under |
||||
* the terms of any one of the MPL, the GPL or the LGPL. |
||||
* |
||||
* ***** END LICENSE BLOCK ***** */ |
||||
|
||||
let EXPORTED_SYMBOLS = ["Preferences"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cr = Components.results; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// The minimum and maximum integers that can be set as preferences.
|
||||
// The range of valid values is narrower than the range of valid JS values
|
||||
// because the native preferences code treats integers as NSPR PRInt32s,
|
||||
// which are 32-bit signed integers on all platforms.
|
||||
const MAX_INT = Math.pow(2, 31) - 1; |
||||
const MIN_INT = -MAX_INT; |
||||
|
||||
function Preferences(args) { |
||||
if (isObject(args)) { |
||||
if (args.branch) |
||||
this._prefBranch = args.branch; |
||||
} |
||||
else if (args) |
||||
this._prefBranch = args; |
||||
this.isDefaultBranch = false; |
||||
} |
||||
|
||||
Preferences.prototype = { |
||||
/** |
||||
* Get the value of a pref, if any; otherwise return the default value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to get, or an array of prefs to get |
||||
* |
||||
* @param defaultValue |
||||
* the default value, if any, for prefs that don't have one |
||||
* |
||||
* @returns the value of the pref, if any; otherwise the default value |
||||
*/ |
||||
get: function(prefName, defaultValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(v => this.get(v, defaultValue)); |
||||
|
||||
return this._get(prefName, defaultValue); |
||||
}, |
||||
|
||||
// In all cases below, the preference might exist as a user pref, but not
|
||||
// have a default value. In those cases, get* throws. Return the default value.
|
||||
_get: function(prefName, defaultValue) { |
||||
switch (this._prefSvc.getPrefType(prefName)) { |
||||
case Ci.nsIPrefBranch.PREF_STRING: |
||||
try { |
||||
return this._prefSvc.getComplexValue(prefName, Ci.nsISupportsString).data; |
||||
} catch (ex) { |
||||
if (this.isDefaultBranch) |
||||
return defaultValue; |
||||
else |
||||
return this._prefSvc.getCharPref(prefName); |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INT: |
||||
try { |
||||
return this._prefSvc.getIntPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_BOOL: |
||||
try { |
||||
return this._prefSvc.getBoolPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INVALID: |
||||
return defaultValue; |
||||
|
||||
default: |
||||
// This should never happen.
|
||||
throw "Error getting pref " + prefName + "; its value's type is " + |
||||
this._prefSvc.getPrefType(prefName) + ", which I don't know " + |
||||
"how to handle."; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Set a preference to a value. |
||||
* |
||||
* You can set multiple prefs by passing an object as the only parameter. |
||||
* In that case, this method will treat the properties of the object |
||||
* as preferences to set, where each property name is the name of a pref |
||||
* and its corresponding property value is the value of the pref. |
||||
* |
||||
* @param prefName {String|Object} |
||||
* the name of the pref to set; or an object containing a set |
||||
* of prefs to set |
||||
* |
||||
* @param prefValue {String|Number|Boolean} |
||||
* the value to which to set the pref |
||||
* |
||||
* Note: Preferences cannot store non-integer numbers or numbers outside |
||||
* the signed 32-bit range -(2^31-1) to 2^31-1, If you have such a number, |
||||
* store it as a string by calling toString() on the number before passing |
||||
* it to this method, i.e.: |
||||
* Preferences.set("pi", 3.14159.toString()) |
||||
* Preferences.set("big", Math.pow(2, 31).toString()). |
||||
*/ |
||||
set: function(prefName, prefValue) { |
||||
if (isObject(prefName)) { |
||||
for (let [name, value] in Iterator(prefName)) |
||||
this.set(name, value); |
||||
return; |
||||
} |
||||
|
||||
this._set(prefName, prefValue); |
||||
}, |
||||
|
||||
_set: function(prefName, prefValue) { |
||||
let prefType; |
||||
if (typeof prefValue != "undefined" && prefValue != null) |
||||
prefType = prefValue.constructor.name; |
||||
|
||||
var existingPrefType = this._prefSvc.getPrefType(prefName); |
||||
if (existingPrefType != Ci.nsIPrefBranch.PREF_INVALID) |
||||
{ |
||||
// convert
|
||||
if (existingPrefType == Ci.nsIPrefBranch.PREF_INT && prefType == "String") |
||||
{ |
||||
prefValue = parseInt(prefValue); |
||||
if (isNaN(prefValue)) |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Number"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "String") |
||||
{ |
||||
if (prefValue == "true") |
||||
prefValue = true; |
||||
else if (prefValue == "false") |
||||
prefValue = false; |
||||
else |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Boolean"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "Number") |
||||
{ |
||||
prefValue = prefValue != 0; |
||||
prefType = "Boolean"; |
||||
} |
||||
} |
||||
|
||||
switch (prefType) { |
||||
case "String": |
||||
{ |
||||
try { |
||||
this._prefSvc.setStringPref(prefName, prefValue); |
||||
} catch (e) { |
||||
try { |
||||
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); |
||||
string.data = prefValue; |
||||
this._prefSvc.setComplexValue(prefName, Ci.nsISupportsString, string); |
||||
} catch (e2) { |
||||
Components.utils.reportError(e2); |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case "Number": |
||||
// We throw if the number is outside the range, since the result
|
||||
// will never be what the consumer wanted to store, but we only warn
|
||||
// if the number is non-integer, since the consumer might not mind
|
||||
// the loss of precision.
|
||||
if (prefValue > MAX_INT || prefValue < MIN_INT) |
||||
throw("you cannot set the " + prefName + " pref to the number " + |
||||
prefValue + ", as number pref values must be in the signed " + |
||||
"32-bit integer range -(2^31-1) to 2^31-1. To store numbers " + |
||||
"outside that range, store them as strings."); |
||||
try { |
||||
this._prefSvc.setIntPref(prefName, prefValue); |
||||
} catch (e) { |
||||
throw new Error(e.toString() + " - " + prefName); |
||||
} |
||||
if (prefValue % 1 != 0) |
||||
Cu.reportError("Warning: setting the " + prefName + " pref to the " + |
||||
"non-integer number " + prefValue + " converted it " + |
||||
"to the integer number " + this.get(prefName) + |
||||
"; to retain fractional precision, store non-integer " + |
||||
"numbers as strings."); |
||||
break; |
||||
|
||||
case "Boolean": |
||||
this._prefSvc.setBoolPref(prefName, prefValue); |
||||
break; |
||||
|
||||
default: |
||||
throw "can't set pref " + prefName + " to value '" + prefValue + |
||||
"'; it isn't a String, Number, or Boolean"; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a value. This is different from isSet |
||||
* because it returns true whether the value of the pref is a default value |
||||
* or a user-set value, while isSet only returns true if the value |
||||
* is a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a value; or, if the caller provided |
||||
* an array of pref names, an array of booleans indicating whether |
||||
* or not the prefs have values |
||||
*/ |
||||
has: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.has, this); |
||||
|
||||
return this._has(prefName); |
||||
}, |
||||
|
||||
_has: function(prefName) { |
||||
return (this._prefSvc.getPrefType(prefName) != Ci.nsIPrefBranch.PREF_INVALID); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. This is different |
||||
* from |has| because it returns true only if the value of the pref is a user- |
||||
* set value, while |has| returns true if the value of the pref is a default |
||||
* value or a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a user-set value; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs have user-set values |
||||
*/ |
||||
isSet: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.isSet, this); |
||||
|
||||
return (this.has(prefName) && this._prefSvc.prefHasUserValue(prefName)); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. Use isSet instead, |
||||
* which is equivalent. |
||||
* @deprecated |
||||
*/ |
||||
modified: function(prefName) { return this.isSet(prefName) }, |
||||
|
||||
reset: function(prefName) { |
||||
if (isArray(prefName)) { |
||||
prefName.map(v => this.reset(v)); |
||||
return; |
||||
} |
||||
|
||||
this._reset(prefName); |
||||
}, |
||||
|
||||
_reset: function(prefName) { |
||||
try { |
||||
this._prefSvc.clearUserPref(prefName); |
||||
} |
||||
catch(ex) { |
||||
// The pref service throws NS_ERROR_UNEXPECTED when the caller tries
|
||||
// to reset a pref that doesn't exist or is already set to its default
|
||||
// value. This interface fails silently in those cases, so callers
|
||||
// can unconditionally reset a pref without having to check if it needs
|
||||
// resetting first or trap exceptions after the fact. It passes through
|
||||
// other exceptions, however, so callers know about them, since we don't
|
||||
// know what other exceptions might be thrown and what they might mean.
|
||||
if (ex.result != Cr.NS_ERROR_UNEXPECTED) |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* If you need to know the default values, without resetting the actual |
||||
* user prefs, you can use this. |
||||
* @returns {Preferences} a new Preferences object, which accesses |
||||
* the defaults rather than the user prefs. |
||||
* *Only* call get() on this. |
||||
* If you call set(), you will modify the defaults, so don't do that! |
||||
*/ |
||||
get defaults() { |
||||
// nsIPrefService
|
||||
let defaultBranch = Services.prefs. |
||||
getDefaultBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
let prefs = new Preferences(this._prefBranch); |
||||
// override. nasty, but this is internal, so OK.
|
||||
Object.defineProperty(prefs, "_prefSvc", { |
||||
get: function() { |
||||
return defaultBranch; |
||||
} |
||||
}); |
||||
prefs.isDefaultBranch = true; |
||||
return prefs; |
||||
}, |
||||
|
||||
/** |
||||
* Lock a pref so it can't be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
* @param prefValue {String} (optional) |
||||
* default value of pref to lock only works if prefName isn't an array |
||||
*/ |
||||
lock: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.lock, this); |
||||
else if (typeof prefValue != "undefined") |
||||
this.defaults.set(prefName, prefValue); |
||||
|
||||
this._prefSvc.lockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Unlock a pref so it can be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
*/ |
||||
unlock: function(prefName) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.unlock, this); |
||||
|
||||
this._prefSvc.unlockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref is locked against changes and |
||||
* if it is set to the passedi n value |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* @param prefValue {String|Number|Boolean}} |
||||
* the pref value to compare against |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref is locked; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs are locked |
||||
* If a pref value was specified returns whether or not the pref |
||||
* was locked and equal to the passed in value. |
||||
*/ |
||||
locked: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.locked, this); |
||||
|
||||
if (prefValue) |
||||
return this._prefSvc.prefIsLocked(prefName) && (this.get(prefName) == prefValue); |
||||
else |
||||
return this._prefSvc.prefIsLocked(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Start observing a pref. |
||||
* |
||||
* The callback can be a function or any object that implements nsIObserver. |
||||
* When the callback is a function and thisObject is provided, it gets called |
||||
* as a method of thisObject. |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref to observe |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code to notify when the pref changes; |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object to use as |this| when calling a Function callback; |
||||
* |
||||
* @returns the wrapped observer |
||||
*/ |
||||
observe: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
let observer = new PrefObserver(fullPrefName, callback, thisObject); |
||||
Preferences._prefSvc.addObserver(fullPrefName, observer, true); |
||||
observers.push(observer); |
||||
|
||||
return observer; |
||||
}, |
||||
|
||||
/** |
||||
* Stop observing a pref. |
||||
* |
||||
* You must call this method with the same prefName, callback, and thisObject |
||||
* with which you originally registered the observer. However, you don't have |
||||
* to call this method on the same exact instance of Preferences; you can call |
||||
* it on any instance. For example, the following code first starts and then |
||||
* stops observing the "foo.bar.baz" preference: |
||||
* |
||||
* let observer = function() {...}; |
||||
* Preferences.observe("foo.bar.baz", observer); |
||||
* new Preferences("foo.bar.").ignore("baz", observer); |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref being observed |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code being notified when the pref changes |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object being used as |this| when calling a Function callback |
||||
*/ |
||||
ignore: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
// This seems fairly inefficient, but I'm not sure how much better we can
|
||||
// make it. We could index by fullBranch, but we can't index by callback
|
||||
// or thisObject, as far as I know, since the keys to JavaScript hashes
|
||||
// (a.k.a. objects) can apparently only be primitive values.
|
||||
let [observer] = observers.filter(v => v.prefName == fullPrefName && |
||||
v.callback == callback && |
||||
v.thisObject == thisObject); |
||||
|
||||
if (observer) { |
||||
Preferences._prefSvc.removeObserver(fullPrefName, observer); |
||||
observers.splice(observers.indexOf(observer), 1); |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Same as observe(), but automatically unregisters itself when |
||||
* the window closes, saving you from writing an unload handler and |
||||
* calling ignore(). |
||||
* @param win {nsIDOMWindow} your |window| |
||||
*/ |
||||
observeAuto: function(win, prefName, callback, thisObject) { |
||||
if (!win instanceof Ci.nsIDOMWindow) |
||||
throw "Need your |window| as first parameter"; |
||||
this.observe(prefName, callback, thisObject); |
||||
var self = this; |
||||
win.addEventListener("unload", function() |
||||
{ |
||||
self.ignore(prefName, callback, thisObject); |
||||
}, false); |
||||
win = null; // don't let closure hold on to window unnecessarily
|
||||
}, |
||||
|
||||
resetBranch: function(prefBranch) { |
||||
try { |
||||
this._prefSvc.resetBranch(prefBranch); |
||||
} |
||||
catch(ex) { |
||||
// The current implementation of nsIPrefBranch in Mozilla
|
||||
// doesn't implement resetBranch, so we do it ourselves.
|
||||
if (ex.result == Cr.NS_ERROR_NOT_IMPLEMENTED) |
||||
this.reset(this._prefSvc.getChildList(prefBranch, [])); |
||||
else |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Returns all child prefs of this pref branch. |
||||
* This equals nsIPrefBranch.getChildList(). |
||||
* This allows you to do e.g. |
||||
* var myPrefs = new Preferences("extensions.cooler."); |
||||
* var contents = myPrefs.branch("contents."); |
||||
* for each (let prefname in contents.childPrefNames()) |
||||
* dump("have " + contents.get(prefname) + " " + prefname + "\n"); |
||||
* |
||||
* @returns {Array of String} The names of the children, |
||||
* without the base pref branch, but with subbranch. |
||||
*/ |
||||
childPrefNames : function() { |
||||
return this._prefSvc.getChildList("", []); |
||||
}, |
||||
|
||||
/** |
||||
* Returns an nsIPrefBranch for the pref branch that this object stands for. |
||||
* You can use this to use functions that are not supported here. |
||||
* @returns {nsIPrefBranch} |
||||
*/ |
||||
get mozillaPrefBranch() { |
||||
return this._prefSvc; |
||||
}, |
||||
|
||||
/** |
||||
* Returns the base pref name that this object stands for. |
||||
* E.g. "extensions.yourcooler."; |
||||
* @returns {String} |
||||
*/ |
||||
get prefBranchName() { |
||||
return this._prefBranch; |
||||
}, |
||||
|
||||
/** |
||||
* Returns an Preferences object for an sub pref branch |
||||
* underneath the current pref branch. |
||||
* @param subbranch {String} Will be appended to the |
||||
* current pref branch. Don't forget the trailing dot, |
||||
* where necessary. |
||||
* E.g. "contents." |
||||
* @returns {Preferences} |
||||
*/ |
||||
branch : function(subbranch) { |
||||
return new Preferences(this._prefBranch + subbranch); |
||||
}, |
||||
|
||||
/** |
||||
* The branch of the preferences tree to which this instance provides access. |
||||
* @private |
||||
*/ |
||||
_prefBranch: "", |
||||
|
||||
/** |
||||
* Preferences Service |
||||
* @private |
||||
*/ |
||||
get _prefSvc() { |
||||
// nsIPrefService
|
||||
let prefSvc = Services.prefs. |
||||
getBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
Object.defineProperty(this, "_prefSvc", { |
||||
get: function() { |
||||
return prefSvc; |
||||
} |
||||
}); |
||||
return this._prefSvc; |
||||
} |
||||
|
||||
}; |
||||
|
||||
// Give the constructor the same prototype as its instances, so users can access
|
||||
// preferences directly via the constructor without having to create an instance
|
||||
// first.
|
||||
Preferences.__proto__ = Preferences.prototype; |
||||
|
||||
/** |
||||
* A cache of pref observers. |
||||
* |
||||
* We use this to remove observers when a caller calls Preferences::ignore. |
||||
* |
||||
* All Preferences instances share this object, because we want callers to be |
||||
* able to remove an observer using a different Preferences object than the one |
||||
* with which they added it. That means we have to identify the observers |
||||
* in this object by their complete pref name, not just their name relative to |
||||
* the root branch of the Preferences object with which they were created. |
||||
*/ |
||||
let observers = []; |
||||
|
||||
function PrefObserver(prefName, callback, thisObject) { |
||||
this.prefName = prefName; |
||||
this.callback = callback; |
||||
this.thisObject = thisObject; |
||||
} |
||||
|
||||
PrefObserver.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), |
||||
|
||||
observe: function(subject, topic, data) { |
||||
// The pref service only observes whole branches, but we only observe
|
||||
// individual preferences, so we check here that the pref that changed
|
||||
// is the exact one we're observing (and not some sub-pref on the branch).
|
||||
if (data != this.prefName) |
||||
return; |
||||
|
||||
if (typeof this.callback == "function") { |
||||
let prefValue = Preferences.get(this.prefName); |
||||
|
||||
if (this.thisObject) |
||||
this.callback.call(this.thisObject, prefValue); |
||||
else |
||||
this.callback(prefValue); |
||||
} |
||||
else // typeof this.callback == "object" (nsIObserver)
|
||||
this.callback.observe(subject, topic, data); |
||||
} |
||||
}; |
||||
|
||||
function isArray(val) { |
||||
// We can't check for |val.constructor == Array| here, since the value
|
||||
// might be from a different context whose Array constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Array"); |
||||
} |
||||
|
||||
function isObject(val) { |
||||
// We can't check for |val.constructor == Object| here, since the value
|
||||
// might be from a different context whose Object constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Object"); |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* 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"; |
||||
|
||||
/** |
||||
* JS module implementation of nsIDOMJSWindow.setTimeout and clearTimeout. |
||||
*/ |
||||
|
||||
this.EXPORTED_SYMBOLS = ["setTimeout", "clearTimeout"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
|
||||
let gNextTimeoutId = 1; // setTimeout must return a positive integer
|
||||
|
||||
let gTimeoutTable = new Map(); // int -> nsITimer
|
||||
|
||||
this.setTimeout = function setTimeout(aCallback, aMilliseconds) { |
||||
let id = gNextTimeoutId++; |
||||
let args = Array.slice(arguments, 2); |
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
||||
timer.initWithCallback(function setTimeout_timer() { |
||||
gTimeoutTable.delete(id); |
||||
aCallback.apply(null, args); |
||||
}, aMilliseconds, timer.TYPE_ONE_SHOT); |
||||
|
||||
gTimeoutTable.set(id, timer); |
||||
return id; |
||||
} |
||||
|
||||
this.clearTimeout = function clearTimeout(aId) { |
||||
if (gTimeoutTable.has(aId)) { |
||||
gTimeoutTable.get(aId).cancel(); |
||||
gTimeoutTable.delete(aId); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = ["errorCritical"]; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
function errorCritical(e) |
||||
{ |
||||
Services.prompt.alert(null, "", e); |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIID7DCCAtSgAwIBAgIJAKXaTovgoTIUMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD |
||||
VQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdvcmsxEjAQBgNVBAoMCVB1cnBsZUky |
||||
UDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR0w |
||||
GwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmkycDAeFw0xODA4MjQyMTQ3NTJaFw0y |
||||
MzA4MjMyMTQ3NTJaMIGCMQswCQYDVQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdv |
||||
cmsxEjAQBgNVBAoMCVB1cnBsZUkyUDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRp |
||||
ZmljYXRpb24gQXV0aG9yaXR5MR0wGwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmky |
||||
cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAZnN/U5bgkmiBqp/Np |
||||
yiMOkUPjr2tLhV78Oba46xDLA6AiQ7yTPg+/ZYPIfbF2dPBTpfgGdly2M1xymRKc |
||||
3Pa+IUXkLw6oCA+lFzOFW0Swtekk9HRAgGyHgj6/Hvagva5Wer4HJIO1qRsFPew+ |
||||
XcM3uhhiXoiO8o+YGpJ/7kz0gED3p2b9OVsLPd8G/GfdR3miD+Au+kUx/27z/WdJ |
||||
ISfFILFnYeYZGffrpRcFtoGwuZUCugwnbLtpQpNKuGq8jDidm1v6Rb85JmkoH3Sg |
||||
lRaX1MK0aPhM4WfCf7aWCNe669FAWPNB3Ya2lue7ewPLI84ZUEqcoJwmWn2ci2SU |
||||
EXUCAwEAAaNjMGEwHQYDVR0OBBYEFG3hwzikpXqMasw678OHM8uLyjEoMB8GA1Ud |
||||
IwQYMBaAFG3hwzikpXqMasw678OHM8uLyjEoMA8GA1UdEwQIMAYBAf8CAQAwDgYD |
||||
VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQA07URxJMI/Ta9y1wIg+k7o |
||||
1aHXsl6YOXmd2ymhKZhZHrZlutE2U19IQSoEV0SBddP9D05xD6Ovsrwo7caeYzNt |
||||
+2DJnlJ2IY61NqYUIDEoJyNPL/S7WleH+xO+bcSqWvbntTNYAD6WQVfHCAimVE6P |
||||
RnSZGqG089i84DRCyrh/6F1OxnBd6j14z+2ctQD+h6NlQXiCAUIwzVirYoE7oGpH |
||||
Xta7Ei+RDvBXLXLAQRdXpzSP/Ddf7MCJzmH3VYAy+0sVuHr09hpFMtC59hTrdLVD |
||||
/qma0eKrBr1DGH6QrZMZDqpNfv4wUPyVQBsRbbn2/1fL9IqK43CIj8RUllCOsmyU |
||||
-----END CERTIFICATE----- |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIFxzCCA6+gAwIBAgIQZfqn0yiJL3dGgCjeOeWS6DANBgkqhkiG9w0BAQsFADBw |
||||
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK |
||||
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ |
||||
aG90dHVuYUBtYWlsLmkycDAeFw0xNjExMDkwMzE1MzJaFw0yNjExMDkwMzE1MzJa |
||||
MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV |
||||
BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD |
||||
DBBob3R0dW5hQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC |
||||
AgEA21Bfgcc9VVH4l2u1YvYlTw2OPUyQb16X2IOW0PzdsUO5W78Loueu974BkiKi |
||||
84lQZanLr0OwEopdfutGc6gegSLmwaWx5YCG5uwpLOPkDiObfX+nptH6As/B1cn+ |
||||
mzejYdVKRnWd7EtHW0iseSsILBK1YbGw4AGpXJ8k18DJSzUt2+spOkpBW6XqectN |
||||
8y2JDSTns8yiNxietVeRN/clolDXT9ZwWHkd+QMHTKhgl3Uz1knOffU0L9l4ij4E |
||||
oFgPfQo8NL63kLM24hF1hM/At7XvE4iOlObFwPXE+H5EGZpT5+A7Oezepvd/VMzM |
||||
tCJ49hM0OlR393tKFONye5GCYeSDJGdPEB6+rBptpRrlch63tG9ktpCRrg2wQWgC |
||||
e3aOE1xVRrmwiTZ+jpfsOCbZrrSA/C4Bmp6AfGchyHuDGGkRU/FJwa1YLJe0dkWG |
||||
ITLWeh4zeVuAS5mctdv9NQ5wflSGz9S8HjsPBS5+CDOFHh4cexXRG3ITfk6aLhuY |
||||
KTMlkIO4SHKmnwAvy1sFlsqj6PbfVjpHPLg625fdNxBpe57TLxtIdBB3C7ccQSRW |
||||
+UG6Cmbcmh80PbsSR132NLMlzLhbaOjxeCWWJRo6cLuHBptAFMNwqsXt8xVf9M0N |
||||
NdJoKUmblyvjnq0N8aMEqtQ1uGMTaCB39cutHQq+reD/uzsCAwEAAaNdMFswDgYD |
||||
VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV |
||||
HRMBAf8EBTADAQH/MBkGA1UdDgQSBBBob3R0dW5hQG1haWwuaTJwMA0GCSqGSIb3 |
||||
DQEBCwUAA4ICAQCibFV8t4pajP176u3jx31x1kgqX6Nd+0YFARPZQjq99kUyoZer |
||||
GyHGsMWgM281RxiZkveHxR7Hm7pEd1nkhG3rm+d7GdJ2p2hujr9xUvl0zEqAAqtm |
||||
lkYI6uJ13WBjFc9/QuRIdeIeSUN+eazSXNg2nJhoV4pF9n2Q2xDc9dH4GWO93cMX |
||||
JPKVGujT3s0b7LWsEguZBPdaPW7wwZd902Cg/M5fE1hZQ8/SIAGUtylb/ZilVeTS |
||||
spxWP1gX3NT1SSvv0s6oL7eADCgtggWaMxEjZhi6WMnPUeeFY8X+6trkTlnF9+r/ |
||||
HiVvvzQKrPPtB3j1xfQCAF6gUKN4iY+2AOExv4rl/l+JJbPhpd/FuvD8AVkLMZ8X |
||||
uPe0Ew2xv30cc8JjGDzQvoSpBmVTra4f+xqH+w8UEmxnx97Ye2aUCtnPykACnFte |
||||
oT97K5052B1zq+4fu4xaHZnEzPYVK5POzOufNLPgciJsWrR5GDWtHd+ht/ZD37+b |
||||
+j1BXpeBWUBQgluFv+lNMVNPJxc2OMELR1EtEwXD7mTuuUEtF5Pi63IerQ5LzD3G |
||||
KBvXhMB0XhpE6WG6pBwAvkGf5zVv/CxClJH4BQbdZwj9HYddfEQlPl0z/XFR2M0+ |
||||
9/8nBfGSPYIt6KeHBCeyQWTdE9gqSzMwTMFsennXmaT8gyc7eKqKF6adqw== |
||||
-----END CERTIFICATE----- |
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
[XRE] |
||||
EnableProfileMigrator=0 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
resource cck2 modules/ |
@ -0,0 +1,154 @@
@@ -0,0 +1,154 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gForceExternalHandler = false; |
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "extProtocolSvc", |
||||
"@mozilla.org/uriloader/external-protocol-service;1", "nsIExternalProtocolService"); |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
// If the parent document is a local file, don't do anything
|
||||
// Links will just work
|
||||
if (doc.location.href.indexOf("file://") == 0) { |
||||
return; |
||||
} |
||||
var links = event.target.getElementsByTagName("a"); |
||||
for (var i=0; i < links.length; i++) { |
||||
var link = links[i]; |
||||
if (link.href.indexOf("file://") != 0) { |
||||
continue; |
||||
} |
||||
link.addEventListener("click", function(link) { |
||||
return function(event) { |
||||
event.preventDefault(); |
||||
if (gForceExternalHandler) { |
||||
extProtocolSvc.loadUrl(Services.io.newURI(link.href, null, null)); |
||||
} else { |
||||
var target = "_self"; |
||||
if (link.hasAttribute("target")) { |
||||
target = link.getAttribute("target"); |
||||
} |
||||
// If we were told somewhere other than current (based on modifier keys), use it
|
||||
var where = whereToOpenLink(event); |
||||
if (where != "current" || target == "_blank") { |
||||
sendAsyncMessage("cck2:open-url", { |
||||
"url": link.href, |
||||
"where": (target == "_blank") ? "tab" : where |
||||
}); |
||||
return; |
||||
} |
||||
switch (target) { |
||||
case "_self": |
||||
link.ownerDocument.location = link.href; |
||||
break; |
||||
case "_parent": |
||||
link.ownerDocument.defaultView.parent.document.location = link.href; |
||||
break; |
||||
case "_top": |
||||
link.ownerDocument.defaultView.top.document.location = link.href; |
||||
break; |
||||
default: |
||||
// Attempt to find the iframe that this goes into
|
||||
var iframes = doc.defaultView.parent.document.getElementsByName(target); |
||||
if (iframes.length > 0) { |
||||
iframes[0].contentDocument.location = link.href; |
||||
} else { |
||||
link.ownerDocument.location = link.href; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}(link), false); |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.checkloaduri.enabled") == "allAccess") { |
||||
gForceExternalHandler = !extProtocolSvc.isExposedProtocol('file'); |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} catch (e) {} |
||||
} |
||||
|
||||
|
||||
/* Copied from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/utilityOverlay.js?raw=1 */ |
||||
|
||||
function getBoolPref(prefname, def) |
||||
{ |
||||
try { |
||||
return Services.prefs.getBoolPref(prefname); |
||||
} |
||||
catch(er) { |
||||
return def; |
||||
} |
||||
} |
||||
|
||||
/* whereToOpenLink() looks at an event to decide where to open a link. |
||||
* |
||||
* The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). |
||||
* |
||||
* On Windows, the modifiers are: |
||||
* Ctrl new tab, selected |
||||
* Shift new window |
||||
* Ctrl+Shift new tab, in background |
||||
* Alt save |
||||
* |
||||
* Middle-clicking is the same as Ctrl+clicking (it opens a new tab). |
||||
* |
||||
* Exceptions: |
||||
* - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. |
||||
* (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) |
||||
* - Alt is hard to use in context menus, because pressing Alt closes the menu. |
||||
* - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". |
||||
* - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. |
||||
*/ |
||||
function whereToOpenLink( e, ignoreButton, ignoreAlt ) |
||||
{ |
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm"); |
||||
|
||||
// This method must treat a null event like a left click without modifier keys (i.e.
|
||||
// e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 })
|
||||
// for compatibility purposes.
|
||||
if (!e) |
||||
return "current"; |
||||
|
||||
var shift = e.shiftKey; |
||||
var ctrl = e.ctrlKey; |
||||
var meta = e.metaKey; |
||||
var alt = e.altKey && !ignoreAlt; |
||||
|
||||
// ignoreButton allows "middle-click paste" to use function without always opening in a new window.
|
||||
var middle = !ignoreButton && e.button == 1; |
||||
var middleUsesTabs = true; |
||||
|
||||
// Don't do anything special with right-mouse clicks. They're probably clicks on context menu items.
|
||||
|
||||
var metaKey = AppConstants.platform == "macosx" ? meta : ctrl; |
||||
if (metaKey || (middle && middleUsesTabs)) |
||||
return shift ? "tabshifted" : "tab"; |
||||
|
||||
if (alt && getBoolPref("browser.altClickSave", false)) |
||||
return "save"; |
||||
|
||||
if (shift || (middle && !middleUsesTabs)) |
||||
return "window"; |
||||
|
||||
return "current"; |
||||
} |
@ -0,0 +1,183 @@
@@ -0,0 +1,183 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
var gAllowedPasteSites = []; |
||||
var gAllowedCutCopySites = []; |
||||
var gDeniedPasteSites = []; |
||||
var gDeniedCutCopySites = []; |
||||
var gDefaultPastePolicy = false; |
||||
var gDefaultCutCopyPolicy = false; |
||||
|
||||
function allowCutCopy(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultCutCopyPolicy == true) { |
||||
for (var i=0; i < gDeniedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedCutCopySites[i]) == 0) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedCutCopySites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedCutCopySites[i]) == 0) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function allowPaste(doc) { |
||||
var win = doc.defaultView; |
||||
if (win !== win.top) { |
||||
// It's an iframe. Use the top level window
|
||||
// for security purposes
|
||||
win = win.top; |
||||
} |
||||
|
||||
if (gDefaultPastePolicy == true) { |
||||
for (var i=0; i < gDeniedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gDeniedPasteSites[i]) == 0) { |
||||
return false; |
||||
break; |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
for (var i=0; i < gAllowedPasteSites.length; i++) { |
||||
if (win.location.href.indexOf(gAllowedPasteSites[i]) == 0) { |
||||
return true; |
||||
break; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
function myExecCommand(doc, originalExecCommand) { |
||||
return function(aCommandName, aShowDefaultUI, aValueArgument) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
var win = Services.wm.getMostRecentWindow("navigator:browser"); |
||||
win.goDoCommand("cmd_" + aCommandName.toLowerCase()); |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalExecCommand.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
function myQueryCommandSupported(doc, originalQueryCommandSupported) { |
||||
return function(aCommandName) { |
||||
switch (aCommandName.toLowerCase()) { |
||||
case "cut": |
||||
case "copy": |
||||
if (allowCutCopy(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
case "paste": |
||||
if (allowPaste(doc)) { |
||||
return true; |
||||
} |
||||
break; |
||||
} |
||||
return originalQueryCommandSupported.call(doc, aCommandName, aShowDefaultUI, aValueArgument); |
||||
} |
||||
} |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
var cutCopyAllowed = allowCutCopy(doc); |
||||
var pasteAllowed = allowPaste(doc); |
||||
if (!cutCopyAllowed && !pasteAllowed) { |
||||
return; |
||||
} |
||||
var originalExecCommand = Cu.waiveXrays(doc).execCommand; |
||||
Cu.exportFunction(myExecCommand(doc, originalExecCommand), doc, {defineAs: "execCommand"}); |
||||
var originalQueryCommandSupported = Cu.waiveXrays(doc).queryCommandSupported; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandSupported), doc, {defineAs: "queryCommandSupported"}); |
||||
var originalQueryCommandEnabled = Cu.waiveXrays(doc).queryCommandEnabled; |
||||
Cu.exportFunction(myQueryCommandSupported(doc, originalQueryCommandEnabled), doc, {defineAs: "queryCommandEnabled"}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Don't do this check before Firefox 29
|
||||
if (Services.vc.compare(Services.appinfo.version, "29") > 0) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.cutcopy") == "allAccess") { |
||||
gDefaultCutCopyPolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy.default.Clipboard.paste") == "allAccess") { |
||||
gDefaultPastePolicy = true; |
||||
} |
||||
} catch (e) {} |
||||
try { |
||||
var policies = []; |
||||
policies = Services.prefs.getCharPref("capability.policy.policynames").split(', '); |
||||
for (var i=0; i < policies.length; i++ ) { |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "allAccess") { |
||||
var allowedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedCutCopySites.length; j++) { |
||||
gAllowedCutCopySites.push(allowedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.cutcopy") == "noAccess") { |
||||
var deniedCutCopySites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedCutCopySites.length; j++) { |
||||
gDeniedCutCopySites.push(deniedCutCopySites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "allAccess") { |
||||
var allowedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < allowedPasteSites.length; j++) { |
||||
gAllowedPasteSites.push(allowedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
try { |
||||
if (Services.prefs.getCharPref("capability.policy." + policies[i] + ".Clipboard.paste") == "noAccess") { |
||||
var deniedPasteSites = Services.prefs.getCharPref("capability.policy." + policies[i] + ".sites").split(" "); |
||||
for (var j=0; j < deniedPasteSites.length; j++) { |
||||
gDeniedPasteSites.push(deniedPasteSites[j]); |
||||
} |
||||
} |
||||
} catch(e) {} |
||||
} |
||||
} catch (e) {} |
||||
if (gDefaultCutCopyPolicy || gDefaultPastePolicy || |
||||
gAllowedCutCopySites.length > 0 || gAllowedPasteSites> 0) { |
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,111 @@
@@ -0,0 +1,111 @@
|
||||
/* This file overlays about:addons. It does the following: */ |
||||
/* Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1132971 */ |
||||
/* Hide the "Install Add-on From File" menu if xpinstall.enabled is false */ |
||||
/* Hides the discover pane if xpinstall.enabled is false */ |
||||
/* Hides the add-on entry if specified in the CCK2 config */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var addonId = "cck2wizard@kaply.com"; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:addons": |
||||
case "chrome://mozapps/content/extensions/extensions.xul": |
||||
var configs = CCK2.getConfigs(); |
||||
var hiddenAddons = []; |
||||
var requiredAddons = []; |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config && "extension" in config && config.extension.hide) { |
||||
hiddenAddons.push(config.extension.id); |
||||
} |
||||
if (config.requiredAddons) { |
||||
requiredAddons.push.apply(requiredAddons, config.requiredAddons.split(",")); |
||||
} |
||||
} |
||||
if (hiddenAddons.length > 0 || requiredAddons.length > 0) { |
||||
var ss; |
||||
for (var i = 0; i < doc.styleSheets.length; i++) { |
||||
if (doc.styleSheets[i].href == "chrome://mozapps/skin/extensions/extensions.css") { |
||||
ss = doc.styleSheets[i]; |
||||
break; |
||||
} |
||||
} |
||||
for (var i=0; i < hiddenAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + hiddenAddons[i] + "'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
for (var i=0; i < requiredAddons.length; i++) { |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='disable-btn'] { display: none;}", ss.cssRules.length); |
||||
ss.insertRule("richlistitem[value='" + requiredAddons[i] + "'] button[anonid='remove-btn'] { display: none;}", ss.cssRules.length); |
||||
} |
||||
if (requiredAddons.length > 0) { |
||||
win.gViewController.commands.cmd_disableItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_disableItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
win.gViewController.commands.cmd_uninstallItem.origIsEnabled = win.gViewController.commands.cmd_disableItem.isEnabled; |
||||
win.gViewController.commands.cmd_uninstallItem.isEnabled = function(aAddon) { if (aAddon && requiredAddons.indexOf(aAddon.id) != -1) return false; return this.origIsEnabled;} |
||||
} |
||||
} |
||||
var showDiscoverPane = true; |
||||
var xpinstallEnabled = true; |
||||
try { |
||||
xpinstallEnabled = Services.prefs.getBoolPref("xpinstall.enabled"); |
||||
} catch (e) {} |
||||
try { |
||||
showDiscoverPane = Services.prefs.getBoolPref("extensions.getAddons.showPane"); |
||||
} catch (e) {} |
||||
if (!xpinstallEnabled || !showDiscoverPane) { |
||||
// Work around Mozilla bug 1132971
|
||||
// Hide the discover pane if it is the selected pane
|
||||
if (E("view-port", doc) && E("view-port", doc).selectedIndex == 0) { |
||||
try { |
||||
win.gViewController.loadView("addons://list/extension"); |
||||
} catch (ex) { |
||||
// This fails with Webconverger installed. Ignore it.
|
||||
} |
||||
} |
||||
} |
||||
if (!xpinstallEnabled) { |
||||
// Hide the "Install Add-on From File" separator
|
||||
hide(E("utils-installFromFile-separator", doc)); |
||||
// Hide the "Install Add-on From File" menuitem
|
||||
hide(E("utils-installFromFile", doc)); |
||||
win.gDragDrop.onDragOver = function(event) { |
||||
event.dataTransfer.dropEffect = "none"; |
||||
event.stopPropagation(); |
||||
event.preventDefault(); |
||||
}; |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
/* This file is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1139509 */ |
||||
/* It bolds the Firefox version in the about dialog and unbolds the distribution information */ |
||||
/* It can be removed once Firefox 38 ESR is out of support */ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/aboutDialog.xul": |
||||
doc.querySelector("#version").style.fontWeight = "bold"; |
||||
doc.querySelector("#distribution").style.fontWeight = "normal"; |
||||
doc.querySelector("#distributionId").style.fontWeight = "normal"; |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/* This file overrides about:home. It does the following: |
||||
* Remove the sync button if Sync is disabled |
||||
* Remove the Addons button if Sync is disabled |
||||
* Remove the snippets if snippets are disabled |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "content-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:home": |
||||
case "chrome://browser/content/abouthome/aboutHome.xhtml": |
||||
if (!configs) { |
||||
// TODO - Make this Async
|
||||
configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
remove(E("sync", doc)); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
remove(E("addons", doc)); |
||||
} |
||||
if (config.disableWebApps) { |
||||
remove(E("apps", doc)); |
||||
} |
||||
if (config.removeSnippets) { |
||||
var snippets = E("snippets", doc); |
||||
if (snippets) { |
||||
snippets.style.display = "none"; |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(config.hiddenUI[i]); |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
uiElement.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "content-document-global-created", false); |
||||
|
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(observer, "content-document-global-created", false); |
||||
}) |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* This file overrides about:support It does the following: |
||||
* Remove the reset Firefox button if disableResetFirefox is set |
||||
* Remove the safe mode Button if disableSafeMode is set |
||||
* Remove the box if both are set |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "about:support": |
||||
case "chrome://global/content/aboutSupport.xhtml": |
||||
if (!configs) { |
||||
configs = CCK2.getConfigs(); |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableResetFirefox) { |
||||
remove(E("reset-box", doc)); |
||||
} |
||||
if (config.disableSafeMode) { |
||||
remove(E("safe-mode-box", doc)); |
||||
} |
||||
if (config.disableResetFirefox && |
||||
config.disableSafeMode) { |
||||
remove(E("action-box", doc)); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
|
||||
function remove(element) { |
||||
if (element && element.parentNode) |
||||
element.parentNode.removeChild(element); |
||||
} |
@ -0,0 +1,373 @@
@@ -0,0 +1,373 @@
|
||||
/* This file modifies the main browser window. It does the following: |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource:///modules/CustomizableUI.jsm"); |
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/browser.xul": |
||||
// Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1149617
|
||||
var origSetReportPhishingMenu = win.gSafeBrowsing.setReportPhishingMenu; |
||||
win.gSafeBrowsing.setReportPhishingMenu = function() { |
||||
try { |
||||
origSetReportPhishingMenu(); |
||||
} catch (e) {} |
||||
} |
||||
|
||||
win.addEventListener("unload", function onUnload(event) { |
||||
win.removeEventListener("unload", onUnload, false); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).removeEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
}); |
||||
var panelUIPopup = doc.getElementById("PanelUI-popup"); |
||||
if (panelUIPopup) { |
||||
E("PanelUI-popup", doc).addEventListener("popupshowing", onPanelShowing, false); |
||||
} |
||||
var appMenuPopup = doc.getElementById("appMenu-popup"); |
||||
if (appMenuPopup) { |
||||
E("appMenu-popup", doc).addEventListener("popupshowing", onAppMenuShowing, false); |
||||
} |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
config = configs[id]; |
||||
if (config.disablePrivateBrowsing && |
||||
PrivateBrowsingUtils.isWindowPrivate(win)) { |
||||
win.setTimeout(function() { |
||||
Services.prompt.alert(win, "Private Browsing", "Private Browsing has been disabled by your administrator"); |
||||
win.close(); |
||||
}, 0, false); |
||||
} |
||||
if (config.disablePrivateBrowsing) { |
||||
disablePrivateBrowsing(doc); |
||||
} |
||||
if (config.disableSync) { |
||||
disableSync(doc); |
||||
} |
||||
if (config.disableAddonsManager) { |
||||
disableAddonsManager(doc); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
Services.tm.mainThread.dispatch(function() { |
||||
removeDeveloperTools(doc); |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.disableErrorConsole) { |
||||
disableErrorConsole(doc); |
||||
} |
||||
if (config.disableFirefoxHealthReport) { |
||||
var healthReportMenu = doc.getElementById("healthReport"); |
||||
if (healthReportMenu) { |
||||
healthReportMenu.parentNode.removeChild(healthReportMenu); |
||||
} |
||||
} |
||||
if (config.removeSafeModeMenu) { |
||||
hide(E("helpSafeMode", doc)); |
||||
} |
||||
if (config.titlemodifier) { |
||||
doc.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier); |
||||
} |
||||
if (config.removeSetDesktopBackground) { |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-setDesktopBackground", doc)) { |
||||
E("context-setDesktopBackground", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableWebApps) { |
||||
CustomizableUI.destroyWidget("web-apps-button"); |
||||
hide(E("menu_openApps", doc)); |
||||
} |
||||
if (config.disableHello) { |
||||
CustomizableUI.destroyWidget("loop-button"); |
||||
hide(E("menu_openLoop", doc)); |
||||
} |
||||
if (config.disablePocket) { |
||||
CustomizableUI.destroyWidget("pocket-button"); |
||||
} |
||||
if (config.disableSharePage) { |
||||
CustomizableUI.destroyWidget("social-share-button"); |
||||
// Because these are on a context menu, we can't use "hidden"
|
||||
if (E("context-sharelink", doc)) { |
||||
E("context-sharelink", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareselect", doc)) { |
||||
E("context-shareselect", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-shareimage", doc)) { |
||||
E("context-shareimage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharevideo", doc)) { |
||||
E("context-sharevideo", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
if (E("context-sharepage", doc)) { |
||||
E("context-sharepage", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.disableSocialAPI) { |
||||
win.SocialActivationListener = {}; |
||||
} |
||||
if (config.disableForget) { |
||||
CustomizableUI.destroyWidget("panic-button"); |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
if (config.helpMenu) { |
||||
// We need to run this function on a delay, because we won't know
|
||||
// if the about menu is hidden for mac until after it is run.
|
||||
Services.tm.mainThread.dispatch(function() { |
||||
var helpMenuPopup = doc.getElementById("menu_HelpPopup"); |
||||
var menuitem = doc.createElement("menuitem"); |
||||
menuitem.setAttribute("label", config.helpMenu.label); |
||||
if ("accesskey" in config.helpMenu) { |
||||
menuitem.setAttribute("accesskey", config.helpMenu.accesskey); |
||||
} |
||||
menuitem.setAttribute("oncommand", "openUILink('" + config.helpMenu.url + "');"); |
||||
menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);"); |
||||
if (!E("aboutName", doc) || E("aboutName", doc).hidden) { |
||||
// Mac
|
||||
helpMenuPopup.appendChild(menuitem); |
||||
} else { |
||||
helpMenuPopup.insertBefore(menuitem, E("aboutName", doc)); |
||||
helpMenuPopup.insertBefore(doc.createElement("menuseparator"), |
||||
E("aboutName", doc)); |
||||
} |
||||
}, Ci.nsIThread.DISPATCH_NORMAL); |
||||
} |
||||
if (config.firstrun || config.upgrade) { |
||||
if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) { |
||||
CustomizableUI.setToolbarVisibility("PersonalToolbar", "true"); |
||||
} |
||||
if (config.displayMenuBar) { |
||||
CustomizableUI.setToolbarVisibility("toolbar-menubar", "true"); |
||||
} |
||||
if (config.showSearchBar) { |
||||
CustomizableUI.addWidgetToArea("search-container", CustomizableUI.AREA_NAVBAR, |
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1); |
||||
} |
||||
config.firstrun = false; |
||||
config.upgrade = false; |
||||
} |
||||
} |
||||
break; |
||||
case "chrome://browser/content/places/places.xul": |
||||
case "chrome://browser/content/bookmarks/bookmarksPanel.xul": |
||||
case "chrome://browser/content/history/history-panel.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
if (E("placesContext_open:newprivatewindow", doc)) { |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
} |
||||
} |
||||
if (config.hiddenUI) { |
||||
hideUIElements(doc, config.hiddenUI); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
function disableSync(doc) { |
||||
var win = doc.defaultView; |
||||
if (win.gSyncUI) { |
||||
var mySyncUI = { |
||||
init: function() { |
||||
return; |
||||
}, |
||||
initUI: function() { |
||||
return; |
||||
}, |
||||
updateUI: function() { |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
} |
||||
win.gSyncUI = mySyncUI; |
||||
} |
||||
CustomizableUI.destroyWidget("sync-button"); |
||||
CustomizableUI.removeWidgetFromArea("sync-button"); |
||||
var toolbox = doc.getElementById("navigator-toolbox"); |
||||
if (toolbox && toolbox.palette) { |
||||
let element = toolbox.palette.querySelector("#sync-button"); |
||||
if (element) { |
||||
element.parentNode.removeChild(element); |
||||
} |
||||
} |
||||
hide(E("sync-setup-state", doc)); |
||||
hide(E("sync-syncnow-state", doc)); |
||||
hide(E("sync-setup", doc)); |
||||
hide(E("sync-syncnowitem", doc)); |
||||
} |
||||
|
||||
function disablePrivateBrowsing(doc) { |
||||
disable(E("Tools:PrivateBrowsing", doc)); |
||||
hide(E("menu_newPrivateWindow", doc)); |
||||
// Because this is on a context menu, we can't use "hidden"
|
||||
if (E("context-openlinkprivate", doc)) |
||||
E("context-openlinkprivate", doc).setAttribute("style", "display: none;"); |
||||
if (E("placesContext_open:newprivatewindow", doc)) |
||||
E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;"); |
||||
CustomizableUI.destroyWidget("privatebrowsing-button") |
||||
} |
||||
|
||||
function disableAddonsManager(doc) { |
||||
hide(E("menu_openAddons", doc)); |
||||
disable(E("Tools:Addons", doc)); // Ctrl+Shift+A
|
||||
CustomizableUI.destroyWidget("add-ons-button") |
||||
} |
||||
|
||||
function removeDeveloperTools(doc) { |
||||
var win = doc.defaultView; |
||||
// Need to delay this because devtools is created dynamically
|
||||
win.setTimeout(function() { |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
hide(E("webDeveloperMenu", doc)); |
||||
var devtoolsKeyset = doc.getElementById("devtoolsKeyset"); |
||||
if (devtoolsKeyset) { |
||||
for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) { |
||||
devtoolsKeyset.childNodes[i].removeAttribute("oncommand"); |
||||
devtoolsKeyset.childNodes[i].removeAttribute("command"); |
||||
} |
||||
} |
||||
}, 0); |
||||
try { |
||||
doc.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:Scratchpad").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserConsole").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbar").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbox").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
try { |
||||
doc.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand"); |
||||
} catch (e) {} |
||||
CustomizableUI.destroyWidget("developer-button") |
||||
} |
||||
|
||||
function disableErrorConsole(doc) { |
||||
doc.getElementById("Tools:ErrorConsole").removeAttribute("oncommand"); |
||||
} |
||||
|
||||
function onPanelShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("PanelUI-fxa-status", event.target.ownerDocument)); |
||||
hide(E("PanelUI-footer-fxa", event.target.ownerDocument)); // Firefox 42+
|
||||
} |
||||
} |
||||
} |
||||
|
||||
function onAppMenuShowing(event) { |
||||
var configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("appMenu-fxa-container", event.target.ownerDocument)); |
||||
} |
||||
if (config.removeDeveloperTools) { |
||||
hide(E("appMenu-developer-button", event.target.ownerDocument)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
element.setAttribute("disabled", "true"); |
||||
} |
||||
} |
||||
|
||||
function hideUIElements(doc, hiddenUI) { |
||||
for (var i=0; i < hiddenUI.length; i++) { |
||||
var uiElements = doc.querySelectorAll(hiddenUI[i]); |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + hiddenUI[i] + "{display: none !important;}"; |
||||
if (!uiElements || uiElements.length == 0) { |
||||
continue; |
||||
} |
||||
for (var j=0; j < uiElements.length; j++) { |
||||
var uiElement = uiElements[j]; |
||||
if (uiElement.nodeName == "menuitem") { |
||||
uiElement.removeAttribute("key"); |
||||
uiElement.removeAttribute("oncommand"); |
||||
if (uiElement.hasAttribute("command")) { |
||||
var commandId = uiElement.getAttribute("command"); |
||||
uiElement.removeAttribute("command"); |
||||
var command = doc.getElementById(commandId); |
||||
command.removeAttribute("oncommand"); |
||||
var keys = doc.querySelectorAll("key[command='" + commandId + "']") |
||||
for (var k=0; k < keys.length; k++) { |
||||
keys[k].removeAttribute("command"); |
||||
} |
||||
} |
||||
} |
||||
// Horrible hack to work around the crappy Australis help menu
|
||||
// Items on the menu always show up in the Australis menu, so we have to remove them.
|
||||
if (uiElements[j].parentNode.id == "menu_HelpPopup") { |
||||
uiElements[j].parentNode.removeChild(uiElements[j]); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = []; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
let CCK2FileBlock = { |
||||
chromeBlacklist: ["browser", "mozapps", "marionette", "specialpowers", |
||||
"branding", "alerts"], |
||||
shouldLoad: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
// Prevent the loading of chrome URLs into the main browser window
|
||||
if (aContentLocation.scheme == "chrome") { |
||||
if (aRequestOrigin && |
||||
(aRequestOrigin.spec == "chrome://browser/content/browser.xul" || |
||||
aRequestOrigin.scheme == "moz-nullprincipal")) { |
||||
for (var i=0; i < this.chromeBlacklist.length; i++) { |
||||
if (aContentLocation.host == this.chromeBlacklist[i]) { |
||||
if (aContentLocation.spec.includes(".xul")) { |
||||
return Ci.nsIContentPolicy.REJECT_REQUEST; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
shouldProcess: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { |
||||
return Ci.nsIContentPolicy.ACCEPT; |
||||
}, |
||||
classDescription: "CCK2 FileBlock Service", |
||||
contractID: "@kaply.com/cck2-fileblock-service;1", |
||||
classID: Components.ID('{26e7afc9-e22d-4d12-bb57-c184fe24b828}'), |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]), |
||||
createInstance: function(outer, iid) { |
||||
return this.QueryInterface(iid); |
||||
}, |
||||
}; |
||||
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
||||
registrar.registerFactory(CCK2FileBlock.classID, |
||||
CCK2FileBlock.classDescription, |
||||
CCK2FileBlock.contractID, |
||||
CCK2FileBlock); |
||||
|
||||
var cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); |
||||
cm.addCategoryEntry("content-policy", CCK2FileBlock.contractID, |
||||
CCK2FileBlock.contractID, false, true); |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var disableSearchEngineInstall = false; |
||||
|
||||
var documentObserver = { |
||||
observe: function observe(subject, topic, data) { |
||||
if (subject instanceof Ci.nsIDOMWindow && topic == 'content-document-global-created') { |
||||
var doc = subject.document; |
||||
doc.addEventListener("DOMContentLoaded", function onLoad(event) { |
||||
event.target.removeEventListener("DOMContentLoaded", onLoad, false); |
||||
if (disableSearchEngineInstall) { |
||||
subject.wrappedJSObject.external.AddSearchProvider = function() {}; |
||||
} |
||||
if (!doc.documentURI.startsWith("about:")) { |
||||
return; |
||||
} |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
}, false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
var configs = sendSyncMessage("cck2:get-configs")[0]; |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSearchEngineInstall) { |
||||
disableSearchEngineInstall = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
Services.obs.addObserver(documentObserver, "content-document-global-created", false); |
||||
addEventListener("unload", function() { |
||||
Services.obs.removeObserver(documentObserver, "content-document-global-created", false); |
||||
}) |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/* This file modifies the preferences dialogs. It does the following: |
||||
* Removes private browsing from the pref UI if it is disabled |
||||
* Removes Sync from the pref UI if it is diabled |
||||
* Disables the crash reporter button if crash reporter is disabled |
||||
* Removed the master password UI if it is disabled |
||||
* Goes through the hiddenUI list and hides any UI |
||||
* |
||||
*/ |
||||
|
||||
const EXPORTED_SYMBOLS = []; |
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://cck2/CCK2.jsm"); |
||||
|
||||
var configs = null; |
||||
|
||||
var observer = { |
||||
observe: function observe(subject, topic, data) { |
||||
switch (topic) { |
||||
case "chrome-document-global-created": |
||||
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow); |
||||
win.addEventListener("load", function onLoad(event) { |
||||
win.removeEventListener("load", onLoad, false); |
||||
var doc = event.target; |
||||
var url = doc.location.href.split("?")[0].split("#")[0]; |
||||
switch (url) { |
||||
case "chrome://browser/content/preferences/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
win.addEventListener("paneload", function(event) { |
||||
updatePrefUI(event.target.ownerDocument); |
||||
}, false); |
||||
updatePrefUI(doc); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (!config.disableSync) { |
||||
continue; |
||||
} |
||||
var prefWindow = E("BrowserPreferences", doc); |
||||
var paneSyncRadio = doc.getAnonymousElementByAttribute(prefWindow, "pane", "paneSync"); |
||||
hide(paneSyncRadio); |
||||
var paneDeck = doc.getAnonymousElementByAttribute(prefWindow, "anonid", "paneDeck"); |
||||
var paneSync = E("paneSync", doc); |
||||
paneSync.removeAttribute("helpTopic"); |
||||
var weavePrefsDeck = E("weavePrefsDeck", doc); |
||||
if (weavePrefsDeck) |
||||
weavePrefsDeck.parentNode.removeChild(weavePrefsDeck); |
||||
if (prefWindow.currentPane == E("paneSync", doc)) |
||||
prefWindow.showPane(E("paneMain", doc)); |
||||
} |
||||
break; |
||||
case "about:preferences": |
||||
case "chrome://browser/content/preferences/in-content/preferences.xul": |
||||
configs = CCK2.getConfigs(); |
||||
for (let id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disableSync) { |
||||
hide(E("category-sync", doc)); |
||||
} |
||||
} |
||||
updatePrefUI(doc); |
||||
break; |
||||
} |
||||
}, false); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
Services.obs.addObserver(observer, "chrome-document-global-created", false); |
||||
|
||||
// The IDs are the same, so I can reuse this for regular and in-content prefs
|
||||
function updatePrefUI(doc) { |
||||
for (var id in configs) { |
||||
var config = configs[id]; |
||||
if (config.disablePrivateBrowsing) { |
||||
hide(E("privateBrowsingAutoStart", doc)); |
||||
var privateBrowsingMenu = doc.querySelector("menuitem[value='dontremember']"); |
||||
hide(privateBrowsingMenu, doc); |
||||
} |
||||
if (config.disableCrashReporter) { |
||||
disable(E("submitCrashesBox", doc)); |
||||
} |
||||
if (config.disableSync) { |
||||
hide(E("noFxaAccount", doc)); |
||||
hide(E("hasFxaAccount", doc)); |
||||
} |
||||
if (config.noMasterPassword == true) { |
||||
hide(E("useMasterPassword", doc)); |
||||
hide(E("changeMasterPassword", doc)); |
||||
} |
||||
if (config.hiddenUI) { |
||||
for (var i=0; i < config.hiddenUI.length; i++) { |
||||
// Don't use .hidden since it doesn't work sometimes
|
||||
var style = doc.getElementById("cck2-hidden-style"); |
||||
if (!style) { |
||||
style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); |
||||
style.setAttribute("id", "cck2-hidden-style"); |
||||
style.setAttribute("type", "text/css"); |
||||
doc.documentElement.appendChild(style); |
||||
} |
||||
style.textContent = style.textContent + config.hiddenUI[i] + "{display: none !important;}"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
function E(id, context) { |
||||
var element = context.getElementById(id); |
||||
return element; |
||||
} |
||||
|
||||
function hide(element) { |
||||
if (element) { |
||||
element.setAttribute("hidden", "true"); |
||||
} |
||||
} |
||||
|
||||
function disable(element) { |
||||
if (element) { |
||||
element.disabled = true; |
||||
} |
||||
} |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/** |
||||
* Copied from https://github.com/jvillalobos/CTP-Manager/blob/master/extension/modules/permissions.js
|
||||
**/ |
||||
|
||||
/** |
||||
* Copyright 2013 Jorge Villalobos |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
**/ |
||||
|
||||
var EXPORTED_SYMBOLS = ["CTP"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
var CTP = { |
||||
/** |
||||
* Cleans up the plugin name to a more readable form. |
||||
* Taken from /browser/base/content/pageinfo/permissions.js (Firefox 20) |
||||
* @param aPluginName the name to clean up. |
||||
* @return cleaned up plugin name. |
||||
*/ |
||||
makeNicePluginName : function(aPluginName) { |
||||
let newName = |
||||
aPluginName.replace(/[\s\d\.\-\_\(\)]+$/, ""). |
||||
replace(/\bplug-?in\b/i, "").trim(); |
||||
|
||||
return newName; |
||||
}, |
||||
|
||||
/** |
||||
* Gets the plugin permission string from the tag object. In Firefox 20, this |
||||
* is the plugin filename. In 21 an above, the file extension is removed and |
||||
* Flash and Java are special-cased. |
||||
* @param aTag the tag object with the plugin information. |
||||
* @return permission string that corresponds to the plugin in the tag. |
||||
*/ |
||||
getPluginPermissionFromTag : function(aTag) { |
||||
let permission = null; |
||||
let majorVersion = Services.appinfo.platformVersion.split(".")[0]; |
||||
|
||||
if (21 <= majorVersion) { |
||||
let mimeTypes = aTag.getMimeTypes(); |
||||
|
||||
if (CTP.isFlashPlugin(mimeTypes)) { |
||||
permission = "flash"; |
||||
} else if (CTP.isJavaPlugin(mimeTypes)) { |
||||
permission = "java"; |
||||
} else { |
||||
let lastPeriod = aTag.filename.lastIndexOf("."); |
||||
|
||||
permission = |
||||
((0 < lastPeriod) ? aTag.filename.substring(0, lastPeriod) : |
||||
aTag.filename); |
||||
// Remove digits at the end
|
||||
permission = permission.replace(/[0-9]+$/, ""); |
||||
permission = permission.toLowerCase(); |
||||
} |
||||
} else { |
||||
permission = aTag.filename; |
||||
} |
||||
|
||||
return permission; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Java plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Java plugin. |
||||
*/ |
||||
isJavaPlugin : function(aMimeTypes) { |
||||
let isJava = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if ((0 == mimeType.indexOf("application/x-java-vm")) || |
||||
(0 == mimeType.indexOf("application/x-java-applet")) || |
||||
(0 == mimeType.indexOf("application/x-java-bean"))) { |
||||
isJava = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isJava; |
||||
}, |
||||
|
||||
/** |
||||
* Checks if the tag object corresponds to the Flash plugin. |
||||
* @param aMimeTypes the list of MIME types for the plugin. |
||||
* @return true if the tag corresponds to the Flash plugin. |
||||
*/ |
||||
isFlashPlugin : function(aMimeTypes) { |
||||
let isFlash = false; |
||||
let mimeType; |
||||
|
||||
for (let i = 0; i < aMimeTypes.length; i++) { |
||||
mimeType = |
||||
((null != aMimeTypes[i].type) ? aMimeTypes[i].type : aMimeTypes[i]); |
||||
|
||||
if (0 == mimeType.indexOf("application/x-shockwave-flash")) { |
||||
isFlash = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return isFlash; |
||||
} |
||||
}; |
@ -0,0 +1,629 @@
@@ -0,0 +1,629 @@
|
||||
/* ***** BEGIN LICENSE BLOCK ***** |
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
||||
* |
||||
* The contents of this file are subject to the Mozilla Public License Version |
||||
* 1.1 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* http://www.mozilla.org/MPL/
|
||||
* |
||||
* Software distributed under the License is distributed on an "AS IS" basis, |
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
||||
* for the specific language governing rights and limitations under the |
||||
* License. |
||||
* |
||||
* The Original Code is Preferences. |
||||
* |
||||
* The Initial Developer of the Original Code is Mozilla. |
||||
* Portions created by the Initial Developer are Copyright (C) 2008 |
||||
* the Initial Developer. All Rights Reserved. |
||||
* |
||||
* Contributor(s): |
||||
* Myk Melez <myk@mozilla.org> |
||||
* Daniel Aquino <mr.danielaquino@gmail.com> |
||||
* |
||||
* Alternatively, the contents of this file may be used under the terms of |
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or |
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
||||
* in which case the provisions of the GPL or the LGPL are applicable instead |
||||
* of those above. If you wish to allow use of your version of this file only |
||||
* under the terms of either the GPL or the LGPL, and not to allow others to |
||||
* use your version of this file under the terms of the MPL, indicate your |
||||
* decision by deleting the provisions above and replace them with the notice |
||||
* and other provisions required by the GPL or the LGPL. If you do not delete |
||||
* the provisions above, a recipient may use your version of this file under |
||||
* the terms of any one of the MPL, the GPL or the LGPL. |
||||
* |
||||
* ***** END LICENSE BLOCK ***** */ |
||||
|
||||
let EXPORTED_SYMBOLS = ["Preferences"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cr = Components.results; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// The minimum and maximum integers that can be set as preferences.
|
||||
// The range of valid values is narrower than the range of valid JS values
|
||||
// because the native preferences code treats integers as NSPR PRInt32s,
|
||||
// which are 32-bit signed integers on all platforms.
|
||||
const MAX_INT = Math.pow(2, 31) - 1; |
||||
const MIN_INT = -MAX_INT; |
||||
|
||||
function Preferences(args) { |
||||
if (isObject(args)) { |
||||
if (args.branch) |
||||
this._prefBranch = args.branch; |
||||
} |
||||
else if (args) |
||||
this._prefBranch = args; |
||||
this.isDefaultBranch = false; |
||||
} |
||||
|
||||
Preferences.prototype = { |
||||
/** |
||||
* Get the value of a pref, if any; otherwise return the default value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to get, or an array of prefs to get |
||||
* |
||||
* @param defaultValue |
||||
* the default value, if any, for prefs that don't have one |
||||
* |
||||
* @returns the value of the pref, if any; otherwise the default value |
||||
*/ |
||||
get: function(prefName, defaultValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(v => this.get(v, defaultValue)); |
||||
|
||||
return this._get(prefName, defaultValue); |
||||
}, |
||||
|
||||
// In all cases below, the preference might exist as a user pref, but not
|
||||
// have a default value. In those cases, get* throws. Return the default value.
|
||||
_get: function(prefName, defaultValue) { |
||||
switch (this._prefSvc.getPrefType(prefName)) { |
||||
case Ci.nsIPrefBranch.PREF_STRING: |
||||
try { |
||||
return this._prefSvc.getComplexValue(prefName, Ci.nsISupportsString).data; |
||||
} catch (ex) { |
||||
if (this.isDefaultBranch) |
||||
return defaultValue; |
||||
else |
||||
return this._prefSvc.getCharPref(prefName); |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INT: |
||||
try { |
||||
return this._prefSvc.getIntPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_BOOL: |
||||
try { |
||||
return this._prefSvc.getBoolPref(prefName); |
||||
} catch (ex) { |
||||
return defaultValue; |
||||
} |
||||
|
||||
case Ci.nsIPrefBranch.PREF_INVALID: |
||||
return defaultValue; |
||||
|
||||
default: |
||||
// This should never happen.
|
||||
throw "Error getting pref " + prefName + "; its value's type is " + |
||||
this._prefSvc.getPrefType(prefName) + ", which I don't know " + |
||||
"how to handle."; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Set a preference to a value. |
||||
* |
||||
* You can set multiple prefs by passing an object as the only parameter. |
||||
* In that case, this method will treat the properties of the object |
||||
* as preferences to set, where each property name is the name of a pref |
||||
* and its corresponding property value is the value of the pref. |
||||
* |
||||
* @param prefName {String|Object} |
||||
* the name of the pref to set; or an object containing a set |
||||
* of prefs to set |
||||
* |
||||
* @param prefValue {String|Number|Boolean} |
||||
* the value to which to set the pref |
||||
* |
||||
* Note: Preferences cannot store non-integer numbers or numbers outside |
||||
* the signed 32-bit range -(2^31-1) to 2^31-1, If you have such a number, |
||||
* store it as a string by calling toString() on the number before passing |
||||
* it to this method, i.e.: |
||||
* Preferences.set("pi", 3.14159.toString()) |
||||
* Preferences.set("big", Math.pow(2, 31).toString()). |
||||
*/ |
||||
set: function(prefName, prefValue) { |
||||
if (isObject(prefName)) { |
||||
for (let [name, value] in Iterator(prefName)) |
||||
this.set(name, value); |
||||
return; |
||||
} |
||||
|
||||
this._set(prefName, prefValue); |
||||
}, |
||||
|
||||
_set: function(prefName, prefValue) { |
||||
let prefType; |
||||
if (typeof prefValue != "undefined" && prefValue != null) |
||||
prefType = prefValue.constructor.name; |
||||
|
||||
var existingPrefType = this._prefSvc.getPrefType(prefName); |
||||
if (existingPrefType != Ci.nsIPrefBranch.PREF_INVALID) |
||||
{ |
||||
// convert
|
||||
if (existingPrefType == Ci.nsIPrefBranch.PREF_INT && prefType == "String") |
||||
{ |
||||
prefValue = parseInt(prefValue); |
||||
if (isNaN(prefValue)) |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Number"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "String") |
||||
{ |
||||
if (prefValue == "true") |
||||
prefValue = true; |
||||
else if (prefValue == "false") |
||||
prefValue = false; |
||||
else |
||||
throw "Incompatible pref value type - " + prefName; |
||||
prefType = "Boolean"; |
||||
} |
||||
else if (existingPrefType == Ci.nsIPrefBranch.PREF_BOOL && prefType == "Number") |
||||
{ |
||||
prefValue = prefValue != 0; |
||||
prefType = "Boolean"; |
||||
} |
||||
} |
||||
|
||||
switch (prefType) { |
||||
case "String": |
||||
{ |
||||
try { |
||||
this._prefSvc.setStringPref(prefName, prefValue); |
||||
} catch (e) { |
||||
try { |
||||
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); |
||||
string.data = prefValue; |
||||
this._prefSvc.setComplexValue(prefName, Ci.nsISupportsString, string); |
||||
} catch (e2) { |
||||
Components.utils.reportError(e2); |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case "Number": |
||||
// We throw if the number is outside the range, since the result
|
||||
// will never be what the consumer wanted to store, but we only warn
|
||||
// if the number is non-integer, since the consumer might not mind
|
||||
// the loss of precision.
|
||||
if (prefValue > MAX_INT || prefValue < MIN_INT) |
||||
throw("you cannot set the " + prefName + " pref to the number " + |
||||
prefValue + ", as number pref values must be in the signed " + |
||||
"32-bit integer range -(2^31-1) to 2^31-1. To store numbers " + |
||||
"outside that range, store them as strings."); |
||||
try { |
||||
this._prefSvc.setIntPref(prefName, prefValue); |
||||
} catch (e) { |
||||
throw new Error(e.toString() + " - " + prefName); |
||||
} |
||||
if (prefValue % 1 != 0) |
||||
Cu.reportError("Warning: setting the " + prefName + " pref to the " + |
||||
"non-integer number " + prefValue + " converted it " + |
||||
"to the integer number " + this.get(prefName) + |
||||
"; to retain fractional precision, store non-integer " + |
||||
"numbers as strings."); |
||||
break; |
||||
|
||||
case "Boolean": |
||||
this._prefSvc.setBoolPref(prefName, prefValue); |
||||
break; |
||||
|
||||
default: |
||||
throw "can't set pref " + prefName + " to value '" + prefValue + |
||||
"'; it isn't a String, Number, or Boolean"; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a value. This is different from isSet |
||||
* because it returns true whether the value of the pref is a default value |
||||
* or a user-set value, while isSet only returns true if the value |
||||
* is a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a value; or, if the caller provided |
||||
* an array of pref names, an array of booleans indicating whether |
||||
* or not the prefs have values |
||||
*/ |
||||
has: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.has, this); |
||||
|
||||
return this._has(prefName); |
||||
}, |
||||
|
||||
_has: function(prefName) { |
||||
return (this._prefSvc.getPrefType(prefName) != Ci.nsIPrefBranch.PREF_INVALID); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. This is different |
||||
* from |has| because it returns true only if the value of the pref is a user- |
||||
* set value, while |has| returns true if the value of the pref is a default |
||||
* value or a user-set value. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref has a user-set value; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs have user-set values |
||||
*/ |
||||
isSet: function(prefName) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.isSet, this); |
||||
|
||||
return (this.has(prefName) && this._prefSvc.prefHasUserValue(prefName)); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref has a user-set value. Use isSet instead, |
||||
* which is equivalent. |
||||
* @deprecated |
||||
*/ |
||||
modified: function(prefName) { return this.isSet(prefName) }, |
||||
|
||||
reset: function(prefName) { |
||||
if (isArray(prefName)) { |
||||
prefName.map(v => this.reset(v)); |
||||
return; |
||||
} |
||||
|
||||
this._reset(prefName); |
||||
}, |
||||
|
||||
_reset: function(prefName) { |
||||
try { |
||||
this._prefSvc.clearUserPref(prefName); |
||||
} |
||||
catch(ex) { |
||||
// The pref service throws NS_ERROR_UNEXPECTED when the caller tries
|
||||
// to reset a pref that doesn't exist or is already set to its default
|
||||
// value. This interface fails silently in those cases, so callers
|
||||
// can unconditionally reset a pref without having to check if it needs
|
||||
// resetting first or trap exceptions after the fact. It passes through
|
||||
// other exceptions, however, so callers know about them, since we don't
|
||||
// know what other exceptions might be thrown and what they might mean.
|
||||
if (ex.result != Cr.NS_ERROR_UNEXPECTED) |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* If you need to know the default values, without resetting the actual |
||||
* user prefs, you can use this. |
||||
* @returns {Preferences} a new Preferences object, which accesses |
||||
* the defaults rather than the user prefs. |
||||
* *Only* call get() on this. |
||||
* If you call set(), you will modify the defaults, so don't do that! |
||||
*/ |
||||
get defaults() { |
||||
// nsIPrefService
|
||||
let defaultBranch = Services.prefs. |
||||
getDefaultBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
let prefs = new Preferences(this._prefBranch); |
||||
// override. nasty, but this is internal, so OK.
|
||||
Object.defineProperty(prefs, "_prefSvc", { |
||||
get: function() { |
||||
return defaultBranch; |
||||
} |
||||
}); |
||||
prefs.isDefaultBranch = true; |
||||
return prefs; |
||||
}, |
||||
|
||||
/** |
||||
* Lock a pref so it can't be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
* @param prefValue {String} (optional) |
||||
* default value of pref to lock only works if prefName isn't an array |
||||
*/ |
||||
lock: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.lock, this); |
||||
else if (typeof prefValue != "undefined") |
||||
this.defaults.set(prefName, prefValue); |
||||
|
||||
this._prefSvc.lockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Unlock a pref so it can be changed. |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to lock, or an array of prefs to lock |
||||
*/ |
||||
unlock: function(prefName) { |
||||
if (isArray(prefName)) |
||||
prefName.map(this.unlock, this); |
||||
|
||||
this._prefSvc.unlockPref(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Whether or not the given pref is locked against changes and |
||||
* if it is set to the passedi n value |
||||
* |
||||
* @param prefName {String|Array} |
||||
* the pref to check, or an array of prefs to check |
||||
* @param prefValue {String|Number|Boolean}} |
||||
* the pref value to compare against |
||||
* |
||||
* @returns {Boolean|Array} |
||||
* whether or not the pref is locked; or, if the caller |
||||
* provided an array of pref names, an array of booleans indicating |
||||
* whether or not the prefs are locked |
||||
* If a pref value was specified returns whether or not the pref |
||||
* was locked and equal to the passed in value. |
||||
*/ |
||||
locked: function(prefName, prefValue) { |
||||
if (isArray(prefName)) |
||||
return prefName.map(this.locked, this); |
||||
|
||||
if (prefValue) |
||||
return this._prefSvc.prefIsLocked(prefName) && (this.get(prefName) == prefValue); |
||||
else |
||||
return this._prefSvc.prefIsLocked(prefName); |
||||
}, |
||||
|
||||
/** |
||||
* Start observing a pref. |
||||
* |
||||
* The callback can be a function or any object that implements nsIObserver. |
||||
* When the callback is a function and thisObject is provided, it gets called |
||||
* as a method of thisObject. |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref to observe |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code to notify when the pref changes; |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object to use as |this| when calling a Function callback; |
||||
* |
||||
* @returns the wrapped observer |
||||
*/ |
||||
observe: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
let observer = new PrefObserver(fullPrefName, callback, thisObject); |
||||
Preferences._prefSvc.addObserver(fullPrefName, observer, true); |
||||
observers.push(observer); |
||||
|
||||
return observer; |
||||
}, |
||||
|
||||
/** |
||||
* Stop observing a pref. |
||||
* |
||||
* You must call this method with the same prefName, callback, and thisObject |
||||
* with which you originally registered the observer. However, you don't have |
||||
* to call this method on the same exact instance of Preferences; you can call |
||||
* it on any instance. For example, the following code first starts and then |
||||
* stops observing the "foo.bar.baz" preference: |
||||
* |
||||
* let observer = function() {...}; |
||||
* Preferences.observe("foo.bar.baz", observer); |
||||
* new Preferences("foo.bar.").ignore("baz", observer); |
||||
* |
||||
* @param prefName {String} |
||||
* the name of the pref being observed |
||||
* |
||||
* @param callback {Function|Object} |
||||
* the code being notified when the pref changes |
||||
* |
||||
* @param thisObject {Object} [optional] |
||||
* the object being used as |this| when calling a Function callback |
||||
*/ |
||||
ignore: function(prefName, callback, thisObject) { |
||||
let fullPrefName = this._prefBranch + (prefName || ""); |
||||
|
||||
// This seems fairly inefficient, but I'm not sure how much better we can
|
||||
// make it. We could index by fullBranch, but we can't index by callback
|
||||
// or thisObject, as far as I know, since the keys to JavaScript hashes
|
||||
// (a.k.a. objects) can apparently only be primitive values.
|
||||
let [observer] = observers.filter(v => v.prefName == fullPrefName && |
||||
v.callback == callback && |
||||
v.thisObject == thisObject); |
||||
|
||||
if (observer) { |
||||
Preferences._prefSvc.removeObserver(fullPrefName, observer); |
||||
observers.splice(observers.indexOf(observer), 1); |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Same as observe(), but automatically unregisters itself when |
||||
* the window closes, saving you from writing an unload handler and |
||||
* calling ignore(). |
||||
* @param win {nsIDOMWindow} your |window| |
||||
*/ |
||||
observeAuto: function(win, prefName, callback, thisObject) { |
||||
if (!win instanceof Ci.nsIDOMWindow) |
||||
throw "Need your |window| as first parameter"; |
||||
this.observe(prefName, callback, thisObject); |
||||
var self = this; |
||||
win.addEventListener("unload", function() |
||||
{ |
||||
self.ignore(prefName, callback, thisObject); |
||||
}, false); |
||||
win = null; // don't let closure hold on to window unnecessarily
|
||||
}, |
||||
|
||||
resetBranch: function(prefBranch) { |
||||
try { |
||||
this._prefSvc.resetBranch(prefBranch); |
||||
} |
||||
catch(ex) { |
||||
// The current implementation of nsIPrefBranch in Mozilla
|
||||
// doesn't implement resetBranch, so we do it ourselves.
|
||||
if (ex.result == Cr.NS_ERROR_NOT_IMPLEMENTED) |
||||
this.reset(this._prefSvc.getChildList(prefBranch, [])); |
||||
else |
||||
throw ex; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Returns all child prefs of this pref branch. |
||||
* This equals nsIPrefBranch.getChildList(). |
||||
* This allows you to do e.g. |
||||
* var myPrefs = new Preferences("extensions.cooler."); |
||||
* var contents = myPrefs.branch("contents."); |
||||
* for each (let prefname in contents.childPrefNames()) |
||||
* dump("have " + contents.get(prefname) + " " + prefname + "\n"); |
||||
* |
||||
* @returns {Array of String} The names of the children, |
||||
* without the base pref branch, but with subbranch. |
||||
*/ |
||||
childPrefNames : function() { |
||||
return this._prefSvc.getChildList("", []); |
||||
}, |
||||
|
||||
/** |
||||
* Returns an nsIPrefBranch for the pref branch that this object stands for. |
||||
* You can use this to use functions that are not supported here. |
||||
* @returns {nsIPrefBranch} |
||||
*/ |
||||
get mozillaPrefBranch() { |
||||
return this._prefSvc; |
||||
}, |
||||
|
||||
/** |
||||
* Returns the base pref name that this object stands for. |
||||
* E.g. "extensions.yourcooler."; |
||||
* @returns {String} |
||||
*/ |
||||
get prefBranchName() { |
||||
return this._prefBranch; |
||||
}, |
||||
|
||||
/** |
||||
* Returns an Preferences object for an sub pref branch |
||||
* underneath the current pref branch. |
||||
* @param subbranch {String} Will be appended to the |
||||
* current pref branch. Don't forget the trailing dot, |
||||
* where necessary. |
||||
* E.g. "contents." |
||||
* @returns {Preferences} |
||||
*/ |
||||
branch : function(subbranch) { |
||||
return new Preferences(this._prefBranch + subbranch); |
||||
}, |
||||
|
||||
/** |
||||
* The branch of the preferences tree to which this instance provides access. |
||||
* @private |
||||
*/ |
||||
_prefBranch: "", |
||||
|
||||
/** |
||||
* Preferences Service |
||||
* @private |
||||
*/ |
||||
get _prefSvc() { |
||||
// nsIPrefService
|
||||
let prefSvc = Services.prefs. |
||||
getBranch(this._prefBranch). |
||||
QueryInterface(Ci.nsIPrefBranch); |
||||
Object.defineProperty(this, "_prefSvc", { |
||||
get: function() { |
||||
return prefSvc; |
||||
} |
||||
}); |
||||
return this._prefSvc; |
||||
} |
||||
|
||||
}; |
||||
|
||||
// Give the constructor the same prototype as its instances, so users can access
|
||||
// preferences directly via the constructor without having to create an instance
|
||||
// first.
|
||||
Preferences.__proto__ = Preferences.prototype; |
||||
|
||||
/** |
||||
* A cache of pref observers. |
||||
* |
||||
* We use this to remove observers when a caller calls Preferences::ignore. |
||||
* |
||||
* All Preferences instances share this object, because we want callers to be |
||||
* able to remove an observer using a different Preferences object than the one |
||||
* with which they added it. That means we have to identify the observers |
||||
* in this object by their complete pref name, not just their name relative to |
||||
* the root branch of the Preferences object with which they were created. |
||||
*/ |
||||
let observers = []; |
||||
|
||||
function PrefObserver(prefName, callback, thisObject) { |
||||
this.prefName = prefName; |
||||
this.callback = callback; |
||||
this.thisObject = thisObject; |
||||
} |
||||
|
||||
PrefObserver.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), |
||||
|
||||
observe: function(subject, topic, data) { |
||||
// The pref service only observes whole branches, but we only observe
|
||||
// individual preferences, so we check here that the pref that changed
|
||||
// is the exact one we're observing (and not some sub-pref on the branch).
|
||||
if (data != this.prefName) |
||||
return; |
||||
|
||||
if (typeof this.callback == "function") { |
||||
let prefValue = Preferences.get(this.prefName); |
||||
|
||||
if (this.thisObject) |
||||
this.callback.call(this.thisObject, prefValue); |
||||
else |
||||
this.callback(prefValue); |
||||
} |
||||
else // typeof this.callback == "object" (nsIObserver)
|
||||
this.callback.observe(subject, topic, data); |
||||
} |
||||
}; |
||||
|
||||
function isArray(val) { |
||||
// We can't check for |val.constructor == Array| here, since the value
|
||||
// might be from a different context whose Array constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Array"); |
||||
} |
||||
|
||||
function isObject(val) { |
||||
// We can't check for |val.constructor == Object| here, since the value
|
||||
// might be from a different context whose Object constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" && |
||||
val.constructor.name == "Object"); |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* 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"; |
||||
|
||||
/** |
||||
* JS module implementation of nsIDOMJSWindow.setTimeout and clearTimeout. |
||||
*/ |
||||
|
||||
this.EXPORTED_SYMBOLS = ["setTimeout", "clearTimeout"]; |
||||
|
||||
const Cc = Components.classes; |
||||
const Ci = Components.interfaces; |
||||
const Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
// This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
|
||||
let gNextTimeoutId = 1; // setTimeout must return a positive integer
|
||||
|
||||
let gTimeoutTable = new Map(); // int -> nsITimer
|
||||
|
||||
this.setTimeout = function setTimeout(aCallback, aMilliseconds) { |
||||
let id = gNextTimeoutId++; |
||||
let args = Array.slice(arguments, 2); |
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
||||
timer.initWithCallback(function setTimeout_timer() { |
||||
gTimeoutTable.delete(id); |
||||
aCallback.apply(null, args); |
||||
}, aMilliseconds, timer.TYPE_ONE_SHOT); |
||||
|
||||
gTimeoutTable.set(id, timer); |
||||
return id; |
||||
} |
||||
|
||||
this.clearTimeout = function clearTimeout(aId) { |
||||
if (gTimeoutTable.has(aId)) { |
||||
gTimeoutTable.get(aId).cancel(); |
||||
gTimeoutTable.delete(aId); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
||||
|
||||
var EXPORTED_SYMBOLS = ["errorCritical"]; |
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
function errorCritical(e) |
||||
{ |
||||
Services.prompt.alert(null, "", e); |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIID7DCCAtSgAwIBAgIJAKXaTovgoTIUMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD |
||||
VQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdvcmsxEjAQBgNVBAoMCVB1cnBsZUky |
||||
UDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR0w |
||||
GwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmkycDAeFw0xODA4MjQyMTQ3NTJaFw0y |
||||
MzA4MjMyMTQ3NTJaMIGCMQswCQYDVQQGEwJXVzEUMBIGA1UECAwLSTJQIE5ldHdv |
||||
cmsxEjAQBgNVBAoMCVB1cnBsZUkyUDEqMCgGA1UEAwwhUHVycGxlSTJQIENlcnRp |
||||
ZmljYXRpb24gQXV0aG9yaXR5MR0wGwYJKoZIhvcNAQkBFg5yNHNhc0BtYWlsLmky |
||||
cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAZnN/U5bgkmiBqp/Np |
||||
yiMOkUPjr2tLhV78Oba46xDLA6AiQ7yTPg+/ZYPIfbF2dPBTpfgGdly2M1xymRKc |
||||
3Pa+IUXkLw6oCA+lFzOFW0Swtekk9HRAgGyHgj6/Hvagva5Wer4HJIO1qRsFPew+ |
||||
XcM3uhhiXoiO8o+YGpJ/7kz0gED3p2b9OVsLPd8G/GfdR3miD+Au+kUx/27z/WdJ |
||||
ISfFILFnYeYZGffrpRcFtoGwuZUCugwnbLtpQpNKuGq8jDidm1v6Rb85JmkoH3Sg |
||||
lRaX1MK0aPhM4WfCf7aWCNe669FAWPNB3Ya2lue7ewPLI84ZUEqcoJwmWn2ci2SU |
||||
EXUCAwEAAaNjMGEwHQYDVR0OBBYEFG3hwzikpXqMasw678OHM8uLyjEoMB8GA1Ud |
||||
IwQYMBaAFG3hwzikpXqMasw678OHM8uLyjEoMA8GA1UdEwQIMAYBAf8CAQAwDgYD |
||||
VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQA07URxJMI/Ta9y1wIg+k7o |
||||
1aHXsl6YOXmd2ymhKZhZHrZlutE2U19IQSoEV0SBddP9D05xD6Ovsrwo7caeYzNt |
||||
+2DJnlJ2IY61NqYUIDEoJyNPL/S7WleH+xO+bcSqWvbntTNYAD6WQVfHCAimVE6P |
||||
RnSZGqG089i84DRCyrh/6F1OxnBd6j14z+2ctQD+h6NlQXiCAUIwzVirYoE7oGpH |
||||
Xta7Ei+RDvBXLXLAQRdXpzSP/Ddf7MCJzmH3VYAy+0sVuHr09hpFMtC59hTrdLVD |
||||
/qma0eKrBr1DGH6QrZMZDqpNfv4wUPyVQBsRbbn2/1fL9IqK43CIj8RUllCOsmyU |
||||
-----END CERTIFICATE----- |
Loading…
Reference in new issue