The plugin starts to take form - and works.
This commit is contained in:
@ -1,5 +1,9 @@
|
||||
content i2pbutton chrome/content/
|
||||
overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/i2pbutton.xul
|
||||
overlay chrome://messenger/content/messenger.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
overlay about:addons chrome://i2pbutton/content/i2pbutton-extensions.xul
|
||||
overlay chrome://mozapps/content/extensions/extensions.xul chrome://i2pbutton/content/i2pbutton-extensions.xul
|
||||
resource i2pbutton ./
|
||||
resource i2pbutton-assets resource://i2pbutton/chrome/skin/ contentaccessible=yes
|
||||
|
||||
@ -8,16 +12,27 @@ override chrome://branding/locale/brand.dtd chrome://i2pbutton/locale/brand.dtd
|
||||
override chrome://branding/locale/brand.properties chrome://i2pbutton/locale/brand.properties
|
||||
overlay chrome://browser/content/aboutDialog.xul chrome://i2pbutton/content/aboutDialog.xul
|
||||
|
||||
skin torbutton classic/1.0 chrome/skin/
|
||||
# UI customization
|
||||
overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/menu-items-overlay.xul
|
||||
|
||||
# Strings for the about:ibupdate page
|
||||
override chrome://browser/locale/aboutIBUpdate.dtd chrome://i2pbutton/locale/aboutIBUpdate.dtd
|
||||
|
||||
locale i2pbutton en chrome/locale/en-US/
|
||||
|
||||
skin i2pbutton classic/1.0 chrome/skin/
|
||||
style chrome://global/content/customizeToolbar.xul chrome://i2pbutton/skin/i2pbutton.css
|
||||
|
||||
# Firefox 4-style component registration
|
||||
component {f605ec27-d867-44b5-ad97-2a29276642c3} components/dragDropFilter.js
|
||||
contract @geti2p.net/i2pbutton-dragDropFilter;1 {f605ec27-d867-44b5-ad97-2a29276642c3}
|
||||
|
||||
component {06322def-6fde-4c06-aef6-47ae8e799629} components/startup-observer.js
|
||||
contract @geti2p.net/startup-observer;1 {06322def-6fde-4c06-aef6-47ae8e799629}
|
||||
|
||||
component {f36d72c9-9718-4134-b550-e109638331d7} components/i2pbutton-logger.js
|
||||
contract @geti2p.net/i2pbutton-logger;1 {f36d72c9-9718-4134-b550-e109638331d7}
|
||||
|
||||
|
||||
category profile-after-change StartupObserver @geti2p.net/startup-observer;1
|
||||
category profile-after-change DragDropFilter @geti2p.net/i2pbutton-dragDropFilter;1
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
content i2pbutton jar:chrome/i2pbutton.jar!/content/
|
||||
overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/i2pbutton.xul
|
||||
overlay chrome://messenger/content/messenger.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
|
||||
locale i2pbutton en jar:chrome/i2pbutton.jar!/locale/en/
|
||||
|
||||
skin i2pbutton classic/1.0 jar:chrome/i2pbutton.jar!/skin/
|
||||
style chrome://global/content/customizeToolbar.xul chrome://i2pbutton/skin/i2pbutton.css
|
||||
|
@ -1,5 +1,9 @@
|
||||
content torbutton chrome/content/
|
||||
content i2pbutton chrome/content/
|
||||
overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/i2pbutton.xul
|
||||
overlay chrome://messenger/content/messenger.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
|
||||
locale i2pbutton en chrome/locale/en/
|
||||
|
||||
skin i2pbutton classic/1.0 chrome/skin/
|
||||
style chrome://global/content/customizeToolbar.xul chrome://i2pbutton/skin/i2pbutton.css
|
||||
|
@ -31,7 +31,7 @@ var AboutI2pListener = {
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (!this.isAboutTor)
|
||||
if (!this.isAboutI2p)
|
||||
return;
|
||||
|
||||
switch (aMessage.name) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
%htmlDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutTorDTD SYSTEM "chrome://i2pbutton/locale/aboutI2p.dtd">
|
||||
<!ENTITY % aboutI2pDTD SYSTEM "chrome://i2pbutton/locale/aboutI2p.dtd">
|
||||
%aboutI2pDTD;
|
||||
<!ENTITY % ibUpdateDTD SYSTEM "chrome://browser/locale/aboutIBUpdate.dtd">
|
||||
%ibUpdateDTD;
|
||||
@ -15,7 +15,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>&aboutTor.title;</title>
|
||||
<title>&aboutI2p.title;</title>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="resource://i2pbutton-assets/aboutI2p.css"/>
|
||||
<script type="text/javascript">
|
||||
@ -28,7 +28,9 @@ window.addEventListener("pageshow", function() {
|
||||
</script>
|
||||
</head>
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
<div>
|
||||
<b>It works!</b>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
28
src/chrome/content/i2pbutton-extensions.xul
Normal file
28
src/chrome/content/i2pbutton-extensions.xul
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://i2pbutton/locale/brand.dtd">
|
||||
|
||||
<overlay id="i2pbutton-extensions-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<vbox id="plugin-enable-button" class="alert-container" flex="1"
|
||||
hidden="true">
|
||||
<spacer class="alert-spacer-before"/>
|
||||
<vbox class="alert">
|
||||
<label value="&plugins.installed.find;"/>
|
||||
<button class="button-plugin-enable"
|
||||
label="&plugins.installed.enable;"
|
||||
command="cmd_pluginEnable"/>
|
||||
</vbox>
|
||||
<spacer class="alert-spacer-after"/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="plugin-disable-button" class="global-info" flex="1" align="end">
|
||||
<button class="button-plugin-disable"
|
||||
label="&plugins.installed.disable;"
|
||||
tooltiptext="&plugins.installed.disable.tip;"
|
||||
command="cmd_pluginDisable"/>
|
||||
<spacer flex="5000"/>
|
||||
</vbox>
|
||||
|
||||
</overlay>
|
618
src/chrome/content/i2pbutton.js
Normal file
618
src/chrome/content/i2pbutton.js
Normal file
@ -0,0 +1,618 @@
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm")
|
||||
|
||||
var m_ib_prefs = Services.prefs
|
||||
|
||||
// This function closes all XUL browser windows except this one. For this
|
||||
// window, it closes all existing tabs and creates one about:blank tab.
|
||||
function i2pbutton_close_tabs_on_new_identity() {
|
||||
if (!m_ib_prefs.getBoolPref("extensions.i2pbutton.close_newnym")) {
|
||||
i2pbutton_log(3, "Not closing tabs");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: muck around with browser.tabs.warnOnClose.. maybe..
|
||||
i2pbutton_log(3, "Closing tabs...");
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator);
|
||||
let enumerator = wm.getEnumerator("navigator:browser");
|
||||
let windowsToClose = new Array();
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let win = enumerator.getNext();
|
||||
let browser = win.getBrowser();
|
||||
if (!browser) {
|
||||
i2pbutton_log(5, "No browser for possible closed window");
|
||||
continue;
|
||||
}
|
||||
|
||||
let tabCount = browser.browsers.length;
|
||||
i2pbutton_log(3, "Tab count for window: " + tabCount);
|
||||
let tabsToRemove = new Array();
|
||||
for (let i = 0; i < tabCount; i++) {
|
||||
let tab = browser.getTabForBrowser(browser.browsers[i]);
|
||||
if (!tab) {
|
||||
i2pbutton_log(5, "No tab for browser");
|
||||
} else {
|
||||
tabsToRemove.push(tab);
|
||||
}
|
||||
}
|
||||
|
||||
if (win == window) {
|
||||
browser.addTab("about:blank");
|
||||
} else {
|
||||
// It is a bad idea to alter the window list while iterating
|
||||
// over it, so add this window to an array and close it later.
|
||||
windowsToClose.push(win);
|
||||
}
|
||||
|
||||
// Close each tab except the new blank one that we created.
|
||||
tabsToRemove.forEach(aTab => browser.removeTab(aTab));
|
||||
}
|
||||
|
||||
// Close all XUL windows except this one.
|
||||
i2pbutton_log(2, "Closing windows...");
|
||||
windowsToClose.forEach(aWin => aWin.close());
|
||||
|
||||
i2pbutton_log(3, "Closed all tabs");
|
||||
}
|
||||
|
||||
|
||||
function i2pbutton_new_identity() {
|
||||
try {
|
||||
// Make sure that we can only click once on New Identiy to avoid race
|
||||
// conditions leading to failures (see bug 11783 for an example).
|
||||
// TODO: Remove the i2pbutton menu entry again once we have done our
|
||||
// security control redesign.
|
||||
document.getElementById("i2pbutton-new-identity").disabled = true;
|
||||
document.getElementById("menu_newIdentity").disabled = true;
|
||||
document.getElementById("appMenuNewIdentity").disabled = true;
|
||||
|
||||
let shouldConfirm = m_ib_prefs.getBoolPref("extensions.i2pbutton.confirm_newnym");
|
||||
|
||||
if (shouldConfirm) {
|
||||
let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Ci.nsIPromptService);
|
||||
|
||||
// Display two buttons, both with string titles.
|
||||
let flags = prompts.STD_YES_NO_BUTTONS;
|
||||
|
||||
let message = i2pbutton_get_property_string("i2pbutton.popup.confirm_newnym");
|
||||
let askAgainText = i2pbutton_get_property_string("i2pbutton.popup.never_ask_again");
|
||||
let askAgain = {value: false};
|
||||
|
||||
let confirmed = (prompts.confirmEx(null, "", message, flags, null, null, null,
|
||||
askAgainText, askAgain) == 0);
|
||||
|
||||
m_ib_prefs.setBoolPref("extensions.i2pbutton.confirm_newnym", !askAgain.value);
|
||||
|
||||
if (confirmed) {
|
||||
i2pbutton_do_new_identity();
|
||||
} else {
|
||||
// TODO: Remove the i2pbutton menu entry again once we have done our
|
||||
// security control redesign.
|
||||
document.getElementById("i2pbutton-new-identity").disabled = false;
|
||||
document.getElementById("menu_newIdentity").disabled = false;
|
||||
document.getElementById("appMenuNewIdentity").disabled = false;
|
||||
}
|
||||
} else {
|
||||
i2pbutton_do_new_identity();
|
||||
}
|
||||
} catch(e) {
|
||||
// If something went wrong make sure we have the New Identity button
|
||||
// enabled (again).
|
||||
// TODO: Remove the i2pbutton menu entry again once we have done our
|
||||
// security control redesign.
|
||||
document.getElementById("i2pbutton-new-identity").disabled = false;
|
||||
document.getElementById("menu_newIdentity").disabled = false;
|
||||
document.getElementById("appMenuNewIdentity").disabled = false;
|
||||
i2pbutton_log(5, "Unexpected error on new identity: "+e);
|
||||
window.alert("i2pbutton: Unexpected error on new identity: "+e);
|
||||
}
|
||||
}
|
||||
|
||||
function i2pbutton_do_new_identity() {
|
||||
var obsSvc = Components.classes["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
i2pbutton_log(3, "New Identity: Disabling JS");
|
||||
i2pbutton_disable_all_js();
|
||||
|
||||
m_ib_prefs.setBoolPref("browser.zoom.siteSpecific",
|
||||
!m_ib_prefs.getBoolPref("browser.zoom.siteSpecific"));
|
||||
m_ib_prefs.setBoolPref("browser.zoom.siteSpecific",
|
||||
!m_ib_prefs.getBoolPref("browser.zoom.siteSpecific"));
|
||||
|
||||
try {
|
||||
if(m_ib_prefs.prefHasUserValue("geo.wifi.access_token")) {
|
||||
m_ib_prefs.clearUserPref("geo.wifi.access_token");
|
||||
}
|
||||
} catch(e) {
|
||||
i2pbutton_log(3, "Exception on wifi token clear: "+e);
|
||||
}
|
||||
|
||||
try {
|
||||
if(m_ib_prefs.prefHasUserValue("general.open_location.last_url")) {
|
||||
m_ib_prefs.clearUserPref("general.open_location.last_url");
|
||||
}
|
||||
} catch(e) {
|
||||
i2pbutton_log(3, "Exception on clearing last opened location: "+e);
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Closing tabs and clearing searchbox");
|
||||
|
||||
i2pbutton_close_tabs_on_new_identity();
|
||||
|
||||
// Bug #10800: Trying to clear search/find can cause exceptions
|
||||
// in unknown cases. Just log for now.
|
||||
try {
|
||||
var searchBar = window.document.getElementById("searchbar");
|
||||
if (searchBar)
|
||||
searchBar.textbox.reset();
|
||||
} catch(e) {
|
||||
i2pbutton_log(5, "New Identity: Exception on clearing search box: "+e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (gFindBarInitialized) {
|
||||
var findbox = gFindBar.getElement("findbar-textbox");
|
||||
findbox.reset();
|
||||
gFindBar.close();
|
||||
}
|
||||
} catch(e) {
|
||||
i2pbutton_log(5, "New Identity: Exception on clearing find bar: "+e);
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Emitting Private Browsing Session clear event");
|
||||
obsSvc.notifyObservers(null, "browser:purge-session-history", "");
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing HTTP Auth");
|
||||
|
||||
if(m_ib_prefs.getBoolPref('extensions.i2pbutton.clear_http_auth')) {
|
||||
var auth = Components.classes["@mozilla.org/network/http-auth-manager;1"].
|
||||
getService(Components.interfaces.nsIHttpAuthManager);
|
||||
auth.clearAll();
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Crypto Tokens");
|
||||
|
||||
// Clear all crypto auth tokens. This includes calls to PK11_LogoutAll(),
|
||||
// nsNSSComponent::LogoutAuthenticatedPK11() and clearing the SSL session
|
||||
// cache.
|
||||
let sdr = Components.classes["@mozilla.org/security/sdr;1"].
|
||||
getService(Components.interfaces.nsISecretDecoderRing);
|
||||
sdr.logoutAndTeardown();
|
||||
|
||||
// This clears the OCSP cache.
|
||||
//
|
||||
// nsNSSComponent::Observe() watches security.OCSP.enabled, which calls
|
||||
// setValidationOptions(), which in turn calls setNonPkixOcspEnabled() which,
|
||||
// if security.OCSP.enabled is set to 0, calls CERT_DisableOCSPChecking(),
|
||||
// which calls CERT_ClearOCSPCache().
|
||||
// See: https://mxr.mozilla.org/comm-esr24/source/mozilla/security/manager/ssl/src/nsNSSComponent.cpp
|
||||
var ocsp = m_ib_prefs.getIntPref("security.OCSP.enabled");
|
||||
m_ib_prefs.setIntPref("security.OCSP.enabled", 0);
|
||||
m_ib_prefs.setIntPref("security.OCSP.enabled", ocsp);
|
||||
|
||||
// This clears the site permissions on I2P Browser
|
||||
// XXX: Tie to some kind of disk-ok pref?
|
||||
try {
|
||||
Services.perms.removeAll();
|
||||
} catch(e) {
|
||||
// Actually, this catch does not appear to be needed. Leaving it in for
|
||||
// safety though.
|
||||
i2pbutton_log(3, "Can't clear permissions: Not I2P Browser: "+e);
|
||||
}
|
||||
|
||||
// Clear site security settings
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].
|
||||
getService(Ci.nsISiteSecurityService);
|
||||
sss.clearAll();
|
||||
|
||||
// This clears the undo tab history.
|
||||
var tabs = m_ib_prefs.getIntPref("browser.sessionstore.max_tabs_undo");
|
||||
m_ib_prefs.setIntPref("browser.sessionstore.max_tabs_undo", 0);
|
||||
m_ib_prefs.setIntPref("browser.sessionstore.max_tabs_undo", tabs);
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Image Cache");
|
||||
i2pbutton_clear_image_caches();
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Offline Cache");
|
||||
|
||||
try {
|
||||
const LoadContextInfo = Cc["@mozilla.org/load-context-info-factory;1"]
|
||||
.getService(Ci.nsILoadContextInfoFactory);
|
||||
|
||||
for (let contextInfo of [LoadContextInfo.default, LoadContextInfo.private]) {
|
||||
let appCacheStorage = Services.cache2.appCacheStorage(contextInfo, null);
|
||||
// The following call (asyncEvictStorage) is actually synchronous, either
|
||||
// if we have pref "browser.cache.use_new_backend" -> 1 or
|
||||
// "browser.cache.use_new_backend_temp" -> true,
|
||||
// then we are using the new cache (cache2) which operates synchronously.
|
||||
// If we are using the old cache, then the tor-browser.git patch for
|
||||
// #5715 also makes this synchronous. So we pass a null callback.
|
||||
try {
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch (err) {
|
||||
// We ignore "not available" errors because they occur if a cache
|
||||
// has not been used, e.g., if no browsing has been done.
|
||||
if (err.name !== 'NS_ERROR_NOT_AVAILABLE') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
i2pbutton_log(5, "Exception on cache clearing: "+e);
|
||||
window.alert("i2pbutton: Unexpected error during offline cache clearing: "+e);
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Disk and Memory Caches");
|
||||
|
||||
try {
|
||||
Services.cache2.clear();
|
||||
} catch(e) {
|
||||
i2pbutton_log(5, "Exception on cache clearing: "+e);
|
||||
window.alert("i2pbutton: Unexpected error during cache clearing: "+e);
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing storage");
|
||||
|
||||
let orig_quota_test = m_ib_prefs.getBoolPref("dom.quotaManager.testing");
|
||||
try {
|
||||
// This works only by setting the pref to `true` otherwise we get an
|
||||
// exception and nothing is happening.
|
||||
m_ib_prefs.setBoolPref("dom.quotaManager.testing", true);
|
||||
Cc["@mozilla.org/dom/quota-manager-service;1"]
|
||||
.getService(Ci.nsIQuotaManagerService).clear();
|
||||
} catch(e) {
|
||||
i2pbutton_log(5, "Exception on storage clearing: "+e);
|
||||
} finally {
|
||||
m_ib_prefs.setBoolPref("dom.quotaManager.testing", orig_quota_test);
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Cookies and DOM Storage");
|
||||
|
||||
if (m_ib_prefs.getBoolPref('extensions.i2pbutton.cookie_protections')) {
|
||||
var selector = Components.classes["@geti2p.net/cookie-jar-selector;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
// This emits "cookie-changed", "cleared", which kills DOM storage
|
||||
// and the safe browsing API key
|
||||
selector.clearUnprotectedCookies("i2p");
|
||||
} else {
|
||||
i2pbutton_clear_cookies();
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Closing open connections");
|
||||
|
||||
// Clear keep-alive
|
||||
obsSvc.notifyObservers(this, "net:prune-all-connections", null);
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing Content Preferences");
|
||||
|
||||
// XXX: This may not clear zoom site-specific
|
||||
// browser.content.full-zoom
|
||||
if (Ci.nsIContentPrefService2) { // Firefox >= 20
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
var pbCtxt = PrivateBrowsingUtils.privacyContextFromWindow(window);
|
||||
var cps = Cc["@mozilla.org/content-pref/service;1"]
|
||||
.getService(Ci.nsIContentPrefService2);
|
||||
cps.removeAllDomains(pbCtxt);
|
||||
} else { // Firefox < 20
|
||||
var cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
cps.removeGroupedPrefs();
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "New Identity: Syncing prefs");
|
||||
|
||||
// Force prefs to be synced to disk
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
i2pbutton_log(3, "New Identity: Clearing permissions");
|
||||
|
||||
let pm = Cc["@mozilla.org/permissionmanager;1"].
|
||||
getService(Ci.nsIPermissionManager);
|
||||
pm.removeAll();
|
||||
|
||||
i2pbutton_log(3, "New Identity: Sending NEWNYM");
|
||||
|
||||
// We only support TBB for newnym.
|
||||
if (!m_tb_control_pass || (!m_tb_control_ipc_file && !m_tb_control_port)) {
|
||||
var warning = i2pbutton_get_property_string("i2pbutton.popup.no_newnym");
|
||||
i2pbutton_log(5, "i2pbutton cannot safely newnym. It does not have access to the I2P Control Port.");
|
||||
window.alert(warning);
|
||||
} else {
|
||||
if (!i2pbutton_send_ctrl_cmd("SIGNAL NEWNYM\r\n")) {
|
||||
var warning = i2pbutton_get_property_string("i2pbutton.popup.no_newnym");
|
||||
i2pbutton_log(5, "i2pbutton was unable to request a new tunnel from I2P");
|
||||
window.alert(warning);
|
||||
}
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "Ending any remaining private browsing sessions.");
|
||||
obsSvc.notifyObservers(null, "last-pb-context-exited", "");
|
||||
|
||||
i2pbutton_log(3, "New Identity: Opening a new browser window");
|
||||
|
||||
// Open a new window with the TBB check homepage
|
||||
// In Firefox >=19, can pass {private: true} but we do not need it because
|
||||
// we have browser.privatebrowsing.autostart = true
|
||||
OpenBrowserWindow();
|
||||
|
||||
i2pbutton_log(3, "New identity successful");
|
||||
|
||||
// Run garbage collection and cycle collection after window is gone.
|
||||
// This ensures that blob URIs are forgotten.
|
||||
window.addEventListener("unload", function (event) {
|
||||
i2pbutton_log(3, "Initiating New Identity GC pass");
|
||||
// Clear out potential pending sInterSliceGCTimer:
|
||||
m_tb_domWindowUtils.runNextCollectorTimer();
|
||||
|
||||
// Clear out potential pending sICCTimer:
|
||||
m_tb_domWindowUtils.runNextCollectorTimer();
|
||||
|
||||
// Schedule a garbage collection in 4000-1000ms...
|
||||
m_tb_domWindowUtils.garbageCollect();
|
||||
|
||||
// To ensure the GC runs immediately instead of 4-10s from now, we need
|
||||
// to poke it at least 11 times.
|
||||
// We need 5 pokes for GC, 1 poke for the interSliceGC, and 5 pokes for CC.
|
||||
// See nsJSContext::RunNextCollectorTimer() in
|
||||
// https://mxr.mozilla.org/mozilla-central/source/dom/base/nsJSEnvironment.cpp#1970.
|
||||
// XXX: We might want to make our own method for immediate full GC...
|
||||
for (let poke = 0; poke < 11; poke++) {
|
||||
m_tb_domWindowUtils.runNextCollectorTimer();
|
||||
}
|
||||
|
||||
// And now, since the GC probably actually ran *after* the CC last time,
|
||||
// run the whole thing again.
|
||||
m_tb_domWindowUtils.garbageCollect();
|
||||
for (let poke = 0; poke < 11; poke++) {
|
||||
m_tb_domWindowUtils.runNextCollectorTimer();
|
||||
}
|
||||
|
||||
i2pbutton_log(3, "Completed New Identity GC pass");
|
||||
});
|
||||
|
||||
// Close the current window for added safety
|
||||
window.close();
|
||||
}
|
||||
|
||||
function i2pbutton_clear_image_caches()
|
||||
{
|
||||
try {
|
||||
let imgCache;
|
||||
let imgTools = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools);
|
||||
if (!("getImgCacheForDocument" in imgTools)) {
|
||||
// In Firefox 17 and older, there is one global image cache. Clear it.
|
||||
imgCache = Cc["@mozilla.org/image/cache;1"].getService(Ci.imgICache);
|
||||
imgCache.clearCache(false); // evict all but chrome cache
|
||||
} else {
|
||||
// In Firefox 18 and newer, there are two image caches: one that is
|
||||
// used for regular browsing and one that is used for private browsing.
|
||||
|
||||
// Clear the non-private browsing image cache.
|
||||
imgCache = imgTools.getImgCacheForDocument(null);
|
||||
imgCache.clearCache(false); // evict all but chrome cache
|
||||
|
||||
// Try to clear the private browsing cache. To do so, we must locate
|
||||
// a content document that is contained within a private browsing window.
|
||||
let didClearPBCache = false;
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator);
|
||||
let enumerator = wm.getEnumerator("navigator:browser");
|
||||
while (!didClearPBCache && enumerator.hasMoreElements()) {
|
||||
let win = enumerator.getNext();
|
||||
let browserDoc = win.document.documentElement;
|
||||
if (!browserDoc.hasAttribute("privatebrowsingmode"))
|
||||
continue;
|
||||
|
||||
let tabbrowser = win.getBrowser();
|
||||
if (!tabbrowser)
|
||||
continue;
|
||||
|
||||
var tabCount = tabbrowser.browsers.length;
|
||||
for (var i = 0; i < tabCount; i++) {
|
||||
let doc = tabbrowser.browsers[i].contentDocument;
|
||||
if (doc) {
|
||||
imgCache = imgTools.getImgCacheForDocument(doc);
|
||||
imgCache.clearCache(false); // evict all but chrome cache
|
||||
didClearPBCache = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
// FIXME: This can happen in some rare cases involving XULish image data
|
||||
// in combination with our image cache isolation patch. Sure isn't
|
||||
// a good thing, but it's not really a super-cookie vector either.
|
||||
// We should fix it eventually.
|
||||
i2pbutton_log(4, "Exception on image cache clearing: "+e);
|
||||
}
|
||||
}
|
||||
|
||||
function i2pbutton_toggle_plugins(disable_plugins) {
|
||||
if (m_tb_tbb) {
|
||||
var PH=Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
var P=PH.getPluginTags({});
|
||||
for(var i=0; i<P.length; i++) {
|
||||
if ("enabledState" in P[i]) { // FF24
|
||||
// FIXME: DOCDOC the reasoning for the isDisabled check, or remove it.
|
||||
var isDisabled = (P[i].enabledState == Ci.nsIPluginTag.STATE_DISABLED);
|
||||
if (!isDisabled && disable_plugins)
|
||||
P[i].enabledState = Ci.nsIPluginTag.STATE_DISABLED;
|
||||
else if (isDisabled && !disable_plugins)
|
||||
P[i].enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
||||
} else if (P[i].disabled != disable_plugins) { // FF17
|
||||
P[i].disabled=disable_plugins;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function i2pbutton_update_disk_prefs() {
|
||||
var mode = m_ib_prefs.getBoolPref("browser.privatebrowsing.autostart");
|
||||
|
||||
m_ib_prefs.setBoolPref("browser.cache.disk.enable", !mode);
|
||||
m_ib_prefs.setBoolPref("places.history.enabled", !mode);
|
||||
|
||||
m_ib_prefs.setBoolPref("security.nocertdb", mode);
|
||||
|
||||
// No way to clear this beast during New Identity. Leave it off.
|
||||
//m_ib_prefs.setBoolPref("dom.indexedDB.enabled", !mode);
|
||||
|
||||
if (m_tb_tbb) m_ib_prefs.setBoolPref("permissions.memory_only", mode);
|
||||
|
||||
// Third party abuse. Leave it off for now.
|
||||
//m_ib_prefs.setBoolPref("browser.cache.offline.enable", !mode);
|
||||
|
||||
if (mode) {
|
||||
m_ib_prefs.setIntPref("network.cookie.lifetimePolicy", 2);
|
||||
m_ib_prefs.setIntPref("browser.download.manager.retention", 1);
|
||||
} else {
|
||||
m_ib_prefs.setIntPref("network.cookie.lifetimePolicy", 0);
|
||||
m_ib_prefs.setIntPref("browser.download.manager.retention", 2);
|
||||
}
|
||||
|
||||
// Force prefs to be synced to disk
|
||||
Services.prefs.savePrefFile(null);
|
||||
}
|
||||
|
||||
function i2pbutton_update_fingerprinting_prefs() {
|
||||
var mode = m_ib_prefs.getBoolPref("privacy.resistFingerprinting");
|
||||
|
||||
m_ib_prefs.setBoolPref("webgl.disable-extensions", mode);
|
||||
m_ib_prefs.setBoolPref("dom.network.enabled", !mode);
|
||||
m_ib_prefs.setBoolPref("dom.enable_performance", !mode);
|
||||
m_ib_prefs.setBoolPref("plugin.expose_full_path", !mode);
|
||||
m_ib_prefs.setBoolPref("browser.zoom.siteSpecific", !mode);
|
||||
|
||||
m_ib_prefs.setBoolPref("extensions.i2pbutton.resize_new_windows", mode);
|
||||
|
||||
// Force prefs to be synced to disk
|
||||
Services.prefs.savePrefFile(null);
|
||||
}
|
||||
|
||||
function i2pbutton_do_startup()
|
||||
{
|
||||
if(m_ib_prefs.getBoolPref("extensions.i2pbutton.startup")) {
|
||||
// Bug 1506: Still want to do this
|
||||
i2pbutton_toggle_plugins(
|
||||
m_ib_prefs.getBoolPref("plugin.disable"));
|
||||
|
||||
// Bug 1506: Should probably be moved to an XPCOM component
|
||||
i2pbutton_do_main_window_startup();
|
||||
|
||||
// For charsets
|
||||
i2pbutton_update_fingerprinting_prefs();
|
||||
|
||||
// Bug 30565: sync browser.privatebrowsing.autostart with security.nocertdb
|
||||
i2pbutton_update_disk_prefs();
|
||||
|
||||
// #5758: Last ditch effort to keep Vanilla i2pbutton users from totally
|
||||
// being pwnt. This is a pretty darn ugly hack, too. But because of #5863,
|
||||
// we really don't care about preserving the user's values for this.
|
||||
if (!m_tb_tbb) {
|
||||
// Bug 1506 P5: You have to set these two for non-TBB Firefoxen
|
||||
m_ib_prefs.setBoolPref("network.websocket.enabled", false);
|
||||
m_ib_prefs.setBoolPref("dom.indexedDB.enabled", false);
|
||||
}
|
||||
|
||||
// Still need this in case people shove this thing back into FF
|
||||
if (!m_tb_tbb && m_ib_prefs.getBoolPref("extensions.i2pbutton.prompt_torbrowser")) {
|
||||
var warning = i2pbutton_get_property_string("i2pbutton.popup.short_torbrowser");
|
||||
var title = i2pbutton_get_property_string("i2pbutton.title.prompt_torbrowser");
|
||||
var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
|
||||
prompts.alert(null, title, warning);
|
||||
}
|
||||
|
||||
// For general pref fixups to handle pref damage in older versions
|
||||
i2pbutton_fixup_old_prefs();
|
||||
|
||||
m_ib_prefs.setBoolPref("extensions.i2pbutton.startup", false);
|
||||
}
|
||||
}
|
||||
|
||||
// Bug 1506 P3: This is needed pretty much only for the version check
|
||||
// and the window resizing. See comments for individual functions for
|
||||
// details
|
||||
function i2pbutton_new_window(event)
|
||||
{
|
||||
i2pbutton_log(3, "New window");
|
||||
var browser = window.gBrowser;
|
||||
|
||||
if(!browser) {
|
||||
i2pbutton_log(5, "No browser for new window.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_tb_window_height = window.outerHeight;
|
||||
m_tb_window_width = window.outerWidth;
|
||||
|
||||
if (!m_tb_wasinited) {
|
||||
i2pbutton_init();
|
||||
}
|
||||
// Add tab open listener..
|
||||
browser.tabContainer.addEventListener("TabOpen", i2pbutton_new_tab, false);
|
||||
|
||||
i2pbutton_do_startup();
|
||||
|
||||
let progress = Cc["@mozilla.org/docloaderservice;1"]
|
||||
.getService(Ci.nsIWebProgress);
|
||||
|
||||
if (m_ib_prefs.getBoolPref("extensions.i2pbutton.resize_new_windows")
|
||||
&& i2pbutton_is_windowed(window)) {
|
||||
progress.addProgressListener(i2pbutton_resizelistener,
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
}
|
||||
|
||||
// Check the version on every new window. We're already pinging check in these cases.
|
||||
i2pbutton_do_async_versioncheck();
|
||||
|
||||
}
|
||||
|
||||
// Bug 1506 P2: This is only needed because we have observers
|
||||
// in XUL that should be in an XPCOM component
|
||||
function i2pbutton_close_window(event) {
|
||||
i2pbutton_window_pref_observer.unregister();
|
||||
i2pbutton_tor_check_observer.unregister();
|
||||
|
||||
window.removeEventListener("sizemodechange", m_tb_resize_handler,
|
||||
false);
|
||||
|
||||
// TODO: This is a real ghetto hack.. When the original window
|
||||
// closes, we need to find another window to handle observing
|
||||
// unique events... The right way to do this is to move the
|
||||
// majority of i2pbutton functionality into a XPCOM component..
|
||||
// But that is a major overhaul..
|
||||
if (m_tb_is_main_window) {
|
||||
i2pbutton_log(3, "Original window closed. Searching for another");
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var enumerator = wm.getEnumerator("navigator:browser");
|
||||
while(enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
// For some reason, when New Identity is called from a pref
|
||||
// observer (ex: i2pbutton_use_nontor_proxy) on an ASAN build,
|
||||
// we sometimes don't have this symbol set in the new window yet.
|
||||
// However, the new window will run this init later in that case,
|
||||
// as it does in the OSX case.
|
||||
if(win != window && "i2pbutton_do_main_window_startup" in win) {
|
||||
i2pbutton_log(3, "Found another window");
|
||||
win.i2pbutton_do_main_window_startup();
|
||||
m_tb_is_main_window = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i2pbutton_unique_pref_observer.unregister();
|
||||
|
||||
if(m_tb_is_main_window) { // main window not reset above
|
||||
// This happens on Mac OS because they allow firefox
|
||||
// to still persist without a navigator window
|
||||
i2pbutton_log(3, "Last window closed. None remain.");
|
||||
m_ib_prefs.setBoolPref("extensions.i2pbutton.startup", true);
|
||||
m_tb_is_main_window = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://i2pbutton/skin/torbutton.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://i2pbutton/skin/torbutton.css" type="text/css"?>
|
||||
<?xul-overlay href="chrome://i2pbutton/content/popup.xul"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://i2pbutton/locale/i2pbutton.dtd">
|
||||
@ -8,7 +8,6 @@
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/x-javascript" src="chrome://i2pbutton/content/i2pbutton_util.js" />
|
||||
<script type="application/x-javascript" src="chrome://i2pbutton/content/content-sizer.js" />
|
||||
<script type="application/x-javascript" src="chrome://i2pbutton/content/i2pbutton.js" />
|
||||
<script language="JavaScript">
|
||||
//onLoad Hander
|
||||
@ -26,7 +25,7 @@
|
||||
</toolbar>
|
||||
|
||||
<toolbarpalette id="BrowserToolbarPalette">
|
||||
<toolbarbutton
|
||||
<toolbarbutton
|
||||
id="i2pbutton-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
type="menu"
|
||||
|
38
src/chrome/content/i2pbutton_tb.xul
Normal file
38
src/chrome/content/i2pbutton_tb.xul
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://i2pbutton/skin/i2pbutton.css" type="text/css"?>
|
||||
<?xul-overlay href="chrome://i2pbutton/content/popup.xul"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://i2pbutton/locale/i2pbutton.dtd">
|
||||
|
||||
<overlay id="i2pbutton-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/x-javascript" src="chrome://i2pbutton/content/i2pbutton_util.js" />
|
||||
<script type="application/x-javascript" src="chrome://i2pbutton/content/i2pbutton.js" />
|
||||
<script language="JavaScript">
|
||||
//onLoad Hander
|
||||
try{window.addEventListener("load", i2pbutton_init, false);}catch(e){}
|
||||
</script>
|
||||
|
||||
<stringbundleset id="i2pbutton-stringbundleset">
|
||||
<stringbundle id="i2pbutton-bundle" src="chrome://i2pbutton/locale/i2pbutton.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<toolbarpalette id="MailToolbarPalette">
|
||||
<toolbarbutton
|
||||
id="i2pbutton-button-tb"
|
||||
class="toolbarbutton-1"
|
||||
label="i2pbutton"
|
||||
tooltiptext="&i2pbutton.button.tooltip;"
|
||||
context="i2pbutton-context-menu" />
|
||||
</toolbarpalette>
|
||||
|
||||
<toolbarpalette id="MsgComposeToolbarPalette">
|
||||
<toolbarbutton
|
||||
id="i2pbutton-button-tb-msg"
|
||||
class="toolbarbutton-1"
|
||||
label="i2pbutton"
|
||||
tooltiptext="&i2pbutton.button.tooltip;"
|
||||
context="i2pbutton-context-menu" />
|
||||
</toolbarpalette>
|
||||
|
||||
</overlay>
|
21
src/chrome/content/menu-items-overlay.xul
Normal file
21
src/chrome/content/menu-items-overlay.xul
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- Mode: HTML -*- -->
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://i2pbutton/locale/i2pbutton.dtd">
|
||||
|
||||
<overlay id="i2pbutton-menu-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<menuitem id="menu_newIdentity"
|
||||
accesskey="&i2pbutton.context_menu.new_identity_key;"
|
||||
key="i2pbutton-new-identity-key"
|
||||
label="&i2pbutton.context_menu.new_identity;"
|
||||
oncommand="i2pbutton_new_identity();"/>
|
||||
<toolbarbutton id="appMenuNewIdentity"
|
||||
class="subviewbutton subviewbutton-iconic"
|
||||
key="i2pbutton-new-identity-key"
|
||||
label="&i2pbutton.context_menu.new_identity;"
|
||||
oncommand="i2pbutton_new_identity();"/>
|
||||
<toolbarbutton id="appMenu-private-window-button"
|
||||
hidden="true"/>
|
||||
<toolbarbutton id="appMenuRestoreLastSession"
|
||||
hidden="true"/>
|
||||
</overlay>
|
@ -27,10 +27,6 @@
|
||||
insertafter="context-stop"
|
||||
hidden="true"
|
||||
oncommand="i2pbutton_open_cookie_dialog()"/>
|
||||
<menuitem id="i2pbutton-networksettings"
|
||||
label="&i2pbutton.context_menu.networksettings;"
|
||||
accesskey="&i2pbutton.context_menu.networksettings.key;"
|
||||
oncommand="i2pbutton_open_network_settings()"/>
|
||||
<menuseparator id="i2pbutton-checkForUpdateSeparator"/>
|
||||
<menuitem id="i2pbutton-checkForUpdate"
|
||||
label="&i2pbutton.context_menu.downloadUpdate;"
|
||||
|
8
src/chrome/content/pref-connection.xul
Normal file
8
src/chrome/content/pref-connection.xul
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://i2pbutton/locale/i2pbutton.dtd">
|
||||
|
||||
<overlay id="i2pbutton-prefs-notice"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
</overlay>
|
12
src/chrome/locale/en-US/aboutDialog.dtd
Normal file
12
src/chrome/locale/en-US/aboutDialog.dtd
Normal file
@ -0,0 +1,12 @@
|
||||
<!ENTITY project.start "&brandShortName; is developed by ">
|
||||
<!ENTITY project.tpoLink "the &vendorShortName;">
|
||||
<!ENTITY project.end ", a nonprofit working to defend your privacy and freedom online.">
|
||||
<!ENTITY help.start "Want to help? ">
|
||||
<!ENTITY help.donateLink "Donate">
|
||||
<!ENTITY help.or " or ">
|
||||
<!ENTITY help.getInvolvedLink "get involved">
|
||||
<!ENTITY help.end "!">
|
||||
<!ENTITY bottomLinks.questions "Questions?">
|
||||
<!ENTITY bottomLinks.grow "Help the I2P Network Grow!">
|
||||
<!ENTITY bottomLinks.license "Licensing Information">
|
||||
<!ENTITY tor.TrademarkStatement "'I2P' are registered trademarks of the I2P Project.">
|
8
src/chrome/locale/en-US/aboutIBUpdate.dtd
Normal file
8
src/chrome/locale/en-US/aboutIBUpdate.dtd
Normal file
@ -0,0 +1,8 @@
|
||||
<!ENTITY aboutTBUpdate.changelogTitle "I2P Browser Changelog">
|
||||
<!ENTITY aboutTBUpdate.updated "I2P Browser has been updated.">
|
||||
<!ENTITY aboutTBUpdate.linkPrefix "For the most up-to-date information about this release, ">
|
||||
<!ENTITY aboutTBUpdate.linkLabel "visit our website">
|
||||
<!ENTITY aboutTBUpdate.linkSuffix ".">
|
||||
<!ENTITY aboutTBUpdate.version "Version">
|
||||
<!ENTITY aboutTBUpdate.releaseDate "Release Date">
|
||||
<!ENTITY aboutTBUpdate.releaseNotes "Release Notes">
|
41
src/chrome/locale/en-US/i2pbutton.dtd
Normal file
41
src/chrome/locale/en-US/i2pbutton.dtd
Normal file
@ -0,0 +1,41 @@
|
||||
<!ENTITY i2pbutton.context_menu.new_identity "New Identity">
|
||||
<!ENTITY i2pbutton.context_menu.new_identity_key "I">
|
||||
<!ENTITY i2pbutton.context_menu.new_circuit "New Tor Circuit for this Site">
|
||||
<!ENTITY i2pbutton.context_menu.new_circuit_key "C">
|
||||
<!ENTITY i2pbutton.context_menu.networksettings "Tor Network Settings…">
|
||||
<!ENTITY i2pbutton.context_menu.networksettings.key "N">
|
||||
<!ENTITY i2pbutton.context_menu.downloadUpdate "Check for I2P Browser Update…">
|
||||
<!ENTITY i2pbutton.context_menu.downloadUpdate.key "U">
|
||||
<!ENTITY i2pbutton.context_menu.cookieProtections "Cookie Protections…">
|
||||
<!ENTITY i2pbutton.context_menu.cookieProtections.key "C">
|
||||
<!ENTITY i2pbutton.button.tooltip "Click to initialize i2pbutton">
|
||||
<!ENTITY i2pbutton.prefs.security_settings "I2P Browser Security Settings">
|
||||
<!ENTITY i2pbutton.cookiedialog.title "Manage Cookie Protections">
|
||||
<!ENTITY i2pbutton.cookiedialog.lockCol "Protected">
|
||||
<!ENTITY i2pbutton.cookiedialog.domainCol "Host">
|
||||
<!ENTITY i2pbutton.cookiedialog.nameCol "Name">
|
||||
<!ENTITY i2pbutton.cookiedialog.pathCol "Path">
|
||||
<!ENTITY i2pbutton.cookiedialog.protectCookie "Protect Cookie">
|
||||
<!ENTITY i2pbutton.cookiedialog.removeCookie "Remove Cookie">
|
||||
<!ENTITY i2pbutton.cookiedialog.unprotectCookie "Unprotect Cookie">
|
||||
<!ENTITY i2pbutton.cookiedialog.removeAllBut "Remove All But Protected">
|
||||
<!ENTITY i2pbutton.cookiedialog.saveAllCookies "Protect New Cookies">
|
||||
<!ENTITY i2pbutton.cookiedialog.doNotSaveAllCookies "Do Not Protect New Cookies">
|
||||
<!ENTITY i2pbutton.prefs.sec_caption "Security Level">
|
||||
<!ENTITY i2pbutton.prefs.sec_caption_tooltip "The Security Slider lets you disable certain browser features that may make your browser more vulnerable to hacking attempts.">
|
||||
<!ENTITY i2pbutton.prefs.sec_standard_label "Standard">
|
||||
<!ENTITY i2pbutton.prefs.sec_standard_description "All I2P Browser and website features are enabled.">
|
||||
<!ENTITY i2pbutton.prefs.sec_safer_label "Safer">
|
||||
<!ENTITY i2pbutton.prefs.sec_safer_description "Disables website features that are often dangerous, causing some sites to lose functionality.">
|
||||
<!ENTITY i2pbutton.prefs.sec_safer_list_label "At the safer setting:">
|
||||
<!ENTITY i2pbutton.prefs.sec_safest_label "Safest">
|
||||
<!ENTITY i2pbutton.prefs.sec_safest_description "Only allows website features required for static sites and basic services. These changes affect images, media, and scripts.">
|
||||
<!ENTITY i2pbutton.prefs.sec_safest_list_label "At the safest setting:">
|
||||
<!ENTITY i2pbutton.prefs.sec_learn_more_label "Learn more">
|
||||
<!ENTITY i2pbutton.prefs.sec_js_on_https_sites_only "JavaScript is disabled on non-HTTPS sites.">
|
||||
<!ENTITY i2pbutton.prefs.sec_js_disabled "JavaScript is disabled by default on all sites.">
|
||||
<!ENTITY i2pbutton.prefs.sec_limit_typography "Some fonts and math symbols are disabled.">
|
||||
<!ENTITY i2pbutton.prefs.sec_limit_graphics_and_typography "Some fonts, icons, math symbols, and images are disabled.">
|
||||
<!ENTITY i2pbutton.prefs.sec_click_to_play_media "Audio and video (HTML5 media), and WebGL are click-to-play.">
|
||||
<!ENTITY i2pbutton.circuit_display.title "Tor Circuit">
|
||||
<!ENTITY i2pbutton.circuit_display.new_circuit "New Circuit for this Site">
|
60
src/chrome/locale/en-US/i2pbutton.properties
Normal file
60
src/chrome/locale/en-US/i2pbutton.properties
Normal file
@ -0,0 +1,60 @@
|
||||
i2pbutton.circuit_display.internet = Internet
|
||||
i2pbutton.circuit_display.ip_unknown = IP unknown
|
||||
i2pbutton.circuit_display.onion_site = Onion site
|
||||
i2pbutton.circuit_display.this_browser = This browser
|
||||
i2pbutton.circuit_display.relay = Relay
|
||||
i2pbutton.circuit_display.tor_bridge = Bridge
|
||||
i2pbutton.circuit_display.unknown_country = Unknown country
|
||||
i2pbutton.circuit_display.guard = Guard
|
||||
i2pbutton.circuit_display.guard_note = Your [Guard] node may not change.
|
||||
i2pbutton.circuit_display.learn_more = Learn more
|
||||
i2pbutton.content_sizer.margin_tooltip = I2P Browser adds this margin to make the width and height of your window less distinctive, and thus reduces the ability of people to track you online.
|
||||
i2pbutton.panel.tooltip.disabled = Click to enable I2P
|
||||
i2pbutton.panel.tooltip.enabled = Click to disable I2P
|
||||
i2pbutton.panel.label.disabled = I2P Disabled
|
||||
i2pbutton.panel.label.enabled = I2P Enabled
|
||||
extensions.i2pbutton@geti2p.net.description = i2pbutton provides a button to configure I2P settings and quickly and easily clear private browsing data.
|
||||
i2pbutton.popup.external.title = Download an external file type?
|
||||
i2pbutton.popup.external.app = Tor Browser cannot display this file. You will need to open it with another application.\n\n
|
||||
i2pbutton.popup.external.note = Some types of files can cause applications to connect to the Internet without using I2P.\n\n
|
||||
i2pbutton.popup.external.suggest = To be safe, you should only open downloaded files while offline, or use a I2P Live CD such as Tails.\n
|
||||
i2pbutton.popup.launch = Download file
|
||||
i2pbutton.popup.cancel = Cancel
|
||||
i2pbutton.popup.dontask = Automatically download files from now on
|
||||
i2pbutton.popup.no_newnym = i2pbutton cannot safely give you a new identity. It does not have access to the I2P Control Port.\n\nAre you running I2P Browser Bundle?
|
||||
i2pbutton.security_settings.menu.title = Security Settings
|
||||
i2pbutton.title.prompt_i2pbrowser = Important i2pbutton Information
|
||||
i2pbutton.popup.prompt_i2pbrowser = i2pbutton works differently now: you can't turn it off any more.\n\nWe made this change because it isn't safe to use i2pbutton in a browser that's also used for non-Tor browsing. There were too many bugs there that we couldn't fix any other way.\n\nIf you want to keep using Firefox normally, you should uninstall i2pbutton and download Tor Browser Bundle. The privacy properties of Tor Browser are also superior to those of normal Firefox, even when Firefox is used with i2pbutton.\n\nTo remove i2pbutton, go to Tools->Addons->Extensions and then click the Remove button next to i2pbutton.
|
||||
i2pbutton.popup.short_i2pbrowser = Important i2pbutton Information!\n\ni2pbutton is now always enabled.\n\nClick on the i2pbutton for more information.
|
||||
|
||||
i2pbutton.popup.confirm_plugins = Plugins such as Flash can harm your privacy and anonymity.\n\nThey can also bypass I2P to reveal your current location and IP address.\n\nAre you sure you want to enable plugins?\n\n
|
||||
i2pbutton.popup.never_ask_again = Never ask me again
|
||||
i2pbutton.popup.confirm_newnym = Tor Browser will close all windows and tabs. All website sessions will be lost.\n\nRestart I2P Browser now to reset your identity?\n\n
|
||||
|
||||
i2pbutton.maximize_warning = Maximizing I2P Browser can allow websites to determine your monitor size, which can be used to track you. We recommend that you leave I2P Browser windows in their original default size.
|
||||
|
||||
# Canvas permission prompt. Strings are kept here for ease of translation.
|
||||
canvas.siteprompt=This website (%S) attempted to extract HTML5 canvas image data, which may be used to uniquely identify your computer.\n\nShould I2P Browser allow this website to extract HTML5 canvas image data?
|
||||
canvas.notNow=Not Now
|
||||
canvas.notNowAccessKey=N
|
||||
canvas.allow=Allow in the future
|
||||
canvas.allowAccessKey=A
|
||||
canvas.never=Never for this site (recommended)
|
||||
canvas.neverAccessKey=e
|
||||
|
||||
# Profile/startup error messages. Strings are kept here for ease of translation.
|
||||
# LOCALIZATION NOTE: %S is the application name.
|
||||
profileProblemTitle=%S Profile Problem
|
||||
profileReadOnly=You cannot run %S from a read-only file system. Please copy %S to another location before trying to use it.
|
||||
profileReadOnlyMac=You cannot run %S from a read-only file system. Please copy %S to your Desktop or Applications folder before trying to use it.
|
||||
profileAccessDenied=%S does not have permission to access the profile. Please adjust your file system permissions and try again.
|
||||
profileMigrationFailed=Migration of your existing %S profile failed.\nNew settings will be used.
|
||||
|
||||
# "Downloading update" string for the hamburger menu (see #28885).
|
||||
# This string is kept here for ease of translation.
|
||||
# LOCALIZATION NOTE: %S is the application name.
|
||||
updateDownloadingPanelUILabel=Downloading %S update
|
||||
|
||||
# .Onion Page Info prompt. Strings are kept here for ease of translation.
|
||||
pageInfo_OnionEncryptionWithBitsAndProtocol=Connection Encrypted (Onion Service, %1$S, %2$S bit keys, %3$S)
|
||||
pageInfo_OnionEncryption=Connection Encrypted (Onion Service)
|
@ -3,7 +3,7 @@ const kMODULE_NAME = "about:i2p";
|
||||
const kMODULE_CONTRACTID = "@mozilla.org/network/protocol/about;1?what=i2p";
|
||||
const kMODULE_CID = Components.ID("84d47da6-79c3-4661-aa9f-8049476f7bf5");
|
||||
|
||||
const kAboutTorURL = "chrome://i2pbutton/content/aboutI2p/aboutI2p.xhtml";
|
||||
const kAboutI2pURL = "chrome://i2pbutton/content/aboutI2p/aboutI2p.xhtml";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -16,7 +16,7 @@ function AboutI2p()
|
||||
}
|
||||
|
||||
|
||||
AboutTor.prototype =
|
||||
AboutI2p.prototype =
|
||||
{
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||
|
||||
|
@ -62,7 +62,7 @@ function padInt(i)
|
||||
return (i < 10) ? '0' + i : i;
|
||||
}
|
||||
|
||||
TorbuttonLogger.prototype =
|
||||
I2pbuttonLogger.prototype =
|
||||
{
|
||||
QueryInterface: function(iid)
|
||||
{
|
||||
@ -158,7 +158,7 @@ TorbuttonLogger.prototype =
|
||||
Services.prefs.setBoolPref("browser.dom.window.dump.enabled",
|
||||
true);
|
||||
} else if (Services.prefs.
|
||||
getIntPref("extensions.torlauncher.logmethod", 3) !== 0) {
|
||||
getIntPref("extensions.i2plauncher.logmethod", 3) !== 0) {
|
||||
// If Tor Launcher is not available or its log method is not 0
|
||||
// then let's reset the dump pref.
|
||||
Services.prefs.setBoolPref("browser.dom.window.dump.enabled",
|
||||
|
194
src/components/startup-observer.js
Normal file
194
src/components/startup-observer.js
Normal file
@ -0,0 +1,194 @@
|
||||
/*************************************************************************
|
||||
* Startup observer (JavaScript XPCOM component)
|
||||
*
|
||||
* Cases tested (each during Tor and Non-Tor, FF4 and FF3.6)
|
||||
* 1. Crash
|
||||
* 2. Upgrade
|
||||
* 3. Fresh install
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
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");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
Cu.import("resource://i2pbutton/modules/default-prefs.js", {}).ensureDefaultPrefs();
|
||||
//let NoScriptControl = Cu.import("resource://torbutton/modules/noscript-control.js", {});
|
||||
|
||||
// Module specific constants
|
||||
const kMODULE_NAME = "Startup";
|
||||
const kMODULE_CONTRACTID = "@geti2p.net/startup-observer;1";
|
||||
const kMODULE_CID = Components.ID("06322def-6fde-4c06-aef6-47ae8e799629");
|
||||
|
||||
function StartupObserver() {
|
||||
this.logger = Cc["@geti2p.net/i2pbutton-logger;1"]
|
||||
.getService(Ci.nsISupports).wrappedJSObject;
|
||||
this._prefs = Services.prefs;
|
||||
this.logger.log(3, "Startup Observer created");
|
||||
|
||||
var env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
var prefName = "browser.startup.homepage";
|
||||
if (env.exists("TOR_DEFAULT_HOMEPAGE")) {
|
||||
// if the user has set this value in a previous installation, don't override it
|
||||
if (!this._prefs.prefHasUserValue(prefName)) {
|
||||
this._prefs.setCharPref(prefName, env.get("TOR_DEFAULT_HOMEPAGE"));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var test = this._prefs.getCharPref("i2pbrowser.version");
|
||||
this.is_tbb = true;
|
||||
this.logger.log(3, "This is a I2P Browser's XPCOM");
|
||||
} catch(e) {
|
||||
this.logger.log(3, "This is not a I2P Browser's XPCOM");
|
||||
}
|
||||
|
||||
try {
|
||||
// XXX: We're in a race with HTTPS-Everywhere to update our proxy settings
|
||||
// before the initial SSL-Observatory test... If we lose the race, Firefox
|
||||
// caches the old proxy settings for check.tp.o somehwere, and it never loads :(
|
||||
this.setProxySettings();
|
||||
} catch(e) {
|
||||
this.logger.log(4, "Early proxy change failed. Will try again at profile load. Error: "+e);
|
||||
}
|
||||
|
||||
// Arrange for our about:tor handler to be loaded in the default (chrome)
|
||||
// process as well as in each content process.
|
||||
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIProcessScriptLoader);
|
||||
ppmm.loadProcessScript("resource://i2pbutton/components/aboutI2p.js",
|
||||
true);
|
||||
}
|
||||
|
||||
StartupObserver.prototype = {
|
||||
// Bug 6803: We need to get the env vars early due to
|
||||
// some weird proxy caching code that showed up in FF15.
|
||||
// Otherwise, homepage domain loads fail forever.
|
||||
setProxySettings: function() {
|
||||
if (!this.is_tbb)
|
||||
return;
|
||||
|
||||
// Bug 1506: Still want to get these env vars
|
||||
let environ = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
if (environ.exists("TOR_TRANSPROXY")) {
|
||||
/*
|
||||
this.logger.log(3, "Resetting Tor settings to transproxy");
|
||||
this._prefs.setBoolPref("network.proxy.socks_remote_dns", false);
|
||||
this._prefs.setIntPref("network.proxy.type", 0);
|
||||
this._prefs.setIntPref("network.proxy.socks_port", 0);
|
||||
this._prefs.setCharPref("network.proxy.socks", "");
|
||||
*/
|
||||
} else {
|
||||
|
||||
// Try to retrieve SOCKS proxy settings from Tor Launcher.
|
||||
let socksPortInfo;
|
||||
try {
|
||||
//let tlps = Cc["@torproject.org/torlauncher-protocol-service;1"]
|
||||
// .getService(Ci.nsISupports).wrappedJSObject;
|
||||
//socksPortInfo = tlps.TorGetSOCKSPortInfo();
|
||||
} catch(e) {
|
||||
this.logger.log(3, "i2p launcher failed " + e);
|
||||
}
|
||||
|
||||
// If Tor Launcher is not available, check environment variables.
|
||||
if (!socksPortInfo) {
|
||||
socksPortInfo = { ipcFile: undefined, host: undefined, port: 0 };
|
||||
|
||||
let isWindows = Services.appinfo.OS === "WINNT";
|
||||
if (!isWindows && environ.exists("TOR_SOCKS_IPC_PATH")) {
|
||||
socksPortInfo.ipcFile = new FileUtils.File(
|
||||
environ.get("TOR_SOCKS_IPC_PATH"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (environ.exists("TOR_SOCKS_HOST"))
|
||||
socksPortInfo.host = environ.get("TOR_SOCKS_HOST");
|
||||
if (environ.exists("TOR_SOCKS_PORT"))
|
||||
socksPortInfo.port = parseInt(environ.get("TOR_SOCKS_PORT"));
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust network.proxy prefs.
|
||||
if (socksPortInfo.ipcFile) {
|
||||
let fph = Services.io.getProtocolHandler("file")
|
||||
.QueryInterface(Ci.nsIFileProtocolHandler);
|
||||
let fileURI = fph.newFileURI(socksPortInfo.ipcFile);
|
||||
this.logger.log(3, "Reset socks to "+fileURI.spec);
|
||||
//this._prefs.setCharPref("network.proxy.socks", fileURI.spec);
|
||||
//this._prefs.setIntPref("network.proxy.socks_port", 0);
|
||||
} else {
|
||||
if (socksPortInfo.host) {
|
||||
//this._prefs.setCharPref("network.proxy.socks", socksPortInfo.host);
|
||||
this.logger.log(3, "Reset socks host to "+socksPortInfo.host);
|
||||
}
|
||||
if (socksPortInfo.port) {
|
||||
//this._prefs.setIntPref("network.proxy.socks_port",
|
||||
// socksPortInfo.port);
|
||||
this.logger.log(3, "Reset socks port to "+socksPortInfo.port);
|
||||
}
|
||||
}
|
||||
|
||||
if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) {
|
||||
//this._prefs.setBoolPref("network.proxy.socks_remote_dns", true);
|
||||
//this._prefs.setIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Force prefs to be synced to disk
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
this.logger.log(3, "Synced network settings to environment.");
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
if(topic == "profile-after-change") {
|
||||
// Bug 1506 P1: We listen to these prefs as signals for startup,
|
||||
// but only for hackish reasons.
|
||||
this._prefs.setBoolPref("extensions.i2pbutton.startup", true);
|
||||
|
||||
// We need to listen for NoScript before it starts.
|
||||
//NoScriptControl.initialize();
|
||||
|
||||
this.setProxySettings();
|
||||
}
|
||||
|
||||
// In all cases, force prefs to be synced to disk
|
||||
Services.prefs.savePrefFile(null);
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
if(iid.equals(Ci.nsIClassInfo)) {
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// method of nsIClassInfo
|
||||
classDescription: "I2pbutton Startup Observer",
|
||||
classID: kMODULE_CID,
|
||||
contractID: kMODULE_CONTRACTID,
|
||||
|
||||
// Hack to get us registered early to observe recovery
|
||||
_xpcom_categories: [{category:"profile-after-change"}],
|
||||
|
||||
getInterfaces: function(count) {
|
||||
var interfaceList = [nsIClassInfo];
|
||||
count.value = interfaceList.length;
|
||||
return interfaceList;
|
||||
},
|
||||
getHelperForLanguage: function(count) { return null; }
|
||||
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([StartupObserver]);
|
@ -6,7 +6,7 @@
|
||||
<em:name>I2pbutton</em:name>
|
||||
<em:creator>Meeh, Mikal Villa</em:creator>
|
||||
<em:id>i2pbutton@geti2p.net</em:id>
|
||||
<em:version>2.2</em:version>
|
||||
<em:version>0.1</em:version>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
<em:homepageURL>https://geti2p.net/en/download/lab</em:homepageURL>
|
||||
<em:iconURL>chrome://i2pbutton/skin/i2p.png</em:iconURL>
|
||||
|
13
src/jar.mn
13
src/jar.mn
@ -11,6 +11,10 @@ i2pbutton.jar:
|
||||
skin/ (chrome/skin/*)
|
||||
|
||||
% overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/i2pbutton.xul
|
||||
% overlay chrome://messenger/content/messenger.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
% overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://i2pbutton/content/i2pbutton_tb.xul
|
||||
% overlay about:addons chrome://i2pbutton/content/i2pbutton-extensions.xul
|
||||
% overlay chrome://mozapps/content/extensions/extensions.xul chrome://i2pbutton/content/i2pbutton-extensions.xul
|
||||
|
||||
% resource i2pbutton %
|
||||
% resource i2pbutton-assets resource://i2pbutton/skin/ contentaccessible=yes
|
||||
@ -20,11 +24,18 @@ i2pbutton.jar:
|
||||
% override chrome://branding/locale/brand.properties chrome://i2pbutton/locale/brand.properties
|
||||
% overlay chrome://browser/content/aboutDialog.xul chrome://i2pbutton/content/aboutDialog.xul
|
||||
|
||||
# UI customization
|
||||
% overlay chrome://browser/content/browser.xul chrome://i2pbutton/content/menu-items-overlay.xul
|
||||
|
||||
|
||||
# Strings for the about:ibupdate page
|
||||
% override chrome://browser/locale/aboutIBUpdate.dtd chrome://i2pbutton/locale/aboutIBUpdate.dtd
|
||||
|
||||
% locale i2pbutton en-US %locale/en-US/
|
||||
locale/en-US/ (chrome/locale/en-US/*)
|
||||
|
||||
|
||||
% skin torbutton classic/1.0 %skin/
|
||||
% skin i2pbutton classic/1.0 %skin/
|
||||
% style chrome://global/content/customizeToolbar.xul chrome://i2pbutton/skin/i2pbutton.css
|
||||
|
||||
# Firefox 4-style component registration
|
||||
|
36
src/modules/default-prefs.js
Normal file
36
src/modules/default-prefs.js
Normal file
@ -0,0 +1,36 @@
|
||||
let loaded = false;
|
||||
|
||||
function ensureDefaultPrefs () {
|
||||
if (loaded) {
|
||||
return;
|
||||
}
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
const kDefaultPreferences = "resource://i2pbutton/defaults/preferences/preferences.js";
|
||||
const defaultPrefBranch = Services.prefs.getDefaultBranch(null);
|
||||
|
||||
const context = {
|
||||
pref: function (aPrefName, aValue) {
|
||||
const aValueType = typeof aValue;
|
||||
if (aValueType === "boolean") {
|
||||
defaultPrefBranch.setBoolPref(aPrefName, aValue);
|
||||
} else if (aValueType === "number") {
|
||||
defaultPrefBranch.setIntPref(aPrefName, aValue);
|
||||
} else if (aValueType === "string") {
|
||||
defaultPrefBranch.setCharPref(aPrefName, aValue);
|
||||
} else {
|
||||
Services.console.logStringMessage(
|
||||
`Preference ${aPrefName} with value ${aValue} has an invalid value type`);
|
||||
}
|
||||
|
||||
// Disable the External App Blocker on Android
|
||||
if ((aPrefName === "extensions.i2pbutton.launch_warning") &&
|
||||
(Services.appinfo.OS === "Android")) {
|
||||
defaultPrefBranch.setBoolPref(aPrefName, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
Services.scriptloader.loadSubScript(kDefaultPreferences, context);
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
let EXPORTED_SYMBOLS = ["ensureDefaultPrefs"];
|
120
src/modules/utils.js
Normal file
120
src/modules/utils.js
Normal file
@ -0,0 +1,120 @@
|
||||
// ### Shortcut
|
||||
const { Cu: utils, Cr: results } = Components
|
||||
|
||||
// ### Import Mozilla Services
|
||||
Cu.import("resource://gre/modules/Services.jsm")
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm")
|
||||
|
||||
// ### Import global URL
|
||||
Cu.importGlobalProperties(["URL"])
|
||||
|
||||
const ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService)
|
||||
|
||||
const getProfileDir = function() {
|
||||
let directoryService =
|
||||
Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties)
|
||||
// this is a reference to the profile dir (ProfD) now.
|
||||
let localDir = directoryService.get("ProfD", Ci.nsIFile)
|
||||
return localDir.path
|
||||
}
|
||||
|
||||
//window.open("chrome://browser/content/browser.xul", "bmarks", "chrome,width=600,height=300")
|
||||
|
||||
// __prefs__. A shortcut to Mozilla Services.prefs.
|
||||
let prefs = Services.prefs;
|
||||
|
||||
// __getPrefValue(prefName)__
|
||||
// Returns the current value of a preference, regardless of its type.
|
||||
var getPrefValue = function (prefName) {
|
||||
switch(prefs.getPrefType(prefName)) {
|
||||
case prefs.PREF_BOOL: return prefs.getBoolPref(prefName);
|
||||
case prefs.PREF_INT: return prefs.getIntPref(prefName);
|
||||
case prefs.PREF_STRING: return prefs.getCharPref(prefName);
|
||||
default: return null;
|
||||
}
|
||||
};
|
||||
|
||||
// __bindPref(prefName, prefHandler, init)__
|
||||
// Applies prefHandler whenever the value of the pref changes.
|
||||
// If init is true, applies prefHandler to the current value.
|
||||
// Returns a zero-arg function that unbinds the pref.
|
||||
var bindPref = function (prefName, prefHandler, init = false) {
|
||||
let update = () => { prefHandler(getPrefValue(prefName)); },
|
||||
observer = { observe : function (subject, topic, data) {
|
||||
if (data === prefName) {
|
||||
update();
|
||||
}
|
||||
} };
|
||||
prefs.addObserver(prefName, observer, false);
|
||||
if (init) {
|
||||
update();
|
||||
}
|
||||
return () => { prefs.removeObserver(prefName, observer); };
|
||||
};
|
||||
|
||||
// __bindPrefAndInit(prefName, prefHandler)__
|
||||
// Applies prefHandler to the current value of pref specified by prefName.
|
||||
// Re-applies prefHandler whenever the value of the pref changes.
|
||||
// Returns a zero-arg function that unbinds the pref.
|
||||
var bindPrefAndInit = (prefName, prefHandler) =>
|
||||
bindPref(prefName, prefHandler, true);
|
||||
|
||||
// ## Observers
|
||||
|
||||
// __observe(topic, callback)__.
|
||||
// Observe the given topic. When notification of that topic
|
||||
// occurs, calls callback(subject, data). Returns a zero-arg
|
||||
// function that stops observing.
|
||||
var observe = function (topic, callback) {
|
||||
let observer = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
if (topic === aTopic) {
|
||||
callback(aSubject, aData);
|
||||
}
|
||||
},
|
||||
};
|
||||
Services.obs.addObserver(observer, topic, false);
|
||||
return () => Services.obs.removeObserver(observer, topic);
|
||||
};
|
||||
|
||||
// ## Environment variables
|
||||
|
||||
// __env__.
|
||||
// Provides access to process environment variables.
|
||||
let env = Components.classes["@mozilla.org/process/environment;1"]
|
||||
.getService(Components.interfaces.nsIEnvironment);
|
||||
|
||||
// __getEnv(name)__.
|
||||
// Reads the environment variable of the given name.
|
||||
var getEnv = function (name) {
|
||||
return env.exists(name) ? env.get(name) : undefined;
|
||||
};
|
||||
|
||||
// __getLocale
|
||||
// Reads the browser locale, the default locale is en-US.
|
||||
var getLocale = function() {
|
||||
return Services.locale.getRequestedLocale() || "en-US";
|
||||
}
|
||||
|
||||
// ## Windows
|
||||
|
||||
// __dialogsByName__.
|
||||
// Map of window names to dialogs.
|
||||
let dialogsByName = {};
|
||||
|
||||
// __showDialog(parent, url, name, features, arg1, arg2, ...)__.
|
||||
// Like window.openDialog, but if the window is already
|
||||
// open, just focuses it instead of opening a new one.
|
||||
var showDialog = function (parent, url, name, features) {
|
||||
let existingDialog = dialogsByName[name];
|
||||
if (existingDialog && !existingDialog.closed) {
|
||||
existingDialog.focus();
|
||||
return existingDialog;
|
||||
} else {
|
||||
let newDialog = parent.openDialog.apply(parent,
|
||||
Array.slice(arguments, 1));
|
||||
dialogsByName[name] = newDialog;
|
||||
return newDialog;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user